Read first, in this order:
.specify/memory/constitution.md— the rules. Every PR must comply; plans justify deviations.docs/data-model.md— the shared data model.src/schema/is its executable form.specs/<feature>/— the Spec Kit artifacts for the feature you are working on (spec.md,plan.md,tasks.md). Mark tasks[x]intasks.mdas you complete them.
docs/architecture.md has the layout and data flow, docs/development.md the full command
reference, CONTRIBUTING.md the rules for data and code pull requests. README.md is the public
front page and advertises the lab; keep working notes out of it.
pnpm install— Node 22, pnpm 10.pnpm dev— dev server on http://localhost:4321.pnpm validate:data— schema and cross-reference checks overdata/. Run after any data edit.pnpm check— validate:data, lint (Biome), typecheck, unit tests, build. Must pass before a push.pnpm test:e2e— Playwright againstastro preview(runpnpm buildfirst). Screenshot baselines live intests/e2e/__screenshots__and must come from Playwright's pinned Chromium:pnpm test:e2e --update-snapshotswith that build, or therefresh-screenshotslabel on the pull request (seedocs/atlas-maintenance.md). Update them only for intended changes.pnpm observe <server> <feature> <status> --by <handle> --evidence <url|note>— appends one validated manual observation (docs/atlas-maintenance.md). Observations are never edited.pnpm check:append-only— fails if an existing observation entry was edited or removed.pnpm scan <url>|<server-id>|--all [--write]— the passive scanner (docs/scanner.md). The only command in the repo that contacts a third-party server;--writeappends observations.
- Data is YAML under
data/, one entity per file; observations are append-only lists per server. - Every feature cites a spec revision and section; the build fails on a dangling citation.
unknownis a real status. Never render missing data asunsupported.- Explorer scenarios live in
data/scenarios/, one file each; every step and toggle cites a revision and section, and the diagram, the step list and the token views are all rendered from the one definition. A toggle is its own static page; one toggle at a time. src/scanner/is the only code that may contact a server, and only throughpnpm scan(run by the scheduled job or a contributor); the site build never imports anything that fetches. There is no on-demand scanning for visitors. Seed data isvendor-claimormanual; scanner cells arrive by pull request.- One token system:
src/styles/tokens.css. Components use tokens, never literal colours. Colours are OKLCH pairs resolved withlight-dark();data-themeonly flipscolor-scheme. Type is Geist for headlines, text and interface, Geist Mono for ids and code. Shared surfaces (.card,.button,.pill,.level,.kv,.field,.crumbs,.eyebrow) live insrc/styles/global.css; reuse them before adding page-local styles. - One page skeleton: every page is a left-aligned
.wrapcolumn that opens withheader.page-head(eyebrow, h1,.lede, optional.page-head__metaline, optionaldl.factsrow) and closes a data page withfooter.page-foot. Pages below/mcp/and/standards/put<Crumbs>above the head; long-form text pages usesrc/layouts/Document.astro(numbered sections, a rail of them on wide screens, no breadcrumb). New pages take these before inventing a head of their own. - Status glyphs come from
StatusCell: observed statuses are filled chips, a recordedunknownis a dashed ring, a derived one (no observation) a faint dot. Keep that distinction. - Islands only where interaction needs them. Pages must read fully without JavaScript.
- The site is an early preview.
src/layouts/Base.astroshows a work-in-progress banner (.wip) above the header on every page; keep it until the owner says the site is out of preview, then remove it in its own PR. Nothing else depends on it.