Feature Lists Are a Harness Primitive, Not a To-Do List
Feature Lists Are a Harness Primitive, Not a To-Do List
Most people hand an agent a paragraph. "Build the checkout flow: cart, payment, receipt email, and an admin refund view." Then they wonder why the loop wanders — half-finishing three things, re-deciding scope every iteration, marking the whole thing "done" when the receipt email was never wired up. The paragraph looks like a spec. It isn't one. It's prose, and prose is the wrong material for the one file the loop leans on hardest.
The Anatomy of an Agent Loop already lists the memory file — IMPLEMENTATION_PLAN.md, tasks.md, progress.txt — as one of the five parts. This is the part underneath that one: not that you keep a plan file, but what happens when that file stops being narrative and becomes a structured, machine-checkable list of discrete units with a pass/fail state on each. That's the move the "Learn Harness Engineering" course makes in its lecture on feature lists as harness primitives, and it's a genuinely good one — worth reading in full alongside this. The framing is right: the feature list is infrastructure, not a note.
Prose to-do list vs. structured feature list
The difference isn't formatting taste. It changes what the loop can and can't do on every iteration.
| Prose to-do list | Structured feature list | |
|---|---|---|
| Scope boundary | "the checkout flow" — the agent re-interprets it each run | one row = one slice; the agent picks the next pending item and stops |
| "Done" | a judgment call, re-litigated every iteration | a per-item state (pass / fail / pending) with a defined check |
| Survives context reset | no — the reasoning that decided scope lived in a flushed window | yes — it's state on disk, not a memory of a conversation |
| What the verifier grades | "the whole diff" against a vague goal | this one item against this one item's acceptance check |
A prose list is re-read and re-understood every run, which means it's re-decided every run. A model with a fresh context window and a paragraph will not reliably re-derive the same scope you had in your head — it'll find a plausible boundary, which is not the same as the right one. A structured list removes the decision. Row three is pending, its acceptance criteria are written next to it, so the agent does row three. Nothing to interpret.
Why "state, not narrative" is the whole point
The reason this is a primitive and not a nicety is context loss. An agent forgets everything between runs, and often within a long run. A prose plan encodes progress as narrative — "I've started the payment integration and I think the cart is mostly done" — and narrative doesn't survive a compaction. A feature list encodes progress as flags. cart: pass. payment: fail (Stripe test key rejected). receipt_email: pending. That reads identically to a fresh agent, a resumed agent, and a human at 9am. It's the difference between a diary and a control panel — and a diary is exactly what the anatomy guide warns the memory file must never become.
This is also why the plan file wants explicit pass/fail rather than checkboxes a human ticks. A checkbox says a human looked. A fail with a reason says the check ran and the item isn't done — which is a thing the loop itself can act on next iteration without asking anyone.
The feature list is what the verifier grades against
Here's the connection that makes it load-bearing rather than tidy. A loop's quality lives in its verifier — the separate grader that didn't write the code. Hand that verifier a paragraph goal and a full diff, and you've asked it to grade "is all of this good?" — the vaguest possible question, the one it'll answer with plausible-looking approval. Hand it a feature list, and each row becomes its own gradeable unit: does the diff satisfy receipt_email's acceptance check — an email actually sent on order completion — yes or no? That's a question with an evidence-backed answer. The list is what turns one unbounded grading call into a series of bounded, checkable ones.
The same structure feeds the Plan stage in The Claude Code Harness: the plan file is where approved slices live, and the feature list is that plan made checkable. Work happens only against approved rows. The agent doesn't freelance a fifth feature nobody asked for — adding one is a plan-file edit, which makes scope creep a visible, reviewable diff instead of a silent surprise in the output.
Where to see it
The rows aren't abstract — they're lines in a file the agent reads before it touches code, and the verifier reads before it grades. Strip the branding off "spec-driven," "feature-list," and "task-graph" harness write-ups and they're describing the same file: discrete units, a state per unit, a check per unit. The loops in the directory that grade well almost all ship one; the ones that don't are usually the ones handed a paragraph and asked to know when they're finished. Start from a graded one, and copy the list before you copy anything else.