@bongos/core 1.19.218 → 1.19.219

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.218",
6
- "core_contract": "1.19.218",
7
- "source_commit": "a00e409d98973f59f934543251e819a2b9deabd5",
5
+ "core_version": "1.19.219",
6
+ "core_contract": "1.19.219",
7
+ "source_commit": "c74ac31eedb3ec3676f8517b51302df625298931",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-08-18T01:00:37.333Z",
9
+ "built_at": "2026-08-18T03:06:20.562Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 311,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 1634,
20
- "tree_sha256": "fe7773c1c51b74af666fd1bd0db3495ae383d717ca65af9a4ef310f9e252efb0",
20
+ "tree_sha256": "4da1158ccf79b2a7a5253dad319cc74192493be9bda2e6a8874df8c60f581cc5",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/blocker-review/SKILL.md",
@@ -2697,7 +2697,7 @@
2697
2697
  {
2698
2698
  "path": "modules/dev-box/box-access.js",
2699
2699
  "mode": "0000644",
2700
- "sha256": "9357b423836c4e8d2cd3c9144d294c3cd3b498ac30755a9e6f62b5bbaa2add5e"
2700
+ "sha256": "870976966de7c48be4172390dc8e4f7d2eb6ac53e20dfb3fd5d40b08cfcd7850"
2701
2701
  },
2702
2702
  {
2703
2703
  "path": "modules/dev-box/box-credential.js",
@@ -4287,12 +4287,12 @@
4287
4287
  {
4288
4288
  "path": "package-lock.json",
4289
4289
  "mode": "0000644",
4290
- "sha256": "199faf243475315d256fab355abdc1bfa2547a1d42d0ac623080b44be144de26"
4290
+ "sha256": "ac23681c5493a57f1faca551e4896e4a7a4e2dabb6246bf2a84c39ae6e571257"
4291
4291
  },
4292
4292
  {
4293
4293
  "path": "package.json",
4294
4294
  "mode": "0000644",
4295
- "sha256": "81b98db9ae28ac2606efa211fe791632c1857e796c4d7e00cddbcf26daf76362"
4295
+ "sha256": "7122e5cca352a5abc317d25267eba6c0bab955febf2179bf362a896be424d0bc"
4296
4296
  },
4297
4297
  {
4298
4298
  "path": "public-docs/index.html",
@@ -5907,7 +5907,7 @@
5907
5907
  {
5908
5908
  "path": "src/module-api.js",
5909
5909
  "mode": "0000644",
5910
- "sha256": "559f382c12c7f37bc85227630cd5670d9f4b7749e9994036d85c221a5d3d3b43"
5910
+ "sha256": "d509a7e4f16027ccef999e8aadf1a2cef5368bce5cd0c3bda3b7eb61cbceaa5f"
5911
5911
  },
5912
5912
  {
5913
5913
  "path": "src/module-loader/catalog.js",
@@ -6202,7 +6202,7 @@
6202
6202
  {
6203
6203
  "path": "tests/box_access.mjs",
6204
6204
  "mode": "0000644",
6205
- "sha256": "694153e377a78d4325aa4ff9b947f691d71362f843da25815b9740821903802c"
6205
+ "sha256": "1e4db680c5925e473fff9ad6247e797bd9089fdf3696c3ffb161903bda41dcda"
6206
6206
  },
6207
6207
  {
6208
6208
  "path": "tests/box_auth_check.mjs",
@@ -171,24 +171,63 @@ const BASE_SPARSE_PATHS = [
171
171
  // globs come in two shapes: directory globs (trailing '/', e.g. 'modules/dev-box/')
172
172
  // and file-list globs (exact paths, e.g. the kernel key's 'src/bongos/db.js'). We
173
173
  // KEEP the directory globs (normalized to no trailing slash, matching the BASE
174
- // style) and DROP the file globs — every file glob in the map sits under a BASE
175
- // directory (src/bongos, scripts) or is a top-level/ancestor file cone mode pulls
176
- // automatically, so base already materializes it. (A future non-cone sparse move
177
- // could pull individual files; out of scope — cone mode stays.) Deterministic:
178
- // BASE in declared order, then the module dirs sorted + deduped.
174
+ // style). A FILE glob cannot be emitted as-is, so it contributes its PARENT
175
+ // DIRECTORY instead — unless BASE or another emitted dir already covers it.
176
+ //
177
+ // It used to be dropped outright, on the reasoning that "every file glob in the
178
+ // map sits under a BASE directory (src/bongos, scripts) or is a top-level file
179
+ // cone mode pulls automatically". That was true when written and **silently
180
+ // stopped being true**: ADR 0174 gave the `government` key the file globs
181
+ // `config/government.json` + `config/government.neutral.json`, and `config` is
182
+ // not in BASE. The result was a goal walled to `government` whose box could never
183
+ // see two files inside its own scope wall — which released task 1003018 (R05 of
184
+ // goal 1000069), whose entire deliverable was one of them. Rather than restore an
185
+ // invariant that expires again the next time a module claims a config file, the
186
+ // parent is emitted and the class is covered by construction.
187
+ //
188
+ // TRADE-OFF, stated rather than implied: the parent directory is a SUPERSET of
189
+ // the glob — asking for `config/government.json` materializes all of `config/`.
190
+ // The box's view is already a superset of the wall (BASE hands out `scripts`,
191
+ // `docs` and `tests` wholesale regardless of scope), so this is consistent with
192
+ // the existing posture, not a new concession. The WALL is unchanged: what a
193
+ // builder may author is still decided by goal-scope-check against the globs, not
194
+ // by what happens to be on disk.
195
+ //
196
+ // Top-level file globs (no '/') contribute nothing — cone mode includes root
197
+ // files automatically. Deterministic: BASE in declared order, then the module
198
+ // dirs sorted + deduped.
179
199
  function sparsePathsForScopeKeys(scopeKeys, moduleScopeMap) {
180
200
  const base = [...BASE_SPARSE_PATHS];
181
201
  const seen = new Set(base);
182
202
  const extra = [];
203
+ // Cone mode materializes a directory and everything under it, so a path is
204
+ // already covered when IT or any ancestor has been emitted. This is what keeps
205
+ // `scripts/gds/box.js` from adding `scripts/gds` — BASE's `scripts` covers it.
206
+ const covered = (dir) => {
207
+ let p = dir;
208
+ for (;;) {
209
+ if (seen.has(p)) return true;
210
+ const cut = p.lastIndexOf('/');
211
+ if (cut < 0) return false;
212
+ p = p.slice(0, cut);
213
+ }
214
+ };
215
+ const add = (dir) => {
216
+ if (!dir || covered(dir)) return;
217
+ seen.add(dir);
218
+ extra.push(dir);
219
+ };
183
220
  for (const key of Array.isArray(scopeKeys) ? scopeKeys : []) {
184
221
  const entry = moduleScopeMap && typeof moduleScopeMap.scopeForModule === 'function'
185
222
  ? moduleScopeMap.scopeForModule(key)
186
223
  : null;
187
224
  if (!entry || !Array.isArray(entry.globs)) continue;
188
225
  for (const glob of entry.globs) {
189
- if (typeof glob !== 'string' || !glob.endsWith('/')) continue; // dirs only (cone mode)
190
- const dir = glob.replace(/\/+$/, '');
191
- if (!seen.has(dir)) { seen.add(dir); extra.push(dir); }
226
+ if (typeof glob !== 'string' || !glob) continue;
227
+ if (glob.endsWith('/')) { add(glob.replace(/\/+$/, '')); continue; }
228
+ const cut = glob.lastIndexOf('/');
229
+ if (cut < 0) continue; // a root file — cone mode already includes it
230
+ add(glob.slice(0, cut));
192
231
  }
193
232
  }
194
233
  extra.sort();
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.218",
3
+ "version": "1.19.219",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.218",
9
+ "version": "1.19.219",
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.218",
3
+ "version": "1.19.219",
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
@@ -863,8 +863,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
863
863
  // landed since 1.19.216 with no explicit bump. run 32084927511. (task 1002620)
864
864
  // 1.19.218 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
865
865
  // landed since 1.19.217 with no explicit bump. run 32086598601. (task 1002620)
866
+ // 1.19.219 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
867
+ // landed since 1.19.218 with no explicit bump. run 32094215476. (task 1002620)
866
868
  // ---------------------------------------------------------------------------
867
- const CORE_VERSION = '1.19.218'; // CI auto-patch carrier (ADR 0161); see changelog above
869
+ const CORE_VERSION = '1.19.219'; // CI auto-patch carrier (ADR 0161); see changelog above
868
870
 
869
871
  // A namespaced logger so a module's log lines are attributable + consistent.
870
872
  // Usage: const log = api.logger('dev-box'); log.info('mounted');
@@ -221,14 +221,69 @@ t('cone-filter: dev-box keeps its DIRS, DROPS its file globs (scripts/gds/box.js
221
221
  assert.ok(out.includes('devbox-app'), 'the app dir is kept');
222
222
  assert.ok(!out.some((p) => p.endsWith('.js') || p.endsWith('.sh')), 'no file globs survive the cone filter');
223
223
  assert.ok(!out.includes('scripts/gds/box.js'), 'the box CLI file is dropped (BASE scripts covers it)');
224
+ // …and its PARENT is not added either: BASE's `scripts` already covers it, so
225
+ // the ancestor check must stop `scripts/gds` from appearing. This is the half
226
+ // that keeps the file-glob rescue below from over-sharing.
227
+ assert.ok(!out.includes('scripts/gds'), 'a covered parent is not re-emitted');
228
+ });
229
+
230
+ // A file glob whose parent is NOT already covered must contribute that parent.
231
+ // Regression for the live failure that released task 1003018 (R05 of goal
232
+ // 1000069): the `government` key's config/government*.json globs were dropped on
233
+ // the reasoning that every file glob sits under a BASE directory — true when
234
+ // written, false once ADR 0174 added them, since `config` is not in BASE. The box
235
+ // could not see two files inside its own scope wall.
236
+ t('file-glob rescue: government contributes `config` for its config/*.json globs', () => {
237
+ const out = access.sparsePathsForScopeKeys(['government'], scopeMap);
238
+ assert.ok(out.includes('modules/government'), 'the module dir is kept');
239
+ assert.ok(out.includes('config'), 'config/government.neutral.json must reach the box via its parent');
240
+ assert.ok(!out.some((p) => p.endsWith('.json')), 'still no file paths — cone mode would reject one');
241
+ });
242
+
243
+ t('file-glob rescue holds for EVERY key in the map — no module can silently lose one', () => {
244
+ // Enumerated, never sampled: a module that gains a file glob under a new parent
245
+ // is covered the day it lands, which is exactly how this bug escaped before.
246
+ for (const key of scopeMap.moduleKeys()) {
247
+ const out = access.sparsePathsForScopeKeys([key], scopeMap);
248
+ for (const glob of scopeMap.scopeForModule(key).globs) {
249
+ if (glob.endsWith('/')) continue;
250
+ const cut = glob.lastIndexOf('/');
251
+ if (cut < 0) continue; // a root file — cone mode includes it automatically
252
+ const parent = glob.slice(0, cut);
253
+ const reachable = out.some((p) => parent === p || parent.startsWith(`${p}/`));
254
+ assert.ok(reachable, `${key}: no cone path materializes ${glob} (parent ${parent})`);
255
+ }
256
+ }
257
+ });
258
+
259
+ t('the emitted set stays directories only, for every key', () => {
260
+ // A leading dot is a DIRECTORY here ('.devcontainer', '.claude'), so the
261
+ // extension test must require a non-dot character before the dot — otherwise
262
+ // every BASE dotfile-dir reads as a file and this assertion fires on healthy
263
+ // input. (It did, on first write.)
264
+ const looksLikeFile = (seg) => /[^.]\.[a-z0-9]+$/i.test(seg);
265
+ for (const key of scopeMap.moduleKeys()) {
266
+ for (const p of access.sparsePathsForScopeKeys([key], scopeMap)) {
267
+ assert.ok(!looksLikeFile(p.split('/').pop()),
268
+ `${key}: ${p} looks like a file — git sparse-checkout set would abort on it`);
269
+ }
270
+ }
224
271
  });
225
272
 
226
- t('cone-filter: the kernel key contributes only its real DIR globs (config, src/module-loader)', () => {
273
+ t('cone-filter: the kernel key materializes its real DIR globs (config, src/module-loader)', () => {
227
274
  const out = access.sparsePathsForScopeKeys(['kernel'], scopeMap);
228
275
  // kernel is mostly individual src/bongos/*.js FILES (dropped — BASE src/bongos
229
276
  // covers them via cone ancestor-inclusion) + a few genuine DIR globs.
230
277
  assert.ok(out.includes('config'), 'config/ is a real dir the task needs, not in BASE');
231
- assert.ok(out.includes('src/module-loader'), 'src/module-loader/ is a real dir not in BASE');
278
+ // src/module-loader/ is a real dir not in BASE, but it is NOT emitted verbatim:
279
+ // kernel also carries the file globs src/instance-config.js, src/branding.js,
280
+ // src/modules.js and src/module-api.js, whose rescued parent is `src` — and once
281
+ // `src` is emitted the ancestor check absorbs every path beneath it, this one
282
+ // included. Asserting literal membership would be asserting emission ORDER, not
283
+ // reachability. What the box must actually get is the DIRECTORY's contents, so
284
+ // assert that, using the same idiom as the enumerated rescue test above.
285
+ const reaches = (dir) => out.some((p) => dir === p || dir.startsWith(`${p}/`));
286
+ assert.ok(reaches('src/module-loader'), 'src/module-loader must be materialized (here via the rescued `src`)');
232
287
  assert.ok(!out.includes('src/bongos/db.js'), 'the kernel FILE globs are dropped');
233
288
  assert.ok(!out.includes('server.js'), 'top-level files never enter the sparse set (cone auto-includes them)');
234
289
  });