@bongos/core 1.24.70 → 1.24.72

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.
@@ -757,7 +757,7 @@ html[data-theme="dark"] .brand-mark__mark { --mark-ink: #e2e1e4; }
757
757
  .genesis__step-n { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; font-size: 10px; background: var(--rule-soft); }
758
758
  .genesis__step.is-done { color: var(--ink-soft); }
759
759
  .genesis__step.is-now { color: var(--ink); border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
760
- .genesis__step.is-now .genesis__step-n { background: var(--accent); color: var(--bg); }
760
+ .genesis__step.is-now .genesis__step-n { background: var(--accent); color: var(--accent-on); }
761
761
  .genesis__plan, .genesis__stages, .genesis__tasks, .genesis__life { list-style: none; margin: 0; padding: 0; }
762
762
  .genesis__plan-row, .genesis__stage, .genesis__task { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid var(--rule-soft); }
763
763
  .genesis__plan-row:first-child, .genesis__stage:first-child, .genesis__task:first-child { border-top: 0; }
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.24.70",
3
+ "version": "1.24.72",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.24.70",
9
+ "version": "1.24.72",
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.24.70",
3
+ "version": "1.24.72",
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",
@@ -11445,5 +11445,17 @@
11445
11445
  "id": "1004949",
11446
11446
  "text": "When a shell command was blocked by one hook and another hook was missing, the warning about the missing hook vanished. Now both messages show."
11447
11447
  }
11448
+ ],
11449
+ "1.24.71": [
11450
+ {
11451
+ "id": "1002450",
11452
+ "text": "New projects can no longer be born on an outdated or mislabelled copy of the core. When the hub's saved core file is stale or doesn't match the published one, provisioning now says so loudly and uses the current, published cor"
11453
+ }
11454
+ ],
11455
+ "1.24.72": [
11456
+ {
11457
+ "id": "1005103",
11458
+ "text": "The current step number in the project-setup steps is now dark ink on the orange dot, so it's readable in light mode too."
11459
+ }
11448
11460
  ]
11449
11461
  }
@@ -533,7 +533,9 @@ function installedCoreTarball({ instanceRoot, fsImpl = fs } = {}) {
533
533
  // nothing either way. The file: pin is kept for the reason in ADR 0168 — a child is born
534
534
  // on the core its parent actually runs — not for access control.) Returns { dir, version, tarballName } or null
535
535
  // (a file: pin, an uninstalled dep, or a source checkout). fs reads only → dry-run safe.
536
- function installedCorePackDir({ instanceRoot, fsImpl = fs } = {}) {
536
+ // `includeFilePins` (task 1002450): the stale-pin recovery below packs the core a
537
+ // file:-pinned hub has INSTALLED, so it must not skip the file: spec the default does.
538
+ function installedCorePackDir({ instanceRoot, fsImpl = fs, includeFilePins = false } = {}) {
537
539
  const root = instanceRoot || process.env.BONGOS_INSTANCE_ROOT || process.cwd();
538
540
  let pkg;
539
541
  try { pkg = JSON.parse(fsImpl.readFileSync(path.join(root, 'package.json'), 'utf8')); }
@@ -541,7 +543,7 @@ function installedCorePackDir({ instanceRoot, fsImpl = fs } = {}) {
541
543
  const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
542
544
  for (const name of ['@bongos/core', '@cloudbongos/core']) {
543
545
  const spec = String(deps[name] || '').trim();
544
- if (!spec || spec.startsWith('file:')) continue; // file: pins belong to installedCoreTarball
546
+ if (!spec || (spec.startsWith('file:') && !includeFilePins)) continue; // file: pins belong to installedCoreTarball
545
547
  const dir = path.join(root, 'node_modules', ...name.split('/'));
546
548
  try {
547
549
  const installed = JSON.parse(fsImpl.readFileSync(path.join(dir, 'package.json'), 'utf8'));
@@ -568,13 +570,113 @@ function coreCheckoutHasGit({ repoRoot = REPO_ROOT, fsImpl = fs } = {}) {
568
570
  // The core version THIS control plane runs — what the ladder below would vend: the
569
571
  // pinned tarball's version, else the registry-installed package's, else the checkout's
570
572
  // CORE_VERSION. fs reads only → dry-run safe.
573
+ // A pinned tarball whose label disagrees with coreV is STALE (task 1002450): the hall runs
574
+ // coreV, so that is its running version, not the leftover tarball's label.
571
575
  function runningCoreVersion({ instanceRoot, coreV }) {
572
576
  const pinned = installedCoreTarball({ instanceRoot });
573
- if (pinned) return require('./upgrade').versionFromTgzPath(path.basename(pinned)) || coreV;
577
+ if (pinned) {
578
+ const pinnedV = pinnedTarballVersion(pinned);
579
+ return (coreV && pinnedV && pinnedV !== coreV) ? coreV : (pinnedV || coreV);
580
+ }
574
581
  const packSrc = installedCorePackDir({ instanceRoot });
575
582
  return packSrc ? packSrc.version : coreV;
576
583
  }
577
584
 
585
+ // ── the stale-pin guard (task 1002450) ────────────────────────────────────────────
586
+ // Rung 1 below trusted a file:-pinned hub's own vendored tarball unconditionally ("the
587
+ // child pins the SAME core the hub runs"). Two ways that was false, both seen live: an
588
+ // out-of-band upgrade swaps node_modules/@bongos/core without rewriting vendor/*.tgz, so
589
+ // the label trails the core the hub RUNS; and the same label can name different bytes —
590
+ // an early instance was born on a 1.18.14 tarball 15 kB smaller than the published 1.18.14,
591
+ // missing the task-1002419 poller fix, so its first ship never left 'confirmed'. Quiet
592
+ // failure, so this guard is loud.
593
+ //
594
+ // The two sibling gaps are closed elsewhere, on purpose — tests/provision.mjs proves each:
595
+ // - PUBLISHING one version twice as different bytes: the npm registry refuses it (a
596
+ // version is immutable), and .github/workflows/publish.yml fails the run loudly on
597
+ // that refusal (task 1004886). What escaped was a LOCAL build carrying a published
598
+ // label — the vendoring this guard checks.
599
+ // - a hub BEHIND upstream: projectCoreDecision gives a new project the release when
600
+ // the runner is behind it (task 1004556), and that target short-circuits this ladder.
601
+ // The integrity read costs one `npm view` on the reuse path; projectCoreTarget already
602
+ // makes one per scaffold, and both fail open when the registry is unreachable.
603
+
604
+ // The version a core tarball's FILENAME carries — both scope aliases (bongos-core-*,
605
+ // cloudbongos-core-*), which upgrade.versionFromTgzPath (bongos-core only) would miss.
606
+ // Digits, dots and [A-Za-z0-9.+-] only, so the result is shell-safe. PURE.
607
+ function pinnedTarballVersion(p) {
608
+ const m = /(?:^|-)core-(\d+\.\d+\.\d+[A-Za-z0-9.+-]*)\.tgz$/.exec(path.basename(String(p || '')));
609
+ return m ? m[1] : null;
610
+ }
611
+
612
+ // A version that may enter a shell command, or null — the same character set as
613
+ // safeVersionLabel, the file's interpolation chokepoint. PURE.
614
+ function shellSafeVersion(v) {
615
+ const s = safeVersionLabel(v);
616
+ return s === '(unversioned)' ? null : s;
617
+ }
618
+
619
+ // npm's dist.integrity form for a file: sha512, base64. fs injectable for tests.
620
+ function tarballIntegrity(p, fsImpl = fs) {
621
+ return 'sha512-' + crypto.createHash('sha512').update(fsImpl.readFileSync(p)).digest('base64');
622
+ }
623
+
624
+ // Is the pinned tarball the core this hub runs, AND the bytes the registry published
625
+ // under that label? → { verdict, pinnedV, reason }:
626
+ // 'stale-version' — its label is not coreV (the hub moved on, the tarball did not);
627
+ // 'stale-bytes' — the label matches but the registry's integrity for it differs
628
+ // (the charter case: same version, different artifact);
629
+ // 'unverifiable' — no coreV, an unparseable label, or no registry answer: reuse it
630
+ // (fail-open, never block a scaffold on a resolution gap) but SAY so;
631
+ // 'fresh' — both checks pass.
632
+ // The registry read goes through the injected exec, so a dry run never hits the network.
633
+ function checkPinnedTarball({ pinned, coreV, exec, fsImpl = fs }) {
634
+ const pinnedV = shellSafeVersion(pinnedTarballVersion(pinned));
635
+ if (!pinnedV) return { verdict: 'unverifiable', pinnedV, reason: 'no version in its filename' };
636
+ if (!coreV) return { verdict: 'unverifiable', pinnedV, reason: 'the running core version is unknown' };
637
+ if (pinnedV !== coreV) return { verdict: 'stale-version', pinnedV, reason: `it is ${pinnedV} but this control plane runs ${coreV}` };
638
+ const res = exec(`npm view ${CORE_PKG}@${pinnedV} dist.integrity`, { allowFail: true });
639
+ const published = String((res && res.ok !== false && res.stdout) || '').trim();
640
+ if (!/^sha512-/.test(published)) return { verdict: 'unverifiable', pinnedV, reason: `the registry gave no integrity for ${pinnedV}` };
641
+ let local;
642
+ try { local = tarballIntegrity(pinned, fsImpl); } catch { return { verdict: 'unverifiable', pinnedV, reason: 'it could not be read' }; }
643
+ if (local !== published) return { verdict: 'stale-bytes', pinnedV, reason: `its bytes are not the ${pinnedV} the registry published (a different build under the same version label)` };
644
+ return { verdict: 'fresh', pinnedV, reason: 'matches the running core and the published bytes' };
645
+ }
646
+
647
+ // Where a stale pin goes instead. NEVER to the package-core.js rungs: on a file:-pinned
648
+ // consumer hub those abort on an empty core set and leave the new repo empty (task 1002275).
649
+ // stale-bytes → the registry's own bytes for that version (canonical by definition);
650
+ // stale-version → the core the hub has INSTALLED, when it is coreV; else the registry's coreV;
651
+ // neither → refuse, loudly: no project is born on a core nobody can name.
652
+ function recoverFromStalePin({ instanceRoot, exec, log, tag, coreV, check }) {
653
+ const fromRegistry = (raw) => {
654
+ const v = shellSafeVersion(raw); // interpolated into a shell command below
655
+ if (!v) return null;
656
+ const packDest = path.join(os.tmpdir(), `bongos-core-registry-${v}`);
657
+ exec(`mkdir -p ${packDest}`);
658
+ const res = exec(`npm pack ${CORE_PKG}@${v} --pack-destination ${packDest}`, { allowFail: true });
659
+ if (res && res.ok === false) { exec(`rm -rf ${packDest}`); return null; }
660
+ log(` ${tag} packed the published ${v} from the registry instead (task 1002450)`);
661
+ return { tgz: path.join(packDest, `bongos-core-${v}.tgz`), packDest };
662
+ };
663
+ if (check.verdict === 'stale-version') {
664
+ const installed = installedCorePackDir({ instanceRoot, includeFilePins: true });
665
+ const v = installed && shellSafeVersion(installed.version); // interpolated into a shell command below
666
+ if (v && v === coreV) {
667
+ const packDest = path.join(os.tmpdir(), `bongos-core-pack-${v}`);
668
+ log(` ${tag} packing the installed core this control plane runs (v${v}) instead (task 1002450)`);
669
+ exec(`mkdir -p ${packDest}`);
670
+ exec(`npm pack ${installed.dir} --pack-destination ${packDest}`);
671
+ return { tgz: path.join(packDest, installed.tarballName), packDest };
672
+ }
673
+ }
674
+ const v = check.verdict === 'stale-bytes' ? check.pinnedV : coreV;
675
+ const got = fromRegistry(v);
676
+ if (got) return got;
677
+ throw new Error(`refusing to give a new project a stale core: the pinned tarball ${check.reason}, and neither an installed core ${coreV} nor a published ${v} could be packed. Re-run \`bongos upgrade\` on this control plane so its vendor/ tarball matches the core it runs, then retry (task 1002450).`);
678
+ }
679
+
578
680
  // Which core a hosted project is given (task 1004299, ADR 0361 D5). PURE. Since merges
579
681
  // publish as candidates, the platform hall runs ahead of the registry's `latest` label by
580
682
  // design — and the ladder below vends whatever the hall runs, so every new project would
@@ -617,7 +719,8 @@ function projectCoreTarget({ instanceRoot, coreV, exec, log, tag = '[core]' }) {
617
719
  // project gets the released version packed from the registry, not this hall's core.
618
720
  // 1. a `file:`-pinned control plane reuses its own pinned tarball (task 1002275 —
619
721
  // rebuilding via package-core.js aborts with an EMPTY core set when this runner
620
- // IS a consumer instance, leaving new repos empty);
722
+ // IS a consumer instance, leaving new repos empty) — unless checkPinnedTarball
723
+ // finds it STALE, when recoverFromStalePin replaces it (task 1002450);
621
724
  // 2. a REGISTRY-pinned consumer (the post-1002621 mothership shape) packs the core
622
725
  // it has INSTALLED — the child pins the SAME, CURRENT core the hub runs, ending
623
726
  // the frozen-old-tarball births (task 1002706, gap 13) without requiring the
@@ -641,8 +744,14 @@ function resolveVendorableCoreTarball({ instanceRoot, repoRoot = REPO_ROOT, exec
641
744
  }
642
745
  const pinned = installedCoreTarball({ instanceRoot });
643
746
  if (pinned) {
644
- log(` ${tag} reusing the pinned core tarball this control plane runs (${path.basename(pinned)}) — no source rebuild (task 1002275)`);
645
- return { tgz: pinned, packDest: null };
747
+ const check = checkPinnedTarball({ pinned, coreV, exec });
748
+ if (check.verdict === 'fresh' || check.verdict === 'unverifiable') {
749
+ if (check.verdict === 'unverifiable') log(` ${tag} WARNING: cannot verify the pinned core tarball ${path.basename(pinned)} — ${check.reason}; reusing it anyway (task 1002450)`);
750
+ log(` ${tag} reusing the pinned core tarball this control plane runs (${path.basename(pinned)}) — no source rebuild (task 1002275)`);
751
+ return { tgz: pinned, packDest: null };
752
+ }
753
+ log(` ${tag} STALE pinned core tarball ${path.basename(pinned)} — ${check.reason}. NOT vendoring it into a new project (task 1002450)`);
754
+ return recoverFromStalePin({ instanceRoot, exec, log, tag, coreV, check });
646
755
  }
647
756
  const packSrc = installedCorePackDir({ instanceRoot });
648
757
  if (packSrc) {
@@ -1294,6 +1403,7 @@ module.exports = {
1294
1403
  ownerLoginOf,
1295
1404
  asPostgres,
1296
1405
  buildCorePinRefreshCommit,
1406
+ checkPinnedTarball,
1297
1407
  coreCheckoutHasGit,
1298
1408
  dbCreateCmd,
1299
1409
  dbName,
@@ -1318,6 +1428,7 @@ module.exports = {
1318
1428
  migrateCmd,
1319
1429
  onboardMode,
1320
1430
  parseTargetRef,
1431
+ pinnedTarballVersion,
1321
1432
  planCorePinRefresh,
1322
1433
  refreshStandaloneCorePin,
1323
1434
  resolveOwnerGithubToken,
package/src/module-api.js CHANGED
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
81
81
  // MAJOR (see allowBoxScope below): passes the request through untouched.
82
82
  function deprecatedNoopMiddleware(_req, _res, next) { next(); }
83
83
 
84
- const CORE_VERSION = '1.24.70'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
84
+ const CORE_VERSION = '1.24.72'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
85
85
 
86
86
  // A namespaced logger so a module's log lines are attributable + consistent.
87
87
  // Usage: const log = api.logger('discord'); log.info('mounted');
@@ -406,3 +406,22 @@ test('the reduced-motion kill switch is present and closes the token layer', ()
406
406
  assert.equal(src.split('@media (prefers-reduced-motion: reduce)').length - 1, 1,
407
407
  'exactly one kill switch — a second copy is a place for the rule to rot');
408
408
  });
409
+
410
+ test('ink set on an --accent fill is readable on it in both modes', () => {
411
+ // Task 1005103: .genesis__step.is-now .genesis__step-n painted --bg on the
412
+ // accent (light ~2.2:1). Any rule that fills with var(--accent) and names its
413
+ // own ink token must measure that ink against the fill, in both modes.
414
+ const fails = [];
415
+ const plain = src.replace(/\/\*[\s\S]*?\*\//g, '');
416
+ for (const m of plain.matchAll(/([^{}]+)\{([^{}]*)\}/g)) {
417
+ const body = m[2];
418
+ if (!/background(?:-color)?\s*:\s*var\(--accent\)\s*[;}]?/.test(body)) continue;
419
+ const ink = body.match(/(?:^|[;\s])color\s*:\s*var\((--[\w-]+)\)/);
420
+ if (!ink) continue;
421
+ for (const mode of ['light', 'dark']) {
422
+ const r = ratio(ink[1], '--accent', mode);
423
+ if (r < 4.5) fails.push(`${mode} ${m[1].trim()}: ${ink[1]} on --accent = ${r.toFixed(2)}:1`);
424
+ }
425
+ }
426
+ assert.deepEqual(fails, [], 'ink on an accent fill needs 4.5:1');
427
+ });
@@ -14,6 +14,7 @@ import { strict as assert } from 'node:assert';
14
14
  import { createRequire } from 'node:module';
15
15
  import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
16
16
  import { tmpdir } from 'node:os';
17
+ import { createHash } from 'node:crypto';
17
18
  import { join } from 'node:path';
18
19
 
19
20
  const require = createRequire(import.meta.url);
@@ -905,12 +906,15 @@ t('installedCoreTarball: reuses a consumer instance file: core pin; null on a so
905
906
  });
906
907
 
907
908
  await ta('scaffoldStandaloneRepo: on a consumer control plane it REUSES the pinned tarball — no package-core rebuild (task 1002275)', async () => {
908
- // the control plane is itself a consumer instance: its package.json file:-pins the core
909
+ // the control plane is itself a consumer instance: its package.json file:-pins the core.
910
+ // Pinned to the REAL running CORE_VERSION — a fixed old literal would now be STALE
911
+ // (task 1002450) and exercise the recovery instead of the reuse this test is named for.
912
+ const coreV = P.coreVersionSafe();
909
913
  const cp = mkdtempSync(join(tmpdir(), 'cptgz-cp-'));
910
914
  mkdirSync(join(cp, 'vendor'));
911
- const pinned = join(cp, 'vendor', 'bongos-core-1.17.4.tgz');
915
+ const pinned = join(cp, 'vendor', `bongos-core-${coreV}.tgz`);
912
916
  writeFileSync(pinned, 'x');
913
- writeFileSync(join(cp, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': 'file:vendor/bongos-core-1.17.4.tgz' } }));
917
+ writeFileSync(join(cp, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': `file:vendor/bongos-core-${coreV}.tgz` } }));
914
918
  const base = mkdtempSync(join(tmpdir(), 'cptgz-standalone-')); // FRESH base → the scaffold proceeds
915
919
  const origBase = P.CONFIG.standaloneBase;
916
920
  P.CONFIG.standaloneBase = base;
@@ -931,6 +935,127 @@ await ta('scaffoldStandaloneRepo: on a consumer control plane it REUSES the pinn
931
935
  }
932
936
  });
933
937
 
938
+ // ── the stale-pin guard (task 1002450) ───────────────────────────────────────────────
939
+ // Rung 1 reused a file:-pinned hub's own tarball with no check it was still the core the
940
+ // hub runs — an early instance was born on a 1.18.14 tarball that was NOT the published
941
+ // 1.18.14 (missing the task-1002419 poller fix) and its first ship never left 'confirmed'.
942
+ // A stale pin must be replaced, loudly, and never by the package-core.js rungs (which
943
+ // abort on a consumer hub and leave the new repo empty — task 1002275).
944
+ const sha512 = (txt) => 'sha512-' + createHash('sha512').update(txt).digest('base64');
945
+ function filePinnedHub(label, bytes = 'x', { installed = null, scope = 'bongos' } = {}) {
946
+ const cp = mkdtempSync(join(tmpdir(), 'stalepin-'));
947
+ mkdirSync(join(cp, 'vendor'));
948
+ const file = `${scope}-core-${label}.tgz`;
949
+ writeFileSync(join(cp, 'vendor', file), bytes);
950
+ writeFileSync(join(cp, 'package.json'), JSON.stringify({ dependencies: { [`@${scope}/core`]: `file:vendor/${file}` } }));
951
+ if (installed) {
952
+ mkdirSync(join(cp, 'node_modules', '@bongos', 'core'), { recursive: true });
953
+ writeFileSync(join(cp, 'node_modules', '@bongos', 'core', 'package.json'), JSON.stringify({ name: '@bongos/core', version: installed }));
954
+ }
955
+ return { cp, pinned: join(cp, 'vendor', file) };
956
+ }
957
+ function resolveWith(cp, coreV, respond = () => ({ ok: true, stdout: '' })) {
958
+ const cmds = [], logs = [];
959
+ let res, err;
960
+ try {
961
+ res = P.resolveVendorableCoreTarball({ instanceRoot: cp, exec: (c, o) => { cmds.push(c); return respond(c, o); }, log: (m) => logs.push(m), coreV });
962
+ } catch (e) { err = e; }
963
+ return { ...res, cmds, logs, err };
964
+ }
965
+
966
+ t('pinnedTarballVersion: reads both scope aliases; null when the name carries no version', () => {
967
+ assert.equal(PR.pinnedTarballVersion('/x/vendor/bongos-core-1.18.14.tgz'), '1.18.14');
968
+ assert.equal(PR.pinnedTarballVersion('cloudbongos-core-2.0.0.tgz'), '2.0.0', 'the @cloudbongos alias the ARTIFACT regex in upgrade.js misses');
969
+ assert.equal(PR.pinnedTarballVersion('vendor/core.tgz'), null);
970
+ });
971
+
972
+ t('stale label on a file:-pinned hub → packs the INSTALLED core it runs, loudly, never package-core.js (task 1002450)', () => {
973
+ const { cp, pinned } = filePinnedHub('1.18.14', 'x', { installed: '1.18.17' });
974
+ const r = resolveWith(cp, '1.18.17');
975
+ assert.ok(!r.err, String(r.err));
976
+ assert.ok(r.logs.some((l) => /STALE/.test(l) && /1\.18\.14/.test(l) && /1\.18\.17/.test(l)), `a loud warning naming both versions, got: ${r.logs.join(' | ')}`);
977
+ assert.notEqual(r.tgz, pinned, 'never vendors the stale tarball');
978
+ assert.ok(r.cmds.some((c) => c.startsWith('npm pack ') && c.includes(join(cp, 'node_modules', '@bongos', 'core'))), 'packs node_modules/@bongos/core despite the file: pin');
979
+ assert.equal(r.tgz, join(r.packDest, 'bongos-core-1.18.17.tgz'));
980
+ assert.ok(!r.cmds.some((c) => /package-core\.js/.test(c)), 'the empty-set abort path is never reached');
981
+ assert.equal(PR.runningCoreVersion({ instanceRoot: cp, coreV: '1.18.17' }), '1.18.17', 'the hall runs coreV, not the leftover label');
982
+ rmSync(cp, { recursive: true, force: true });
983
+ });
984
+
985
+ t('stale label and no installed match → the registry\'s coreV; no registry either → refuses loudly, never an empty repo (task 1002450)', () => {
986
+ const { cp } = filePinnedHub('1.18.14');
987
+ const ok = resolveWith(cp, '1.18.17');
988
+ assert.ok(ok.cmds.some((c) => c.startsWith('npm pack @bongos/core@1.18.17 ')), `packs the published coreV, got: ${ok.cmds.join(' | ')}`);
989
+ assert.equal(ok.tgz, join(ok.packDest, 'bongos-core-1.18.17.tgz'));
990
+ const down = resolveWith(cp, '1.18.17', (c) => (c.startsWith('npm pack ') ? { ok: false, stdout: '' } : { ok: true, stdout: '' }));
991
+ assert.ok(down.err && /refusing to give a new project a stale core/.test(down.err.message), 'a scaffold with nothing current to vendor is refused');
992
+ assert.ok(!down.cmds.some((c) => /package-core\.js/.test(c)));
993
+ rmSync(cp, { recursive: true, force: true });
994
+ });
995
+
996
+ t('same label, different bytes (the charter case) → the registry\'s own bytes for that version; matching bytes → reuse (task 1002450)', () => {
997
+ const { cp, pinned } = filePinnedHub('1.18.14', 'local-build');
998
+ const view = (published) => (c) => (c.startsWith('npm view @bongos/core@1.18.14 dist.integrity') ? { ok: true, stdout: published + '\n' } : { ok: true, stdout: '' });
999
+ const bad = resolveWith(cp, '1.18.14', view(sha512('published-build')));
1000
+ assert.ok(bad.logs.some((l) => /STALE/.test(l) && /same version label/.test(l)), `loud, got: ${bad.logs.join(' | ')}`);
1001
+ assert.ok(bad.cmds.some((c) => c.startsWith('npm pack @bongos/core@1.18.14 ')), 'repacks the canonical published artifact');
1002
+ assert.notEqual(bad.tgz, pinned);
1003
+ const good = resolveWith(cp, '1.18.14', view(sha512('local-build')));
1004
+ assert.equal(good.tgz, pinned, 'identical bytes → reuse');
1005
+ assert.equal(good.packDest, null);
1006
+ assert.ok(!good.logs.some((l) => /STALE|WARNING/.test(l)));
1007
+ rmSync(cp, { recursive: true, force: true });
1008
+ });
1009
+
1010
+ t('unverifiable pin (no coreV, no registry answer) → reused, but SAID out loud; the cloudbongos alias is checked too (task 1002450)', () => {
1011
+ const { cp, pinned } = filePinnedHub('1.18.14');
1012
+ const noCore = resolveWith(cp, null);
1013
+ assert.equal(noCore.tgz, pinned, 'fail-open: a resolution gap never blocks a scaffold');
1014
+ assert.ok(noCore.logs.some((l) => /WARNING: cannot verify/.test(l)), 'but it is not silent');
1015
+ const offline = resolveWith(cp, '1.18.14');
1016
+ assert.equal(offline.tgz, pinned);
1017
+ assert.ok(offline.logs.some((l) => /WARNING: cannot verify/.test(l) && /no integrity/.test(l)));
1018
+ rmSync(cp, { recursive: true, force: true });
1019
+ const alt = filePinnedHub('1.0.0', 'x', { scope: 'cloudbongos' });
1020
+ const r = resolveWith(alt.cp, '1.0.1');
1021
+ assert.ok(r.logs.some((l) => /STALE/.test(l)), 'a cloudbongos-core-* pin is not exempt from the label check');
1022
+ assert.notEqual(r.tgz, alt.pinned);
1023
+ rmSync(alt.cp, { recursive: true, force: true });
1024
+ });
1025
+
1026
+ t('a stale pin\'s recovery never puts an unsafe version into a shell command (task 1002450)', () => {
1027
+ const { cp } = filePinnedHub('1.18.14');
1028
+ const r = resolveWith(cp, '1.18.17;touch pwn');
1029
+ assert.ok(!r.cmds.some((c) => /pwn/.test(c)), `no command carries the label, got: ${r.cmds.join(' | ')}`);
1030
+ assert.ok(r.err && /refusing to give a new project a stale core/.test(r.err.message), 'nothing safe to pack → refused');
1031
+ rmSync(cp, { recursive: true, force: true });
1032
+ // the INSTALLED core's version (read off node_modules) is held to the same rule
1033
+ const inst = filePinnedHub('1.18.14', 'x', { installed: '1.18.17;touch pwn' });
1034
+ const r2 = resolveWith(inst.cp, '1.18.17;touch pwn');
1035
+ assert.ok(!r2.cmds.some((c) => /pwn/.test(c)), `no command carries the installed label, got: ${r2.cmds.join(' | ')}`);
1036
+ assert.ok(r2.err, 'refused');
1037
+ rmSync(inst.cp, { recursive: true, force: true });
1038
+ });
1039
+
1040
+ t('a file:-pinned hub BEHIND the release gives the new project the release, not its own pin (hub-vs-upstream drift, tasks 1004556 + 1002450)', () => {
1041
+ const { cp, pinned } = filePinnedHub('1.18.14');
1042
+ const cmds = [];
1043
+ const exec = (c) => { cmds.push(c); return { ok: true, stdout: /dist-tags\.latest/.test(c) ? '1.18.17\n' : '' }; };
1044
+ const target = PR.projectCoreTarget({ instanceRoot: cp, coreV: '1.18.14', exec, log: () => {} });
1045
+ assert.deepEqual([target.version, target.source], ['1.18.17', 'released']);
1046
+ const r = P.resolveVendorableCoreTarball({ instanceRoot: cp, exec, log: () => {}, coreV: '1.18.14', target });
1047
+ assert.notEqual(r.tgz, pinned, 'the hub\'s own (older) pin is not vendored');
1048
+ assert.ok(cmds.some((c) => c.startsWith('npm pack @bongos/core@1.18.17 ')), 'the release is packed from the registry');
1049
+ rmSync(cp, { recursive: true, force: true });
1050
+ });
1051
+
1052
+ t('publishing one version twice as different bytes is refused loudly by the publish workflow (the publish half of the build-identity guard, task 1002450)', () => {
1053
+ const wf = readFileSync(new URL('../.github/workflows/publish.yml', import.meta.url), 'utf8');
1054
+ assert.match(wf, /npm publish "\$TGZ"/, 'the workflow publishes to the npm registry, where a version is immutable');
1055
+ assert.match(wf, /cannot publish over\|previously published\|EPUBLISHCONFLICT/, 'it recognises the registry\'s refusal');
1056
+ assert.match(wf, /::error title=version already on the registry/, 'and fails the run loudly on it');
1057
+ });
1058
+
934
1059
  // ── registry-pinned consumer control plane (task 1002706) ─────────────────────────
935
1060
  // After the mothership's registry cutover (task 1002621) its package.json pins
936
1061
  // "@bongos/core": "1.19.x" — NO file: pin — so installedCoreTarball returns null and,
@@ -1001,10 +1126,10 @@ t('resolveVendorableCoreTarball: the ladder picks file: pin → registry pack
1001
1126
  // One helper per rung so the ONLY thing varying between cases is which shape the
1002
1127
  // control-plane root presents. Asserting on the recorded commands is what proves the
1003
1128
  // ORDER: a rung that fires early leaves the later rung's command unrun.
1004
- const run = (instanceRoot, repoRoot) => {
1129
+ const run = (instanceRoot, repoRoot, coreV = '9.9.9') => {
1005
1130
  const cmds = [];
1006
1131
  const res = P.resolveVendorableCoreTarball({
1007
- instanceRoot, repoRoot, exec: (c) => { cmds.push(c); }, log: () => {}, coreV: '9.9.9',
1132
+ instanceRoot, repoRoot, exec: (c) => { cmds.push(c); }, log: () => {}, coreV,
1008
1133
  });
1009
1134
  return { cmds, ...res };
1010
1135
  };
@@ -1017,9 +1142,9 @@ t('resolveVendorableCoreTarball: the ladder picks file: pin → registry pack
1017
1142
  mkdirSync(join(filePinned, 'vendor'));
1018
1143
  writeFileSync(join(filePinned, 'vendor', 'bongos-core-1.2.3.tgz'), 'x');
1019
1144
  writeFileSync(join(filePinned, 'package.json'), JSON.stringify({ dependencies: { '@bongos/core': 'file:vendor/bongos-core-1.2.3.tgz' } }));
1020
- const r1 = run(filePinned, bareRoot);
1145
+ const r1 = run(filePinned, bareRoot, '1.2.3');
1021
1146
  assert.equal(r1.tgz, join(filePinned, 'vendor', 'bongos-core-1.2.3.tgz'));
1022
- assert.deepEqual(r1.cmds, [], 'rung 1 runs no command — it reuses bytes already on disk');
1147
+ assert.ok(r1.cmds.every((c) => c.startsWith('npm view ')), 'rung 1 builds and packs nothing — it reuses bytes already on disk (only the read-only integrity check runs)');
1023
1148
 
1024
1149
  // Rung 2 — a registry-installed core packs, still without touching package-core.js.
1025
1150
  const reg = mkdtempSync(join(tmpdir(), 'rvct-reg-'));