The feasibility audit is the substance and lives at docs/CRUMB-PREFILL-FEASIBILITY-2026-08-09.md. This plan is the build order, and it does not restate the audit.
Where the work lands. Most of it is in grain/packages/crumb (the parser grammar, the client, the lint), which is a different repo, so this plan tracks the portfolio half: the tours, the standard, the one registered field surface, and the e2e that holds it. CRUMB is a published package, so nothing here reaches the live site until the npm token clears (grain-0-1-18-bump).
The one thing to settle before code. Prefill is a write, and CRUMB's design law says the tour never writes. The audit recommends amending the law to "writes only through the door, and never submits" rather than carving out an exception. Settled, and settled before P2 needed it: the amended law is the one design law in docs/crumb/WRITE-A-TOUR.md.
Phases
- [x] P0. Fix the route comparison in
crumb-live.js. Done 2026-08-09, crumbcore/nav.tsplus a drift-guarded mirror in the client. A step'satmay now carry query state and reaches it in one navigation. Verified in a browser against the local package: one navigation for the query-state step, and the URL settles. - [x] P1. The tour that writes the next prompt. Done 2026-08-09. The reserved
## promptsection, rendered as the card after the last step in both presentations, composed live, offered as a readonly field that selects on focus plus a handoff button when the host loaded grain'shandoff.js.check.tsfails an ask the template never uses. Walked in a browser, both presentations, and the tour for it iscontent/tours/review-prompt-card.md. - [x] P1b. The portfolio e2e, and the publish it waits on. Done 2026-08-10. The gate lifted without anyone announcing it:
@tjakoen/crumb0.1.9is on the registry, pinned here with a real integrity hash, and it ships all three ofneedsNavigation, the prompt card andprefill. So this phase turned out to be the e2e alone, and it covers P2 as well rather than P0 and P1 only. Twelve cases ine2e/crumb-prompt-and-prefill.e2e.ts, all green, against the two real review tours rather than fixtures. The loop regression is held by counting document navigations, which is the only assertion that tells a fixed hop from a loop that happens to be paused when the expect runs. Three things the walk taught that the plan had wrong:crumb.starthonours the tour's ownroute:and goes home first, so no test may jump straight to a step on another page; the popover has no step list, so the only way to the prompt card is Next off the last step, the way a reader gets there; and the compose panel is not measurably visible inside the frame presentation, so P2's walk is the popover, which is also the presentation a visitor uses. The refusal is held too, and it needed the honest sequence: stage, type over the draft (which strips the door's ink), re-render, and the card stops claiming the field. - [x] P2. Prefill one registered field through the door. Done 2026-08-10, the portfolio half. The law question was not a blocker in the end: it was settled before this phase started, and the amended law already stands in
docs/crumb/WRITE-A-TOUR.md, soTOUR-STANDARD.mdonly gained the authoring rule that falls out of it (a step that stages state says so in its own prose, because a staged screen otherwise reads as one the app reached by itself). The pilot tour iscontent/tours/say-hello.md, three steps, ending onfield:contact-messagewith a staged draft. Getting there needed a fix nobody had planned: the compose panel starts collapsed and CRUMB has no flow verbs, so/mail#composehad to actually open the panel on a cold load before a tour could reach the field at all. That is now one reveal function with two callers, and it fixes a real defect for people too, since the panel's own href had only ever worked after a click.prefillis documented indocs/crumb/WRITE-A-TOUR.md. The walk was unverified when this phase closed and is not any more: the pin turned out to be past the key already, so P1b's e2e covers this phase too. Walking it found one thing the tour had claimed wrongly, and the step's verify line now says so, because Back leaves /mail entirely and so can never be the test of whether your own words survive. - [x] P3. Preset a page's own state via URL state. Done 2026-08-10, on the calendar's feed. The page picked itself: its three filter tabs were the only real page state on the site that a person could reach and a link could not, and unlike the mail folders (the other candidate) the feed is a pure filter over a server-rendered list, so the same address gives everyone the same view. The tab now lives in the URL as
?feed=notes|all, read on boot and written back on every click with the same replaceState the notes feed already uses for?tag=. The default drops the parameter, an unknown value lands on the default rather than an empty page, and every parameter the island does not own is carried through, because a tour arrives with its own. That last detail is what makes the preset honest: a person clicking a tab produces the address, soat: /calendar?feed=notesasks for nothing a visitor could not have asked for. The tour iscontent/tours/review-calendar-feed-state.md, walked in a browser: one navigation, the URL settles, the Notes tab is selected on arrival, twelve note cards visible and nine hidden. Four e2e cases ine2e/calendar.e2e.ts, and a fifth spec that had been red since the tabs landed inc359d35is green again, fixed by the very thing this phase built. Cost: two hours, no new CRUMB vocabulary, no new verb. Unlike P1 and P2 this needed nothing unpublished, so its e2e is committed green rather than parked behind the pin. - [ ] Deferred: flow verbs. No
drawer.openortab.selectuntil a real change needs one.
Verification
Each phase owes a dev tour, per LOOP section 4a, and P1 is the first phase whose own output is a tour feature, so its tour doubles as the demonstration.