grounded
The site is rendered from the specs, and only from the specs
The accepted-spec ledger SHALL be generated from openspec/specs/ and SHALL NOT be hand-maintained. A separately labeled public work board MAY show committed in-flight proposals, but SHALL identify them as drafts and SHALL NOT include their requirements in the accepted-spec ledger or its verification tally.
Building SHALL be a single command, and it SHALL be the same command locally and in CI, so that what a person sees before pushing is what gets published.
groundingscripts/render_specs.py walks openspec/specs/**/spec.md and reads nothing else, on the Python standard library alone. scripts/build_site.py is the one command; the workflow runs it and nothing else. docs/evidence/spec-site-build.txt records both. The existing accepted ledger test excludes in-flight change identifiers from index and capability pages. docs/evidence/spec-site-work-board/README.md records the focused work-board tests and the published page at revision 95595a8e.
evidence in this repository scenarios A capability's spec is edited
- WHEN a spec file changes and the site is rebuilt
- THEN the change appears, with no other file edited by hand
An in-flight change exists
- WHEN the site is built while proposals are open
- THEN the accepted-spec ledger and requirement tally exclude it, while the separate work board may link to it with a visible draft label
grounded
The site leads with what is unproven
Every requirement SHALL be shown as either grounded or unverified. The landing page SHALL state how many requirements are unverified before it presents anything else.
This is the site's reason to exist. On this board the documentation and the hardware disagree routinely — a datasheet described a working radio whose enable line is never driven, and a vendor page described the Wi-Fi as an ESP32-S3 that the schematic contradicts. A reader's first question is which claims have been observed, and the site SHALL answer it without being asked.
groundingthe landing page's <h1> is the count itself, emitted before any capability is named. Tests against the built site assert that the count's position in the HTML precedes every capability name and every section heading, and that the number printed matches what the spec tree actually contains rather than what the page claims. Status is carried as a colour on every requirement and as one proportional bar summarising the whole tree, in both light and dark.
scenarios A reader opens the site
- WHEN the landing page is loaded
- THEN the number of unverified requirements is visible before any capability's prose
A requirement carries an UNVERIFIED marker
- WHEN a requirement is marked unverified
- THEN it is rendered as unverified wherever it appears, and its stated reason is shown alongside it
grounded
Evidence is reachable from the requirement it grounds
Where a requirement cites a path under docs/, the site SHALL link to that file. A boot log or photograph that grounds a requirement SHALL be one click from it, for a reader on the web and not only in a checkout.
A path named only inside an <!-- UNVERIFIED --> marker is not a citation. Those markers routinely name the evidence that would ground a requirement, which has not been captured yet, and treating that as a citation would report a missing file for every requirement honestly waiting on one.
groundingcited files are rendered into the site as pages of their own, and listed on the landing page under "Evidence on file". A test walks every built page and asserts that every link resolves to a file that exists. Another asserts that a cited path has a page. docs/rtsmart-boot-log.txt reaches the site with the two NUL bytes a serial capture left in it shown rather than removed.
evidence in this repository scenarios A requirement cites a committed boot log
- WHEN that requirement is rendered
- THEN the cited path is a working link to the committed file
A requirement cites evidence that does not exist
- WHEN a cited evidence path is missing from the repository
- THEN the build fails and names the requirement and the missing path
grounded
The renderer fails rather than guessing
The site depends on conventions carried in prose — the <!-- UNVERIFIED --> marker and the citation of a read path as grounding. Where the build cannot determine a requirement's verification status, it SHALL fail and name the file and the requirement, rather than rendering it as grounded.
A silent default would make the count of unverified requirements untrustworthy, and that count is the only reason to build this.
Failing SHALL mean a non-zero exit that names every such requirement. It SHALL NOT mean withholding the site: the output is still written, and a requirement that declared no status is shown on it as a defect, in its own colour, with the capability it came from. A front door that reports "three requirements never said" is more useful than no front door, and a defect nobody can see is one nobody fixes.
Quoting a convention SHALL NOT count as using it. A requirement discussing the marker inside a code span is not thereby unverified.
groundingdocs/evidence/spec-site-build.txt records a run over a staged tree in which three requirements declare neither a marker nor a citation: the command names each one and exits non-zero, and the page it wrote carries them under "Build defects". Unit tests assert that the classifier raises on a requirement carrying neither rather than returning grounded, and that a marker quoted in a code span is not read as a marker — a bug the first real build produced, which reported two grounded requirements as unverified.
evidence in this repository scenarios A requirement's status cannot be determined
- WHEN the build meets a requirement it cannot classify
- THEN the build fails and names the file and the requirement
The build has failed on an unclassifiable requirement
- WHEN a reader opens the site that build wrote
- THEN the requirement is shown as a defect rather than as grounded, and the capability it belongs to is named
grounded
The build stays fast and small
Generation SHALL complete within a recorded time budget and the output SHALL stay within a recorded size budget, both enforced by the build. The budgets SHALL be set above what the tree currently produces, so that a breach means something changed rather than that the numbers were always tight.
groundingdocs/evidence/spec-site-build.txt records the date, the machine, the Python, Node and Astro versions, and the measured build. The budgets in scripts/build_site.py are set well above it, with the headroom stated and the reason for it. A test forces a breach and asserts the failure names the measured value and the budget.
evidence in this repository scenarios The site grows past its budget
- WHEN generation exceeds its time or size budget
- THEN the build fails and reports the measured value against the budget
grounded
The published site is current without anyone maintaining it
The site SHALL be published at a URL, and that URL SHALL be rebuilt from openspec/specs/ on every push to the default branch. A reader SHALL NOT have to clone the repository or run anything to learn what is unproven.
A build that fails SHALL NOT be published. The count on the URL is only worth reading if it could not have been published while the specs were in a state the build rejects.
groundingobserved from a machine that is not the build host, over one push. Before: https://knewter.github.io/tdisplay-k230/ served "generated 2026-09-21 02:55 UTC" and "1 of 11 requirements is unverified". Commit e70934a was pushed to main at 2026-09-22 00:21 UTC. Fifty-odd seconds later the same URL served "generated 2026-09-22 00:21 UTC", "1 of 18 requirements is unverified" and six capability pages, with nothing else done by anyone. Recorded in docs/evidence/spec-site-build.txt, which also records that the previous day's failing builds were not published — the URL served the last good build across five pushes while the tree was in a state the build rejects — as an inference from what the URL served rather than from the CI logs, which were not read.
evidence in this repository scenarios A change is archived and pushed
- WHEN
openspec archive adds a capability and the commit reaches the default branch - THEN the published site shows that capability, and its requirements in the count, without anyone rebuilding anything
A push carries a requirement the build rejects
- WHEN the build fails on that requirement
- THEN the previously published site is left standing, and the failure is attributed to the commit that caused it
grounded
A public work board explains what remains
groundingdocs/evidence/spec-site-work-board/README.md records the host layout and link checks and the published four-lane page at revision 95595a8e.* The documentation site SHALL provide a touch-readable work board with planned, in-progress, verification/review, and shipped/archived lanes. Each work item SHALL show its task progress, next concrete action or evidence gate, dependencies, and links to committed proposal, accepted spec, or evidence where available. Where source code has landed but physical proof remains, the two states SHALL be distinct. A checked task count alone SHALL NOT imply shipment, deployment, or physical verification.
evidence in this repository scenarios A reader looks for remaining work
- WHEN a reader opens the work board on a narrow touch screen
- THEN the reader can scroll through each lane and identify the next action and evidence gate for an open item
Source is landed but board proof is pending
- WHEN an item's committed source is awaiting physical verification
- THEN the card shows both facts and remains outside the shipped/archived lane
unverified
Work cards expose their visual evidence
why it is unverified host-browser and published-site proof is recorded in docs/evidence/work-card-media/README.md; this is not physical K230 grounding.
The work board SHALL discover committed images and videos associated with a change's cited evidence, show a representative visual cover when available, and present the discovered media inside that card's detail view. Videos SHALL provide playback controls, start playback when opened or selected in the media viewer, and support Space to toggle play/pause without closing it. Card previews SHALL remain paused. Captions and evidence-class labels SHALL not imply physical validation from mockups or automated captures. Changes without visual evidence SHALL remain readable text cards.
scenarios Screenshot and video arrive during implementation
- WHEN screenshot or video evidence is committed for an open change and the site publishes that revision
- THEN the card and detail view expose the new media without waiting for task completion or archive
A reader opens a card
- WHEN the reader clicks the card outside its evidence links or activates its primary link by keyboard
- THEN the existing inline detail view opens with its media and documents, without a separate View details button
Enlarge media while reading a card
- WHEN the reader activates an image or the enlarge action for a video in the card detail
- THEN a gallery modal displays that media at the largest size that fits the viewport while preserving its aspect ratio, supports adjacent-media navigation by touch swipe and arrow keys, and returns to the same card position when closed