@bongos/core 1.19.92 → 1.19.94

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.
@@ -0,0 +1,146 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>The hub's ground — three candidates (task 1002758)</title>
7
+ <link rel="stylesheet" href="../../../public-landing/assets/cosmos.css">
8
+ <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Quicksand:wght@400;500;600;700&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
9
+ <style>
10
+ /* Contact sheet — the same pattern landing-palettes.html used for the palette
11
+ choice. Each tile is the REAL mock at ?rail=0, scaled, so nothing is drawn
12
+ twice and the comparison cannot drift from the thing being approved. */
13
+ body{background:var(--page-bg);padding:clamp(18px,3vw,36px);}
14
+ .head{max-width:1180px;margin:0 auto 26px;}
15
+ .head h1{font-family:var(--font-display);font-size:var(--fs-h2);letter-spacing:-.5px;margin-bottom:8px;}
16
+ .head p{font-size:var(--fs-lede);color:var(--ink-soft);font-weight:500;line-height:1.6;max-width:74ch;}
17
+ .head p + p{margin-top:10px;}
18
+ .head b{color:var(--ink);}
19
+ .sheet{max-width:1180px;margin:0 auto;display:grid;gap:var(--pad-md);grid-template-columns:repeat(2,1fr);}
20
+ @media (max-width:920px){.sheet{grid-template-columns:1fr;}}
21
+ .tile{background:var(--bg-card);border:2px solid var(--line);border-radius:20px;overflow:hidden;
22
+ box-shadow:var(--shadow-card);}
23
+ .tile h2{font-family:var(--font-display);font-size:16px;padding:14px 18px 4px;display:flex;
24
+ align-items:center;gap:10px;flex-wrap:wrap;}
25
+ .tile h2 .tag{font-family:var(--font-mono);font-size:11px;font-weight:500;padding:2px 9px;
26
+ border-radius:999px;background:var(--accent-soft);color:var(--accent-deep);}
27
+ .tile h2 .rec{background:var(--ok-soft);color:var(--ok);}
28
+ .tile p{font-size:13.5px;color:var(--ink-soft);font-weight:500;line-height:1.55;padding:0 18px 12px;}
29
+ .tile p .risk{color:var(--err);font-weight:700;}
30
+ .frame{position:relative;height:430px;border-top:2px solid var(--line);background:var(--bg-deep);overflow:hidden;}
31
+ .frame iframe{position:absolute;top:0;left:0;width:1440px;height:900px;border:0;
32
+ transform:scale(.4097);transform-origin:0 0;}
33
+ .pair{display:grid;grid-template-columns:1fr 1fr;}
34
+ .pair .frame{height:300px;}
35
+ .pair .frame iframe{transform:scale(.2861);}
36
+ .pair .lbl{position:absolute;left:9px;top:9px;z-index:2;font-family:var(--font-mono);font-size:10.5px;
37
+ background:rgba(0,0,0,.62);color:#fff;padding:2px 8px;border-radius:999px;}
38
+ .pair .frame + .frame{border-left:2px solid var(--line);}
39
+ .foot{max-width:1180px;margin:26px auto 0;font-size:13.5px;color:var(--ink-soft);font-weight:500;line-height:1.6;}
40
+ .foot a{color:var(--accent-deep);font-weight:700;}
41
+ </style>
42
+ </head>
43
+ <body>
44
+
45
+ <div class="head">
46
+ <h1>The hub’s ground — three candidates</h1>
47
+ <p>Task 1002758 · goal 1000061. <b>Structure is already settled</b> — <code>/projects</code> is the one hub
48
+ holding the map, your projects, and create. What is open is the <b>ground</b>: today the sky is a dark
49
+ full-bleed canvas while <code>/projects</code> and <code>/create</code> are light marigold document pages, and
50
+ one hub has to reconcile them.</p>
51
+ <p>Each tile below is the <b>real mock</b> (<code>projects-hub-mock.html</code>) running at that ground, in
52
+ light and dark. Open any of them full size to walk it. The status quo is included as a labelled option —
53
+ <b>C</b> is what the gate ships today.</p>
54
+ </div>
55
+
56
+ <div class="sheet">
57
+
58
+ <div class="tile">
59
+ <h2>B · dual-mode full-bleed <span class="tag rec">recommended</span> <span class="tag">default</span></h2>
60
+ <p>The sky is the page, and it follows light/dark like everything else: marigold daylight in light, warm-umber
61
+ space in dark. <b>cosmos.css already encodes this</b> — <code>--sky-bg</code> is <code>#f9d9a8</code>/<code>#150c06</code>
62
+ and <code>--star-display</code> flips <code>none</code>/<code>block</code> (:61-62, :99-100), so no new decision
63
+ is needed and the mode toggle keeps meaning something in every view.
64
+ <span class="risk">Its risk:</span> light mode loses the starfield drama entirely — the map becomes a calm
65
+ diagram rather than a place.</p>
66
+ <div class="pair">
67
+ <div class="frame"><span class="lbl">light</span>
68
+ <iframe src="projects-hub-mock.html?view=map&rail=0#b-light" data-g="b" data-m="light" loading="lazy"></iframe></div>
69
+ <div class="frame"><span class="lbl">dark</span>
70
+ <iframe src="projects-hub-mock.html?view=map&rail=0#b-dark" data-g="b" data-m="dark" loading="lazy"></iframe></div>
71
+ </div>
72
+ </div>
73
+
74
+ <div class="tile">
75
+ <h2>A · framed window <span class="tag">document-first</span></h2>
76
+ <p>The hub is a marigold document page in both modes and the sky lives inside a bounded, rounded panel —
77
+ a component rather than the environment. The chrome never changes character between views, and the map
78
+ stops competing with the page it sits on.
79
+ <span class="risk">Its risk:</span> a 540px window onto a gravity field reads as a widget; the sky’s whole
80
+ appeal is that it feels like somewhere you are, and a panel makes it somewhere you are looking at.</p>
81
+ <div class="pair">
82
+ <div class="frame"><span class="lbl">light</span>
83
+ <iframe src="projects-hub-mock.html?view=map&rail=0#a-light" data-g="a" data-m="light" loading="lazy"></iframe></div>
84
+ <div class="frame"><span class="lbl">dark</span>
85
+ <iframe src="projects-hub-mock.html?view=map&rail=0#a-dark" data-g="a" data-m="dark" loading="lazy"></iframe></div>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="tile">
90
+ <h2>C · locked deep space <span class="tag">the status quo</span></h2>
91
+ <p>What the gate ships today: the blue-violet starfield, full-bleed, in <b>both</b> modes — the locked
92
+ <code>--space-deep/mid/high</code> palette (cosmos.css:47-49) that no branding pack can re-theme. Keeps the
93
+ sky exactly as designed.
94
+ <span class="risk">Its risk:</span> the light/dark toggle silently does nothing on the hub’s main view, and
95
+ the hub reads as a different product from the marigold landing page a visitor just came through.</p>
96
+ <div class="pair">
97
+ <div class="frame"><span class="lbl">light</span>
98
+ <iframe src="projects-hub-mock.html?view=map&rail=0#c-light" data-g="c" data-m="light" loading="lazy"></iframe></div>
99
+ <div class="frame"><span class="lbl">dark</span>
100
+ <iframe src="projects-hub-mock.html?view=map&rail=0#c-dark" data-g="c" data-m="dark" loading="lazy"></iframe></div>
101
+ </div>
102
+ </div>
103
+
104
+ <div class="tile">
105
+ <h2>The other two views <span class="tag">ground-independent</span></h2>
106
+ <p>Your projects and New project are document views in every candidate — they carry controls a canvas cannot.
107
+ Shown here in light and dark so the card vocabulary, the verification chips, and the dropped-buddha create
108
+ step can be judged alongside the map.</p>
109
+ <div class="pair">
110
+ <div class="frame"><span class="lbl">your projects</span>
111
+ <iframe src="projects-hub-mock.html?view=mine&rail=0" loading="lazy"></iframe></div>
112
+ <div class="frame"><span class="lbl">new project</span>
113
+ <iframe src="projects-hub-mock.html?view=new&rail=0" loading="lazy"></iframe></div>
114
+ </div>
115
+ </div>
116
+
117
+ </div>
118
+
119
+ <p class="foot">
120
+ Walk the real thing: <a href="projects-hub-mock.html">projects-hub-mock.html</a> — the rail at the bottom
121
+ switches ground, view, mode and signed-in state; <code>S</code> outlines apex-only blocks and <code>C</code>
122
+ previews the child-instance shape. Serve over HTTP (<code>python -m http.server 8899</code>), not
123
+ <code>file://</code>.
124
+ </p>
125
+
126
+ <script>
127
+ /* Each tile drives its own iframe to a ground/mode after load. The iframes share
128
+ a localStorage key, so the attribute is written directly into the frame's
129
+ document instead of relying on the mock's own persistence. */
130
+ document.querySelectorAll('iframe[data-g]').forEach(function (f) {
131
+ f.addEventListener('load', function () {
132
+ try {
133
+ var d = f.contentDocument.documentElement;
134
+ d.setAttribute('data-ground', f.dataset.g);
135
+ d.setAttribute('data-mode', f.dataset.m);
136
+ } catch (e) {}
137
+ });
138
+ });
139
+ document.querySelectorAll('iframe:not([data-g])').forEach(function (f, i) {
140
+ f.addEventListener('load', function () {
141
+ try { f.contentDocument.documentElement.setAttribute('data-mode', i === 0 ? 'light' : 'dark'); } catch (e) {}
142
+ });
143
+ });
144
+ </script>
145
+ </body>
146
+ </html>
@@ -0,0 +1,347 @@
1
+ # The /projects Hub — Direction
2
+
3
+ > **Task 1002758** (goal 1000061 "Apex UI pass") · decided with the owner 2026-08-13.
4
+ > The mock this approves: [`mocks/projects-hub-mock.html`](mocks/projects-hub-mock.html).
5
+ > Ground comparison sheet: [`mocks/projects-hub-variants.html`](mocks/projects-hub-variants.html).
6
+
7
+ Scope: the **look and view model** of `/projects` once it becomes the project hub. Structure was already
8
+ settled by [`front-door-and-hub-direction.md`](front-door-and-hub-direction.md) §1–2, whose §7 deferred the
9
+ visual design to this pass and told it to take the structure as given. This document does not reopen which
10
+ URL serves what, what the hub contains, or what redirects where.
11
+
12
+ It also does **not** cover *how the sky moves* — panning, zoom, the Shift-search spotlight, the hover-card
13
+ lifecycle, the ghost orb, the minimap and the whale are goal 1000031. The line: **if it changes where a
14
+ person can go it is this pass; if it changes how the sky moves it is not.**
15
+
16
+ ---
17
+
18
+ ## 0. Starting point — what exists today
19
+
20
+ Verified live on core 1.19.91 and read from `origin/main` at `3458c70`, 2026-08-13.
21
+
22
+ **Three surfaces that do not know about each other.**
23
+
24
+ | Path | What it is | Nav out |
25
+ |---|---|---|
26
+ | `/gate/` | the orb sky, behind the pre-launch `basic_auth` (401) | a corner `.space-projects` pill — **and it is hidden in the table view** |
27
+ | `/projects` | a hero + a sign-in card. Signed out, that is the entire page | wordmark, "+ New project" |
28
+ | `/create` | the buddha, a 4-step rail, a sign-in card | "Exit `esc`" |
29
+
30
+ **Four defects this pass found on shipped files**, recorded here because the build inherits them:
31
+
32
+ 1. **`/projects` promises a sky it does not have.** Its lede reads *"The same sky as the front door — every
33
+ project you own is an orb here"*, and the page renders a flat marigold ground with one card. The copy
34
+ describes the gate, which a visitor to `/projects` never sees.
35
+ 2. **`?view=` is inert.** `public-landing/index.html:240` and `:430` — both "Start a project" CTAs on the
36
+ landing page shipped in `d53f51b` — link `/projects?view=new`, and `projects.html` reads **no query
37
+ string at all** (`grep -c "searchParams\|location.search" ` → 0). Both land on the plain list. This is a
38
+ live navigation bug on the front door, and §1.5 fixes it here because the hub is the surface that owns it.
39
+ 3. **The table view has no verification overlay and no way back.** The gate's table shows Project / Builders
40
+ / Type / Tags and no liveness chip, and its `body:not(.view-space)` rule hides the only projects door —
41
+ so the one view where a person is scanning for their own project is the view that cannot say whether it
42
+ is up, or get them to it.
43
+ 4. **The landing hero's shadow inverts in dark mode.** `public-landing/index.html:276` fills the drums'
44
+ ground shadow with `var(--ink)`, which is `#fdeedd` in dark — a glowing cream puddle rather than a
45
+ shadow. Filed as its own task (§8) because it is a fault on the *landing* page, not a hub decision.
46
+
47
+ `projects.html` also bakes two platform claims into a file that ships to every instance — `<title>Your
48
+ projects — Cloud Bongos</title>` (`:6`) and the commons footer (`:93`) — and contains **zero** apex-only
49
+ sentinels. §7 C5 and the mock's `C` preview settle which side of the line each block sits on.
50
+
51
+ ## 1. Decisions (owner, 2026-08-13)
52
+
53
+ 1. **The map is what you land on.** Signed in or out, `/projects` opens on the map.
54
+ 2. **An "only mine" filter lives in the map *and* the table.** The catalog is four projects and not all of
55
+ them are the viewer's; one control filters both browse views in place.
56
+ 3. **The ground is `B` — dual-mode full-bleed.** The sky is the page and follows light/dark.
57
+ 4. **`/gate/` retires at the apex flip.** The landing page already replaces it as the front door.
58
+ 5. **The buddha is dropped.** The bongo pair is the mark on every surface.
59
+ 6. **"Your projects" stays a distinct view, not a filtered map** (§3).
60
+ 7. **`?view=map|mine|new` is the hub's deep-link contract** (§4), which fixes defect 2 above.
61
+
62
+ ## 2. The ground — why dual-mode beat a framed panel
63
+
64
+ Three grounds were built as the *same mock* under a switch and compared as rendered pages; all three are
65
+ preserved in `projects-hub-mock.html` behind `html[data-ground]`, and the contact sheet is the record.
66
+
67
+ **B · dual-mode full-bleed won because cosmos.css had already decided it.** `--sky-bg` is
68
+ `#f9d9a8` in light and `#150c06` in dark, and `--star-display` flips `none`/`block` (`cosmos.css:61-62`,
69
+ `:99-100`). The shared stylesheet was built expecting a sky that changes with the mode; a hub that ignored
70
+ that would have been the only surface where the persistent ☾/☀ toggle does nothing.
71
+
72
+ - **A · framed window** — the sky as a bounded panel on a document page — was rejected because a ~540px
73
+ window onto a gravity field reads as a widget. The sky's whole appeal is that it is somewhere you *are*.
74
+ - **C · locked deep space** — the status quo, blue-violet in both modes — was rejected on two counts: the
75
+ mode toggle would silently do nothing on the hub's main view, and the hub would read as a different
76
+ product from the marigold landing page a visitor just came through.
77
+
78
+ **Dark mode is warm, not blue.** The map's dark ground is `--sky-bg` `#150c06` (warm umber), **not** the
79
+ gate's `--space-deep` `#05060f`. The locked space palette (`cosmos.css:47-49`) stays available and
80
+ platform-fixed, but the hub does not reintroduce the blue-violet the marigold pass moved away from.
81
+
82
+ > **Its risk, recorded so the build can watch for it:** light mode loses the starfield entirely
83
+ > (`--star-display:none`), so the map becomes a calm diagram rather than a place. If light mode ends up
84
+ > feeling inert, the fix is *not* to force stars onto a marigold ground — it is to give the light sky its
85
+ > own depth cue (the gravity grid carries most of it already; a soft vignette or warm haze layer is the
86
+ > next lever).
87
+
88
+ ## 2b. What "mine" means — and the fact that nothing is
89
+
90
+ The owner's "only mine" toggle sounds like one predicate. It is not, and the platform had already decided
91
+ the vocabulary before this pass asked the question.
92
+
93
+ **Authority is the memberships table, not the catalog's owner column.**
94
+ `<redacted>` (ADR 0141 §3) carries `role IN ('owner','builder','visitor','pending')`,
95
+ and `GET /my-projects` already returns the split — `{ owned, building }`, with `pending` excluded
96
+ (`modules/platform-identity/routes/my-projects.js:25-38`). Meanwhile
97
+ `platform_identity_projects.owner_github_id` describes itself in its own migration as *"advisory attribution
98
+ (not an authority)"*. **The build must read memberships. It must not read `owner_github_id`.**
99
+
100
+ So the filter keeps `owner` **and** `builder`, and the map says the two differently — a solid accent ring
101
+ and a filled **yours** badge for owned; a softer ring and an outlined **you build here** badge for building.
102
+ Claiming ownership the membership row does not assert would be the same class of lie as the verification
103
+ overlay's (C6).
104
+
105
+ **And today the honest answer is that nothing is anyone's.** Verified 2026-08-13 as the platform's own
106
+ archon: `GET /my-projects` → `{"owned":[],"building":[]}`. Of the three catalog rows, `Demo` is owned by
107
+ another GitHub id and `Emersonian Circles` and `Example` have `owner_github_id` **NULL**. The
108
+ memberships directory is written only by the server-to-server check-in a *federated* instance posts on
109
+ sign-in — and the apex is not a federated client of itself.
110
+
111
+ That makes the empty state the **day-one** state, not an edge case, so the mock designs it: `0 projects`,
112
+ "You don't own or build on anything here yet", and a way out (turn the filter off, or start one). The
113
+ mock's rail carries a **real memberships** switch that reproduces it exactly, so the build cannot forget.
114
+ The data gap itself is **task 1002760** (§8), which now blocks carrier 1002744.
115
+
116
+ > **Its risk, recorded so the build can watch for it:** the sample data in the mock is *illustrative* —
117
+ > it marks one project owned and two built-on so the feature can be judged. Do not read it as a fixture.
118
+ > The switch, not the default, shows the truth.
119
+
120
+ ## 3. Why "your projects" is a view and not a filter
121
+
122
+ The owner's "only mine" toggle could have replaced the manage view outright. It does not, because the two
123
+ answer different questions and only one of them fits on an orb.
124
+
125
+ The manage card is **contractual**, and its order is fixed by
126
+ [`projects-surfaces-redesign-direction.md`](projects-surfaces-redesign-direction.md) §8: orb → name +
127
+ status chip → meta row → address row → optional attach-domain input → optional error paragraph → progress
128
+ strip → last-action message → actions. Behind it sit **eight** chip outcomes, **four** progress flows
129
+ (standup / revive / teardown / address) × three stages, a teardown confirm that swaps the actions row, and
130
+ **eleven** named refusal messages. None of that survives being drawn as a dot in a starfield.
131
+
132
+ So: the map answers *what exists and is any of it mine*, and the toggle makes that fast. "Your projects"
133
+ answers *what do I do about it*. The filter is a lens on the browse surface; the view is where the controls
134
+ live.
135
+
136
+ ## 3b. Search and filtering in the manage view
137
+
138
+ Added on the owner's ask, 2026-08-13: *"we should probably have some sort of search and filtering on the
139
+ Your Projects tab."* It is the one view that grows without bound — a builder with twenty projects has no
140
+ way to find one — and it was the only browse surface with no way to narrow.
141
+
142
+ **Search** matches name, repo slug and address, so `example-owner/spike` finds Spike Harbor and
143
+ `emersonian.cloudbongos.com` finds Emersonian Circles. Same predicate for all three fields; substring, not
144
+ fuzzy.
145
+
146
+ **The filter groups the chip outcomes; it never relabels them.** Five pills, each carrying a live count:
147
+
148
+ | Pill | Holds | Why |
149
+ |---|---|---|
150
+ | **All** | everything | |
151
+ | **Live** | `live` **and** `live?` | neither is known-down |
152
+ | **Needs you** | `unreachable`, `snagged` | the two that will not resolve on their own |
153
+ | **Working** | `queued`, `standing up`, `tearing down` | the platform is mid-flight; wait |
154
+ | **Torn down** | `torn down` | |
155
+
156
+ **This does not collapse the three active outcomes (C6).** Grouping `live` with `live?` under one *filter*
157
+ is not the same as printing one *label*: every card still says which it is, with its own recency. The rule
158
+ forbids a badge that claims more than the probe knows — it does not forbid a filter whose question is "is
159
+ this known to be down". A pill named "Up" would break it; "Live" holding both, with the cards unchanged
160
+ underneath, does not.
161
+
162
+ **Counts recompute against the search**, so typing a query and seeing `Needs you 0` is a real answer rather
163
+ than a stale one. An empty result says so and offers to clear.
164
+
165
+ ## 4. Navigation — one shell, three destinations, and a real URL
166
+
167
+ The persistent header is fixed in form by [`gate-navigation-direction.md`](gate-navigation-direction.md) §4:
168
+ a header belonging to the **page shell**, not the orb field, so it does not drift, scale or pan with the
169
+ sky. It replaces `.space-projects`, and the `body:not(.view-space)` hide rule is deleted rather than
170
+ extended — which is what closes defect 3.
171
+
172
+ `?view=` carries `map` (default) / `mine` / `new`, pushed with `history.replaceState` so a view is
173
+ linkable and back-button-able. `/create` redirects to `?view=new`, and the landing page's two existing
174
+ `/projects?view=new` links start working the day this ships.
175
+
176
+ **The nav carries a `Home` item, and it is not a view.** The first draft had only the three hub views, on
177
+ the assumption that the wordmark's link to `/` was door enough. Owner review killed that: *"I dont see
178
+ exactly how a landing page is going to fit in here. Theres no 'home' page at the top tabs."* A wordmark that
179
+ happens to be a link announces nothing, and after the apex flip `/` is a real destination with real content.
180
+
181
+ So the nav reads `Home │ Map · Your projects · New project`, with a hairline after Home. The two kinds of
182
+ destination are deliberately not levelled: **Home is a page**, so it navigates and never takes the
183
+ current-view pill; the other three are **views of this page**, so they swap in place and one of them is
184
+ always current. The relationship between the two surfaces is one-way by design — the landing page is the
185
+ stranger's front door and sends people *into* the hub (its "Start a project" and "See what's building" CTAs
186
+ both point here); the hub is where they stay. `Home` is the way back out, not a tab someone is expected to
187
+ live on.
188
+
189
+ > **A trap the build must not walk into, found while mocking:** the wordmark **types**, so its width changes
190
+ > every ~190ms. With the nav as the middle child of a `space-between` row, the tabs visibly slide left and
191
+ > right while the logo animates. Both flanks take `flex:1 1 0` so they compute to equal width and the nav is
192
+ > pinned dead centre regardless of what the mark is currently spelling. Measured: 0px drift across seven
193
+ > typed states. Below 820px the three groups stack and the nav takes its own centred row.
194
+
195
+ ## 5. The content spine
196
+
197
+ Ordered. **Portable** = true on every instance; **apex-only** = true of Cloud Bongos the platform.
198
+ Press `S` in the mock to outline the apex-only blocks, `C` to see the child-instance shape.
199
+
200
+ | | Section | Portable? |
201
+ |---|---|---|
202
+ | S0 | Head metadata — title + description from `{{productName}}`/`{{tagline}}` | server-stamped |
203
+ | S1 | Shell — self-typing wordmark, **Home │ Map · Your projects · New project**, hall link, mode toggle, identity chip | portable (hall link apex-only) |
204
+ | S2 | Toolbar — Sky \| Table, **only mine**, search + count | portable |
205
+ | S3 | Map · sky — orb field, owned marking, verification chip on owned orbs, hint rail | **catalog apex-only** |
206
+ | S4 | Map · table — Project / Builders / Type / Tags / **Status** / open | **catalog apex-only** |
207
+ | S5 | Your projects — **search + state filter**, then the manage cards (§3) | portable |
208
+ | S6 | New project — 4-step rail, the bongo pair, AGPL fine print | portable |
209
+ | S7 | Footer | split — commons claim apex-only |
210
+
211
+ Copy notes:
212
+ - The create pitch is verbatim from `create.html`, and the AGPL sentence from `create.html:391` — both
213
+ already public-facing and owner-approved. **Not newly invented.**
214
+ - **`/projects`' current lede is retired**, not reworded: "The same sky as the front door" described a page
215
+ the visitor never reached, and after the apex flip there is no separate front-door sky to be the same as.
216
+ - The self-typing wordmark **stays** — it is the sole carrier of the "type `bongos` in any AI" metaphor and
217
+ the one gate flourish that survives the ritual's removal (owner disposition, gate-navigation §4).
218
+ - **The entry ritual's copy dies with it**, including the table footer's "`esc` back to entry".
219
+
220
+ ## 6. The design system
221
+
222
+ The mock **links `cosmos.css`** and adds a page-local sheet. It does not fork it. The chips are literally
223
+ the `.chip .live/.maybe/.down/.bad/.busy/.calm` vocabulary the manage list already ships, the manage cards
224
+ are `.proj`/`.projHead`/`.addr`/`.strip`, and the buttons are `.btn`/`.btn-space` — the map and the
225
+ management page share components rather than resembling each other.
226
+
227
+ **These are authored page-locally in the mock and must GRADUATE into `cosmos.css` in the build**, not be
228
+ copied into the page (each is marked ★ in the mock's stylesheet):
229
+
230
+ | Component | What it is |
231
+ |---|---|
232
+ | `.shell` / `.navrow` | the persistent hub header + its three-destination nav, incl. the equal-flanks rule (§4) |
233
+ | `.toolbar` / `.seg` | the per-view control strip and the segmented Sky \| Table control |
234
+ | `.switch` | the two-state "only mine" filter |
235
+ | `.search` | the glass search field + result count — used by the map toolbar **and** the manage bar |
236
+ | `.mineBar` / `.filters` | the manage view's search + state-filter pills with live counts (§3b) |
237
+ | `.field` / `.worldOrb` | the orb field and a project rendered as an orb, incl. `.badge` and the owned ring |
238
+ | `.tbl` | the directory table |
239
+ | `.steps` | the 4-step create rail |
240
+ | `.fieldNote` | the honest empty / not-available-here state |
241
+
242
+ **Orb colour must be tokenized.** `projects.html:221-231` hashes five hardcoded hexes and five rgba glows
243
+ off the instance slug; two happen to equal `--sun-lit`/`--gold-soft`, three are orphans, and none follow a
244
+ re-theme. Keep the per-project variety — it is what makes a sky legible — but re-express the five as
245
+ `color-mix()` derivations off `--accent`, `--sea`, `--terracotta` and the locked `--sun-lit`/`--gold`, so
246
+ every orb accent lands inside the contrast test.
247
+
248
+ ## 7. Constraints the build must respect
249
+
250
+ - **C1 · One `:root`.** `injectBrandingGlobal()` splices the pack's `:root` at the **end of `<head>`, after
251
+ the stylesheet link** (`src/bongos/serve-internal.js:138-146`) — equal specificity, later in order, so the
252
+ pack wins. A page-local `:root` silently outranks it and defeats re-branding. Page-local custom properties
253
+ stay scoped to their component. The mock has **no** `:root` block; follow that.
254
+ - **C2 · Dark changes are made twice.** `:root[data-mode="dark"]` and the `prefers-color-scheme` twin are
255
+ byte-identical duplicates in `cosmos.css`. Both, every time — a `deepEqual` lockstep test compares them.
256
+ - **C3 · The page must ship a `.sky` element.** `themeMarkup()` emits `body{background:#f9d9a8}` after
257
+ cosmos.css in **both** modes and not mode-aware (`serve-internal.js:119`); `.sky` is the only mode-aware
258
+ full-page paint. Never ground the hub on `body`.
259
+ - **C4 · Never pin `--accent`, `--accent-deep`, `--sea`, `--terracotta` to a literal hex in a dark block**
260
+ (dark blocks are (0,2,0) and would outrank the pack permanently), and add every new fg/bg pair to
261
+ `tests/cosmos_token_contrast.mjs`'s `PAIRS` array — 32 pairs at 4.5:1 in **both** modes, CI-enforced.
262
+ - **C5 · Instance portability.** `public-landing/` ships wholesale to every instance. The catalog of other
263
+ instances, the "this platform" self-badge and the commons footer line are **apex-only** and go inside
264
+ `<!--apex-only:start--> … <!--apex-only:end-->` (server-stripped by `stripApexOnly()`,
265
+ `src/platform-server.js:75-97`) — removal, not CSS-hiding. The `<title>` becomes
266
+ `{{productName}}`/`{{tagline}}`. On a child, provisioning is `"default": false`, so the hub renders the
267
+ plain "projects aren't managed from this instance" state rather than falling into the generic alert.
268
+ - **C6 · Verification truth is load-bearing.** Three active outcomes stay three — `null` = never probed →
269
+ "live?", `false` = probed and down → "unreachable" (`modules/provisioning/provisioning.js:151`: *"Never
270
+ collapse the two."*). Liveness is an **overlay, never a lifecycle state**; an unreachable instance is
271
+ still `active` and still teardownable. Every liveness claim carries recency, and "live" only appears
272
+ inside `FRESH_MS` (12 min). **Map and list are two views of one truth** — never alive on one and
273
+ unreachable in the other.
274
+ - **C7 · Real markup, not JS-built.** The hub must read correctly to a crawler and with JavaScript off —
275
+ the exact failure task 1002746 had to repair on the gate.
276
+ - **C8 · The map must not run when it is not visible.** The gate's `requestAnimationFrame(tick)` at
277
+ `space.js:1847` writes a transform to every orb node with **no view guard** (`:631-654`), and `space.js`
278
+ assigns `document.body.className` **wholesale in 10 places** (`904, 961, 974, 979, 1241, 1248, 1374, 1394,
279
+ 1406, 1827`), which would destroy any hub-level body class on every view change. Those become `classList`
280
+ operations, `render()` gets a view guard, and the design does not rely on a persistent `body` class —
281
+ `data-mode` lives on `<html>`.
282
+ - **C9 · Motion respects `prefers-reduced-motion`.** The gate honors it throughout (`space.css:802-809`);
283
+ the typing wordmark, the chip pulse and any orb drift must too.
284
+
285
+ ## 8. Follow-on tasks this direction produced
286
+
287
+ | Task | Goal | What it does |
288
+ |---|---|---|
289
+ | **task 1002743** | 1000061 | **Build carrier 1 — the shell.** Retires the entry ritual, builds the persistent header + `?view=` contract across every view including the table, and carries the apex flip (part 3) with `platform_boot` unparked in the same change. Now **depends on 1002758**. |
290
+ | **task 1002744** | 1000061 | **Build carrier 2 — the map.** Owner-scoped feed, owned-orb identity with click-to-manage, and the verification chip on owned orbs. Now **depends on 1002758**. |
291
+ | **task 1002759** | 1000059 | **The dark-mode hero shadow** found in §0.4. Filed separately because it is a live fault on the shipped *landing* page and should not be buried inside a hub commit — the same reasoning that split task 1002749 out of task 1002747. |
292
+ | **task 1002760** | 1000061 | **The membership data gap** found in §2b — `GET /my-projects` is empty for the platform's own archon, and two of three catalog rows have a NULL owner, so "only mine" and owned-orb identity have nothing to render on the apex. **Blocks 1002744**, which is why it is a dependency rather than a note. |
293
+ | **task 1002761** | — | **`docs-entropy.js` is a silent no-op on Windows.** Found running it as a pre-ship check here: `git ls-files '*.md'` keeps its quotes through the shell Node uses on Windows, so git matches 0 of 339 tracked files and the tool reports a clean run. Unrelated to the hub, filed on its own. |
294
+
295
+ This document plus the approved mock are the contract for 1002743 and 1002744: **build what the mock shows;
296
+ do not redesign it.**
297
+
298
+ Also settled by this pass, for the carrier that lands it: **criterion 1000253 previously had no design
299
+ task.** Its only linked tasks were the two build carriers, both with empty `dependencies`, so nothing gated
300
+ the hub build on an approved mock and the criterion was unsatisfiable as written. Task 1002758 now carries
301
+ the criterion link and both carriers depend on it.
302
+
303
+ ## 9. What is deliberately still open
304
+
305
+ - **How the sky moves.** Pan, zoom, spotlight search, hover cards, the ghost orb, the minimap and the whale
306
+ are goal 1000031. The mock places orbs statically on purpose.
307
+ - **`view-detail` and `view-download`.** The gate has five views; the hub names three. The recommendation on
308
+ the table — not yet an owner decision — is to delete `view-download` (a 2.75s descent cinematic, a temple
309
+ `.stage` with non-functional tiles, a 44-frame buddha loop and a 190-line drag IIFE at
310
+ `gate/index.html:378-630`) and make the self-orb open the **same** detail card every other orb opens, kept
311
+ as an overlay *inside* the map rather than a fourth destination. That is ~380 lines and two sprite files.
312
+ - **Whether light mode needs a depth cue** beyond the gravity grid (§2's recorded risk).
313
+ - **What the light sky does at 40 projects.** Four orbs sit comfortably; the mock does not prove a crowd.
314
+
315
+ ## 10. Sign-off dispositions (owner, 2026-08-13)
316
+
317
+ 1. **Map first**, for signed-in owners too — asked as a two-option question, answered with a correction
318
+ worth keeping: *"The map shows 4 total projects, not all of which the user is a part of."* The four are
319
+ the platform's own orb plus `Demo`, `Emersonian Circles` and `Example` (verified via
320
+ `GET /projects`). The premise of the question — that the catalog held one project — **was wrong**, and
321
+ the "only mine" toggle exists because the owner corrected it.
322
+ 2. **The "only mine" toggle appears in the table too**, not just the sky — stated explicitly.
323
+ 3. **`/gate/` retires at the apex flip** rather than surviving as a redirect or an easter egg, *"since we
324
+ have already designed a landing page."*
325
+ 4. **The buddha is dropped** in favour of the bongo pair everywhere — chosen against the recommendation to
326
+ keep it in the create view.
327
+ 5. **The ground was not decided in the abstract.** The owner declined to pick from a description —
328
+ *"we should run through these where you publish versions and I approve"* — so all three were built and
329
+ rendered, and **B** was approved from the walked mock.
330
+ 6. **The nav-drift bug was caught by the owner in review**, not by the mock's author: *"the top tabs move
331
+ with the cloud ____ typing."* Fixed in §4 and pinned as a build constraint.
332
+ 7. **The invented ownership was caught by the owner in review**, and it turned out to be the biggest finding
333
+ of the pass: *"example and emersonian circles arent owned by me and i am not apart of them yet they
334
+ appear in only mine."* The mock had asserted ownership no row supports. Chasing it produced §2b — the
335
+ owner/builder vocabulary, the rule that `owner_github_id` is not the authority, the day-one empty state,
336
+ and **task 1002760**, which blocks carrier 1002744. The owner's second phrasing — *"not owned by me
337
+ **and** i am not a part of them"* — is exactly the `{ owned, building }` split the API already returns,
338
+ arrived at independently.
339
+ 8. **A missing door home was caught by the owner in review** (§4): the nav offered no route back to the
340
+ landing page. `Home` added, and deliberately set apart from the three views.
341
+ 9. **Malformed table controls were caught by the owner in review:** "Manage →" wrapped to two lines and the
342
+ status chip's recency dropped below its label, because nothing stopped the action and status cells
343
+ breaking. Both now claim their width and refuse to wrap; the name cell absorbs the slack (§6 `.tbl`).
344
+ 10. **Search + filtering on the manage view was asked for by the owner** and is §3b. The mock gained a
345
+ fifth card (`Mercury`, standing up) so the "Working" filter has a real member — and, incidentally, so
346
+ the standup progress flow is shown somewhere, which no other card did.
347
+ 11. **Approved to ship** on the owner's word, 2026-08-13, after four review rounds against the live mock.
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.92",
3
+ "version": "1.19.94",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.92",
9
+ "version": "1.19.94",
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.92",
3
+ "version": "1.19.94",
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",