@bongos/core 1.19.187 → 1.19.189

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.187",
6
- "core_contract": "1.19.187",
7
- "source_commit": "403b66bde87b5b97d9aec89a8ab95794d525cb0d",
5
+ "core_version": "1.19.189",
6
+ "core_contract": "1.19.189",
7
+ "source_commit": "106408b1519091ef056ef82d9bd542a68308e363",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-16T23:14:43.477Z",
9
+ "built_at": "2026-08-17T00:49:35.464Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 308,
12
+ "docs_redacted": 309,
13
13
  "agent_docs_stubbed": 21,
14
14
  "functional_verbatim": 1282,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1611,
20
- "tree_sha256": "3d648b4ac642a80bde4746eaaab7f61fc06cd888117fc17bc66751d8f1e15fc8",
19
+ "file_count": 1612,
20
+ "tree_sha256": "386f81ead8236148579f8ab7743305bf0e2edbd8d0349ad9125e23d90eba84fe",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -1222,7 +1222,7 @@
1222
1222
  {
1223
1223
  "path": "docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md",
1224
1224
  "mode": "0000644",
1225
- "sha256": "20fcf384ddef52e0ac09e52372cbd532ea3a4c40705dba7a84e48891a5c14256"
1225
+ "sha256": "dc8615b7e8b807ef69852ee4cdfcad7db0ab737a1ed733fc96ca712a4ad18ec2"
1226
1226
  },
1227
1227
  {
1228
1228
  "path": "docs/adr/0152-landing-gate-served-by-the-core-app.md",
@@ -1337,7 +1337,7 @@
1337
1337
  {
1338
1338
  "path": "docs/adr/0172-editable-rank-roles-substrate-axis.md",
1339
1339
  "mode": "0000644",
1340
- "sha256": "2b813d75d1fb2aa3f9978a6dee7855f963444f1734bed5766ef269dae7637a2c"
1340
+ "sha256": "390339e26a5e05fd65c8bd4f9303434a8d799e4747b6c1921c2abcc859a331ae"
1341
1341
  },
1342
1342
  {
1343
1343
  "path": "docs/adr/0172-per-craft-compensation-ideator-credit-lane.md",
@@ -1354,10 +1354,15 @@
1354
1354
  "mode": "0000644",
1355
1355
  "sha256": "c645ce8202fa8e8faa59d3aa00a8167477b5223817b760a733b38864d7625c1d"
1356
1356
  },
1357
+ {
1358
+ "path": "docs/adr/0175-the-board-room-full-idea-ratification.md",
1359
+ "mode": "0000644",
1360
+ "sha256": "aaff11b955bcbacaebf2475d01034dce1c47c70c22534195aebbf90767b025f6"
1361
+ },
1357
1362
  {
1358
1363
  "path": "docs/adr/README.md",
1359
1364
  "mode": "0000644",
1360
- "sha256": "79b6d2e5dee626f509ace71bcd133e707ae26b7cbe96a64eb93ebf868c3aabf3"
1365
+ "sha256": "6748701da2559d6019116eb00e9aeeaad947e08d17f9c9cf77e8f45c19e2c69f"
1361
1366
  },
1362
1367
  {
1363
1368
  "path": "docs/api-reference.md",
@@ -1372,7 +1377,7 @@
1372
1377
  {
1373
1378
  "path": "docs/architecture.md",
1374
1379
  "mode": "0000644",
1375
- "sha256": "f6fc3ee98615f246b4a79b89f17641bf96a8da3c07fa30ddb0fcc0112118897e"
1380
+ "sha256": "497b1fbf18ec1cf6d7e0f3620669cfba9008bc6a40e1f70e4b5f53d3406bc12e"
1376
1381
  },
1377
1382
  {
1378
1383
  "path": "docs/branding-contract.md",
@@ -1387,7 +1392,7 @@
1387
1392
  {
1388
1393
  "path": "docs/canonical-permissions.md",
1389
1394
  "mode": "0000644",
1390
- "sha256": "7f32dfe18655bec5890fbaf00491c8ff7fd1f960f0de3caf1cf56ab34562e4fa"
1395
+ "sha256": "9cd97486edfff51a2175c2e758ce99cd217658caec857fddaca366db338822ad"
1391
1396
  },
1392
1397
  {
1393
1398
  "path": "docs/design-contract.md",
@@ -1492,7 +1497,7 @@
1492
1497
  {
1493
1498
  "path": "docs/file-map.md",
1494
1499
  "mode": "0000644",
1495
- "sha256": "e174499ab9f798b88f5747ea143400ddfa3fa6602858dc7518de769c839831f5"
1500
+ "sha256": "a045f8b58bb2e52d770a24fe44524c27afaa4a24acd3e886e1a9a55cff24d3ed"
1496
1501
  },
1497
1502
  {
1498
1503
  "path": "docs/handoff-template.md",
@@ -4257,12 +4262,12 @@
4257
4262
  {
4258
4263
  "path": "package-lock.json",
4259
4264
  "mode": "0000644",
4260
- "sha256": "436a51acc58194d24659f69a9db624e06296dde02416cc2c3bf2ef2086f35ff4"
4265
+ "sha256": "15ace363831ad92eff83b61408618af68029feb1701bc757dc007390cfbc13f7"
4261
4266
  },
4262
4267
  {
4263
4268
  "path": "package.json",
4264
4269
  "mode": "0000644",
4265
- "sha256": "5dfe0314cb6157006b6eeb88e03cb8c2d2d20a6535d1f303903cb336cd06ae86"
4270
+ "sha256": "31315335f0107717d68755300632cd57b25f62b6d58a6b5309ba82030bf894ce"
4266
4271
  },
4267
4272
  {
4268
4273
  "path": "public-docs/index.html",
@@ -5867,7 +5872,7 @@
5867
5872
  {
5868
5873
  "path": "src/module-api.js",
5869
5874
  "mode": "0000644",
5870
- "sha256": "5034caf71ab288ff969e2ca31c4b80c5c97e62b327711f5de6e6e53e13ce6c13"
5875
+ "sha256": "a47c1e24a6e69d6b109956b1fe0e9acc34905fc148de1199a132301d66e3d597"
5871
5876
  },
5872
5877
  {
5873
5878
  "path": "src/module-loader/catalog.js",
@@ -10,6 +10,13 @@
10
10
 
11
11
  ---
12
12
 
13
+
14
+ > **⚠ VOCABULARY AMENDED by [ADR 0174](<redacted>.md) (owner directive, 2026-08-16) — the DECISION below is unchanged.**
15
+ > What this ADR calls *governance* is now the **government**; what it calls *seeded roles* / *rank-roles* are now simply **ranks**. The word *role* is reserved for the three Cloud Bongos crafts — Artist, Ideator, Builder — and appears nowhere on the government side.
16
+ > Concretely: `governance_roles` → `government_ranks`, `governance_builder_roles` → `government_builder_ranks`, `governance_role_permissions` → `government_rank_permissions`, `role_key` → `rank_key`, `governance.manage` → `government.manage`, `page.view.governance` → `page.view.government`, `/governance/roles/*` → `/government/ranks/*`, and `modules/governance/` → `modules/government/`.
17
+ > **The body below is deliberately left in the old vocabulary.** An ADR records what was decided and why at a point in time; rewriting it to match today's words would erase the evidence that the words changed — which is the one thing a reader who hits "rank-role" in an old session log actually needs. Every decision it makes still holds; only the nouns moved. A `fitness.js` check now enforces the new vocabulary, and excludes this file by construction.
18
+
19
+
13
20
  ## Context
14
21
 
15
22
  Authority in Cloud Bongos is a **single rank threshold** today. [ADR 0016](<redacted>.md) put authority in one DB column (`builders.rank`), checked server-side per request with no caching; [ADR 0018](<redacted>.md) / [ADR 0034](<redacted>.md) wired the four live ranks into the ordered tier `xenos (1) < thetes (2) < metic (3) < archon (4)`. Every privileged route calls `requireRank(...allowed)`, which admits a builder whose rank sits **at or above** the lowest-authority rank named (a threshold, [#591](https://cloudbongos.com/builders#/task/591)). That design is sound and is **not** being replaced — it is the substrate this ADR builds *on top of*.
@@ -6,6 +6,13 @@
6
6
  - **Amends:** ADR 0151 §2 (the "four seeded rank-roles are immutable through this API" wall — the GRANT half only)
7
7
  - **Related:** ADR 0016 (trust boundary — server-enforced, uncached, per request), 0043 (git/ssh trust boundary + the rank floor on protected paths), 0157 (the archon→metic delegation of nineteen operational keys)
8
8
 
9
+
10
+ > **⚠ VOCABULARY AMENDED by [ADR 0174](<redacted>.md) (owner directive, 2026-08-16) — the DECISIONS below are unchanged.**
11
+ > What this ADR calls *governance* is now the **government**; what it calls *seeded roles* / *rank-roles* are now simply **ranks**. The word *role* is reserved for the three Cloud Bongos crafts — Artist, Ideator, Builder — and appears nowhere on the government side.
12
+ > Concretely: `governance_roles` → `government_ranks`, `governance_builder_roles` → `government_builder_ranks`, `governance_role_permissions` → `government_rank_permissions`, `role_key` → `rank_key`, `governance.manage` → `government.manage`, `page.view.governance` → `page.view.government`, `/governance/roles/*` → `/government/ranks/*`, and `modules/governance/` → `modules/government/`.
13
+ > **The body below is deliberately left in the old vocabulary.** An ADR records what was decided and why at a point in time; rewriting it to match today's words would erase the evidence that the words changed — which is the one thing a reader who hits "rank-role" in an old session log actually needs. Every decision it makes still holds; only the nouns moved. A `fitness.js` check now enforces the new vocabulary, and excludes this file by construction.
14
+
15
+
9
16
  ## Context
10
17
 
11
18
  The governance tab (BV1.R110/R111) let an Archon build custom roles and toggle their operational permissions, but rendered all four **rank roles** — Newcomer/`xenos`, Contributor/`thetes`, Trusted/`metic`, Owner/`archon` — read-only. The owner asked why, and then asked for them to be editable.
@@ -0,0 +1,243 @@
1
+ # 0175 — The Board Room: Full Idea ratification as the first upward-pointing gate
2
+
3
+ - **Status:** Accepted
4
+ - **Date:** 2026-08-17
5
+ - **Task:** [#1003014](https://cloudbongos.com/builders#/task/1003014) (R01 of goal 1000069 — the Board Room)
6
+ - **Related:** ADR 0151 (permissions-as-atoms), 0157 (Archon is rank and identity only), 0162 (verdicts advisory, never self-executing), 0172-per-craft (the ideator credit lane — stream 3), 0174 (government, not governance; "role" means a craft), 0037 (Discord channel layout), 0016 (trust boundary), 0086 (goals + scope walls)
7
+ - **Spec:** [`docs/specs/bongos-v1-board-room.md`](../specs/bongos-v1-board-room.md) — the planning session that produced this decision, with the full interview record
8
+ - **Source ideas:** 1000738 (the Board Room), 1000754 (scoping brief)
9
+
10
+ ## Context
11
+
12
+ **Every gate in this system points down the rank ladder.** Rank floors, protected paths,
13
+ the grader, Archon approvals — each one constrains someone below the person who set it.
14
+ Nothing points up. An Archon can ship whatever they want, and on 2026-08-16 the owner named
15
+ that as a loophole they can walk through at will:
16
+
17
+ > *"I am a little unsure about just implementing without team buy-in… Otherwise I can just
18
+ > ship and build as I want, finding loopholes."*
19
+
20
+ The most senior person on the project asked for a structure that can slow **them** down. That
21
+ framing is the specification, and it is why the decision below is about *legitimacy* rather
22
+ than about permissions — the permission system (ADR 0151) already works, and adding a rank
23
+ floor would only point the gate downward again.
24
+
25
+ Three constraints shaped what could actually be built.
26
+
27
+ **1. The ADR 0162 discipline.** Verdicts are advisory and never self-executing. A gate that
28
+ blocks a seeding until a quorum is reached would violate that; a gate that merely records an
29
+ opinion would be theatre. The resolution turned out not to be a compromise between them —
30
+ see Decision 1.
31
+
32
+ **2. Franchise cannot be role-derived.** ADR 0174 §5 freed the word "role" for the three
33
+ crafts (Artist, Ideator, Builder), which makes a craft-scoped voting chamber superficially
34
+ attractive: an Ideator chamber for ideas, a Builder chamber for seedings. It is not viable.
35
+ `PATCH /me/disciplines` is deliberately ungated — *"a builder owns their own profile"*
36
+ (`src/bongos/routes/me.js`) — so self-selecting into a chamber would be a one-request
37
+ privilege escalation. Role also gates nothing anywhere in the codebase today; authority runs
38
+ rank → rank-role → permission, end to end. **Franchise therefore derives from rank**, and the
39
+ role-chamber model is rejected.
40
+
41
+ **3. The scale is the "circle" rung.** The governance synthesis this session worked from
42
+ (*The Six Variables of Governance*, Verro Labs, Aug 2026) argues that formality is adopted
43
+ only where informal coordination breaks, and that the thresholds are set by human cognitive
44
+ constants: an executive differentiates around 9 people, written law separates around 50,
45
+ adjudication separates around 150. This project sits at 3–8. A seven-preset Charter Builder
46
+ is a 150-rung constitution, and shipping one now would be building the wrong rung.
47
+
48
+ ## Decision
49
+
50
+ ### 1. The board's subjects are exactly two, and both are rare by construction
51
+
52
+ The board votes on a **Full Idea** (`modules/ideas`, goal 1000062 — the five-field graded
53
+ deliverable), and on a **change to the constitution itself**. Nothing else. Claims, seedings,
54
+ promotes, ships and grades behave exactly as they do today; Quick Ideas and Sparks keep
55
+ promoting straight to a task, untouched.
56
+
57
+ Idea 1000738 also wanted votes on task-set seedings and *"anything a member puts up"*. The
58
+ owner narrowed it — *"only Full Detail Ideas (E.g. new goals) should need ratification,
59
+ everything else should function as is"* — and then re-widened it by exactly one subject, so
60
+ that the rule constraining the owner cannot be weakened by the owner alone.
61
+
62
+ **This is what dissolves the ADR 0162 tension rather than compromising on it.** A board vote
63
+ gates no build path, so nothing self-executes because there is nothing downstream to execute.
64
+ Ratification confers legitimacy and triggers a credit award; it does **not** auto-create the
65
+ goal (goal 1000062 already settled that a Full Idea is not auto-converted — the conversion
66
+ recommendation stays a human step).
67
+
68
+ Board items carry a `subject_type` (`full_idea` | `constitutional_amendment`) **from day one**.
69
+ A third subject should be a row, not a migration.
70
+
71
+ ### 2. A vote is a timed sitting, not a quorum
72
+
73
+ Asking *"how many votes must we collect"* produces deadlock — Linz's problem, no
74
+ constitutional exit. We invert it: members are notified that a vote is wanted within a window,
75
+ and **an unvoted window nulls that member's vote** — they drop out of the denominator. They
76
+ are never counted as a no.
77
+
78
+ **The clock is the deadlock exit.** This is why no shotgun buy-sell or fork-with-treasury-split
79
+ clause is needed at this scale: absence cannot stall anything, so there is no state for such a
80
+ clause to resolve.
81
+
82
+ Default window: **90 minutes**, closing early the moment every member has voted, so latency is
83
+ `min(full turnout, window)`. Stored in minutes and set per project.
84
+
85
+ Stated plainly because it is the owner's explicit intent, not an accident: **a short window
86
+ means whoever is awake governs.** Standing accrues to those actively governing. The window
87
+ length is a governance lever, not a UX detail.
88
+
89
+ ### 3. Consent, not majority — and a zero-vote close passes
90
+
91
+ Silence is consent. A **single reasoned objection** returns the idea to its author. A window
92
+ that closes with **no votes at all passes** — the idea already cleared the completeness gate to
93
+ reach the board, and absence never blocks.
94
+
95
+ This makes both halves of the owner's intent true at once: pace is never obstructed, and only
96
+ an active participant can change an outcome. It also makes the feedback mechanism in Decision 4
97
+ load-bearing rather than decorative — an objection must carry a reason and a section flag to
98
+ count at all.
99
+
100
+ Trade-off recorded deliberately: with five members, 4-yes/1-no returns the idea. That is real
101
+ minority-block power. The cost of a wrong objection is one revision cycle, not a kill.
102
+
103
+ ### 4. A rejection carries a reason and one of the five sections — and that forces the surface
104
+
105
+ A Full Idea that fails, **whether on completeness grade or on the vote**, returns to its
106
+ originator rather than dying or stalling. Every rejection carries free text **plus exactly one
107
+ of the five Full Idea sections** flagged as the cause. A sub-bar grade flags its weakest
108
+ section automatically, using the per-field scores `completeness.js` already computes — which
109
+ also means a resubmission can be checked against the flagged section.
110
+
111
+ **This requirement is what makes the hall the only possible voting surface.** A Discord
112
+ reaction can express yes or no and nothing else, so reaction-voting would make every
113
+ Discord-cast rejection feedback-free — precisely what this decision exists to prevent. The hall
114
+ is not the *richer* surface; it is the only one that satisfies the rule.
115
+
116
+ Resubmission is unbounded in v1 — the grade gate already bounds spam — and every past rejection
117
+ stays visible on the item's history.
118
+
119
+ ### 5. The completeness grade is the floor; the vote is the merit
120
+
121
+ A Full Idea must clear the completeness pass bar (60, ADR 0172-per-craft) before a window can
122
+ open, and a window opens **automatically** on that pass.
123
+
124
+ Two gates doing two jobs: the deterministic scorer asks *is the thought fully expressed*, the
125
+ board asks *is it worth doing*. Board time is never spent on what a free, reproducible check
126
+ could bounce.
127
+
128
+ Consequence to design for, and a direct result of automatic opening at a 90-minute default:
129
+ **concurrent windows are normal.**
130
+
131
+ ### 6. Who governs is configuration, and day one is monarchy
132
+
133
+ The membership predicate, the pass rule, and the window live in `config/government.json`,
134
+ resolved **per request and uncached** so the ADR 0016 instant-demotion property survives.
135
+
136
+ Day one this instance runs `membership: rank:archon`, `pass_rule: first_ratifier`, no clock —
137
+ **monarchy, expressed as configuration on the real machinery rather than as a separate code
138
+ path.** The board path therefore executes from the first ratification, and flipping the switch
139
+ later changes numbers, not a code path that has never run. The documented recommended starting
140
+ point for a new project is: all Archons, one vote each, consent, 90-minute window.
141
+
142
+ ### 7. Amendments are decided under whatever rule the current constitution names
143
+
144
+ Changing the constitution is a board subject (Decision 1). It is decided by **whatever rule is
145
+ currently in force** — so under monarchy, "the board must ratify" resolves to "the Archon
146
+ ratifies", and flipping *out* of monarchy is a legal act of the monarchy. Every change after
147
+ that belongs to the board.
148
+
149
+ **No bootstrap special case is required**, and none should be added. This is how a
150
+ constitution's own amendment procedure normally works, and inventing an exception here would
151
+ create exactly the loophole this ADR exists to close.
152
+
153
+ ### 8. Discord is an outbound notification mirror that casts nothing
154
+
155
+ On window open, the board channel receives an announcement mentioning the members whose vote is
156
+ wanted, carrying a deep link to that item in the hall. State changes — closed, outcome — are
157
+ mirrored. **Discord reads nothing inbound and casts no vote.**
158
+
159
+ The mention *is* the "vote within X" notice, and Discord's own mobile app *is* the mobile push
160
+ — **no mobile surface needs to be built.** The bot has no DM capability today, and a channel is
161
+ the better shape regardless: it is a room, it is auditable, and deliberation sits beside the
162
+ vote. Per-rank view access follows ADR 0037.
163
+
164
+ `modules/discord/discord-approvals.js` (task 1100) is the precedent for **how to broadcast and
165
+ how to re-check a live rank** — *"the bot asserts only who reacted; the GDS decides what they
166
+ may do"* — and explicitly **not** for how to vote, per Decision 4.
167
+
168
+ ### 9. Open ballot
169
+
170
+ Member, direction, timestamp, and objection reason are visible to all members. A board whose
171
+ votes are invisible cannot constrain anyone, which is the entire purpose of an upward-pointing
172
+ gate. It also makes the vote-karma in Decision 10 auditable.
173
+
174
+ ### 10. Voting earns karma
175
+
176
+ A small award per vote cast in-window (proposed `+1`); the Full Idea's author earns karma on
177
+ ratification, mirroring `KARMA_RATIFY_DELTA` (`+3` — tuned down from `+5` in V3.R28 / task 248;
178
+ do not copy the stale `+5` still printed in `planning-session/SKILL.md` and `openapi.json`).
179
+
180
+ **Decided against the recommendation, with the risk accepted knowingly.** Under consent a *yes*
181
+ is one click while a *no* requires a written reason and a section flag, so equal pay for unequal
182
+ effort tilts toward assent. Accepted because **the item volume is too low to farm** — the
183
+ board's only subjects are Full Ideas and constitutional amendments, both rare by construction.
184
+ Revisit if item volume grows; the award is one constant.
185
+
186
+ ### 11. An author may never vote on their own item
187
+
188
+ Server-side, on the `peer_votes` anti-self precedent (migration 058, `UNIQUE(voter, target)`).
189
+ This is the bright line that keeps ratification from being ceremonial, and it is the one rule
190
+ that survived from a much larger scrutiny mechanism the owner cut.
191
+
192
+ ## Consequences
193
+
194
+ **Goal 1000067 (IC5, task 1002999) is unblocked by the pass event, and by nothing else.** ADR
195
+ 0172-per-craft is explicit that stream 3 *"consumes the Board Room's pass event; invents no
196
+ parallel vote."* There is exactly one vote surface in this system. The event fires once per
197
+ ratified idea and must be idempotent across replays, re-closes, and a resubmission that passes
198
+ again. `economy` is deliberately outside this goal's scope: we emit, 1000067 pays.
199
+
200
+ **The permission keys must land with their grant migration in the same deploy as the code
201
+ constant.** `government_rank_permissions.permission_key` stores the key as text while
202
+ `catalog.js` holds it as a constant; if the rows change while old code is serving, the check
203
+ fails closed — on the very tab an owner would use to investigate (ADR 0174 §Consequences). The
204
+ grant migration is load-bearing, not bookkeeping: `governance_002` is run-once, so an
205
+ already-migrated database never learns a key added only in code.
206
+
207
+ **Board state lives in `modules/government/`, which is protected.** All board work is therefore
208
+ Archon-gated. This was chosen over `modules/ideas/` (subject-ownership) on the grounds that the
209
+ board is an authority mechanism. The rename that created that folder landed on `origin/main` in
210
+ `14dcedd`; note that task 1003005 reads `abandoned` but was *absorbed* into 1003004 and shipped
211
+ there — read the note, not the status.
212
+
213
+ **Goal 1000069 is walled to the `governance` alias, not `government`.** Prod served core
214
+ 1.19.179 while the new scope key landed in 1.19.180, so the live server rejected the new key at
215
+ goal-creation time. The alias carries identical globs. **Re-point `scope_modules` once 1.19.180
216
+ is deployed.**
217
+
218
+ **The charter library ships without the Charter Builder.** The Government page presents all
219
+ seven constitutions, the three trajectories and the ladder thresholds, marking which are
220
+ selectable today. This is the reference half only — the configuration machinery is deliberately
221
+ absent, per the scale argument in Context 3. At two builders this is the half that earns its
222
+ keep, and its stated purpose is getting a team up to speed before deciding when to flip the
223
+ switch.
224
+
225
+ **The agora auto-link from idea 1000738 is deferred, not dropped.** Linking discussion *in*
226
+ would mean reading Discord inbound, contradicting Decision 8. Once goal 1000064 makes the Agora
227
+ a hall surface, the link is hall→hall and needs no adapter. Filed as idea 1000757.
228
+
229
+ **Rejected: quadratic vote weighting and the attribution-economy knobs.** The synthesis doc's
230
+ Part V spends its length on meter-weighted franchise — the Solon problem, compressing whales
231
+ with √credits, the drift from timocracy toward isonomia. None of it applies here, because v1's
232
+ franchise is a flat membership rule and is not weighted by credits at all. Hop decay (γ), time
233
+ half-life (τ), the 30% stack cap and vote coupling belong to the ideator credit lane, not to
234
+ this decision.
235
+
236
+ **Rejected: eternity clauses in v1.** Fork rights with an asset-split rule, meter transparency,
237
+ and a dead-man's switch on founder inactivity are real and worth having — Germany's Basic Law
238
+ Art. 79(3) and MolochDAO's ragequit are the precedents — but nothing in v1 depends on them, and
239
+ an unamendable floor written before the amendable part has ever run would be guesswork.
240
+
241
+ **Rejected: any legal-entity integration.** Equity issuance, Rev. Proc. 93-27 profit interests,
242
+ Subchapter T patronage, and the Howey posture are a later version's problem. v1 credits stay
243
+ reputation- and governance-weighted only, which is also what keeps the Howey question asleep.
@@ -220,7 +220,7 @@ This keeps the decision history honest and traceable.
220
220
  | 0146 | [Configurable reward mode — an instance chooses whether a shipped task pays BOTH reward streams or ONLY the cost-plus one ([task 1002270](https://cloudbongos.com/builders#/task/1002270), goal 1000037; follow-up to [ADR 0120](<redacted>.md)). A shipped task pays two streams onto one balance (the [ADR 0054](<redacted>.md) "two conventions, one ledger" tension): the per-task author ESTIMATE (`credits_reward` × kind multiplier — unitless, [ADR 0023](<redacted>.md)) AND the cost-plus SESSION reward (`round(true_cost_usd × 1.20)`, 1 credit = $1 — ADR 0054). New `branding.reward.mode`: `"cost-plus-and-estimate"` (DEFAULT — pay both, exactly today's behavior; every existing instance unchanged on upgrade) or `"cost-plus-only"` (the cost-plus reward is the SOLE equity reward; the per-task estimate PAYOUT is withheld and its idea-promotion slice cascades to 0). Resolved by a pure `rewardPolicy()`; gated in the single per-task credit writer (`insertMultipliedConfirmCredit`) — entirely inside the economy module, ZERO lifecycle changes. `credits_reward` still rides the task row for display + the no-zero-reward claim gate; only the payout is suppressed. Unknown mode → default (a typo can't silently zero rewards). Cloud Bongos selects `cost-plus-only`; achievements + the net-negative +1 bonus are out of scope. Backward-compatible + reversible — no clawback, no migration.](<redacted><redacted>.md) | GDS / economy |
221
221
  | 0149 | [`bongos dev` — a one-command LOCAL launcher for a standalone instance repo (owner ask, 2026-07-19: "we need a better option to stand up the local host"). A freshly-created project's `config/branding.json` points at `http://localhost:<port>` — configured to run on the owner's machine — but the platform shipped no command to START it there; `bongos onboard` provisions a CLOUD server and Docker serves a vanilla brand on `:3000`. Standing it up by hand was a six-part assembly (Postgres → createdb → migrate → PORT/PGDATABASE/PGHOST/OAuth env → server → login) with three silent mismatches: the server reads PORT from env not branding (platform-server.js:44); the pool DB name collapses to the OS user while migrate.sh defaults to `example` (pool.js:47 vs migrate.sh:52) unless PGDATABASE is set for BOTH; and node-pg defaults to the Linux peer socket `/var/run/postgresql` (pool.js:46), absent under Homebrew on a Mac. `bongos dev` does the whole thing idempotently from one source of truth (branding): ensures Postgres, createdb, migrate (`MEDUSA_GDS_ONLY=1`), starts the server on the branding port, and signs in. The background server is MANAGED (pid/log per instance) with `bongos dev stop`/`status` — the fix for the orphaned-server accident (a stale `:3005` answering a new project's login). Pure resolution + process mgmt in `scripts/gds/dev-lib.js` (unit-tested `tests/dev_lib.mjs`); orchestration in `scripts/gds/dev.js`. Alternatives rejected: cloud dev box (needs hosting + cost — kept for remote work), Docker (vanilla brand/wrong port — kept for Windows), recipe-only (leaves the six steps). Not bundled into the standalone on-ramp binary (needs a real checkout).](<redacted>.md) | Cloud Bongos / dev experience |
222
222
  | 0150 | [Box first-boot bring-up on vendored instances — resolve `infra/` from the instance root + fail loud on empty user-data (spike BV1.R97, [task 1002385](https://cloudbongos.com/builders#/task/1002385); C2 of goals 1000051/1000052, "make cloudbongos boxes stop coming up bare"). Root cause: `box.js` sets `REPO_ROOT` two dirs up from itself, which on a VENDORED instance is the `@bongos/core` package — but the R89 packaging split kept `infra/` (the DO cloud-init template + inlined `box-source-fetch.sh`/cloudflared/ttyd/heartbeat scripts) as INSTANCE content, not in the core publish-manifest. So `readCloudInit` reads a missing template, its `try/catch` returns `null`, and the caller's only guard (`0 > 64KiB`) passes → the box is created with EMPTY user-data and boots bare Ubuntu (no clone, no toolchain, no terminal); `fileGzB64` is likewise fail-soft (warns, returns `''`) so a partial `infra/` half-wires. Live re-confirmed 2026-07-19: instance-root `infra/` present, vendored-core `infra/` gone (the [ADR 0144](<redacted>.md) node_modules workaround wiped by a reinstall), fleet idle so the bug is latent-but-live (next provision boots bare). Fix (R98, [task 1002386](https://cloudbongos.com/builders#/task/1002386)): a `resolveBoxInfraDir()` locating `infra/` via [ADR 0108](<redacted>.md)'s `resolveInstanceRootExplicit()` (cloudbongos `bongos.config.json` = `{"instanceRoot":"."}`) + an env override + a walk-up-out-of-`node_modules` fallback, AND fail-loud backstops (throw on missing template; abort provision on empty user-data). R99 ([task 1002387](https://cloudbongos.com/builders#/task/1002387)) then ensures the toolchain builds on the box. Reinstall-proof + portable; core-only, no migration/doorway change.](<redacted>.md) | GDS / dev boxes |
223
- | 0151 | [Governance: **permissions are the atom, ranks become seeded roles** — the foundation of the BONGOS-V1 Governance goal (1000030), spike BV1.R90 ([task 1001838](https://cloudbongos.com/builders#/task/1001838)); settles the model in an ADR before R93–R114 build. Authority stops being an all-or-nothing rank threshold ([ADR 0016](<redacted>.md)/0018/0034) and becomes granular **permissions** (code constants that map 1:1 to real routes/surfaces — a permission no route consumes doesn't exist), bundled into assignable **roles**; the four live ranks become four seeded roles whose grants reproduce today's thresholds EXACTLY (the compat seed — cumulative nested supersets, so the resolver's UNION preserves the at-or-above threshold), and `builders.rank` stays as the identity/graduation column. A per-request **uncached** `resolveBuilderPermissions()` (kernel port, preserving ADR 0016's instant-demotion) + a `requirePermission()` gate that coexists with `requireRank` via the seed → gates migrate route-by-route, no flag day. The **complete authority model** (C3) represents four axes as first-class types, not rank special-cases: rank-seeded roles, machine **principals** (`system_role`=bfg/discord_bot, exact-identity gate, never UI-grantable), **session-scopes** (box tokens, deny-by-default allow-list intersected with the builder's roles), and **ownership-scoped** perms (`X.manage.own` ≠ `.any`; goal owner/manager per [ADR 0106](<redacted>.md)). The safety keystone (C6): every permission carries a **`system` flag** — `system:true` (deploy, protected-path, rank-set, version-close, grade-bypass, cross-tier edges) is **non-grantable** and LOCKED in the tab, so no configurable role can hand out the crown jewels; and the today-hardcoded `PROTECTED_GLOBS`/`EXPECTED_RANKS` map becomes a **governance-owned protected-surface registry** that the OUT-OF-BAND substrate (pre-push hook, grader pre-pass, `main-audit.js`, gate-review — [ADR 0043](<redacted>.md)) READS but never moves in-process: **policy owns / substrate enforces** — the tab can re-map the floor but a forced `system` grant still can't deploy (abuse-matrix + live-demo proofs, R112/R114). Capability in **core** (`modules/governance/`, default:true); role templates are per-instance **config** (`config/governance.json` over `config/governance.neutral.json` over env, mirroring `src/branding.js`), live assignments in the DB. Collapses the ~6 duplicated numeric rank-tier maps (the Builder-25-incident drift class) behind the resolver. Zero day-one behavior change (parity test R103); one deliberate fail-closed divergence (unwired divine ranks map to no role instead of latently inheriting Archon). Includes the full enumerated permission catalog (every key + `system` flag) grounded in the 2026-07-24 authority sweep. No new recurring cost.](<redacted>.md) | governance / permissions / Cloud Bongos |
223
+ | 0151 | [Governance: **permissions are the atom, ranks become seeded roles** — the foundation of the BONGOS-V1 Governance goal (1000030), spike BV1.R90 ([task 1001838](https://cloudbongos.com/builders#/task/1001838)); settles the model in an ADR before R93–R114 build. Authority stops being an all-or-nothing rank threshold ([ADR 0016](<redacted>.md)/0018/0034) and becomes granular **permissions** (code constants that map 1:1 to real routes/surfaces — a permission no route consumes doesn't exist), bundled into assignable **roles**; the four live ranks become four seeded roles whose grants reproduce today's thresholds EXACTLY (the compat seed — cumulative nested supersets, so the resolver's UNION preserves the at-or-above threshold), and `builders.rank` stays as the identity/graduation column. A per-request **uncached** `resolveBuilderPermissions()` (kernel port, preserving ADR 0016's instant-demotion) + a `requirePermission()` gate that coexists with `requireRank` via the seed → gates migrate route-by-route, no flag day. The **complete authority model** (C3) represents four axes as first-class types, not rank special-cases: rank-seeded roles, machine **principals** (`system_role`=bfg/discord_bot, exact-identity gate, never UI-grantable), **session-scopes** (box tokens, deny-by-default allow-list intersected with the builder's roles), and **ownership-scoped** perms (`X.manage.own` ≠ `.any`; goal owner/manager per [ADR 0106](<redacted>.md)). The safety keystone (C6): every permission carries a **`system` flag** — `system:true` (deploy, protected-path, rank-set, version-close, grade-bypass, cross-tier edges) is **non-grantable** and LOCKED in the tab, so no configurable role can hand out the crown jewels; and the today-hardcoded `PROTECTED_GLOBS`/`EXPECTED_RANKS` map becomes a **governance-owned protected-surface registry** that the OUT-OF-BAND substrate (pre-push hook, grader pre-pass, `main-audit.js`, gate-review — [ADR 0043](<redacted>.md)) READS but never moves in-process: **policy owns / substrate enforces** — the tab can re-map the floor but a forced `system` grant still can't deploy (abuse-matrix + live-demo proofs, R112/R114). Capability in **core** (`modules/governance/`, default:true); role templates are per-instance **config** (`config/governance.json` over `config/governance.neutral.json` over env, mirroring `src/branding.js`), live assignments in the DB. Collapses the ~6 duplicated numeric rank-tier maps (the Builder-25-incident drift class) behind the resolver. Zero day-one behavior change (parity test R103); one deliberate fail-closed divergence (unwired divine ranks map to no role instead of latently inheriting Archon). Includes the full enumerated permission catalog (every key + `system` flag) grounded in the 2026-07-24 authority sweep. No new recurring cost. **Vocabulary amended by ADR 0174 (2026-08-16): governance→government, seeded roles→ranks; the decisions are unchanged.**](<redacted>.md) | governance / permissions / Cloud Bongos |
224
224
  | 0152 | [The landing gate is served by the **core app**, not by the front proxy — the cutover step of the landing migration ([task 1002411](https://example.com/builders#/task/1002411), L05 of goal 1000035). The reference instance's orb-gate front page was `file_server`'d by Caddy straight out of a checkout of an UNRELATED product repo (`root * <checkout>/brand/cloud-bongos`), so the landing had two sources of truth, no deploy path of its own, and a cross-product coupling the core could not express. [L01](https://example.com/builders#/task/1002407) had already ported the bundle into the core as `public-landing/` and [L02](https://example.com/builders#/task/1002408) had already taught `platform-server.js` to serve it (`/` -> 302 `/gate/`, `/gate/` serves the index raw, `express.static` covers the assets) — so by the time L05 came up, BOTH halves of its original plan ("give the landing (a) its own Caddy config and (b) its own deploy script") had dissolved. **Decision:** the app owns the landing end to end; the proxy drops `root` + `file_server` and keeps exactly three jobs on that surface — TLS, an optional pre-launch `basic_auth` lock, and the `@hidden` guard that keeps `gate/README.md` unreachable. No separate Caddy config to write (the resulting block IS the generic pure-proxy shape `provision.js`'s `caddyBlock()` already emits per instance, [ADR 0111](<redacted>.md) §4; host-specific hostnames/certs stay on the host per [ADR 0062](<redacted>.md) §7) and no separate deploy script to write (the landing ships INSIDE the pinned core package, so it rides the instance's existing pull-deploy — one artifact, one version, one path). Keeps `redir / /gate/ 302` because Caddy orders `redir` before `basic_auth`, so "/" behaves identically before and after, and the app issues the same 302 once the lock is lifted. Cost accepted: the landing now sits in the app's request path (a dead app = a dead front page — but the gate's whole purpose is to reach the app), and a landing tweak now needs a core release. Verified on the live instance: identical status codes across the apex and both vanity doors before/after, relative redirects (no origin leak), and a **severance test** — with the foreign repo's landing folder moved aside entirely the site still served the byte-identical gate, proving the dependency is cut rather than merely unused. Retiring the foreign copy is L06 ([task 1002412](https://example.com/builders#/task/1002412)).](<redacted>.md) | platform serving / instance infra |
225
225
  | 0152 | [**Metic gains task abandonment, paired with an un-abandon at the same rank** (owner directive 2026-07-27: "Metics should also be able to abandon tasks"; [task 1002476](https://cloudbongos.com/builders#/task/1002476)). [ADR 0090](<redacted>.md) moved task authoring (create/edit/promote/deps/criteria) down to the trusted working rank but kept `POST /tasks/:id/abandon` Archon-only as "terminal scope removal" — so the rank that runs idea-triage, seeds the tasks, and shapes them still had to hand every duplicate/moot/superseded chore back to the owner to retire. That hand-back is janitorial, not adjudication. The real hazard was never the grant: abandon was **one-way through the API** (`/promote` took only backlog/blocked, `PATCH` refuses `status`), so a mis-retire needed hand-SQL on prod, and an abandoned task is invisible in every claimable list and every version rollup (migration 017 excludes it from `version_progress`) — nobody notices until the work silently doesn't happen. So the gate moves to `requireRank('metic','archon')` **and** `/promote` gains a third source state, `abandoned → backlog` (never straight to ready — a retired task re-enters un-workable and takes a second deliberate promote), backed by `db.restoreTask`, the mirror of `abandonTask`, which clears the `'Abandoned: <reason>'` stamp and only that. Unchanged: the shipped-task and active-claim refusals, idempotency, and the `audit_log` record of who retired what and who brought it back. The `EXPECTED_RANKS` lifecycle pin moves in lockstep (a *further* downgrade stays a hard CI fail); under [ADR 0151](<redacted>.md) the `task.abandon` floor moves archon→metic, landing as `governance_003` because the compat seed is run-once — purely additive, and the drift guard now compares the **union** of grant migrations to the catalog and fails loudly on a future revocation.](<redacted>.md) | GDS / permissions |
226
226
  | 0153 | [**Sequential chain execution — one kickoff walks a dependency chain** ([task 1002484](https://cloudbongos.com/builders#/task/1002484)). [ADR 0015](<redacted>.md) made `dependencies[]` load-bearing and auto-promotes a task's dependents `backlog`→`ready` on ship — but nothing *picks the unblocked task up*, so on the live instance **146 of 303 open tasks sit behind a predecessor** and a 24-task planning seed needed 24 separate human kickoffs. The only "sequential" affordance was a clipboard prompt on the Tasks board (`<redacted>`), which is text rather than execution and cannot even select the gated successors, because they are still `backlog`. Requested independently by two builders (ideas 1000461, 1000398). **Decision:** a chain runner with **no schema change** (the polymorphic `dependencies` table + `task_is_fully_unblocked` + the promote-on-ship trigger already encode the order; a `chain_id`/queue column would be a second, drift-prone source of truth) and **no new claim guard** (one-active-claim-per-session is keyed on the *working tree*, so ship-before-next-claim is already the enforced shape — and batch-claiming a chain is impossible anyway, since successors fail `DEPS_NOT_SHIPPED` until their predecessor ships; the ship IS what unblocks the next step). Deterministic plumbing (`scripts/gds/sequence.js` — scope, topological order, halt matrix, all read off the task row) is split from judgement (`.claude/skills/builder-sequence/`, which defers to `/builder-claim` + `/dev` + `/builder-ship`). **Halt, do not skip** (owner decision): on `needs_migration`, `security_sensitive`, `protected_path`, `rank_floor`, `thin_spec`, `judgement_kind`, `not_claimable`, `deps_unmet`, `in_flight`, or `cycle`, the runner stops and reports with the task still claimed — because in a dependency graph a skipped task is a *predecessor*, so skipping strands everything behind it while the run keeps posting apparent progress. Not built: chains as a priced claimable unit on the board (idea 1000398), which is additive.](<redacted>.md) | GDS / methodology |
@@ -244,9 +244,10 @@ This keeps the decision history honest and traceable.
244
244
  | 0167 | [**The /create gate trust link defaults to the AGPL-3.0 license text, not the npm package page** ([task 1002705](https://cloudbongos.com/builders#/task/1002705); gap 1 of the project-creation audit). The gate's "open source" link pointed at a nonexistent repo (404); the task brief's suggested default — the npm package page — is ALSO dead for the gate's actual audience (signed-out visitors): `@cloudbongos/core` and `@bongos/core` both 404 anonymously (private scopes, ADR 0134), and the ADR 0099 public mirror stays dormant until ~2026-11. The license text is the one live, instance-neutral artifact behind the claim today. The browsable-code upgrade is the owner's filed choice (idea 1000700): public repo now (forfeits the ADR 0065 §4 redaction window) / public npm package / wait for the mirror. Rejected: the npm link (verified dead), flipping the repo public (not a builder's call), plain unlinked text (less information, same cost).](<redacted>.md) | public landing / governance |
245
245
  | 0169 | [**`bongos serve`: the `bongos dev` boot path, on a real host** ([task 1002398](https://cloudbongos.com/builders#/task/1002398), goal 1000052). [ADR 0149](<redacted>.md) gave an owner one command to stand an instance up on their laptop; "now put it on a server" had no equally good answer — Docker serves the *vanilla* brand on `:3000`, `bongos onboard` provisions a whole droplet through the control plane, and [`instance-deploy.md`](../recipes/instance-deploy.md) left the systemd unit as a hand-written prose step. The six steps (deps → Postgres → createdb → migrate → env → server → health) were already right for a host; only four *decisions inside them* were laptop-shaped. So: a `--server` **mode** on the same script (`bongos serve`), never a second boot path, so the two can't drift. (1) **Supervision** — a systemd unit (`Restart=always`, `WantedBy=multi-user.target`) instead of a pid file that dies on reboot, falling back to the pid-managed process where systemd is absent rather than refusing. (2) **Bind address, derived from the origin** — `https://…` means a proxy terminates TLS, so bind `127.0.0.1`; plain `http://` on a public host means nothing is in front, so bind `0.0.0.0`. The common misconfiguration (app publicly reachable on its raw port behind a proxy) becomes impossible by default. (3) **Peer-auth bootstrap** — a fresh `apt-get install postgresql` cluster has only the `postgres` role, so a deploy user's `createdb` fails with `role "deploy" does not exist`; that reads like a broken install and is really an unbootstrapped cluster, so we create the login role as the superuser. (4) **Health means the PUBLIC origin** — the loopback probe proves the app; DNS/proxy/TLS are where a host actually fails, so it probes the advertised origin too and names the missing layer (advisory — DNS may legitimately not be wired). Secrets go to a root-owned `0600` `EnvironmentFile`, never `Environment=` (`systemctl show` leaks those, and the laptop path's `buildEnv()` spreads the caller's whole shell). Every decision is a pure injectable in `dev-lib.js`, proved in `tests/dev_lib.mjs` with no host. Rejected: a separate `deploy.sh` (drift — the point is the *same* six steps), Docker-on-the-host (makes brand+port a compose override), always binding `0.0.0.0` (exposes the raw port), refusing without systemd (breaks containers/BSD).](<redacted>.md) | onboarding / deploy |
246
246
  | 0173 | [**The legacy multi-ship reward shortfall is NOT backfilled — it closes as a one-time transition cost** ([task 1002520](https://cloudbongos.com/builders#/task/1002520), goal 1000037). Before `core_196` the cost-plus reward booked ONE row per session, so a multi-ship session (the normal shape — ship, new worktree, claim again) was paid at its first ship's level and never topped up; `core_196`'s watermark accounting `(session_id, reward_basis)` fixed that forward and deferred the retroactive half to an "owner-signed-off backfill, tracked separately". This is that decision, and it is **decline**. Measured live 2026-08-16, both of the task's open questions answered: (1) the task's own premise is wrong — `reward_basis = 0` is the column's DEFAULT, so it means "booked before top-ups existed", not "underpaid", and **over-selects by ~60%** (478 legacy sessions, but 287 are single-ship and were paid in full; only 191 are candidates); (2) re-pricing each candidate's stored `session_records.model_usage` at `round(true_cost_usd × 1.20)` gives **7,697 credits owed** across 119 sessions — example-owner 5,296 (69%), jaxri 2,319, scootermack 82 — with **72 candidates unreconstructable** (empty `model_usage`) and 16 already OVER-paid by 1,131 that nobody proposed clawing back. Declined because it mirrors the ADR 0146 clawback's own logic (the accounting changed; neither side of the boundary reopens), because paying only the 119 that happened to leave a server-side trace is arbitrary against the 38% that did not, and because correcting shortfalls while ignoring overpayment is a policy choice the owner declined to adopt. Consequence recorded plainly: three builders stay permanently short. **Does NOT close task 1002448** — that is the Windows `encodeProjectPath` population, never *recorded* rather than paid at a stale watermark, still recoverable and still owed.](<redacted>.md) | economy / rewards |
247
- | 0172 | [**The sub-Archon rank roles are owner-editable; the Archon role is not; the substrate keys are non-grantable to everything** ([task 1002961](https://cloudbongos.com/builders#/task/1002961), goal 1000030). Amends ADR 0151 §2's "the four seeded rank-roles are immutable through this API" wall — the GRANT half only. Their grants were always ordinary `governance_role_permissions` rows (the `governance_002` seed writes them); the read-only rendering was route policy, not structure. Three walls now, where there was one: the **Archon** rank-role stays frozen as the LOCKOUT GUARD (it is the only role holding `governance.manage` by seed, so freezing it means no click sequence can revoke the permission needed to reach this tab); the three **sub-Archon** rank-roles become grant-editable, the seven **in-app** Archon powers included (owner's explicit choice, escalation consequence stated); and `substrate` becomes a declared catalog axis — `deploy.push_main`/`path.protected.modify`/`infra.ssh` are non-grantable to EVERY role forever, because ADR 0043 enforces them out of band, so a grant row confers nothing and the toggle would be the UI lying. Grantability goes per-role (`isGrantableTo(key, role)`); `isGrantable(key)` survives as the narrow custom-role question config.js strips against. **Custom roles are deliberately NOT widened** — a rank-role moves only by a rank write, a custom role is assignable by anyone holding `governance.manage`. Assignment stays rank-derived (R95b) untouched. Adds `POST /governance/roles/:roleKey/reset` (one transaction, filtered through `isGrantableTo`, refused on a custom role) because a drifted ~60-row rank has no way back by clicking. Rejected: substrate keys behind a warning (a toggle that succeeds and delegates nothing), an editable Archon role behind a confirm (a confirm is not a guard; real recovery is hand-written SQL on the droplet).](<redacted>.md) | governance / permissions |
247
+ | 0172 | [**The sub-Archon rank roles are owner-editable; the Archon role is not; the substrate keys are non-grantable to everything** ([task 1002961](https://cloudbongos.com/builders#/task/1002961), goal 1000030). Amends ADR 0151 §2's "the four seeded rank-roles are immutable through this API" wall — the GRANT half only. Their grants were always ordinary `governance_role_permissions` rows (the `governance_002` seed writes them); the read-only rendering was route policy, not structure. Three walls now, where there was one: the **Archon** rank-role stays frozen as the LOCKOUT GUARD (it is the only role holding `governance.manage` by seed, so freezing it means no click sequence can revoke the permission needed to reach this tab); the three **sub-Archon** rank-roles become grant-editable, the seven **in-app** Archon powers included (owner's explicit choice, escalation consequence stated); and `substrate` becomes a declared catalog axis — `deploy.push_main`/`path.protected.modify`/`infra.ssh` are non-grantable to EVERY role forever, because ADR 0043 enforces them out of band, so a grant row confers nothing and the toggle would be the UI lying. Grantability goes per-role (`isGrantableTo(key, role)`); `isGrantable(key)` survives as the narrow custom-role question config.js strips against. **Custom roles are deliberately NOT widened** — a rank-role moves only by a rank write, a custom role is assignable by anyone holding `governance.manage`. Assignment stays rank-derived (R95b) untouched. Adds `POST /governance/roles/:roleKey/reset` (one transaction, filtered through `isGrantableTo`, refused on a custom role) because a drifted ~60-row rank has no way back by clicking. Rejected: substrate keys behind a warning (a toggle that succeeds and delegates nothing), an editable Archon role behind a confirm (a confirm is not a guard; real recovery is hand-written SQL on the droplet). **Vocabulary amended by ADR 0174 (2026-08-16): governance→government, seeded roles→ranks; the decisions are unchanged.**](<redacted>.md) | governance / permissions |
248
248
  | 0171 | [**Profile ↔ cross-project rollup: the join runs in-process on the hub; consent is fail-closed account state; the hide flag lives on the account, enforced in the read path** ([task 1002277](https://cloudbongos.com/builders#/task/1002277), R01 of goal 1000045). The C1 cross-project profile reads the platform-identity rollup through the module's **declared-but-never-registered `platform-identity.hub` port**: the module registers a real provider and core `GET /builders/:id/profile` `resolveOptional`s it beside `reward` — zero network, `null` (clean degrade) on every non-hub instance. Federated instances **link out** instead of inlining (amends profile-page spec Decision 1: an instance-side copy is either stale-on-hide or a per-view hub call). Consent: `profile_state` on `platform_identity_accounts`, **fail-closed** — `active` iff touched by a hub-session `/sso/authorize` (device-poll/check-in create `provisional`; backfill = all provisional, lazy upgrade; no core-`builders` join — type-unsafe vs `system:*` ids and a module-migration boundary breach), so the P03 owner decision can only ever widen, never claw back. The C2 hide flag is `hide_stats` on the account (NOT per-instance `behavior_prefs`), enforced **inside** the module's read functions — `listScoutingRollup` itself gains the `active AND NOT hide_stats` predicate so the live Metic-floor `/people`+`/scouting` surfaces honor it by construction. Hub profile responses go `no-store` (hide must beat the 60s cache). Publishing is gated on hardening the self-reported rollup (membership-row requirement, rank-vocab validation, disciplines caps, check-in→rollup sequencing). Found + filed: the `LATERAL unnest` fan-out inflating rollup sums (task 1002911), the unreserved `u` slug (task 1002912), the missing platform T&C artifact (task 1002913), criterion amendments (task 1002914). Rejected: instance→hub per-view pull (always-on dependency), hub→instance mirroring (stale-on-hide), storing the flag in builder-settings, backfilling `active` from hub `builders` rows.](<redacted>.md) | platform identity / profiles / privacy |
249
249
  | 0170 | [**The featured projection tells time honestly: `created_at` in, `updated_at` out, owner from the project's own archon** ([task 1002778](https://cloudbongos.com/builders#/task/1002778), goal 1000061). The hub card's metadata pass added `created_at` to the public `/projects/featured` projection, labelled **Listed** — it is the moment the hub catalogued the row, never when the project began, and the C6 card test bans the word "Created". Two recorded deviations: (1) the task brief said `updated_at` was ready to add, but the column is bumped by every client re-registration AND the Archon's feature toggle, so as a public "last updated" it would report curation noise as project activity — it may sort, never project, and the test pins the SELECT list itself (`SELECT *` banned: the route is CORS-open rank:public and a star would leak `owner_github_id`/`status`). (2) The owner fact reads the project's OWN leaderboard archon row (login + avatar, type-checked and capped) from the payload project-stats already fetches — zero extra requests, the 2-fetch pin intact, the advisory `owner_github_id` column still unread per the design contract. Multi-archon: top-credits archon is named; a fallen-off-the-page archon renders as no owner shown, never a wrong one. Rejected: projecting `updated_at` as asked (it lies), reading `owner_github_id` (advisory, contract-banned), a third per-origin fetch for activity recency (moves the test pin for a fact nobody asked for yet).](<redacted>.md) | platform identity / public surface |
250
250
  | 0174 | [**Governance is renamed government, its positions are ranks, and "role" is reserved for the three crafts** ([task 1003002](https://cloudbongos.com/builders#/task/1003002), R01 of goal 1000068). Owner directive, 2026-08-16. The word **role** named two unrelated things: the permission system's ladder tiers (`governance_roles`, the "rank-roles") and the three crafts (`tasks.discipline` = engineer/artist/ideator) — and goal 1000066 was actively claiming it for the crafts (`three-roles-only`, `users-hold-roles`), putting the two on a collision course. Resolved at full depth rather than as a label pass, because a labels-only fix leaves the UI and the code disagreeing, which is the condition that produced the collision. `modules/governance/` → `modules/government/`; the kernel module key, the config files, `/api/bongos/governance/*` → `/government/*`, and the permission keys `governance.manage` → `government.manage` (~50 sites) + `page.view.governance` → `page.view.government`. **The entity IS the rank — no second noun**: `governance_roles` → `government_ranks`, `role_key` → `rank_key`, `rank-roles.js` → `ranks.js`; "position" stays prose-only, since introducing it as a code term would recreate the qualifier problem "rank-role" already demonstrates. The cross-module kernel port `governance.roleSync` → `government.rankSync` must land atomically across its provider and both consumers (`modules/lifecycle/db.js`, `src/bongos/db.js`) because it is a transaction participant on the rank-write path. Hand-composed bundles stay in the one table as **custom ranks** — the owner's call over splitting them into a separate "appointments" concept, with the objection recorded (a custom bundle is not a ladder position, and ADR 0172 §4 already treats the two kinds as different). Enforced by a `fitness.js` rule, allowlist shipped with reasons. **Discord's server roles keep the word** — that noun belongs to Discord's API. Amends ADR 0151 + ADR 0172 (the editable-rank-roles one) in **vocabulary only**; ladder slugs, `builders.rank`, `requireRank`, and every floor/grant/assignment semantic are untouched. Rejected: renaming the ladder slugs (turns a bounded rename into a trust-boundary migration), a permanent compat shim (both vocabularies stay correct forever).](<redacted>.md) | government / permissions |
251
+ | 0175 | [**The Board Room: Full Idea ratification is the first upward-pointing gate** ([task 1003014](https://cloudbongos.com/builders#/task/1003014), R01 of goal 1000069). Every existing gate points DOWN the rank ladder; the owner asked for one that could slow THEM down — *"otherwise I can just ship and build as I want, finding loopholes."* The board's subjects are exactly **two**, both rare by construction: a **Full Idea** and a **change to the constitution itself** (`subject_type` from day one). Because the vote gates no build path, the **ADR 0162 tension dissolves rather than being compromised** — nothing self-executes because there is nothing downstream to execute; ratification confers legitimacy and does NOT auto-create the goal. A vote is a **timed sitting, not a quorum**: absent members are *nulled* (dropped from the denominator, never counted as a no), so the clock is the deadlock exit and no shotgun/fork-with-treasury clause is needed at this scale — default 90 minutes, closing early on full turnout, and yes, a short window means whoever is awake governs (the owner's explicit intent). **Consent, not majority**: silence is consent, one reasoned objection returns the idea, and a zero-vote close PASSES. A rejection must carry free text **plus one of the five Full Idea sections** — which is what **forces the hall to be the voting surface**, since a Discord reaction could only ever be feedback-free; Discord is therefore an outbound notification mirror that casts nothing, and its own mobile app is the mobile push (no mobile surface is built). The completeness grade is the **floor** (a window opens automatically on pass), the vote is the **merit**; concurrent windows are normal. Who governs is **configuration** — day one is monarchy expressed as config on the real machinery, never a separate code path — and **amendments are decided under whatever rule is currently in force**, so flipping out of monarchy is a legal monarchy act and no bootstrap exception is needed. Open ballot; an author may never vote on their own item. Franchise derives from **rank, not role**, and that is forced: `PATCH /me/disciplines` is deliberately ungated, so a craft-scoped chamber would be one-request privilege escalation. Unblocks goal 1000067 / IC5, which consumes the pass event and *"invents no parallel vote"*. Rejected: quadratic vote weighting and the attribution-economy knobs (γ, τ, the 30% stack cap — v1's franchise is not credit-weighted at all), eternity clauses, and any legal-entity integration.](<redacted>.md) | government / ideas / governance |
251
252
 
252
253
  > ⚠️ **Numbering collision (known):** two ADRs share `0008`. The numbers were assigned in parallel sessions before the lock could be enforced. The files are kept under their existing filenames to preserve git history, but the table disambiguates them as `0008-a` / `0008-b`. New ADRs should resume at `0040` to avoid further collisions. (`0024` is also a real on-disk duplicate: the cloneable-repo/local-first-memory ADR and the multi-agent-system-architecture ADR were both numbered `0024` in parallel; both keep their filenames, disambiguated as `0024-a` / `0024-b` like `0008`. Likewise `0025` ended up with two on-disk files — the offsite-backup ADR and the structured-criterion↔task-link ADR — both kept under their existing filenames and disambiguated as `0025-a` / `0025-b`; separately, the BFG ADR had also claimed `0025` on 2026-05-30 and yielded to `0026`. A third happened 2026-06-06: `0036` was claimed in parallel by the builders-subdomain ADR ([#726](https://example.com/builders#/task/726)) and this Discord-channels ADR ([#727](https://example.com/builders#/task/727)); the Discord-channels ADR yielded to `0037`. A fourth landed 2026-06-10: `0044` was claimed in parallel by the palette-replacement ADR and the per-box game-preview ADR ([#897](https://example.com/builders#/task/897)); both keep their filenames, disambiguated as `0044-a` / `0044-b` like `0008`. A fifth was caught pre-land 2026-06-13: `0050` was claimed in parallel by the device-flow-admission ADR ([#1000](https://example.com/builders#/task/1000)) and the sandbox-for-everyone ADR ([#1001](https://example.com/builders#/task/1001)); the latter yielded to `0052` before merging, so there is no `0050` duplicate. A sixth was caught pre-land 2026-06-21: the tool-agnostic-design-layer ADR ([#1375](https://example.com/builders#/task/1375)) first collided at `0079` with the value-gated-autonomous-engagement ADR, then at `0080` with the llm-cache-api-transport ADR (both part of the 0075–0080 LLM-cost-reduction series, landed on `main` in parallel); it yielded to `0081` before merging, so there is no `0079`/`0080` design-layer duplicate. A seventh landed 2026-06-23: `0084` was claimed in parallel by the auto-derived-per-task-rank-floor ADR and the remove-default-spend-cap ADR (task 1499); the rank-floor ADR landed on `main` first, so the spend-cap ADR yielded to `0085`, leaving no `0084` duplicate. An eighth landed 2026-06-27: `0095` was claimed in parallel by the borrowed-memory-and-retrieval-concepts ADR (PR #459, landed first) and the cross-agent-context-management ADR ([#1651](https://example.com/builders#/task/1651), PR #460); both keep their filenames, disambiguated as `0095-a` / `0095-b` like `0008`. These two are companions — `0095-a` adopts the memory/retrieval concepts and explicitly defers the grep-vs-semantic question to `0095-b`.)
@@ -231,7 +231,7 @@ markdown describes, the DB enforces.**
231
231
 
232
232
  - **`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.
233
233
  - **`status.example.com`** — public build dashboard. **Carved to the `status-ui` module in BV1.R84** ([ADR 0093](adr/<redacted>.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/gds/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.
234
- - **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/<redacted>.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 `requireGovernancePage`), **`/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/**`.
234
+ - **`builders.example.com`** — dedicated builder surface (`isBuildersHost`, ADR 0036). **Carved to the `hall-ui` module in BV1.R85** ([ADR 0093](adr/<redacted>.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/**`.
235
235
  - **`/downloads/devbox/*`** (every host, mounted right after the API so the builders-host shim can't rewrite it — [#904](https://example.com/builders#/task/904), [ADR 0045](adr/<redacted>.md)): branded download surface for the Dev Box desktop app. `/{mac-arm64,mac-x64,win-x64}` (+ `mac`/`win` aliases) 302 to the release assets on the public releases repo named in [`config/devbox-app.json`](../config/devbox-app.json); `latest.json` feeds the app's update check. Logic in [`src/devbox-downloads.js`](../src/devbox-downloads.js); the installers never ride the git deploy.
236
236
  - The `/api/gds/*` 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.
237
237
  - Caddy gets a site block per host ([`infra/Caddyfile`](../infra/Caddyfile)), all reverse-proxying to `127.0.0.1:3000`.
@@ -141,7 +141,7 @@ or missing ranks fail closed.
141
141
  - **the four escalation keys**, which look operational but are not: `POST /api/gds/tasks/:id/confirm`
142
142
  (grader-bypass), `POST /api/gds/gate-approvals/:pr/approve` (CI deploy-gate override), protected-module
143
143
  **goal scope** ([ADR 0086](adr/<redacted>.md)), and `government.manage` (the
144
- roles/permissions tab). Delegating any one of them lets a Metic reach Archon in four steps — create a
144
+ ranks/permissions tab). Delegating any one of them lets a Metic reach Archon in four steps — create a
145
145
  protected-scope goal in the permission core, claim a task there (protected paths already floor at
146
146
  *metic* per [ADR 0043](adr/<redacted>.md)), confirm
147
147
  past the failed grade, approve their own red gate — so keeping rank Archon-only depends on keeping
@@ -152,17 +152,17 @@ or missing ranks fail closed.
152
152
 
153
153
  > **Amended by [ADR 0172](adr/<redacted>.md) (owner decision, 2026-08-16).**
154
154
  > The paragraphs above describe the SEEDED ladder, which is still what a fresh instance boots with — but
155
- > they are no longer a guarantee about a running one. The owner made the three sub-Archon **rank roles**
156
- > editable from the governance tab and chose to include the seven in-app Archon powers, `government.manage`
155
+ > they are no longer a guarantee about a running one. The owner made the three sub-Archon **ranks**
156
+ > editable from the Government tab and chose to include the seven in-app Archon powers, `government.manage`
157
157
  > and `builder.rank.set` among them. So "no system permission is grantable below archon" now reads:
158
- > *no system permission is grantable to a CUSTOM role, and none is seeded below archon* — an Archon may
159
- > nonetheless hand one to a rank role deliberately. The four-step escalation chain described above is
158
+ > *no system permission is grantable to a CUSTOM rank, and none is seeded below archon* — an Archon may
159
+ > nonetheless hand one to a rank deliberately. The four-step escalation chain described above is
160
160
  > therefore **open by decision, not by accident**: whoever holds `government.manage` can reach the rest.
161
- > Two things that did NOT move, and that bound the blast radius: the **Archon** rank-role is immutable
161
+ > Two things that did NOT move, and that bound the blast radius: the **Archon** rank is immutable
162
162
  > (nothing clickable revokes the permission needed to reach the tab), and the three **substrate** keys stay
163
- > non-grantable to every role — ADR 0043's enforcers read the rank ladder and never consult this database,
163
+ > non-grantable to every rank — ADR 0043's enforcers read the rank ladder and never consult this database,
164
164
  > so no amount of in-app escalation produces a push to `main`, a protected-path edit, or an ssh session.
165
- > `builders.rank` remains the only writer of who holds a rank role (R95b).
165
+ > `builders.rank` remains the only writer of who holds a rank (R95b).
166
166
 
167
167
  Earlier one-power delegations that ADR 0157 generalises: **task authoring** — `POST /api/gds/tasks`,
168
168
  `PATCH /api/gds/tasks/:id` (incl. the `newcomer_friendly` flag), `POST /api/gds/tasks/:id/promote`, and the
@@ -192,7 +192,7 @@ or missing ranks fail closed.
192
192
 
193
193
  **[ADR 0157](adr/<redacted>.md) added the whole operational block here** —
194
194
  20 permissions that had been Archon-gated only by ADR 0016's fail-closed default, never by a decision:
195
- the governance/monitoring **pages** (`/watch`, `/harbor`, `/gate` — `page.view.government`) and
195
+ the government/monitoring **pages** (`/watch`, `/harbor`, `/gate` — `page.view.government`) and
196
196
  `GET /api/gds/sessions/search` (whose own `/sessions` page had no server gate at all until
197
197
  task 1002710 put it behind `page.view.government` alongside its three group-mates); the
198
198
  **dev-box + provisioning fleets** (`GET /boxes[/cost-ledger]`,
package/docs/file-map.md CHANGED
@@ -37,7 +37,7 @@
37
37
  ├── brand/ ← repo-canonical design system (ADR 0081)
38
38
  │ └── cloud-bongos/ ← Cloud Bongos brand: README design guide + tokens.json + regen_*.py + assets/ (mascot, 9 animation states, Docker-homage sky-whale, coin logo + Baloo 2 wordmark, painted code-glyph charms). Built under task 1506 (mascot restyle 1529, code glyphs 1527); illustrations generated via Gemini (modules/art-pipeline/pipeline gen_api).
39
39
  │
40
- ├── config/ ← per-instance config packs. Each pair resolves env → `X.json` (this host's, boundary-excluded) → `X.neutral.json` (the portable starter, the twin that publishes with the core): branding (ADR 0062 §3), modules, design-tokens, and governance role templates (BV1.R96 — labels/descriptions/custom-role templates only; live grants + assignments are DB rows).
40
+ ├── config/ ← per-instance config packs. Each pair resolves env → `X.json` (this host's, boundary-excluded) → `X.neutral.json` (the portable starter, the twin that publishes with the core): branding (ADR 0062 §3), modules, design-tokens, and government rank templates (BV1.R96 — labels/descriptions/custom-rank templates only; live grants + assignments are DB rows).
41
41
  │
42
42
  ├── docs/
43
43
  │ ├── adr/ ← Architecture Decision Records
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.187",
3
+ "version": "1.19.189",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.187",
9
+ "version": "1.19.189",
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.187",
3
+ "version": "1.19.189",
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",
package/src/module-api.js CHANGED
@@ -801,8 +801,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
801
801
  // landed since 1.19.185 with no explicit bump. run 31977207459. (task 1002620)
802
802
  // 1.19.187 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
803
803
  // landed since 1.19.186 with no explicit bump. run 31978548058. (task 1002620)
804
+ // 1.19.188 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
805
+ // landed since 1.19.187 with no explicit bump. run 31978931152. (task 1002620)
806
+ // 1.19.189 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
807
+ // landed since 1.19.188 with no explicit bump. run 31983108640. (task 1002620)
804
808
  // ---------------------------------------------------------------------------
805
- const CORE_VERSION = '1.19.187'; // CI auto-patch carrier (ADR 0161); see changelog above
809
+ const CORE_VERSION = '1.19.189'; // CI auto-patch carrier (ADR 0161); see changelog above
806
810
 
807
811
  // A namespaced logger so a module's log lines are attributable + consistent.
808
812
  // Usage: const log = api.logger('dev-box'); log.info('mounted');