Fix-From-Diagnostics Skill
Turn typechecker/linter failures into a Bun-style work queue: parse once → cyclic-dependency pre-pass → shard by package → fix per shard (optionally dual-review large shards) → re-check diagnostics → only then run the full suite / smoke.
Use when:
tsc/mypy/ruff/eslintreports many errors (rough rule: ≥ 15 distinct findings, or ≥ 3 packages), or/autoself-heal classifieslint_format/type_errorand a single-file fix is clearly insufficient, or/implementStep 6 validation fails with a wall of type/lint noise.
Do not use for one-off annotation fixes (≤ ~5 errors in one file) — fix those inline.
Process
1. Capture diagnostics
Run the project's type/lint command(s) and capture full stdout+stderr to a file, e.g.:
# examples — use project-manifest / package scripts when present
npx tsc --noEmit 2>&1 | tee /tmp/harness-tsc.txt
npx eslint . -f stylish 2>&1 | tee /tmp/harness-eslint.txt
ruff check . 2>&1 | tee /tmp/harness-ruff.txt
mypy . 2>&1 | tee /tmp/harness-mypy.txt
Prefer the command that failed. If multiple tools failed, run this skill once per tool (or merge captures only when the same tool).
2. Cyclic-dependency pre-pass
Before sharding by package, check whether the failure is actually a dependency cycle wearing a diagnostics costume — Bun ran a separate workflow to resolve cyclic dependencies before mass-fixing their 16k Zig→Rust compiler errors, because errors clustered on a cycle re-open each other across shards and can burn the full queue-pass budget (Step 6) without ever converging.
- From the raw capture, roughly count the distinct packages/modules touched (the same package boundary
diagnostics-shard.jswill use). If fewer than 3 packages are affected, skip this step — go straight to Step 3. - If ≥ 3 packages are affected, check for a known import cycle: read
specs/brownfield/modularity-pack.mdif present, orspecs/brownfield/code-graph.json'scyclesfield as a fallback. If neither exists, skip this step — go straight to Step 3. - Identify the error-dense packages (the ones carrying the most diagnostic lines in the raw capture) and check whether 2 or more of them appear together in a listed cycle.
- If they do: pause before sharding. Run a structural pass first — break the cycle at its smallest cut (extract a shared interface/type to a lower-level module, invert one edge, or introduce a boundary module;
modularity-reviewer's cycle analysis is the reference ifspecs/brownfield/modularity-pack.mdexists), and validate the cut narrowly (targeted build/typecheck on just the packages touched by the cut, not the full suite). Then re-capture diagnostics (Step 1) and rebuild the work queue (Step 3) before resuming normal per-shard fixing — the re-shard after a structural fix does not count against Step 6's 3-pass cap, since it precedes the normal queue rather than repeating it. - If the error-dense packages are not on a known cycle (or there's no cycle data at all), proceed straight to Step 3 — this pre-pass is a judgment threshold, not a mandatory detour.
Prompt-only step, no computational sensor — like G32's canary-first guide, the "≥3 packages" and "error-dense" thresholds are judgment applied mid-task, not a mechanically checkable commit-time property.
3. Build the work queue
node .claude/scripts/diagnostics-shard.js --tool tsc --from-file /tmp/harness-tsc.txt
# or auto-detect:
node .claude/scripts/diagnostics-shard.js --auto --from-file /tmp/harness-tsc.txt
Writes:
.claude/state/diagnostics/errors.jsonl— one JSON object per error.claude/state/diagnostics/shards.json— shards grouped by package/module
If total_errors is 0, stop — diagnostics are clean.
4. Parallel safety
If processing 2+ shards concurrently:
- Create
.claude/state/parallel-implement.lock(empty). - Set
HARNESS_PARALLEL_AGENTS=1for the window. - Teammates must not run full monorepo
npm test/ full-suite until all shards report clean diagnostics for this tool. - Git safety (stash / reset --hard / force-push) remains denied while the lock exists.
- Remove the lock when done.
5. Fix each shard
For each shard in shards.json (dependency order optional; prefer smaller shards first):
- Ownership: only edit files listed in
shard.files(plus minimal import/type neighbors if required for the fix — note them). - Fix real errors — no stub-to-green (
todo!,NotImplementedError, emptypasssolely to clear compile). - Re-run the scoped tool on those files when possible (e.g.
tsc --noEmitstill whole-project is OK; prefereslint path1 path2). - Review (tiered): if the shard touches ≥
review.adversarial_min_filesfiles or ≥review.adversarial_min_lineslines, run dual adversarial code-review viareview-tier.js+merge-review-verdicts.js(same as/implementStep 7). Otherwise onecode-revieweris enough for the shard diff. - Commit owned paths only when the shard's diagnostic count for those files drops (optional mid-queue commits; at least one commit before the final suite). After dual review, prefer:
git commit -m "$(node .claude/scripts/review-commit-msg.js --subject "fix $(shard.id) diagnostics" --from-audit specs/reviews/adversarial-review-audit.json)"
6. Close the queue
- Re-run the full tool check; re-shard if errors remain (
diagnostics-shard.jsagain). - Max 3 full queue passes; if still red, stop and escalate with remaining
errors.jsonl. - Only after zero errors for this tool: run project tests + lint/type as in
/implementStep 6 (or resume/autofailed gate). - Optional smoke: if the app has a health check, boot per resume-smoke conventions before claiming success.
7. Process learning
If the queue failed because agents stubbed, ran full-suite mid-shard, or used destructive git, append a rule to .claude/state/process-rules.md (workflow constraint, not code style).
Rules
- No full monorepo suite between shards when error count was ≥ 15 at queue start — mid-queue suite thrash is the failure mode this skill exists to prevent.
- Check for a cycle before sharding when ≥3 packages are error-dense and cycle data exists (Step 2) — sharding across a cycle risks burning the queue-pass budget without converging.
- No stub-to-green to empty the queue.
- Implementer does not self-review large shards — use fresh-context
code-reviewer. - Prefer fixing production code over weakening types (
any,@ts-ignore) unless the story explicitly allows.
Outputs
| Path | Purpose |
|---|---|
.claude/state/diagnostics/errors.jsonl |
Flat error list |
.claude/state/diagnostics/shards.json |
Work queue + progress input |
| Commits on owned paths | Per-shard or end-of-queue |
Gotchas
- Pretty-printed multi-line tsc notes: only the primary
error TSxxxxlines are parsed; related "note:" lines are ignored (by design). - Absolute paths from eslint: packages still shard correctly via path segments.
- Mixed tools: do not feed eslint JSON into
--tool tsc— use--autoor the matching--tool.