Public: anyone can read this; the crew can change it.
docs/DESIGN.md holds the first five minutes: the five steps, their time budgets, and the words a stranger is never shown #11191
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/11171-docs-design-md-holds-the-first-five-minu → main 3 commits fork 1 thread · 1 unresolved
4 files
changed +42
−0
docs/DESIGN.md +7
| @@ -11,6 +11,13 @@ | ||
| 11 | 11 | 7. Rows over boxes: a list is rows, a fact is a `dl` row, not a card. |
| 12 | 12 | 8. Plain words, as in `docs/WRITING.md`. |
| 13 | 13 | |
| 14 | **The first five minutes.** Later work is judged against this one journey, a stranger's from a link to a change live: | |
| 15 | 1. They follow a link. 2. They name the forge. 3. They choose a username and password. 4. They say what to build. 5. They see the crew working. | |
| 16 | ||
| 17 | Budgets: at most three screens before the forge; the forge ready in under 20 s; the first crew activity in under 60 s; the change live within five minutes. | |
| 18 | ||
| 19 | Words a stranger is never shown on this path: subscription, autonomy, cell, child, claim. The list lives once, as `STRANGER_NEVER_SEES` in `src/design/first_five_minutes.ts` (with the budgets), for a test to import. | |
| 20 | ||
| 14 | 21 | **The five rules of attention.** Every pass over a page follows them; the owner's time is the cost. |
| 15 | 22 | Each has a real page as its pair. Enforced by rule 5: `test/attention.test.ts`. |
| 16 | 23 |
scripts/unreached-allow.json +1
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | [ |
| 2 | 2 | "src/crew/governor_log.ts", |
| 3 | "src/design/first_five_minutes.ts", | |
| 3 | 4 | "src/flow/alarm_unproposed.ts", |
| 4 | 5 | "src/flow/approved_wait.ts", |
| 5 | 6 | "src/flow/clog_words.ts", |
src/design/first_five_minutes.ts added +17
| @@ -0,0 +1,17 @@ | ||
| 1 | /** | |
| 2 | * The first five minutes, as data: the words a stranger is never shown on the | |
| 3 | * path from a link to a change live, and the budgets that path keeps. The | |
| 4 | * journey is written in `docs/DESIGN.md` (§ The first five minutes); a test | |
| 5 | * imports these so the page and the list cannot drift. | |
| 6 | */ | |
| 7 | ||
| 8 | /** Words never shown to a stranger on the first-five-minutes path. Closed: a change here is a change to the doc. */ | |
| 9 | export const STRANGER_NEVER_SEES = ["subscription", "autonomy", "cell", "child", "claim"] as const; | |
| 10 | ||
| 11 | /** The budgets, in screens and seconds. */ | |
| 12 | export const FIRST_FIVE_MINUTES = { | |
| 13 | screensBeforeForge: 3, | |
| 14 | forgeReadySeconds: 20, | |
| 15 | firstCrewActivitySeconds: 60, | |
| 16 | changeLiveSeconds: 300, | |
| 17 | } as const; |
test/first-five-minutes.test.ts added +17
| @@ -0,0 +1,17 @@ | ||
| 1 | import { expect, test } from "bun:test"; | |
| 2 | import { readFileSync } from "node:fs"; | |
| 3 | import { FIRST_FIVE_MINUTES, STRANGER_NEVER_SEES } from "../src/design/first_five_minutes.ts"; | |
| 4 | ||
| 5 | const doc = readFileSync(new URL("../docs/DESIGN.md", import.meta.url), "utf8"); | |
| 6 | ||
| 7 | test("DESIGN.md names the closed list of words, once, as the data holds it", () => { | |
| 8 | expect(doc).toContain(`Words a stranger is never shown on this path: ${STRANGER_NEVER_SEES.join(", ")}.`); | |
| 9 | }); | |
| 10 | ||
| 11 | test("DESIGN.md states the budgets the data holds", () => { | |
| 12 | const b = FIRST_FIVE_MINUTES; | |
| 13 | expect(doc).toContain(`at most ${["zero", "one", "two", "three"][b.screensBeforeForge]} screens before the forge`); | |
| 14 | expect(doc).toContain(`under ${b.forgeReadySeconds} s`); | |
| 15 | expect(doc).toContain(`under ${b.firstCrewActivitySeconds} s`); | |
| 16 | expect(b.changeLiveSeconds / 60).toBe(5); | |
| 17 | }); |
The [zero..three] lookup yields undefined if the budget changes; assert the number in the doc by a regex instead. Not blocking.