@bongos/core 1.19.335 → 1.19.337

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,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.335",
6
- "core_contract": "1.19.335",
7
- "source_commit": "b5f2b884a9011be30bffe5bbd62c272a7497314a",
5
+ "core_version": "1.19.337",
6
+ "core_contract": "1.19.337",
7
+ "source_commit": "a1079dd09b8ae45b780cdcab81eb44696be21f01",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-25T00:51:04.860Z",
9
+ "built_at": "2026-08-25T01:01:18.995Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 325,
13
13
  "agent_docs_stubbed": 22,
14
- "functional_verbatim": 1490,
14
+ "functional_verbatim": 1483,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 1837,
20
- "tree_sha256": "9792847e3608bc598acfe751efe68d1e8cbb5b0ab10a19490cf2f325db36a44c",
19
+ "file_count": 1830,
20
+ "tree_sha256": "39cc259330321323f293c3d933377998d7c3cf229570269ccbf77fa1bef52857",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -287,7 +287,7 @@
287
287
  {
288
288
  "path": ".devcontainer/post-create.sh",
289
289
  "mode": "0000644",
290
- "sha256": "db5db43fc7a692008eb1f70c6bec4345d6812939e9f09b302e2692621bbaece9"
290
+ "sha256": "69aef5fb55abc1bcd7c5f437df9bf7a38459eb52e1e4cc687b81d801f9c911ab"
291
291
  },
292
292
  {
293
293
  "path": ".dockerignore",
@@ -472,12 +472,12 @@
472
472
  {
473
473
  "path": "docs/adr/0011-terrain-id-rendering-model.md",
474
474
  "mode": "0000644",
475
- "sha256": "68e9189dd2d99428b599d02011f8c88649151e9acaf9d8912c98b231eed4507e"
475
+ "sha256": "b3c9291fda6fd5e19601a9b79a97359682d26bb316b357f28db12dbb281d79cf"
476
476
  },
477
477
  {
478
478
  "path": "docs/adr/0012-ground-object-cell-split.md",
479
479
  "mode": "0000644",
480
- "sha256": "bb26e441c48117377bbd451ea679a864bd58d5ac3a3a775cf20bc7219e5090e1"
480
+ "sha256": "a724bcd8c583d7f53515809da27202a7e512bad7862a8f77c8d8bd07c001792d"
481
481
  },
482
482
  {
483
483
  "path": "docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md",
@@ -2987,7 +2987,7 @@
2987
2987
  {
2988
2988
  "path": "modules/economy/achievements.js",
2989
2989
  "mode": "0000644",
2990
- "sha256": "387c37df8b65bab755e8f006722e6665d9e5aafea29eabf868d1e2dfc4720e99"
2990
+ "sha256": "fc270efbe9439442d2f51490a8a292313e3f66c7b5d33c28cd9e7f929f56b307"
2991
2991
  },
2992
2992
  {
2993
2993
  "path": "modules/economy/cost-classify.js",
@@ -3007,7 +3007,7 @@
3007
3007
  {
3008
3008
  "path": "modules/economy/credits.js",
3009
3009
  "mode": "0000644",
3010
- "sha256": "7c42fc848a1b7139d7ffa59cc3d81d89db84329b7beae9d5b8c5bc0afefc6f41"
3010
+ "sha256": "a3d9d82cb5f19fdb8520c4df74022219886c767ae626dccf27728e07bf6d36f2"
3011
3011
  },
3012
3012
  {
3013
3013
  "path": "modules/economy/migrations/economy_001_fix_gds_shipper_description.sql",
@@ -3019,6 +3019,11 @@
3019
3019
  "mode": "0000644",
3020
3020
  "sha256": "b8b3a4add551b32bc625dca0390afc2176dcd9e433b24d21128dd6e249e70623"
3021
3021
  },
3022
+ {
3023
+ "path": "modules/economy/policy.js",
3024
+ "mode": "0000644",
3025
+ "sha256": "cc953acd69f844d158c3a79ea4de3b12d652ea0247c878c6a6c33d5abf68eab3"
3026
+ },
3022
3027
  {
3023
3028
  "path": "modules/economy/reward.js",
3024
3029
  "mode": "0000644",
@@ -4422,7 +4427,7 @@
4422
4427
  {
4423
4428
  "path": "modules/provisioning/routes/provisioning.js",
4424
4429
  "mode": "0000644",
4425
- "sha256": "8bd43d1101599f5ff838641a9cbaa9bfd208eea4a3c7876f45ac034a8bf3b5d0"
4430
+ "sha256": "b9762b6b76d4ee7f57a3a8c37f126eb768ff8c90e194a575dddc7704a534062d"
4426
4431
  },
4427
4432
  {
4428
4433
  "path": "modules/provisioning/tests/liveness.mjs",
@@ -4722,12 +4727,12 @@
4722
4727
  {
4723
4728
  "path": "package-lock.json",
4724
4729
  "mode": "0000644",
4725
- "sha256": "c3a2cfd45a78396f4f7186492cf625a2351f4dfd78c0d82dbffc4217db97a68d"
4730
+ "sha256": "6e1f14fea8a5dac393261b47a9563eabca0bda30f2c9a6d56f22e17f548c42aa"
4726
4731
  },
4727
4732
  {
4728
4733
  "path": "package.json",
4729
4734
  "mode": "0000644",
4730
- "sha256": "9896b1417474da8bf8b09e8dd188455d6d75b5e95602c7409a81ea17ee6e4cc3"
4735
+ "sha256": "b3c8163bb92a02b01ca2ec14a46b8b1b3c25f1e6ae25001b0fea4a2303820713"
4731
4736
  },
4732
4737
  {
4733
4738
  "path": "public-docs/index.html",
@@ -5377,7 +5382,7 @@
5377
5382
  {
5378
5383
  "path": "scripts/gds/fitness-checks-identity.js",
5379
5384
  "mode": "0000644",
5380
- "sha256": "5d731cf4703ca47be3dfd272f4bc74f6f49471f6b027474285cca4221fac47d5"
5385
+ "sha256": "f87265779d60ae2d642e370f7af2d1d70fa6a1354a7389835d887b0dfe3c5dfc"
5381
5386
  },
5382
5387
  {
5383
5388
  "path": "scripts/gds/fitness-checks-vocabulary.js",
@@ -5397,7 +5402,7 @@
5397
5402
  {
5398
5403
  "path": "scripts/gds/fitness-ratchets.js",
5399
5404
  "mode": "0000644",
5400
- "sha256": "3f32080357abdecb0f0860c5c9313f12283f01774c8367ac22c1c12d0d176411"
5405
+ "sha256": "1732691382d3ec82f4f59b44250fce6367179a44283395dc92c78cfd67493ed2"
5401
5406
  },
5402
5407
  {
5403
5408
  "path": "scripts/gds/fitness.js",
@@ -5802,7 +5807,7 @@
5802
5807
  {
5803
5808
  "path": "scripts/gds/run-unit-tests.js",
5804
5809
  "mode": "0000644",
5805
- "sha256": "c96e50e533f4e20dba91c6a26ac6efd2c6ad33ffcdc856eeb46af21a17e67975"
5810
+ "sha256": "b3d816af249491e6187676ad084a60aaa72881615f8824a0263c31505d57a149"
5806
5811
  },
5807
5812
  {
5808
5813
  "path": "scripts/gds/sandbox-stage.js",
@@ -5949,11 +5954,6 @@
5949
5954
  "mode": "0000644",
5950
5955
  "sha256": "14825fa0500e600efcc518e7120dd4b64fdae9235509e7a39d3865f179754f5f"
5951
5956
  },
5952
- {
5953
- "path": "scripts/gds/seed-v3-tasks.js",
5954
- "mode": "0000644",
5955
- "sha256": "a0d8c1530cfc80f5604fb4d520d131daa2a9001f0a28f5e184dd0386034af6e0"
5956
- },
5957
5957
  {
5958
5958
  "path": "scripts/gds/sequence.js",
5959
5959
  "mode": "0000644",
@@ -6239,26 +6239,6 @@
6239
6239
  "mode": "0000644",
6240
6240
  "sha256": "5860bf9daef3dd83a5ff4d3ee5e017e3cbd465ebda0c00df4ca622d629468ec4"
6241
6241
  },
6242
- {
6243
- "path": "scripts/snapshots/backfill-history.mjs",
6244
- "mode": "0000644",
6245
- "sha256": "536c5dce00bb8fc04d895396dfe593cfef1317c6d5666d76a0e0586f08f08987"
6246
- },
6247
- {
6248
- "path": "scripts/snapshots/maybe-render-on-deploy.sh",
6249
- "mode": "0000644",
6250
- "sha256": "e8392d7dc47f583c75acdf87bdd8ba9cae19fd348dd8f559802955690938545d"
6251
- },
6252
- {
6253
- "path": "scripts/snapshots/render-pre-art-eras.mjs",
6254
- "mode": "0000644",
6255
- "sha256": "a5e5498067075212e7a38eda2faf1d4cdf5f98421a71bed85e46a2c0f9dc882c"
6256
- },
6257
- {
6258
- "path": "scripts/snapshots/render-world.mjs",
6259
- "mode": "0000644",
6260
- "sha256": "deb5f6169f53771bc119cdbaa3164112b8cf480b49c1adf0d65914b7c96ee84f"
6261
- },
6262
6242
  {
6263
6243
  "path": "scripts/status-mirror-sync.js",
6264
6244
  "mode": "0000644",
@@ -6577,7 +6557,7 @@
6577
6557
  {
6578
6558
  "path": "src/module-api.js",
6579
6559
  "mode": "0000644",
6580
- "sha256": "490504c9d10309b811026a035d5999360cbe00b8eb912bb8c4d0873c8271cff2"
6560
+ "sha256": "8ffe1c3c3683e95f182da6cad74272574cbe1a2d94a9b959221cc71084c1b8d3"
6581
6561
  },
6582
6562
  {
6583
6563
  "path": "src/module-loader/catalog.js",
@@ -6654,11 +6634,6 @@
6654
6634
  "mode": "0000644",
6655
6635
  "sha256": "125edcec8c7d7536365b9675daa1fceb9fe072a30e2a4a68ee2911cd258a8c10"
6656
6636
  },
6657
- {
6658
- "path": "tests/anti_grid.mjs",
6659
- "mode": "0000644",
6660
- "sha256": "2d78ef9e446efa0aa66e716b362d72432024773b28d94f5768bcbaaf79c99dad"
6661
- },
6662
6637
  {
6663
6638
  "path": "tests/api_cli_flags.mjs",
6664
6639
  "mode": "0000644",
@@ -6824,16 +6799,6 @@
6824
6799
  "mode": "0000644",
6825
6800
  "sha256": "034114a63f2d8a431755f6cf35a7e66b1cbb3b7931bb251e3a8f235ff5057e29"
6826
6801
  },
6827
- {
6828
- "path": "tests/autotile_variants.mjs",
6829
- "mode": "0000644",
6830
- "sha256": "0cd3167548071272f13a3072a87d6071c46540a1fc0f810ca4584ac3f93693f6"
6831
- },
6832
- {
6833
- "path": "tests/autotile_xverify.mjs",
6834
- "mode": "0000644",
6835
- "sha256": "4986f25a93ef89f0312eeb1f4ff32cd82e2f8e7bcc9749143443537e734d5193"
6836
- },
6837
6802
  {
6838
6803
  "path": "tests/backfill_sessions.mjs",
6839
6804
  "mode": "0000644",
@@ -8492,7 +8457,7 @@
8492
8457
  {
8493
8458
  "path": "tests/provisioning_github_app_routes.mjs",
8494
8459
  "mode": "0000644",
8495
- "sha256": "fce4837d4882dcd980bc144a2afeaf04fbce99aa31d7d1a72a277bad0ebfae99"
8460
+ "sha256": "dd53361cf8bd7e517e886701753d64c05c3235995785991558805f493cde529c"
8496
8461
  },
8497
8462
  {
8498
8463
  "path": "tests/provisioning_onboard_mode.mjs",
@@ -8712,7 +8677,7 @@
8712
8677
  {
8713
8678
  "path": "tests/search_isolation.mjs",
8714
8679
  "mode": "0000644",
8715
- "sha256": "4832744832280a72cc84b8c4b7a4b836612fbec733972bedaa1810124a90de8b"
8680
+ "sha256": "21a352003eac3ef3975aecf758163bd90fb58c34daef643055b2423ea2ffdc17"
8716
8681
  },
8717
8682
  {
8718
8683
  "path": "tests/search_route.mjs",
@@ -102,13 +102,9 @@ echo
102
102
 
103
103
  # --- 3. Full-stack verification -----------------------------------------------
104
104
  say "4/4 Verifying the box is ready"
105
- # sharp: the native image dep — proves npm ci produced a working binary on this
106
- # arch (x64 or arm64).
107
- if node -e "require('sharp'); console.log('sharp', require('sharp/package.json').version)" >/dev/null 2>&1; then
108
- echo " ${green}ok${reset} sharp loads ($(node -e "console.log(require('sharp/package.json').version)" 2>/dev/null))"
109
- else
110
- echo " ${yellow}!!${reset} sharp failed to load — the game/art build will break"
111
- fi
105
+ # sharp was verified here as "the native image dep". Task 1003207 removed it: its
106
+ # only consumers were the game-era snapshot renderers and an art-pipeline test,
107
+ # all of which left this core with the game. Nothing native remains to prove.
112
108
  # The five art libs must import in the venv.
113
109
  if python3 -c "import PIL, numpy, scipy, sklearn, certifi" >/dev/null 2>&1; then
114
110
  echo " ${green}ok${reset} art libs import (Pillow, numpy, scipy, scikit-learn, certifi)"
@@ -94,7 +94,8 @@ chooses the foam variant at the boundary. One less hand-tuned terrain
94
94
  in the map.
95
95
 
96
96
  A Python↔JS cross-verification smoke test
97
- ([`tests/autotile_xverify.mjs`](../../tests/autotile_xverify.mjs) plus
97
+ (`tests/autotile_xverify.mjs` — deleted by task 1003207 with the rest of the
98
+ game-era art pipeline; named here as the historical record, not a live file — plus
98
99
  its emitter [`art/pipeline/autotile_xverify.py`](../../art/pipeline/autotile_xverify.py))
99
100
  asserts that all 256 blob47 inputs and all 16 path16 inputs map to the
100
101
  same tile index in both implementations. Wired into
@@ -113,7 +113,8 @@ server module directly to guard against drift.
113
113
  ### Cross-verify safety
114
114
 
115
115
  The Python↔JS autotile lookup table cross-verifier
116
- ([`tests/autotile_xverify.mjs`](../../tests/autotile_xverify.mjs))
116
+ (`tests/autotile_xverify.mjs`, deleted by task 1003207 with the game-era art
117
+ pipeline — named here as the historical record, not a live file)
117
118
  tests `selectBlob47` / `selectPath16` directly — unchanged by this
118
119
  ADR. Picker behavior change is captured in the new
119
120
  [`tests/terrain_picker.mjs`](../../tests/terrain_picker.mjs), which
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const { SUBTRACTOR_THRESHOLD } = require('./policy');
4
+
3
5
  // Achievement evaluation — runs inside existing DB transactions so unlocks
4
6
  // are atomic with the action that triggered them.
5
7
  //
@@ -318,10 +320,9 @@ async function eligible_breaking100c(client, builderId) {
318
320
 
319
321
  async function eligible_subtractor(client, builderId) {
320
322
  // Mirror credits.awardNetNegativeBonus: subtractor unlocks at SUBTRACTOR_THRESHOLD
321
- // net-negative ship bonuses. Lazy-require the threshold (credits.js requires
322
- // this module, so a top-level require would be circular — same lazy pattern
323
- // renderProgressText uses for ./streak).
324
- const { SUBTRACTOR_THRESHOLD } = require('./credits');
323
+ // net-negative ship bonuses. The threshold used to be lazy-required from
324
+ // credits.js to dodge a circular import; task 1003207 moved it to ./policy.js,
325
+ // which both files read, so the cycle is gone rather than deferred.
325
326
  const r = await client.query(
326
327
  `SELECT COUNT(*)::int AS n FROM credit_log
327
328
  WHERE builder_id = $1 AND reason = 'ship.net_negative'`,
@@ -712,7 +712,9 @@ async function awardSessionTokenReward(client, builderId, sessionId, modelUsage,
712
712
  // ship's bonus row is inserted — and that insert lives here. Doing the unlock
713
713
  // inline keeps the read-then-unlock atomic with the insert in one transaction.
714
714
  const NET_NEGATIVE_BONUS = 1;
715
- const SUBTRACTOR_THRESHOLD = 3; // net-negative ships needed to unlock Subtractor
715
+ // task 1003207: moved to ./policy.js so achievements.js can read it without a
716
+ // lazy require back into this file (that circularity was a tracked cycle).
717
+ const { SUBTRACTOR_THRESHOLD } = require('./policy');
716
718
  function netNegativeBonusAmount(diffStats) {
717
719
  if (!diffStats) return 0;
718
720
  const added = Number(diffStats.lines_added) || 0;
@@ -0,0 +1,22 @@
1
+ // modules/economy/policy.js — economy policy constants that BOTH the credit
2
+ // writers and the achievement predicates need.
3
+ //
4
+ // Extracted by task 1003207 (goal 1000079) to break a genuine require cycle:
5
+ // credits.js requires achievements.js at load, and achievements.js needed
6
+ // SUBTRACTOR_THRESHOLD back from credits.js. The workaround was a lazy
7
+ // require() inside the function body, with a comment explaining the circularity
8
+ // — a cycle papered over rather than removed, and one of the five the
9
+ // require_cycle_count ratchet was holding.
10
+ //
11
+ // A shared constant is the honest seam: the threshold is neither a credit-writing
12
+ // concern nor an achievement concern, it is the POLICY both read. credits.js
13
+ // still re-exports it, so no caller outside this module changed.
14
+
15
+ 'use strict';
16
+
17
+ // Net-negative ships needed to unlock Subtractor. Read by credits.js when it
18
+ // awards the bonus, and by achievements.js when it decides the badge is earned —
19
+ // the two must agree, which is why it lives in one place.
20
+ const SUBTRACTOR_THRESHOLD = 3;
21
+
22
+ module.exports = { SUBTRACTOR_THRESHOLD };
@@ -144,7 +144,9 @@ code{font-family:"Fira Code",ui-monospace,SFMono-Regular,monospace;background:rg
144
144
  // land. Deliberately contains NO backticks and NO ${...} so it survives the outer
145
145
  // template literal verbatim; the only server data it reads is the JSON config block
146
146
  // written just above it. Fails soft — a poll hiccup just retries; a long wait reveals a
147
- // manual "open" button rather than ever falsely erroring.
147
+ // manual "open" button rather than ever falsely erroring. The auto-open countdown runs
148
+ // ONLY when this page is the wizard's pop-up; a same-tab return (pop-up blocked) keeps
149
+ // the founder here with the door and a way back to the checklist (task 1003236).
148
150
  const CALLBACK_SCRIPT = `
149
151
  (function(){
150
152
  var cfg=window.__CB_SETUP__||{};
@@ -153,12 +155,18 @@ const CALLBACK_SCRIPT = `
153
155
  var target='https://'+domain;
154
156
  var pollUrl=location.pathname.replace('/callback','/status')+'?state='+encodeURIComponent(state);
155
157
  var steps=document.getElementById('steps'),statusEl=document.getElementById('status');
156
- var cta=document.getElementById('cta'),go=document.getElementById('go'),foot=document.getElementById('foot');
158
+ var cta=document.getElementById('cta'),go=document.getElementById('go'),foot=document.getElementById('foot'),back=document.getElementById('back');
159
+ /* Opened from the wizard as a pop-up (window.opener alive, or the tab still carries the name the wizard gave it):
160
+ the checklist is in the other tab, so this one may auto-open the instance. Same-tab fallback (pop-up blocked,
161
+ form target=_self): this IS the founder's checklist tab — never navigate it away; offer both doors (task 1003236). */
162
+ var popup=!!window.opener||window.name==='ghAppSetup';
157
163
  var finished=false,tries=0,manual=false;
158
164
  function dot(n){return steps.querySelector('[data-step="'+n+'"]');}
159
165
  function setActive(n){for(var i=1;i<=3;i++){var el=dot(i);if(!el)continue;el.classList.remove('active','done');if(i<n){el.classList.add('done');el.querySelector('.dot').textContent='\\u2713';}else if(i===n){el.classList.add('active');}}}
160
166
  function allDone(){for(var i=1;i<=3;i++){var el=dot(i);if(!el)continue;el.classList.remove('active');el.classList.add('done');el.querySelector('.dot').textContent='\\u2713';}}
161
- function ready(){if(finished)return;finished=true;allDone();statusEl.textContent='Your instance is ready \\u2014 sign in with GitHub to claim it as owner.';cta.classList.remove('hidden');var n=4;(function tick(){if(n<=0){location.href=target;return;}go.textContent='Opening '+domain+' in '+n+'\\u2026';n--;setTimeout(tick,1000);})();}
167
+ function ready(){if(finished)return;finished=true;allDone();statusEl.textContent='Your instance is ready \\u2014 sign in with GitHub to claim it as owner.';cta.classList.remove('hidden');
168
+ if(!popup){go.textContent='Open '+domain+' \\u2192';if(back)back.classList.remove('hidden');if(foot)foot.textContent='Your setup checklist is waiting where you left it \\u2014 finish it first, or open your instance now.';return;}
169
+ var n=4;(function tick(){if(n<=0){location.href=target;return;}go.textContent='Opening '+domain+' in '+n+'\\u2026';n--;setTimeout(tick,1000);})();}
162
170
  function failed(){if(finished)return;finished=true;statusEl.textContent='Setup didn\\u2019t finish. Open your instance page and start the GitHub sign-in setup again.';cta.classList.remove('hidden');go.textContent='Open '+domain+' \\u2192';}
163
171
  function revealManual(){if(manual||finished)return;manual=true;cta.classList.remove('hidden');go.textContent='Open '+domain+' \\u2192';if(foot)foot.textContent='This is taking a little longer than usual \\u2014 you can open your instance now, or keep waiting.';}
164
172
  function schedule(){if(!finished)setTimeout(poll,3000);}
@@ -195,6 +203,7 @@ function callbackPage({ ok, title, body, state, domain }) {
195
203
  </div>
196
204
  <p class="status-line" id="status">Hang tight — keep this tab open while we finish.</p>
197
205
  <div class="cta hidden" id="cta"><a class="btn" id="go" href="https://${esc(domain)}">Open ${esc(domain)} →</a></div>
206
+ <p class="muted hidden" id="back"><a href="/projects?view=new">Finish your remaining setup steps →</a></p>
198
207
  <p class="muted" id="foot">This page opens <code>${esc(domain)}</code> for you the moment it’s ready.</p>
199
208
  <noscript><p class="muted">When setup finishes, open <a href="https://${esc(domain)}">${esc(domain)}</a> and sign in with GitHub — that first sign-in makes you the owner.</p></noscript>
200
209
  </main>
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.335",
3
+ "version": "1.19.337",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.335",
9
+ "version": "1.19.337",
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.335",
3
+ "version": "1.19.337",
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",
@@ -101,7 +101,6 @@ const IDENTITY_SCAN_ALLOWED = {
101
101
  // when the monolith was split, so the detector's self-carve-out moved with them.
102
102
  'scripts/gds/fitness-checks-identity.js': 2,
103
103
  'scripts/gds/package-core.js': 1,
104
- 'scripts/gds/seed-v3-tasks.js': 14,
105
104
  // audit-replay.sh + db-backup-{nightly,offsite}.sh were carved out here as
106
105
  // "host-pinned ops"; task 1002757 RETIRED that justification for them — each
107
106
  // now resolves its database from the branding pack (the migrate.sh pattern) and
@@ -143,9 +143,19 @@ function requireGraph(contentsByFile) {
143
143
  const edges = new Map();
144
144
  for (const [file, text] of contentsByFile) {
145
145
  const deps = [];
146
- for (const m of text.matchAll(REQUIRE_RE)) {
147
- const target = resolveRelative(file, m[2], exists);
148
- if (target && target !== file) deps.push(target);
146
+ // Scan line by line and skip WHOLE-LINE comments. A comment that merely
147
+ // NAMES a require — "// re-exports every name, so no require('./db') call
148
+ // site had to change" — used to create a phantom edge, and during the task
149
+ // 1003204 carve one such header comment on twelve new files fabricated a
150
+ // twelve-file cycle and reddened CI. Only a `//`- or `*`-leading line is
151
+ // dropped, so an inline trailing comment still counts, which is the safe
152
+ // direction: a missed real edge would hide a cycle.
153
+ for (const line of text.split('\n')) {
154
+ if (/^\s*(\/\/|\*)/.test(line)) continue;
155
+ for (const m of line.matchAll(REQUIRE_RE)) {
156
+ const target = resolveRelative(file, m[2], exists);
157
+ if (target && target !== file) deps.push(target);
158
+ }
149
159
  }
150
160
  edges.set(file, deps);
151
161
  }
@@ -49,7 +49,11 @@ const MODULE_TESTS = {
49
49
  'terrain_picker', 'local_preview',
50
50
  ],
51
51
  'art-pipeline': [
52
- 'anti_grid', 'autotile_variants', 'autotile_xverify', 'art_key', 'art_stage',
52
+ // task 1003207 deleted anti_grid / autotile_variants / autotile_xverify — the
53
+ // art pipeline is not a module of this core any more, so they targeted a
54
+ // directory that no longer exists. art_key / art_stage still gate on the
55
+ // module being enabled, which is what this map is for.
56
+ 'art_key', 'art_stage',
53
57
  ],
54
58
  };
55
59
 
@@ -116,21 +120,17 @@ const INTEGRATION = new Set([
116
120
  ]);
117
121
 
118
122
  // Excluded so this gate is trustworthy in a CLEAN checkout (the CI condition):
119
- // - autotile_variants / autotile_xverify: depend on a python-generated artifact
120
- // (modules/art-pipeline/pipeline/_autotile_tables.json) / build output absent in a fresh clone,
121
- // so they exit non-zero standalone. Belong in an art-pipeline gate, not here.
122
- // - anti_grid: runs modules/art-pipeline/pipeline/anti_grid_eval.py, which needs numpy (absent in
123
- // the Node-only CI runner) -> ModuleNotFoundError. Same python-artifact class
124
- // as autotile; belongs in an art-pipeline gate (task 859 / ADR 0042 cutover).
123
+ // - autotile_variants / autotile_xverify / anti_grid were parked here because they
124
+ // needed modules/art-pipeline artifacts. Task 1003207 DELETED all three: the
125
+ // art pipeline left this core with the game, so they targeted a module that no
126
+ // longer exists and could never have gone green again. A permanently-parked
127
+ // test is not a gate, it is a file that looks like one.
125
128
  //
126
129
  // grader_panel was excluded here (2 "failing" assertions, idea #225) until #954
127
130
  // (V4.R16) diagnosed them as STALE — they predated #481's Narc-advisory change,
128
131
  // NOT a grader regression. Now green and back under this gate so the quality-
129
132
  // gate brain can't silently regress.
130
133
  const KNOWN_FAILING = new Set([
131
- 'autotile_variants',
132
- 'autotile_xverify',
133
- 'anti_grid',
134
134
  // #1002617: red in every clean environment (Linux CI and a Windows checkout
135
135
  // alike), surfaced by the unit lane's first-ever runs. Parked so the `unit`
136
136
  // check can be required (a gate that's already red gates nothing); per-test
package/src/module-api.js CHANGED
@@ -1097,8 +1097,12 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
1097
1097
  // landed since 1.19.333 with no explicit bump. run 32794305277. (task 1002620)
1098
1098
  // 1.19.335 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1099
1099
  // landed since 1.19.334 with no explicit bump. run 32795232997. (task 1002620)
1100
+ // 1.19.336 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1101
+ // landed since 1.19.335 with no explicit bump. run 32795564021. (task 1002620)
1102
+ // 1.19.337 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1103
+ // landed since 1.19.336 with no explicit bump. run 32795896926. (task 1002620)
1100
1104
  // ---------------------------------------------------------------------------
1101
- const CORE_VERSION = '1.19.335'; // CI auto-patch carrier (ADR 0161); see changelog above
1105
+ const CORE_VERSION = '1.19.337'; // CI auto-patch carrier (ADR 0161); see changelog above
1102
1106
 
1103
1107
  // A namespaced logger so a module's log lines are attributable + consistent.
1104
1108
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -11,10 +11,13 @@
11
11
 
12
12
  import { strict as assert } from 'node:assert';
13
13
  import { createRequire } from 'node:module';
14
+ import { fileURLToPath } from 'node:url';
14
15
  import http from 'node:http';
15
16
 
16
17
  const require = createRequire(import.meta.url);
17
- const ROOT = new URL('..', import.meta.url).pathname;
18
+ // fileURLToPath, not .pathname: a checkout path with a space reads back percent-encoded
19
+ // (and drive-prefixed) from .pathname on Windows, and require() cannot follow it
20
+ const ROOT = fileURLToPath(new URL('..', import.meta.url));
18
21
 
19
22
  // Stub the data-access fns BEFORE the route factory captures the module object.
20
23
  const provisioning = require(`${ROOT}/modules/provisioning/provisioning.js`);
@@ -92,6 +95,42 @@ console.log('\nGET /provisioning/github-app/callback (the public GitHub redirect
92
95
  const html = await res.text();
93
96
  t('good state → 200 text/html progress page wired to auto-open', res.status === 200 && /text\/html/.test(res.headers.get('content-type') || '') && /Setting up your instance/.test(html) && /Placing credentials/.test(html) && /__CB_SETUP__/.test(html) && html.includes('GOODSTATE'), `status=${res.status}`);
94
97
  t('the page names the instance host', /mercury\.example\.com/.test(html));
98
+ // task 1003236: a same-tab return (pop-up blocked → form target=_self) must never be
99
+ // navigated away from the checklist. The page carries a hidden way back, and the
100
+ // countdown sits behind the pop-up guard.
101
+ t('carries a hidden "finish your remaining setup steps" link back to the wizard', /<p class="muted hidden" id="back"><a href="\/projects\?view=new">Finish your remaining setup steps/.test(html));
102
+ t('the auto-open countdown is reachable only past the pop-up guard', /var popup=!!window\.opener\|\|window\.name==='ghAppSetup';/.test(html) && /if\(!popup\)\{[^}]*return;\}\s*var n=4;\(function tick\(\)\{if\(n<=0\)\{location\.href=target;/.test(html) && (html.match(/location\.href=target/g) || []).length === 1);
103
+
104
+ // Run the served script itself (not a copy) against a minimal DOM, once as the
105
+ // wizard's pop-up and once as a same-tab return, and watch what it does to location.
106
+ const script = (html.match(/<script>\s*(\(function\(\)\{[\s\S]*?)<\/script>\s*<\/body>/) || [])[1];
107
+ t('the progress page ships the client script', typeof script === 'string' && script.length > 200);
108
+ async function runCallback({ opener, name }) {
109
+ const vm = await import('node:vm');
110
+ const el = () => { const cls = new Set(); return { textContent: '', classList: { add: (...c) => c.forEach((x) => cls.add(x)), remove: (...c) => c.forEach((x) => cls.delete(x)), contains: (c) => cls.has(c) }, querySelector: () => el() }; };
111
+ const els = { steps: el(), status: el(), cta: el(), go: el(), foot: el(), back: el() };
112
+ els.steps.querySelector = () => el();
113
+ els.back.classList.add('hidden'); els.cta.classList.add('hidden');
114
+ const timers = [];
115
+ const sandbox = {
116
+ __CB_SETUP__: { state: 'GOODSTATE', domain: 'mercury.example.com' },
117
+ opener, name,
118
+ document: { getElementById: (id) => els[id] || null },
119
+ location: { pathname: '/api/bongos/provisioning/github-app/callback', href: 'about:callback' },
120
+ fetch: async () => ({ ok: true, json: async () => ({ ok: true, ready: true, status: 'done' }) }),
121
+ setTimeout: (fn) => { timers.push(fn); return timers.length; },
122
+ encodeURIComponent,
123
+ };
124
+ sandbox.window = sandbox;
125
+ vm.runInNewContext(script, sandbox);
126
+ for (let i = 0; i < 5; i++) await new Promise((r) => setImmediate(r)); // let the poll's promise chain settle
127
+ for (let guard = 0; guard < 10 && timers.length; guard++) { const fn = timers.shift(); fn(); }
128
+ return { href: sandbox.location.href, go: els.go.textContent, backHidden: els.back.classList.contains('hidden'), foot: els.foot.textContent };
129
+ }
130
+ const popup = await runCallback({ opener: {}, name: 'ghAppSetup' });
131
+ t('as the wizard’s pop-up it still counts down and opens the instance', popup.href === 'https://mercury.example.com', JSON.stringify(popup));
132
+ const sameTab = await runCallback({ opener: null, name: '' });
133
+ t('as a same-tab return it stays put: door shown, way back revealed, no navigation', sameTab.href === 'about:callback' && sameTab.go === 'Open mercury.example.com →' && sameTab.backHidden === false && /checklist is waiting/.test(sameTab.foot), JSON.stringify(sameTab));
95
134
  }
96
135
  {
97
136
  const res = await fetch(`${base}/provisioning/github-app/callback?code=X&state=NOPE`);
@@ -143,7 +143,10 @@ console.log('\nLayer C — real searchChunks against a live DB (skips if unreach
143
143
 
144
144
  let pool = null;
145
145
  try {
146
- ({ pool } = require('../src/db'));
146
+ // task 1003207: this said `../src/db`, which has not existed since the kernel
147
+ // carve — so the require ALWAYS threw, pool stayed null, and Layer C skipped
148
+ // even against a live Postgres. It was a dead layer reporting as a skip.
149
+ ({ pool } = require('../src/bongos/pool'));
147
150
  } catch { pool = null; }
148
151
 
149
152
  async function dbReachable() {