Skip to content

refactor(code-metrics)!: fold audit-size, audit-complexity and audit-type-debt into the audit router - #12641

Open
melodic-automation-lanes[bot] wants to merge 1 commit into
mainfrom
work-resolve-issue/issue-12619-41570586663-1
Open

melodic-automation-lanes[bot] wants to merge 1 commit into
mainfrom
work-resolve-issue/issue-12619-41570586663-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Refs: #12619

Summary

Opened by the work-resolve-issue lane. The run's own summary:

Wave 1 of the #12491 plan: creates the code-metrics:audit router at plugins/code-metrics/skills/audit/ (SKILL.md, actions/size.md, actions/complexity.md, actions/type-debt.md, scripts/, evals/). The three leaf skills' bodies move into the actions, their entry scripts and tests move unchanged in name to skills/audit/scripts/, and their eval cases merge into one evals.json. The three leaf directories are removed with no aliases, and every reference to the three skills is repointed to /code-metrics:audit <action>. The report skill field values, the dispatch.sh id argument and the detector rule ids keep their old values, per the plan's "Contracts that keep their values". Design choices and their basis: action files use <skill-dir>/<plugin-root> placeholders that a router "Spoke paths" section resolves, because the plugins reference says ${...} is substituted only in skill content, not in supporting files (same pattern as code-metrics:principles). Scripts keep their file names so their ../../.. plugin-root resolution and the report ids are unchanged. code-metrics joins the registered audit leaf-name collision in scripts/skill-leaf-name-registry.txt with a rationale, since the router is the target #12491 decided.

Remaining work

  • Post the eval evidence: before.json captured on the pre-move tree with convert-evals-json.py, then /evals:plugin-eval --baseline before.json --margin 5 on the moved actions, non-inferior
  • Post the merge probe per D82/Q186 after merge

Not verified

  • Eval non-inferiority: convert-evals-json.py on the three pre-move evals.json, before.json captured on the pre-move tree, and /evals:plugin-eval --baseline before.json --margin 5 on the moved actions were not run. This lane cannot run an interpreter or the plugin eval CLI. main is still the pre-move
  • The code-metrics test suites (audit-size/-complexity/-type-debt/-coverage .test.sh, check-skill.test.sh, test_check_code_metrics_skill_prose.py) were not executed here; left to the PR's CI.
  • git diff --no-renames origin/main byte size not measured: no origin/main and no byte count available in this lane. The plan measured 189,588 bytes for this move plus about 20 KB for the router; this diff adds about 5 KB of router and small repoints, so it is expected under 262,144. Confirm on the
  • scripts/validate-plugins.sh full run: check-affected ran it but skipped three sub-checks that execute tree code (identity-prerequisites drift, native-overlap registry, claude plugin test). The merge probe per D82/Q186 is post-merge.
  • .claude/skills/control-claude-code-plugins/features/code-metrics/README.md still lists audit-complexity, audit-size and audit-type-debt as Parts. The write was denied in this lane (no approval surface). Its Parts list needs audit (actions size, complexity, type-debt) in place of the three rows.
  • plugins/code-metrics/README.md 'Listing budget' still says six listing-eligible descriptions, measured 2026-09-05. Now five. The figure needs a re-measure with check-listing-budget.sh, which this lane cannot run.
  • Untracked runner files at the repository root (.bash_profile, .bashrc, .gitconfig, .idea, .mcp.json, .profile, .ripgreprc, .vscode, .zprofile, .zshrc) are not part of this change; exclude them from the patch. Empty leaf directories may remain on disk in this checkout; git does not track them.
  • tidy skipped: the change touches 45 files across several areas and edits the shared scripts/ path, over the tidy cutoffs (10 files, 300 lines, 1 area).
  • build/test verify step skipped: no interpreter or test runner can run in this lane.

Fix

  • plugins/code-metrics/skills/audit/SKILL.md: new router (was audit-size/SKILL.md): action table, standing rules, Spoke paths, allowed-tools for all three scripts
  • plugins/code-metrics/skills/audit/actions/size.md: the audit-size skill body as the size action
  • plugins/code-metrics/skills/audit/actions/complexity.md: the audit-complexity skill body as the complexity action; collectors.md links re-pathed
  • plugins/code-metrics/skills/audit/actions/type-debt.md: the audit-type-debt skill body as the type-debt action
  • plugins/code-metrics/skills/audit/evals/evals.json: the three skills' nine cases merged, prompts now /code-metrics:audit <action>
  • plugins/code-metrics/skills/audit/scripts/{audit-size,audit-complexity,audit-type-debt}.sh and .test.sh: moved from the leaf skills; header comments name the new invocation; audit-size.test.sh reads actions/size.md and the router description
  • plugins/code-metrics/skills/audit-complexity/, audit-type-debt/ (SKILL.md, evals/evals.json): removed
  • plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh: COMPLEXITY now skills/audit/scripts/audit-complexity.sh
  • plugins/code-metrics/skills/audit-coverage/{SKILL.md,scripts/audit-coverage.test.sh,scripts/join.py}: references repointed
  • plugins/code-metrics/skills/{audit-duplication,audit-suppressions,setup,principles}/SKILL.md: pointers repointed to /code-metrics:audit <action>
  • plugins/code-metrics/prerequisites.json: for entries now skill:audit; degrade text names the new invocation
  • plugins/code-metrics/.claude-plugin/plugin.json, README.md, scripts/dispatch.sh (comment): repointed
  • plugins/review/{agents/code-reviewer.md,skills/quality-gate/context/code.md,skills/quality-gate/evals/evals.json,skills/fanout/context/default-mode.md}: size step runs /code-metrics:audit size
  • plugins/verification/skills/measure/context/metrics.md: complexity and size rows repointed
  • plugins/discipline/probes/script-the-deterministic-work.json, plugins/performance/probes/target.json: competitor id now code-metrics:audit
  • plugins/skill-quality/scripts/check-skill.test.sh: three Next fixtures repointed
  • scripts/check-code-metrics-skill-prose.py: type_debt phrase now pinned in skills/audit/actions/type-debt.md
  • scripts/affected-tests-live.sh, scripts/suite-seconds.txt, docs/test-wall-clock-baseline.md: test paths moved, lists kept in byte order
  • scripts/skill-leaf-name-registry.txt: code-metrics added to the audit owner set with its rationale
  • docs/catalog.md, docs/skill-cheat-sheet.md, docs/upstream/cursor-pstack.md: generated rows and references updated to match

Verification

The runner ran each check from the base copy against 3108d29:

  • scripts/check-changelog-fragments.sh --check: passed
  • scripts/check-changed-skills.sh --merge-base: passed

The run reports:

  • read https: //code.claude.com/docs/en/plugins/manifest-reference: 'Where each variable resolves' lists skill, command and agent content (the Markdown body) as where ${...} resolves; the variables are not in the Bash tool's environment
  • read https: //github.com/melodic-software/claude-code-plugins/issues /12486: blocker closed as completed on 2026-11-03 (PRs #12564, #12610)
  • read https: //github.com/melodic-software/claude-code-plugins/issues /12491: decided target (one code-metrics:audit router, no aliases), wave sizes, contracts that keep their values
  • check-changelog-fragments: all 23 fragments valid
  • check-changed-skills: 9 skills checked, 0 failed (new audit router PASS, 1 description-length warning)
  • check-affected: 13 passed, 5 skipped (typos not installed; validate-plugins sub-checks and changed-skills that run tree code skipped by the check), 0 failed; its first run failed on missing fragments for performance, skill-quality and discipline, fixed
  • check-evals-quality plugins/code-metrics/skills/audit/evals/evals.json: PASS, 0 warnings
  • cant-fail-scan --file audit-size.test.sh --lines 4,53-80 --check: PASS, no gating findings
  • grep for code-metrics:audit-(size|complexity|type-debt), skills/audit-(size|complexity|type-debt), skill:audit-(...) outside CHANGELOG.md: no matches
  • Glob plugins/code-metrics/skills/audit-*/: three tracked leaf skills remain (coverage, duplication, suppressions)
  • fresh-context review subagent over the whole diff: no high or medium findings; two low-confidence stale-text items, the dispatch.sh comment fixed and the README listing-budget figure left (see not_done)
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/41570586663

Left out: the items under Not verified.

Related

#12619

Lane-Activity: work-resolve-issue/resolve-issue
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 3108d291f6bb3667e4013da23195f5ebe2819457: read 45 of 45 changed file(s); 0 finding(s), 0 as inline comments.

Chunk 1 of 2 (37 files)

Security review: chunk 1 of 2 (37 files)

I read every hunk of the 37 files in this chunk and found no security issues.

The chunk combines the audit-size, audit-complexity and audit-type-debt skills into one router, code-metrics:audit, and updates the references to them. The rest is docs, changelog fragments, probe competitor ids, renamed scripts that only change header comments, and moved evals.

What I checked

  • New skill's tool grants (plugins/code-metrics/skills/audit/SKILL.md:6). allowed-tools lists exactly the three Bash(${CLAUDE_SKILL_DIR}/scripts/<script>.sh:*) grants the three deleted leaf skills held, plus the git branch --show-current grant each of them already had. The same scripts moved into this skill's scripts/ directory. No new command, wildcard or broader path is granted, so the session can run nothing it could not run before.
  • Script relocation (plugins/code-metrics/skills/audit-coverage/scripts/audit-coverage.sh:23). COMPLEXITY now points at $PLUGIN_ROOT/skills/audit/scripts/audit-complexity.sh, a fixed path inside the plugin. Nothing from the user or the consumer repository feeds into it. The moved entry scripts change only their header comments; the .test.sh renames are byte-identical or repoint test paths.
  • Placeholders in the action files. <skill-dir> and <plugin-root> are text the model replaces with the router's ${CLAUDE_SKILL_DIR} and ${CLAUDE_PLUGIN_ROOT}. They do not change what the tool grants allow.
  • Deleted instructions. Each action file loses its frontmatter and its "Next" pointers. The rules that matter ("never installs", "reports, never gates", "never count by hand", a missing collector shown as a row with its install hint) are restated in the router's Standing rules or remain in the action bodies. No guardrail in a protected class goes missing. docs/contracts/instruction-exception-register/README.md was not read; I judged the deletions by what each rule prevented.
  • Trust controls. No file in this chunk matches a trusted-path glob or touches the trusted-trigger check, the token broker, the kill switch or a merge hold.
  • PR context. It contains no embedded instructions aimed at this review.

Manifest

  • manifest description: pass. In plugins/code-metrics/.claude-plugin/plugin.json only the inert description field changed. No userConfig, hooks, mcpServers or dependencies change.

Prior findings: none (round 0 of 3; the round cap did not apply).

Spend: none. The change adds no lane runs, schedules or model use.

critical-findings: 0

Chunk 2 of 2 (8 files)

Security review: chunk 2 of 2 (8 files)

I found no security issues in this chunk.

I read every hunk of all 8 files:

  • plugins/review/skills/quality-gate/context/code.md
  • plugins/review/skills/quality-gate/evals/evals.json
  • plugins/skill-quality/scripts/check-skill.test.sh
  • plugins/verification/skills/measure/context/metrics.md
  • scripts/affected-tests-live.sh
  • scripts/check-code-metrics-skill-prose.py
  • scripts/skill-leaf-name-registry.txt
  • scripts/suite-seconds.txt

What changed. Every hunk renames a reference from the old skills (/code-metrics:audit-size, audit-complexity, audit-type-debt) to the new router form (/code-metrics:audit <action>). The rest moves file paths to skills/audit/.... That covers:

  • a test-to-source mapping string in affected-tests-live.sh
  • a pinned-phrase path in check-code-metrics-skill-prose.py
  • rows in the test-timing list (suite-seconds.txt)
  • a comment explaining why code-metrics was added to the registry's shared audit name

None of these changes runs a command built from outside input, uses a token or secret, adds a trigger, or changes permissions.

Removed or weakened instructions. None. The quality-gate size-crossing step in code.md keeps the same rule: run it only when the skill is available and no --worktree is passed, and use the same --base. Only the skill it names has changed. Nothing is deleted from an instruction file, hook, or allowlist.

Trusted paths. No file in this chunk matches a trusted-path glob. None touches a trust control (trusted-trigger check, lane token, kill switch, token broker, merge holds, or anything under .github/actions/).

Plugin manifests. None in this chunk. plugins/code-metrics/.claude-plugin/plugin.json is in chunk 1, so chunk 1's review covers it.

Prior findings. None: 0 rounds before this one, and the cap does not apply.

Spend. None.

critical-findings: 0

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude-review: 1 inline finding(s) on 3108d291f6bb3667e4013da23195f5ebe2819457; the summary is in this lane's pull request comment.

claude-lane: claude-review

Comment on lines +52 to +54
The `actions/` files write this skill's directory as `<skill-dir>`, which is `${CLAUDE_SKILL_DIR}`,
and the plugin's root directory as `<plugin-root>`, which is `${CLAUDE_PLUGIN_ROOT}`. Put those
paths in place of the placeholders before running a command: a `${…}` token is substituted in

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advisory: this restates upstream behavior as the reason (.claude/rules/skill-bodies-state-current-rules.md: "A skill or agent body never restates a volatile upstream specific, quoted or paraphrased … product or tool behavior given as our reason", and "A record never cures a restatement").

This line paraphrases how the product behaves: "a ${…} token is substituted in skill content but not in a supporting file, and the Bash tool does not receive the plugin variables". Lines 56–59 do add a pointer, an as-of date and a recheck trigger, but under the rule a record does not make a restatement acceptable. If the docs table changes, this body keeps giving the old behavior as its reason.

The sibling router this PR copies, plugins/code-metrics/skills/principles/SKILL.md:146-153, states our decision instead: "a ${…} token in a supporting file is not one this plugin can rely on being expanded, either in the file or in the Bash tool." Using the same wording here, and keeping the pointer, as-of date and recheck trigger, would make the two routers match and satisfy the rule.

claude-lane: claude-review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #12803, the owner-login replacement for this PR: the Spoke paths section now states our decision in the same words as plugins/code-metrics/skills/principles/SKILL.md:146-153 and keeps the pointer, as-of date and recheck trigger.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

claude-review reviewed 3108d291f6bb3667e4013da23195f5ebe2819457: read 45 of 45 changed file(s); 1 finding(s), 1 as inline comments.

Chunk 1 of 2 (37 files)

Code review, chunk 1 of 2 (37 files)

I read every hunk of this chunk: the six changelog fragments, the generated docs rows, the code-metrics manifest, README and prerequisites, the new audit router and its three action files, the merged evals, the moved scripts and tests, the repointed sibling skills, the probes, and the review agent and fanout context.

Overall. The move holds together. I found one advisory finding and nothing blocking.

  • Script paths. audit-coverage.sh now calls skills/audit/scripts/audit-complexity.sh, and that file exists at head. The moved scripts keep their ../../.. plugin-root depth, because skills/audit/scripts/ sits at the same depth as before.
  • Links. The collectors.md links in actions/complexity.md were re-pathed to ../../../reference/collectors.md, which resolves to plugins/code-metrics/reference/collectors.md.
  • Leftover tokens. No ${CLAUDE_…} token is left in any actions/*.md file.
  • Size test. audit-size.test.sh now looks for the provenance sentence in actions/size.md and checks the router's description on line 2 of SKILL.md. That description is well under 1024 characters. I did not run the test.
  • Stale references. A repo-wide search (excluding CHANGELOGs, .changes/ and the lane's own files) finds no remaining code-metrics:audit-(size|complexity|type-debt), skills/audit-(…) or skill:audit-(…) reference.
  • Report ids. The report skill values (audit-size, audit-complexity, audit-type-debt) are unchanged in the tests and in test_report.py, which matches the plan's list of contracts that keep their values.

Plugin manifest

  • manifest description: pass. It names audit size, audit complexity and audit type-debt, which is what ships after this change.
  • manifest version: pass. The code-metrics fragment declares bump: major, which fits removing three user-invocable skills. The review and verification fragments are patch, and the discipline, performance and skill-quality fragments are none because they change only probe data or test fixtures. All of those levels fit.
  • No userConfig field changed.

Path-scoped rule. .claude/rules/skill-bodies-state-current-rules.md applies to plugins/*/skills/**. One inline comment covers it: the router's Spoke paths section states upstream behavior as its reason. The router has a ## Next section before ## Gotchas, as the rule's successor-section part requires.

Not counted as findings (the PR already lists both as not done):

What I could not check. The PR says the eval non-inferiority run and the code-metrics test suites were not run. I did not run them either; that remains unverified and is left to CI and the follow-up the PR describes. Nothing in the PR context or rule files was embedded text addressed to this lane.

Out of scope. Chunk 2's files (quality-gate, check-skill.test.sh, measure metrics, and the scripts/ lists and registry) are reviewed separately.

Chunk 2 of 2 (8 files)

Code review: chunk 2 of 2 (8 files)

No findings in this chunk. I read every hunk of all 8 files. Each change points a reference at the new /code-metrics:audit <action> router or at the moved script paths. I checked each one against the files at head.

  • plugins/review/skills/quality-gate/context/code.md and quality-gate/evals/evals.json: the size step now runs /code-metrics:audit size ... --base <base>. The router's argument-hint (plugins/code-metrics/skills/audit/SKILL.md:3) and audit-size.sh both accept --base <ref>, so the call still works the same way.
  • plugins/skill-quality/scripts/check-skill.test.sh: I checked the three repointed ## Next fixtures against the checker's opening-token regex, ^\?/[a-z0-9-]+:[a-z0-9-]+(`|[[:space:]]|[.,;:]|$), in check-skill.sh:2440`.
    • `/code-metrics:audit complexity` still matches, because a space follows the token. So next-single stays silent and next-late still gets only the placement warning.
    • The next-operative line still opens with prose, so it still warns as the test expects.
  • plugins/verification/skills/measure/context/metrics.md: the complexity and size rows are repointed correctly. Duplication still points at audit-duplication, which this PR does not fold in.
  • scripts/check-code-metrics-skill-prose.py: the pinned phrase `type_debt.reference`, `null` is present in plugins/code-metrics/skills/audit/actions/type-debt.md:71. scripts/test_check_code_metrics_skill_prose.py has no reference to the old path.
  • scripts/affected-tests-live.sh and scripts/suite-seconds.txt:
    • The paths match the renamed test scripts.
    • The suite-seconds.txt entries are in byte order: audit-* (-, 0x2D) sorts before audit/ (/, 0x2F), so the new rows correctly sit after audit-duplication and before setup.
    • The per-suite seconds are unchanged.
  • scripts/skill-leaf-name-registry.txt: the registry header (lines 9–15) says check-skill-leaf-names.sh compares owner sets, not order. Adding code-metrics to the audit entry with a rationale block follows the file's documented process for a new owner joining an accepted collision.

Context outside this chunk: .claude/skills/control-claude-code-plugins/features/code-metrics/README.md still lists audit-complexity, audit-size and audit-type-debt as separate parts. The PR's "Not verified" section already names this as a write the lane could not make. That file is not in the diff, so it is not counted as a finding here.

Closing issue: the PR context has only Refs: #12619 and no ## Closing issue section, so there were no acceptance criteria to check.

Verification: I ran no tests or scripts; this lane has no shell. The test-suite results the PR describes are the author's claims and remain unverified.

Spend: none in this chunk. It changes no paid plans or billing, and no lane run counts or model settings.

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The unattended merge path armed native auto-merge at head 3108d291f6bb3667e4013da23195f5ebe2819457.

@kyle-sexton kyle-sexton added the do-not-merge Hard merge gate: do not merge while applied. label Nov 3, 2026
@kyle-sexton
kyle-sexton disabled auto-merge November 3, 2026 05:12
@kyle-sexton kyle-sexton removed the do-not-merge Hard merge gate: do not merge while applied. label Nov 3, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

pr-unblock / address-feedback finished round 1 of max 4 on 3108d29.

@kyle-sexton

Copy link
Copy Markdown
Member

Hold: superseded by #12803, an owner-login replacement. Releases when: #12803 merges, then this PR closes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge Hard merge gate: do not merge while applied.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant