agentleFS
PrairieAster-AiPrairieAster-Ai/quality-butler/skills/code-health/SKILL.md

code-health

Skill0 starsChanged 4 months agoApache-2.0View on GitHub

Structural code-health metrics, the rolled-up CodeHealth score, and the Code Health Dashboard pipeline (Maintainability Index, cyclomatic/cognitive complexity, churn×complexity hotspots, coupling/instability, change-coupling, duplication, circular imports). Measures + trends + renders; the quality-butler composes it. Use to instrument a repo, take a reading, or refresh the dashboard.

10 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use dependency-watch, perform-task and 3 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • telegramdesktopSkill

    dependency-watch

    Audit Telegram Desktop dependencies on freshly fetched origin/dev for releases and security fixes, including upstream lag and backport candidates in patched forks. Use for the scheduled dependency monitor or an explicitly requested dependency report.

    Also in 3 projects that use this

  • telegramdesktopSkill

    perform-task

    Resolve, start or resume, implement, review, test, and publish exactly one existing ai-tdesktop task by short slug or full dated id, including rare blocked retries and split-required results. Use when the user invokes $perform-task or /perform-task with a known task name, or when the continue scheduler delegates one selected task. Runs standard review lenses with fast applicability bailouts and selects task-specific domain and evidence instruments without selecting additional work.

    Also in 3 projects that use this

  • JerovinoSkill

    process-inbox

    Processes tasks.md inbox items by triaging each one to its proper location in the vault

    Also in 3 projects that use this

  • Trejon-888Skill

    continue

    Load project context, alignment audit, status check, suggest next action. Auto-invoke at session start, after context switches, or when user says 'continue', 'pick up where we left off', 'resume', 'what's next', 'status check', 'what now'.

    Also in 3 projects that use this

  • raineSkill

    rebase

    Rebase the current branch with smart conflict resolution.

    Also in 3 projects that use this

The file

We split this skill into the rules it gives an agent

6 rules. 0 are common, 2 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 10 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add code-health.config.json at the repo root (defaults assume a single src/):

    line 36
  2. Very specific:

    Every dimension reports whether it observed anything.

    line 109
  3. Very specific:

    Run by run-all.mjs last, because it costs roughly one API call per CI run examined.

    line 200
  4. Distinctive:

    Don't annotate docs or write tests here — that's code-readability / code-quality.

    line 275
  5. Distinctive:

    Don't hardcode repo paths in the scripts — everything comes from config.

    line 276
  6. Very specific:

    Don't stamp a dashboard without running the roll-up first (stale codehealth-stamp.json).

    line 277

“Common” is measured: kept by at least 6 in 10 of the 10 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Code Health Skill

Owns the structural-health concern: how maintainable, well-structured, and low-risk the code is — measured, trended, and rolled up into one CodeHealth grade and a published dashboard. Bundles repo-agnostic scripts that run against whatever repo invokes them (config from the repo root).

Separation of concerns (where this sits)

One dashboard, several producers — each skill owns its dimension:

ConcernOwnerFeeds the roll-up
Structural metrics (MI, complexity, hotspots, coupling, change-coupling, duplication, cycles) + CodeHealth roll-up + dashboard render/stamp/trendcode-health (this)Maintainability, Structure, Resilience, Type & size
Docs / TSDoc / wiki publishcode-readabilityDocumentation
Coverage / lint / sprint planningcode-quality(Test trend, informational)
SAST · secrets · SCA (per-PR + dep advisories)security-auditSecurity

This skill measures and aggregates; it does not annotate docs, write tests, or run the full security toolchain — it reads those signals (doc%, npm-audit counts, coverage) where they live and rolls them into the score. The quality-butler agent is the orchestrator that runs all four and publishes the dashboard.

Configure for your project

Add code-health.config.json at the repo root (defaults assume a single src/):

{
  "dirs": ["apps/web/src"],
  "docDirs": ["apps/web/src/components", "apps/web/src/hooks", "apps/web/src/services",
              "apps/web/src/utils", "apps/web/src/types", "apps/web/src/config"],
  "coverageWorkspaces": ["apps/web"],
  "tsconfig": "apps/web/tsconfig.json",
  "historyDir": "code-health",
  "window": "365 days ago"
}

blobBase (GitHub file links) is auto-derived from origin; override if needed. changeCoupling thresholds and thresholds.{miGreen,miYellow,dupMinLines} are tunable. All output goes to <historyDir>/*-history.tsv (the trend) + codehealth-stamp.json (the dashboard facts).

Install (repo devDeps): typescript, dependency-cruiser, madge. eslint (complexity), jscpd, and vitest --coverage are invoked via the repo's existing toolchain / npx.

Modes

  • instrument — first-time setup in a repo: write code-health.config.json, add devDeps + npm run aliases (see below), run run-all.mjs once to seed the history TSVs, and create/stamp the Code-Health-Dashboard wiki page.
  • read — take a fresh reading: node <skill>/scripts/run-all.mjs (all producers then the roll-up). Add --no-write to print without appending history.
  • refresh — regenerate the dashboard: run-all.mjs --stamp <wiki>/Code-Health-Dashboard.md <wiki>/Home.md fills the <!--ch:*--> markers.

If the repo vendors this skill into .claude/skills/code-health, run that copy. A vendored copy is pinned to the commit the repo's CI uses, and the recorded history was produced by it. A global ~/.claude/skills install can be an older build, and an older build writes fewer columns than the history names — the reader keys on header position, finds nothing, and falls back to a default, so you get a plausible grade with a wrong number in it and a narrative explaining the change. run-all.mjs now refuses this: it exits 1 when a pinned copy exists and you are running another one.

Suggested package.json aliases — always the vendored path when there is one:

"mi:report":             "node .claude/skills/code-health/scripts/maintainability-report.mjs",
"complexity:report":     "node .claude/skills/code-health/scripts/complexity-report.mjs",
"hotspot:report":        "node .claude/skills/code-health/scripts/hotspot-report.mjs",
"coupling:report":       "node .claude/skills/code-health/scripts/coupling-report.mjs",
"change-coupling:report":"node .claude/skills/code-health/scripts/change-coupling-report.mjs",
"duplication:report":    "node .claude/skills/code-health/scripts/duplication-report.mjs",
"codehealth:report":     "node .claude/skills/code-health/scripts/run-all.mjs"

The CodeHealth roll-up

A 0–100 score (letter grade A–F) over six dimensions, each normalized against documented anchors then weighted. Run the producers first — the roll-up reads their latest TSV rows; run-all.mjs sequences this for you.

DimensionWeightSource
Documentation20%doc coverage %
Maintainability25%MI health proportion (green + ½·yellow) / files
Structure20%circular imports + cross-layer change-coupling
Resilience (worst file)10%lowest single-file MI
Type & size safety15%any count + files > 500 LOC
Security (deps)10%npm-audit advisory counts

Full formulas, bands, and the "why health-proportion not the MI mean" rationale live in references/methodology.md. Grade bands: A ≥ 90 · B 80–89 · C 70–79 · D 60–69 · F < 60.

No silent defaults

Every dimension reports whether it observed anything. This used to be implicit and generous: a missing security history meant 0 critical / 0 high, a missing coupling history meant zero coupled pairs, a doc probe that failed to match meant 100% documented. A repo with no source files and no measurement history scored Maintainability 100 and Security 100 — positive claims about work nobody had done.

  • A dimension with no input reads NOT MEASURED and is excluded from the score.
  • A reading missing any dimension is a partial reading: it gets no grade, and the executive summary says the reading is incomplete instead of describing a codebase it did not measure. Renormalizing over the measured weight is the same mistake wearing a different hat — scoring one dimension out of six produced "100/100, grade A" for an empty repo.
  • A partial reading is refused entry to the trend, because the chart draws a line between it and a complete one as though they were comparable. --allow-partial records it anyway, for a repo not yet instrumented.

Duplicate declarations

node <skill>/scripts/duplicate-declarations.mjs finds the same exported name declared in two places — and reports whether the two shapes still agree.

This is not what a copy-paste detector finds. jscpd finds duplicated blocks; this finds duplicated contracts: one PlannedRow in the API and another in the web app, identical the day they were written and drifting apart afterwards.

It is the characteristic failure of AI-assisted work, because an assistant works in the context it was given. Asked to add a field to a screen, it declares the type where it is looking, since the other declaration is in a file it never opened. The result compiles, passes review, and is wrong later rather than now.

  • same name, same shape — a warning: it will drift.
  • same name, different shape — a bug that has already happened. One side is missing something the other sends.

Validated against a repo where six such drifts had been found by hand: run at the commit before they were fixed, it independently flagged all six.

Metrics for assisted development

Three measures aimed at how the work actually fails when a model writes most of it.

mutation-score.mjs — do the tests test anything? Coverage says a line ran; it does not say anyone checked the result. Under assistance that is the default failure rather than a rare one, because test volume is nearly free and a test that asserts "it did not throw" looks like a test that verifies the answer. This changes the source under the tests and asks whether they notice. Only files with a colocated test are mutated: a file with no test is a coverage question, and mixing the two drowns the signal that matters — you have a test for this and it does not catch a changed comparison.

Deliberately not in run-all: it runs the whole suite once per mutant. Give it a nightly. On the repo this was built for, a sample of 8 found that every test on the invite sender asserted a failure path and none asserted success, so return true could have become return false untouched.

delivery-metrics.mjs — DORA, re-pointed. Deploy frequency and lead time measure how fast work leaves the keyboard, which is exactly the part that got cheap; they inflate under assistance and stop discriminating. What still means something:

  • verification ratio — non-test lines changed per test line. A large diff that moved no test is either safe by construction or unverified, and the number makes you say which.
  • change-failure rate — share of commits that fix or revert. A proxy for the DORA definition, which needs incident data this cannot see.
  • time to detect — how old the lines a fix rewrote actually were. Blame the lines, not the files: blaming files reported 0.2 days on a repo whose real median was 6.1, because it was measuring how recently anyone had touched them.

Gate liveness

node <skill>/scripts/gate-liveness.mjs [--limit 100] asks the question the other metrics cannot: which of your checks has ever been observed to fail?

Noise gets noticed; silence does not. A gate that cries wolf gets fixed the same week. A gate that quietly stopped discriminating stays green forever, and looks exactly like a healthy repo. This looks for the silence, in the two places it hides:

  • Declared but never run — a gate-shaped npm script no workflow invokes. It exists, it is documented, and it is dead.
  • Run but never failed — a step that has executed many times and never once gone red.

The second is deliberately not a pass/fail signal, and the report says so. Plenty of gates never fail because the code is good; a green lint over a clean repo is the point. The output is a question: here are the checks you have no evidence about. Answer it by writing each one a negative control — plant the failure it claims to catch and watch it go red, the way selftest.mjs does.

Run by run-all.mjs last, because it costs roughly one API call per CI run examined. Without gh authenticated it prints a notice and scores nothing.

Negative controls

node <skill>/scripts/selftest.mjs plants known-bad input and asserts each gate fires: an unmeasured dimension, a partial reading, a history row narrower than its header, a copy of the skill the repo did not pin. Each negative is paired with a positive so the suite cannot pass by having everything break.

A gate that has never been shown to fail has not been shown to work. Several of these were inert at some point and passed while inert — a mermaid check that passed on an empty diagram list, a doc generator that exited 0 with none of its tooling installed, a trend chart drawn from a history nobody wrote. Run it in CI; the plugin repo runs it on every push.

The dashboard

Code-Health-Dashboard.md (wiki) is the single rendering. Hand-authored prose + <!--ch:NAME-->…<!--/ch:NAME--> markers that stamp-codehealth.mjs fills from codehealth-stamp.json, so the prose never drifts from the numbers. The marker stamping + wiki clone/commit/push are the shared /wiki-publish substrate (stamp-codehealth.mjs delegates to it, prefix ch, with an inline fallback so code-health stays self-contained). Structure: generated executive summary (ch:exec) → headline grade → generated metrics by business outcome (risk / throughput / key-person, ch:outcomes) → detailed views (MI pie, hotspots, coupling) → generated Improve & ROI (ch:roi) → glossary. Mirror the layout in references/methodology.md.

The interpretation layer (ch:exec / ch:outcomes / ch:roi) is produced by codehealth-report.mjs, not hand-authored — so every install ships plain-language verdicts (✅/⚠️/❌), direction-of-travel (▲/▼ vs last reading), a "so what," and a citable benchmark next to each number, legible to the non-technical leaders these dashboards get presented to. The audience personas and encoding principles behind it live in references/methodology.md and the Audience-Personas wiki page.

Stamp facts include a ch:trend score-over-time chart (a Mermaid xychart-beta line of the last ~12 codehealth-history.tsv readings, with a Unicode-sparkline fallback and an "insufficient history" note when there are <2 readings) plus ch:doc_pct / ch:security for the CodeHealth roll-up's documentation and dependency-security dimensions. The full marker set lives in references/methodology.md.

Quality-coverage checklist (butler feature)

quality-checklist.mjs is a butler-level tracker that ships here (it reuses this skill's config + the /wiki-publish stamper). It probes the repo — CI workflows, ESLint config, package.json, pre-commit, the code-health history, installed skills, and (with --wiki) published pages — for every capability the quality skills offer, and classifies each ✅ enabled / ⚠️ partial / ❌ gap / ➖ n/a. It exists to stop audits from forgetting things: a capability that's available but never turned on is a silent gap (e.g. a metric measured but never made a CI gate).

node <skill>/scripts/quality-checklist.mjs --wiki <wiki> --stamp <wiki>/Quality-Coverage.md

Writes <historyDir>/quality-checklist.json and stamps the <!--ql:*--> markers on the Quality-Coverage dashboard. The butler runs it in its weekly document step.

Trend it (optional)

Schedule the butler (or a maintainability.yml workflow) weekly to accumulate the *-history.tsv rows and re-stamp the dashboard, turning a one-time reading into an early-warning trend.

Where the trend lives: the <historyDir>/*-history.tsv + stamp JSON are generated artifacts — gitignore them on the default branch. The durable trend belongs on the butler's butler-state branch (the quality-butler workflow restores it before a run and persists it after), so it survives ephemeral CI runners without the agent ever pushing to the default branch. Committing the trend to the default branch instead leaves a snapshot that silently goes stale.

Don'ts

  • Don't annotate docs or write tests here — that's code-readability / code-quality.
  • Don't hardcode repo paths in the scripts — everything comes from config.
  • Don't stamp a dashboard without running the roll-up first (stale codehealth-stamp.json).

Files

  • scripts/config.mjs — shared config loader + helpers
  • scripts/{maintainability,complexity,hotspot,coupling,change-coupling,duplication,security,coverage}-report.mjs — producers
  • scripts/{check-circular-deps,check-doc-coverage}.mjs — gate-able checks
  • scripts/codehealth-report.mjs — the roll-up + stamp facts (incl. the trend sparkline)
  • scripts/stamp-codehealth.mjs — fill dashboard markers
  • scripts/run-all.mjs — produce everything in order (+ optional --stamp)
  • scripts/agnostic-report.mjs — language-agnostic size/complexity backend (via scc) for non-TS repos
  • scripts/portfolio-report.mjs — multi-repo CodeHealth rollup → portfolio dashboard
  • scripts/quality-checklist.mjs — capability-coverage checklist → Quality-Coverage dashboard
  • references/methodology.md — formulas, anchors, glossary, dashboard template

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.