@bongos/core 1.24.58 → 1.24.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.bongos-core.json CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/bongos/package-core.js",
5
- "core_version": "1.24.58",
6
- "core_contract": "1.24.58",
7
- "source_commit": "5d0373a2fc9f96cfacd4488757826a5ebd6942b4",
5
+ "core_version": "1.24.59",
6
+ "core_contract": "1.24.59",
7
+ "source_commit": "a6ac4e31607a82978349eba6f0d2c113bdc48345",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-11-07T14:15:06.231Z",
9
+ "built_at": "2026-11-07T15:21:01.170Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 638,
13
13
  "agent_docs_stubbed": 32,
14
- "functional_verbatim": 3897,
14
+ "functional_verbatim": 3900,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 4568,
20
- "tree_sha256": "e12981ebf9b882c4a0e83b648d1b5319525ddb38ab10765143743eef0b9a1f2e",
19
+ "file_count": 4571,
20
+ "tree_sha256": "0d58836fc7200aa61d37a68fc94e1fef65ba9556f5afb9e9c7105fcc474f0d4b",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2472,7 +2472,7 @@
2472
2472
  {
2473
2473
  "path": "docs/architecture.md",
2474
2474
  "mode": "0000644",
2475
- "sha256": "351c01f41d4149c64f3b729f2fb55c7ba52e7202cc97c8621f120ba95f7c9fd6"
2475
+ "sha256": "58b03efd477eb60e66022cce2e4adda65a359d20ee992c6bceb3320a995322c5"
2476
2476
  },
2477
2477
  {
2478
2478
  "path": "docs/branding-contract.md",
@@ -3007,7 +3007,7 @@
3007
3007
  {
3008
3008
  "path": "docs/module-api-changelog.md",
3009
3009
  "mode": "0000644",
3010
- "sha256": "51ac2ca6bc7322d551ec3374877f213009191c23df9f967f5a7b0996a17fb7d3"
3010
+ "sha256": "b68ba24d900494bac49e77694a228c04794d1c0b5a43c4733159ee5429cbec4f"
3011
3011
  },
3012
3012
  {
3013
3013
  "path": "docs/modules-contract.md",
@@ -3097,7 +3097,7 @@
3097
3097
  {
3098
3098
  "path": "docs/page-readings.json",
3099
3099
  "mode": "0000644",
3100
- "sha256": "73b2e41788d1a41b8ccc2bdda733cf9cd136aeb44b7b5f972184dc807ff4e5a2"
3100
+ "sha256": "16e8909e4de1207587056fece1ee2fc2455778f569d3338043fd6bc5eb05543d"
3101
3101
  },
3102
3102
  {
3103
3103
  "path": "docs/project-context.template.md",
@@ -3192,7 +3192,7 @@
3192
3192
  {
3193
3193
  "path": "docs/recipes/ops-gotchas.md",
3194
3194
  "mode": "0000644",
3195
- "sha256": "6baf5e52b156463f928d084b6eb9f0974d9a9e620d4eb40802cad3f42f5d1982"
3195
+ "sha256": "99193931238d13b50918ddc794136a3f5a499ef384cd5ff227c64a5cbb5dc116"
3196
3196
  },
3197
3197
  {
3198
3198
  "path": "docs/recipes/overnight-builder.md",
@@ -11332,7 +11332,7 @@
11332
11332
  {
11333
11333
  "path": "modules/status-ui/public/style.css",
11334
11334
  "mode": "0000644",
11335
- "sha256": "22d0198fb04024732ea119397c1d63163d1293811232d19c3cc1ccecba9c51df"
11335
+ "sha256": "84b2a0c1e49eef8a7f87a586f250afce3a7c89d54a4211a0ac52820e3de63929"
11336
11336
  },
11337
11337
  {
11338
11338
  "path": "modules/ui-design/CLAUDE.md",
@@ -11702,12 +11702,12 @@
11702
11702
  {
11703
11703
  "path": "modules/ui-design/public/brand.css",
11704
11704
  "mode": "0000644",
11705
- "sha256": "02e8b06b640a7eebd905ecac18bde4b22b5718c0cde8d6abe3c99b17f6230e96"
11705
+ "sha256": "4d80b05a7f569217a96df00e2c11a8005e540730d67ea94f0d2fa7fe66303343"
11706
11706
  },
11707
11707
  {
11708
11708
  "path": "modules/ui-design/public/brand.html",
11709
11709
  "mode": "0000644",
11710
- "sha256": "718ed7bf511946f9878a894d6019cf5ae667b970c7e45371515c357310ceb9fb"
11710
+ "sha256": "9bd01c16060a9624f3f1e0e4467ca7b4da4df3b7527c8b005a669b331b171d1a"
11711
11711
  },
11712
11712
  {
11713
11713
  "path": "modules/ui-design/public/brand.states.json",
@@ -11759,6 +11759,11 @@
11759
11759
  "mode": "0000644",
11760
11760
  "sha256": "e168fdd0f4ac94754af089e7240be7cbba46704b36a617252f2942c97e8835e2"
11761
11761
  },
11762
+ {
11763
+ "path": "modules/ui-design/public/brand/png-sources.json",
11764
+ "mode": "0000644",
11765
+ "sha256": "6181696f80b70fab9daadc14f77963093223387ecff5d4f13b9e1f63e1c6ad6f"
11766
+ },
11762
11767
  {
11763
11768
  "path": "modules/ui-design/public/tokens.css",
11764
11769
  "mode": "0000644",
@@ -11777,7 +11782,7 @@
11777
11782
  {
11778
11783
  "path": "modules/ui-design/scripts/gen-design-reference.js",
11779
11784
  "mode": "0000644",
11780
- "sha256": "f372163aa83a75e5d9ec5650d28e6a1c11a43c084a5db16d4284bbd60b68e70e"
11785
+ "sha256": "d59b046a2aabda513d2d580a574c74ae43b04e97c847315c16eaa2ab50144ffb"
11781
11786
  },
11782
11787
  {
11783
11788
  "path": "modules/ui-design/scripts/gen-design-tokens.js",
@@ -11897,17 +11902,17 @@
11897
11902
  {
11898
11903
  "path": "package-lock.json",
11899
11904
  "mode": "0000644",
11900
- "sha256": "ff15a28e3b58b826fdf033ea0320275c687447782431dfe1e0932d36731af282"
11905
+ "sha256": "38c4ec31d6cb51fd92185003e550832f29d0e44f18f3a2df2b7d3594bdca972e"
11901
11906
  },
11902
11907
  {
11903
11908
  "path": "package.json",
11904
11909
  "mode": "0000644",
11905
- "sha256": "8e6ce0901458e4035f4387b5bccff0893029342324492322e44f00a5be1689db"
11910
+ "sha256": "0a9fbd43bcf2caa7e6c2b6faeef134a0dc96d7c5f1ee29519edf5d48ffb78db9"
11906
11911
  },
11907
11912
  {
11908
11913
  "path": "public-docs/index.html",
11909
11914
  "mode": "0000644",
11910
- "sha256": "e2be4b4b58abe21333727c23fd953a238edb4c8e6c087e2aacbfbef0271a496a"
11915
+ "sha256": "6ec35589784910e09c362401b3e0468b90cbe58c56754d6e6d7e4353a8083444"
11911
11916
  },
11912
11917
  {
11913
11918
  "path": "public-docs/redoc.standalone.js",
@@ -11922,7 +11927,7 @@
11922
11927
  {
11923
11928
  "path": "release-notes.json",
11924
11929
  "mode": "0000644",
11925
- "sha256": "6fc3843a52303a6b7759157432db6166ef692a9d5fba2b51cb2d078788caa3f1"
11930
+ "sha256": "9735ab47bbd28140534686e37156442e586d1a7c5abce86f23ab0d546c9da0a7"
11926
11931
  },
11927
11932
  {
11928
11933
  "path": "scripts/bongos/CLAUDE.md",
@@ -12297,7 +12302,7 @@
12297
12302
  {
12298
12303
  "path": "scripts/bongos/design-generators-fresh.js",
12299
12304
  "mode": "0000644",
12300
- "sha256": "f417e0ffcc884b018748a7f17062f52a6f247b8364ea4471efc97dd476143db3"
12305
+ "sha256": "a51d725286fa198505ff57ceceb50412ffa18e9f659c88cbe01d501bac8da9f5"
12301
12306
  },
12302
12307
  {
12303
12308
  "path": "scripts/bongos/design-sync.js",
@@ -12517,7 +12522,7 @@
12517
12522
  {
12518
12523
  "path": "scripts/bongos/gen-brand.js",
12519
12524
  "mode": "0000644",
12520
- "sha256": "529c51487ccf9e5b302fd361343224db202f1d1f9726b7e2bfe2864dd54b34ca"
12525
+ "sha256": "bc3ce6eebc646e7f2359ef2495a99878e060d7b41c27673833d824d428a379bd"
12521
12526
  },
12522
12527
  {
12523
12528
  "path": "scripts/bongos/gen-diagrams.js",
@@ -15302,7 +15307,7 @@
15302
15307
  {
15303
15308
  "path": "scripts/status-mirror-sync.js",
15304
15309
  "mode": "0000644",
15305
- "sha256": "be3152e3d9afc3c6ef81a8e059ef0b24e717b52bffd2a4f00f5df0bccb70516a"
15310
+ "sha256": "41628e240bb4f5c9840f1ce3839d1a299df8cacd54b2706f4151dcda53e7495b"
15306
15311
  },
15307
15312
  {
15308
15313
  "path": "src/asset-version.js",
@@ -15672,7 +15677,7 @@
15672
15677
  {
15673
15678
  "path": "src/bongos/routes/auth.js",
15674
15679
  "mode": "0000644",
15675
- "sha256": "1591c366d5504c821d7a2dc31d160b09733ad8b51abbece6188da6f6f8e9f6b3"
15680
+ "sha256": "6348ee00e6e60d899f3e98bc55a75e6b3f88562fcda7a1655a4d4df1c2273393"
15676
15681
  },
15677
15682
  {
15678
15683
  "path": "src/bongos/routes/backup.js",
@@ -15807,12 +15812,12 @@
15807
15812
  {
15808
15813
  "path": "src/bongos/serve-internal.js",
15809
15814
  "mode": "0000644",
15810
- "sha256": "2eb8bc66efdb69b965baae62bf6e2271910da8f791fb0dc39f7a5fc7ef5594a3"
15815
+ "sha256": "0d5a45ed0f8b8f907169a886504749887a659fbd2bdff23c28fa8146c3742a05"
15811
15816
  },
15812
15817
  {
15813
15818
  "path": "src/bongos/sign-in-pages.js",
15814
15819
  "mode": "0000644",
15815
- "sha256": "c8cb78f67fce5c42bbe896207d1a0d323215592a36c5d231d7f586e41479b409"
15820
+ "sha256": "cfd8a09da90e8f2a176e94c960736bbb295c216a1d6bf1f8027f7f0ce1ceacc8"
15816
15821
  },
15817
15822
  {
15818
15823
  "path": "src/bongos/software-update.js",
@@ -15832,7 +15837,7 @@
15832
15837
  {
15833
15838
  "path": "src/brand-mark.js",
15834
15839
  "mode": "0000644",
15835
- "sha256": "bd45563a5fe3cf9aee5dfddffd8d34d8898842e3871280b3fe924ec9fe7a4c16"
15840
+ "sha256": "5484f9ff087a0d28d076f5079c49aaa55e704ba52e60be03a9454e3b8fc4b3c8"
15836
15841
  },
15837
15842
  {
15838
15843
  "path": "src/branding.js",
@@ -15847,7 +15852,7 @@
15847
15852
  {
15848
15853
  "path": "src/error-page.js",
15849
15854
  "mode": "0000644",
15850
- "sha256": "08fc77867dd4f9709cbf1983dabcddfd0e8835c728695a71762ac8ec106f1e66"
15855
+ "sha256": "ddfd55f0581a32e31b26624e0e981b1768af896f7edc962bc1779eb05f64ccba"
15851
15856
  },
15852
15857
  {
15853
15858
  "path": "src/hall-look.js",
@@ -15872,7 +15877,7 @@
15872
15877
  {
15873
15878
  "path": "src/module-api.js",
15874
15879
  "mode": "0000644",
15875
- "sha256": "fda44df6daf88d610dcbfb9d9c9f98e4da9d00cc09759adebfe7e598daa845b4"
15880
+ "sha256": "06c54ea826895a4de9a90970d7b72e6479fada3880d45e1c1f164f29e7c319c5"
15876
15881
  },
15877
15882
  {
15878
15883
  "path": "src/module-loader/catalog.js",
@@ -15939,6 +15944,11 @@
15939
15944
  "mode": "0000644",
15940
15945
  "sha256": "1565fab25ca23066a460ef35f3693a56186fdc03f5461d3fc891b528d185885c"
15941
15946
  },
15947
+ {
15948
+ "path": "src/theme-markup.js",
15949
+ "mode": "0000644",
15950
+ "sha256": "7efca13206ba049b5958bcfdbb674e14e67ff4e8c1ddb33f0729bcbd6de4624f"
15951
+ },
15942
15952
  {
15943
15953
  "path": "tests/abandon_creator_authz.mjs",
15944
15954
  "mode": "0000644",
@@ -16662,12 +16672,12 @@
16662
16672
  {
16663
16673
  "path": "tests/brand_mark.mjs",
16664
16674
  "mode": "0000644",
16665
- "sha256": "2b052667e604a1b0570353c2ce09016b7dd8716dee0acf8fa982d380dc8ec641"
16675
+ "sha256": "68ff85560c05b7426139527cea3832429e17da4b64c96bbc26ba46c02305d97e"
16666
16676
  },
16667
16677
  {
16668
16678
  "path": "tests/brand_surfaces.mjs",
16669
16679
  "mode": "0000644",
16670
- "sha256": "6c8a84bda7dc9bfa4e10eadc6a9e489ba9847bd632f10eda0cafe33bcbcdcb63"
16680
+ "sha256": "26684884f85c8ad99966ae4f7713552cc12709c0d41100b3d7a5b60b8d50c9af"
16671
16681
  },
16672
16682
  {
16673
16683
  "path": "tests/branding.mjs",
@@ -17402,12 +17412,12 @@
17402
17412
  {
17403
17413
  "path": "tests/design_counts_ratchet.mjs",
17404
17414
  "mode": "0000644",
17405
- "sha256": "99d6c3b98b6ec839fe4b4856ab081bc6b19e96a39b4db4be0c155eb2e09e4ed0"
17415
+ "sha256": "2fd9ecdc86bb0a9b2392db350568eb4776a27b3d3bd43e896686475707a61a85"
17406
17416
  },
17407
17417
  {
17408
17418
  "path": "tests/design_reference.mjs",
17409
17419
  "mode": "0000644",
17410
- "sha256": "64a500720aa3d0179700366ce948a93a84dcf4e975a4e261ff95eb6575412c0e"
17420
+ "sha256": "809766d9baedf5ed420935d3c94c7e1bcb27cfd46c307792cd556ea7eb4f24af"
17411
17421
  },
17412
17422
  {
17413
17423
  "path": "tests/design_tokens_generated.mjs",
@@ -22814,6 +22824,11 @@
22814
22824
  "mode": "0000644",
22815
22825
  "sha256": "486bb5b4af30db3ab3a6a0f047edf60a9d4ec5a70cb1c19cebbd1fcd89578799"
22816
22826
  },
22827
+ {
22828
+ "path": "tests/wordmark_and_faces.mjs",
22829
+ "mode": "0000644",
22830
+ "sha256": "bb1ac8d5fd24e2ea073b768298acbe4bcc55ca5f2e25d36d9904fdcd18037ac8"
22831
+ },
22817
22832
  {
22818
22833
  "path": "tests/work_board_live_refresh.mjs",
22819
22834
  "mode": "0000644",
@@ -456,7 +456,7 @@ markdown describes, the DB enforces.**
456
456
 
457
457
  - **the apex root itself** — the public front door (`/`, `/projects`, `/create`, `/privacy`, `/terms`, `/contact`). **Carved to the `public-landing` module in task 1003322** ([ADR 0218](adr/0218-the-apex-root-web-surface.md)): the surface moved from repo-root `public-landing/` to `modules/public-landing/public/` and is a loader-discovered web-surface module — the THIRD, and the first that is not a subdomain. Where `hall-ui`/`status-ui` declare a Host PREFIX, this one declares `{ apexRoot: true, dir }`, because the apex is whatever host is left once the subdomains are taken (`isApexHost` = `!isStatusHost && !isBuildersHost`); `host: ""` is rejected, since `host.startsWith("")` is true for every host and would swallow the other two surfaces. Like the hall it keeps its **dedicated** serving block — in `src/platform-server.js`, now resolving its root through `moduleWebSurfaces()` by the `apexRoot` predicate rather than a hardcoded path — so the apex-only sentinel strip, the brand-token stamp and the `?v=` content stamp are unchanged. Disable the module and the front door vanishes: every route falls through to the game-less 404 tail. Served bytes are identical across the carve apart from the module's own `window.__MODULES__` entry.
458
458
  - **`example.com`** — game (Phaser + Colyseus). Static files from `public/`. `/builders` + `/builders/*` now **301-redirect to `builders.example.com/<rest>`** ([#739](https://example.com/builders#/task/739) then promoted to permanent 301 in [#741](https://example.com/builders#/task/741), ADR 0036 cutover); the apex no longer serves the builder surface directly.
459
- - **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/bongos/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected), run automatically by `.github/workflows/sync-status-mirror.yml` (needs the `STATUS_MIRROR_TOKEN` secret) ([#737](https://example.com/builders#/task/737)). **⚠ FOLLOW-UP (R84):** that workflow's path trigger still watches `public-status/**` and must be re-pointed at `modules/status-ui/public/**` by an owner/Archon — the GitHub App can't push `.github/workflows/*` (learning 107), so until then the mirror sync won't auto-fire on future status edits.
459
+ - **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-status/` to `modules/status-ui/public/`, now served by the loader's web-surface seam (`moduleWebSurfaces` → `serve-internal.js`, routed on the `status.` Host prefix the manifest declares) instead of a hardcoded block — no behavior change. Layout reorganized in [#726](https://example.com/builders#/task/726) (ADR 0036): Pulse / Watch(uptime) / Architects / Works / Treasury / Lately Inscribed / The World — the grade-aggregate, estimation-drift, and repo-health tablets moved to the Archon `/watch` page. **⚠ Served OFF the droplet** (ADR 0029, outage resilience): the live page is **GitHub Pages from the separate repo `example-owner/example-status`** (CNAME → Fastly), reading data cross-origin from the droplet's `/api/bongos/public/*` (CORS open) and an availability banner from the prober's `status-data` branch. The droplet still serves `modules/status-ui/public/` (on the `status.` host) as a same-origin fallback, but **DNS points at Pages, not the droplet** — so a droplet deploy does NOT update the live page. Changes to the surface publish to the mirror via `scripts/status-mirror-sync.js` (re-pointed at `modules/status-ui/public/`; status.js/style.css/cursors are byte-identical copies; index.html gets the off-box bits injected) ([#737](https://example.com/builders#/task/737)). **⚠ Run by hand:** no workflow runs the sync — `.github/workflows/sync-status-mirror.yml` is not in this repo — so a status-surface change reaches the live page only when someone runs `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` (task 1005131).
460
460
  - **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/0093-tranche-2-core-carve-sequence.md) §1): the surface moved from `public-builders/` to `modules/hall-ui/public/` (~13k LOC, the largest module) and is a loader-discovered web-surface module (`contributes.webSurfaces` host `builders.`). UNLIKE the generic status surface it keeps its **dedicated** serving block in `serve-internal.js` (`BUILDERS_DIR = modules/hall-ui/public/`), partitioned out of the generic web-surface loop on the `isBuildersHost` predicate. A thin rewrite shim maps every non-API path onto the existing `/builders/*` tree (so all serving + gating + asset-stamping is reused), serving the hall (`/`), the Metic+ **`/watch`** monitoring page (gated by `requireGovernmentPage`), **`/settings`** (Voices + Craft prefs), plus ranks/sessions/primer/diagrams. No behavior change — byte-identical (only `window.__MODULES__.enabled` gains `hall-ui:true`). **Additive** — until its DNS A record + cert are live, the whole surface stays reachable at `example.com/builders/*`. No `.github/workflows/*` follow-up: unlike R84, no workflow path-trigger watches `public-builders/**`.
461
461
  - The `/api/bongos/*` surface is reachable from every host. **Cross-subdomain sign-in:** the `gds_session` cookie is scoped to `.example.com` on the production hosts (apex/www/builders/status) and host-only on localhost/staging (no cross-env token bleed); the OAuth handshake runs on the canonical origin with a validated `?return=` (open-redirect-guarded) so the subdomain can land a builder back on itself.
462
462
  - Caddy gets a site block per host (`infra/Caddyfile` (instance-side)), all reverse-proxying to `127.0.0.1:3000`.
@@ -3370,5 +3370,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
3370
3370
  landed since 1.24.56 with no explicit bump. run 42379442367. (task 1002620)
3371
3371
  1.24.58 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3372
3372
  landed since 1.24.57 with no explicit bump. run 42380593295. (task 1002620)
3373
+ 1.24.59 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
3374
+ landed since 1.24.58 with no explicit bump. run 42385816081. (task 1002620)
3373
3375
  ---------------------------------------------------------------------------
3374
3376
  ```
@@ -5031,7 +5031,7 @@
5031
5031
  "surface": "status",
5032
5032
  "title": "{{productName}} — build status",
5033
5033
  "states_read": ["loaded"],
5034
- "files_hash": "10ee56cc01853b2d",
5034
+ "files_hash": "5b546389375906c5",
5035
5035
  "reading_hash": "5abba39cf5ec9226",
5036
5036
  "counts": {"lines":66,"placed":47,"shared":9,"unplaced":10},
5037
5037
  "omitted": {"data":90},
@@ -276,11 +276,11 @@ Inside the namespace the file lists as `---------- 1 root root 0`. The runner un
276
276
 
277
277
  ### The live status page is NOT served by the droplet — editing the status surface + deploying does nothing
278
278
 
279
- > **Path note (BV1.R84):** the status surface moved from `public-status/` to `modules/status-ui/public/` (carved to the `status-ui` web-surface module). Everything below applies at the new path; `scripts/status-mirror-sync.js` was re-pointed. **Open follow-up:** `.github/workflows/sync-status-mirror.yml` still triggers on `public-status/**` and must be re-pointed at `modules/status-ui/public/**` by an owner/Archon (the GitHub App can't push `.github/workflows/*`, learning 107) — until then the auto-sync won't fire and you must run the script by hand.
279
+ > **Path note (BV1.R84):** the status surface moved from `public-status/` to `modules/status-ui/public/` (carved to the `status-ui` web-surface module). Everything below applies at the new path; `scripts/status-mirror-sync.js` was re-pointed. **No auto-sync:** `.github/workflows/sync-status-mirror.yml` is not in this repo and nothing in CI runs the sync — you must run the script by hand (task 1005131).
280
280
 
281
281
  - **Symptom:** you change `modules/status-ui/public/`, deploy to the droplet, the origin serves the new page (verified via `curl` on the box), but `status.example.com` keeps showing the old version. Purging Cloudflare doesn't help.
282
282
  - **Root cause:** the off-box move (ADR 0029) repointed `status.example.com` DNS at **GitHub Pages from the separate repo `example-owner/example-status`** (served by Fastly — headers say `server: GitHub.com`, `via: varnish`, **no `cf-*` headers** → Cloudflare isn't even in the path). The droplet still serves `modules/status-ui/public/` as a same-origin fallback, but the public DNS goes to Pages. There was no sync, so droplet edits never reached the live page.
283
- - **Fix:** publish to the mirror with `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` — or (once the workflow trigger is re-pointed, see the path note above) let `.github/workflows/sync-status-mirror.yml` do it on push (needs the `STATUS_MIRROR_TOKEN` repo secret). `status.js`/`style.css`/`cursors/` are byte-identical copies (the one off-box difference, the API base, is injected via `window.STATUS_API_BASE` in the mirror's `index.html`); the sync injects the off-box banner + API-base script into `index.html` at fixed anchors and **throws if an anchor is missing** rather than mis-publishing. GitHub Pages purges its own Fastly cache on deploy, so the live page updates ~1 min after the Pages build goes green (`gh api repos/example-owner/example-status/pages/builds/latest`). ([#737](https://example.com/builders#/task/737))
283
+ - **Fix:** publish to the mirror with `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` (by hand — no workflow runs it, see the path note above). `status.js`/`style.css`/`cursors/` are byte-identical copies (the one off-box difference, the API base, is injected via `window.STATUS_API_BASE` in the mirror's `index.html`); the sync injects the off-box banner + API-base script into `index.html` at fixed anchors and **throws if an anchor is missing** rather than mis-publishing. GitHub Pages purges its own Fastly cache on deploy, so the live page updates ~1 min after the Pages build goes green (`gh api repos/example-owner/example-status/pages/builds/latest`). ([#737](https://example.com/builders#/task/737))
284
284
  - **Why it bites:** the origin looks correct at every layer you can `curl` from the box, so you chase a phantom cache on the wrong CDN. The tell is the response headers — `server: GitHub.com` + Fastly, not `cloudflare`.
285
285
 
286
286
  ---
@@ -250,11 +250,14 @@ a:hover { text-decoration-color: currentColor; }
250
250
  /* drawn from the one mark (modules/ui-design/public/brand/mark.svg, task 1005088) */
251
251
  --mark-ink: var(--ink);
252
252
  }
253
+ /* the wordmark: the pack's productName, lowercase and light, as the hall's lockup
254
+ (DESIGN.md "Naming"; task 1005135) */
253
255
  .topbar__name {
254
256
  font-family: var(--font-display);
255
- font-size: var(--ds-text-xl);
256
- font-weight: 500;
257
+ font-size: var(--ds-text-lg);
258
+ font-weight: 300;
257
259
  letter-spacing: -0.01em;
260
+ text-transform: lowercase;
258
261
  color: var(--ink);
259
262
  white-space: nowrap;
260
263
  overflow: hidden;
@@ -0,0 +1,10 @@
1
+ {
2
+ "apple-touch-icon.png": {
3
+ "page": "b665654a1cdfa7fb91f9aef0ab4a06831922c2e12bd7eb3dea572dd0db4988a2",
4
+ "png": "953557984586881b25452b8642f595dfad39d17b86459cee5c5b080b74165362"
5
+ },
6
+ "og-card.png": {
7
+ "page": "5f7d738dd440ed4760017fe4e468ec8a593745536336f819d4a3bd2c32a5c38d",
8
+ "png": "e168fdd0f4ac94754af089e7240be7cbba46704b36a617252f2942c97e8835e2"
9
+ }
10
+ }
@@ -15,6 +15,11 @@ body[data-page="brand"] {
15
15
  font-family: var(--font-body);
16
16
  }
17
17
 
18
+ /* The hall's sheet paints its plate veil as a fixed body::after over the page
19
+ (black in dark); the hall lifts its shell above it, and so does this page —
20
+ otherwise the whole reference reads through the veil, dimmed (task 1005135). */
21
+ body[data-page="brand"] > * { position: relative; z-index: 1; }
22
+
18
23
  /* ---- the bar: the mark, the name, the sections ---- */
19
24
  .ref-head {
20
25
  box-sizing: border-box;
@@ -134,6 +139,7 @@ body[data-page="brand"] {
134
139
  font-weight: 300;
135
140
  font-size: var(--ds-text-headline);
136
141
  letter-spacing: -0.01em;
142
+ text-transform: lowercase;
137
143
  color: var(--ink);
138
144
  }
139
145
  .ref-lockup__mark { width: 72px; height: 72px; }
@@ -13,7 +13,7 @@
13
13
  </head>
14
14
  <body data-page="brand">
15
15
  <header class="ref-head">
16
- <a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg><span>cloud bongos</span></a>
16
+ <a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg><span>{{productName}}</span></a>
17
17
  </header>
18
18
  <main class="ref-main">
19
19
  <h1 class="ref-title">Design system</h1>
@@ -27,7 +27,7 @@
27
27
 
28
28
  <div class="ref-lockup">
29
29
  <svg class="ref-lockup__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg>
30
- <span class="ref-lockup__name">cloud bongos</span>
30
+ <span class="ref-lockup__name">{{productName}}</span>
31
31
  </div>
32
32
  <div class="ref-naming">
33
33
  <p><strong>The wordmark is lowercase; the name in a sentence is capitalised</strong> (owner, 2026-11-06):</p>
@@ -152,7 +152,6 @@ function build(src = read()) {
152
152
  for (const cls of NEEDS) {
153
153
  if (!new RegExp(cls.replace(/[.[\]-]/g, '\\$&') + '(?![a-z0-9_-])').test(allCss)) throw new Error(`the hall's sheets no longer define ${cls}`);
154
154
  }
155
- const product = (src.pack.identity && src.pack.identity.productName) || '';
156
155
  const naming = readNaming(src.design);
157
156
  const files = readBrandFiles(src.genBrand, SRC.brandDir);
158
157
  const OTB = src.otb;
@@ -199,7 +198,7 @@ function build(src = read()) {
199
198
  parts.push(section('ref-logo', 'Logo and name', 'The mark is one file every page draws from. The ring and the planet take the ink; the moon takes the accent.', `
200
199
  <div class="ref-lockup">
201
200
  <svg class="ref-lockup__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg>
202
- <span class="ref-lockup__name">${esc(product.toLowerCase())}</span>
201
+ <span class="ref-lockup__name">{{productName}}</span>
203
202
  </div>
204
203
  <div class="ref-naming">
205
204
  ${naming.lead.map((p) => `<p>${p}</p>`).join('\n ')}
@@ -315,7 +314,7 @@ function build(src = read()) {
315
314
  </head>
316
315
  <body data-page="brand">
317
316
  <header class="ref-head">
318
- <a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg><span>${esc(product.toLowerCase())}</span></a>
317
+ <a class="ref-head__brand" href="/"><svg class="ref-head__mark" viewBox="0 0 200 200" aria-hidden="true"><use href="${BRAND_URL}mark.svg#mark"/></svg><span>{{productName}}</span></a>
319
318
  </header>
320
319
  <main class="ref-main">
321
320
  <h1 class="ref-title">Design system</h1>
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.58",
3
+ "version": "1.24.59",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.24.58",
9
+ "version": "1.24.59",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.58",
3
+ "version": "1.24.59",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -54,6 +54,8 @@
54
54
  }
55
55
  #topbar .mark { width: 28px; height: 28px; flex-shrink: 0; --mark-ink: var(--ink); }
56
56
  #topbar strong { font-family: var(--font-display); font-size: var(--ds-text-xl); font-weight: 500; }
57
+ /* the wordmark: the pack's productName, lowercase and light (DESIGN.md "Naming"; task 1005135) */
58
+ #topbar .wordmark { font-size: var(--ds-text-lg); font-weight: 300; letter-spacing: -0.01em; text-transform: lowercase; }
57
59
  #topbar .muted {
58
60
  font-family: var(--font-mono); font-size: var(--ds-text-2xs); letter-spacing: .12em;
59
61
  text-transform: uppercase; color: var(--ink-soft);
@@ -72,7 +74,7 @@
72
74
  <body>
73
75
  <div id="topbar">
74
76
  <svg class="mark" viewBox="0 0 200 200" aria-hidden="true"><use href="/modules/ui-design/public/brand/mark.svg#mark"/></svg>
75
- <strong>{{productName}} — API</strong>
77
+ <strong><span class="wordmark">{{productName}}</span> — API</strong>
76
78
  <span class="muted">OpenAPI 3.1</span>
77
79
  <span class="spacer"></span>
78
80
  <a href="/docs/openapi.json" download>Download spec</a>
@@ -11319,5 +11319,15 @@
11319
11319
  "id": "1005128",
11320
11320
  "text": "A project's owner now takes a new Bongos version with one Update button; the \"ask the team for this upgrade\" step is gone for every hosted project."
11321
11321
  }
11322
+ ],
11323
+ "1.24.59": [
11324
+ {
11325
+ "id": "1005135",
11326
+ "text": "The name beside the logo now reads 'cloud bongos' in lowercase everywhere, taken from the project's branding, and the sign-in and error pages use the same fonts and colours as the rest of the site."
11327
+ },
11328
+ {
11329
+ "id": "1005133",
11330
+ "text": "The logo files and the link-preview pictures are now checked automatically, so a logo change can no longer ship with out-of-date copies; the docs now say plainly that the off-site status page is updated by hand."
11331
+ }
11322
11332
  ]
11323
11333
  }
@@ -4,7 +4,8 @@
4
4
  // check; kept in its own file because fitness.js sits at the 1,500-line budget.
5
5
  //
6
6
  // Both generated files read the shared token sheet (modules/ui-design/public/tokens.css) and the brand pack; the public
7
- // reference also reads the hall's sheets and DESIGN.md. A stylesheet edit without a
7
+ // reference also reads the hall's sheets and DESIGN.md. The logo set (scripts/bongos/gen-brand.js)
8
+ // reads mark.svg and the pack, and checks its two PNGs by hash (task 1005133). A stylesheet edit without a
8
9
  // regeneration used to surface only as a failing unit test; this names it in fitness.
9
10
  // Skipped when the ui-design module is not in the checkout. `root` is injectable for
10
11
  // tests/design_counts_ratchet.mjs, which runs it against a copied tree.
@@ -17,14 +18,21 @@ const { REPO_ROOT } = require('./fitness-lib.js');
17
18
 
18
19
  function checkDesignGeneratorsFresh(root = REPO_ROOT) {
19
20
  const violations = [];
20
- for (const [script, out, task] of [
21
- ['gen-design-tokens.js', 'config/design-tokens.neutral.json', '1005082'],
22
- ['gen-design-reference.js', 'modules/ui-design/public/brand.html (the public /brand page)', '1005083'],
21
+ const UI = ['modules', 'ui-design', 'scripts'];
22
+ for (const [dir, script, out, why, task] of [
23
+ [UI, 'gen-design-tokens.js', 'config/design-tokens.neutral.json', 'a design source (the token sheet, the brand pack, a hall sheet or DESIGN.md)', '1005082'],
24
+ [UI, 'gen-design-reference.js', 'modules/ui-design/public/brand.html (the public /brand page)', 'a design source (the token sheet, the brand pack, a hall sheet or DESIGN.md)', '1005083'],
25
+ // The logo and favicon set, and the two PNGs by hash (task 1005133): mark.svg or the
26
+ // pack's colours changed without a regeneration. A PNG needs `--png` (a system browser).
27
+ [['scripts', 'bongos'], 'gen-brand.js', 'the logo set in modules/ui-design/public/brand/', 'mark.svg or the brand pack', '1005133'],
23
28
  ]) {
24
- const gen = path.join(root, 'modules', 'ui-design', 'scripts', script);
29
+ const gen = path.join(root, ...dir, script);
25
30
  if (!fs.existsSync(gen)) continue;
26
31
  try { execFileSync(process.execPath, [gen, '--check'], { cwd: root, stdio: 'pipe' }); }
27
- catch { violations.push(`${out} is STALE — a design source (the token sheet, the brand pack, a hall sheet or DESIGN.md) changed without a regeneration. Run \`node modules/ui-design/scripts/${script}\` and commit (task ${task}).`); }
32
+ catch (e) {
33
+ const said = String((e && e.stderr) || '').trim().split('\n').filter(Boolean).join(' ');
34
+ violations.push(`${out} is STALE — ${why} changed without a regeneration. Run \`node ${[...dir, script].join('/')}\`${script === 'gen-brand.js' ? ' (with --png for a PNG)' : ''} and commit (task ${task}).${said ? ` [${said}]` : ''}`);
35
+ }
28
36
  }
29
37
  return violations;
30
38
  }