v0.26.0
Greenfield first-code generation: the planner can now author file bodies from scratch.
FIXED — greenfield plans no longer die in an unwinnable retry loop.
On a fresh child with an empty RAG index, a story whose targets are all op: create never
produced code. The JSON-embedded planner emitted PROSE NARRATION in a step's content field
("Create a Calculator component that handles the four operations.") instead of an actual file
body, and two failures compounded:
-
PREDICATE DIVERGENCE. The LLM-side executability check accepted any non-empty
content
string and called the planexecutable; the server-side create-coverage gate was stricter
and called the same target uncovered. The plan was simultaneously too complete to retry
usefully and too empty to execute, so it round-tripped asoutput_invalid/has_note_steps
until retries exhausted. No refinement could escape it — the planner cannot emit a whole file
body through the JSON channel, so re-asking just re-narrates. -
NO SYNTHESIS PATH FOR SOURCE FILES. Test files had an escape hatch (a focused raw-code LLM
call); source files had none. Greenfield is exactly the case where every file is a source
file being born.
CHANGES
-
NEW
isSynthesizedBody(content, filePath)inserver/plan-quality.mjs— ONE shared predicate
answering "is this a real file body?" for BOTH the LLM-side and server-side gates, so they can
no longer diverge. Rejects empty bodies, placeholder/comment-ONLY bodies, and prose narration in
code files. Deliberately conservative: it fail-safes to "this is a real body" when unsure,
because a false negative is catastrophic (a real component downgraded to a note, or a covered
target declared unauthorable → hard unrefinable failure) while a false positive is merely the
status quo ante. -
NEW
enrichCreateFileContentinllm/planner.mjs— synthesizes real file bodies via a focused
raw-code LLM call for anycreate_filestep the JSON planner narrated instead of authoring,
running UPSTREAM of every gate (critic, retry, coverage). Explicitly NOT gated ontestExemplar
the way the test-content enricher is: a fresh child has no exemplar, and the fresh child is
precisely the case this rescues. When synthesis itself cannot author the file, the step is left
untouched so the coverage gate fails LOUD and unrefinable — rather than swapping in another
unauthorable body and re-entering the loop. -
The placeholder rule is now a WHOLE-BODY test, not an unanchored substring match. A real
200-line component containing one incidental// TODO:is no longer downgraded to a note.
LLM-authored code carries TODOs routinely; that body is real and now stays executable. -
De-fragilized the witness tests: replaced source-grep pins (which assert nothing about behavior
and break on every refactor) with behavioral assertions against the real predicate, removed a
duplicated local mirror of the coverage rule, and killed asrc.slice(idx, idx + 2200)fixed
window that empties silently when the code above it grows — making every assertion below it
vacuously pass.