Skip to content

Projects

Solution · Project 4 — A Fix Loop with a Real Checker

Reference solution. Read the project first.

Reference solution. Read the project first.

Worked example

Target: an internal @acme/shared-utils TypeScript package consumed by three services. A zod-schema bump broke type inference on parseRequestBody<T>, and CI (lint, typecheck, unit) is red across all consumers.

Attempt 1:

$ git worktree add ../fix-attempt-1 fix/type-error-1
$ cd ../fix-attempt-1 && opencode run "Fix the type error CI flagged in src/parse.ts only."
# edits src/parse.ts's generic constraint
$ npm run lint && npm run typecheck && npm test
# typecheck passes; ONE unrelated unit test now fails — a snapshot depending on the old inferred type

Checker verdict (separate session, diff + CI log only, no edit access):

FAIL — typecheck now passes, but tests/parse.snapshot.test.ts regressed. The fix
narrowed the generic in a way that changed a public return type. Recommend
attempt 2 constrain only the internal helper, not the exported signature.

fix-state.md:

| Attempt | Worktree | Verdict |
| --- | --- | --- |
| 1 | ../fix-attempt-1 | FAIL — snapshot regression from a public-signature change |
| 2 | ../fix-attempt-2 | PASS — lint+typecheck+tests all green, no public API change |

Attempt 2 scoped the fix to the internal helper only, per the checker's note; CI went green with no other test movement. The loop stopped and reported fix/type-error-2 for human review — it did not merge.

Why this satisfies "done when"

  • Attempt 1's worktree is deletable garbage — the main checkout, and the other two worktrees, never saw its edits.
  • The checker session had no access to attempt 1's reasoning, only the diff and CI output — which is exactly why it caught a public-API side effect the maker's own "typecheck passes" framing missed.
  • The loop stopped at a PASS and named a branch — merging stayed a human's call.

Common wrong turns

  • Running the "checker" as a follow-up prompt in the same session as the fix — it will tend to agree with itself, because it still has the maker's framing in context. Start a fresh session with only the diff and CI log as input.
  • Auto-merging on PASS — the project's own done-when is explicit that the human gate is the branch hand-off, not the merge.