| name | fix-one-issue |
| description | Implement a single work-unit (a tracker issue or a described task) end to end in its branch: explore, make the smallest correct change, verify, and commit. Use for "implement this issue", "fix issue 123", "make this change and verify it". The implement stage of the ship-it orchestrator, and usable standalone on an issue or a described task. Not for review (use review-and-address), comments (comment-cleanup), or CI (ci-fix). |
fix-one-issue: implement, verify, commit
Take one work-unit's intent and land the smallest correct change for it in its branch, verified and committed. The core implement stage.
1. Resolve the work-unit and working copy
2. Read config
Load the resolved config via ${CLAUDE_PLUGIN_ROOT}/scripts/load-config.sh (defaults applied, @FILE refs inlined); read keys with jq:
houseRules / safety (carry into every edit and the commit: no em dashes, no AI attribution, plus project rails, e.g. "read the framework doc first" if a project rule says so),
verify (the commands to run after the change),
worktree.prepare (the make-runnable command used above).
3. Implement
If the work-unit carries a plan (from the planning stage), implement against it: the plan names the steps, files, and edge cases, so follow it rather than re-deriving the approach. For a stacked child (its base is a sibling branch, not config.repo.mainBranch), the plan was drafted before the parent landed, so first reconcile it with the parent's committed work: read git -C <worktree> diff <config.repo.mainBranch>...HEAD (everything the parent already put on your base) and adjust the plan for it before coding. With no plan (standalone, or planning disabled), proceed from exploration.
- Explore the working copy to find the exact code, or confirm the plan's predicted files; scope every search to it.
- Verify every external API before you write it. Do not write a single call into a third-party package, framework, runtime, or platform API from memory. Training data lags the installed version, and a hallucinated attribute or a renamed option is how confidently-broken code ships. Read the version from
package.json / the lockfile (or Cargo.toml, go.mod, ...), then confirm the exact symbol, signature, options, and behavior against THAT version: check the package's shipped docs and types in node_modules (a docs/ folder, an llms.txt, an AGENTS.md, a README, or .d.ts types, e.g. node_modules/next/dist/docs/); the installed source itself, wherever the ecosystem installs it (node_modules for JS/TS, ~/.cargo/registry/src for Rust crates, site-packages for Python, vendor/ for Go), not just node_modules; and version-pinned official docs via the context7 MCP tool or the docs site. The same goes for network service calls (REST / GraphQL / RPC, an LLM, payment, or platform API): confirm the endpoints, the request and response shape, auth, pagination, and error handling against the service's current, version-pinned reference (its docs, an OpenAPI or GraphQL schema, an llms.txt, or context7) and against the API version the project targets (a version header, a /vN/ base path, or the SDK version, which can itself lag the live service). Verify service shapes from docs and schemas, never by making a live call to the endpoint. If a plan step relies on an API you cannot confirm (even a plausible one), do not implement it on faith: use a verified API or stop and flag it. Honor any project rule that already requires this.
- Make the smallest correct change that fully resolves the intent, following the plan when present. Match surrounding style and conventions. If reality diverges from the plan, do the correct thing and note the divergence.
- Change a signature, fix every call site. When you alter a symbol's signature (turning a function
async, changing its params or return type), it ripples to every caller. Grep the symbol and update each one. Beware the silent trap: a missed await leaves if (asyncFn()) / !asyncFn() testing a Promise, which is always truthy, so the gate goes dead, and tsc and most linters do NOT flag it. Confirm every call site reads the awaited value.
- Stay in scope: resolve this work-unit, nothing else.
4. Verify
Run the verify commands inside the working copy; fix anything you introduced. Some checks may not reproduce locally; note what you could and could not verify.
5. Commit
git -C <worktree> add -A
git -C <worktree> commit -m "<concise imperative subject; mention the id if there is one>"
Honor houseRules: no em dashes, no AI attribution. Do NOT push or open a PR; later stages do that.
6. Classify documentation impact (do not write docs)
For each configured doc job (config.docs.jobs), decide whether this change meets its trigger (appliesWhen): a user-facing capability / behavior / route / data-path change (a spec job), a reusable visual or design-system primitive (a design job), an architectural decision or boundary shift (an architecture job), and so on. Return the matching job names, or none. If the work-unit's plan carried a preliminary docNeed, treat it as a hint and confirm it against the actual change; you are the authority here, since you see what really changed. Most changes are none; do not over-classify. The doc phase runs the matching jobs later, so do not write docs here.
Output
- Standalone: report what changed (files plus a one-line summary) and the verification result.
- Called by the orchestrator: a structured result,
{ issueId, implemented, committed, summary, filesChanged, addedComments, verification, docNeed: [...], docRationale }. Set addedComments true only if you added or changed a code comment (it gates the comment-cleanup stage).