@bongos/core 1.19.398 → 1.19.399

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.398",
6
- "core_contract": "1.19.398",
7
- "source_commit": "d2fe79ca3d995c8416584bc06575b73afeaec45c",
5
+ "core_version": "1.19.399",
6
+ "core_contract": "1.19.399",
7
+ "source_commit": "078d5aba95cdb1b88fa5d41cea74d8f5970f0153",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-28T18:29:17.996Z",
9
+ "built_at": "2026-08-28T18:52:22.972Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 348,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2029,
20
- "tree_sha256": "034d29b37b3208023040c5ded6d355c32bba38f3e57ced2a770e893f8d1928ff",
20
+ "tree_sha256": "db3d8330b945cae451854b1aa6971c725a064644793114830480a32bc0c7ccc3",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -5307,12 +5307,12 @@
5307
5307
  {
5308
5308
  "path": "package-lock.json",
5309
5309
  "mode": "0000644",
5310
- "sha256": "13f7c20f7d01157842d006764090fabd60536d20e4dee048243f04851ece16c8"
5310
+ "sha256": "e036f768512bfbfbc2851b076a12e6185b7e9d02b9a919a8b0c5bd32dc94e246"
5311
5311
  },
5312
5312
  {
5313
5313
  "path": "package.json",
5314
5314
  "mode": "0000644",
5315
- "sha256": "f45044af3ba97b0e1b923e179ea75e8186280f21bb0168cefd7489a133a137c0"
5315
+ "sha256": "25cb1fa5145932470a12a6cee77b1515feed2ceb24d3c3418028efd08ea2f37e"
5316
5316
  },
5317
5317
  {
5318
5318
  "path": "public-docs/index.html",
@@ -5662,7 +5662,7 @@
5662
5662
  {
5663
5663
  "path": "public-landing/projects.html",
5664
5664
  "mode": "0000644",
5665
- "sha256": "1e1867918ec2a8fe489d9d21aa2e50fada9950b220c865c57f23c703a6c29f24"
5665
+ "sha256": "55f3cc6b922e355cdb910b99487dfda61eb78c0d6f682de5ed3c534d0dfb7e65"
5666
5666
  },
5667
5667
  {
5668
5668
  "path": "public-landing/projects.probes.json",
@@ -7327,7 +7327,7 @@
7327
7327
  {
7328
7328
  "path": "src/module-api.js",
7329
7329
  "mode": "0000644",
7330
- "sha256": "ecd70bbc85834d5014b2062dd73436d56124aa399c12f9f4f0fc0f5e5f25a594"
7330
+ "sha256": "939ace4177533bab1902bf03a387547efef875752d69f1050610b46606bc8d2f"
7331
7331
  },
7332
7332
  {
7333
7333
  "path": "src/module-loader/catalog.js",
@@ -9342,7 +9342,7 @@
9342
9342
  {
9343
9343
  "path": "tests/projects_hub_pre_uat.mjs",
9344
9344
  "mode": "0000644",
9345
- "sha256": "3104082c86aabc56824a026eccf028c9971bfbffc5a2c7801accbe1c899cba0c"
9345
+ "sha256": "0b3f5b5cd293f0b6805df75e7b3f43e4e453718cc83e66297e3a4a693a27f36c"
9346
9346
  },
9347
9347
  {
9348
9348
  "path": "tests/promote_goal_id.mjs",
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.398",
3
+ "version": "1.19.399",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.398",
9
+ "version": "1.19.399",
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.398",
3
+ "version": "1.19.399",
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",
@@ -1086,6 +1086,10 @@ summary{min-height:24px;padding:3px 0;}
1086
1086
  (direction §3 — an active card must be able to
1087
1087
  self-correct, so the list re-reads once a minute) */
1088
1088
  var FRESH_MS = 12 * 60 * 1000; /* "checked Xm ago" freshness ≈ 2 heartbeat sweeps */
1089
+ /* how long the card keeps showing the moment a standup LANDED (task 1003243).
1090
+ Shorter than FRESH_MS on purpose: "live" is a standing fact the chip carries
1091
+ forever, while "it just came up" is an event that stops being news. */
1092
+ var LIVE_MOMENT_MS = 5 * 60 * 1000;
1089
1093
 
1090
1094
  var b = (typeof window !== 'undefined' && window.__BRANDING__) || {};
1091
1095
  var productName = (b.identity && b.identity.productName) || 'Cloud Bongos';
@@ -3950,6 +3954,20 @@ summary{min-height:24px;padding:3px 0;}
3950
3954
  so the page can never say "Answering at …" beside a chip that says "live?". */
3951
3955
  function verifiedAt(inst) { return inst.last_verified_at ? new Date(inst.last_verified_at).getTime() : 0; }
3952
3956
  function freshUp(inst) { var at = verifiedAt(inst); return !!(inst.last_verified_up && at && (Date.now() - at) <= FRESH_MS); }
3957
+ /* the landing moment (task 1003243): a standup or revive that VERIFIABLY came
3958
+ up, still recent enough to be news. Two gates, both already on the card —
3959
+ freshUp() so "live" stays ONE rule (a lit third stage beside a "live?" chip
3960
+ would be the exact contradiction direction §3 forbids), and provisioned_at,
3961
+ which the runner re-stamps every time it flips an instance to active, so a
3962
+ revive earns the moment too. No sticky per-card flag is invented: the whole
3963
+ window is derived from data the card already holds, which is why a reload
3964
+ mid-window still shows it and a long-live project never does. */
3965
+ function provisionedAt(inst) { return inst.provisioned_at ? new Date(inst.provisioned_at).getTime() : 0; }
3966
+ function justLive(inst) {
3967
+ var at = provisionedAt(inst);
3968
+ return inst.status === 'active' && !inst.open_intent && freshUp(inst) &&
3969
+ !!at && (Date.now() - at) <= LIVE_MOMENT_MS;
3970
+ }
3953
3971
 
3954
3972
  function chipMarkup(cls, label, rec) {
3955
3973
  return '<span class="chip ' + cls + '"><span class="cdot"></span>' + esc(label) +
@@ -4037,9 +4055,9 @@ summary{min-height:24px;padding:3px 0;}
4037
4055
  address: { names: ['Address queued', 'Wiring the address', 'Answering there'], cls: '' },
4038
4056
  settings: { names: ['Change saved', 'Restarting to apply it', 'Applied'], cls: '' }
4039
4057
  };
4040
- function stripMarkup(flow, stageNow, stagesDone, note) {
4058
+ function stripMarkup(flow, stageNow, stagesDone, note, extraCls) {
4041
4059
  var f = FLOWS[flow];
4042
- return '<div class="strip ' + f.cls + '" role="status" aria-live="polite">' +
4060
+ return '<div class="strip ' + f.cls + (extraCls ? ' ' + extraCls : '') + '" role="status" aria-live="polite">' +
4043
4061
  '<ul class="stages">' + f.names.map(function (n, i) {
4044
4062
  var c = stagesDone > i ? 'done' : (stageNow === i ? 'now' : '');
4045
4063
  return '<li class="' + c + '"><span class="sdot"></span><span class="slbl">' + n + '</span></li>';
@@ -4075,6 +4093,17 @@ summary{min-height:24px;padding:3px 0;}
4075
4093
  if (a === 'provision') return stripMarkup(s === 'torn_down' ? 'revive' : 'standup', 0, 0, (s === 'torn_down' ? 'A revive is queued' : 'A standup is queued') + ' — this card updates when it starts.');
4076
4094
  return stripMarkup('standup', 2, 2, 'A ' + esc(a) + ' run is queued — this card updates when it lands.');
4077
4095
  }
4096
+ /* the moment it landed (task 1003243). Until now this fell straight through to
4097
+ '' — stages 1 and 2 lit while the work ran, then the strip vanished, so the
4098
+ founder watching their own card never saw the third stage the wizard's done
4099
+ panel shows them. stagesDone=3 lights all three; stageNow=-1 because nothing
4100
+ is in progress any more. The address row carries the address, so this line
4101
+ says the EVENT and does not repeat it. */
4102
+ if (justLive(inst)) {
4103
+ return stripMarkup(revive ? 'revive' : 'standup', -1, 3,
4104
+ revive ? 'It’s back — your project is answering again.' : 'Standing up finished — your project is answering.',
4105
+ 'isLive');
4106
+ }
4078
4107
  return '';
4079
4108
  }
4080
4109
 
@@ -4340,7 +4369,11 @@ summary{min-height:24px;padding:3px 0;}
4340
4369
  var at = inst.last_verified_at ? new Date(inst.last_verified_at).getTime() : 0;
4341
4370
  return JSON.stringify([inst.status, inst.domain, inst.error_note,
4342
4371
  inst.open_intent && inst.open_intent.action, inst.open_intent && inst.open_intent.state,
4343
- inst.last_verified_up, at ? Math.floor((Date.now() - at) / 60000) : -1]);
4372
+ inst.last_verified_up, at ? Math.floor((Date.now() - at) / 60000) : -1,
4373
+ /* the landing moment is time-boxed (task 1003243), so its own age is part of
4374
+ what the card renders from — otherwise a stalled heartbeat freezes
4375
+ last_verified_at's bucket and the moment never clears itself */
4376
+ justLive(inst)]);
4344
4377
  }
4345
4378
  function takeUpdate(id, inst) {
4346
4379
  var prev = byId[id];
package/src/module-api.js CHANGED
@@ -1236,8 +1236,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
1236
1236
  // landed since 1.19.396 with no explicit bump. run 33193365480. (task 1002620)
1237
1237
  // 1.19.398 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1238
1238
  // landed since 1.19.397 with no explicit bump. run 33199474439. (task 1002620)
1239
+ // 1.19.399 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1240
+ // landed since 1.19.398 with no explicit bump. run 33201243958. (task 1002620)
1239
1241
  // ---------------------------------------------------------------------------
1240
- const CORE_VERSION = '1.19.398'; // CI auto-patch carrier (ADR 0161); see changelog above
1242
+ const CORE_VERSION = '1.19.399'; // CI auto-patch carrier (ADR 0161); see changelog above
1241
1243
 
1242
1244
  // A namespaced logger so a module's log lines are attributable + consistent.
1243
1245
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -54,6 +54,43 @@ test('addressRow branches by state before it trusts the domain — torn down and
54
54
  assert.match(body, /We keep checking every few minutes/, 'an unreachable project says what the platform is doing');
55
55
  });
56
56
 
57
+ /* ── the moment a standup lands (task 1003243) ── */
58
+ test('the landed moment is earned by a VERIFIED probe inside a window, not invented state', () => {
59
+ const body = fn('justLive');
60
+ assert.match(body, /freshUp\(inst\)/, '"live" stays ONE rule — a lit third stage beside a "live?" chip is the contradiction §3 forbids');
61
+ assert.match(body, /LIVE_MOMENT_MS/, 'and it is time-boxed');
62
+ assert.match(body, /inst\.status === 'active'/);
63
+ assert.match(body, /!inst\.open_intent/, 'work in flight tells its own story');
64
+ assert.match(SCRIPT, /var LIVE_MOMENT_MS = [\s\S]{0,40}?;/, 'the window is a named constant');
65
+ // derived from data the card already holds — a sticky per-card flag would not
66
+ // survive a reload, and would keep claiming the moment after the project died
67
+ assert.match(fn('provisionedAt'), /inst\.provisioned_at/, 'the runner re-stamps this on every standup, so a revive earns it too');
68
+ assert.doesNotMatch(body, /localStorage|sessionStorage|sawLive|_seen/, 'no invented client-side state');
69
+ });
70
+
71
+ test('the landed moment lights all three stages green — and only stripFor may do it', () => {
72
+ const body = fn('stripFor');
73
+ assert.match(body, /justLive\(inst\)/, 'the active fallthrough is no longer a bare return');
74
+ assert.match(body, /stripMarkup\(revive \? 'revive' : 'standup', -1, 3,[\s\S]*?'isLive'\)/,
75
+ 'all three done (stagesDone=3), nothing in progress (stageNow=-1), painted in the landed palette');
76
+ // the strip must still vanish once the moment passes — a permanent progress
77
+ // strip on a long-live project is exactly what the pre-UAT review flagged
78
+ assert.match(body, /\n return '';\n \}/, "the fallthrough still ends at ''");
79
+ assert.match(SCRIPT, /function stripMarkup\(flow, stageNow, stagesDone, note, extraCls\)/, 'one markup fn, not a second copy');
80
+ });
81
+
82
+ test('the landed note says the EVENT — the address row already carries the address', () => {
83
+ const body = fn('stripFor');
84
+ assert.match(body, /Standing up finished — your project is answering\./, 'a first standup');
85
+ assert.match(body, /It’s back — your project is answering again\./, 'and a revive says the right thing');
86
+ assert.doesNotMatch(body, /justLive[\s\S]{0,400}?esc\(inst\.domain\)/, 'the note does not repeat the domain');
87
+ });
88
+
89
+ test('the moment clears itself even if the heartbeat stalls — sig() renders from its own age', () => {
90
+ assert.match(fn('sig'), /justLive\(inst\)/,
91
+ "last_verified_at's per-minute bucket stops moving when the sweep stalls; without this the strip would freeze on screen");
92
+ });
93
+
57
94
  test('"live" is ONE rule — chip, orb and address row all read freshUp()', () => {
58
95
  assert.match(SCRIPT, /function freshUp\(inst\)/);
59
96
  assert.match(fn('chipFor'), /freshUp\(inst\)/, 'the chip');