@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 +10 -10
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/projects.html +36 -3
- package/src/module-api.js +3 -1
- package/tests/projects_hub_pre_uat.mjs +37 -0
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
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:
|
|
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": "
|
|
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": "
|
|
5310
|
+
"sha256": "e036f768512bfbfbc2851b076a12e6185b7e9d02b9a919a8b0c5bd32dc94e246"
|
|
5311
5311
|
},
|
|
5312
5312
|
{
|
|
5313
5313
|
"path": "package.json",
|
|
5314
5314
|
"mode": "0000644",
|
|
5315
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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');
|