Nine phases of building pieces that pointedly did not touch each other. Phase 10 of kodr is where they finally connect, and the harness does the thing it has been pretending it cannot do: take a prompt and produce file changes.
This is the payoff phase. Nothing new and clever - just wiring.
The loop
A run now goes:
- Run a prompt against the local model.
- Save the usual artifacts: prompt, context, response, summary, raw response.
- Try to extract a proposal from the response -
{ "files": [{ "path": "...", "content": "..." }] }- using the defensive JSON extractor, because the model will absolutely wrap it in prose. - Push the proposed writes through the safe-write gate and record the result in
writes.json. - With
--yes, actually apply the writes (and the backups that come with them). - With
--test, run an allowlisted check afterward and record it intests.json.
Read that list back and it is basically a table of contents for the last five posts. Defensive extraction, context packing, safe writes, verification - each was built and tested in isolation precisely so that this phase could be boring. The whole loop is glue.
Dry-run is still the default
The important default: nothing applies unless I say --yes. A bare run extracts the proposal, diffs it, writes writes.json, and stops. Apply is an explicit opt-in, every time. Untrusted model output does not get to modify files because it felt like it - it gets to propose, and I get to look.
The fake-model test infrastructure from way back in phase 03 earns its keep here too: I can drive the entire loop deterministically without a real model in the picture, and assert that dry-run leaves files untouched while apply writes them and records backups.
The bug, naturally
The first test run failed - and it was my own fault in a very on-brand way. An old phase 04 assertion checked the exact list of artifacts a run produces. Phase 10 added writes.json and tests.json to that list, and the exact-match assertion fell over. The fix was trivial (update the expected artifact map), but the lesson is the recurring one in this repo: an exact-match assertion is a tripwire you are guaranteeing your future self will hit. Recorded in failures.jsonl with the rest.
So: a real, local, prompt-to-patch coding loop, running against a model on my own machine, with a dry-run default and a path jail standing between it and anything destructive. Small, but it actually works.
Links:
- Phase doc: phases/10-proposal-flow.md
- Kodr post: blog/10-proposal-flow.md
- The wiring: src/app.mjs