@bongos/core 1.19.694 → 1.19.695

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.694",
6
- "core_contract": "1.19.694",
7
- "source_commit": "7cd0b705f047458dfa2038bd842adee75333a643",
5
+ "core_version": "1.19.695",
6
+ "core_contract": "1.19.695",
7
+ "source_commit": "178cdaa548f0ea45deb347104acd63d6aeb20cc7",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-13T01:54:36.629Z",
9
+ "built_at": "2026-09-13T02:08:24.203Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 477,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2628,
20
- "tree_sha256": "0ab80bfe776899e5734f702ca69263e38455dae234ba01b3d422d6ef131e6c49",
20
+ "tree_sha256": "2b4685b0549d24df433e75ac5aa8719b418ddfee7e86c70726b5bb5c994586a0",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2802,7 +2802,7 @@
2802
2802
  {
2803
2803
  "path": "docs/module-api-changelog.md",
2804
2804
  "mode": "0000644",
2805
- "sha256": "578d0d708917e956889cfbd990258b1cda804052474f07087d9af589f387425e"
2805
+ "sha256": "e9a7dcf5d697f1051d5c54199c9b30b21b2e76f332c87bc7e8d9503318f842f5"
2806
2806
  },
2807
2807
  {
2808
2808
  "path": "docs/modules-contract.md",
@@ -7782,12 +7782,12 @@
7782
7782
  {
7783
7783
  "path": "package-lock.json",
7784
7784
  "mode": "0000644",
7785
- "sha256": "929bc69d15f44bc6648df7b2f3a9e22d72501486ae2abb9b0491cfcfabbd6683"
7785
+ "sha256": "5d78acccc55e18e1a0eb5b1c9345dede369578daff1162114ffc35f11c209999"
7786
7786
  },
7787
7787
  {
7788
7788
  "path": "package.json",
7789
7789
  "mode": "0000644",
7790
- "sha256": "cc0356495a5cf8f4822c0e6efff4b17ef7a1dcd69da2f724a5089b99be71aea7"
7790
+ "sha256": "952678094d2f65405c5195d793f8754b78113e2b489fc9171bff02dee8c9bd76"
7791
7791
  },
7792
7792
  {
7793
7793
  "path": "public-docs/index.html",
@@ -9147,7 +9147,7 @@
9147
9147
  {
9148
9148
  "path": "scripts/gds/worktree.js",
9149
9149
  "mode": "0000644",
9150
- "sha256": "849cd462b9c50866ca1582ed2156fb68ac76699c8270796d1daf6942c09713dc"
9150
+ "sha256": "af95d7ae434d587dae654e24640163c44ac293edb11d2c0deb979b855701ac85"
9151
9151
  },
9152
9152
  {
9153
9153
  "path": "scripts/hall-preview/README.md",
@@ -9552,7 +9552,7 @@
9552
9552
  {
9553
9553
  "path": "src/module-api.js",
9554
9554
  "mode": "0000644",
9555
- "sha256": "60f2d47936df6dee6b06ea525d1a6d397d563ed6ee3e052b566936b6e5515af8"
9555
+ "sha256": "309fdfdb42698f3cdb53b167cffa0fbab10ae61904d6f331035edf35ef547047"
9556
9556
  },
9557
9557
  {
9558
9558
  "path": "src/module-loader/catalog.js",
@@ -13147,7 +13147,7 @@
13147
13147
  {
13148
13148
  "path": "tests/worktree_helper.mjs",
13149
13149
  "mode": "0000644",
13150
- "sha256": "367e4c9a63bc8752b94d0fc7af171d34390034adc2a75c8ec15f00b335c077ca"
13150
+ "sha256": "9d511e7cf21cea05cc565e9e5022c7c86cd3cf0d67053125ec27aeae3348e30a"
13151
13151
  },
13152
13152
  {
13153
13153
  "path": "tests/world_tokens.mjs",
@@ -1847,5 +1847,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
1847
1847
  landed since 1.19.692 with no explicit bump. run 34731402927. (task 1002620)
1848
1848
  1.19.694 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1849
1849
  landed since 1.19.693 with no explicit bump. run 34731674808. (task 1002620)
1850
+ 1.19.695 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
1851
+ landed since 1.19.694 with no explicit bump. run 34732266878. (task 1002620)
1850
1852
  ---------------------------------------------------------------------------
1851
1853
  ```
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.694",
3
+ "version": "1.19.695",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.694",
9
+ "version": "1.19.695",
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.694",
3
+ "version": "1.19.695",
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",
@@ -62,6 +62,45 @@ function needsJunction({ wtPath, repoRoot, platform }) {
62
62
  return isOutsideRepo({ wtPath, repoRoot });
63
63
  }
64
64
 
65
+ // A node_modules directory sitting BETWEEN an inside-repo worktree and the repo
66
+ // root — e.g. `.claude/worktrees/node_modules` — shadowing the main checkout's.
67
+ // Returns its path, or null. Pure: `existsFn` is injected so this is testable
68
+ // without building a directory tree.
69
+ //
70
+ // WHY THIS IS WORTH DETECTING (task 1003627). An inside-repo worktree deliberately
71
+ // gets NO junction: node's resolution walks up to the main checkout, which is the
72
+ // documented design. But walk-up stops at the FIRST node_modules it meets, so a
73
+ // stray one on the way up silently wins for EVERY inside-repo worktree at once.
74
+ //
75
+ // Measured, not assumed: with the same package present at both levels, a probe in
76
+ // `<root>/worktrees/wt` resolved to the main checkout's copy with no stray, and to
77
+ // the stray the moment one existed one level up.
78
+ //
79
+ // The failure is quiet in the worst way — `require('pino')` still SUCCEEDS, just
80
+ // from somewhere nobody installed on purpose, so a partial or stale stray reads as
81
+ // a mysterious version skew rather than as a path problem. Two agents hit this on
82
+ // 2026-09-04 (tasks 1002331, 1003577) and both concluded `worktree.js add` had
83
+ // failed to create a junction. It had not: for an inside-repo worktree there is no
84
+ // junction to create, and needsJunction — a pure win32-and-outside-root string
85
+ // compare, unchanged since task 1002809 — never consulted a directory at all. The
86
+ // missing piece was never a junction; it was anyone SAYING that the stray was there.
87
+ function shadowingNodeModules({ wtPath, repoRoot, existsFn }) {
88
+ const exists = existsFn || ((p) => fs.existsSync(p));
89
+ if (isOutsideRepo({ wtPath, repoRoot })) return null; // outside gets a junction instead
90
+ let dir = path.dirname(path.resolve(wtPath));
91
+ const root = path.resolve(repoRoot);
92
+ // Walk from the worktree's PARENT up to (but not including) the repo root: a
93
+ // node_modules AT the root is the one we want resolution to reach.
94
+ while (dir !== root && dir.length > root.length) {
95
+ const candidate = path.join(dir, 'node_modules');
96
+ if (exists(candidate)) return candidate;
97
+ const parent = path.dirname(dir);
98
+ if (parent === dir) break; // hit the filesystem root without meeting repoRoot
99
+ dir = parent;
100
+ }
101
+ return null;
102
+ }
103
+
65
104
  // Ordered removal steps. The junction MUST go before git worktree remove (git
66
105
  // follows it into the shared node_modules); a REAL node_modules dir is left for
67
106
  // git to refuse — this tool never deletes real directories.
@@ -182,6 +221,18 @@ function cmdAdd(root, argv) {
182
221
  // Explicit --path outside the repo on posix: no junction is created here,
183
222
  // so say plainly that node_modules won't resolve rather than fail later.
184
223
  console.log(' ⚠ this worktree is outside the repo — node_modules will NOT resolve from here on this platform.');
224
+ } else {
225
+ // Inside the repo: no junction by design, node walks up to the main checkout.
226
+ // But walk-up stops at the FIRST node_modules, so name a stray one in between
227
+ // — it silently captures every inside-repo worktree and `require` still
228
+ // succeeds, which is what makes it so hard to spot (task 1003627).
229
+ const shadow = shadowingNodeModules({ wtPath, repoRoot: root });
230
+ if (shadow) {
231
+ console.log(` ⚠ a stray node_modules sits between this worktree and the repo root: ${shadow}`);
232
+ console.log(" node's walk-up stops THERE, not at the main checkout — so this worktree (and every other");
233
+ console.log(' one beside it) resolves dependencies from a directory nobody installed on purpose.');
234
+ console.log(' Delete it, then re-run: dependencies belong in the MAIN checkout only.');
235
+ }
185
236
  }
186
237
  console.log('');
187
238
  console.log('Next:');
@@ -280,4 +331,4 @@ function main() {
280
331
 
281
332
  if (require.main === module) main();
282
333
 
283
- module.exports = { worktreeNameFor, needsJunction, removalPlan, nodeModulesState };
334
+ module.exports = { worktreeNameFor, needsJunction, removalPlan, nodeModulesState, shadowingNodeModules };
package/src/module-api.js CHANGED
@@ -71,7 +71,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
71
71
  // there. scripts/gds/bump-version.js still rewrites the literal below; it appends
72
72
  // the entry to that file. Look for a version's history there, not here.
73
73
  // ---------------------------------------------------------------------------
74
- const CORE_VERSION = '1.19.694'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.695'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
75
75
 
76
76
  // A namespaced logger so a module's log lines are attributable + consistent.
77
77
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -27,7 +27,7 @@ import os from 'node:os';
27
27
  import path from 'node:path';
28
28
 
29
29
  const require = createRequire(import.meta.url);
30
- const { worktreeNameFor, needsJunction, removalPlan, nodeModulesState } = require('../scripts/gds/worktree.js');
30
+ const { worktreeNameFor, needsJunction, removalPlan, nodeModulesState, shadowingNodeModules } = require('../scripts/gds/worktree.js');
31
31
 
32
32
  let passed = 0;
33
33
  let failed = 0;
@@ -140,6 +140,55 @@ test('a REAL node_modules dir is left for git to refuse — we never rm it', ()
140
140
  eqArr(removalPlan({ nodeModulesState: 'real-dir' }), ['git-worktree-remove']);
141
141
  });
142
142
 
143
+ // ---- shadowingNodeModules (task 1003627) ----------------------------------
144
+ // An inside-repo worktree gets NO junction by design — node walks up to the main
145
+ // checkout. But walk-up stops at the FIRST node_modules, so a stray one in
146
+ // between captures every inside-repo worktree at once, and `require` still
147
+ // SUCCEEDS from the wrong place. Two agents read that as "worktree.js add failed
148
+ // to make a junction" on 2026-09-04; there was no junction to make.
149
+ const R = 'C:/repo';
150
+ const WT = 'C:/repo/.claude/worktrees/task-1';
151
+ const at = (...present) => {
152
+ const set = new Set(present.map((p) => path.resolve(p)));
153
+ return (p) => set.has(path.resolve(p));
154
+ };
155
+
156
+ test('names a stray node_modules one level above the worktree', () => {
157
+ const hit = shadowingNodeModules({
158
+ wtPath: WT, repoRoot: R, existsFn: at('C:/repo/.claude/worktrees/node_modules'),
159
+ });
160
+ eq(path.resolve(hit), path.resolve('C:/repo/.claude/worktrees/node_modules'));
161
+ });
162
+
163
+ test('names a stray further up too (any level BELOW the repo root shadows it)', () => {
164
+ const hit = shadowingNodeModules({ wtPath: WT, repoRoot: R, existsFn: at('C:/repo/.claude/node_modules') });
165
+ eq(path.resolve(hit), path.resolve('C:/repo/.claude/node_modules'));
166
+ });
167
+
168
+ test('the repo root\'s OWN node_modules is not a stray — that is the target', () => {
169
+ // The whole point of walk-up is to reach this one; flagging it would make the
170
+ // warning fire on every healthy worktree, which is how a warning becomes noise.
171
+ eq(shadowingNodeModules({ wtPath: WT, repoRoot: R, existsFn: at('C:/repo/node_modules') }), null);
172
+ });
173
+
174
+ test('no stray anywhere → null', () => {
175
+ eq(shadowingNodeModules({ wtPath: WT, repoRoot: R, existsFn: () => false }), null);
176
+ });
177
+
178
+ test('an OUTSIDE-repo worktree is not checked — it gets a junction instead', () => {
179
+ eq(shadowingNodeModules({ wtPath: 'C:/tmp/wt-9', repoRoot: R, existsFn: () => true }), null);
180
+ });
181
+
182
+ test('the nearest stray wins, matching node\'s own resolution order', () => {
183
+ const hit = shadowingNodeModules({
184
+ wtPath: WT,
185
+ repoRoot: R,
186
+ existsFn: at('C:/repo/.claude/worktrees/node_modules', 'C:/repo/.claude/node_modules'),
187
+ });
188
+ eq(path.resolve(hit), path.resolve('C:/repo/.claude/worktrees/node_modules'),
189
+ 'node stops at the first node_modules it meets walking up');
190
+ });
191
+
143
192
  console.log('');
144
193
  console.log(`worktree_helper: ${passed} passed, ${failed} failed`);
145
194
  process.exit(failed > 0 ? 1 : 0);