@bongos/core 1.19.58 → 1.19.59

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,11 +2,11 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.58",
6
- "core_contract": "1.19.58",
7
- "source_commit": "138d3a9bbd75c0edac9f89c279e76e9ce9789b0b",
5
+ "core_version": "1.19.59",
6
+ "core_contract": "1.19.59",
7
+ "source_commit": "e93244fafbe4236b1b90218f03c70c92bfd0becb",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-11T23:20:42.316Z",
9
+ "built_at": "2026-08-11T23:37:01.674Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 291,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 1529,
20
- "tree_sha256": "08cfb44880c063d98dfdd34b729592669fd80917f30027532bf691f3f0a2abe4",
20
+ "tree_sha256": "0f793cd7617fce56439932f68de11239e7639d28e50f8d9ee485ba8a602a5f30",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -2577,7 +2577,7 @@
2577
2577
  {
2578
2578
  "path": "modules/dev-box/boxes.js",
2579
2579
  "mode": "0000644",
2580
- "sha256": "acb95d0a5fb535197e949effd0a8720dfaa743a6d86109f10d91505401197c63"
2580
+ "sha256": "fbf9bb7bd4c70ac81627d7d473a94e98e6976581bc29f60c5342d428a39238cf"
2581
2581
  },
2582
2582
  {
2583
2583
  "path": "modules/dev-box/db.js",
@@ -2962,7 +2962,7 @@
2962
2962
  {
2963
2963
  "path": "modules/hall-ui/public/box-panel.js",
2964
2964
  "mode": "0000644",
2965
- "sha256": "271246b55dfd787c338b6f844b96d0032e111b2943d5e12cfaeb9bca3ef75f26"
2965
+ "sha256": "d4b32aa4382100a7e60cc83e83ef23ba34dac0ff759143286b2deaebb8f56cb1"
2966
2966
  },
2967
2967
  {
2968
2968
  "path": "modules/hall-ui/public/brand-apply.js",
@@ -4032,12 +4032,12 @@
4032
4032
  {
4033
4033
  "path": "package-lock.json",
4034
4034
  "mode": "0000644",
4035
- "sha256": "32227d0bece0f036772ed8a6f01a5aee0ea6c47d81b471a3e7cf734aeb24f1ed"
4035
+ "sha256": "f2e15bf06d0e8080e47aeea514dfc26dc267c14a96d32fe805cb240491f0baad"
4036
4036
  },
4037
4037
  {
4038
4038
  "path": "package.json",
4039
4039
  "mode": "0000644",
4040
- "sha256": "b2931ffd8ff5d2fd5d320c3c435e3bc16d59a2757c248529d6160f305216a24d"
4040
+ "sha256": "c3feb3c561c5bf96e9580673b6995835a0d5674f54f96c8b3109fc304e090556"
4041
4041
  },
4042
4042
  {
4043
4043
  "path": "public-docs/index.html",
@@ -5657,7 +5657,7 @@
5657
5657
  {
5658
5658
  "path": "src/module-api.js",
5659
5659
  "mode": "0000644",
5660
- "sha256": "98dd7f963174211b172a2023fe2d13a249362d7471d59ab6eb411424332bee3f"
5660
+ "sha256": "a02eb4c1cfa272d700a9776652612143de38566cd86208f059ed1d0fed24934b"
5661
5661
  },
5662
5662
  {
5663
5663
  "path": "src/module-loader/loader.js",
@@ -5947,7 +5947,7 @@
5947
5947
  {
5948
5948
  "path": "tests/box_code_staleness.mjs",
5949
5949
  "mode": "0000644",
5950
- "sha256": "fc29b6b8be8aa4780486ff33abceceb3a46fc421198a78a09a2a8cf693fd33f1"
5950
+ "sha256": "59d4580504c7352d5f83eec0914f21d0af559b9782bdde1353b5cb3eb2dbb31f"
5951
5951
  },
5952
5952
  {
5953
5953
  "path": "tests/box_connect_e2e.mjs",
@@ -752,8 +752,17 @@ const CODE_STALE_LAG_MS = 2 * 24 * 60 * 60 * 1000; // 2 days behind deployed cod
752
752
  // { stale, reason } where reason ∈
753
753
  // not_active — only active boxes are judged (parked/destroyed → n/a)
754
754
  // awaiting_first_report — active, never reported, still inside provision grace
755
- // never_reported — active, past grace, never reported ⇒ too old to even
756
- // run the reporter (a pre-self-update box) ⇒ STALE
755
+ // never_reported — active, past grace, never reported ⇒ NOT stale. Silence
756
+ // is an unknown, not a verdict: it means the reporter never
757
+ // ran, which is at least as likely to be OUR fault as the
758
+ // box's. It was our fault for the whole life of this feature
759
+ // (task 1002698) — ADR 0072 specified infra/box-report-version.sh
760
+ // and it was never written (task 1002699), so EVERY box in the
761
+ // fleet read as stale, and the banner's only remedy (destroy the
762
+ // box, provision a fresh one) could not possibly clear it. A
763
+ // builder who believed it rebuilt in a loop, losing uncommitted
764
+ // work and spending money each time. Only a box that has ACTUALLY
765
+ // REPORTED can be called stale — see 'behind'.
757
766
  // behind — reported, but its commit is > CODE_STALE_LAG_MS older
758
767
  // than the server's deployed commit ⇒ STALE (a box whose
759
768
  // `pull --ff-only` has been silently failing)
@@ -772,7 +781,9 @@ function computeCodeStaleness({ state, provisionedAt, codeReportedAt, codeCommit
772
781
  const prov = toMs(provisionedAt);
773
782
  const withinGrace = prov != null && (now - prov) < CODE_REPORT_GRACE_MS;
774
783
  if (withinGrace) return { stale: false, reason: 'awaiting_first_report' };
775
- return { stale: true, reason: 'never_reported' };
784
+ // Not stale — see the 'never_reported' note above. The reason is still returned
785
+ // so an operator surface can show "we don't know", which is the honest answer.
786
+ return { stale: false, reason: 'never_reported' };
776
787
  }
777
788
 
778
789
  const boxCommit = toMs(codeCommittedAt);
@@ -183,15 +183,28 @@
183
183
  function renderBoxActive(box, term, cost) {
184
184
  const parts = ['<p class="setup__box-msg setup__box-msg--ok">Your dev box is ready.</p>'];
185
185
 
186
- // idea 332 / task 1316 (ADR 0072): flag a box running old code. A box too
187
- // old to self-update can't be fixed in place — only a rebuild (Close box →
188
- // provision fresh) brings it onto current code. Points at the Close button
189
- // below. The server decides `stale` (boxes.computeCodeStaleness).
186
+ // idea 332 / task 1316 (ADR 0072): flag a box running old code. The server
187
+ // decides `stale` (boxes.computeCodeStaleness), and since task 1002698 it says
188
+ // so ONLY for reason 'behind' — a box that actually reported a commit far
189
+ // behind the deployed one. Silence ('never_reported') is an unknown and no
190
+ // longer flags, so this banner can't fire on a healthy box any more.
191
+ //
192
+ // Lead with the CHEAP, NON-DESTRUCTIVE fix. A 'behind' box is reporting, so its
193
+ // sync cron is alive and a pull usually clears this on its own; closing the box
194
+ // destroys uncommitted work and costs a fresh spin-up. The old copy named the
195
+ // rebuild as the ONLY remedy ("It can't update itself"), which sent builders
196
+ // straight to the destructive option — and while never_reported still flagged,
197
+ // sent them there in a loop it could never resolve.
190
198
  if (box.code && box.code.stale) {
199
+ const days = Number(box.code.lag_ms) > 0
200
+ ? Math.floor(Number(box.code.lag_ms) / 86400000) : 0;
191
201
  parts.push(
192
- '<p class="setup__box-msg setup__box-msg--warn">⚠ This box is running <strong>old code</strong>, '
193
- + 'which can break art generation and reconnecting. It can\'t update itself — '
194
- + 'use <strong>Close box</strong> below, then provision a fresh one to bring it current.</p>'
202
+ '<p class="setup__box-msg setup__box-msg--warn">⚠ This box is running <strong>older code</strong>'
203
+ + (days ? ` (about ${days} day${days === 1 ? '' : 's'} behind)` : '')
204
+ + ', which can break art generation and reconnecting. '
205
+ + 'Run <code>/builder-sync</code> in the terminal to pull the latest — that fixes it in place, '
206
+ + 'and keeps your work. If it is still behind after that, use <strong>Close box</strong> below '
207
+ + 'and provision a fresh one.</p>'
195
208
  );
196
209
  }
197
210
 
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.58",
3
+ "version": "1.19.59",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.58",
9
+ "version": "1.19.59",
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.58",
3
+ "version": "1.19.59",
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
@@ -543,8 +543,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
543
543
  // landed since 1.19.56 with no explicit bump. run 31542659439. (task 1002620)
544
544
  // 1.19.58 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
545
545
  // landed since 1.19.57 with no explicit bump. run 31546064883. (task 1002620)
546
+ // 1.19.59 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
547
+ // landed since 1.19.58 with no explicit bump. run 31547103265. (task 1002620)
546
548
  // ---------------------------------------------------------------------------
547
- const CORE_VERSION = '1.19.58'; // CI auto-patch carrier (ADR 0161); see changelog above
549
+ const CORE_VERSION = '1.19.59'; // CI auto-patch carrier (ADR 0161); see changelog above
548
550
 
549
551
  // A namespaced logger so a module's log lines are attributable + consistent.
550
552
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -42,14 +42,27 @@ t('active + never reported + just provisioned → not stale (awaiting first repo
42
42
  assert.equal(r.reason, 'awaiting_first_report');
43
43
  });
44
44
 
45
- t('active + never reported + past the provision grace → STALE (never_reported, ancient box)', () => {
45
+ t('active + never reported + past the provision grace → NOT stale (never_reported is an unknown, task 1002698)', () => {
46
46
  const r = boxes.computeCodeStaleness({
47
47
  state: 'active', provisionedAt: iso(NOW - 13 * DAY), codeReportedAt: null, now: NOW,
48
48
  });
49
- assert.equal(r.stale, true);
49
+ assert.equal(r.stale, false);
50
50
  assert.equal(r.reason, 'never_reported');
51
51
  });
52
52
 
53
+ // Regression (task 1002698): the whole fleet reported never_reported because the
54
+ // reporter ADR 0072 specified was never written (task 1002699). Silence must never
55
+ // be enough on its own to tell a builder to destroy a working box.
56
+ t('silence alone never flags a box — a report is required to call it stale', () => {
57
+ for (const age of [31 * 60 * 1000, 13 * DAY, 400 * DAY]) {
58
+ const r = boxes.computeCodeStaleness({
59
+ state: 'active', provisionedAt: iso(NOW - age), codeReportedAt: null,
60
+ serverCommittedAt: iso(NOW - HOUR), now: NOW,
61
+ });
62
+ assert.equal(r.stale, false, `age=${age}`);
63
+ }
64
+ });
65
+
53
66
  t('active + reported a commit within the lag window → current', () => {
54
67
  const r = boxes.computeCodeStaleness({
55
68
  state: 'active',