engineer/skills/fix/SKILL.md
Use to drive a bug fix from first report through close, with a "why didn't we catch it?" loop at the end. Triggers — "/engineer.fix", "a bug came in", "this is broken", "a user reported X", "there's a defect", "we have a regression", "this needs a fix", "another report", "more issues", "still failing", "validation failed again", "another bug", "next defect", "more fixes".
npx skillsauth add swingerman/atdd fixInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The defect unit-of-work — parallel to "feature" in the DAE pipeline. Tracks a bug from first report through a regression spec, code fix, hardening, and a structured retrospective that feeds back into the methodology.
Unlike ad-hoc fixes, the fix workflow enforces a regression spec that must be RED on current code before any change, and closes the loop with a "why didn't we catch it?" gap analysis tied to a closed category vocabulary. That loop is the methodology contribution: bugs become methodology feedback, not just patches.
Not for: building a new capability (/engineer.discuss or /engineer.feature-init); adjusting an in-flight feature's scope (/engineer.feature-edit); reviewing recent changes without a defect (/engineer.verify or /crap-analyzer).
Infra contract. Any step that runs tests, mutations, or the regression spec MUST first ensure required infra is up via ${CLAUDE_PLUGIN_ROOT}/scripts/dae_infra.py ensure <names> (reading the manifest's infra: section). On a start-failed failure → stop and surface the structured diagnosis. On undeclared required infra → stop with "declare in manifest" message. This applies to Steps 3, 4, 7.
Quirks contract. Before booting infra or running test commands, consult manifest.infra_quirks: apply runtime_pins (e.g. ensure JAVA_HOME matches runtime_pins.java), read port_map_file if set, surface framework_constraints to the agent if relevant ("note: Flutter web has no hot-reload — full rebuild required"), and use recovery_commands keyed by failure signature when probing reports a known stuck state. Quirks exist so the agent doesn't rediscover what's already documented (nexthq Java/Flutter, mmc Apache opcache).
Before Step 1, probe for in-flight fixes via ${CLAUDE_PLUGIN_ROOT}/scripts/dae_fix.py list_open_fixes (any status != closed). Three cases:
| State | Action |
|---|---|
| No open fixes | Proceed to Step 1 (Capture) as a new defect. |
| Exactly one open fix, agent has fresh context (e.g. just typed "still failing", "validation failed again") | Continue that fix from its current status: — jump to the matching step. Don't write a new artifact. |
| Multiple open fixes, or one open fix + trigger sounds like a new defect (e.g. "another bug", "a new report came in") | Surface the open fixes one-line each and ask "continue X, or capture a new defect?" — single AskUserQuestion, then proceed. |
mmc ran 5 sequential fixes from one /engineer.fix invocation because the skill assumed one-shot. Re-entry routing makes "many fixes in a row" cheap: no re-anchor, no template re-read, just pick up where the last close left off. A fresh defect from re-entry still flows through Steps 1–9 — it just doesn't lose the agent's context to a cold start.
Accept free-form input; no feature slug required. Collect: title, severity (low | medium | high | critical), source (kind: sentry|github|slack|user|internal, ref: <url-or-id>), whether it blocks users (blocks_user), workaround ("none" if none), and a concise repro/expected/actual.
Write .engineer/fixes/<YYYY-MM-DD-slug>.md via the schema in references/artifact-template.md. Set status: investigating.
CLI shortcut: /engineer.fix "title" --source <url> pre-fills title and source; skip the prompt for those fields.
Validate the new artifact: ${CLAUDE_PLUGIN_ROOT}/scripts/dae_fix.py --validate <fix-file>. Surface any errors before proceeding.
Goal: identify which feature(s) own the broken code.
Heuristics — run cheapest first to bound token cost:
feature.files in known features..engineer/features/*/feature.md.git log --oneline -- <file>).Match resolution:
prime-context confirms strong relevance → AUTO-POPULATE feature_refs; record match_mode: auto.prime-context per candidate, present ranked list, ask user to confirm. Record match_mode: manual.match_mode: none; proceed as a loose fix (no feature_refs).Record investigation.candidates_considered. Set status: pinned-pending.
Write one regression Given/When/Then spec per feature_refs entry (not a shared spec). Use references/regression-spec-template.md.
Run the spec on current code. It MUST be RED. If it passes (GREEN) the spec does not pin the bug — redraft until RED. Record red_run.result: red + command + output in pin_confirmation.feature_refs[*].
Present the spec(s) and red-run evidence to the user for confirmation before proceeding. Set status: pinned.
Implement the fix using the same discipline as Checkpoint 5. The regression spec must turn GREEN. Update fix_commits. Set status: fixed.
Invoke engineer:refine on touched code. Set status: refined.
Run engineer:arch-check on each touched feature. Run crap-analyzer on the fix diff. Record results. Set status: verified.
Run atdd:atdd-mutate on touched files. Record harden_results.mutation_score.
Bug-line mutation gate: recover the buggy line(s) via git show HEAD~1 -- <file>, apply locally, run only the regression spec, assert RED. If the spec stays GREEN the spec is coupled to the fix, not the bug — back to Step 3 (Pin). Restore the fix. Record harden_results.bug_line_mutation_confirmed: true.
Record harden_results.arch_check. Set status: hardened.
For each affected feature, identify which DAE phase leaked. Use the closed vocabulary in references/gap-analysis-categories.md — one entry per distinct finding.
CONFIRM-FIRST: present findings to the user for approval before writing to the artifact. Findings are claims about methodology gaps; the user is the source of truth.
Write approved findings to gap_analysis[*]. Determine blockers via blocker_categories() (see references/gap-analysis-categories.md for the rule). Advisory followups go to .engineer/consolidation.md tagged with the fix slug; blocker followups must be applied inline or the charter explicitly amended. Set status: gap-analyzed.
Run ${CLAUDE_PLUGIN_ROOT}/scripts/dae_fix.py close_ready(rec). Hard preconditions: pin confirmed, hardened (including bug-line gate), gap_analysis non-empty, no unresolved blockers.
Emit a handoff that reference-links each feature_refs[*]/progress.md. Set status: closed.
Then dispatch per ${CLAUDE_PLUGIN_ROOT}/references/handoff-dispatch.md: advisory followups already landed in .engineer/consolidation.md (no dispatch — next surfaces them); blocker followups are already applied. Auto-invoke /engineer.progress-log to propagate the closure entry to each affected feature's progress.md at autonomy medium/high; confirm-then-dispatch at low.
Post-merge cleanup (deferred). Print the cleanup commands the user (or next agent) must run after the fix PR merges, and record the branch name in the closure entry so next/session-summary can detect a stale branch later:
After the PR merges:
git checkout main && git pull --ff-only && git branch -d <branch>
This is informational — the close step happens before merge, so cleanup can't run here. next and session-summary both probe for merged branches and will offer the cleanup automatically.
/engineer.discuss or /engineer.feature-init/engineer.feature-edit/engineer.verify or /crap-analyzerreferences/artifact-template.md — canonical .engineer/fixes/<slug>.md schemareferences/regression-spec-template.md — Given/When/Then template used in Step 3references/gap-analysis-categories.md — closed vocabulary + blocker ruleprime-context (Step 2 per candidate), arch-check + crap-analyzer (Step 6), atdd-mutate (Step 7), progress-log (Step 9), next (surfaces open fixes)engineer/references/handoff-dispatch.md — infra-ensure-before-stop ruledata-ai
Use immediately after a PR is merged to clean up the local feature branch and resync main. Triggers — "/engineer.post-merge", "did we merge", "did we push", "PR merged", "post-merge cleanup", or right after a `gh pr merge` succeeds in the same session.
testing
Use mid-task when the working thread is lost — after a context compaction, a long agent run, or coming back to a feature unsure of the role, the current checkpoint, or the next action. Triggers — "/engineer.reorient", "reorient", "re-anchor", "what should I be doing right now", "I lost track", "where was I".
development
Use to check a feature's code against the charter's architecture rules — dependency layering, cycles, forbidden patterns, file naming, file size. Triggers — "/engineer.arch-check", "architecture check", "check architecture fitness", "does this follow the charter", "check layering".
tools
Use at the start of a work session, or any time the question is "what should I pick up now" across the whole project. Triggers — "/engineer.next", "what's next", "what should I work on", "what should I do next", "where do I pick up".