A plan.yaml is a needs spec that also says what each form collects
(and which stages a case may pass over). `portal-trainer build`
derives everything structural from it with no model involved:
needs.yaml, aggregates.yaml with the state machine read off `stages`
(walk the line, be turned down anywhere, succeed only from the end),
the front door, a followup page per need, a gated directory per group
holding its desk and the pages only that group may open, and every
desk button the machine allows.
The model is asked for words only, one page at a time, as a JSON object
whose shape is fixed by built-in fallbacks. Its strings are merged over
the fallbacks key by key, so a missing, malformed or partial reply
costs wording, never a working site, and it can neither add nor drop
structure. `via` in needs.yaml is filled mechanically from the heading
the words gave.
plans/contractor.yaml builds with no model into a site portal's
question_lint accepts: 6 needs met, 12 pages, 5 aggregates.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH