spec-site: what the build measures, and what it refuses ======================================================= Captured 2026-09-20 20:57 UTC on `solomon`: Linux 7.1.9-1-MANJARO x86_64, AMD Ryzen 9 5950X 16-Core Processor, 32 threads Python 3.14.7 -- the data pass, standard library only node v26.7.0, npm 12.0.2, astro 5.18.2 One command runs the lot: the data pass, Astro, the budgets, and the assertions against what was built. Budgets live at the top of scripts/build_site.py. --- the measured build -------------------------------------------------- $ ./scripts/build_site.py 15:57:16 [content] Syncing content 15:57:16 [content] Synced content 15:57:16 [types] Generated 110ms 15:57:16 [build] output: "static" 15:57:16 [build] mode: "static" 15:57:16 [build] directory: /site/dist/ 15:57:16 [build] Collecting build info... 15:57:16 [build] ✓ Completed in 143ms. 15:57:16 [build] Building static entrypoints... 15:57:19 [vite] ✓ built in 2.31s 15:57:19 [build] ✓ Completed in 2.46s. generating static routes 15:57:19 ▶ src/pages/c/[slug].astro 15:57:19 └─ /c/docs-spec-site/index.html (+27ms) 15:57:19 ▶ src/pages/evidence/[slug].astro 15:57:19 ├─ /evidence/docs-evidence-spec-site-build-txt/index.html (+11ms) 15:57:19 └─ /evidence/docs-rtsmart-boot-log-txt/index.html (+10ms) 15:57:19 ▶ src/pages/index.astro 15:57:19 └─ /index.html (+15ms) 15:57:19 ✓ Completed in 89ms. 15:57:19 [build] 4 page(s) built in 2.75s 15:57:19 [build] Complete! ....... ---------------------------------------------------------------------- Ran 7 tests in 0.025s OK docs/spec-site 6 requirements 5 grounded 1 unverified 1 of 6 requirements unverified wrote /site/src/data/specs.json $ npm run build --prefix site /site/dist: 4 pages, 47711 bytes, 6.48 s (budgets: 8388608 bytes, 120.0 s) ok (exit 0) --- budgets ------------------------------------------------------------- MAX_BUILD_SECONDS = 120.0 measured 6.5 s ~18x headroom MAX_OUTPUT_BYTES = 8 MiB measured 47 KiB ~176x headroom Set high on purpose. A cold GitHub runner pays Node start-up and a Vite build that a warm 5950X does not, and the capability taxonomy in .skills/k230-spec-change/SKILL.md allows fifteen capabilities where this tree has one. A breach should mean something changed -- an evidence file the size of a video, or a build that started doing real work -- not that the numbers were always tight. A budget raised reflexively means nothing. A forced breach names both numbers: $ ./scripts/build_site.py --max-bytes 1 error: output is 44891 bytes against a budget of 1 bytes --- the build refuses to guess ------------------------------------------ Run over a scratch tree staging every capability the open proposals will add. Three of their requirements declare neither an UNVERIFIED marker nor a Grounding citation. The build will not call them grounded: $ ./scripts/render_specs.py --repo $SCRATCH/preview error: openspec/specs/image/boot-chain/spec.md: requirement 'The hardware boot path differs from the emulated one, and that difference is recorded' declares no verification status: it carries neither an `` marker nor a `*Grounding: ...*` citation error: openspec/specs/image/sd-layout/spec.md: requirement 'Flashing names the target by a stable identifier' declares no verification status: it carries neither an `` marker nor a `*Grounding: ...*` citation error: openspec/specs/system/nixos-config/spec.md: requirement 'The system boots to a console prompt' declares no verification status: it carries neither an `` marker nor a `*Grounding: ...*` citation error: 3 requirement defect(s); the data was written so the site can show them, but the build failed image/boot-chain 3 requirements 1 grounded 1 unverified 1 undeclared image/cross-build 2 requirements 1 grounded 1 unverified image/sd-layout 2 requirements 0 grounded 1 unverified 1 undeclared system/console 2 requirements 2 grounded 0 unverified system/kernel 1 requirements 1 grounded 0 unverified system/nixos-config 4 requirements 1 grounded 2 unverified 1 undeclared display/panel 2 requirements 1 grounded 1 unverified display/touch 2 requirements 1 grounded 1 unverified docs/spec-site 6 requirements 5 grounded 1 unverified 8 of 24 requirements unverified, 3 undeclared wrote $SCRATCH/preview/specs.json (exit 2 -- the data is still written, so the site can show the defects) --- tests --------------------------------------------------------------- $ python3 -m unittest discover -s tests -p 'test_render_specs.py' Ran 18 tests in 0.044s OK $ python3 -m unittest discover -s tests -p 'test_site_output.py' Ran 7 tests in 0.037s OK --- deployment ---------------------------------------------------------- .github/workflows/spec-site.yml runs the same command on every push to main and publishes site/dist to GitHub Pages at https://knewter.github.io/tdisplay-k230/. Run 35537228320: every step of the build job green on ubuntu-latest -- dependencies, the data-pass tests, the build with its budgets and assertions, and the Pages artifact uploaded. The deploy job then failed at actions/deploy-pages, because GitHub Pages has never been enabled on the repository. An earlier run tried to enable it from the workflow (actions/configure-pages with enablement: true) and was refused: the Actions token is not permitted to create a Pages site. That is a repository setting, not something CI can do, and the step was removed so that a setting cannot fail the build itself. To finish it, once: 1. github.com/knewter/tdisplay-k230/settings/pages Build and deployment -> Source: GitHub Actions 2. if that is not selectable, settings/actions -> Workflow permissions -> Read and write permissions 3. re-run the Spec site workflow, or push anything to main Until a deployment completes, the requirement 'The published site is current without anyone maintaining it' stays UNVERIFIED. That is the correct output, and it is what the site itself says on its own page. ===================================================================== 2026-09-22 00:22 UTC: the deployment completed, and a push moved it ===================================================================== Pages was enabled on the repository after the note above was written, and the URL has been serving since. What had never been observed is the part the requirement actually asks for: that a push to main moves what the URL says, with nobody doing anything else. Observed over one push, from a machine that is not the build host, with curl: before HTTP 200 "generated 2026-09-21 02:55 UTC" "1 of 11 requirements is unverified" 3 capability links push e70934a to origin/main at 2026-09-22 00:21 UTC after HTTP 200 (last-modified: Tue, 22 Sep 2026 00:22:01 GMT) "generated 2026-09-22 00:21 UTC" "1 of 18 requirements is unverified" 6 capability links Under a minute from push to served page, and the count moved because the spec tree moved. Also checked live, all 200: /hardware/panel-lit/ /hardware/touch-reports/ /evidence/docs-evidence-panel-photos-05-console-on-panel-jpg/ /evidence/docs-evidence-flicker-after-headroom-revert-md/ /c/system-console/ /evidence/docs-evidence-panel-photos-05-console-on-panel-jpg.jpg 26667 bytes, image/jpeg -- byte-identical in size to the committed docs/evidence/panel-photos/05-console-on-panel.jpg The other half of the requirement -- "a build that fails SHALL NOT be published" -- was demonstrated in the least welcome way available, and is recorded here as an INFERENCE rather than an observation because the Actions logs were not read. The 02:55 UTC build above is the one the URL served for the whole of 2026-09-21, across five pushes to main. From 77d65e1 onward the tree held six capabilities and eighteen requirements, and the served page said three and eleven. Running the same command locally on that tree exits 2: two requirements opened "*Grounded on hardware. ...*" rather than "*Grounding: ...*", which classifies as undeclared. A non-zero build step stops the upload step after it, so no artifact was uploaded and Pages kept serving the last good one. The behaviour is what the requirement asks for. The cost of it -- a day of a published count that was correct-when-written and wrong-by-then, with nothing on the page to say so -- is recorded here because it is the argument anyone reopening that decision will need. 2026-09-24: evidence and proposal dashboard growth budget ======================================================== Source 30c73fc4 now builds 259 pages, compared with four in the original measurement. A local build of the same site content at b9f393cf produced 8,366,045 bytes in 20.23 seconds. The twelve output assertions passed; blob-scan correctly caught two native captures missing machine MANIFEST rows despite having prose inventory entries. This change adds those rows. Measured output by extension: HTML 6,634,157; PNG 1,319,682; JPEG 256,899; CSS 67,044; WebP 41,900; SVG 31,153; JavaScript 15,210 bytes. The largest page is the work dashboard (2,538,098 bytes), which includes local proposal details and evidence links. The largest log page is the USB enumeration record (870,164 bytes). This is accumulated evidence and local detail content, not a newly bundled video or JavaScript dependency. Set the aggregate output ceiling to 16 MiB to allow the requested ongoing proposal/media publication. Retain the 120-second build ceiling, evidence checks, binary inventory and output assertions. This aggregate ceiling is not a per-page load budget; the large dashboard warrants a separate payload/loading improvement as proposal history grows. 2026-10-05: continued committed evidence exceeded aggregate budget ================================================================= Exact master b90a5318d11290f27e6d47dcc3284b9da060d3c6, Spec site run37258512080, failed the aggregate size check after Astro and all twelve output assertions passed. The deploy job was skipped. Measured620 pages, 16,784,105 bytes,20.53 seconds; enforced budgets16,777,216 bytes/120 seconds. The failed run remains at: https://github.com/knewter/tdisplay-k230/actions/runs/37258512080 The previous growth audit counted259 pages. New committed proposal and text evidence pages exhausted its aggregate16 MiB headroom; this change adds no media or dependency. Set the enforced aggregate ceiling to32 MiB, approximately twice the measured output, retaining the120-second ceiling, evidence checks, binary inventory and output assertions. This is an aggregate site growth allowance, not a per-page performance claim. The large dashboard still warrants a separate loading/payload improvement. Exact corrected CI/deployment must be inspected after this commit; this measurement records the failed build, not a successful new publication. Subsequent correction210735d7854114f612358b9f87dcae57668396da passed Spec site run37258852614 including deployment:620 pages,16,785,273 bytes, 20.32 seconds, enforced33,554,432-byte/120-second limits. The published https://knewter.github.io/tdisplay-k230/work/ returned HTTP200 with exact 210735d7854114f612358b9f87dcae57668396da in its artifact-index revision. https://github.com/knewter/tdisplay-k230/actions/runs/37258852614