Plan review

Coding with a model is a collaboration, and a collaboration needs a moment where both parties agree on what is about to happen. PounceCode puts that moment between the plan and the first write.

The loop

the shape of a turn
1 2 3 4 5 6 7 8
request — what you asked for, kept verbatim │ plan — a separate model call, clean context │ REVIEW — held here; every write tool is refused │ run — step by step, each in its own context report — refused unless every criterion has evidence

Planning is its own call

The plan is not written by the model mid-turn. It is a separate call with a clean context, and it defaults to the working model because planning is the most reasoning-heavy moment in the job. You can point it at a different profile if you want a stronger model to plan and a cheaper one to execute.

Why clean context matters. By the time a model reaches the point where it would plan, its context holds the system prompt, the sources it read, the conversation and a pile of tool output. Asked to "write your plan" from there, it ratifies what it has already decided. Asked fresh, it plans.

The gate is real

Holding a plan is not a prompt instruction. While a plan is awaiting review, the tool registry refuses every dangerous and every write tool at the point of execution, whatever the model believes it is doing.

Enforced where tools run

An earlier version checked the hold inside the task tool. A model that skipped the task board and called write_file directly walked straight past it. The check now sits in the registry, so there is one place to get right and no way around it.

Reads stay open

The hold stops writing, not thinking. The model can keep reading files and searching while it waits, so answering a question you raise about step 3 does not require approving the plan first.

What you can do to a plan

ActionEffect
ApproveReleases the gate and resumes the turn immediately — no need to type "go ahead".
Edit a stepRewrites the step's text. The model works from your wording, not its own.
Drop a stepRemoves it. Useful when it has planned work you have already done.
Add a stepInserts something it missed.
CheckpointMarks a step to stop at. The run pauses there for another look.
RejectSends it back to plan again, with your reason.

Checkpoints you did not have to ask for

A step that deletes, drops, deploys, pushes, resets or force-anythings gets marked as a checkpoint automatically. Approving a plan is agreement about direction, not a blank cheque on its most expensive step.

Matching on the verb, not the text. This looks at what the step's leading verb is, not whether a dangerous word appears somewhere in the line. The substring version marked "write a README with install instructions" as irreversible, and a checkpoint that fires on nothing teaches you to click through checkpoints.

When it asks

Three settings, per profile:

SettingBehaviour
offNever hold. The plan is still drawn and still tracked — you just are not asked.
askHold when there is a reason to: the plan touches something irreversible, or the working tree is already dirty. The default.
alwaysHold every plan, every time.

A dirty tree counts as a reason because an agent's changes and your uncommitted ones are hard to separate afterwards, and the moment to notice is before rather than during.

While it runs

A task list you can watch

Steps tick off as they complete, with the current one marked. Open it, collapse it, leave it open — it is a panel, not a wall of text scrolling past.

A notification when it needs you

A plan waiting for review raises a notification, and approving it clears the notification. If you stepped away, the thing waiting on you is the thing that tells you.

It tells you when it stops

The end of a run is marked with how long it took — so "did that finish?" has an answer that is not "scroll up and guess".

Reporting has to show its work

A plan carries acceptance criteria, and the report is refused while any step is still open or any criterion lacks evidence. A criterion marked unmet with a reason is accepted — silence is not. The failure this exists to catch is a model reporting success it did not achieve, which is also why the app's own benchmark checks the disk rather than reading the model's reply.