一键导入
fix-department
Drive a department or gem all the way to 100% conformance using per-cop validation and generated corpus reports, never manual README/docs edits.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Drive a department or gem all the way to 100% conformance using per-cop validation and generated corpus reports, never manual README/docs edits.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Review PRs created by the agent cop fix workflow and approve, fix, or close them.
Fix variant (EnforcedStyle) FP/FN on a cop — either a CI regression on a bot PR, or outstanding divergence from the corpus oracle. Auto-reads docs/corpus.md for examples.
Get a department or gem all the way to 100% conformance using per-cop validation and generated corpus reports, never manual README/docs edits.
Rank cops by FP+FN from the corpus oracle to find the next batch to fix
Checklist of files to update when adding or updating a rubocop plugin gem
| name | fix-department |
| description | Drive a department or gem all the way to 100% conformance using per-cop validation and generated corpus reports, never manual README/docs edits. |
| allowed-tools | Bash(*), Read, Write, Edit, Grep, Glob |
This skill targets one department or one gem (for example Naming,
rubocop-performance, rubocop-rspec, or rubocop-rails) and drives it all
the way to 100% conformance.
docs/corpus.md is an autogenerated corpus report. The conformance/corpus
section in README.md is also autogenerated. Never edit those generated
sections directly. Other non-generated README.md content may still be edited
normally when appropriate. Treat the generated scorecard rows as read-only and
refresh them only through the CI corpus-oracle workflow/PR. Local dry-run
checks are fine, but never run a local generator/script that writes README.md
or docs/corpus.md.
Final stop condition:
README.md, docs/corpus.md, and related artifacts), never via manual edits.check_cop.py --rerun results are intermediate count-based gates only.
They are necessary, but they are NOT sufficient to end /fix-department.
When the corpus oracle has concrete FP/FN examples for a cop, use
check_cop.py --rerun to verify before treating that cop as done locally.
Run fix work from a dedicated git worktree by default.Default behavior for this skill is to keep iterating until the target is
actually done or truly blocked. Do not stop just because a batch was committed,
landed onto main, or pushed.
$fix-department --loop makes this explicit:
README.md / docs/corpus.md CI-owned scorecard at 100%)Codex skill activation is turn-scoped, but /fix-department --loop should be
treated as a standing task across the thread.
/fix-department --loop run and the user
asks for status, commit, land, cherry-pick, rebase, push, or verification,
treat that request as a sub-step inside the same loop.$fix-continue --loop rather than silently
ending the workflow.Start with the scoreboard:
python3 .agents/skills/fix-department/scripts/gem_progress.py --summary
The summary treats cops covered by the synthetic benchmark as covered, but synthetic-only divergence is called out in the gem deep-dive rather than the summary row alone.
Determine the target:
rubocop department (for example Naming,
Layout, Lint, Metrics, Style), use the owning gem only for triage,
but treat the department row in README.md / docs/corpus.md as the
read-only scorecard.rubocop-performance,
rubocop-rspec, rubocop-rails, etc.), the gem is both the triage scope
and the final scorecard.If no gem/department is specified, pick one with:
Untest means no corpus or synthetic coverageRun deep-dive for the selected gem:
python3 .agents/skills/fix-department/scripts/gem_progress.py --gem <gem-name>
Also inspect the current checked-in scorecard row for the target in
README.md and docs/corpus.md. Never patch the generated conformance
section by hand. That row, not the per-cop rerun output, is the lagging
scorecard that must eventually be refreshed to 100% by the report
CI corpus-oracle workflow/PR.
Bootstrap the environment before reducers/tests/check-cop:
git submodule update --init --recursive
bench/corpus/vendor/bundle/ is missing for the active Ruby version, install it:
cd bench/corpus && BUNDLE_PATH=vendor/bundle bundle install
vendor/corpus/ as mandatory bootstrap. The smoke test does not
need it, and cloud environments should not prefetch the full corpus checkout.bench/corpus/manifest.jsonl (no cloning needed):
gh api repos/OWNER/REPO/contents/PATH?ref=SHA --jq '.content' | base64 -d
Select up to 4 cops for the next batch:
Establish ground truth first — before reading cop source or running reducers, run these commands in parallel for each selected cop:
git log --oneline -5 -- src/cop/<dept>/<cop_name>.rs # what's been committed recently?
python3 scripts/check_cop.py Department/CopName --verbose # oracle FP/FN — the actual current gap
Compare the latest cop commit date against the corpus oracle run date (shown in
check_cop.py output). If the oracle ran AFTER the latest fix, its FP/FN
numbers are the real remaining gap — not stale data from before the fix. This
tells you exactly what still needs fixing before you spend time reading source
or running reducers. Do NOT read the full cop source (which may have hundreds
of lines of investigation comments) until you know the current numbers and
which repos are diverging.
Investigate each selected cop:
python3 scripts/check_cop.py Department/CopName --examples --fp-only --limit 10
python3 scripts/check_cop.py Department/CopName --examples --fn-only --limit 10
check_cop.py prefers embedded snippets from corpus-results.json. If that
is insufficient, fetch full source files directly from GitHub using repo info
from bench/corpus/manifest.jsonl:
gh api repos/OWNER/REPO/contents/PATH?ref=SHA --jq '.content' | base64 -d
Synthetic-only cops (zero corpus activity): If check_cop.py shows no results, the cop
only has data in the synthetic corpus. Investigate using:
# Read synthetic results for the cop
python3 -c "import json; d=json.loads(open('bench/synthetic/synthetic-results.json').read()); [print(c) for c in d['by_cop'] if c['cop']=='Department/CopName']"
# Read the synthetic source files directly (paths from fp_examples/fn_examples)
# Source files are at bench/synthetic/project/<path>
The synthetic corpus files at bench/synthetic/project/ are handcrafted trigger patterns - read
the relevant source file to understand the expected behavior. Run python3 bench/synthetic/run_synthetic.py --verbose
to re-verify after fixing.
Reduce up to 3 examples per cop (corpus cops only - not applicable to synthetic-only cops):
python3 scripts/reduce_mismatch.py Department/CopName repo_id filepath:line
python3 scripts/reduce_mismatch.py Department/CopName repo_id filepath:line --type fn
Read reduced repros from /tmp/nitrocop-reduce/ and capture root-cause hypotheses.
Read:
src/cop/<dept>/<cop_name>.rsvendor/rubocop*/spec/rubocop/cop/<dept>/<cop_name>_spec.rbAdd failing tests first:
tests/fixtures/cops/<dept>/<cop_name>/no_offense.rbtests/fixtures/cops/<dept>/<cop_name>/offense.rbcargo test --release -p nitrocop --lib -- <cop_name_snake>
Implement the fix in src/cop/<dept>/<cop_name>.rs.
Re-run targeted tests and ensure they pass. Important: Fixture tests bypass config (Include patterns, Enabled status). A passing test does NOT guarantee the binary fires on real files. If fixing an FN, also verify the binary detects the pattern — see AGENTS.md Key Constraints for Prism block body shape gotchas (BeginNode vs StatementsNode, itblock/numblock).
Verify with the right acceptance gate for cops changed in this loop:
python3 scripts/check_cop.py Department/CopName --verbose --rerun
python3 bench/synthetic/run_synthetic.py --verbose
Corpus validation is the intermediate acceptance gate for corpus-backed cops.
For synthetic-only cops, rerun the synthetic benchmark and inspect that cop's
entry in bench/synthetic/synthetic-results.json; check_cop.py has no
signal there. Unit tests passing is necessary but not sufficient.
Use --rerun only for cops whose behavior may have changed (cop source or
related parsing/config logic). For untouched corpus cops, prefer artifact
mode (python3 scripts/check_cop.py Department/CopName --verbose) when the
latest corpus oracle run is current.
Do not stop here. Exact-match per-cop reruns can still leave the target department/gem below 100% once the corpus reports are regenerated.
Handle regressions:
gh run view <run-id> --job <job-id> --log 2>&1 | grep -A 3 "FAIL:"
This immediately names the regressed repo(s) — do NOT re-run
check_cop.py --rerun locally to find a regression that CI
already identified./// ## Known false positives (N FP in corpus as of YYYY-MM-DD)
///
/// Attempted fix: <summary> (commit XXXXXXXX, reverted).
/// Code path changed: <file::function and condition changed>.
/// Acceptance gate before: expected=?, actual=?, excess=?, missing=?
/// Acceptance gate after: expected=?, actual=?, excess=?, missing=?
/// Effect: fixed A target FP but introduced B new FP (X -> Y total FP).
/// Root cause of regression: <why this approach regressed>.
/// A correct fix needs to: <constraints for a future correct fix>.
Document ALL investigation outcomes as /// comments on the cop's struct in its
source file. This is mandatory for EVERY cop in the batch — including:
standard:disable handling or other config edge cases (these are still bugs to fix, not acceptable differences)This prevents future investigators from repeating the same analysis. Do not consider a cop "done" until it has an investigation comment, even if the fix itself is already committed. Use:
/// ## Corpus investigation (YYYY-MM-DD)
///
/// Corpus oracle reported FP=X, FN=Y.
///
/// FP=X: <what was fixed or why no fix is needed>
/// FN=Y: <what was fixed, what remains, and root cause of any remaining FN>
After all cops in the batch are fixed:
cargo fmt
cargo clippy --release -- -D warnings
cargo test --release
python3 scripts/corpus_smoke_test.py --binary target/release/nitrocop
Run the corpus smoke test once per batch, not after every cop. It is the cheap
systemic guard for file discovery, config/plugin loading, directive handling,
and other cross-cop regressions that per-cop check_cop.py reruns will not catch.
It does not require vendor/corpus/.
Re-check each fixed cop with the right acceptance gate:
python3 scripts/check_cop.py Department/CopName --verbose --rerun
python3 bench/synthetic/run_synthetic.py --verbose
Use check_cop.py for corpus-backed cops and run_synthetic.py for synthetic-only cops.
Refresh department/gem status:
python3 .agents/skills/fix-department/scripts/gem_progress.py --gem <gem-name>
If the user explicitly asks for a corpus-report refresh, use the real generation path rather than editing files by hand:
cargo run --release --bin bench_nitrocop -- conform
bench_nitrocop -- conform refreshes bench/conform.json and bench/results.md
only. It does NOT update README.md or docs/corpus.md.
When the generated conformance section in README.md or docs/corpus.md needs
to move, do not run local generators against those files. README.md and
docs/corpus.md are CI-owned artifacts and may only be updated by the CI
corpus-oracle workflow/PR. Local dry-run comparisons are allowed only if they
do not write those files. Never patch that generated content directly.
/fix-department is not done until the generated reports show the target at
100.0% / 0 FP / 0 FN.
After a CI corpus-report refresh, inspect the target row in README.md and
docs/corpus.md:
check_cop.py --rerun.If diverging cops remain, loop back to Phase 1.
Report:
fmt / clippy / test
per-cop check-cop / run_synthetic
corpus-report generation status
README.md / docs/corpus.md target row after CI refresh
Linux CI parity status (confirmed / pending / diverged)Do not leave retained progress only in a worktree branch.
Commit all progress worth keeping in the worktree:
Integrate those commit(s) into main immediately (unless the user explicitly says not to).
If working in a worktree, cherry-pick from the worktree branch:
git checkout main
git cherry-pick <sha1> [<sha2> ...]
If already on main (worktree not used), commits are already there — just verify.
Verify integration on main:
git log --oneline -n 10
git status --short --branch
Report exactly what was integrated (commit SHA(s) and short subjects).
If there is truly no repo-retained progress, explicitly report that no commit was made.
In --loop mode, after integration/reporting, return to Phase 1 unless the
target is done or the user explicitly stopped the run.
This includes turns where the user asked only for an intermediate git action
such as "commit to main", "rebase", or "push".
git rev-parse --show-toplevel.
If not in a worktree, continue working on main — do not block on this.git submodule update --init --recursivebench/corpus/vendor/bundle/ exists for the active Ruby version before any corpus-backed validation or smoke runs.bench/corpus/manifest.jsonl:
gh api repos/OWNER/REPO/contents/PATH?ref=SHA --jq '.content' | base64 -dmain before ending the run.git stash or git stash pop./tmp/, not anywhere outside the test fixtures. Running nitrocop on arbitrary paths fails
("No lockfile found") and wastes tokens. The ONLY ways to verify cop behavior are:
offense.rb / no_offense.rb fixtures and run
cargo test --lib -- <cop_name_snake>.check_cop.py --rerun for aggregate count regression on
modified cops; check_cop.py --verbose (artifact mode) for untouched cops.python3 bench/synthetic/run_synthetic.py --verbose for synthetic-only cops.
Never create test Ruby files outside the fixture directories.docs/corpus.md is autogenerated, and the conformance/corpus section in
README.md is autogenerated. Do not update either file locally, even via
generator scripts; only the CI corpus-oracle workflow/PR may change them.cargo run --release --bin bench_nitrocop -- conform updates
bench/conform.json and bench/results.md; it does not regenerate
the generated conformance section in README.md or docs/corpus.md.check_cop.py is a count-only cop-level gate, not the completion gate. Never declare
/fix-department done while generated README.md / docs/corpus.md still
show the target below 100%, or while Linux CI parity is still unconfirmed.vendor/corpus/ when available, but fetch them selectively rather than assuming a full local corpus checkout.$fix-department — show scoreboard and choose a gem$fix-department Naming — complete the Naming department and keep going until its generated corpus-report rows hit 100%$fix-department Layout --loop — persistent run: keep fixing, integrating, and resuming until the department is actually done or truly blocked$fix-department rubocop-performance — focus that gem$fix-department rubocop-rspec — focus that gem$fix-department rubocop-rails — focus that gem$fix-department --input /path/to/corpus-results.json — use local corpus data