Why feature lists are harness primitives
A feature list is not a memo. It is the shared data structure that tells the scheduler what to run, the verifier what counts as done, and the handoff what state exists.
Notes from Learn Harness Engineering - Lecture 08
Agents do not share your definition of done.
If you ask for an e-commerce site without a feature list, the agent may stop when the code looks plausible. You meant: users can browse products, add to cart, and complete checkout end-to-end.
Memo mode
Progress is stored as ambiguous prose. A later session has to infer what passed, what failed, and what was only started.
Primitive mode
Each feature has behavior, verification, and state. A later session can resume from the next unresolved item without re-implementing finished work.
One usable feature row has a triple.
Missing any field turns the row back into a note. The behavior tells the agent what to build, the verification tells it what proves completion, and the state tells every harness component where things stand.
POST /cart/items with product_id and quantity returns 201.not_started, active, blocked, or passing.The list becomes a state machine.
The agent can work on a row, but the harness owns state transitions. The only path from active to passing is a successful verification command with evidence.
not_started
Scheduler chooses the next item from the queue.
active
The agent works on that one item and requests verification.
blocked
Dependency or environment issue prevents a valid pass check.
passing
Verifier ran the command successfully and attached evidence.
PASS-STATE GATING: agent requests -> harness verifies -> state updates
Why it must be a primitive
Documents can be ignored. Primitives are system inputs. Like a database constraint, a feature list constrains what can happen rather than merely advising it.
Scheduler
Reads states and picks the next not_started feature.
Verifier
Runs that row's verification command and controls pass transitions.
Handoff reporter
Generates session summaries from the same state table.
Progress tracker
Tallies state distribution and shows remaining project pressure.
How to apply it
Use structured Markdown or JSON.
Keep the file in the repo and make it machine-readable enough for tools to parse.
Give every item an exact check.
Prefer end-to-end behavioral verification over "code exists" or "no syntax errors."
Let tools update pass state.
The agent can request verification, but it cannot mark its own work as passing.
Write the rule into agent instructions.
Put feature-list location, WIP limit, and pass-gate policy in CLAUDE.md or AGENTS.md.
{
"id": "F03",
"behavior": "POST /cart/items returns 201",
"verification": "curl ... | jq .status == 201",
"state": "active",
"evidence": "commit abc123, test output log"
}
Calibrate granularity to one session.
Too broad
"Implement the shopping cart" hides several behaviors and is unlikely to finish cleanly.
Right size
"User can add items to cart" is a behavior that can be implemented and verified in one session.
Too narrow
"Create the name field on the Cart model" creates management overhead without user-visible completion.