Problem
/toolchain:lint --fix is the weakest-gated tree-mutating surface in the fleet. The flag is the only gate: no confirmation step in the skill body, no dry-run mode, no LOC budget, and no file cap.
That would be defensible if the fix commands were formatting-only. They are not — the bundled defaults change code:
plugins/toolchain/reference/ecosystems/python.yaml:9 — uv run ruff check . --fix && uv run ruff format .
plugins/toolchain/reference/ecosystems/go.yaml:37 — golangci-lint run --fix ./...
plugins/toolchain/reference/ecosystems/typescript.yaml:9 — npx biome check --write .
The sharpest instance
The Python fix-cmd targets . — the whole tree, not the changed files — and carries no --unfixable F401, so it deletes unused imports.
The fleet already knows this is hazardous. plugins/ruff-format/hooks/ruff-format.sh:238 runs the guarded form, and its header (:19-23) explains exactly why:
--unfixable F401 protects just-added imports: during iterative editing an import often lands one edit before the code that uses it […] F401 still surfaces as an advisory finding — only the auto-deletion is suppressed.
The hook has a regression test for the behavior (ruff-format.test.sh:255 "unused import preserved (--unfixable F401) but reported"). Two surfaces in the same repo take opposite positions on the same fix, and the unguarded one is the one with no confirmation gate.
Note the asymmetry is deliberate on the check side — python.yaml:8 uses --no-fix for check-cmd. Only the fix path is unguarded.
Why it matters now
Unrelated adoption research surveyed every findings→apply relay in the fleet. Every other mutator has a gate of some kind: review:fanout fix has a confirmation step plus a surface-instead-of-applying carve-out, claude-memory:audit fix is documented as never batch-applying without approval. This one has the flag and nothing else — and it is reachable non-interactively.
Suggested direction
Not prescribing the fix, but the options that keep the skill useful:
- Add
--unfixable F401 to the Python fix-cmd, matching the hook's already-tested position.
- Scope
fix-cmd to the detected changed files rather than ., consistent with the skill's own ecosystem-detection step.
- Add a dry-run and/or a confirmation gate for the fix path, matching the pattern the other mutating surfaces use.
(1) is the smallest change that closes the sharpest edge; (2) and (3) are the general fix.
Verification
All paths and line numbers verified against 065877c8.
Problem
/toolchain:lint --fixis the weakest-gated tree-mutating surface in the fleet. The flag is the only gate: no confirmation step in the skill body, no dry-run mode, no LOC budget, and no file cap.That would be defensible if the fix commands were formatting-only. They are not — the bundled defaults change code:
plugins/toolchain/reference/ecosystems/python.yaml:9—uv run ruff check . --fix && uv run ruff format .plugins/toolchain/reference/ecosystems/go.yaml:37—golangci-lint run --fix ./...plugins/toolchain/reference/ecosystems/typescript.yaml:9—npx biome check --write .The sharpest instance
The Python
fix-cmdtargets.— the whole tree, not the changed files — and carries no--unfixable F401, so it deletes unused imports.The fleet already knows this is hazardous.
plugins/ruff-format/hooks/ruff-format.sh:238runs the guarded form, and its header (:19-23) explains exactly why:The hook has a regression test for the behavior (
ruff-format.test.sh:255"unused import preserved (--unfixable F401) but reported"). Two surfaces in the same repo take opposite positions on the same fix, and the unguarded one is the one with no confirmation gate.Note the asymmetry is deliberate on the check side —
python.yaml:8uses--no-fixforcheck-cmd. Only the fix path is unguarded.Why it matters now
Unrelated adoption research surveyed every findings→apply relay in the fleet. Every other mutator has a gate of some kind:
review:fanout fixhas a confirmation step plus a surface-instead-of-applying carve-out,claude-memory:auditfix is documented as never batch-applying without approval. This one has the flag and nothing else — and it is reachable non-interactively.Suggested direction
Not prescribing the fix, but the options that keep the skill useful:
--unfixable F401to the Pythonfix-cmd, matching the hook's already-tested position.fix-cmdto the detected changed files rather than., consistent with the skill's own ecosystem-detection step.(1) is the smallest change that closes the sharpest edge; (2) and (3) are the general fix.
Verification
All paths and line numbers verified against
065877c8.