Workflow
How a change goes from a branch to the Worker and the sidecar, and which check proves which claim. The rules behind each check are in AGENTS.project.md.
One roof
Docs are claims about the repo, and each claim has one check. Every markdown check reads the doc through scripts/md.ts, one Bun.markdown pass that returns headings, links, images and tables, so a doc parses the same way whichever check reads it.
| Claim | Written in | Proven by | Bun API |
|---|---|---|---|
| A cited image exists and decodes | Any doc, as a markdown image or an <img> tag. docs/dashboard.md also names a capture for every route in docs/goal.md and every /desk?screen= URL | bun run cli proof | Bun.markdown, Bun.Image |
| An image table row is right | docs/dashboard.md (Format, Size, Bytes) | bun run cli proof (--write fixes it) | Bun.markdown, Bun.Image |
| A design token has this value | docs/design.md | bun run cli design | Bun.markdown, Bun.Glob |
| Code reads only tokens that exist | src/ | bun run cli design | Bun.Glob |
| Every served route is documented and visited by axe | docs/goal.md, docs/endpoints.md, bun/a11y-check.ts | bun run cli contract | Bun.markdown |
| Each page has one name, nav label, key and head; hotkeys never collide; each theme has a palette; every heading, key hint, table label, column label, empty message, link value and storage key is read from the map | docs/site.md (GFM tables and a task list of flags), src/lib/site.gen.ts (--write regenerates) | bun run cli site, bun run cli contract | Bun.markdown |
| What is public matches the published docs | public/llms.txt, public/docs/manifest.json, public/manifest.webmanifest (--write regenerates) | bun run cli contract | Bun.markdown, Bun.CryptoHasher |
| Every identity surface names the app the same way | site.json, head, manifests, llms.txt, README, package.json | bun run meta:audit | |
| Title, description, spelling, doc links | src/lib/og/site.json, docs | bun run meta:audit | |
| Repo rules (hosts, pins, secrets, boundaries) | AGENTS.project.md | bun run guard | |
| Behavior | Tests | bun run test, bun run test:node | bun:test |
The same pass draws /docs. scripts/docs-plugin.mjs runs Bun.markdown.react on each doc in PUBLIC_DOCS when the app is built, because the Worker has no Bun, and src/components/docs/doc-view.tsx renders the tree with the token classes every screen uses. A doc is published only when it is on that list. The app has no sign-in, so docs that name hosts, accounts or secrets stay off it. A link to a doc that is not published shows as plain text. public/llms.txt and public/docs/manifest.json are committed snapshots of that list, with each doc's outline and a SHA-256 of its source, so editing a published doc means running bun run cli contract --write and committing the result. The pre-commit hook runs cli contract --staged, which reads the staged copy of every file, and the gate runs cli contract.
bun run gate runs all of them and refuses a regression against gate.baseline.json. Nothing deploys from a commit the gate has not passed.
A change, start to finish
- Branch from an up-to-date
main. One change per branch: a fix, a feature, or one dependency upgrade. - While editing, run the fast checks.
bun run cli design,bun run cli proofandbun run cli contractfinish in well under a second. - A UI change that shows on a documented screen gets a new capture of that screen.
docs/dashboard.mdlists them, one row for every route indocs/goal.mdand every data screen. Capture withbun run cli shot capture <url> --out screenshots/<name>.png --width <w> --height <h>, then runbun run cli proof --writeso the table matches the file. - A new color, size or radius is a row in
docs/design.mdand a line in each theme block ofsrc/styles.css. Components use the token, never a hex value. A page name, nav label, hotkey, URL value, heading, subtitle, table label, storage key, theme or flag changes indocs/site.md, by hand or withbun run cli site set/flag, never in a component. - Run
bun run gatebefore pushing. The pre-commit hook runs the guard. Pre-push runsgate --reuse, except under the Cursor hook dispatcher, which does not forward pre-push. - Open the pull request with what changed, how it was checked, and the gate line it printed. Merge into
main. - Ship the Worker and the sidecar from the same
maincommit:bun run deploy:cf, thenbun run deploy:sidecar. Both rungate --reusefirst.
Order of work
Land open pull requests before starting a cross-cutting branch. A branch that touches every screen, like a token or layout pass, conflicts with every branch still open, and the gate baseline moves under each of them.
After that, unify one surface per branch, smallest first, each with its own capture and gate run:
- Tokens. Every color, size and radius comes from
docs/design.md, proven bycli design. - Shared parts. Every page shares
BrandandNavLinks. A new shared part is one branch, with a capture. - One wall. Fold the F402 tape into the command center, as
docs/standing.mdlists under Next.