Skip to content

Latest commit

 

History

History
39 lines (20 loc) · 12.6 KB

implementation.md

File metadata and controls

39 lines (20 loc) · 12.6 KB

Implementation

Implementation is where the plan becomes code, and where your role changes. Through the earlier phases you led — describing, exploring, deciding, approving. Here the agents lead. An executor writes the code, a reviewer checks it, and you move to the reviewer's chair: approving completed work at gates, weighing in when something is flagged, and unblocking when the system needs a human call. This inversion is the whole point of front-loading the thinking. Because the decisions are already written into the spec and the plan, the build can run largely on its own, executing choices that were made deliberately rather than improvised mid-loop.

Implementation refuses to start without a completed plan, and it refuses to start quietly beside another session already writing or checking code. Document phases run in parallel as much as you like, but a checkout has one working tree and one index, so implementation and review take turns: a second one meets a red stop naming which topic the other session holds and how long ago it was active. You can go through it — the system can verify that a process is still running, never that the person driving it still cares — so the choice is handed to you on a stated condition: proceed only if you know that session has finished. Past that, before any code is written it settles the ground: it confirms that dependencies from other plans are satisfied, and it handles environment setup. The first time through, it asks whether there are any setup steps it should run first — copying an env file, running migrations, installing an extension — saves your answer so it never asks again ("no special setup" is a valid saved answer), and runs those steps exactly as given before touching a task. It also quietly discovers the project's linters and any project-specific skills, so they apply throughout. If a previous session was interrupted, resuming is automatic — the system re-derives where it was from the files and git history rather than its own memory.

The loop you watch

The plan is executed one task at a time, in dependency order. For each task the same cycle runs, and it opens by telling you what is coming: before any code is written, the task announces itself — its place in the plan, a sentence on what is about to change, and anything worth watching when it lands — so you know what you will be reviewing before the build starts.

An executor agent implements the task under strict test-driven development: it writes a failing test first, confirms it fails for the right reason, writes a complete implementation to pass it, refactors only while the tests stay green, and runs the linters. "Complete" is meant pragmatically — no hardcoded fakes that only satisfy the test, but no gold-plating beyond what the test asks for either. One rule is absolute: it must never edit a test to make broken code pass. Doing so would be admitting the implementation is wrong and hiding it, and hiding a failure is worse than showing one. The executor writes code and tests but never commits.

Then an independent reviewer agent, which did not write the code, checks the finished task on five fronts: does it conform to the spec, does it meet the task's acceptance criteria, is it tested well — flagging both under-testing and over-testing — does it follow the project's conventions, and does it fit the architecture. It returns either an approval or a list of needed changes, each pinned to a specific file and line.

Where you come in

You see the outcome of each task and hold the decision.

When the reviewer asks for changes, you see each issue told as what is wrong or at risk in the work — with the proposed fix, any alternative, and the reviewer's confidence — and choose: apply the fix and re-run the executor, turn on auto so future fixes apply without asking — for the rest of the session, or only to the end of the current plan phase — ask for the code-perspective retelling, ask for the findings drawn as diagrams, question the review, or comment — either guidance for the re-run, or a challenge if you think a finding is wrong. A challenge is adjudicated rather than argued past: a fresh reviewer re-examines the disputed findings against the code with your argument in hand, withdraws what does not survive it, and the verdict flips to approved when nothing blocking remains. There is no way to silently ship over a standing review — findings are either fixed or overturned. If a single task goes three rounds without resolving, the system forces this decision even if you had switched to auto, and shows you a convergence diagnostic — is the task actually converging, treading water, or diverging, with fixes spawning fresh problems? The cap exists so an unattended fix loop cannot thrash forever, and the diagnostic exists so that when it stops to ask, you can tell whether continuing is likely to help or whether something deeper is wrong.

When the reviewer approves, the finished task is retold in the product's terms — what it now does that it did not before, the decisions worth knowing, and how it was verified — rather than as a dump of implementation notes, with the code-perspective telling and a diagram view of what was built available on request. You decide whether to accept it, accept it and auto-accept the rest — for the session, or only to the end of the current plan phase — question it, or comment. Only on your acceptance does the system commit and mark the task complete. The task's code and its tests land as a single commit that names its files explicitly and stages nothing else, so the git history reads as a clean sequence of finished work, any single task can be found or reverted on its own, and nothing another session had in flight is swept in beside it. The bookkeeping that goes with the task — the plan's task state, the record of any fix rounds — is committed under its own scope rather than folded in with the code. And if a file the task changed was left out of that commit, the system is told which, and picks it up then and there rather than letting a forgotten path drift into the next task's history.

How the code gets written is the executor's call — the seam, the shape of a helper, what a component keeps — so it never stops to ask about any of that. It stops for one thing: a question about what the product does that the task, the spec sections it cites, and the code between them do not answer — including a decision in the spec that turns out not to be buildable, where the question becomes what the product does instead. When that happens the system goes to the record first: where the record settles the question, the spec is corrected in place, the answer goes to the executor, and you see a single line saying what landed. Where it is a genuine product call, the stop shows you the task, what the executor found — what the record decides, what the code does, where the two run out — and the options with a recommendation, each option's technical shape, its consequence for your users and its cost stated side by side; you pick one by number, and a comment is how you ask about them or push back. Your answer is written into the record before the executor runs again. On a quick-fix there is no discussion behind the work, so your answer is written straight into its specification. Where the question needs real discussion rather than a quick answer, it is sent to the mailbox of the discussion that owns it; implementation stops there and picks up from the menu once that discussion has decided. A failure — tests that will not pass, an environment that will not cooperate — is a different thing: you see what failed, what the executor tried, why, and what the next attempt should do, and you retry it, with a comment to ask about it or steer it. There is no skipping a task and no stopping the build from inside one — a task is finished or it is being fixed, and an environment you cannot fix today is left in progress for the next session to pick up. And if tasks remain but none are available to start, because something they depend on was skipped or blocked, the system shows you the blockage and lets you proceed, skip, or stop rather than stalling silently.

The plan is the authority, but it is not frozen. When something unplanned surfaces mid-build — you hit a bug while trying the system, notice a gap, or change your mind about a detail — just say so, at any point. Small course corrections pass straight to the executor as part of the current task, or amend a task that hasn't run yet. Genuinely new work is drafted as proper tasks and placed where it belongs — next, later in a phase, or at the tail, using the plan format's own priorities and dependencies — and you approve each one at the same gate you approve everything else. If what surfaced needs a decision the spec doesn't answer, that decision comes to you first; if you rule it out of scope, it is captured to the inbox rather than lost.

The phase boundary

While tasks are built one at a time, each was written in isolation — and things only visible once sibling tasks sit side by side (the same logic landed twice, two nearly-identical helpers, scaffolding a later task made dead) belong to nobody's task. The executor and reviewer note such opportunities as they work, banked rather than acted on. When a phase's last task lands, the phase closes through a consolidation sweep: a fresh agent reads what the phase built as a whole, verdicts everything banked along the way, and anything worth doing is put to you as a short proposal — the problem and what will be done about it, walked one at a time at the familiar gate with the same auto option. The rare proposal carrying an irreducible product fork — a call that changes what your users get, where the costs genuinely conflict and only you can break the tie — is put to you as an explanation built for the decision: what changes for your users, explained from scratch with examples, then the fork as two end states of the product with the consequence neither side escapes, and the sides as the menu with the recommended one first. It always stops, auto or not — that call is yours, never the machine's — and the code-perspective retelling of the record behind it is one option away. Anything the record or an investigation can settle is settled and presented plain, its reasoning stated. Only after you approve does an author write the full task detail; the tasks land in that same phase, build through the normal loop, and only then does the phase record complete. Where the sweep finds the specification itself has drifted from what was rightly built, the record is corrected in place with a dated note — you see a one-line count, never a ceremony. A sweep that finds nothing says so in one line and moves on. Quick-fixes skip this entirely — their plans never grow.

After the tasks

Building every task is not quite the end. Once the task list is drained, an analysis loop runs. The system takes a checkpoint — flagging any unexpected files first — then dispatches agents to review what was actually built against the plan and the spec, and a synthesiser proposes any remediation the review turned up. Every proposal names the failure it prevents — a finding that cannot is dropped, and a fix whose whole content is comment text is applied on the spot rather than planned. You approve those proposals the same way you approved the boundary's; the approved ones are authored into full tasks, written into the plan, and the build loop runs again over them. Build, analyse, perhaps build again — this repeats until the analysis finds nothing more. From the fourth cycle on a topic, however many sessions it took to get there, the system shows the convergence diagnostic and asks whether to continue or stop; it never silently gives up, and never silently loops.

The quick-fix variant

A quick-fix builds through implementation too, but under a different discipline suited to mechanical change. Instead of writing a new failing test first, the executor captures a passing test baseline, applies the change completely across every target file, then verifies the baseline still passes — fixing the change, never the tests, if something breaks. The reviewer switches to completeness criteria: were all the target files updated, do any occurrences of the old pattern remain, do the existing tests still hold. It does not demand new tests, because a mechanical change is verified by the tests that already exist. The gates and the one-commit-per-task rhythm are unchanged.

When the loop finds nothing left to do, implementation asks whether to mark itself complete and hands off to review for independent verification.