02 / Teaching harness
Harness from scratch
A coding agent is two pieces glued together. The model proposes the next step. The harness is the small runtime around it: it asks Allow before any write, runs only what was allowed, and proves done by reading the disk itself.
2026 · Teaching repo · not a product
- Problem
- Most writing about agents starts at the product surface. The actual job is smaller. The model proposes. The harness allows, writes, and proves. People skip that boundary.
- Approach
- One task people can hold: create hello.txt containing exactly ok. FakeModel first, no API key. Optional live guest on the same Allow, write, and byte-check path. The model never writes the disk and never decides that the run succeeded.
- Shipped
- Runnable proof script, tests for success and failure, JSONL transcripts, interactive Allow, argv-only run_command, teaching memory, and a journal TUI. A tutorial, not a product.
What Part 1 proves
This repo is that loop in Node 22 with zero third-party packages. FakeModel needs no network. An optional OpenAI-compatible guest shares the same Model.decide boundary. Deny and timeout never reach the write. Model prose never counts as done.
Success is boring on purpose. Tests pass. workspace/hello.txt is exactly the two bytes ok. The transcript ends on stop with proof.exactBytes true.
The boundary that matters
Allow is a gate, not a vibe. FixedGate keeps CI deterministic. InteractiveGate is the human y/N path. Tools are confined: write_file inside the workspace, run_command as an argv array with shell false.
Later slices stay honest: JSONL resume after an observation, working / episode / durable memory without pretending to be RAG, and a TUI that is a journal projection, not product chrome.
What this is not
This is a teaching harness. It is not DeepHarness, not a SaaS, and not a claim that you should replace Cursor or Claude Code. A companion article stays unpublished until I cut it. The tree is the runnable tutorial.
If you want the loop without the folklore, clone it and run ./run-proof.sh.
- Node 22
- TypeScript
- zero deps