From 3108d291f6bb3667e4013da23195f5ebe2819457 Mon Sep 17 00:00:00 2001 From: "melodic-automation-lanes[bot]" <337595936+melodic-automation-lanes[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2026 03:32:14 +0000 Subject: [PATCH] Resolve issue #12619 Lane-Activity: work-resolve-issue/resolve-issue --- ...ssue-issue-12619-41570586663-1-3b93eb62.md | 17 +++ ...ssue-issue-12619-41570586663-1-ebd4a40c.md | 7 + ...ssue-issue-12619-41570586663-1-d276eaa6.md | 6 + ...ssue-issue-12619-41570586663-1-83b4eac3.md | 9 ++ ...ssue-issue-12619-41570586663-1-8a92d296.md | 6 + ...ssue-issue-12619-41570586663-1-621885c4.md | 9 ++ docs/catalog.md | 2 +- docs/skill-cheat-sheet.md | 4 +- docs/test-wall-clock-baseline.md | 6 +- docs/upstream/cursor-pstack.md | 2 +- .../code-metrics/.claude-plugin/plugin.json | 2 +- plugins/code-metrics/README.md | 8 +- plugins/code-metrics/prerequisites.json | 8 +- plugins/code-metrics/scripts/dispatch.sh | 4 +- .../skills/audit-complexity/evals/evals.json | 44 ------- .../skills/audit-coverage/SKILL.md | 4 +- .../audit-coverage/scripts/audit-coverage.sh | 6 +- .../scripts/audit-coverage.test.sh | 2 +- .../skills/audit-coverage/scripts/join.py | 4 +- .../skills/audit-duplication/SKILL.md | 2 +- .../skills/audit-size/evals/evals.json | 42 ------ .../skills/audit-suppressions/SKILL.md | 2 +- .../skills/audit-type-debt/evals/evals.json | 45 ------- plugins/code-metrics/skills/audit/SKILL.md | 83 ++++++++++++ .../SKILL.md => audit/actions/complexity.md} | 51 ++------ .../SKILL.md => audit/actions/size.md} | 47 ++----- .../SKILL.md => audit/actions/type-debt.md} | 42 ++---- .../skills/audit/evals/evals.json | 121 ++++++++++++++++++ .../scripts/audit-complexity.sh | 2 +- .../scripts/audit-complexity.test.sh | 0 .../scripts/audit-size.sh | 2 +- .../scripts/audit-size.test.sh | 12 +- .../scripts/audit-type-debt.sh | 2 +- .../scripts/audit-type-debt.test.sh | 0 .../code-metrics/skills/principles/SKILL.md | 4 +- plugins/code-metrics/skills/setup/SKILL.md | 2 +- .../probes/script-the-deterministic-work.json | 2 +- plugins/performance/probes/target.json | 2 +- plugins/review/agents/code-reviewer.md | 2 +- .../skills/fanout/context/default-mode.md | 4 +- .../skills/quality-gate/context/code.md | 4 +- .../skills/quality-gate/evals/evals.json | 6 +- .../skill-quality/scripts/check-skill.test.sh | 6 +- .../skills/measure/context/metrics.md | 4 +- scripts/affected-tests-live.sh | 2 +- scripts/check-code-metrics-skill-prose.py | 2 +- scripts/skill-leaf-name-registry.txt | 9 +- scripts/suite-seconds.txt | 6 +- 48 files changed, 363 insertions(+), 295 deletions(-) create mode 100644 .changes/code-metrics/work-resolve-issue-issue-12619-41570586663-1-3b93eb62.md create mode 100644 .changes/discipline/work-resolve-issue-issue-12619-41570586663-1-ebd4a40c.md create mode 100644 .changes/performance/work-resolve-issue-issue-12619-41570586663-1-d276eaa6.md create mode 100644 .changes/review/work-resolve-issue-issue-12619-41570586663-1-83b4eac3.md create mode 100644 .changes/skill-quality/work-resolve-issue-issue-12619-41570586663-1-8a92d296.md create mode 100644 .changes/verification/work-resolve-issue-issue-12619-41570586663-1-621885c4.md delete mode 100644 plugins/code-metrics/skills/audit-complexity/evals/evals.json delete mode 100644 plugins/code-metrics/skills/audit-size/evals/evals.json delete mode 100644 plugins/code-metrics/skills/audit-type-debt/evals/evals.json create mode 100644 plugins/code-metrics/skills/audit/SKILL.md rename plugins/code-metrics/skills/{audit-complexity/SKILL.md => audit/actions/complexity.md} (78%) rename plugins/code-metrics/skills/{audit-size/SKILL.md => audit/actions/size.md} (66%) rename plugins/code-metrics/skills/{audit-type-debt/SKILL.md => audit/actions/type-debt.md} (81%) create mode 100644 plugins/code-metrics/skills/audit/evals/evals.json rename plugins/code-metrics/skills/{audit-complexity => audit}/scripts/audit-complexity.sh (96%) rename plugins/code-metrics/skills/{audit-complexity => audit}/scripts/audit-complexity.test.sh (100%) rename plugins/code-metrics/skills/{audit-size => audit}/scripts/audit-size.sh (97%) rename plugins/code-metrics/skills/{audit-size => audit}/scripts/audit-size.test.sh (88%) rename plugins/code-metrics/skills/{audit-type-debt => audit}/scripts/audit-type-debt.sh (97%) rename plugins/code-metrics/skills/{audit-type-debt => audit}/scripts/audit-type-debt.test.sh (100%) diff --git a/.changes/code-metrics/work-resolve-issue-issue-12619-41570586663-1-3b93eb62.md b/.changes/code-metrics/work-resolve-issue-issue-12619-41570586663-1-3b93eb62.md new file mode 100644 index 00000000000..407b3964cd9 --- /dev/null +++ b/.changes/code-metrics/work-resolve-issue-issue-12619-41570586663-1-3b93eb62.md @@ -0,0 +1,17 @@ +--- +bump: major +--- + +### Added + +- `/code-metrics:audit` is a router skill with three actions: `size` (lines per file), + `complexity` (per-function cyclomatic, cognitive and Halstead complexity) and `type-debt` + (typed-code percentage). Each action runs the same entry script as before, so the options, + report and exit codes are unchanged. + +### Removed + +- The `audit-size`, `audit-complexity` and `audit-type-debt` skills are gone. Run + `/code-metrics:audit size`, `/code-metrics:audit complexity` or `/code-metrics:audit type-debt` + instead. The report `skill` field and the `dispatch.sh` id keep their old values, so reports + taken before and after still compare. diff --git a/.changes/discipline/work-resolve-issue-issue-12619-41570586663-1-ebd4a40c.md b/.changes/discipline/work-resolve-issue-issue-12619-41570586663-1-ebd4a40c.md new file mode 100644 index 00000000000..b351ed47f4c --- /dev/null +++ b/.changes/discipline/work-resolve-issue-issue-12619-41570586663-1-ebd4a40c.md @@ -0,0 +1,7 @@ +--- +bump: none +--- + +No release: the `script-the-deterministic-work` trigger probe now names `code-metrics:audit` as a +competitor in place of the removed `code-metrics:audit-size`. Probe data only; the skill does not +change. diff --git a/.changes/performance/work-resolve-issue-issue-12619-41570586663-1-d276eaa6.md b/.changes/performance/work-resolve-issue-issue-12619-41570586663-1-d276eaa6.md new file mode 100644 index 00000000000..0f949c8e880 --- /dev/null +++ b/.changes/performance/work-resolve-issue-issue-12619-41570586663-1-d276eaa6.md @@ -0,0 +1,6 @@ +--- +bump: none +--- + +No release: the `target` trigger probe now names `code-metrics:audit` as a competitor in place of +the removed `code-metrics:audit-complexity`. Probe data only; the skill does not change. diff --git a/.changes/review/work-resolve-issue-issue-12619-41570586663-1-83b4eac3.md b/.changes/review/work-resolve-issue-issue-12619-41570586663-1-83b4eac3.md new file mode 100644 index 00000000000..5d990c33dbe --- /dev/null +++ b/.changes/review/work-resolve-issue-issue-12619-41570586663-1-83b4eac3.md @@ -0,0 +1,9 @@ +--- +bump: patch +--- + +### Changed + +- The size-crossing step in `quality-gate` code mode and `fanout` default mode now runs + `/code-metrics:audit size`, since code-metrics replaced `audit-size` with the `audit` router. + It still runs only when the code-metrics audit skill is installed. diff --git a/.changes/skill-quality/work-resolve-issue-issue-12619-41570586663-1-8a92d296.md b/.changes/skill-quality/work-resolve-issue-issue-12619-41570586663-1-8a92d296.md new file mode 100644 index 00000000000..7c60d9555da --- /dev/null +++ b/.changes/skill-quality/work-resolve-issue-issue-12619-41570586663-1-8a92d296.md @@ -0,0 +1,6 @@ +--- +bump: none +--- + +No release: three `check-skill.test.sh` fixtures now cite `/code-metrics:audit complexity` in place +of the removed `/code-metrics:audit-complexity`. Test fixtures only; the checker does not change. diff --git a/.changes/verification/work-resolve-issue-issue-12619-41570586663-1-621885c4.md b/.changes/verification/work-resolve-issue-issue-12619-41570586663-1-621885c4.md new file mode 100644 index 00000000000..12c354e3e39 --- /dev/null +++ b/.changes/verification/work-resolve-issue-issue-12619-41570586663-1-621885c4.md @@ -0,0 +1,9 @@ +--- +bump: patch +--- + +### Changed + +- `measure metrics` names `/code-metrics:audit complexity --json` and `/code-metrics:audit size --json` + for the complexity and size rows, since code-metrics replaced its `audit-complexity` and + `audit-size` skills with the `audit` router. diff --git a/docs/catalog.md b/docs/catalog.md index 97b7cb805e7..62fd1775466 100644 --- a/docs/catalog.md +++ b/docs/catalog.md @@ -63,7 +63,7 @@ plugin manifests and kept in sync by CI. Never hand-edit it; the category vocabu - [`mcp-tools`](../plugins/mcp-tools): Two MCP audits. audit scores the tool definitions of a server you build against MCP-specification, Anthropic tool-design, and Claude-Code client criteria in a per-tool PASS/WARN/FAIL scorecard (Python, TypeScript, .NET). audit-posture inventories the MCP servers your Claude Code configuration runs and flags supply-chain risks such as floating package versions, without running any server. - [`review`](../plugins/review): Code-review toolkit: nine agents, read-only over the reviewed code, plus orchestration skills for the quality gate and fan-out, a pull-request change digest with an interactive view (/review:explain-change), a fan-out sweep workflow (/review:fanout-sweep), and CI lane commands (/review:code-review, /review:security-review) for org reusable workflows. - [`codebase-health`](../plugins/codebase-health): Repo-wide drift audit between docs, config, code, and architecture: verifies every factual claim against reality via parallel subagent fan-out, severity-rates findings, and reports read-only, delegating remediation to the implementation/verification lanes. Audit dimensions are configurable through a tracked .claude/codebase-health.md config file written by the setup skill. -- [`code-metrics`](../plugins/code-metrics): Read-only code measures for a change, with cited references and no verdict: lines per file (audit-size), cyclomatic, cognitive, and Halstead complexity (audit-complexity), duplication (audit-duplication), per-function coverage and CRAP from existing lcov, Cobertura, coverage.py, or Go artifacts (audit-coverage), TypeScript and Python type debt (audit-type-debt), metric literacy (principles), and setup. Uses only collectors already installed; never installs or runs tests. +- [`code-metrics`](../plugins/code-metrics): Read-only code measures for a change, with cited references and no verdict: lines per file (audit size), cyclomatic, cognitive, and Halstead complexity (audit complexity), duplication (audit-duplication), per-function coverage and CRAP from existing lcov, Cobertura, coverage.py, or Go artifacts (audit-coverage), TypeScript and Python type debt (audit type-debt), metric literacy (principles), and setup. Uses only collectors already installed; never installs or runs tests. - [`discipline`](../plugins/discipline): Correctors that re-anchor a rule, audit work in flight, and fix drift: do-your-research, follow-our-standards, point-dont-copy, reason-dont-recite, tighten-your-output, recheck-against-upstream, pick-for-the-problem, mind-your-maxims, script-the-deterministic-work, use-your-skills, reuse-or-replace, scrutinize-dont-coast. sweep-all runs them as one batch. wait-what re-pitches a message that did not land. hold-my-hand shows work one phase at a time. be-ambitious raises one request's ambition. - [`ai-slop`](../plugins/ai-slop): Detects and removes AI-writing tells (slop) in tracked markdown, commit messages, PR bodies and interface copy: em dashes, emoji formatting, AI vocabulary, negative parallelisms, chatbot phrases, filler, hedging, citation artifacts and model-era phrases, from a catalog based on Wikipedia's Signs of AI writing plus a graded model-vocabulary inventory. Read-only audit by default (deterministic detector plus judgment rubric); an explicit fix action rewrites findings behind a semantic-diff guard. - [`overengineering`](../plugins/overengineering): Evidence-earned-keep audit of agent hooks and instructions, git hooks, CI lanes and gate scripts, branch protections, forge apps, and integrations. audit treats each as a retirement candidate until evidence earns its keep, argues in cost of carry, caps security-class retirements at FLAG-FOR-HUMAN, and writes a diffable findings file. realign simplifies behind a per-item human gate. delta reports changes since the last run. justify asks whether one artifact's reason still holds. diff --git a/docs/skill-cheat-sheet.md b/docs/skill-cheat-sheet.md index 7f5be24c954..7e4a892bad2 100644 --- a/docs/skill-cheat-sheet.md +++ b/docs/skill-cheat-sheet.md @@ -240,12 +240,10 @@ owned by [docs/catalog-taxonomy.md](catalog-taxonomy.md). | [`/attribution:audit`](../plugins/attribution/skills/audit/SKILL.md) | `attribution` | Find prose copied from external sources and convert it into pointers | | [`/bash-format:check`](../plugins/bash-format/skills/check/SKILL.md) | `bash-format` | Report whether shfmt, shellcheck and node are installed. Never installs. | | [`/biome-format:check`](../plugins/biome-format/skills/check/SKILL.md) | `biome-format` | Report whether biome and node are installed. Never installs. | -| [`/code-metrics:audit-complexity`](../plugins/code-metrics/skills/audit-complexity/SKILL.md) | `code-metrics` | Per-function complexity beside a cited reference, no verdict | +| [`/code-metrics:audit`](../plugins/code-metrics/skills/audit/SKILL.md) | `code-metrics` | Lines, complexity and typed-code numbers beside cited references, no verdict | | [`/code-metrics:audit-coverage`](../plugins/code-metrics/skills/audit-coverage/SKILL.md) | `code-metrics` | Coverage and CRAP read from build artifacts, no verdict | | [`/code-metrics:audit-duplication`](../plugins/code-metrics/skills/audit-duplication/SKILL.md) | `code-metrics` | Clone groups minus the replication the repo declares, no verdict | -| [`/code-metrics:audit-size`](../plugins/code-metrics/skills/audit-size/SKILL.md) | `code-metrics` | Lines per file beside a cited reference, no verdict | | [`/code-metrics:audit-suppressions`](../plugins/code-metrics/skills/audit-suppressions/SKILL.md) | `code-metrics` | Suppressions with their rule ids and reasons, no verdict | -| [`/code-metrics:audit-type-debt`](../plugins/code-metrics/skills/audit-type-debt/SKILL.md) | `code-metrics` | Typed-code percentage per file and per lane, with no standard behind it | | [`/code-metrics:principles`](../plugins/code-metrics/skills/principles/SKILL.md) | `code-metrics` | What each code measure can and cannot tell you | | [`/code-tidying:audit-dead-code`](../plugins/code-tidying/skills/audit-dead-code/SKILL.md) | `code-tidying` | Whole-repo dead-code hunt across four labeled lanes with adjudicated candidates | | [`/code-tidying:tidy`](../plugins/code-tidying/skills/tidy/SKILL.md) | `code-tidying` | Proactively hunt one lane for safe structural tidyings and ship a structure-only PR | diff --git a/docs/test-wall-clock-baseline.md b/docs/test-wall-clock-baseline.md index 7f8f394329b..81bcd4a28b9 100644 --- a/docs/test-wall-clock-baseline.md +++ b/docs/test-wall-clock-baseline.md @@ -173,12 +173,12 @@ and is empty until one is made. | `plugins/code-metrics/scripts/persist-report.test.sh` | 0 | | | `plugins/code-metrics/scripts/python-resolve.test.sh` | 0 | | | `plugins/code-metrics/scripts/tool-free-path.test.sh` | 8 | | -| `plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.test.sh` | 17 | | | `plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh` | 60 | | | `plugins/code-metrics/skills/audit-duplication/scripts/audit-duplication.test.sh` | 40 | | -| `plugins/code-metrics/skills/audit-size/scripts/audit-size.test.sh` | 16 | | | `plugins/code-metrics/skills/audit-suppressions/scripts/audit-suppressions.test.sh` | 10 | | -| `plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.test.sh` | 10 | | +| `plugins/code-metrics/skills/audit/scripts/audit-complexity.test.sh` | 17 | | +| `plugins/code-metrics/skills/audit/scripts/audit-size.test.sh` | 16 | | +| `plugins/code-metrics/skills/audit/scripts/audit-type-debt.test.sh` | 10 | | | `plugins/code-metrics/skills/setup/scripts/setup-check.test.sh` | 21 | | | `plugins/code-tidying/scripts/added-lines.test.sh` | 1 | | | `plugins/code-tidying/scripts/allowed-tools-pairing.test.sh` | 0 | | diff --git a/docs/upstream/cursor-pstack.md b/docs/upstream/cursor-pstack.md index 7a0f84334aa..74813b07a28 100644 --- a/docs/upstream/cursor-pstack.md +++ b/docs/upstream/cursor-pstack.md @@ -86,7 +86,7 @@ is adopted by this record. | [`architect`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/architect) | [`planning:design`](../../plugins/planning/skills/design/SKILL.md), [`implementation:implement`](../../plugins/implementation/skills/implement/SKILL.md), [`architecture:improve`](../../plugins/architecture/skills/improve/research/deepening/vocabulary.md) | Partial | No new skill. Taken: the scrap tells, as the design-signals table `implementation:implement` checks before filing friction as a plan problem (`plugins/implementation/skills/implement/SKILL.md:153`). A `scaffold_stubs` setting, off by default, with which `planning:design` adds a stub scaffold section listing each new file and its signatures before the handoff gate (`plugins/planning/skills/design/SKILL.md:199-201`). In `planning:design`: the two-candidate step, as design's own step rather than a pointer, and Phase 3 opening from two or three caller sites and deriving the types from them (`plugins/planning/skills/design/SKILL.md:116-121,136`). Re-checked at e43c7ee26e: changed: the candidate screen now assumes whoever changes the code later is an agent that reads few files and imitates what is nearby, and the red-flags reference gained four flags: state with more than one writer, two supported routes to the same result, module internals reachable from outside, and lists kept in step by hand. Not taken as a new screen, because each already has an owner here: the duplicate-writer and content-coupling types in `coupling:reduce` (`plugins/coupling/skills/reduce/reference/coupling-model.md:36-50`), its second-list hotspot (same file, `:109-111`), the one-way rule of `discipline:reuse-or-replace` (`plugins/discipline/skills/reuse-or-replace/SKILL.md:14-16`), and the `architecture-test` rung for a forbidden import (`plugins/review/context/enforcement-ladder.md:44-46`). The imitating-agent assumption is already the stated reason for the ladder's `canonical-helper` rung and its rule that the most-copied weak pattern is fixed first (`plugins/review/context/enforcement-ladder.md:38-43,104-114`). `planning:design`'s two-candidate step restates none of the four flags; those owners keep them. Separately landed: the temporal-decomposition entry of the red-flags reference, in `architecture:improve`'s vocabulary as the rule that a run order is not a reason to split modules, which group by the knowledge they keep to themselves (`plugins/architecture/skills/improve/research/deepening/vocabulary.md:82-86`). That entry is identical at `23e4138` and at `e43c7ee26e`; only the four flags above changed. Re-checked at 118e73b0e1: holds; upstream shortened the overview and the implement phase, cut its default runners to two models, and kept the scrap phase and its tells. | none | | [`figure-it-out`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/figure-it-out) | [`planning:plan`'s phase order](../../plugins/planning/reference/config.md), [`implementation:implement`](../../plugins/implementation/skills/implement/SKILL.md), [`implementation:implement-dispatch`](../../plugins/implementation/skills/implement-dispatch/SKILL.md) | Partial | No skill. Taken: `riskiest-first` as one value of the `phase_order` setting in `planning` (`plugins/planning/reference/config.md:39,48`), and revert-not-patch as `implementation:implement`'s rule for a block that leaves its check where it was (`plugins/implementation/skills/implement/SKILL.md:116`). Gate repair in `implementation:implement-dispatch`: a gamed gate is rejected and its criterion restated so the same shortcut fails, and a mistaken gate is repaired in a separate change (`plugins/implementation/skills/implement-dispatch/SKILL.md:369`). Re-checked at 23e4138: holds. Re-checked at 118e73b0e1: holds; the description no longer names `show-me-your-work`, and the loop and revert rules are unchanged. Re-checked at 88d47514b8: holds; the only change is the subagent model-rule line, machinery we drop. | none | | [`how`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/how), [`investigation`](https://github.com/cursor/plugins/blob/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/poteto-mode/playbooks/investigation.md) | [`discovery:explore`](../../plugins/discovery/skills/explore/SKILL.md) and its [`explore_output` setting](../../plugins/discovery/reference/config.md) | Options | No `how` skill. Taken: `explore_output` in `discovery` (`auto` by default, `change-prep`, `explain`) chooses the shape of the final reply, and `explain` walks through how the scope works with a `path:line` cite at each step (`plugins/discovery/reference/config.md:34`). Re-checked at 23e4138: holds. Re-checked at 118e73b0e1: holds. Upstream renumbered its steps and cut the explorer prompt's step list; the walkthrough output we took does not depend on the cut text, and `investigation` is unchanged. Re-checked at 88d47514b8: holds; the only change to `how` is the subagent model-rule line, and `investigation` is unchanged. | none | -| [`interrogate`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/interrogate) | [`review:fanout`](../../plugins/review/skills/fanout/SKILL.md), [`review:code-reviewer`](../../plugins/review/agents/code-reviewer.md), `review:quality-gate` with [`code-metrics:audit-size`](../../plugins/code-metrics/skills/audit-size/SKILL.md) | Partial | Landed in `review:fanout`: a short intent paragraph the orchestrator writes in its own words and passes, labeled as the author's claim, to every surface it dispatches, as a description to test and never evidence (`plugins/review/skills/fanout/SKILL.md:95-99`), and a `## Dismissed` report section listing each demotion with its reason (`:145-149`). Landed in `review:code-reviewer`: the reviewer rubric's repeat-run and dual-path item, flagging an old and a new path for one behavior both left callable with nothing saying which callers use which (`plugins/review/agents/code-reviewer.md:67`). Review's `fanout_diversity` setting, values `lens` (default, one reviewer agent per concern) and `model` (one review prompt per distinct fan-out model tier) (`plugins/review/skills/fanout/SKILL.md:64-76`, `plugins/review/workflows/fanout-sweep.js:32`, `plugins/review/reference/config.md:13`, `plugins/review/.claude-plugin/plugin.json:37`). The same rubric line holds the second rubric item, state-changing code that may run a second time after a retry or a resume (`plugins/review/agents/code-reviewer.md:67`), and the large-file flag is the reviewer's size-crossing note: an advisory finding for a file that went from below the consumer's `size.file_lines` reference at the base to at or above it at the head, counted through `code-metrics:audit-size` (`plugins/review/agents/code-reviewer.md:33`). Re-checked at 23e4138: holds; unchanged at `e43c7ee26e`. Re-checked at 118e73b0e1: holds. Upstream shortened its scope, intent and synthesis steps and cut its default reviewers from three models to two; the intent paragraph, the Dismissed bucket, the agreement section and the rubric's idempotency item remain. Re-checked at 88d47514b8 ([cursor/plugins#634](https://github.com/cursor/plugins/pull/634)): changed: the lead-judgment reference lost its opening, which said why the lead filters rather than aggregates, and its Verdict Calibration section, which capped the Act On list at about five items and called the Dismissed list a trust mechanism; `SKILL.md` gained the subagent model-rule line and a family fallback for `cursor-grok-*` and `composer-*` slugs. The Dismissed section stays in the skill's report shape, so our `## Dismissed` take stands and its reason is now ours alone; we never took the five-item cap. | none | +| [`interrogate`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/interrogate) | [`review:fanout`](../../plugins/review/skills/fanout/SKILL.md), [`review:code-reviewer`](../../plugins/review/agents/code-reviewer.md), `review:quality-gate` with [`code-metrics:audit size`](../../plugins/code-metrics/skills/audit/actions/size.md) | Partial | Landed in `review:fanout`: a short intent paragraph the orchestrator writes in its own words and passes, labeled as the author's claim, to every surface it dispatches, as a description to test and never evidence (`plugins/review/skills/fanout/SKILL.md:95-99`), and a `## Dismissed` report section listing each demotion with its reason (`:145-149`). Landed in `review:code-reviewer`: the reviewer rubric's repeat-run and dual-path item, flagging an old and a new path for one behavior both left callable with nothing saying which callers use which (`plugins/review/agents/code-reviewer.md:67`). Review's `fanout_diversity` setting, values `lens` (default, one reviewer agent per concern) and `model` (one review prompt per distinct fan-out model tier) (`plugins/review/skills/fanout/SKILL.md:64-76`, `plugins/review/workflows/fanout-sweep.js:32`, `plugins/review/reference/config.md:13`, `plugins/review/.claude-plugin/plugin.json:37`). The same rubric line holds the second rubric item, state-changing code that may run a second time after a retry or a resume (`plugins/review/agents/code-reviewer.md:67`), and the large-file flag is the reviewer's size-crossing note: an advisory finding for a file that went from below the consumer's `size.file_lines` reference at the base to at or above it at the head, counted through `code-metrics:audit size` (`plugins/review/agents/code-reviewer.md:33`). Re-checked at 23e4138: holds; unchanged at `e43c7ee26e`. Re-checked at 118e73b0e1: holds. Upstream shortened its scope, intent and synthesis steps and cut its default reviewers from three models to two; the intent paragraph, the Dismissed bucket, the agreement section and the rubric's idempotency item remain. Re-checked at 88d47514b8 ([cursor/plugins#634](https://github.com/cursor/plugins/pull/634)): changed: the lead-judgment reference lost its opening, which said why the lead filters rather than aggregates, and its Verdict Calibration section, which capped the Act On list at about five items and called the Dismissed list a trust mechanism; `SKILL.md` gained the subagent model-rule line and a family fallback for `cursor-grok-*` and `composer-*` slugs. The Dismissed section stays in the skill's report shape, so our `## Dismissed` take stands and its reason is now ours alone; we never took the five-item cap. | none | | [`no-comments`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/no-comments), [`comment-sicko`](https://github.com/cursor/plugins/blob/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/agents/comment-sicko.md) | [`code-tidying:dissolve-comments`](../../plugins/code-tidying/skills/dissolve-comments/SKILL.md), `code-tidying:audit-comment-residue`, [`code-metrics:audit-suppressions`](../../plugins/code-metrics/skills/audit-suppressions/SKILL.md) | Partial | Taken: `code-tidying:dissolve-comments` keeps a suppression's justification beside its waiver (`plugins/code-tidying/skills/dissolve-comments/SKILL.md:102`) and proposes a regression test or a lint rule for a comment that states a constraint the code could enforce (`:168-172`); the run's mode settles a doubtful comment, kept under the cautious modes and kept under `aggressive` and `strip` only when it is a listed survivor kind (`:130-139`); and `code-metrics:audit-suppressions` is the suppression inventory. Re-checked at 23e4138: holds. Re-checked at 118e73b0e1: holds; the agent's id is now `comment-sicko`, and `no-comments` spawns it by that id. Re-checked at 88d47514b8: holds; the only change to `no-comments` is the subagent model-rule line, and `comment-sicko` is unchanged. | none | | [`setup-pstack`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/setup-pstack) | `multi-agent:route` | Partial | We keep alias tiers and per-plugin configuration; an effort budget lives in multi-agent configuration. Re-checked at 23e4138: holds. Re-checked at 118e73b0e1: holds; upstream changed its budget labels and model defaults, which we do not take. Re-checked at 88d47514b8: holds; a new last step offers once to generate a formal verification skill through `create-formal-verification-skill`, which is not adopted (see [below](#sharpen-and-the-formal-verification-pair-not-now)); the alias tiers and per-plugin configuration we keep are unchanged. | none | | [`principle-attack-the-premise`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/principle-attack-the-premise), [`principle-fix-root-causes`](https://github.com/cursor/plugins/tree/88d47514b82e7c44f00f2b2a72ff6dd12158038c/pstack/skills/principle-fix-root-causes) | [`debugging:debug`](../../plugins/debugging/skills/debug/SKILL.md), [`code-tidying:audit-comment-residue`](../../plugins/code-tidying/skills/audit-comment-residue/SKILL.md) | Partial | Taken in `debugging:debug`: after a second failed fix, reduce what the failed fixes share to one claim a test can check, running the per-actor tally first when the symptom is uneven (`plugins/debugging/skills/debug/SKILL.md:383`); a failure that began after a restart with no code change ranks what the old process left on disk first in the hypothesis table (`:200`); and a shipped workaround needs a tracking link or a removal condition in its comment, which `code-tidying:audit-comment-residue` reports as `unjustified-workaround` when both are missing (`:369`). Re-checked at 23e4138: holds. Re-checked at 88d47514b8 ([cursor/plugins#633](https://github.com/cursor/plugins/pull/633), landed by `99743e9c15`): changed; both principles are restated as reasoning. `principle-attack-the-premise` dropped its census of which actors hold an imbalance and its rotate-or-randomize remedies; it now asks for an observation that would come out differently if the premise were false, read from how the failures are distributed and not only their size. That is the one checkable claim `debugging:debug` already takes (`:383`); running the per-actor tally before that test is now ours alone, kept as one way to read the distribution. `principle-fix-root-causes` now names the root cause as the first place the system went wrong, keeps suspecting persisted state after a restart (`:200`) and fixing the code rather than a paragraph-long comment (`:369`), and replaces its flat ban on guards with a test: handling a state is the fix when the system may legitimately be in it, and a guard hides the bug when the state should never exist. Taken in `debugging:debug` under the principle placement of [#7589](https://github.com/melodic-software/claude-code-plugins/issues/7589): its "Does not fix the symptom" line now states that test. Also taken there: after a deep dig, Phase 6 proposes the cheap always-on signal that would have shown the deciding fact at first look, gated by the `always_on_signal` key of `docs/conventions/debugging.yaml`, and searches for the fixed defect's siblings. | none | diff --git a/plugins/code-metrics/.claude-plugin/plugin.json b/plugins/code-metrics/.claude-plugin/plugin.json index b49b562ed81..96f0a71d220 100644 --- a/plugins/code-metrics/.claude-plugin/plugin.json +++ b/plugins/code-metrics/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "code-metrics", - "description": "Read-only code measures for a change, with cited references and no verdict: lines per file (audit-size), cyclomatic, cognitive, and Halstead complexity (audit-complexity), duplication (audit-duplication), per-function coverage and CRAP from existing lcov, Cobertura, coverage.py, or Go artifacts (audit-coverage), TypeScript and Python type debt (audit-type-debt), metric literacy (principles), and setup. Uses only collectors already installed; never installs or runs tests.", + "description": "Read-only code measures for a change, with cited references and no verdict: lines per file (audit size), cyclomatic, cognitive, and Halstead complexity (audit complexity), duplication (audit-duplication), per-function coverage and CRAP from existing lcov, Cobertura, coverage.py, or Go artifacts (audit-coverage), TypeScript and Python type debt (audit type-debt), metric literacy (principles), and setup. Uses only collectors already installed; never installs or runs tests.", "author": { "name": "Melodic Software", "email": "info@melodicsoftware.com" diff --git a/plugins/code-metrics/README.md b/plugins/code-metrics/README.md index 0096082a8c6..86363c04c2b 100644 --- a/plugins/code-metrics/README.md +++ b/plugins/code-metrics/README.md @@ -12,11 +12,11 @@ value to count against, not a bar. | Skill | What it does | |---|---| -| `/code-metrics:audit-complexity` | Per-function cyclomatic and cognitive complexity and Halstead difficulty from whichever collector resolves (`lizard`, `radon`, ESLint rules, `gocyclo`, `gocognit`, `shellmetrics`, `multimetric`), beside the ISO/IEC 5055 §8.2.117 reference of 20 with 10 and 15 selectable; cognitive and Halstead carry no standard threshold. | -| `/code-metrics:audit-size` | Lines per file (total, blank, comment, code through `scc`; total and non-blank from a bundled counter otherwise) beside a cited reference; `size.mode: iso-8.2.115` adds the ISO function-percentage form. | +| `/code-metrics:audit complexity` | Per-function cyclomatic and cognitive complexity and Halstead difficulty from whichever collector resolves (`lizard`, `radon`, ESLint rules, `gocyclo`, `gocognit`, `shellmetrics`, `multimetric`), beside the ISO/IEC 5055 §8.2.117 reference of 20 with 10 and 15 selectable; cognitive and Halstead carry no standard threshold. | +| `/code-metrics:audit size` | Lines per file (total, blank, comment, code through `scc`; total and non-blank from a bundled counter otherwise) beside a cited reference; `size.mode: iso-8.2.115` adds the ISO function-percentage form. | | `/code-metrics:audit-duplication` | Clone classes (the detector's pairs merged; duplicated lines and tokens, every instance's range) from `jscpd`, `dupl`, or PMD CPD, rolled up per lane and per directory, minus the replication the repository declares in a sanctioned-replication registry (a path-within-plugin, or a `canonical -> copies` cluster line), which is an exclusion, not a suppression. A file over the size cap is reported as skipped, never silently dropped. | | `/code-metrics:audit-coverage` | Line coverage per file and per function read from the artifacts a build already produced (lcov 1.x and 2.2, Cobertura, coverage.py JSON, Go cover profile), plus CRAP per function from the complexity rows; it never runs a test, a missing artifact is a visible warning, and a function with no executable lines reports `null`, never zero. | -| `/code-metrics:audit-type-debt` | The typed-code percentage per file and per lane: `type-coverage` for TypeScript, mypy's `--any-exprs-report` for Python; no standard or CWE anchors the measure, so the reference is `null` by design. C# is reported as not applicable. | +| `/code-metrics:audit type-debt` | The typed-code percentage per file and per lane: `type-coverage` for TypeScript, mypy's `--any-exprs-report` for Python; no standard or CWE anchors the measure, so the reference is `null` by design. C# is reported as not applicable. | | `/code-metrics:audit-suppressions` | Every lint and type-checker suppression (ESLint, TypeScript, `noqa`, mypy, pylint, Pyright, Ruff, ShellCheck, C# pragmas and attributes, `nolint`, PowerShell attributes, markdownlint, RuboCop, Java `@SuppressWarnings`) in the change's added lines, a path, or the tree, each with its rule ids and reason and whether it is justified (a reason, plus a rule id where the tool can name one); rule ids listed in `suppressions.correctness_rules` are marked. The bundled scanner's `--count` prints the counts for a CI ceiling. | | `/code-metrics:principles` | Metric literacy: what each measure can and cannot tell you, where every reference value came from, CRAP's corrected provenance, the cross-metric caveats (carried once, here), and gated pointers to the plugins that own mutation score, tautological tests, dead code, coupling, and lint. | | `/code-metrics:setup` | `check` probes the interpreter and every configuration layer, and runs one measure per collector on a bundled fixture; `apply` writes the tracked team configuration per key, idempotently, and never installs a tool. | @@ -26,7 +26,7 @@ value to count against, not a bar. Lanes are detected from file extensions (TypeScript/JavaScript, Python, Bash, Go, and C#, whose complexity lane is deferred and reported as such). Every other text file, markdown, JSON, YAML, PowerShell, a `Makefile`, lands in the catch-all `other` lane, which carries a line count and -nothing else: `audit-size` measures it, and every other measure reports it as not applicable. +nothing else: `audit size` measures it, and every other measure reports it as not applicable. When the consuming repository tracks `.claude/ecosystems/.yaml` files, their `globs` override the bundled map for that lane. Two scopes are first-class: the default is the change, files that differ from the merge-base with the default branch plus uncommitted and untracked diff --git a/plugins/code-metrics/prerequisites.json b/plugins/code-metrics/prerequisites.json index 1b18b3b47e9..844a3b17daa 100644 --- a/plugins/code-metrics/prerequisites.json +++ b/plugins/code-metrics/prerequisites.json @@ -28,14 +28,14 @@ "kind": "runtime", "need": "optional", "for": [ - "skill:audit-type-debt" + "skill:audit" ], "detect": { "any": [ "node" ] }, - "degrade": "Without node, /code-metrics:audit-type-debt cannot tell whether `typescript` resolves and reports no TypeScript type coverage.", + "degrade": "Without node, /code-metrics:audit type-debt cannot tell whether `typescript` resolves and reports no TypeScript type coverage.", "install": { "docs": "https://nodejs.org/en/download", "brew": "node", @@ -49,14 +49,14 @@ "kind": "cli", "need": "optional", "for": [ - "skill:audit-complexity" + "skill:audit" ], "detect": { "any": [ "go" ] }, - "degrade": "Without go, /code-metrics:audit-complexity cannot read the version stamped into a gocognit binary; Go cognitive complexity is reported without it.", + "degrade": "Without go, /code-metrics:audit complexity cannot read the version stamped into a gocognit binary; Go cognitive complexity is reported without it.", "install": { "docs": "https://go.dev/doc/install", "brew": "go", diff --git a/plugins/code-metrics/scripts/dispatch.sh b/plugins/code-metrics/scripts/dispatch.sh index e3c48b8f010..d7bad831daf 100755 --- a/plugins/code-metrics/scripts/dispatch.sh +++ b/plugins/code-metrics/scripts/dispatch.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # The code-metrics dispatcher: resolve the scope, detect lanes, walk the # collector ladder, and print one `code-metrics/v2` document (design T1, T3, -# T5). Every audit skill's entry script (skills//scripts/.sh) calls this; skill-specific options are the -# skill's own and never reach here. +# T5). Every audit entry script (skills//scripts/.sh) calls this; entry-specific options are the +# entry script's own and never reach here. # # dispatch.sh --measures [--all] [--base ] # [--config ] [--ladder ] diff --git a/plugins/code-metrics/skills/audit-complexity/evals/evals.json b/plugins/code-metrics/skills/audit-complexity/evals/evals.json deleted file mode 100644 index a4fd044e538..00000000000 --- a/plugins/code-metrics/skills/audit-complexity/evals/evals.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "skill_name": "audit-complexity", - "evals": [ - { - "id": 1, - "name": "reports-the-change-with-provenance-and-no-verdict", - "prompt": "/code-metrics:audit-complexity", - "expected_output": "Runs the bundled audit-complexity.sh against the change (merge-base diff plus uncommitted files), presents the markdown report with its Coverage of this run table, the cyclomatic reference of 20 cited to ISO/IEC 5055:2021 section 8.2.117, and no reference for cognitive complexity or Halstead difficulty, and renders no pass/fail verdict.", - "files": [], - "expectations": [ - "Invokes the skill's scripts/audit-complexity.sh rather than estimating complexity by reading the code", - "Presents the Coverage of this run table naming the collector and version used per lane and measure", - "Cites ISO/IEC 5055:2021 section 8.2.117 for the cyclomatic reference of 20", - "States that cognitive complexity and Halstead difficulty carry no reference because no standard sets one", - "Does not declare any function a failure, defect, or violation" - ] - }, - { - "id": 2, - "name": "a-missing-collector-is-visible-not-silent", - "prompt": "/code-metrics:audit-complexity src/ (this repository has no eslint-plugin-sonarjs and no lizard)", - "expected_output": "The report's run table shows the TypeScript cognitive row as unavailable with the reason, names the collector that did answer for cyclomatic complexity, offers the install hints without installing anything, and still reports every measure that a resolvable collector produced.", - "files": [], - "expectations": [ - "The run table carries an unavailable row with a reason for the measure whose collectors did not resolve", - "Offers the install hint without installing, downloading, or npx-fetching any collector", - "Still reports the measures the resolvable collectors produced rather than stopping", - "Reports an unmeasured value as null and never as zero" - ] - }, - { - "id": 3, - "name": "json-feeds-a-comparison-through-the-gated-pointer", - "prompt": "/code-metrics:audit-complexity --json --all src/ so I can compare it after the refactor", - "expected_output": "Produces the code-metrics/v2 JSON document, keeps it for the comparison, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explains the manual comparison and that an empty status is inconclusive.", - "files": [], - "expectations": [ - "Runs audit-complexity.sh with --json and keeps the document for the later comparison", - "Mentions /verification:measure only behind an if-installed gate with a stated fallback", - "States that a report with status empty on either side makes the comparison inconclusive" - ] - } - ] -} diff --git a/plugins/code-metrics/skills/audit-coverage/SKILL.md b/plugins/code-metrics/skills/audit-coverage/SKILL.md index 451b7edacb7..16d978f36a0 100644 --- a/plugins/code-metrics/skills/audit-coverage/SKILL.md +++ b/plugins/code-metrics/skills/audit-coverage/SKILL.md @@ -1,5 +1,5 @@ --- -description: "Read coverage artifacts a build already wrote (lcov, Cobertura, coverage.py JSON, a Go cover profile) and report line coverage per file and function, plus CRAP per function, for a change, a path, or the tree. Runs no tests, never gates. Use when: 'coverage of this change', 'coverage per function', 'CRAP score', 'which functions are complex and untested', 'read the lcov report', 'coverage.xml', 'how covered is this file'. Complexity alone: /code-metrics:audit-complexity." +description: "Read coverage artifacts a build already wrote (lcov, Cobertura, coverage.py JSON, a Go cover profile) and report line coverage per file and function, plus CRAP per function, for a change, a path, or the tree. Runs no tests, never gates. Use when: 'coverage of this change', 'coverage per function', 'CRAP score', 'which functions are complex and untested', 'read the lcov report', 'coverage.xml', 'how covered is this file'. Complexity alone: /code-metrics:audit complexity." argument-hint: "[--json] [--all] [--base ] [--artifacts ]... [...]" user-invocable: true disable-model-invocation: false @@ -22,7 +22,7 @@ and stays there, so nothing here executes a test command, starts a runner, or in Two numbers come out. Line coverage per file and per function is read from the artifact. CRAP per function is derived: `comp^2 * (1 - cov/100)^3 + comp`, where `comp` is the function's cyclomatic -complexity from the sibling `audit-complexity` script, run over the same scope. +complexity from the `audit` skill's `audit-complexity.sh` script, run over the same scope. | Format | Written by | What the join gets from it | |---|---|---| diff --git a/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh b/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh index 647c93fd45a..d505bb355c9 100755 --- a/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh +++ b/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh @@ -9,8 +9,8 @@ # instead. Artifacts come from every `--artifacts` and from # `coverage.artifacts` in the config; with none named, well-known names are # looked for under the repository root, at most two directory levels deep. -# Complexity for the CRAP formula comes from the sibling audit-complexity -# skill's entry script, run over the same scope. Exit codes: 0 report +# Complexity for the CRAP formula comes from the audit skill's complexity +# entry script, run over the same scope. Exit codes: 0 report # produced, including an empty one; 2 usage error, which includes a named # artifact or scope path that does not exist; 3 a collector ran and produced # nothing parseable. @@ -20,7 +20,7 @@ SCRIPT_DIR="$(cd "${BASH_SOURCE[0]%/*}" && pwd)" PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$SCRIPT_DIR/../../.." && pwd)}" REPORT="$PLUGIN_ROOT/scripts/report.py" PARSERS="$PLUGIN_ROOT/scripts/parsers" -COMPLEXITY="$PLUGIN_ROOT/skills/audit-complexity/scripts/audit-complexity.sh" +COMPLEXITY="$PLUGIN_ROOT/skills/audit/scripts/audit-complexity.sh" # Well-known artifact names, in the order they are looked for. Directories # excluded from the walk: node_modules, .git, vendor. WELL_KNOWN=(coverage/lcov.info lcov.info coverage.xml cobertura.xml coverage.json coverage.out cover.out) diff --git a/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh b/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh index b8b56eb6b39..d14144bc118 100755 --- a/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh +++ b/plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh @@ -8,7 +8,7 @@ # (fixtures/coverage/lcov-cluster.info covers both cluster copies of the # registry's shared file), and the markdown rendering. # -# Complexity comes from the sibling audit-complexity script, so its collectors +# Complexity comes from the audit skill's audit-complexity script, so its collectors # are stubbed at runtime the same way its own suite does it: a temporary bin/ # prepended to a filtered PATH carries a fake `lizard` replaying # fixtures/tool-output/lizard.csv (function start AND end lines) and a fake diff --git a/plugins/code-metrics/skills/audit-coverage/scripts/join.py b/plugins/code-metrics/skills/audit-coverage/scripts/join.py index 475ac052abb..17371c9af87 100755 --- a/plugins/code-metrics/skills/audit-coverage/scripts/join.py +++ b/plugins/code-metrics/skills/audit-coverage/scripts/join.py @@ -10,8 +10,8 @@ Prints `{"measures": [...], "run": [...]}` to stdout; the two `--*-out` options write the same rows as JSON lines for `report.py assemble`. -`--complexity` is one `code-metrics/v2` document from the sibling -`audit-complexity` skill. Its per-function rows supply the cyclomatic +`--complexity` is one `code-metrics/v2` document from the `audit` skill's +complexity action. Its per-function rows supply the cyclomatic complexity and the line range; `--artifacts` are the mappings the parsers under `../../../scripts/parsers/` print, each tagged with the format it came from, so a reason can name it. diff --git a/plugins/code-metrics/skills/audit-duplication/SKILL.md b/plugins/code-metrics/skills/audit-duplication/SKILL.md index 280fd0ee418..e3de23e56bb 100644 --- a/plugins/code-metrics/skills/audit-duplication/SKILL.md +++ b/plugins/code-metrics/skills/audit-duplication/SKILL.md @@ -1,5 +1,5 @@ --- -description: "Measure duplicated code as clone classes over a change, a path, or the tree, with every instance's file and line range, subtracting replication the repo declares sanctioned. Reports, never gates. Use when: 'is this duplicated', 'find copy-paste code', 'clone detection', 'duplication report', 'how much of this change is copied', 'DRY check', 'redundant code', 'duplicated lines in the diff'. Lines per file: /code-metrics:audit-size." +description: "Measure duplicated code as clone classes over a change, a path, or the tree, with every instance's file and line range, subtracting replication the repo declares sanctioned. Reports, never gates. Use when: 'is this duplicated', 'find copy-paste code', 'clone detection', 'duplication report', 'how much of this change is copied', 'DRY check', 'redundant code', 'duplicated lines in the diff'. Lines per file: /code-metrics:audit size." argument-hint: "[--json] [--keep] [--all] [--base ] [--registry ] [...]" user-invocable: true disable-model-invocation: false diff --git a/plugins/code-metrics/skills/audit-size/evals/evals.json b/plugins/code-metrics/skills/audit-size/evals/evals.json deleted file mode 100644 index 74776e16157..00000000000 --- a/plugins/code-metrics/skills/audit-size/evals/evals.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "skill_name": "audit-size", - "evals": [ - { - "id": 1, - "name": "reports-the-change-with-provenance-and-no-verdict", - "prompt": "/code-metrics:audit-size", - "expected_output": "Runs the bundled audit-size.sh against the change (merge-base diff plus uncommitted files), presents the markdown report with its Coverage of this run table and the 1000-line reference labeled as the plugin's own number rather than ISO-backed, and renders no pass/fail verdict.", - "files": [], - "expectations": [ - "Invokes the skill's scripts/audit-size.sh rather than counting lines by hand", - "Presents the Coverage of this run table naming the collector used (scc or the bundled counter) per lane", - "States the reference's provenance: 1000 is the plugin's own number, not ISO-backed", - "Does not declare any file a failure, defect, or violation" - ] - }, - { - "id": 2, - "name": "scc-absent-is-visible-not-silent", - "prompt": "/code-metrics:audit-size src/ (scc is not installed on this machine)", - "expected_output": "The report's run table shows the bundled counter as the collector with the comment-agnostic label, explains that scc did not resolve, and does not attempt to install it.", - "files": [], - "expectations": [ - "The run table names line-counter as the collector and the rows carry the comment-agnostic label", - "Says scc did not resolve and offers its install hint without installing anything", - "Still reports total and non-blank lines per file" - ] - }, - { - "id": 3, - "name": "json-feeds-a-comparison-through-the-gated-pointer", - "prompt": "/code-metrics:audit-size --json --all src/ so I can compare it after the refactor", - "expected_output": "Produces the code-metrics/v2 JSON document, keeps it for the comparison, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explains the manual comparison and that an empty status is inconclusive.", - "files": [], - "expectations": [ - "Runs audit-size.sh with --json and keeps the document for the later comparison", - "Mentions /verification:measure only behind an if-installed gate with a stated fallback", - "States that a report with status empty on either side makes the comparison inconclusive" - ] - } - ] -} diff --git a/plugins/code-metrics/skills/audit-suppressions/SKILL.md b/plugins/code-metrics/skills/audit-suppressions/SKILL.md index c0485f47ee1..edb1a13208a 100644 --- a/plugins/code-metrics/skills/audit-suppressions/SKILL.md +++ b/plugins/code-metrics/skills/audit-suppressions/SKILL.md @@ -1,5 +1,5 @@ --- -description: "List every lint and type-checker suppression in a change, a path, or the tree (`--all`): eslint-disable, @ts-expect-error, noqa, type: ignore, pylint, pyright, shellcheck disable, C# pragmas and SuppressMessage, nolint, PowerShell SuppressMessageAttribute, markdownlint, rubocop, @SuppressWarnings. Each row names its rule ids, its reason, and whether it is justified; listed correctness rules are marked. Reports, never gates. Use when: 'how many suppressions', 'find eslint-disable comments', 'which noqa have no reason', 'suppressions added in this change', 'audit lint suppressions', 'count suppressions to ratchet'. Complexity: /code-metrics:audit-complexity." +description: "List every lint and type-checker suppression in a change, a path, or the tree (`--all`): eslint-disable, @ts-expect-error, noqa, type: ignore, pylint, pyright, shellcheck disable, C# pragmas and SuppressMessage, nolint, PowerShell SuppressMessageAttribute, markdownlint, rubocop, @SuppressWarnings. Each row names its rule ids, its reason, and whether it is justified; listed correctness rules are marked. Reports, never gates. Use when: 'how many suppressions', 'find eslint-disable comments', 'which noqa have no reason', 'suppressions added in this change', 'audit lint suppressions', 'count suppressions to ratchet'. Complexity: /code-metrics:audit complexity." argument-hint: "[--json|--findings [--memory-dir ]] [--all] [--base ] [...]" user-invocable: true disable-model-invocation: false diff --git a/plugins/code-metrics/skills/audit-type-debt/evals/evals.json b/plugins/code-metrics/skills/audit-type-debt/evals/evals.json deleted file mode 100644 index 3370cb3e845..00000000000 --- a/plugins/code-metrics/skills/audit-type-debt/evals/evals.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "skill_name": "audit-type-debt", - "evals": [ - { - "id": 1, - "name": "reports-both-percentages-without-anchoring-them", - "prompt": "/code-metrics:audit-type-debt", - "expected_output": "Runs the bundled audit-type-debt.sh against the change, presents the markdown report with its Coverage of this run table, and states that no standard or CWE anchors the measure so the reference is null, without declaring any lane a pass or a failure.", - "files": [], - "expectations": [ - "Invokes the skill's scripts/audit-type-debt.sh rather than grepping for any by hand", - "Presents the per-lane percentages for TypeScript and Python with the collector named for each", - "States that no standard or CWE anchors the measure and that the reference is null", - "Does not average the TypeScript and Python percentages or compare them with each other", - "Does not declare any lane a failure, defect, or violation" - ] - }, - { - "id": 2, - "name": "csharp-is-not-applicable-rather-than-a-count", - "prompt": "/code-metrics:audit-type-debt src/ (this repository is mostly C# with one TypeScript front end)", - "expected_output": "The run table shows the dotnet lane as not-applicable with the sentence that no tool produces a comparable percentage for C# and that a dynamic or object occurrence count is not comparable to a ratio, while the TypeScript lane still reports its percentage.", - "files": [], - "expectations": [ - "The dotnet row is reported as not-applicable with its stated reason", - "Explains that an occurrence count is not comparable to a ratio rather than offering one", - "Still reports the TypeScript percentage from the same run" - ] - }, - { - "id": 3, - "name": "absent-type-coverage-is-visible-not-silent", - "prompt": "/code-metrics:audit-type-debt --json --all so I can compare it after the typing sweep (type-coverage is not installed here)", - "expected_output": "Produces the code-metrics/v2 JSON document, reports the typescript lane as unavailable with its install hint and the requirement that typescript also resolves, installs nothing, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explaining the manual comparison.", - "files": [], - "expectations": [ - "Runs audit-type-debt.sh with --json and keeps the document for the later comparison", - "Says the typescript lane is unavailable and offers the install hint without installing anything", - "Notes that type-coverage needs a resolvable typescript in the project", - "Mentions /verification:measure only behind an if-installed gate with a stated fallback", - "States that a report with status empty on either side makes the comparison inconclusive" - ] - } - ] -} diff --git a/plugins/code-metrics/skills/audit/SKILL.md b/plugins/code-metrics/skills/audit/SKILL.md new file mode 100644 index 00000000000..09979f79378 --- /dev/null +++ b/plugins/code-metrics/skills/audit/SKILL.md @@ -0,0 +1,83 @@ +--- +description: "Measure code for the changed files (the default), explicit paths, or the whole tree (`--all`), each number beside a configurable reference with its provenance. Reports, never gates. Actions: size (lines per file, every text file), complexity (per-function cyclomatic, cognitive and Halstead from collectors already installed), type-debt (typed-code percentage from type-coverage and mypy). Use when: 'how long are these files', 'lines per file', 'which files are too big', 'is this file over 1000 lines', 'how complex is this code', 'cyclomatic complexity', 'cognitive complexity', 'Halstead difficulty', 'how much of this is typed', 'type coverage', 'how many anys are in this', 'type debt'. Coverage and CRAP: /code-metrics:audit-coverage." +argument-hint: " [--json] [--all] [--base ] [...]" +user-invocable: true +disable-model-invocation: false +allowed-tools: ["Bash(${CLAUDE_SKILL_DIR}/scripts/audit-size.sh:*)", "Bash(${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh:*)", "Bash(${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh:*)", "Bash(git branch --show-current:*)"] +shell: bash +metadata: + workflow-stage: anytime + summary: Lines, complexity and typed-code numbers beside cited references, no verdict +--- + +## Pre-computed context + +Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"` + +## Variables + +Arguments: `$ARGUMENTS` + +The first word names the action; the rest passes to its script unchanged. + +## Actions + +| Argument | Measures | Script | Full process | +|---|---|---|---| +| `size` | Lines per file, every text file in every lane | `${CLAUDE_SKILL_DIR}/scripts/audit-size.sh` | `actions/size.md` | +| `complexity` | Per-function cyclomatic and cognitive complexity and Halstead difficulty | `${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh` | `actions/complexity.md` | +| `type-debt` | Typed-code percentage per file and per lane (TypeScript, Python) | `${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh` | `actions/type-debt.md` | + +With no action word, take the action from the request: file length or lines is `size`, +complexity is `complexity`, typing or `any` is `type-debt`. When the request names none of them, +list the three actions and ask which to run. Read the action's file before running its script; one +action per invocation. + +## Standing rules + +- Every action reports and never gates: each number sits beside a reference with its provenance, + and nothing here is a pass, a fail, a finding or a severity. +- Run the action's bundled script; never count, estimate or grep the measure by hand. +- Scope is the change by default (the merge-base diff plus uncommitted files); explicit paths or + `--all` widen it, and `--json` prints the `code-metrics/v2` document instead of markdown. +- Present the markdown report as printed. Keep the `--json` document when the numbers feed a + comparison: `/verification:measure metrics` consumes it when the `verification` plugin is + installed (treat `status: empty` on either side as INCONCLUSIVE); otherwise keep it beside your + notes and compare by hand. +- A `null` value is a number the collector did not produce, never zero. +- Nothing is installed; a missing collector is a row in the run table with its install hint. + +## Spoke paths + +The `actions/` files write this skill's directory as ``, which is `${CLAUDE_SKILL_DIR}`, +and the plugin's root directory as ``, which is `${CLAUDE_PLUGIN_ROOT}`. Put those +paths in place of the placeholders before running a command: a `${…}` token is substituted in +skill content but not in a supporting file, and the Bash tool does not receive the plugin +variables. The plugins reference, +, as of +2026-11-03; recheck when that table adds supporting files to where a `${…}` reference resolves, or +the Bash tool starts receiving the plugin variables. + +## What this skill does not do + +- It does not run tests, edit files, or install a collector. +- It does not judge: no reference is a bar, and no `check` gate exists in this version. +- It does not measure duplication, coverage or suppressions; those are the sibling `audit-*` + skills in this plugin, and `/code-metrics:principles` explains what each number can and cannot + tell you. + +## Next + +- The numbers feed a before-and-after comparison: `/verification:measure metrics`. +- A complex function's coverage and CRAP score are the real question: + `/code-metrics:audit-coverage`. +- A number is about to be quoted or read as a bar: `/code-metrics:principles`. + +## Gotchas + +- Change scope needs a merge-base with the default branch; outside a git repository, or on a + branch with no default-branch ancestor, pass paths or `--all` (the usage error says which). +- The report `skill` field and the dispatcher id stay `audit-size`, `audit-complexity` and + `audit-type-debt`: they name the producer, so reports taken before and after the move still + compare. +- Each action's own gotchas are in its file under `actions/`. diff --git a/plugins/code-metrics/skills/audit-complexity/SKILL.md b/plugins/code-metrics/skills/audit/actions/complexity.md similarity index 78% rename from plugins/code-metrics/skills/audit-complexity/SKILL.md rename to plugins/code-metrics/skills/audit/actions/complexity.md index 09be9146203..81db7b2a044 100644 --- a/plugins/code-metrics/skills/audit-complexity/SKILL.md +++ b/plugins/code-metrics/skills/audit/actions/complexity.md @@ -1,23 +1,7 @@ ---- -description: "Measure per-function cyclomatic and cognitive complexity and Halstead difficulty for a change, a path, or the tree, from whichever collector already resolves (it installs none), each number beside its cited reference. Reports, never gates. Use when: 'how complex is this code', 'cyclomatic complexity', 'cognitive complexity', 'complexity audit', 'is this function too complex', 'Halstead difficulty', 'measure complexity of a change'. Lines per file: /code-metrics:audit-size." -argument-hint: "[--json] [--all] [--base ] [...]" -user-invocable: true -disable-model-invocation: false -allowed-tools: ["Bash(${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh:*)", "Bash(git branch --show-current:*)"] -shell: bash -metadata: - workflow-stage: anytime - summary: Per-function complexity beside a cited reference, no verdict ---- - -## Pre-computed context - -Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"` - -## Purpose +# Complexity Complexity is the measure with the most citable reference on the operator's list and the most -folklore around it. This skill reports the numbers, per function where the collector reports per +folklore around it. This action reports the numbers, per function where the collector reports per function, beside references whose provenance is printed with them, and stops there: no pass or fail, no severity, no finding. Whether a complexity of 23 is worth changing is the reader's call. @@ -42,10 +26,10 @@ carry `function: null`, and are labeled `file-level`. Its Bash cyclomatic figure ## Run it ```bash -"${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh" # the change: merge-base diff plus uncommitted files -"${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh" src/ lib/parse.py # explicit paths (a missing one is a usage error) -"${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh" --all # every tracked or untracked-but-not-ignored file -"${CLAUDE_SKILL_DIR}/scripts/audit-complexity.sh" --json --all src/ # the code-metrics/v2 document instead of markdown +"/scripts/audit-complexity.sh" # the change: merge-base diff plus uncommitted files +"/scripts/audit-complexity.sh" src/ lib/parse.py # explicit paths (a missing one is a usage error) +"/scripts/audit-complexity.sh" --all # every tracked or untracked-but-not-ignored file +"/scripts/audit-complexity.sh" --json --all src/ # the code-metrics/v2 document instead of markdown ``` Present the markdown report to the user as printed. It opens with the scope and a "Coverage of @@ -95,12 +79,12 @@ you, and why no threshold here is a verdict. ## Configuration Everything tunable resolves through the code-metrics layers (user-global, team -`docs/conventions/code-metrics.yaml`, local overlay; per-key override; keys in `${CLAUDE_PLUGIN_ROOT}/reference/config.md`): the three +`docs/conventions/code-metrics.yaml`, local overlay; per-key override; keys in `/reference/config.md`): the three references above, scope exclusions (`scope.exclude`, which by default drops `node_modules`, `vendor`, `dist`, and `build` directories at any depth and reports each pattern's count), sanctioned-replication registries (`scope.registries`), the base ref (`scope.base`), and the per-lane collector order (`lanes..collectors.`, validated against -`${CLAUDE_PLUGIN_ROOT}/scripts/collector-ladder.tsv`). The report names the layer that supplied +`/scripts/collector-ladder.tsv`). The report names the layer that supplied any value a personal layer changed. `/code-metrics:setup` writes the team file and probes the collectors. @@ -109,23 +93,16 @@ CPU count or `CODE_METRICS_JOBS`, and prints a progress line per collector on st scope passes a few hundred files (`CODE_METRICS_PROGRESS=1` forces it, `=0` silences it). Its wall clock is the slowest collector's own, which the plugin does not control. -## What this skill does not do +## What this action does not do - It does not install a collector, run tests, or edit files. A missing collector is reported with its install hint and the run continues. - It does not judge. No reference here is a bar, no finding or severity is emitted, and this version ships no `check` gate. - It does not compute CRAP: that needs coverage, and `/code-metrics:audit-coverage` computes it by - joining this skill's per-function numbers with a coverage artifact. -- It does not measure lines, duplication, coverage, or type debt; those are the sibling `audit-*` - skills in this plugin. - -## Next - -- The numbers feed a before-and-after comparison: `/verification:measure metrics`. -- A complex function's coverage and CRAP score are the real question: - `/code-metrics:audit-coverage`. -- A number is about to be quoted at someone: `/code-metrics:principles`. + joining this action's per-function numbers with a coverage artifact. +- It does not measure lines, duplication, coverage, or type debt; those are the sibling `audit` + actions and `audit-*` skills in this plugin. ## Gotchas @@ -136,14 +113,14 @@ wall clock is the slowest collector's own, which the plugin does not control. reports that it found none the row reads `unavailable` with ESLint's own words and the run is not a failure. `lizard` still covers TypeScript cyclomatic complexity. Which file names ESLint accepts is recorded in - [`${CLAUDE_PLUGIN_ROOT}/reference/collectors.md`](../../reference/collectors.md). + [`/reference/collectors.md`](../../../reference/collectors.md). - `multimetric` and `gocognit` have no version flag. The run table carries the version their package metadata or `go version -m` reports, and reads `version unavailable` when neither answers, so two reports can still be compared by tool. - Python and Bash have no maintained cognitive-complexity collector, so those rows read `unavailable` with that reason rather than reporting a substitute measure. The claim, its basis, as-of date and recheck trigger are recorded in - [`${CLAUDE_PLUGIN_ROOT}/reference/collectors.md`](../../reference/collectors.md). + [`/reference/collectors.md`](../../../reference/collectors.md). - Halstead outside Python is per file, so a file's difficulty is not a function's. Python is the only lane with per-function Halstead, and even there the rows carry no line range. - A collector that reports only a start line cannot bound a function's lines, so `audit-coverage` diff --git a/plugins/code-metrics/skills/audit-size/SKILL.md b/plugins/code-metrics/skills/audit/actions/size.md similarity index 66% rename from plugins/code-metrics/skills/audit-size/SKILL.md rename to plugins/code-metrics/skills/audit/actions/size.md index e730a5e6e3d..77bca1e5e25 100644 --- a/plugins/code-metrics/skills/audit-size/SKILL.md +++ b/plugins/code-metrics/skills/audit/actions/size.md @@ -1,26 +1,10 @@ ---- -description: "Measure lines per file for the changed files (the default), explicit paths, or the whole tree (`--all`), every text file in every lane, each beside a configurable reference with its provenance, longest first. Reports, never gates. Use when: 'how long are these files', 'lines per file', 'file size audit', 'which files are too big', 'LOC per file', 'is this file over 1000 lines', 'count lines in the change'. Complexity: /code-metrics:audit-complexity." -argument-hint: "[--json] [--all] [--base ] [...]" -user-invocable: true -disable-model-invocation: false -allowed-tools: ["Bash(${CLAUDE_SKILL_DIR}/scripts/audit-size.sh:*)", "Bash(git branch --show-current:*)"] -shell: bash -metadata: - workflow-stage: anytime - summary: Lines per file beside a cited reference, no verdict ---- - -## Pre-computed context - -Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"` - -## Purpose +# Size Lines per file is the one measure on the operator's list with a crisp definition and no -standard-backed file-level threshold. This skill reports the number, per file in the scope, beside -a reference whose provenance is printed with it, and stops there: no pass or fail, no severity, no -finding. Deciding what to do with a long file is the reader's call; the report gives them the -number and the citation. +standard-backed file-level threshold. This action reports the number, per file in the scope, +beside a reference whose provenance is printed with it, and stops there: no pass or fail, no +severity, no finding. Deciding what to do with a long file is the reader's call; the report gives +them the number and the citation. Two collectors, tried in order: @@ -40,10 +24,10 @@ other does; `lanes.other.enabled: false` opts it out. ## Run it ```bash -"${CLAUDE_SKILL_DIR}/scripts/audit-size.sh" # the change: diff from the merge-base plus uncommitted files -"${CLAUDE_SKILL_DIR}/scripts/audit-size.sh" src/ lib/util.py # explicit paths (a missing one is a usage error) -"${CLAUDE_SKILL_DIR}/scripts/audit-size.sh" --all # every tracked or untracked-but-not-ignored file -"${CLAUDE_SKILL_DIR}/scripts/audit-size.sh" --json --all src/ # the code-metrics/v2 document instead of markdown +"/scripts/audit-size.sh" # the change: diff from the merge-base plus uncommitted files +"/scripts/audit-size.sh" src/ lib/util.py # explicit paths (a missing one is a usage error) +"/scripts/audit-size.sh" --all # every tracked or untracked-but-not-ignored file +"/scripts/audit-size.sh" --json --all src/ # the code-metrics/v2 document instead of markdown ``` Present the markdown report to the user as printed. It opens with the scope and a "Coverage of @@ -72,7 +56,7 @@ side as INCONCLUSIVE); otherwise keep the JSON beside your notes and compare by ## Configuration Everything tunable resolves through the code-metrics layers (user-global, team -`docs/conventions/code-metrics.yaml`, local overlay; per-key override; keys in `${CLAUDE_PLUGIN_ROOT}/reference/config.md`): the reference +`docs/conventions/code-metrics.yaml`, local overlay; per-key override; keys in `/reference/config.md`): the reference (`size.file_lines`), the mode (`size.mode`: `file-lines`, or `iso-8.2.115`, which adds a `function_lines` measure comparing each function's non-empty lines against `size.function_lines_pct` of the file's, from a collector that reports function ranges such as @@ -80,19 +64,14 @@ Everything tunable resolves through the code-metrics layers (user-global, team per-lane collector order. The report names the layer that supplied any value a personal layer changed. `/code-metrics:setup` writes the team file and probes the collectors. -## What this skill does not do +## What this action does not do - It does not run tests, edit files, or install `scc`; when `scc` is absent the run table says so and the bundled counter answers. - It does not judge: no threshold here is a bar, and no `check` gate exists in this version. - It does not measure complexity, duplication, coverage, or type debt; those are the sibling - `audit-*` skills in this plugin, and `/code-metrics:principles` explains what each number can and - cannot tell you. - -## Next - -- The numbers feed a before-and-after comparison: `/verification:measure metrics`. -- A file is about to be called too long: `/code-metrics:principles`. + `audit` actions and `audit-*` skills in this plugin, and `/code-metrics:principles` explains + what each number can and cannot tell you. ## Gotchas diff --git a/plugins/code-metrics/skills/audit-type-debt/SKILL.md b/plugins/code-metrics/skills/audit/actions/type-debt.md similarity index 81% rename from plugins/code-metrics/skills/audit-type-debt/SKILL.md rename to plugins/code-metrics/skills/audit/actions/type-debt.md index 28f0754657f..e5b306eae6c 100644 --- a/plugins/code-metrics/skills/audit-type-debt/SKILL.md +++ b/plugins/code-metrics/skills/audit/actions/type-debt.md @@ -1,23 +1,7 @@ ---- -description: "Measure how much code is typed, per file and per lane, for a change, a path, or the tree: `type-coverage` for TypeScript, mypy's any-expressions report for Python. No standard anchors it, so the number is a trend, not a bar. Use when: 'how much of this is typed', 'type coverage', 'how many anys are in this', 'any usage in the change', 'type debt', 'measure our typing', 'mypy any expressions report'. Complexity: /code-metrics:audit-complexity." -argument-hint: "[--json] [--all] [--base ] [...]" -user-invocable: true -disable-model-invocation: false -allowed-tools: ["Bash(${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh:*)", "Bash(git branch --show-current:*)"] -shell: bash -metadata: - workflow-stage: anytime - summary: Typed-code percentage per file and per lane, with no standard behind it ---- - -## Pre-computed context - -Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"` - -## Purpose +# Type debt "Get `any` and `unknown` to zero" is a goal without a yardstick: no standard and no CWE anchors a -typed-code percentage. This skill reports what the two tools that produce a real percentage +typed-code percentage. This action reports what the two tools that produce a real percentage measure, per file and per lane, and says plainly where the number comes from and what it does not mean. There is no pass or fail here, and no bar to argue with. @@ -32,10 +16,10 @@ mean. There is no pass or fail here, and no bar to argue with. ## Run it ```bash -"${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh" # the change: diff from the merge-base plus uncommitted files -"${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh" src/ lib/api.py # explicit paths (a missing one is a usage error) -"${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh" --all # every tracked or untracked-but-not-ignored file -"${CLAUDE_SKILL_DIR}/scripts/audit-type-debt.sh" --json --all src/ # the code-metrics/v2 document instead of markdown +"/scripts/audit-type-debt.sh" # the change: diff from the merge-base plus uncommitted files +"/scripts/audit-type-debt.sh" src/ lib/api.py # explicit paths (a missing one is a usage error) +"/scripts/audit-type-debt.sh" --all # every tracked or untracked-but-not-ignored file +"/scripts/audit-type-debt.sh" --json --all src/ # the code-metrics/v2 document instead of markdown ``` Present the markdown report as printed. It opens with the scope and a "Coverage of this run" table @@ -83,27 +67,23 @@ your notes and compare by hand. Everything tunable resolves through the code-metrics layers (user-global, team `docs/conventions/code-metrics.yaml`, local overlay; -per-key override; keys in `${CLAUDE_PLUGIN_ROOT}/reference/config.md`): the reference +per-key override; keys in `/reference/config.md`): the reference (`type_debt.reference`, `null` by default), scope exclusions (`scope.exclude`), a per-lane opt-out (`lanes..enabled: false`, which drops that lane even under `--all`), and the per-lane collector order (`lanes..collectors.type_coverage`). The report names the layer that supplied any value a personal layer changed. `/code-metrics:setup` writes the team file and probes the collectors. -## What this skill does not do +## What this action does not do - It does not run tests, edit files, add annotations, or install `type-coverage` or `mypy`; an absent tool is a row in the run table with its install hint. - It does not judge: the reference is not a bar, and no `check` gate exists in this version. - It does not count `any` occurrences for C#, and it does not report a count where the other lanes report a ratio. -- It does not measure complexity, size, duplication, or coverage; those are the sibling `audit-*` - skills in this plugin, and `/code-metrics:principles` explains what each number means. - -## Next - -- The numbers feed a before-and-after comparison: `/verification:measure metrics`. -- A percentage is about to be read as a bar: `/code-metrics:principles`. +- It does not measure complexity, size, duplication, or coverage; those are the sibling `audit` + actions and `audit-*` skills in this plugin, and `/code-metrics:principles` explains what each + number means. ## Gotchas diff --git a/plugins/code-metrics/skills/audit/evals/evals.json b/plugins/code-metrics/skills/audit/evals/evals.json new file mode 100644 index 00000000000..3f9a477e5b5 --- /dev/null +++ b/plugins/code-metrics/skills/audit/evals/evals.json @@ -0,0 +1,121 @@ +{ + "skill_name": "audit", + "evals": [ + { + "id": 1, + "name": "size-reports-the-change-with-provenance-and-no-verdict", + "prompt": "/code-metrics:audit size", + "expected_output": "Runs the bundled audit-size.sh against the change (merge-base diff plus uncommitted files), presents the markdown report with its Coverage of this run table and the 1000-line reference labeled as the plugin's own number rather than ISO-backed, and renders no pass/fail verdict.", + "files": [], + "expectations": [ + "Invokes the skill's scripts/audit-size.sh rather than counting lines by hand", + "Presents the Coverage of this run table naming the collector used (scc or the bundled counter) per lane", + "States the reference's provenance: 1000 is the plugin's own number, not ISO-backed", + "Does not declare any file a failure, defect, or violation" + ] + }, + { + "id": 2, + "name": "size-scc-absent-is-visible-not-silent", + "prompt": "/code-metrics:audit size src/ (scc is not installed on this machine)", + "expected_output": "The report's run table shows the bundled counter as the collector with the comment-agnostic label, explains that scc did not resolve, and does not attempt to install it.", + "files": [], + "expectations": [ + "The run table names line-counter as the collector and the rows carry the comment-agnostic label", + "Says scc did not resolve and offers its install hint without installing anything", + "Still reports total and non-blank lines per file" + ] + }, + { + "id": 3, + "name": "size-json-feeds-a-comparison-through-the-gated-pointer", + "prompt": "/code-metrics:audit size --json --all src/ so I can compare it after the refactor", + "expected_output": "Produces the code-metrics/v2 JSON document, keeps it for the comparison, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explains the manual comparison and that an empty status is inconclusive.", + "files": [], + "expectations": [ + "Runs audit-size.sh with --json and keeps the document for the later comparison", + "Mentions /verification:measure only behind an if-installed gate with a stated fallback", + "States that a report with status empty on either side makes the comparison inconclusive" + ] + }, + { + "id": 4, + "name": "complexity-reports-the-change-with-provenance-and-no-verdict", + "prompt": "/code-metrics:audit complexity", + "expected_output": "Runs the bundled audit-complexity.sh against the change (merge-base diff plus uncommitted files), presents the markdown report with its Coverage of this run table, the cyclomatic reference of 20 cited to ISO/IEC 5055:2021 section 8.2.117, and no reference for cognitive complexity or Halstead difficulty, and renders no pass/fail verdict.", + "files": [], + "expectations": [ + "Invokes the skill's scripts/audit-complexity.sh rather than estimating complexity by reading the code", + "Presents the Coverage of this run table naming the collector and version used per lane and measure", + "Cites ISO/IEC 5055:2021 section 8.2.117 for the cyclomatic reference of 20", + "States that cognitive complexity and Halstead difficulty carry no reference because no standard sets one", + "Does not declare any function a failure, defect, or violation" + ] + }, + { + "id": 5, + "name": "complexity-a-missing-collector-is-visible-not-silent", + "prompt": "/code-metrics:audit complexity src/ (this repository has no eslint-plugin-sonarjs and no lizard)", + "expected_output": "The report's run table shows the TypeScript cognitive row as unavailable with the reason, names the collector that did answer for cyclomatic complexity, offers the install hints without installing anything, and still reports every measure that a resolvable collector produced.", + "files": [], + "expectations": [ + "The run table carries an unavailable row with a reason for the measure whose collectors did not resolve", + "Offers the install hint without installing, downloading, or npx-fetching any collector", + "Still reports the measures the resolvable collectors produced rather than stopping", + "Reports an unmeasured value as null and never as zero" + ] + }, + { + "id": 6, + "name": "complexity-json-feeds-a-comparison-through-the-gated-pointer", + "prompt": "/code-metrics:audit complexity --json --all src/ so I can compare it after the refactor", + "expected_output": "Produces the code-metrics/v2 JSON document, keeps it for the comparison, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explains the manual comparison and that an empty status is inconclusive.", + "files": [], + "expectations": [ + "Runs audit-complexity.sh with --json and keeps the document for the later comparison", + "Mentions /verification:measure only behind an if-installed gate with a stated fallback", + "States that a report with status empty on either side makes the comparison inconclusive" + ] + }, + { + "id": 7, + "name": "type-debt-reports-both-percentages-without-anchoring-them", + "prompt": "/code-metrics:audit type-debt", + "expected_output": "Runs the bundled audit-type-debt.sh against the change, presents the markdown report with its Coverage of this run table, and states that no standard or CWE anchors the measure so the reference is null, without declaring any lane a pass or a failure.", + "files": [], + "expectations": [ + "Invokes the skill's scripts/audit-type-debt.sh rather than grepping for any by hand", + "Presents the per-lane percentages for TypeScript and Python with the collector named for each", + "States that no standard or CWE anchors the measure and that the reference is null", + "Does not average the TypeScript and Python percentages or compare them with each other", + "Does not declare any lane a failure, defect, or violation" + ] + }, + { + "id": 8, + "name": "type-debt-csharp-is-not-applicable-rather-than-a-count", + "prompt": "/code-metrics:audit type-debt src/ (this repository is mostly C# with one TypeScript front end)", + "expected_output": "The run table shows the dotnet lane as not-applicable with the sentence that no tool produces a comparable percentage for C# and that a dynamic or object occurrence count is not comparable to a ratio, while the TypeScript lane still reports its percentage.", + "files": [], + "expectations": [ + "The dotnet row is reported as not-applicable with its stated reason", + "Explains that an occurrence count is not comparable to a ratio rather than offering one", + "Still reports the TypeScript percentage from the same run" + ] + }, + { + "id": 9, + "name": "type-debt-absent-type-coverage-is-visible-not-silent", + "prompt": "/code-metrics:audit type-debt --json --all so I can compare it after the typing sweep (type-coverage is not installed here)", + "expected_output": "Produces the code-metrics/v2 JSON document, reports the typescript lane as unavailable with its install hint and the requirement that typescript also resolves, installs nothing, and points at /verification:measure metrics only if the verification plugin is installed, otherwise explaining the manual comparison.", + "files": [], + "expectations": [ + "Runs audit-type-debt.sh with --json and keeps the document for the later comparison", + "Says the typescript lane is unavailable and offers the install hint without installing anything", + "Notes that type-coverage needs a resolvable typescript in the project", + "Mentions /verification:measure only behind an if-installed gate with a stated fallback", + "States that a report with status empty on either side makes the comparison inconclusive" + ] + } + ] +} diff --git a/plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.sh b/plugins/code-metrics/skills/audit/scripts/audit-complexity.sh similarity index 96% rename from plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.sh rename to plugins/code-metrics/skills/audit/scripts/audit-complexity.sh index eb04cec9d60..6d497bbcd73 100755 --- a/plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.sh +++ b/plugins/code-metrics/skills/audit/scripts/audit-complexity.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# /code-metrics:audit-complexity entry point: cyclomatic and cognitive +# /code-metrics:audit complexity entry point: cyclomatic and cognitive # complexity and Halstead difficulty for the files in scope. # # audit-complexity.sh [--json] [--all] [--base ] [--config ] [...] diff --git a/plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.test.sh b/plugins/code-metrics/skills/audit/scripts/audit-complexity.test.sh similarity index 100% rename from plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.test.sh rename to plugins/code-metrics/skills/audit/scripts/audit-complexity.test.sh diff --git a/plugins/code-metrics/skills/audit-size/scripts/audit-size.sh b/plugins/code-metrics/skills/audit/scripts/audit-size.sh similarity index 97% rename from plugins/code-metrics/skills/audit-size/scripts/audit-size.sh rename to plugins/code-metrics/skills/audit/scripts/audit-size.sh index 7bebaf09aee..f95c8c1215f 100755 --- a/plugins/code-metrics/skills/audit-size/scripts/audit-size.sh +++ b/plugins/code-metrics/skills/audit/scripts/audit-size.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# /code-metrics:audit-size entry point: lines per file, comment-aware when +# /code-metrics:audit size entry point: lines per file, comment-aware when # `scc` resolves, comment-agnostic from the bundled counter otherwise. # # audit-size.sh [--json] [--all] [--base ] [--config ] [...] diff --git a/plugins/code-metrics/skills/audit-size/scripts/audit-size.test.sh b/plugins/code-metrics/skills/audit/scripts/audit-size.test.sh similarity index 88% rename from plugins/code-metrics/skills/audit-size/scripts/audit-size.test.sh rename to plugins/code-metrics/skills/audit/scripts/audit-size.test.sh index ec6231715bc..08d19b4f597 100755 --- a/plugins/code-metrics/skills/audit-size/scripts/audit-size.test.sh +++ b/plugins/code-metrics/skills/audit/scripts/audit-size.test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Regression tests for the audit-size entry point (audit-size.sh): option parsing, # JSON versus markdown output, and exit-code passthrough from dispatch.sh. -# test-scope: plugins/code-metrics/scripts/collectors/*.py plugins/code-metrics/scripts/fixtures/* plugins/code-metrics/skills/audit-size/SKILL.md +# test-scope: plugins/code-metrics/scripts/collectors/*.py plugins/code-metrics/scripts/fixtures/* plugins/code-metrics/skills/audit/SKILL.md plugins/code-metrics/skills/audit/actions/size.md # test-scope: plugins/code-metrics/scripts/yaml_subset.py set -uo pipefail unset GIT_DIR GIT_WORK_TREE GIT_CONFIG @@ -52,14 +52,14 @@ assert_eq "--help prints usage" 0 "$?" # The 1000-line provenance is one sentence, owned by the bundled defaults and # repeated verbatim where a reader meets the number without the report: the -# skill body and the principles threshold table. A rewording in one place is a -# second story about where the number came from. +# size action body and the principles threshold table. A rewording in one place +# is a second story about where the number came from. provenance="$("$PY" -c ' import json, sys doc = json.load(open(sys.argv[1])) print(next(t["provenance"] for t in doc["thresholds"] if t["measure"] == "file_lines")) ' "$PLUGIN_ROOT/scripts/config-defaults.json")" -for surface in "$SCRIPT_DIR/../SKILL.md" "$SCRIPT_DIR/../../principles/reference/thresholds.md"; do +for surface in "$SCRIPT_DIR/../actions/size.md" "$SCRIPT_DIR/../../principles/reference/thresholds.md"; do # Markdown wraps the sentence across lines; compare with whitespace folded. folded="$(tr -s '[:space:]' ' ' <"$surface")" case "$folded" in @@ -68,8 +68,8 @@ for surface in "$SCRIPT_DIR/../SKILL.md" "$SCRIPT_DIR/../../principles/reference esac done -# The description names `--all` as a scope in its own right and no longer -# disowns the whole-tree run, and stays inside the field maximum. +# The router's description names `--all` as a scope in its own right and no +# longer disowns the whole-tree run, and stays inside the field maximum. description="$(sed -n '2p' "$SCRIPT_DIR/../SKILL.md")" case "$description" in *"wrong tool"*) fail "the description no longer disowns --all" "no 'wrong tool' clause" "$description" ;; diff --git a/plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.sh b/plugins/code-metrics/skills/audit/scripts/audit-type-debt.sh similarity index 97% rename from plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.sh rename to plugins/code-metrics/skills/audit/scripts/audit-type-debt.sh index fc7d44879ab..69dc8300319 100755 --- a/plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.sh +++ b/plugins/code-metrics/skills/audit/scripts/audit-type-debt.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# /code-metrics:audit-type-debt entry point: how much of the code is typed, +# /code-metrics:audit type-debt entry point: how much of the code is typed, # per file and per lane, as a percentage from `type-coverage` (TypeScript) and # from mypy's `--any-exprs-report` (Python). # diff --git a/plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.test.sh b/plugins/code-metrics/skills/audit/scripts/audit-type-debt.test.sh similarity index 100% rename from plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.test.sh rename to plugins/code-metrics/skills/audit/scripts/audit-type-debt.test.sh diff --git a/plugins/code-metrics/skills/principles/SKILL.md b/plugins/code-metrics/skills/principles/SKILL.md index 76ea7349d66..09a892bb4c3 100644 --- a/plugins/code-metrics/skills/principles/SKILL.md +++ b/plugins/code-metrics/skills/principles/SKILL.md @@ -154,8 +154,8 @@ the Bash tool starts receiving the plugin variables. ## Next -- The number in question still has to be measured: `/code-metrics:audit-complexity`, or the - `audit-*` skill for that measure. +- The number in question still has to be measured: `/code-metrics:audit complexity`, or the + `audit` action or `audit-*` skill for that measure. - The bundled reference values are not the ones your codebase can defend: `/code-metrics:setup`. ## Gotchas diff --git a/plugins/code-metrics/skills/setup/SKILL.md b/plugins/code-metrics/skills/setup/SKILL.md index ffce6c3b007..da3e1f4634f 100644 --- a/plugins/code-metrics/skills/setup/SKILL.md +++ b/plugins/code-metrics/skills/setup/SKILL.md @@ -113,7 +113,7 @@ bundled default. ## Next -`/code-metrics:audit-complexity`. The sibling `audit-*` skills cover the other measures. +`/code-metrics:audit complexity`. The other `audit` actions and `audit-*` skills cover the rest. ## Gotchas diff --git a/plugins/discipline/probes/script-the-deterministic-work.json b/plugins/discipline/probes/script-the-deterministic-work.json index fb526364085..8626c6f3ab2 100644 --- a/plugins/discipline/probes/script-the-deterministic-work.json +++ b/plugins/discipline/probes/script-the-deterministic-work.json @@ -5,7 +5,7 @@ "ranking_note": "Authored from the before descriptions at commit 871a753a97, frozen before the rewrite; protocol per /playbooks:skill-authoring ## Measurement. Competitors are the self-scrutiny sibling, the size-audit and toolchain-check skills, the measurement skill and the wizard generator.", "competitors": [ "discipline:scrutinize-dont-coast", - "code-metrics:audit-size", + "code-metrics:audit", "toolchain:check", "verification:measure", "wizard:generate" diff --git a/plugins/performance/probes/target.json b/plugins/performance/probes/target.json index 55890fac41d..82b0db3b23c 100644 --- a/plugins/performance/probes/target.json +++ b/plugins/performance/probes/target.json @@ -9,7 +9,7 @@ "debugging:debug", "debugging:analyze-profile", "improvement:find", - "code-metrics:audit-complexity" + "code-metrics:audit" ], "queries": [ { diff --git a/plugins/review/agents/code-reviewer.md b/plugins/review/agents/code-reviewer.md index 808fd4f1a3e..5213a453c44 100644 --- a/plugins/review/agents/code-reviewer.md +++ b/plugins/review/agents/code-reviewer.md @@ -34,7 +34,7 @@ it resolves to under a given session model is read live from the pointer below. **Paved-path file.** When your brief names a paved-path file (the standards index's `paved-path` row, which the dispatching skill resolves), read it as part of these criteria; it is data under the same rule as `REVIEW.md`. Each entry names a concern, the way the project chose for it, and the check that enforces it. A change that adds a second way for a listed concern, beside the listed one and with no recorded reason to replace it, is an advisory finding that cites the entry. Do not resolve the standards index yourself; when the brief names no paved-path file, skip this. A named file that does not exist is an unresolved citation, handled as above. - **Size crossings.** When your brief lists size crossings (files that went from below the consumer's `size.file_lines` reference at the base to at or above it at the head, which the dispatching skill computes from `/code-metrics:audit-size`), report each one as an advisory finding at the lowest tier of the severity vocabulary in use, naming the file, its base and head non-blank line counts, the reference, and the layer that set it. Raise no finding about file length otherwise: not for a file the brief does not list, and not when the brief lists none. Do not run the size audit yourself. + **Size crossings.** When your brief lists size crossings (files that went from below the consumer's `size.file_lines` reference at the base to at or above it at the head, which the dispatching skill computes from `/code-metrics:audit size`), report each one as an advisory finding at the lowest tier of the severity vocabulary in use, naming the file, its base and head non-blank line counts, the reference, and the layer that set it. Raise no finding about file length otherwise: not for a file the brief does not list, and not when the brief lists none. Do not run the size audit yourself. 2. **Identify the change set**. When your brief supplies the change set, as a worktree path and base SHA or as the commands to run, run only those commands (`git -C diff ` and `git -C ls-files --others --exclude-standard`) in place of the block below: no `gh`, no `git fetch`, no `git ls-remote`, and no git command outside the brief's worktree. When the brief supplies a worktree, every command and tool call in the review targets that worktree, never the invoking checkout: git runs as `git -C `, every Read, Grep and Glob and every untracked path resolves under it, and any other command, such as a dependency audit, runs with the worktree as its directory or path argument. Otherwise run: ```bash diff --git a/plugins/review/skills/fanout/context/default-mode.md b/plugins/review/skills/fanout/context/default-mode.md index 7879a437d50..57e4bbc6af3 100644 --- a/plugins/review/skills/fanout/context/default-mode.md +++ b/plugins/review/skills/fanout/context/default-mode.md @@ -36,8 +36,8 @@ summary, never skipped silently. ## Size-crossing brief -Before dispatch, when `/code-metrics:audit-size` is among the available skills, run it over the -changed files with `--base `, the review diff base, and read the `file_lines` row (config +Before dispatch, when `/code-metrics:audit` is among the available skills, run +`/code-metrics:audit size` over the changed files with `--base `, the review diff base, and read the `file_lines` row (config key `size.file_lines`) of its References table. When that row's layer is `bundled default`, the `code-reviewer` brief lists no size crossing. When the layer is any other (`user-global`, `team`, `local`), the consumer set the value: for each measured file, count its diff --git a/plugins/review/skills/quality-gate/context/code.md b/plugins/review/skills/quality-gate/context/code.md index 627756baf3a..ab01f336535 100644 --- a/plugins/review/skills/quality-gate/context/code.md +++ b/plugins/review/skills/quality-gate/context/code.md @@ -17,8 +17,8 @@ Choose deliberately: ## Size crossings (when code-metrics is enabled) -Before either path below, when `/code-metrics:audit-size` is among the available skills and no -`--worktree` is passed ([phase-boundary.md](phase-boundary.md)), run it over the changed files with `--base `, the review diff base, so both counts share one base. +Before either path below, when `/code-metrics:audit` is among the available skills and no +`--worktree` is passed ([phase-boundary.md](phase-boundary.md)), run `/code-metrics:audit size` over the changed files with `--base `, the review diff base, so both counts share one base. Read the `file_lines` row of its References table (config key `size.file_lines`): - **Layer `bundled default`:** pass nothing. The plugin's own reference is not the consumer's diff --git a/plugins/review/skills/quality-gate/evals/evals.json b/plugins/review/skills/quality-gate/evals/evals.json index 1958144972c..a1f89e30bb9 100644 --- a/plugins/review/skills/quality-gate/evals/evals.json +++ b/plugins/review/skills/quality-gate/evals/evals.json @@ -236,11 +236,11 @@ "id": 19, "name": "code-mode-flags-a-file-crossing-the-consumer-size-reference", "prompt": "/review:quality-gate code\n\nThe code-metrics plugin is enabled and our tracked docs/conventions/code-metrics.yaml sets size.file_lines to 500. My branch grows src/billing/invoice_builder.py from 470 non-blank lines at the merge-base to 540, and grows src/billing/tax.py from 120 to 160. pr-review-toolkit is not installed.", - "expected_output": "Runs /code-metrics:audit-size over the changed files, reads that the size.file_lines reference of 500 came from the team layer, counts each changed file's non-blank lines at the base with git show :, and finds that only invoice_builder.py went from below 500 to at or above it. The code-reviewer brief lists that one crossing, and the report flags invoice_builder.py with the reference 500 and the team layer. tax.py gets no size finding.", + "expected_output": "Runs /code-metrics:audit size over the changed files, reads that the size.file_lines reference of 500 came from the team layer, counts each changed file's non-blank lines at the base with git show :, and finds that only invoice_builder.py went from below 500 to at or above it. The code-reviewer brief lists that one crossing, and the report flags invoice_builder.py with the reference 500 and the team layer. tax.py gets no size finding.", "files": [], "narration": true, "expectations": [ - "Runs /code-metrics:audit-size over the changed files before dispatching the reviewer", + "Runs /code-metrics:audit size over the changed files before dispatching the reviewer", "Reads the base count of non-blank lines with git show at the merge-base", "The code-reviewer brief lists src/billing/invoice_builder.py as a size crossing and does not list src/billing/tax.py", "The report flags src/billing/invoice_builder.py with the reference 500 and names the team layer as its source", @@ -251,7 +251,7 @@ "id": 20, "name": "code-mode-raises-no-size-flag-on-the-bundled-default", "prompt": "/review:quality-gate code\n\nThe code-metrics plugin is enabled but no code-metrics.yaml layer exists anywhere, so size.file_lines is the bundled default. My branch grows scripts/sync_ledger.py from 980 non-blank lines at the merge-base to 1030. pr-review-toolkit is not installed.", - "expected_output": "Runs /code-metrics:audit-size, sees that the size.file_lines reference came from the bundled default, and passes no size crossing into the code-reviewer brief. The review raises no finding about the length of scripts/sync_ledger.py, even though it crossed 1000.", + "expected_output": "Runs /code-metrics:audit size, sees that the size.file_lines reference came from the bundled default, and passes no size crossing into the code-reviewer brief. The review raises no finding about the length of scripts/sync_ledger.py, even though it crossed 1000.", "files": [], "narration": true, "expectations": [ diff --git a/plugins/skill-quality/scripts/check-skill.test.sh b/plugins/skill-quality/scripts/check-skill.test.sh index fdab783439d..6f4586dbabe 100755 --- a/plugins/skill-quality/scripts/check-skill.test.sh +++ b/plugins/skill-quality/scripts/check-skill.test.sh @@ -4335,7 +4335,7 @@ Conforming successor section in the single-invocation shape. ## Next -`/code-metrics:audit-complexity`. The sibling skills cover the other measures. +`/code-metrics:audit complexity`. The sibling skills cover the other measures. ## Gotchas @@ -4364,7 +4364,7 @@ None known. ## Next -`/code-metrics:audit-complexity`. +`/code-metrics:audit complexity`. ' out="$(run next-late 2>&1)" rc=$? @@ -4411,7 +4411,7 @@ Skill-tool instruction, an installed-ness gate, and a fallback clause. ## Next -Ask the Skill tool to invoke /code-metrics:audit-complexity when it is installed. +Ask the Skill tool to invoke /code-metrics:audit complexity when it is installed. Otherwise measure by hand. ## Gotchas diff --git a/plugins/verification/skills/measure/context/metrics.md b/plugins/verification/skills/measure/context/metrics.md index 9ed2002972b..5e75ffa597f 100644 --- a/plugins/verification/skills/measure/context/metrics.md +++ b/plugins/verification/skills/measure/context/metrics.md @@ -10,8 +10,8 @@ Quality is partly subjective, but some aspects ARE measurable: | Quality aspect | Measurable proxy | How to check | |---------------|-----------------|--------------| -| Complexity | Cyclomatic complexity, nesting depth | `/code-metrics:audit-complexity --json` when the `code-metrics` plugin is enabled (treat the pair as INCONCLUSIVE when `status` is `empty` on either side, or when the two documents' `schema` values or `root.path` differ; a baseline taken before `code-metrics/v2` is a v1 document and must be re-taken); otherwise count conditionals, measure max nesting | -| Size | Lines of code, file count, method length | `/code-metrics:audit-size --json` when the `code-metrics` plugin is enabled (same INCONCLUSIVE rule); otherwise a line counter (`wc -l` on POSIX/Git Bash, `Measure-Object -Line` in PowerShell), `git diff --stat` | +| Complexity | Cyclomatic complexity, nesting depth | `/code-metrics:audit complexity --json` when the `code-metrics` plugin is enabled (treat the pair as INCONCLUSIVE when `status` is `empty` on either side, or when the two documents' `schema` values or `root.path` differ; a baseline taken before `code-metrics/v2` is a v1 document and must be re-taken); otherwise count conditionals, measure max nesting | +| Size | Lines of code, file count, method length | `/code-metrics:audit size --json` when the `code-metrics` plugin is enabled (same INCONCLUSIVE rule); otherwise a line counter (`wc -l` on POSIX/Git Bash, `Measure-Object -Line` in PowerShell), `git diff --stat` | | Coupling | Dependency count, import count | Count import/dependency declarations (`import`/`require`/`using`, package or project references) | | Cohesion | Methods per class, related functionality | Inspect class responsibility | | Duplication | Repeated code blocks | `/code-metrics:audit-duplication --json` when the `code-metrics` plugin is enabled (same INCONCLUSIVE rule); otherwise grep for similar patterns | diff --git a/scripts/affected-tests-live.sh b/scripts/affected-tests-live.sh index fc80b4d5f38..c966cfaa090 100755 --- a/scripts/affected-tests-live.sh +++ b/scripts/affected-tests-live.sh @@ -253,7 +253,7 @@ read_pairs=( "plugins/ruff-format/hooks/ruff-format.test.sh|plugins/ruff-format/lib/git-hooks/install.mjs" "plugins/ruff-format/hooks/ruff-format.test.sh|plugins/ruff-format/lib/prerequisites.mjs" "plugins/biome-format/hooks/biome-format-end-of-turn.test.sh|plugins/biome-format/hooks/exec-bash.mjs" - "plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.test.sh|plugins/code-metrics/scripts/yaml_subset.py" + "plugins/code-metrics/skills/audit/scripts/audit-complexity.test.sh|plugins/code-metrics/scripts/yaml_subset.py" "plugins/instruction-placement/git-hooks/index-check.test.sh|plugins/instruction-placement/.claude-plugin/plugin.json" ) for fixture in events-v1 invalid-device-scope-on-prototype invalid-reaction-agree \ diff --git a/scripts/check-code-metrics-skill-prose.py b/scripts/check-code-metrics-skill-prose.py index 922a24e58c2..d2dd612d655 100755 --- a/scripts/check-code-metrics-skill-prose.py +++ b/scripts/check-code-metrics-skill-prose.py @@ -90,7 +90,7 @@ def expected_phrases(defaults: dict) -> list[tuple[str, str]]: f"| `coverage.crap.reference` | `{_render(coverage['crap']['reference'])}` |", ), ( - "plugins/code-metrics/skills/audit-type-debt/SKILL.md", + "plugins/code-metrics/skills/audit/actions/type-debt.md", f"`type_debt.reference`, `{_render(defaults['type_debt']['reference'])}`", ), ( diff --git a/scripts/skill-leaf-name-registry.txt b/scripts/skill-leaf-name-registry.txt index 48bd4be9a96..5975eb879b1 100644 --- a/scripts/skill-leaf-name-registry.txt +++ b/scripts/skill-leaf-name-registry.txt @@ -117,7 +117,14 @@ # applying one finding at a time and only after a yes on that finding. The # nearest alternatives are worse: `audit-ui` repeats the namespace, and a # topic qualifier per concern would split one skill into a skill per lane. -audit ai-slop,attribution,harness-config,harness-memory,codebase-health,context-budget,disk-hygiene,github,instruction-placement,machine-health,mcp-tools,mutation-testing,overengineering,plugin-quality,repo-fleet-hygiene,testing,user-interface +# code-metrics joins on the verb's own grounds. Its object, the measures of a +# change, a path or the tree, is supplied by the namespace, and the measure is +# the action argument (size, complexity, type-debt), one spoke per measure +# under one router, so per-measure leaves (`audit-size`, `audit-complexity`) +# would split one report contract into a skill per lane. The contract is exactly +# the verb's: every action reports numbers beside cited references, edits +# nothing, installs nothing, and has no gate or override. +audit ai-slop,attribution,code-metrics,harness-config,harness-memory,codebase-health,context-budget,disk-hygiene,github,instruction-placement,machine-health,mcp-tools,mutation-testing,overengineering,plugin-quality,repo-fleet-hygiene,testing,user-interface # Fixed verb meaning: deterministic pass/fail gate. skill-quality checks a # skill, toolchain checks a build. instruction-placement joins on its own diff --git a/scripts/suite-seconds.txt b/scripts/suite-seconds.txt index 95bafbd84c3..b88beedc4e4 100644 --- a/scripts/suite-seconds.txt +++ b/scripts/suite-seconds.txt @@ -145,15 +145,15 @@ plugins/code-metrics/scripts/test_resolve_config.py 2 plugins/code-metrics/scripts/test_scope_filter.py 1 plugins/code-metrics/scripts/test_yaml_subset.py 1 plugins/code-metrics/scripts/tool-free-path.test.sh 11 -plugins/code-metrics/skills/audit-complexity/scripts/audit-complexity.test.sh 22 plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.test.sh 46 plugins/code-metrics/skills/audit-coverage/scripts/test_crap.py 1 plugins/code-metrics/skills/audit-coverage/scripts/test_join.py 4 plugins/code-metrics/skills/audit-duplication/scripts/audit-duplication.test.sh 47 plugins/code-metrics/skills/audit-duplication/scripts/test_cluster_clones.py 1 plugins/code-metrics/skills/audit-duplication/scripts/test_registry_filter.py 2 -plugins/code-metrics/skills/audit-size/scripts/audit-size.test.sh 13 -plugins/code-metrics/skills/audit-type-debt/scripts/audit-type-debt.test.sh 15 +plugins/code-metrics/skills/audit/scripts/audit-complexity.test.sh 22 +plugins/code-metrics/skills/audit/scripts/audit-size.test.sh 13 +plugins/code-metrics/skills/audit/scripts/audit-type-debt.test.sh 15 plugins/code-metrics/skills/setup/scripts/setup-check.test.sh 15 plugins/code-metrics/skills/setup/scripts/test_setup_apply.py 2 plugins/code-tidying/scripts/allowed-tools-pairing.test.sh 1