@bongos/core 1.19.69 → 1.19.71
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 +26 -16
- package/docs/adr/0167-gate-trust-link-agpl-default.md +24 -0
- package/docs/adr/0168-scaffold-packs-installed-core.md +34 -0
- package/docs/adr/README.md +2 -0
- package/docs/recipes/ops-gotchas.md +10 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/create.html +5 -1
- package/scripts/gds/provision.js +60 -9
- package/src/module-api.js +5 -1
- package/tests/onboard.mjs +13 -0
- package/tests/provision.mjs +76 -1
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.71",
|
|
6
|
+
"core_contract": "1.19.71",
|
|
7
|
+
"source_commit": "4eba29162c98469e50170c8942bb995192ac0378",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-12T15:37:06.175Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
|
-
"docs_redacted":
|
|
12
|
+
"docs_redacted": 294,
|
|
13
13
|
"agent_docs_stubbed": 21,
|
|
14
14
|
"functional_verbatim": 1223,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1538,
|
|
20
|
+
"tree_sha256": "7d0cdc9a7a536092bcbcf6f173a3c55c18773c1878e1613394b768dd54d6228f",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -1304,10 +1304,20 @@
|
|
|
1304
1304
|
"mode": "0000644",
|
|
1305
1305
|
"sha256": "3d260a52d4aa494e2df58f0db1c038c091786fbea99bad77d35b86b1a2024cf3"
|
|
1306
1306
|
},
|
|
1307
|
+
{
|
|
1308
|
+
"path": "docs/adr/0167-gate-trust-link-agpl-default.md",
|
|
1309
|
+
"mode": "0000644",
|
|
1310
|
+
"sha256": "bb187a29953ba5c316977f09fe86e26ca200693b23cf5c41ece93e9dd24f337e"
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
"path": "docs/adr/0168-scaffold-packs-installed-core.md",
|
|
1314
|
+
"mode": "0000644",
|
|
1315
|
+
"sha256": "8bdad4b4333cbb7b38f66e4dddab08675dfc0a431d21c0be6a31ca4afd8c498f"
|
|
1316
|
+
},
|
|
1307
1317
|
{
|
|
1308
1318
|
"path": "docs/adr/README.md",
|
|
1309
1319
|
"mode": "0000644",
|
|
1310
|
-
"sha256": "
|
|
1320
|
+
"sha256": "a96302a9849a2d7225b4a47ce0d7a7ac5f66d6849e80781f9a8e5aa32eba51d4"
|
|
1311
1321
|
},
|
|
1312
1322
|
{
|
|
1313
1323
|
"path": "docs/api-reference.md",
|
|
@@ -1557,7 +1567,7 @@
|
|
|
1557
1567
|
{
|
|
1558
1568
|
"path": "docs/recipes/ops-gotchas.md",
|
|
1559
1569
|
"mode": "0000644",
|
|
1560
|
-
"sha256": "
|
|
1570
|
+
"sha256": "ddbb6d4e0569a6773b648a6fe97abb2e2e04c6e36a5f3100af0cd995688a4810"
|
|
1561
1571
|
},
|
|
1562
1572
|
{
|
|
1563
1573
|
"path": "docs/recipes/overnight-builder.md",
|
|
@@ -4042,12 +4052,12 @@
|
|
|
4042
4052
|
{
|
|
4043
4053
|
"path": "package-lock.json",
|
|
4044
4054
|
"mode": "0000644",
|
|
4045
|
-
"sha256": "
|
|
4055
|
+
"sha256": "9fed4a4c8c227a418e6cc695f1a9a7ddea366f1e0ddd95f788d7b64dacd03ff2"
|
|
4046
4056
|
},
|
|
4047
4057
|
{
|
|
4048
4058
|
"path": "package.json",
|
|
4049
4059
|
"mode": "0000644",
|
|
4050
|
-
"sha256": "
|
|
4060
|
+
"sha256": "af4d4ea3a0dd190dda1d0f04e2d9450b395cc4026405833e970f2ac81772fe5d"
|
|
4051
4061
|
},
|
|
4052
4062
|
{
|
|
4053
4063
|
"path": "public-docs/index.html",
|
|
@@ -4292,7 +4302,7 @@
|
|
|
4292
4302
|
{
|
|
4293
4303
|
"path": "public-landing/create.html",
|
|
4294
4304
|
"mode": "0000644",
|
|
4295
|
-
"sha256": "
|
|
4305
|
+
"sha256": "419539862b5453d613a5ed3758a7d8fa677d16e463895ae64e6268a8d59372ba"
|
|
4296
4306
|
},
|
|
4297
4307
|
{
|
|
4298
4308
|
"path": "public-landing/gate/README.md",
|
|
@@ -5022,7 +5032,7 @@
|
|
|
5022
5032
|
{
|
|
5023
5033
|
"path": "scripts/gds/provision.js",
|
|
5024
5034
|
"mode": "0000644",
|
|
5025
|
-
"sha256": "
|
|
5035
|
+
"sha256": "7ad384495370312a57f7c1f0dab4770888c83afd08b89a8dc27aebae408abfd1"
|
|
5026
5036
|
},
|
|
5027
5037
|
{
|
|
5028
5038
|
"path": "scripts/gds/publish-manifest.js",
|
|
@@ -5672,7 +5682,7 @@
|
|
|
5672
5682
|
{
|
|
5673
5683
|
"path": "src/module-api.js",
|
|
5674
5684
|
"mode": "0000644",
|
|
5675
|
-
"sha256": "
|
|
5685
|
+
"sha256": "110f17337515aa6751a7c881bd20c0694f38686b5b62c29da43ac2677be2b5af"
|
|
5676
5686
|
},
|
|
5677
5687
|
{
|
|
5678
5688
|
"path": "src/module-loader/loader.js",
|
|
@@ -7042,7 +7052,7 @@
|
|
|
7042
7052
|
{
|
|
7043
7053
|
"path": "tests/onboard.mjs",
|
|
7044
7054
|
"mode": "0000644",
|
|
7045
|
-
"sha256": "
|
|
7055
|
+
"sha256": "40d4656e2170370cd3b662911502579fed595fd66fd25b8add65d488a28bb834"
|
|
7046
7056
|
},
|
|
7047
7057
|
{
|
|
7048
7058
|
"path": "tests/onboarding_gate.mjs",
|
|
@@ -7157,7 +7167,7 @@
|
|
|
7157
7167
|
{
|
|
7158
7168
|
"path": "tests/provision.mjs",
|
|
7159
7169
|
"mode": "0000644",
|
|
7160
|
-
"sha256": "
|
|
7170
|
+
"sha256": "edb6c5da9ec32536d50f7cb648b81b026b7926f73f891feb0906fc7343b5b11d"
|
|
7161
7171
|
},
|
|
7162
7172
|
{
|
|
7163
7173
|
"path": "tests/provisioning_domain_attach.mjs",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 0167 — The /create gate trust link defaults to the AGPL license text, not the npm package page
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted — built in task 1002705.
|
|
4
|
+
- **Date:** 2026-08-12
|
|
5
|
+
- **Deciders:** jaxri (Archon) — autonomous session; the residual choice is the owner's (idea 1000700).
|
|
6
|
+
- **Task:** task 1002705 · **Goal:** 1000059 (projects surface revamp) · gap 1 of [`docs/audits/project-creation-gap-list.md`](../audits/project-creation-gap-list.md).
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The /create gate's "open source" trust link pointed at `github.com/example-owner/Claude-OTB` — a 404 even authenticated (the real core repo is private). Task 1002705's brief said to "default to the npm link so the 404 dies now," on the premise that `@cloudbongos/core` is public on the registry.
|
|
11
|
+
|
|
12
|
+
That premise is false, verified 2026-08-12 against `registry.npmjs.org`: **both `@cloudbongos/core` and `@bongos/core` 404 anonymously** — they are private scoped packages (ADR 0134 publishes the core privately; npm shows private packages as 404 to signed-out visitors). The [ADR 0099](<redacted>.md) public mirror is deliberately dormant until history clears the 180-day redaction window (~2026-11). So today there is **no browsable public code artifact at all** — following the brief literally would swap one dead link for another.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
Point the gate's "open source" link at the **AGPL-3.0 license text** (`https://www.gnu.org/licenses/agpl-3.0.html`) and tighten the copy to "open source (AGPL-3.0)". The license is the one live, instance-neutral artifact behind the claim today ([ADR 0065](<redacted>.md) — AGPL is the governance keystone), and the link carries no instance identity into the portable core.
|
|
17
|
+
|
|
18
|
+
The upgrade to a *browsable-code* link is the owner's call, filed as **idea 1000700** with three options: flip the repo public now (forfeits the redaction window — weigh ADR 0065 §4), publish a public npm package, or wait for the ADR 0099 mirror (~2026-11, zero extra work). When one lands, repoint the `finePrint` link in `public-landing/create.html`; the pin is `tests/onboard.mjs` "the /create gate trust link points at a live artifact".
|
|
19
|
+
|
|
20
|
+
## Alternatives considered
|
|
21
|
+
|
|
22
|
+
- **The npm package page (the brief's default)** — rejected: verified 404 for anonymous visitors; the gate's audience is exactly the signed-out visitor.
|
|
23
|
+
- **Make the repo public now** — not a builder's call; forfeits the deliberate 6-month redaction window (ADR 0065/0099). Surfaced to the owner instead (idea 1000700).
|
|
24
|
+
- **Drop the link, keep plain text** — dies the 404 but weakens the claim; the license link is strictly more information at the same cost.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 0168 — The scaffold vendors the hub's running core (npm pack of the installed package); registry-default deferred to the go-public step
|
|
2
|
+
|
|
3
|
+
- **Status:** Accepted — built in task 1002706.
|
|
4
|
+
- **Date:** 2026-08-12
|
|
5
|
+
- **Deciders:** jaxri (Archon) — autonomous session; the go-public trigger stays the owner's (idea 1000700, ADR 0134).
|
|
6
|
+
- **Task:** task 1002706 · **Goal:** 1000059 · gap 13 of [`docs/audits/project-creation-gap-list.md`](../audits/project-creation-gap-list.md) · ties: task 1002621, task 1002275, idea 1000671.
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
Two facts collided at the scaffold's core-install step:
|
|
11
|
+
|
|
12
|
+
1. **New projects were born frozen-stale.** A fresh scaffold pinned `file:vendor/bongos-core-1.19.2.tgz` — ~60 patches behind — because `installedCoreTarball()` (task 1002275) reuses whatever tarball the control plane's own `file:` pin names, and the mothership's pin had sat at 1.19.2. ADR 0136 channels can't move a `file:` pin, so children had no upgrade path.
|
|
13
|
+
2. **The registry cutover quietly broke the fallback.** Task 1002621 moved cloudbongos.com's own pin to the registry (`"@bongos/core": "1.19.56"` — verified on the box 2026-08-12). With no `file:` pin, `installedCoreTarball()` returns null and the scaffold falls into the `package-core.js` source rebuild — which **aborts on a consumer instance** (REPO_ROOT inside gitignored `node_modules` → empty core set → the child repo is left empty, the exact task-1002275 failure resurrected). The next greenfield scaffold on the box would have failed outright.
|
|
14
|
+
|
|
15
|
+
The task brief proposed "make registry the scaffold default now that `@cloudbongos/core` is public (verify unauthenticated `npm view` works)". **That verification fails**: both `@cloudbongos/core` and `@bongos/core` 404 anonymously on `registry.npmjs.org` (2026-08-12) — they are private scoped packages (ADR 0134), public only at the launch go-public step. A registry-default scaffold today would hand every new owner a caret pin + env-fed `.npmrc` they cannot resolve without a paid-org token — a project **born uninstallable**, strictly worse than born-stale.
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
**Three-rung core-resolution ladder** in the standalone scaffold (freshest-correct first), replacing the two-rung one:
|
|
20
|
+
|
|
21
|
+
1. `file:`-pinned control plane → reuse its pinned tarball (task 1002275, unchanged).
|
|
22
|
+
2. **NEW — registry-pinned consumer control plane → `npm pack` the core it has installed** (`installedCorePackDir()` finds `node_modules/@bongos/core`, the scaffold packs it to a temp dir and `--vendor-core`s the result). The child pins the **same, current core the hub runs** — 1.19.56 today, not 1.19.2 — and stays `file:`-pinned, so its owner needs no npm token.
|
|
23
|
+
3. Genuine source checkout → `package-core.js` rebuild (unchanged).
|
|
24
|
+
|
|
25
|
+
The opt-in registry path (`PROVISION_CORE_FROM_REGISTRY=1` + `NPM_TOKEN`, fail-soft) is untouched. **Registry as the scaffold default is deferred to the ADR 0134 go-public step** — the same owner decision idea 1000700 tracks (public repo / public npm / wait for the ADR 0099 mirror). When the package goes public, flipping the default becomes a small follow-up: drop the token gate, keep fail-soft.
|
|
26
|
+
|
|
27
|
+
**Ops leg (gap 13's "flip the box env"):** nothing to flip now — setting `PROVISION_CORE_FROM_REGISTRY=1` on the box today would birth token-locked children (the private-pin trap above). Child freshness rides two things instead: this ladder (children inherit the hub's core at birth) and the hub's own pin staying current (task 1002708 — the upgrade lane must commit + push the pin).
|
|
28
|
+
|
|
29
|
+
## Consequences
|
|
30
|
+
|
|
31
|
+
- Born-stale collapses from "frozen at 1.19.2 forever" to "as fresh as the hub" — and the hub's freshness is an explicitly tracked lane (task 1002708).
|
|
32
|
+
- The post-cutover empty-repo regression is closed before it fired in production.
|
|
33
|
+
- `npm pack` naming (`<scope>-<name>-<version>.tgz`) is derived from the installed package's own `name`, so both scope aliases work.
|
|
34
|
+
- Rejected: registry-default now (verified-dead premise; uninstallable children), dropping `NPM_TOKEN` (the package is private — tokenless `npm ci` fails closed by design, ADR 0134), vendoring from the npm cacache (undocumented layout; `npm pack` is the supported path).
|
package/docs/adr/README.md
CHANGED
|
@@ -239,5 +239,7 @@ This keeps the decision history honest and traceable.
|
|
|
239
239
|
| 0164 | [**The implausible-pass guard reads substance + evidence; the Metic+ honor-system residual is explicit** ([task 1002658](https://cloudbongos.com/builders#/task/1002658); grader-hardening goal 1000056). The guard fired only on `issues.length===0` — one fabricated `{}` defeated it, its magnitude inputs are client-supplied, and every in-sample firing (eval 2-for-2, tasks 1002643 ×2, 1002663) was a false positive on an honest unanimous zero-issue panel PASS. Redesign: count only SUBSTANTIVE issues (known severity + non-empty summary — padding trips the guard regardless), and waive the zero-issue pass when `signals.workers` carries the full ≥3-worker panel shape, stamped `implausible_pass_waived` for /grade-audit. The residual is named, not hidden: every grade-time input is client-authored, so plausibility at grade time is honest-mistake hygiene; the binding authorities on the real diff are land-time (CI unit, gate-review, main audit) — Metic+ grade-time honesty is accepted honor-system per this ADR. The ADR-0042 CI grade-gate (land it vs record permanent deferral) goes to the owner as a blocker, not decided here. No approval step added or removed (ADR 0162).](<redacted>.md) | GDS / grading |
|
|
240
240
|
| 0165 | [**Instances are hookless by default: no scaffolded `.husky/`; local hooks stay an instance-owned opt-in** ([task 1002641](https://cloudbongos.com/builders#/task/1002641); idea 1000655). Task 1002608 delivered the ADR 0043 Layer 1 pre-push gate for the CORE repo, but nothing materializes `.husky/` on a scaffolded standalone instance (`publish-manifest.js` excludes it by design). Decision: that is the accepted posture, not a gap. Sub-Metic instance builders hold no push credential at all (server-mediated publish, ADR 0053/0055) — a client pre-push hook guards a push that cannot happen; a client hook is not a security boundary (ADR 0016); the core cannot maintain hooks it deliberately does not ship (scaffolded hooks would be born orphans — the audit-authorship rot lesson, task 1002640); and ADR 0162 puts gates in CI, rank-consistent and hands-free. Secrets hooks follow the same rule (the PR-time CI secret scan enforces). The opt-in stays real and instance-owned: an instance commits its own `.husky/` and the core's `install-git-hooks.js` (already run by `/builder-setup`) activates it. Rejected: scaffolding wrappers at init, an `--with-hooks` flag (speculative), treating hooklessness as a regression. Revisit if an instance model has builders pushing directly with their own credentials.](<redacted>.md) | provisioning / trust boundary |
|
|
241
241
|
| 0166 | [**Module maintenance & deprecation policy: upkeep is a declared `maintenance` block, and `bongos upgrade` surfaces rot in DISABLED modules too** ([task 1001773](https://cloudbongos.com/builders#/task/1001773)). Implements [ADR 0107](<redacted>.md) §7, which named the catalog-rot problem and deferred the mechanics. `module.json` gains an optional-in-schema, required-to-upstream `maintenance` block — `status` one of `core-maintained` / `maintained` / `deprecated` / `orphaned`, plus `since` / `removeAfter` / `successor` / `note`. Each status owes something the validator enforces: `maintained` requires a named top-level `maintainer` (an unnamed owner IS the orphaning failure), a sunset status requires a deprecation path, and `removeAfter` is rejected on a non-sunset status. `orphaned` is deliberately first-class — a policy that only permits happy statuses gets satisfied by lying. The load-bearing fix: accepted modules ship `default:false` (§6), so every rotted catalog entry is DISABLED by construction — and `preflightModules()` returned only `blocking`, discarding `warnings`, so a real `bongos upgrade --to X` reported `"all enabled modules satisfy the target"` while saying nothing about them. It now returns + prints `warnings`/`deprecations`/`expired` with the maintainer NAMED, before the blocking check returns (so a refused bump reports them too). Enabled mismatches still refuse; disabled ones still never block — report, don't block, because blocking an instance's bump on a catalog entry it never opted into makes the shared catalog a liability. `bongos module check`/`submit` refuse an undeclared posture or an already-sunset module; `GET /modules` + the hall Modules tab show an `upkeep:` chip (incl. `undeclared`); all 17 bundled modules stamped `core-maintained` with a unit test holding the line. Rejected: blocking on disabled rot, a required manifest field (breaks every existing manifest), DB-tracked upkeep (must travel with the module, ADR 0107 §2), auto-deprecating on incompatibility (a fact is not a decision), a separate MAINTAINERS file.](<redacted>.md) | modules / upstreaming |
|
|
242
|
+
| 0168 | [**The scaffold vendors the hub's RUNNING core (`npm pack` of the installed package); registry-default deferred to the go-public step** ([task 1002706](https://cloudbongos.com/builders#/task/1002706); gap 13 of the project-creation audit). Two collided facts: children were born pinned to a frozen `file:vendor/bongos-core-1.19.2.tgz` (installedCoreTarball reuses the hub's own file: pin — task 1002275 — and the hub's pin sat at 1.19.2), and the task-1002621 registry cutover (hub pin now `"@bongos/core": "1.19.56"`, verified on the box) made installedCoreTarball return null — dropping the scaffold into the package-core.js source rebuild that ABORTS on a consumer instance (empty core set → empty child repo, the 1002275 failure resurrected). Fix: a three-rung ladder — file:-pin reuse → NEW `installedCorePackDir()` + `npm pack` of the hub's installed core (child pins the SAME, CURRENT core, stays file:-pinned, owner needs no token) → source rebuild. The brief's "make registry the default now that the package is public" was verified FALSE (both npm scopes 404 anonymously; ADR 0134 keeps them private until go-public) — a registry-default child would be born UNINSTALLABLE for a tokenless owner. Registry-default is deferred to the go-public step (idea 1000700); the gap-13 "flip the box env" ops leg is explicitly a no-op until then; child freshness rides this ladder + the hub-pin lane (task 1002708). Rejected: registry-default now, dropping NPM_TOKEN, vendoring from the npm cacache.](<redacted>.md) | provisioning / distribution |
|
|
243
|
+
| 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 |
|
|
242
244
|
|
|
243
245
|
> ⚠️ **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`.)
|
|
@@ -225,6 +225,16 @@ Organized by topic, not chronology. New entries go in the matching section; crea
|
|
|
225
225
|
- **Fix:** `otb-box-launch.sh` now asserts `defaultMode=bypassPermissions` itself, synchronously, right before it creates a **new** `otb` tmux session — so a fresh session never depends on cron timing. This prevents the race going forward but does **not** repair a box whose `otb` session is already running in the wrong mode: for that, from an SSH/browser-terminal shell run `tmux kill-session -t otb` then reconnect (the launcher creates a fresh session and picks up the corrected setting immediately). Killing the session only drops the terminal pane — it does not touch `/workspace` or in-flight git state.
|
|
226
226
|
- **Why it bites:** every layer *looks* fixed — `~/.claude/settings.json` has the right value, `IS_SANDBOX=1` is set — because you're inspecting the box's filesystem, not the already-running process that never re-read it.
|
|
227
227
|
|
|
228
|
+
## New-project scaffolds & the core pin (gap 13 · task 1002706 · ADR 0168)
|
|
229
|
+
|
|
230
|
+
### Do NOT set `PROVISION_CORE_FROM_REGISTRY=1` on the box until the core package goes public
|
|
231
|
+
|
|
232
|
+
- **Symptom (why you'd be tempted):** the project-creation audit (gap 13) found new projects born on a frozen `file:vendor/bongos-core-1.19.2.tgz`, and the registry-install mode looks like the fix.
|
|
233
|
+
- **Root cause:** `@bongos/core` (and the old `@cloudbongos/core` scope) is a **private** npm package until the ADR 0134 go-public step — both 404 anonymously (verified 2026-08-12). A registry-scaffolded child gets a caret pin + env-fed `.npmrc` that **its owner cannot resolve without a paid-org `NPM_TOKEN`** — a project born uninstallable, strictly worse than born-stale.
|
|
234
|
+
- **Fix (shipped, task 1002706):** nothing to flip. The scaffold now inherits the hub's **running** core automatically: a `file:`-pinned control plane reuses its pinned tarball (task 1002275), a **registry-pinned** control plane (the post-1002621 mothership) `npm pack`s its installed `node_modules/@bongos/core`, and only a true source checkout rebuilds via `package-core.js`. Children stay `file:`-pinned and current-at-birth.
|
|
235
|
+
- **When the package goes public** (idea 1000700 / ADR 0134): flipping registry-default becomes a small follow-up — set `PROVISION_CORE_FROM_REGISTRY=1` in the runner env (token no longer required for public installs; the fail-soft vendor path stays).
|
|
236
|
+
- **Housekeeping:** the mothership's `vendor/` still holds a pile of stale `bongos-core-1.18.x` tarballs no pin references — safe to prune on the next box pass. Child freshness depends on the hub's own pin staying current — that lane is task 1002708 (the upgrade must commit + push the pin, never npm-install in place).
|
|
237
|
+
|
|
228
238
|
## When to add a new entry here
|
|
229
239
|
|
|
230
240
|
Anytime you spend more than ~10 minutes diagnosing something that turned out to have a non-obvious cause, add a section. Include symptom, root cause, fix, and why-it-bites. The cost of a 5-minute write-up is much less than the cost of the next session re-discovering the same thing.
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.71",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.71",
|
|
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.
|
|
3
|
+
"version": "1.19.71",
|
|
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",
|
|
@@ -387,7 +387,11 @@ input[type=text].bad{border-color:var(--err);}
|
|
|
387
387
|
<svg class="gh" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
|
|
388
388
|
Sign in with GitHub
|
|
389
389
|
</a>
|
|
390
|
-
|
|
390
|
+
<!-- Trust link → the AGPL license text (task 1002705): the old private-repo URL
|
|
391
|
+
404ed, and no public code artifact exists until the ADR 0099 mirror flips
|
|
392
|
+
(~2026-11; npm scopes are private too) — the license is the one live,
|
|
393
|
+
instance-neutral artifact behind the claim today. -->
|
|
394
|
+
<p class="finePrint">Free while we find our feet. Your project's repo and server are yours — Cloud Bongos is <a href="https://www.gnu.org/licenses/agpl-3.0.html" style="color:inherit" target="_blank" rel="noopener">open source (AGPL-3.0)</a> and capture-resistant by design.</p>
|
|
391
395
|
<div class="alert" id="gateAlert" role="alert"></div>
|
|
392
396
|
</section>
|
|
393
397
|
|
package/scripts/gds/provision.js
CHANGED
|
@@ -399,6 +399,39 @@ function installedCoreTarball({ instanceRoot, fsImpl = fs } = {}) {
|
|
|
399
399
|
return null;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
// The REGISTRY-pinned sibling of installedCoreTarball (task 1002706). After a control
|
|
403
|
+
// plane moves its own core pin off the vendored tarball onto the npm registry (the
|
|
404
|
+
// cloudbongos.com cutover, task 1002621), its package.json holds a semver pin — no
|
|
405
|
+
// `file:` — so installedCoreTarball returns null and the scaffold would fall into the
|
|
406
|
+
// package-core.js source rebuild, which ABORTS on a consumer instance (the empty-set
|
|
407
|
+
// abort of task 1002275, resurrected by the cutover). The installed package itself is
|
|
408
|
+
// still the exact core this hub runs: return its node_modules dir + version + the
|
|
409
|
+
// `npm pack` tarball name so the scaffold can pack it into a vendorable .tgz. The child
|
|
410
|
+
// stays file:-pinned — its owner needs no npm token (the registry package is PRIVATE
|
|
411
|
+
// until the ADR 0134 go-public step). Returns { dir, version, tarballName } or null
|
|
412
|
+
// (a file: pin, an uninstalled dep, or a source checkout). fs reads only → dry-run safe.
|
|
413
|
+
function installedCorePackDir({ instanceRoot, fsImpl = fs } = {}) {
|
|
414
|
+
const root = instanceRoot || process.env.BONGOS_INSTANCE_ROOT || process.cwd();
|
|
415
|
+
let pkg;
|
|
416
|
+
try { pkg = JSON.parse(fsImpl.readFileSync(path.join(root, 'package.json'), 'utf8')); }
|
|
417
|
+
catch { return null; } // no/unreadable package.json → a source checkout
|
|
418
|
+
const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
|
|
419
|
+
for (const name of ['@bongos/core', '@cloudbongos/core']) {
|
|
420
|
+
const spec = String(deps[name] || '').trim();
|
|
421
|
+
if (!spec || spec.startsWith('file:')) continue; // file: pins belong to installedCoreTarball
|
|
422
|
+
const dir = path.join(root, 'node_modules', ...name.split('/'));
|
|
423
|
+
try {
|
|
424
|
+
const installed = JSON.parse(fsImpl.readFileSync(path.join(dir, 'package.json'), 'utf8'));
|
|
425
|
+
const version = installed && installed.version ? String(installed.version) : null;
|
|
426
|
+
if (!version) continue;
|
|
427
|
+
// npm pack names a scoped tarball <scope>-<name>-<version>.tgz (no @, / → -).
|
|
428
|
+
const base = String(installed.name || name).replace(/^@/, '').replace(/\//g, '-');
|
|
429
|
+
return { dir, version, tarballName: `${base}-${version}.tgz` };
|
|
430
|
+
} catch { /* pinned but not installed → fall through */ }
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
402
435
|
// The onboard mode a provisioning row carries (migration provisioning_004, task 1002562).
|
|
403
436
|
// 'adopt' means target_ref is a repo the owner ALREADY has, so the scaffold must LAYER
|
|
404
437
|
// onto its history. Anything else — including a row written before the column existed, or
|
|
@@ -606,20 +639,38 @@ async function scaffoldStandaloneRepo(inst, deps) {
|
|
|
606
639
|
log(` [scaffold] core install: registry — PRIVATE @bongos/core@${coreV} via env-fed NPM_TOKEN (ADR 0134)`);
|
|
607
640
|
exec(`node scripts/gds/init.js --from ${specPath} --dir ${root} --no-seed ${modeFlags} --registry-core`);
|
|
608
641
|
} else {
|
|
609
|
-
// Vendored tarball
|
|
610
|
-
//
|
|
611
|
-
// with an EMPTY core set when this runner
|
|
612
|
-
//
|
|
613
|
-
//
|
|
642
|
+
// Vendored tarball — a three-rung resolution ladder, freshest-correct first:
|
|
643
|
+
// 1. a `file:`-pinned control plane reuses its own pinned tarball (task 1002275 —
|
|
644
|
+
// rebuilding via package-core.js aborts with an EMPTY core set when this runner
|
|
645
|
+
// IS a consumer instance, leaving new repos empty);
|
|
646
|
+
// 2. a REGISTRY-pinned consumer (the post-1002621 mothership shape) packs the core
|
|
647
|
+
// it has INSTALLED — the child pins the SAME, CURRENT core the hub runs, ending
|
|
648
|
+
// the frozen-old-tarball births (task 1002706, gap 13) without requiring the
|
|
649
|
+
// child's owner to hold a token for the still-private registry package;
|
|
650
|
+
// 3. a genuine core source checkout rebuilds fresh via package-core.js.
|
|
614
651
|
let tgz = installedCoreTarball({ instanceRoot: deps.instanceRoot });
|
|
652
|
+
let packDest = null; // set on the pack rung — cleaned up once init has vendored the tgz
|
|
615
653
|
if (tgz) {
|
|
616
654
|
log(` [scaffold] core install: reusing the pinned core tarball this control plane runs (${path.basename(tgz)}) — no source rebuild (task 1002275)`);
|
|
617
655
|
} else {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
656
|
+
const packSrc = installedCorePackDir({ instanceRoot: deps.instanceRoot });
|
|
657
|
+
if (packSrc) {
|
|
658
|
+
// Keyed by VERSION, not slug: no request-derived value enters this command, and
|
|
659
|
+
// two concurrent scaffolds of the same core pack identical bytes — collision-safe.
|
|
660
|
+
packDest = path.join(os.tmpdir(), `bongos-core-pack-${packSrc.version}`);
|
|
661
|
+
log(` [scaffold] core install: packing the registry-installed core this control plane runs (v${packSrc.version}) — no source rebuild (task 1002706)`);
|
|
662
|
+
exec(`mkdir -p ${packDest}`);
|
|
663
|
+
exec(`npm pack ${packSrc.dir} --pack-destination ${packDest}`);
|
|
664
|
+
tgz = path.join(packDest, packSrc.tarballName);
|
|
665
|
+
} else {
|
|
666
|
+
log(` [scaffold] core install: building a fresh vendored tarball from source (package-core.js)`);
|
|
667
|
+
exec(`node scripts/gds/package-core.js`); // cwd = REPO_ROOT → dist/bongos-core-<v>.tgz
|
|
668
|
+
tgz = path.join(REPO_ROOT, 'dist', `bongos-core-${coreV}.tgz`);
|
|
669
|
+
}
|
|
621
670
|
}
|
|
622
671
|
exec(`node scripts/gds/init.js --from ${specPath} --dir ${root} --no-seed ${modeFlags} --vendor-core ${tgz}`);
|
|
672
|
+
// init --vendor-core COPIED the tarball into the child's vendor/ — the temp pack dir is spent.
|
|
673
|
+
if (packDest) exec(`rm -rf ${packDest}`);
|
|
623
674
|
}
|
|
624
675
|
|
|
625
676
|
// 4. commit + push to the instance's own main (keep node_modules out).
|
|
@@ -1988,7 +2039,7 @@ module.exports = {
|
|
|
1988
2039
|
backupUnitName, backupServicePath, backupTimerPath, backupScriptPath, backupService, backupTimer,
|
|
1989
2040
|
standaloneRoot, standalonePullCmd, standaloneInstallCmd, standaloneMigrateCmd,
|
|
1990
2041
|
// standalone scaffold (ADR 0108 / 0125, task 2055; consumer-core fix task 1002275)
|
|
1991
|
-
parseTargetRef, instanceRepoRemote, instanceInitSpec, installedCoreTarball, scaffoldStandaloneRepo, coreVersionSafe,
|
|
2042
|
+
parseTargetRef, instanceRepoRemote, instanceInitSpec, installedCoreTarball, installedCorePackDir, scaffoldStandaloneRepo, coreVersionSafe,
|
|
1992
2043
|
// adopt vs greenfield onboarding (ADR 0121, task 1002562)
|
|
1993
2044
|
onboardMode, alreadyScaffolded,
|
|
1994
2045
|
zoneForDomain, dnsUpsertEnv, classifyZoneScope, checkDnsTokenScope,
|
package/src/module-api.js
CHANGED
|
@@ -565,8 +565,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
565
565
|
// landed since 1.19.67 with no explicit bump. run 31608183268. (task 1002620)
|
|
566
566
|
// 1.19.69 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
567
567
|
// landed since 1.19.68 with no explicit bump. run 31608503813. (task 1002620)
|
|
568
|
+
// 1.19.70 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
569
|
+
// landed since 1.19.69 with no explicit bump. run 31612248859. (task 1002620)
|
|
570
|
+
// 1.19.71 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
571
|
+
// landed since 1.19.70 with no explicit bump. run 31613220077. (task 1002620)
|
|
568
572
|
// ---------------------------------------------------------------------------
|
|
569
|
-
const CORE_VERSION = '1.19.
|
|
573
|
+
const CORE_VERSION = '1.19.71'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
570
574
|
|
|
571
575
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
572
576
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/onboard.mjs
CHANGED
|
@@ -110,6 +110,19 @@ test('the /create done panel is plan-driven, manifest-driven, and owner-honest (
|
|
|
110
110
|
assert.match(src, /adopt/i, 'the private path (adopt your own private repo) is named');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
test('the /create gate trust link points at a live artifact, not the dead private-repo URL (task 1002705)', () => {
|
|
114
|
+
// Gap 1 of the project-creation audit: the gate linked a nonexistent private repo
|
|
115
|
+
// (404 even authenticated — ADR 0167 names it). No public code artifact exists yet
|
|
116
|
+
// (the ADR 0099 mirror is dormant until ~2026-11, and both npm scopes 404 anonymously
|
|
117
|
+
// — verified 2026-08-12), so the one live, instance-neutral artifact behind
|
|
118
|
+
// "open source" is the license itself.
|
|
119
|
+
const { readFileSync } = require('node:fs');
|
|
120
|
+
const path = require('node:path');
|
|
121
|
+
const src = readFileSync(path.join(import.meta.dirname, '..', 'public-landing/create.html'), 'utf8');
|
|
122
|
+
assert.doesNotMatch(src, /Claude-OTB/, 'the dead repo link is gone');
|
|
123
|
+
assert.match(src, /https:\/\/www\.gnu\.org\/licenses\/agpl-3\.0/, 'the trust link resolves (the AGPL-3.0 license text)');
|
|
124
|
+
});
|
|
125
|
+
|
|
113
126
|
test('oauthAppInstructions pins the apex callback + homepage and points at ACCOUNT Developer settings', () => {
|
|
114
127
|
const oa = ob.oauthAppInstructions('mercury.example.com');
|
|
115
128
|
assert.equal(oa.homepageUrl, 'https://mercury.example.com');
|
package/tests/provision.mjs
CHANGED
|
@@ -489,7 +489,8 @@ t('installedCoreTarball: reuses a consumer instance file: core pin; null on a so
|
|
|
489
489
|
rmSync(join(inst, 'vendor', 'bongos-core-1.17.4.tgz'));
|
|
490
490
|
assert.equal(P.installedCoreTarball({ instanceRoot: inst }), null, 'a dangling file: pin resolves to null');
|
|
491
491
|
|
|
492
|
-
//
|
|
492
|
+
// a caret range (no file: pin) → null HERE — the registry-consumer case is
|
|
493
|
+
// installedCorePackDir's (task 1002706); only a true source checkout rebuilds
|
|
493
494
|
const src = mkdtempSync(join(tmpdir(), 'cptgz-source-'));
|
|
494
495
|
writeFileSync(join(src, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': '^1.17.4' } }));
|
|
495
496
|
assert.equal(P.installedCoreTarball({ instanceRoot: src }), null, 'a source checkout has no file: pin');
|
|
@@ -535,6 +536,80 @@ await ta('scaffoldStandaloneRepo: on a consumer control plane it REUSES the pinn
|
|
|
535
536
|
}
|
|
536
537
|
});
|
|
537
538
|
|
|
539
|
+
// ── registry-pinned consumer control plane (task 1002706) ─────────────────────────
|
|
540
|
+
// After the mothership's registry cutover (task 1002621) its package.json pins
|
|
541
|
+
// "@bongos/core": "1.19.x" — NO file: pin — so installedCoreTarball returns null and,
|
|
542
|
+
// before this fix, the scaffold fell into the package-core.js source rebuild, which
|
|
543
|
+
// ABORTS on a consumer instance (empty core set → empty child repo — the 1002275
|
|
544
|
+
// failure resurrected). Pack the INSTALLED core instead: the child pins the SAME,
|
|
545
|
+
// CURRENT core the hub runs (also kills the frozen-1.19.2 born-stale bug, gap 13).
|
|
546
|
+
t('installedCorePackDir: a registry-pinned consumer with an installed core → its node_modules dir; file:/uninstalled/bare → null', () => {
|
|
547
|
+
const reg = mkdtempSync(join(tmpdir(), 'cpdir-reg-'));
|
|
548
|
+
mkdirSync(join(reg, 'node_modules', '@bongos', 'core'), { recursive: true });
|
|
549
|
+
writeFileSync(join(reg, 'node_modules', '@bongos', 'core', 'package.json'), JSON.stringify({ name: '@bongos/core', version: '1.19.56' }));
|
|
550
|
+
writeFileSync(join(reg, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': '1.19.56' } }));
|
|
551
|
+
const hit = P.installedCorePackDir({ instanceRoot: reg });
|
|
552
|
+
assert.ok(hit, 'a registry-pinned consumer resolves');
|
|
553
|
+
assert.equal(hit.dir, join(reg, 'node_modules', '@bongos', 'core'));
|
|
554
|
+
assert.equal(hit.version, '1.19.56');
|
|
555
|
+
assert.equal(hit.tarballName, 'bongos-core-1.19.56.tgz', 'npm pack naming for the scoped package');
|
|
556
|
+
|
|
557
|
+
// a file: pin belongs to installedCoreTarball, never this path
|
|
558
|
+
const filePinned = mkdtempSync(join(tmpdir(), 'cpdir-file-'));
|
|
559
|
+
writeFileSync(join(filePinned, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': 'file:vendor/bongos-core-1.17.4.tgz' } }));
|
|
560
|
+
assert.equal(P.installedCorePackDir({ instanceRoot: filePinned }), null, 'file: pin → null');
|
|
561
|
+
|
|
562
|
+
// registry pin but the dep is not installed → null → the source rebuild stays the fallback
|
|
563
|
+
const uninstalled = mkdtempSync(join(tmpdir(), 'cpdir-unin-'));
|
|
564
|
+
writeFileSync(join(uninstalled, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': '^1.19.0' } }));
|
|
565
|
+
assert.equal(P.installedCorePackDir({ instanceRoot: uninstalled }), null, 'uninstalled → null');
|
|
566
|
+
|
|
567
|
+
// no package.json at all → null
|
|
568
|
+
const bare2 = mkdtempSync(join(tmpdir(), 'cpdir-bare-'));
|
|
569
|
+
assert.equal(P.installedCorePackDir({ instanceRoot: bare2 }), null, 'no package.json → null');
|
|
570
|
+
|
|
571
|
+
// the @cloudbongos/core alias is honored (matches installedCoreTarball + core-node.sh),
|
|
572
|
+
// and the tarball name follows the INSTALLED package's own name
|
|
573
|
+
const alt2 = mkdtempSync(join(tmpdir(), 'cpdir-alt-'));
|
|
574
|
+
mkdirSync(join(alt2, 'node_modules', '@cloudbongos', 'core'), { recursive: true });
|
|
575
|
+
writeFileSync(join(alt2, 'node_modules', '@cloudbongos', 'core', 'package.json'), JSON.stringify({ name: '@cloudbongos/core', version: '2.0.0' }));
|
|
576
|
+
writeFileSync(join(alt2, 'package.json'), JSON.stringify({ dependencies: { '@cloudbongos/core': '^2.0.0' } }));
|
|
577
|
+
assert.equal(P.installedCorePackDir({ instanceRoot: alt2 }).tarballName, 'cloudbongos-core-2.0.0.tgz');
|
|
578
|
+
|
|
579
|
+
[reg, filePinned, uninstalled, bare2, alt2].forEach((d) => rmSync(d, { recursive: true, force: true }));
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
await ta('scaffoldStandaloneRepo: a REGISTRY-pinned consumer control plane PACKS its installed core — current version, no source rebuild (task 1002706)', async () => {
|
|
583
|
+
const cp = mkdtempSync(join(tmpdir(), 'cpdir-cp-'));
|
|
584
|
+
mkdirSync(join(cp, 'node_modules', '@bongos', 'core'), { recursive: true });
|
|
585
|
+
writeFileSync(join(cp, 'node_modules', '@bongos', 'core', 'package.json'), JSON.stringify({ name: '@bongos/core', version: '1.19.56' }));
|
|
586
|
+
writeFileSync(join(cp, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': '1.19.56' } }));
|
|
587
|
+
const base = mkdtempSync(join(tmpdir(), 'cpdir-standalone-')); // FRESH base → the scaffold proceeds
|
|
588
|
+
const origBase = P.CONFIG.standaloneBase;
|
|
589
|
+
P.CONFIG.standaloneBase = base;
|
|
590
|
+
try {
|
|
591
|
+
const { deps, cmds } = recorder({ apply: true });
|
|
592
|
+
await P.scaffoldStandaloneRepo(
|
|
593
|
+
{ slug: 'demo', hosting_shape: 'standalone', target_ref: 'lars589/demo' },
|
|
594
|
+
{ ...deps, instanceRoot: cp },
|
|
595
|
+
);
|
|
596
|
+
const joined = cmds.join('\n');
|
|
597
|
+
assert.ok(!/package-core\.js/.test(joined), 'does NOT rebuild from source (the empty-set abort on a consumer)');
|
|
598
|
+
assert.match(joined, /npm pack /, 'packs the installed core');
|
|
599
|
+
assert.match(joined, /--vendor-core \S*bongos-core-1\.19\.56\.tgz/, 'vendors the CURRENT core the hub runs into the child');
|
|
600
|
+
assert.ok(!/--registry-core/.test(joined), 'the child stays file:-pinned — its owner needs no npm token');
|
|
601
|
+
// the temp pack dir is version-keyed (no request-derived slug in the command) and
|
|
602
|
+
// cleaned up once init has vendored the tarball into the child
|
|
603
|
+
assert.match(joined, /mkdir -p \S*bongos-core-pack-1\.19\.56/, 'pack dir is keyed by core version');
|
|
604
|
+
const initAt = joined.indexOf('--vendor-core');
|
|
605
|
+
const rmAt = joined.indexOf('rm -rf');
|
|
606
|
+
assert.ok(rmAt > initAt && /rm -rf \S*bongos-core-pack-1\.19\.56/.test(joined), 'temp pack dir removed AFTER init consumed the tarball');
|
|
607
|
+
} finally {
|
|
608
|
+
P.CONFIG.standaloneBase = origBase;
|
|
609
|
+
[cp, base].forEach((d) => rmSync(d, { recursive: true, force: true }));
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
538
613
|
// ── scaffold push via the owner OAuth token (task 1002317) ────────────────────────
|
|
539
614
|
// Deploy keys are per-repo; a shared key can't write to a NEW project repo. Push with the
|
|
540
615
|
// owner's token (which created the repo) instead — WITHOUT leaking it into a logged command.
|