@bongos/core 1.19.87 → 1.19.89

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/gds/package-core.js",
5
- "core_version": "1.19.87",
6
- "core_contract": "1.19.87",
7
- "source_commit": "87978cd9aae6450f9a950000264a6ea3290061a9",
5
+ "core_version": "1.19.89",
6
+ "core_contract": "1.19.89",
7
+ "source_commit": "ed4e7542e4437ae70c78dc251b624ee4890a6050",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-13T00:58:58.091Z",
9
+ "built_at": "2026-08-13T01:22:32.002Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 296,
12
+ "docs_redacted": 297,
13
13
  "agent_docs_stubbed": 21,
14
- "functional_verbatim": 1234,
14
+ "functional_verbatim": 1235,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1551,
20
- "tree_sha256": "76b44f6926a63b7efc6f1458fa1ddb8be237a801879982bddf6c97628d35762f",
19
+ "file_count": 1553,
20
+ "tree_sha256": "9f17eea1b4e64561bd3da49f5fd8494e53ea0ea55d4d860862a1763788507e36",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -1354,10 +1354,15 @@
1354
1354
  "mode": "0000644",
1355
1355
  "sha256": "a86af6a923ed70bb8ea0846266f232f31a5fc9709d286362bcd37104d683342b"
1356
1356
  },
1357
+ {
1358
+ "path": "docs/design/front-door-and-hub-direction.md",
1359
+ "mode": "0000644",
1360
+ "sha256": "e3026e23472629a7d4f1bebe883f9bc84263a849e22eab627f7a5b5ace9dd110"
1361
+ },
1357
1362
  {
1358
1363
  "path": "docs/design/gate-navigation-direction.md",
1359
1364
  "mode": "0000644",
1360
- "sha256": "b56c2394f695b64c567c581203901036222927f6c8e0d49fffceb2365f01e96b"
1365
+ "sha256": "90bed9a9f3859f7cfc6dd8a0e23e70adeda5854be0b10f8208d60a96c83403b3"
1361
1366
  },
1362
1367
  {
1363
1368
  "path": "docs/design/mocks/component-sheet.html",
@@ -2597,7 +2602,7 @@
2597
2602
  {
2598
2603
  "path": "modules/dev-box/box-access.js",
2599
2604
  "mode": "0000644",
2600
- "sha256": "8d2dc69a139a5a658866a18527efeb5d9ae989e05883fa6cbd0ea63db0ba9476"
2605
+ "sha256": "9357b423836c4e8d2cd3c9144d294c3cd3b498ac30755a9e6f62b5bbaa2add5e"
2601
2606
  },
2602
2607
  {
2603
2608
  "path": "modules/dev-box/box-credential.js",
@@ -4087,12 +4092,12 @@
4087
4092
  {
4088
4093
  "path": "package-lock.json",
4089
4094
  "mode": "0000644",
4090
- "sha256": "b3c0559dd15714741dd52b1493e31d0c58b400f29da9b5af0dd410559e890458"
4095
+ "sha256": "91af9550ea511beb785aeda73ead01cc94c2f10b0e6bfb63a5704190fa12fb3b"
4091
4096
  },
4092
4097
  {
4093
4098
  "path": "package.json",
4094
4099
  "mode": "0000644",
4095
- "sha256": "c7433c4d5b1fc188cc1660b3ed0cffd2f9d669fc5974f072af2b2816324efc09"
4100
+ "sha256": "ad3a6daa031c56fe45c5bc5de6036e8e97621e92888135406ed1c3cf5227f3bb"
4096
4101
  },
4097
4102
  {
4098
4103
  "path": "public-docs/index.html",
@@ -4367,7 +4372,7 @@
4367
4372
  {
4368
4373
  "path": "public-landing/gate/index.html",
4369
4374
  "mode": "0000644",
4370
- "sha256": "7e9e68da92493b0a728de0a4ff4d1a036d888df6b47267e5a5ac628ac55fcd07"
4375
+ "sha256": "4fabebb37446cb55803332d89909dd25b905ebbff5f3dd7d607d383122095800"
4371
4376
  },
4372
4377
  {
4373
4378
  "path": "public-landing/gate/previews/cloud-bongos.jpg",
@@ -5727,7 +5732,7 @@
5727
5732
  {
5728
5733
  "path": "src/module-api.js",
5729
5734
  "mode": "0000644",
5730
- "sha256": "3711343a6ac760f4742b14755a1e40722842fce3f29855804a092fdc72da6bb9"
5735
+ "sha256": "2bcad1ce4253a64c908a01fb38cf76a7543fac19a12ff949864de4a08a339861"
5731
5736
  },
5732
5737
  {
5733
5738
  "path": "src/module-loader/loader.js",
@@ -6007,7 +6012,7 @@
6007
6012
  {
6008
6013
  "path": "tests/box_access.mjs",
6009
6014
  "mode": "0000644",
6010
- "sha256": "06e8afe871803c92b20c28b918e39804a1616ee3b5773517f5ac804118d2de1d"
6015
+ "sha256": "694153e377a78d4325aa4ff9b947f691d71362f843da25815b9740821903802c"
6011
6016
  },
6012
6017
  {
6013
6018
  "path": "tests/box_auth_check.mjs",
@@ -6494,6 +6499,11 @@
6494
6499
  "mode": "0000644",
6495
6500
  "sha256": "df503f198853f6fe3497a2e0317d90bee69cc275f024027ad569ee1cef0155b6"
6496
6501
  },
6502
+ {
6503
+ "path": "tests/gate_launch_metadata.mjs",
6504
+ "mode": "0000644",
6505
+ "sha256": "235dfa1ea341b596ea4981fe8375650150387a60c9093c3a1a7b761222ee259a"
6506
+ },
6497
6507
  {
6498
6508
  "path": "tests/gate_review.mjs",
6499
6509
  "mode": "0000644",
@@ -0,0 +1,155 @@
1
+ # The Front Door and the Project Hub — Direction
2
+
3
+ > **Task 1002746** (goal 1000059), promoted from idea 1000713 · decided with the owner 2026-08-13.
4
+ > Surfaced by the gate-navigation session (task 1002741) and **revises it** — see §6.
5
+ > Time-sensitive: whichever page answers `/` when the pre-launch lock comes off becomes the
6
+ > product's first impression.
7
+
8
+ Scope: what `cloudbongos.com/` serves at launch, what happens to the `index.html` placeholder, and
9
+ how the project surfaces are organised. Deliberately **not** in scope: the visual design of any of
10
+ it — the owner plans a whole-site UI pass once the projects work completes, and this direction
11
+ settles structure so that pass inherits a clean shape rather than a decision.
12
+
13
+ ---
14
+
15
+ ## 0. Starting point — what exists today
16
+
17
+ Verified live on core 1.19.85 and read from `origin/main`.
18
+
19
+ **Two landing pages, and the wrong one answers the domain.**
20
+
21
+ | Path | Live | Notes |
22
+ |---|---|---|
23
+ | `/` | **302 → `/gate/` → 401** | the orb sky, behind the pre-launch `basic_auth` |
24
+ | `/index.html` | 200, public | reachable only if you type the filename |
25
+ | `/create`, `/projects` | 200, public | link only to each other |
26
+
27
+ `public-landing/index.html` declares what it is in its own source: *"a deliberately MINIMAL
28
+ placeholder home — just the mascot + a way into the Hall. The full landing page is a separate
29
+ task."* It is a pre-gate stub, not a competing design.
30
+
31
+ **The metadata is inverted.** The placeholder nobody reaches has a real product title and a meta
32
+ description. The gate that actually answers `/` shipped with `<title>Cloud Bongos — landing gate</title>`,
33
+ **no** description, **no** `og:`/`twitter:` tags, and **no** `<noscript>` — and the sky is entirely
34
+ JS-built, so a non-executing crawler or a JS-off visitor got a blank page. None of it bit yet only
35
+ because `X-Robots-Tag: noindex, nofollow` covers the whole host pre-launch. All of it bites at once
36
+ when the lock comes off.
37
+
38
+ **`index.html` is shared, not platform-specific.** It is the default landing every instance serves
39
+ (a child instance like `spike-harbor.cloudbongos.com` has no gate, so it already answers `/` with
40
+ this page). `/projects` is apex-only. That asymmetry constrains what may be hardcoded into it (§4).
41
+
42
+ ---
43
+
44
+ ## 1. Decisions (owner, 2026-08-13)
45
+
46
+ 1. **`/` serves a real landing page** — proper title, meta description, `og:`/social tags, and the
47
+ rest of the landing information. Not a redirect into an interactive experience.
48
+ 2. **`/projects` becomes the project hub.** One surface absorbs *all* project-related actions:
49
+ viewing the map/grid of projects, managing the signed-in owner's own projects, and creating new
50
+ ones. `/create` redirects into it. The orb sky stops being a front door and becomes a **view
51
+ inside the hub**.
52
+ 3. **Launch-safety is fixed now; the visual build is deferred** to the whole-site UI pass.
53
+ 4. **The pre-launch `basic_auth` is temporary** (carried over from task 1002741 §1).
54
+
55
+ ## 2. The hub model
56
+
57
+ `/projects` is the single place a person goes for anything project-shaped:
58
+
59
+ | Inside the hub | Comes from today's |
60
+ |---|---|
61
+ | the map / grid of projects (orb sky + the sortable table) | `/gate/` (`view-space`, `view-table`) |
62
+ | your own projects — status, address, teardown, revive | `/projects` |
63
+ | creating a project | `/create` (redirects in) |
64
+
65
+ - **No new vocabulary.** The hub keeps the `/projects` URL rather than inventing `/projects-hub`;
66
+ every existing link and bookmark keeps working, and "projects" already means projects to anyone
67
+ who has seen the surface. (An underscore form — `/projects_hub` — was considered and rejected:
68
+ underscores are unconventional in URLs and read poorly in search results.)
69
+ - **The map and the manage list are two views of one truth.** Both must render the verification
70
+ overlay the task 1002696 direction established (`live · checked Xm ago` / `live?` / `unreachable`).
71
+ A project cannot look alive on the map and unreachable in the list.
72
+ - **Signed-out visitors get the map** as a showcase, plus a way in. Signed-in owners additionally get
73
+ their own projects — which is where owner-orbs (§6) land.
74
+
75
+ ## 3. Sequencing — why the flip is NOT in this task
76
+
77
+ The apex flip is deliberately **not** shipped here, for a reason worth recording:
78
+
79
+ - `/` today at least reaches the sky, which carries a (weak) corner door to `/projects`. The shared
80
+ `index.html` has **no** door into the hub at all — its only outbound link is the builders' hall.
81
+ Flipping `/` to that page before it has doors would leave navigation **worse** than today, not
82
+ better.
83
+ - The flip also has an **infra half**: `/` is redirected in two places — the app
84
+ (`src/platform-server.js:115-121`) and the live Caddyfile (`redir / /gate/ 302` inside the `@gate`
85
+ block, which also carries the `basic_auth`). Changing code alone moves nothing on prod. The Caddy
86
+ edit is an operator act on the live box tied to launch, not a surface task.
87
+
88
+ So the flip ships **with** the hub build, once the landing page has doors, and is paired with the
89
+ Caddy change. What ships now is the part that is safe and useful regardless (§4).
90
+
91
+ ## 4. What ships in this task (the launch-safety fix)
92
+
93
+ Because the gate is what answers `/` **today**, the launch-safety fix is applied to the gate — not to
94
+ a page that does not yet hold the door:
95
+
96
+ - **`public-landing/gate/index.html`**: a real `<title>`, a meta description, `canonical`,
97
+ `og:type/site_name/url/title/description/image`, and `twitter:` card tags. Absolute
98
+ `cloudbongos.com` URLs, matching the domain `space.js` already pins.
99
+ - **A `<noscript>` block** stating plainly what Cloud Bongos is and linking to `/projects`,
100
+ `/create`, and the hall. Inline-styled, because every rule in `space.css` is scoped to a body
101
+ view-class this block must ignore. **No visual change for a JS visitor** — it renders only when
102
+ scripting is off.
103
+
104
+ **Explicitly not done, and why:** `og:` tags were *not* added to `public-landing/index.html`. It ships
105
+ to every instance, and social tags are read before JS runs — so its `window.__BRANDING__` fill cannot
106
+ populate them, and hardcoding `cloudbongos.com` would make every child instance advertise the wrong
107
+ site. Per-instance social tags need server-side injection; filed as **idea 1000715** rather than
108
+ hacked in here.
109
+
110
+ ## 5. Findings surfaced while deciding this
111
+
112
+ - **`tests/platform_boot.mjs` is parked in `KNOWN_FAILING` and has rotted.** Its apex test asserts
113
+ `/` returns 200 with the landing page; the gate redirect (task 1002408) made it 302, and the test
114
+ was never updated. It sits in `run-unit-tests.js`'s `KNOWN_FAILING` set (parked by task 1002617 so
115
+ the `unit` check could be made required), which is why CI is green. A `known_failing_ratchet.mjs`
116
+ pairs with it and fails the suite if a parked test starts passing — so **the hub flip must unpark
117
+ this test in the same change that makes it pass**. Filed as **idea 1000716**.
118
+ - Note the test also asserts an identity chip (`id="who"`, task 2094) that `index.html` does not
119
+ contain — a second, independent rot in the same file.
120
+ - The assertion the repo already carries (`/` → 200, the landing page) is exactly the behaviour this
121
+ direction decides. The test was right; the code drifted past it.
122
+
123
+ ## 6. Revision of the gate-navigation direction (task 1002741)
124
+
125
+ That direction was written hours earlier on the premise that **the gate is the front door**. This
126
+ direction supersedes that premise. What survives and what changes:
127
+
128
+ | Decision there | Status now |
129
+ |---|---|
130
+ | The `basic_auth` wall is temporary | **stands** |
131
+ | The type-`bongos` entry ritual is removed; land on the sky | **stands** — the sky is now a hub view, and the ritual should not gate a view any more than it should gate a front door |
132
+ | A persistent door in every gate view | **becomes hub navigation** — the same requirement, relocated: the door is now the hub's own nav between map / your projects / create, not a link out of the gate |
133
+ | A signed-in owner's projects get a distinct identity in the sky | **stands** — and lands inside the hub's map view |
134
+ | The sky is the public front door | **superseded** — `/` is the landing page; the sky is a view of `/projects` |
135
+
136
+ Both carriers are re-scoped accordingly: **task 1002743** (ritual removal + hub navigation, plus the
137
+ apex flip and unparking `platform_boot`) and **task 1002744** (owner-scoped feed + owned-orb identity
138
+ inside the hub map).
139
+
140
+ ## 7. Boundary with the coming UI pass
141
+
142
+ This direction settles **structure**: which URL serves what, what the hub contains, and what
143
+ redirects where. It settles **no** visual design — not the landing page's layout, not the hub's
144
+ chrome, not how the map and list views sit together. Those belong to the whole-site UI pass the owner
145
+ plans after the projects work completes, and that pass should be able to take this structure as given
146
+ and change only how it looks.
147
+
148
+ ## 8. Sign-off dispositions (owner, 2026-08-13)
149
+
150
+ 1. **`/` = a real landing page**; the map/project list is a separate surface.
151
+ 2. **That surface is `/projects`**, absorbing map, manage, and create — chosen over a new
152
+ `/projects-hub` URL so no vocabulary or bookmarks are lost.
153
+ 3. **Amend task 1002741's direction and re-scope its two carriers** rather than letting them ship
154
+ against a premise that changed (§6).
155
+ 4. **Decide + do the launch-safety fix now** — hence §4, and hence the flip deferred to §3.
@@ -1,5 +1,22 @@
1
1
  # Gate Navigation — Direction
2
2
 
3
+ > ## ⚠ REVISED the same day — read this first
4
+ >
5
+ > This document's central premise — **the gate is the front door** — was **superseded within hours**
6
+ > by [`front-door-and-hub-direction.md`](front-door-and-hub-direction.md) (task 1002746, owner,
7
+ > 2026-08-13). Under that decision `/` serves a real landing page, and **`/projects` becomes a project
8
+ > hub** that absorbs the map/grid, managing your projects, and creating them. The orb sky is no longer
9
+ > a front door — it is a **view inside the hub**.
10
+ >
11
+ > **What still stands:** the temporary `basic_auth` wall, removing the type-`bongos` entry ritual, the
12
+ > requirement for persistent navigation, and owner-orbs. **What changed:** those land inside the hub
13
+ > rather than on a standalone gate, and the "door out to `/projects`" becomes the hub's own internal
14
+ > navigation. The full disposition is in that document's §6.
15
+ >
16
+ > Everything below is preserved as the **evidence base** — the live navigation trace, the five-view
17
+ > map, the sign-in-awareness findings, and the shipped-door analysis are all still accurate and still
18
+ > load-bearing for the build. Only the framing changed.
19
+
3
20
  > **Task 1002741** (goal 1000059 "Projects surface revamp") · direction decided with the owner 2026-08-13.
4
21
  > Owner finding, 2026-08-12, minutes after the task 1002696 redesign went live: *"cloudbongos.com/gate
5
22
  > is the landing page and there's no way to get there from the landing page."*
@@ -151,6 +151,13 @@ const BASE_SPARSE_PATHS = [
151
151
  // so a box holding the module source but not tests/ cannot verify a change.
152
152
  // A cone-mode directory; it carries no product runtime, only test code.
153
153
  'tests',
154
+ // clients/ — the generated bongos-client (ADR 0118) that cli-lib.js hard-imports
155
+ // since task 1996 made it the CLI's one HTTP client. Without it EVERY /builder-*
156
+ // command on the box dies at import, and the builder cannot self-heal: the
157
+ // workspace is a token-less blob:none clone (sparse-checkout add can't fetch)
158
+ // and box-source-fetch re-applies this server-computed list every tick
159
+ // (task 1002745). Generated ESM only, no product runtime.
160
+ 'clients',
154
161
  ];
155
162
 
156
163
  // sparsePathsForScopeKeys — PURE. Given the module KEYS a builder's active claims
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.87",
3
+ "version": "1.19.89",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.87",
9
+ "version": "1.19.89",
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.19.87",
3
+ "version": "1.19.89",
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",
@@ -3,7 +3,26 @@
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Cloud Bongos — landing gate</title>
6
+ <title>Cloud Bongos — building software is laying down a beat</title>
7
+ <!-- Launch-safety metadata (task 1002746). Until the front door moves to the
8
+ landing page (see docs/design/front-door-and-hub-direction.md), THIS page is
9
+ what answers cloudbongos.com/ — so it is what search results and link
10
+ previews describe. It shipped with an internal-sounding title, no
11
+ description, and no social tags; the whole host is noindex today, so none of
12
+ it bit yet, but all of it bites the moment the pre-launch lock comes off.
13
+ The absolute cloudbongos.com URLs match the domain space.js already pins. -->
14
+ <meta name="description" content="An open-source, AI-first build platform. AI agents claim tasks and write the code; you set the scope and the gates. Explore the live projects, or start your own." />
15
+ <link rel="canonical" href="https://cloudbongos.com/" />
16
+ <meta property="og:type" content="website" />
17
+ <meta property="og:site_name" content="Cloud Bongos" />
18
+ <meta property="og:url" content="https://cloudbongos.com/" />
19
+ <meta property="og:title" content="Cloud Bongos — building software is laying down a beat" />
20
+ <meta property="og:description" content="An open-source, AI-first build platform. AI agents claim tasks and write the code; you set the scope and the gates." />
21
+ <meta property="og:image" content="https://cloudbongos.com/buddha.png" />
22
+ <meta name="twitter:card" content="summary_large_image" />
23
+ <meta name="twitter:title" content="Cloud Bongos — building software is laying down a beat" />
24
+ <meta name="twitter:description" content="An open-source, AI-first build platform. AI agents claim tasks and write the code; you set the scope and the gates." />
25
+ <meta name="twitter:image" content="https://cloudbongos.com/buddha.png" />
7
26
  <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet" />
8
27
  <link rel="stylesheet" href="space.css" />
9
28
  <!-- Anti-flash (task 1985 follow-up): on a direct-orbs load — a vanity door
@@ -139,6 +158,29 @@
139
158
  </style>
140
159
  </head>
141
160
  <body class="view-entry">
161
+ <!-- No-JS fallback (task 1002746). The sky is entirely JS-built: without it this
162
+ page rendered blank, so a non-executing crawler or a JS-off visitor saw
163
+ nothing at all on the domain's front door. Inline styles because every
164
+ stylesheet rule here is scoped to a body view-class this block must ignore.
165
+ Keep the copy in sync with the meta description above. -->
166
+ <noscript>
167
+ <div style="position:fixed;inset:0;z-index:9999;overflow:auto;background:#0b1020;color:#e9edf7;font-family:'Baloo 2',system-ui,sans-serif;padding:2rem;">
168
+ <div style="max-width:34rem;margin:12vh auto 0;">
169
+ <h1 style="font-size:1.9rem;line-height:1.2;margin:0 0 .75rem;">Cloud&nbsp;Bongos</h1>
170
+ <p style="font-size:1.05rem;line-height:1.6;margin:0 0 1rem;color:#c3cbe0;">
171
+ An open-source, AI-first build platform. AI agents claim tasks and write the
172
+ code; you set the scope and the gates.
173
+ </p>
174
+ <p style="font-size:1.05rem;line-height:1.6;margin:0 0 1.5rem;color:#c3cbe0;">
175
+ The interactive map of live projects needs JavaScript, but everything below
176
+ works without it.
177
+ </p>
178
+ <p style="margin:0 0 .6rem;"><a href="/projects" style="color:#ffd98a;">Your projects</a> — find and manage the projects you own.</p>
179
+ <p style="margin:0 0 .6rem;"><a href="/create" style="color:#ffd98a;">Start a project</a> — stand up a new one.</p>
180
+ <p style="margin:0;"><a href="https://builders.cloudbongos.com" style="color:#ffd98a;">Builders' Hall</a> — where the work happens.</p>
181
+ </div>
182
+ </div>
183
+ </noscript>
142
184
  <!-- ═══ dive cinematic (task 1729): clicking the Cloud Bongos orb flies you
143
185
  from the space constellation, down through the clouds, into the Cloud
144
186
  Bongos world (the download page). space.js plays #descent on the self-orb
package/src/module-api.js CHANGED
@@ -601,8 +601,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
601
601
  // landed since 1.19.85 with no explicit bump. run 31655210981. (task 1002620)
602
602
  // 1.19.87 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
603
603
  // landed since 1.19.86 with no explicit bump. run 31656188572. (task 1002620)
604
+ // 1.19.88 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
605
+ // landed since 1.19.87 with no explicit bump. run 31656577595. (task 1002620)
606
+ // 1.19.89 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
607
+ // landed since 1.19.88 with no explicit bump. run 31657467485. (task 1002620)
604
608
  // ---------------------------------------------------------------------------
605
- const CORE_VERSION = '1.19.87'; // CI auto-patch carrier (ADR 0161); see changelog above
609
+ const CORE_VERSION = '1.19.89'; // CI auto-patch carrier (ADR 0161); see changelog above
606
610
 
607
611
  // A namespaced logger so a module's log lines are attributable + consistent.
608
612
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -194,7 +194,9 @@ const BASE = access.BASE_SPARSE_PATHS;
194
194
  console.log('\nBASE_SPARSE_PATHS — the non-product base a task-scoped box layers on:');
195
195
 
196
196
  t('BASE carries the methodology + tooling, NOT the product/game', () => {
197
- for (const p of ['.devcontainer', '.claude', 'scripts', 'src/bongos', 'docs', 'infra', 'tests']) {
197
+ // clients/ is load-bearing: cli-lib.js hard-imports clients/bongos-client, so a
198
+ // cone without it has a fully dead builder CLI on the box (task 1002745).
199
+ for (const p of ['.devcontainer', '.claude', 'scripts', 'src/bongos', 'docs', 'infra', 'tests', 'clients']) {
198
200
  assert.ok(BASE.includes(p), `BASE must include ${p}`);
199
201
  }
200
202
  for (const p of ['src/world', 'src/rooms', 'public', 'art', 'modules/status-ui']) {
@@ -0,0 +1,67 @@
1
+ // tests/gate_launch_metadata.mjs — the landing gate is discoverable and degrades
2
+ // without JavaScript (task 1002746).
3
+ //
4
+ // WHY THIS EXISTS. Until the front door moves to the landing page
5
+ // (docs/design/front-door-and-hub-direction.md), public-landing/gate/index.html is
6
+ // what answers cloudbongos.com/ — so it is what search results and link previews
7
+ // describe, and what a JS-off visitor or a non-executing crawler receives. It
8
+ // shipped with an internal-sounding <title>, no description, no social tags, and
9
+ // no <noscript>, and the sky is entirely JS-built, so that visitor got a blank
10
+ // page. The whole host is noindex pre-launch, which is exactly why the gap went
11
+ // unnoticed — it costs nothing until the lock comes off, then it costs everything
12
+ // at once.
13
+ //
14
+ // Pure disk read: no server boot, no DB, no network — this asserts the shipped
15
+ // artifact, which is the thing that actually reaches a crawler.
16
+
17
+ import assert from 'node:assert/strict';
18
+ import { test } from 'node:test';
19
+ import fs from 'node:fs';
20
+ import path from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+
23
+ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
24
+ const GATE = path.join(REPO_ROOT, 'public-landing', 'gate', 'index.html');
25
+ const html = fs.readFileSync(GATE, 'utf8');
26
+
27
+ test('the gate carries a real product title, not an internal label', () => {
28
+ const title = (html.match(/<title>([^<]*)<\/title>/) || [])[1] || '';
29
+ assert.ok(title.trim().length > 0, 'the gate must have a <title>');
30
+ // "Cloud Bongos — landing gate" described the file to us, not the product to a
31
+ // stranger reading a search result.
32
+ assert.doesNotMatch(title, /landing gate/i, `<title> must not read as an internal label: ${title}`);
33
+ assert.match(title, /Cloud Bongos/);
34
+ });
35
+
36
+ test('the gate is describable by a crawler and a link preview', () => {
37
+ assert.match(html, /<meta\s+name="description"\s+content="[^"]{40,}"/, 'needs a meta description');
38
+ assert.match(html, /<link\s+rel="canonical"\s+href="https:\/\/cloudbongos\.com\/"/);
39
+ for (const prop of ['og:type', 'og:site_name', 'og:url', 'og:title', 'og:description', 'og:image']) {
40
+ assert.match(html, new RegExp(`property="${prop}"`), `missing ${prop}`);
41
+ }
42
+ for (const name of ['twitter:card', 'twitter:title', 'twitter:description', 'twitter:image']) {
43
+ assert.match(html, new RegExp(`name="${name}"`), `missing ${name}`);
44
+ }
45
+ });
46
+
47
+ test('the gate degrades to real content without JavaScript', () => {
48
+ const block = (html.match(/<noscript>([\s\S]*?)<\/noscript>/) || [])[1];
49
+ assert.ok(block, 'the JS-built sky must ship a <noscript> fallback');
50
+ // It has to SAY something, not just exist — a stranger with JS off should learn
51
+ // what this is and be able to leave through a real door.
52
+ assert.match(block, /Cloud&nbsp;Bongos|Cloud Bongos/);
53
+ assert.match(block, /href="\/projects"/, 'the fallback must reach the projects surface');
54
+ assert.match(block, /href="\/create"/, 'the fallback must reach project creation');
55
+ // Every rule in space.css is scoped to a body view-class the fallback must
56
+ // ignore, so its visibility cannot depend on the stylesheet.
57
+ assert.match(block, /style="/, 'the fallback must be inline-styled to survive the view-class CSS');
58
+ });
59
+
60
+ test('the gate still boots into a view class (the ritual removal has not landed yet)', () => {
61
+ // Guards the file's structural contract while task 1002743 is outstanding: the
62
+ // body carries a view class, and <head> closes before <body> opens. If the
63
+ // ritual removal lands, the expected class becomes view-space — update this
64
+ // assertion there rather than deleting it.
65
+ assert.match(html, /<body class="view-(entry|space)"/);
66
+ assert.ok(html.indexOf('</head>') < html.indexOf('<body class='), 'head must close before body opens');
67
+ });