@bongos/core 1.19.787 → 1.19.789

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.787",
6
- "core_contract": "1.19.787",
7
- "source_commit": "b32b78533de72aa607032c7eeea369d98103ef3b",
5
+ "core_version": "1.19.789",
6
+ "core_contract": "1.19.789",
7
+ "source_commit": "bf58d21c806de6d4a0151383543d1388131c90a1",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-16T22:32:51.862Z",
9
+ "built_at": "2026-09-16T22:50:30.953Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
- "docs_redacted": 483,
12
+ "docs_redacted": 484,
13
13
  "agent_docs_stubbed": 25,
14
14
  "functional_verbatim": 2160,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2668,
20
- "tree_sha256": "6633332cd057cd360e74849250fa2f7ab2458f7f683c8c6315c4820d19d06ac7",
19
+ "file_count": 2669,
20
+ "tree_sha256": "7ee2b678f3696611d42205ebc827862fc5750a01a8c6424fbb1e10bfe7b7ede2",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -1137,7 +1137,7 @@
1137
1137
  {
1138
1138
  "path": "docs/adr/0134-private-first-npm-distribution.md",
1139
1139
  "mode": "0000644",
1140
- "sha256": "47b4d52804d291c8fd8952d8a2e8ad673f173a965cf0b5fe100aa6b93d850cd6"
1140
+ "sha256": "46272b26074a2f5531d27bf1699ad6eb93c8dcfa31431239bc6417b9a3d61c47"
1141
1141
  },
1142
1142
  {
1143
1143
  "path": "docs/adr/0135-module-upstream-submission-interim-queue.md",
@@ -1944,10 +1944,15 @@
1944
1944
  "mode": "0000644",
1945
1945
  "sha256": "83b8971f9b2cf280c7ad3baa0fbbaaa59d1a4c3566eccdff02ab1e3195963862"
1946
1946
  },
1947
+ {
1948
+ "path": "docs/adr/0292-both-install-paths-stay-and-vendoring-is-the-production-one.md",
1949
+ "mode": "0000644",
1950
+ "sha256": "6a5afb0821a42af204fe97ec68040ea7781344651e599bce135bf8f15d8c86dc"
1951
+ },
1947
1952
  {
1948
1953
  "path": "docs/adr/README.md",
1949
1954
  "mode": "0000644",
1950
- "sha256": "708c4562d94e836ea3c755eb7bd0c5c0fec81e86e40c532aca27042c0c5ec5dc"
1955
+ "sha256": "7eb54577c118f262fa9bd5bd8b00aa194d88cff85646f57b78bd616813472723"
1951
1956
  },
1952
1957
  {
1953
1958
  "path": "docs/api-reference.md",
@@ -2512,7 +2517,7 @@
2512
2517
  {
2513
2518
  "path": "docs/module-api-changelog.md",
2514
2519
  "mode": "0000644",
2515
- "sha256": "3c0fb2e250b9dca8299cae204683c9fb815421e52206b44472b94952d7e61ede"
2520
+ "sha256": "465dc47c90068c0b1dca4d0f2eb0571d34c81416db376048c47ea4bc44fa70a8"
2516
2521
  },
2517
2522
  {
2518
2523
  "path": "docs/modules-contract.md",
@@ -2772,7 +2777,7 @@
2772
2777
  {
2773
2778
  "path": "docs/recipes/upgrading-the-core.md",
2774
2779
  "mode": "0000644",
2775
- "sha256": "408b4792ffb869f2fa13201485c1ab5b8306b93996bb75f01b4117de3fd39303"
2780
+ "sha256": "041955ed109343181ea563e47e905c59e3bbd052e4dc3988b5ea34fbe5029f16"
2776
2781
  },
2777
2782
  {
2778
2783
  "path": "docs/recipes/windows-builders.md",
@@ -7622,12 +7627,12 @@
7622
7627
  {
7623
7628
  "path": "package-lock.json",
7624
7629
  "mode": "0000644",
7625
- "sha256": "c99209b9bfd8f2191eb0e622e45d4875760a65c7ae4f8653758667e11bd0bb66"
7630
+ "sha256": "20b6df536012185619c495297c7ab916e26abeb9172fa8b0b9d7ee5ecfc2407a"
7626
7631
  },
7627
7632
  {
7628
7633
  "path": "package.json",
7629
7634
  "mode": "0000644",
7630
- "sha256": "fae2586d07f9b98f2631be427db59eb76c7149b49a01c404af51a40edde911a3"
7635
+ "sha256": "d8456ebb3015586d8a310448bbb75a715fbc5743722ad33cb4f7e5658ff2b250"
7631
7636
  },
7632
7637
  {
7633
7638
  "path": "public-docs/index.html",
@@ -9492,7 +9497,7 @@
9492
9497
  {
9493
9498
  "path": "src/module-api.js",
9494
9499
  "mode": "0000644",
9495
- "sha256": "37250a4442445fd5b73d199d17c2646944e633f7816a366ef7f6477168c6c2bd"
9500
+ "sha256": "d2bb1eda91a651b8b9761e0b1b5ecea7cecba84472565ecbf016f33f34f5f7ec"
9496
9501
  },
9497
9502
  {
9498
9503
  "path": "src/module-loader/catalog.js",
@@ -1,6 +1,6 @@
1
1
  # 0134 — Private-first npm distribution for the core + client (paid scoped, then public at launch)
2
2
 
3
- - **Status:** **Superseded.** The **core half** — the private-by-default posture — is superseded by [ADR 0283](0283-the-core-publishes-publicly-because-access-was-never-the-thing-protecting-it.md) ([task 1003872](https://cloudbongos.com/builders#/task/1003872), 2026-09-13): `@bongos/core` now publishes **public**. This ADR's own "public at launch" step is the thing that happened; what remains accurate here is the *reasoning* for the pre-launch posture and the scoped-package mechanics. The **client half** was already superseded by [task 1003742](https://cloudbongos.com/builders#/task/1003742) (2026-09-09) — see the note under Decision. Publish path built in task 2089.
3
+ - **Status:** **Superseded.** The **core half** — the private-by-default posture — is superseded by [ADR 0283](0283-the-core-publishes-publicly-because-access-was-never-the-thing-protecting-it.md) ([task 1003872](https://cloudbongos.com/builders#/task/1003872), 2026-09-13): `@bongos/core` now publishes **public**. This ADR's own "public at launch" step is the thing that happened; what remains accurate here is the *reasoning* for the pre-launch posture and the scoped-package mechanics. The **client half** was already superseded by [task 1003742](https://cloudbongos.com/builders#/task/1003742) (2026-09-09) — see the note under Decision. Publish path built in task 2089. The **vendored-is-the-default** clause — *"until this registry path is proven end-to-end on a real greenfield standup"* — is superseded by [ADR 0292](0292-both-install-paths-stay-and-vendoring-is-the-production-one.md) ([task 1003879](https://cloudbongos.com/builders#/task/1003879), 2026-09-16): the condition is met, and vendoring stays the default anyway because it is the production provisioning path, not a fallback awaiting proof.
4
4
  - **Date:** 2026-07-07
5
5
  - **Deciders:** example-owner (owner/Archon), Claude. Owner asked to have the npm/CLI onboarding commands ready but kept private pre-launch, choosing paid private npm over the free GitHub Packages option.
6
6
  - **Task:** [#2089](https://example.com/builders#/task/2089) (publish path + private config) · [#2092](https://example.com/builders#/task/2092) (the `@cloudbongos` → `@bongos` scope rename + first real publish) · **Goal:** 35 (project-creation flow), criterion 165.
@@ -0,0 +1,77 @@
1
+ # ADR 0292 — Both install paths stay, and vendoring turns out to be the production one
2
+
3
+ - **Status:** accepted
4
+ - **Date:** 2026-09-16
5
+ - **Task:** [1003879](https://cloudbongos.com/builders#/task/1003879) (goal 1000090, working area 4 — Bongos Core distribution). Public-npm **gate 6**, the decision row deliberately held back from gate 5's mechanical cleanup ([1003878](https://cloudbongos.com/builders#/task/1003878)) because both candidates were large deletions that could as easily be mistakes.
6
+ - **Gated on:** [ADR 0283](0283-the-core-publishes-publicly-because-access-was-never-the-thing-protecting-it.md) / [task 1003872](https://cloudbongos.com/builders#/task/1003872) — the flip to a public publish, which is what made this question answerable.
7
+ - **Supersedes:** [ADR 0134](0134-private-first-npm-distribution.md)'s **"vendored is the default, until the registry path is proven end-to-end"** clause. The condition is met; the default does not change, and the reason it does not change is the substance of this ADR.
8
+ - **Adjacent:** [ADR 0258](0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md) (the CLI package, candidate 2) · [ADR 0161](0161-publish-on-merge.md) (the lane that publishes) · [ADR 0108](0108-instance-composition-configurable-root.md) (core-as-npm-dep).
9
+
10
+ ## Context
11
+
12
+ Gate 6 asked two questions that the public flip appeared to answer by implication, and deliberately refused to let them be swept out as consequences:
13
+
14
+ 1. Does the **vendored-tarball install path** (~124 references across `upgrade.js`, `init.js`, `provision-repo.js`, `package-core.js`) still earn its keep now that a registry install works for everyone?
15
+ 2. Does **`@cloudbongos/cli`** ([ADR 0258](0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md)) still earn its keep, given task 1003872 named it as "redundant — that package exists only because the core is private"?
16
+
17
+ Both were framed as probable deletions. Both are **keeps**, and in the first case the framing was wrong in an instructive way.
18
+
19
+ ## The question the task asked was not the question that decides it
20
+
21
+ Gate 6 framed vendoring as insurance for hosts that cannot reach the registry: *"does anyone need to stand up an instance with no access to npm — an air-gapped host, a CI runner with no egress, a self-hoster behind a corporate proxy?"*, to be weighed against the AGPL self-host promise. Read that way, the honest answer is "probably nobody, yet" — and vendoring looks like 124 references maintained for a case that never happens.
22
+
23
+ That is not what the code does with it. From `provision-repo.js`, on the path every project created through the wizard takes:
24
+
25
+ > Core resolution is vendored (`--vendor-core`): **a tarball built from this checkout**, file:-pinned. init still accepts `--registry-core` for an operator who explicitly wants a published version.
26
+
27
+ Vendoring is not the fallback. It is the **production provisioning path for every instance this platform creates**, and `--registry-core` is the opt-out. Deleting it does not remove a contingency; it breaks project creation.
28
+
29
+ The reason is visible in `resolveVendorableCoreTarball`'s three-rung ladder, whose rungs are ordered *freshest-correct first* and whose comments name the bugs each one fixed:
30
+
31
+ 1. a `file:`-pinned control plane reuses its own pinned tarball — rebuilding from source aborts with an empty core set when the runner is itself a consumer instance (task 1002275, which left new repos empty);
32
+ 2. a registry-pinned control plane **packs the core it has installed**, so the child pins the same, current core the hub runs — this is what ended "the frozen-old-tarball births" (task 1002706);
33
+ 3. a genuine core source checkout rebuilds fresh via `package-core.js`.
34
+
35
+ Every rung answers one question: *what is the control plane actually running?* A registry install cannot express that. It can only express *what was most recently published*. Those coincide often and are not the same thing, and the gap between them is precisely where the bugs above lived.
36
+
37
+ This is the owner's own input, stated more sharply than the task body had it: vendoring is what makes standing up today's code work at all, because a checkout routinely runs ahead of the registry. Worth recording honestly, since the obvious measurement appears to contradict it:
38
+
39
+ - `main` is **not** durably ahead of the registry any more. Since publish-on-merge was armed, 136 of the last 300 commits on `main` are release bumps, releases land every 9–51 minutes, and `main`'s `CORE_VERSION` and the registry's `latest` were identical (1.19.785) at the moment this was written.
40
+ - But provisioning does not provision from `main`. It provisions from **the control plane's own checkout**, which is whatever commit that box is on, and it hands the child a byte-exact tarball of it. An unmerged branch, an uncommitted fix, a box deliberately held at an older pin — none of those exist on the registry at any version, ever.
41
+
42
+ So the air-gap argument, the one the task put forward, is the weakest of the reasons. The strongest is that vendoring is the only way to say **"this exact core"** instead of **"the newest published one"**.
43
+
44
+ ## Decision
45
+
46
+ ### 1. The vendored-tarball install path STAYS
47
+
48
+ No removal task follows. It is the default because it is load-bearing, not because the registry path was unproven.
49
+
50
+ ADR 0134's condition — *"until this registry path is proven end-to-end on a real greenfield standup"* — is **met**, and has been twice over: proven with a token on 2026-07-08 (task 2118 / blocker 71, a real `bongos init --registry-core` scaffold resolving `@bongos/core@1.17.0` and generating a reproducible lockfile), and tokenless since ADR 0283 (`npm pack @bongos/core` from a clean `HOME` with no credentials fetches 25.5 MB at the current version). This ADR closes that clause: the registry path is proven, supported, and reachable via `--registry-core` — and vendoring remains the default anyway, for the reason above rather than for want of proof.
51
+
52
+ What the public flip **did** retire is one of vendoring's supporting arguments, not its main one. Rung 2's own comment justifies packing the installed core partly "without requiring the child's owner to hold a token for the still-private registry package". That clause is now obsolete. The primary reason in the same sentence — the child pins the same, current core the hub runs — is untouched by the flip.
53
+
54
+ The costs gate 6 counted are real and are accepted with open eyes: ~124 references, a second install mode every scaffold/upgrade/provision path must keep straight, a Windows-only test failure ([task 1003839](https://cloudbongos.com/builders#/task/1003839)), and the pin-refresh complexity in `refreshStandaloneCorePin`. They buy the ability to provision an instance that matches the platform that provisioned it. That is a fair price.
55
+
56
+ ### 2. `@cloudbongos/cli` STAYS, on a new justification
57
+
58
+ Task 1003872 was right that the *original* reason is gone: the package was built so a newcomer could reach the board without a private-registry credential, and there is no private registry any more. Keeping it needs a reason of its own, and there is one, measured rather than asserted:
59
+
60
+ | | files | unpacked | runtime deps |
61
+ |---|---|---|---|
62
+ | `@cloudbongos/cli` | 32 | 0.5 MB | `undici` |
63
+ | `@bongos/core` | 2,611 | 46.4 MB | `express`, `pg`, `pino` |
64
+
65
+ `npx @cloudbongos/cli` costs a newcomer half a megabyte. Collapsing it into the core would make the same front door a 46 MB download that drags in a web server and a Postgres driver to print a task list. The thin client is the better artifact on merit, independently of why it first existed.
66
+
67
+ The three-way framing in the task body is also narrower than it looked: **unpublishing is not on the table.** The package is public at 0.1.3 and strangers may have installed it; withdrawing a published name is a different act from deleting private code, and nothing here justifies it.
68
+
69
+ So: keep it, keep publishing it, and let it depend on the now-public core. [ADR 0258](0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md) stands, with its *rationale* amended — the package is a deliberately small entry point, no longer a workaround for a private core.
70
+
71
+ ## Consequences
72
+
73
+ - **No code is deleted by this decision.** Gate 6 closes as a keep/keep, which the task explicitly allowed.
74
+ - ADR 0134's "vendored until proven" clause is spent. A future reader asking "why is vendoring still the default when the registry works?" is answered here, not there.
75
+ - The one genuine piece of rot the flip left behind in this area is rung 2's stale token clause; it is a comment, and it is corrected by this ADR's existence rather than by a migration.
76
+ - **What would reopen this:** if provisioning ever stops meaning "match the control plane" — if instances came to be pinned to published versions by policy rather than to the hub's own tree — vendoring's main justification goes with it, and candidate 1 should be re-asked. Nothing on the current roadmap does that.
77
+ - The self-host/AGPL argument the task raised is not the reason for the outcome, but it is not contradicted either: a self-hoster behind a proxy keeps a supported path, as a side effect of a decision made for other reasons.
@@ -383,3 +383,4 @@ This keeps the decision history honest and traceable.
383
383
  | 0289 | [**An unconsumed contribution is a CI failure, not a boot refusal** ([task 1003819](https://cloudbongos.com/builders#/task/1003819), successor to abandoned task 1002464). A module declares `contributes` and nothing checked that a declared seam is actually WIRED: `verifyPortsSatisfied` asks the OPPOSITE question (every `consumes` has exactly one provider) and `validateManifest` checks only the SHAPE (a closed key set, so a typo'd KEY errors). So `contributes.pollers: ["ghost"]` with no `pollers/ghost.js` boots silent — and correctly so, because `startModulePollers`, `hallWidgetScripts` and `moduleWebSurfaces` each skip a missing artifact the same way they skip a genuine declarative-only entry. Verified on main: 84 declared entries resolve, 5 do not. **Decision: `scripts/gds/seam-wiring-guard.js`, fitness Check 33.** Its `SEAM_CONSUMERS` table pairs each seam with THE FUNCTION THAT ACTUALLY READS IT, so the guard asks the consumer's own question instead of a second convention that could drift; a seam with no reader anywhere (`rooms`) carries `consumer: null` and every declaration of it is reported. The exemption is **per-entry, in the manifest** (`declarativeSeams`), validated in `validateManifest` against the module's own `contributes` — a typo'd exemption is an ERROR, since one that validated clean would exempt nothing while reading as though it exempted something — and a **stale** exemption whose artifact now exists is reported too, so the list cannot lie in either direction. The **wired set prints on the PASS path**: a check that is silent when it passes is no evidence it ran. CI and not boot, deliberately asymmetric with `verifyEnabledPorts`: an unprovided port becomes a runtime throw on a request path in a healthy-looking process, while an unconsumed contribution crashes nothing — a start-up refusal would trade a real outage risk for a cosmetic one. Rejected: a boot refusal; a blanket skip for the seams that allow declarative entries (that is how the gap arose); rebasing branch `task-1002464` (333 lines, 461 commits behind, against a since-rewritten `loader.js` — read its tests, close PR #589).](0289-an-unconsumed-contribution-is-a-ci-failure-not-a-boot-refusal.md) | modules / architecture |
384
384
  | 0290 | [**"Disconnect from Bongos entirely" is the owner-initiated exception to retention** ([task 1003249](https://cloudbongos.com/builders#/task/1003249), owner decision 2026-08-24 + this session). ADR 0181 keeps a torn-down project's database, dumps, port and address so "Take it offline" is reversible; this is the separate true delete. Own-scoped + archon override, with the typed name checked SERVER-side (`confirm_slug`); refused while any other run is open (supersedes nothing). The runner tears down, drops the database and its role, erases the dumps by their EXACT nightly filename, removes env/state/checkout/account, forgets the catalog + membership + client rows (new `project.catalog` verb `forget`, both claim rules), and deletes the provisioning row LAST — releasing name, port and address, and keeping every earlier failure retryable. The GitHub repository and any sign-in App are never touched.](0290-disconnect-is-the-owner-initiated-exception-to-address-retention.md) |
385
385
  | 0291 | [**The accessibility dimension scores the transcript, so it lives in the session evaluator, not the grader panel** ([task 1002516](https://cloudbongos.com/builders#/task/1002516), clause 4 of criterion `accessibility-fluency-profile`). The task and its sibling task 1003937 both point at `modules/grading/`, but a v4 worker is handed `{ task, valueSummary, diff, changedFiles, … }` and **no transcript** — it judges the change a session produced, never how the builder was spoken to while producing it. The transcript lives in `session_records`, so the dimension does too: `modules/sessions/accessibility.js`, a pure scorer over the digest's per-turn detail, scored SERVER-SIDE at upload (a score the uploader could supply is a score nobody can read; and the SessionEnd hook's 6-second watchdog rules out a second round trip for the profile). Three signals, exactly the three the criterion names. **Profile-relative, and a sanctioned signal is not scored at all** — `engineer` waives jargon + framing, `comfortable` waives terminal-first, `mixed` widens rather than waives, and an all-waived session scores `null`, not a number, so a profile-sanctioned reply cannot score low even in principle; `verbosity` is not an input and every rate is per-1000-characters, so brevity is arithmetically incapable of lowering it. Advisory, gating nothing (ADR 0241's shape). The profile crosses the module boundary as DATA — the route resolves the `builder-settings` kernel port, never a sibling require (ADR 0083), with a test as the tripwire against a value rename. Detectors deliberately undercount (word-bounded jargon, after a substring match fired `ORM` on "format"; a click-path table of UIs that actually exist), because a metric that punishes correct work is what the task itself calls actively harmful. Does NOT answer task 1003937, whose copy/voice lens judges a DIFF and still needs the owner on cost, gate-or-advisory, and what standard to judge against.](0291-the-accessibility-dimension-scores-the-transcript-not-the-diff.md) | grading / sessions / accessibility |
386
+ | 0292 | [**Both install paths stay, and vendoring turns out to be the production one** ([task 1003879](https://cloudbongos.com/builders#/task/1003879), goal 1000090 — public-npm **gate 6**, the decision row held back from gate 5's mechanical cleanup because both candidates were large deletions that could as easily be mistakes). Gate 6 framed the **vendored-tarball path** (~124 refs across `upgrade.js`/`init.js`/`provision-repo.js`/`package-core.js`) as insurance for hosts that cannot reach npm, to be weighed against the AGPL self-host promise. Read that way it loses. **That is not what the code does with it:** `provision-repo.js` resolves the core for every wizard-created project as "a tarball built from THIS CHECKOUT, file:-pinned", with `--registry-core` as the opt-out — vendoring is the production provisioning path, not the fallback, and deleting it breaks project creation. `resolveVendorableCoreTarball`'s three-rung ladder (reuse the control plane's own pinned tarball → pack the core it has INSTALLED → rebuild from source) exists to answer one question a registry install cannot express: *what is the control plane actually running?* Rungs 1 and 2 each name the bug they fixed — empty new repos when the runner is itself a consumer (task 1002275), and "the frozen-old-tarball births" (task 1002706). The owner's input — a checkout routinely runs ahead of the registry — holds, though not via `main`: since publish-on-merge, 136 of the last 300 `main` commits are release bumps, releases land every 9–51 min, and `main`'s `CORE_VERSION` equalled the registry `latest` (1.19.785) when this was written. Provisioning does not provision from `main`; it provisions from the control plane's own tree, and an unmerged branch or a deliberately-held pin exists on the registry at NO version, ever. **Supersedes ADR 0134's "vendored is the default until the registry path is proven end-to-end" clause:** the condition is MET twice over — with a token 2026-07-08 (task 2118 / blocker 71) and tokenless since [ADR 0283](0283-the-core-publishes-publicly-because-access-was-never-the-thing-protecting-it.md) (`npm pack @bongos/core` from a clean `HOME` fetches 25.5 MB) — and the default stands anyway, for load-bearing reasons rather than for want of proof. Costs accepted with open eyes: ~124 refs, a second install mode every scaffold/upgrade/provision path must keep straight, a Windows-only test failure ([task 1003839](https://cloudbongos.com/builders#/task/1003839)), `refreshStandaloneCorePin`. **Candidate 2 — `@cloudbongos/cli` — also STAYS, on a NEW justification:** task 1003872 was right that the original reason (reaching the board without a private-registry credential) is gone, so it needs one of its own, and the measurement supplies it — 32 files / 0.5 MB / `undici`, versus the core's 2,611 files / 46.4 MB / `express`+`pg`+`pino`. Collapsing it would make `npx` a 46 MB download dragging in a web server and a Postgres driver to print a task list. **Unpublishing was never on the table** (public at 0.1.3, strangers may have installed it); [ADR 0258](0258-the-public-cli-is-a-generated-client-package-not-the-published-core.md) stands with its *rationale* amended — a deliberately small entry point, no longer a private-core workaround. The one real rot the flip left is rung 2's stale "still-private registry package" clause, a comment. **Gate 6 closes keep/keep, no removal task.** Reopens if provisioning ever stops meaning "match the control plane".](0292-both-install-paths-stay-and-vendoring-is-the-production-one.md) | distribution / provisioning |
@@ -2048,5 +2048,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
2048
2048
  landed since 1.19.785 with no explicit bump. run 35157132070. (task 1002620)
2049
2049
  1.19.787 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2050
2050
  landed since 1.19.786 with no explicit bump. run 35158163962. (task 1002620)
2051
+ 1.19.788 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2052
+ landed since 1.19.787 with no explicit bump. run 35159266737. (task 1002620)
2053
+ 1.19.789 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2054
+ landed since 1.19.788 with no explicit bump. run 35159544354. (task 1002620)
2051
2055
  ---------------------------------------------------------------------------
2052
2056
  ```
@@ -110,6 +110,8 @@ node .claude/scheduled-tasks/core-update-subscription/subscribe.js --apply #
110
110
 
111
111
  Each subscribed instance: read its installed core → ask the registry (`npm view`, no credential needed — the package is public) → resolve the newest version its channel permits → if newer, `bongos upgrade --to <v> --registry` with **auto-rollback ON**. It prints one line per instance plus a tally; a non-zero exit means an upgrade failed (already auto-reverted).
112
112
 
113
+ > **Enrolling a `file:`-pinned instance resolves NOTHING — convert the pin first** (task 1003915). A scaffolded co-tenant declares its core as `"@bongos/core": "file:vendor/bongos-core-<v>.tgz"`, a local path with no registry channel to follow, so the sweep has nothing to compare against and the instance sits frozen while the roster reports it enrolled. The conversion is not a separate chore: one manual `bongos upgrade --to <v> --registry` rewrites the pin to a bare registry semver on its way through, and every later sweep then works. Measured on the cloudbongos droplet 2026-09-13, **20 of 22 co-tenants** were `file:`-pinned, which is why enrolment alone had never moved any of them.
114
+
113
115
  **Triple-gated, so nothing moves by accident:** the `core-update-subscription` routine is `requiresAutonomy: true` + **default OFF** in [`config/scheduled-routines.json`](../../config/scheduled-routines.json), the roster ships empty, and every upgrade is health-gated. Arm it by enabling the routine's timer on the control plane once autonomy is on.
114
116
 
115
117
  **Not covered:** multi-host / SSH orchestration across a real fleet (the deferred fleet-control-plane epic, task [#1948](https://example.com/builders#/task/1948)); and *publishing* new patches, which stays a gated owner step (ADR 0134) — a follow-up task decides whether merges auto-publish.
@@ -119,7 +121,11 @@ Each subscribed instance: read its installed core → ask the registry (`npm vie
119
121
  - **`--registry` needs no credential at all** (task 1003878). `@bongos/core` is **public** on npm (task 1003872), so `bongos upgrade --registry` resolves it from the default registry like any other dependency — no token, no login, and no instance `.npmrc`. An install failure on this path is therefore a *real* failure (network, registry outage, or a version that was never published), never a missing credential.
120
122
  *History, so the symptom is recognisable on an old instance:* the core used to publish private, and the instance `.npmrc` read `_authToken=<redacted> npm gives that per-project key precedence, so with the env var unset it expanded EMPTY and **masked a perfectly valid literal token in `~/.npmrc`** — npm went anonymous, the private core 404'd, and the error blamed a credential the box actually held. Task 1002754 worked around it by resolving the token in-process; task 1003878 deleted the whole mechanism along with the `.npmrc` that caused it. An instance still carrying a committed `.npmrc` from a pre-1003878 scaffold can safely delete it.
121
123
  - **A green `publish` run is not evidence of a publish.** The publish-on-merge lane succeeds on its no-op paths too (cascade terminator, armed-gate). Read the run's **job summary**, which now states the verdict explicitly: `PUBLISHED @bongos/core@<v>` vs `NO-OP — nothing was published this run`.
122
- - **`PGDATABASE` is load-bearing on a co-tenant droplet.** `migrate.sh` defaults `PGDATABASE` to `example` — **production**. Always set `PGDATABASE=<instance-db>` explicitly, or you migrate the wrong database.
124
+ - **`PGDATABASE` is load-bearing on a co-tenant droplet.** `migrate.sh` defaults `PGDATABASE` to `example` — **production**. Always set `PGDATABASE=<instance-db>` explicitly, or you migrate the wrong database. The dry run checks this *before* the pin moves, so `--dry-run` first costs seconds and saves a full rollback.
125
+ - **The pin push to a co-tenant's `origin` always fails, and that is not the bump failing.** A co-tenant's remote is `git@github-instances:example-owner/<slug>.git` and the alias carries no usable key, so `--commit-pin` commits locally and the push is refused — reported as a failure even though the core installed, restarted, passed its health check and is serving. Read the **served version** before believing the tally.
126
+ - **⚠ An enrolled co-tenant upgrades ONCE, then wedges itself out of the sweep** (proven on `charter` 2026-09-16, task 1003915). The upgrade's own *materialize* and *regen doc assets* steps rewrite tracked files (`.claude/skills/*`, `clients/*` — 14 of them), and the pin-commit step commits only `package.json`/`package-lock.json`. So a bump that genuinely succeeded — installed, restarted, health 200, **serving** the new core — exits `failed=1`, and the **next** sweep refuses the instance: `worktree not clean and the changes are NOT the pin … skipped, a human needs to look`. Every later run skips it, and a skip is not a failure in the tally, so nothing surfaces it. Until this is fixed, `git add -A && git commit` inside the instance after each sweep; that un-wedges it immediately.
127
+ - **Survey co-tenant git state as `lars`, never as root.** `ssh cloudbongos` lands you as root, where `git config --get remote.origin.url` on a `lars`-owned repo returns **nothing** — which reads exactly like "this instance has no remote" and is wrong. They do: `git@github-instances:example-owner/<slug>.git`. Prefix every probe with `sudo -u lars`.
128
+ - **A scaffold's `migrate` script is not guaranteed.** 21 of the 22 co-tenants have `scripts.migrate`; `mercury` has **no `scripts` block at all** and is started directly by its systemd `ExecStart`, so the normal lane cannot complete on it. `--skip-migrate` gets the install through but silently skips every schema change in the window — check what that window carries before reaching for it, rather than after.
123
129
  - **The health check polls the restart** (fixed in task [#1984](https://example.com/builders#/task/1984)). The service binds its port ~1s after `systemctl restart`, so `--health-url` now polls up to ~30s for a 2xx before reporting a warning — an immediate `fetch failed` no longer means a failed upgrade. (Pre-1984 cores fetched once and spuriously reported `fetch failed`; there, confirm with `is-active` + a manual `curl`.)
124
130
  - **The ledger auto-inserts via `PGDATABASE` too** (fixed in task [#1984](https://example.com/builders#/task/1984)). A consumer on `PGDATABASE` + peer auth now gets its `core_upgrades` row written automatically — the channel delegates the insert to `psql -d "$PGDATABASE"`, exactly like `migrate.sh`, so no manual `psql INSERT` is needed. (`DATABASE_URL` still works, via the `pg` driver.) Pre-1984 cores only auto-wrote with `DATABASE_URL`; on those, record the row manually.
125
131
  - **No deploy key on the droplet** → deploys/upgrades ride a `git bundle`, not `git pull` (idea 509).
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.787",
3
+ "version": "1.19.789",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.787",
9
+ "version": "1.19.789",
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.787",
3
+ "version": "1.19.789",
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
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
71
71
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
72
72
  // the entry to that file. Look for a version's history there, not here.
73
73
  // ---------------------------------------------------------------------------
74
- const CORE_VERSION = '1.19.787'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.789'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
75
75
 
76
76
  // A namespaced logger so a module's log lines are attributable + consistent.
77
77
  // Usage: const log = api.logger('dev-box'); log.info('mounted');