Lean output
No tools, no prose, no echo. The model writes only file edits and console blocks, then a footer.
Why: Every non-patch token is a token not spent on correctness. Prose corrupts the file stream and confuses reviewers.
Protocol Report · For Review
A deterministic, token-lean contract between a developer and an AI model for producing and applying code changes — where every rule exists for a specific reason, and nothing is included that does not earn its token.
The protocol governs three things: what the model is allowed to output, in which form it delivers changes, and how the reviewer verifies them. It replaces free-form chat with a machine-parsable patch stream.
No tools, no prose, no echo. The model writes only file edits and console blocks, then a footer.
Why: Every non-patch token is a token not spent on correctness. Prose corrupts the file stream and confuses reviewers.
Structural moves use one-line commands. Content changes use search/replace until cost crosses 70% of the file.
Why: Sending unchanged lines is waste; sending too few lines causes wrong matches. The threshold keeps both errors out.
Every structural change is a single named command with an :undo escape hatch and a machine-readable footer.
Why: Reviewers need the diff in plain English before they trust it. Silent structural edits are the number-one source of accidental breakage.
These rules define what the model is allowed to do. Each exists because omitting it introduced a concrete failure mode.
The model never runs, tests, or executes code. It writes the change directly.
Why: Execution is non-deterministic and unreviewable. The protocol is a patch format, not a runtime. Anything the model executes produces output a reviewer cannot diff or undo.
Before ### Changed files:, the model outputs only console blocks and file-edit blocks. No prose, labels, notes, or recap.
Why: The stream before the footer is parsed as a patch. Stray text corrupts file boundaries and produces broken or misapplied changes.
The model skips introductory sentences, restating the request, and summarizing what it just did.
Why: These lines carry zero information for the patch applier. They cost tokens, add latency, and risk being misparsed as file content.
The model plans once, writes once, and stops. It does not re-check, re-derive, or repeat a block.
Why: Re-derivation cannot improve an already-correct patch. It only spends tokens and introduces drift between what the model reasoned and what it wrote.
If a name, signature, or path changes, all its usages and imports are updated in the files the model has.
Why: Partial patches compile but fail at runtime or at import time. The reviewer should never have to finish the model's rename.
When the request is unclear, the model proceeds with the most probable interpretation instead of stalling.
Why: A stalling turn produces nothing. A wrong turn produces something the reviewer can correct in one follow-up. Something beats nothing.
If file content is missing, the model edits what it can and lists the missing paths under Need: after the footer.
Why: A guessed file looks plausible and then fails at review. A named missing path lets the developer fix the input in one step.
Structural changes happen only when the user asks, or when the request cannot be fulfilled without them.
Why: Structural changes break imports, CI paths, and review context. They must be explicit and auditable, never incidental to a content fix.
Every change has more than one valid representation. The protocol picks the one with the lowest total cost — measured in tokens, diff surface, and risk — that still produces a correct patch.
:rm <path|glob>
Why: One line, atomic, reversible. Writing a delete as a file edit would require sending the whole file just to prove it is empty.
:mv <src> <dest>
Why: A move is a path change, not a content change. Encoding it as a rename inside a diff is verbose and loses git's rename detection.
:rn <old> <new>
Why: Same reason as move, plus one rename command can update an extension or substring across many files at once.
:undo / :unrm <path>
Why: Structural mistakes are the most expensive to correct by hand. An explicit undo turns a destructive action into a reversible one.
Why: There is no prior content to anchor a search against. The full file is the only correct representation.
Why: S/R sends only the changed lines. Full file sends everything. S/R wins unless the cost rule says otherwise.
S/R ≥ 70% of file
Why: Below 70%, S/R is cheaper than the full file. Above 70%, the patch is essentially the whole file, so sending it whole is simpler and less error-prone.
Why: A search string that matches more than once either fails or silently edits the wrong location. Without a unique anchor, the full file is the only safe format.
Why: A file that does not fit in one reply cannot be sent whole. S/R is the only viable format regardless of cost.
S/R · empty replace
Why: Deleting lines is a content change, not a structural change. S/R with an empty replace is the smallest correct form.
Structural operations are single, named, logged commands. They appear in one fenced block before the footer, and they are the only place where moves, renames, and deletes live.
| Command | Effect | Why it is a command |
|---|---|---|
:rm | Remove path or glob | Removing a file must be explicit, auditable, and reversible. |
:mv | Move file or directory | Preserves git rename detection and keeps imports traceable. |
:rn | Rename file, extension, or substring | One command can update a symbol across many files without touching content. |
:undo | Undo last structural op | Structural mistakes are the costliest; undo makes them cheap. |
:unrm | Restore deleted file | Recovery for the only operation that destroys content. |
:mv -f / :rn -f | Force overwrite | Overwriting must be explicit; the flag keeps it intentional. |
Order matters. Structural commands run first (:mv/:rn), then file edits use the new paths, then :rm runs last.
Why: Edits must reference paths that will exist after the move, and removals must not race with edits that still need the old file.
Content changes follow one of two formats: a full file, or a numbered search/replace under a single file header.
--- File: <path> ---
Why: The header is the parser's only signal that a new file begins. Multiple headers for one file would split its edits across unrelated blocks.
src/app.js, src/App.vue
Why: Absolute paths break on other machines. Missing extensions make file type ambiguous and defeat language-specific tooling.
The search block should match exactly once — usually 1–3 lines, max 12.
Why: Longer searches are safer but cost more. Below 12 lines we can afford context; beyond that, the search itself becomes the bulk of the patch.
Spaces, tabs, and blank lines are preserved exactly. Never use ellipses or placeholders.
Why: A single wrong space makes a search fail silently. The model must reproduce the file, not paraphrase it.
If two changes are separated by two or more unchanged lines, they get separate edits.
Why: Unchanged lines in the middle increase cost and make the anchor non-unique. Separate edits are cheaper and clearer.
Edits that touch or sit within one line of each other are one block.
Why: Two adjacent edits would overlap or fight over the same anchor. One block applies both deterministically.
Edit 1, 2, 3, each applied to the file after the previous one.
Why: The reviewer reads top-to-bottom and can undo to any numbered checkpoint. Global numbering would be meaningless because each file is independent.
Each turn edits what the previous turns produced. The final commit is all turns applied in order — later turns override earlier ones on the same lines, and untouched lines stay exactly as they were.
If a line changed in Turn 1 changes again in Turn 3, the Turn 3 value wins.
Why: This mirrors how a human iterates: each edit supersedes the last.
After :mv, :rn, or :rm, all subsequent edits reference the new paths.
Why: Editing the old path after a move targets a file that no longer exists.
If a prior turn was wrong, the next turn sends the smallest search that isolates the wrong lines.
Why: Re-sending unchanged code costs the same as the original patch and obscures what actually changed between turns.