@bongos/core 1.19.857 → 1.19.858

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.857",
6
- "core_contract": "1.19.857",
7
- "source_commit": "b591a81b627f40ec9e0d235d201b1f54f21ea1bf",
5
+ "core_version": "1.19.858",
6
+ "core_contract": "1.19.858",
7
+ "source_commit": "afc4e781c80a292d23180b498c8a15f9483bcedb",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-17T21:51:29.538Z",
9
+ "built_at": "2026-09-17T22:01:14.430Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 498,
@@ -17,7 +17,7 @@
17
17
  "gate": "passed"
18
18
  },
19
19
  "file_count": 2804,
20
- "tree_sha256": "6d87cce28c4d7d99fab00dce29c6654aa1e59ebbff7c20ece7de301410c34332",
20
+ "tree_sha256": "34a2816607bed641f30b7a13611a257ff4330ca477e9b6fb6e03ed7137e20ad5",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -517,7 +517,7 @@
517
517
  {
518
518
  "path": "docs/adr/0020-security-model-public-stub.md",
519
519
  "mode": "0000644",
520
- "sha256": "b95bade85ead2f18f4ad8da7a96c178ff6ccc141d805247838233e15154ed79b"
520
+ "sha256": "22730680f71c68b508d476bb2a1802586cfd56bffd391cb5d98cac9a928e89f1"
521
521
  },
522
522
  {
523
523
  "path": "docs/adr/0021-per-builder-skill-model-preferences.md",
@@ -2592,7 +2592,7 @@
2592
2592
  {
2593
2593
  "path": "docs/module-api-changelog.md",
2594
2594
  "mode": "0000644",
2595
- "sha256": "6039f82c978097f35c3be7357b99c225fd678ca31692b09a130a5389112735dd"
2595
+ "sha256": "56c034df0c7eb96ada2eed6aa17ce5e3485716901c6215c72eb247276a091ca9"
2596
2596
  },
2597
2597
  {
2598
2598
  "path": "docs/modules-contract.md",
@@ -2867,7 +2867,7 @@
2867
2867
  {
2868
2868
  "path": "docs/research/cursor-competitive-analysis.md",
2869
2869
  "mode": "0000644",
2870
- "sha256": "3659fa514a0f2c392ea1779e1c1af70085760b174028f11065a6b72e06dab253"
2870
+ "sha256": "bc2e01b959b5cf36f848dd57a1635d1a9e0a4ae3439610e936bc709ebfc01f96"
2871
2871
  },
2872
2872
  {
2873
2873
  "path": "docs/research/llm-model-agnostic-and-cheaper-grader.md",
@@ -7917,12 +7917,12 @@
7917
7917
  {
7918
7918
  "path": "package-lock.json",
7919
7919
  "mode": "0000644",
7920
- "sha256": "73c27e08b25249cef8ec8eb6a17f45c8f73c6eb75459aa852129456893485446"
7920
+ "sha256": "66f32ef74e691565c2cb563b55bf7276e51a0fb60ac2e993a92ed490e4124191"
7921
7921
  },
7922
7922
  {
7923
7923
  "path": "package.json",
7924
7924
  "mode": "0000644",
7925
- "sha256": "6a45a64683e79505a88ad297424ff463068def3a2b92ba9a417b7d119941640a"
7925
+ "sha256": "52c154531637a295f97e1352c9506ab2096351f701953d257097a94bef201ccf"
7926
7926
  },
7927
7927
  {
7928
7928
  "path": "public-docs/index.html",
@@ -8232,7 +8232,7 @@
8232
8232
  {
8233
8233
  "path": "scripts/gds/claude-materialize.js",
8234
8234
  "mode": "0000644",
8235
- "sha256": "de8dcb51a250334621b104e99f7bc5f857f4422718c3c3ed8519cd5d0ebc8739"
8235
+ "sha256": "488a2a6c55c794625c47480def16c3b3fee81be4bd73d36a21f11a7feab741fc"
8236
8236
  },
8237
8237
  {
8238
8238
  "path": "scripts/gds/claude-md-template.js",
@@ -9867,7 +9867,7 @@
9867
9867
  {
9868
9868
  "path": "src/module-api.js",
9869
9869
  "mode": "0000644",
9870
- "sha256": "f3e4186d676d49a57c8b8cbe857c25c0632ebf7e6f0991380ee746d995b75e45"
9870
+ "sha256": "afc74def8759f073e583a0ec5677587d849e1d8534f704bd1560cb018a16dc10"
9871
9871
  },
9872
9872
  {
9873
9873
  "path": "src/module-loader/catalog.js",
@@ -10592,7 +10592,7 @@
10592
10592
  {
10593
10593
  "path": "tests/claude_materialize.mjs",
10594
10594
  "mode": "0000644",
10595
- "sha256": "42df08d261aaeb7cf94db3eef0e95b06af138d8d317b57f12dc4cb2c23d9f81a"
10595
+ "sha256": "ac4c44006a151190a5ead99c7a32241cf95e21b3eca397ea7c0d4bf26b0b7de9"
10596
10596
  },
10597
10597
  {
10598
10598
  "path": "tests/clawback_confirmed_backlog.mjs",
@@ -20,7 +20,7 @@ The **full security ADR is server-side**, served by a Metic+-gated endpoint and
20
20
 
21
21
  | Surface | Where | Who reads it |
22
22
  |---|---|---|
23
- | Public stub (this file) | `docs/adr/<redacted>.md`, in the repo | anyone with the repo |
23
+ | Public stub (this file) | `docs/adr/0020-security-model-public-stub.md`, in the repo | anyone with the repo |
24
24
  | Full security ADR | A markdown file on the droplet at the path named by `GDS_SECURITY_ADR_PATH` (recommended: `/etc/example/security-adr.md`, owned by the deploy user, `chmod 600`) | the server process, on read; Metic+ via API |
25
25
  | Public read endpoint | none | — |
26
26
  | Authenticated read endpoint | `GET /api/gds/security/adr` — `requireBuilder` + `requireRank('metic','archon')` — returns the markdown body verbatim under `{ adr_md, source: <path>, fetched_at }` | Metic, Archon |
@@ -2188,5 +2188,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2188
2188
  landed since 1.19.855 with no explicit bump. run 35277927951. (task 1002620)
2189
2189
  1.19.857 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2190
2190
  landed since 1.19.856 with no explicit bump. run 35278916322. (task 1002620)
2191
+ 1.19.858 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2192
+ landed since 1.19.857 with no explicit bump. run 35279781206. (task 1002620)
2191
2193
  ---------------------------------------------------------------------------
2192
2194
  ```
@@ -16,7 +16,7 @@ This was produced by the project's deep-research harness (fan-out web search →
16
16
 
17
17
  > **Operational note for the owner:** this is the **second** harness run in a row truncated by the org's monthly Claude spend limit (the module-system doc was the first). The *subagents* die on it; the *main loop* still works, which is how the verification round below got done. To get full unattended verification + auto-synthesis on the next deep dive, raise the limit at `claude.ai/admin-settings/usage`.
18
18
 
19
- Full bibliography in [§10](#10-bibliography). Our positioning is from a direct read of [`docs/adr/<redacted>.md`](../adr/<redacted>.md), [`docs/adr/<redacted>.md`](../adr/<redacted>.md), and [`GOVERNANCE.md`](../../GOVERNANCE.md).
19
+ Full bibliography in [§10](#10-bibliography). Our positioning is from a direct read of [`docs/adr/0065-agpl-nonprofit-ai-first-governance.md`](../adr/0065-agpl-nonprofit-ai-first-governance.md), [`docs/adr/0062-medusa-instance-model-decoupling.md`](../adr/0062-medusa-instance-model-decoupling.md), and [`GOVERNANCE.md`](../../GOVERNANCE.md).
20
20
 
21
21
  ---
22
22
 
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.857",
3
+ "version": "1.19.858",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.857",
9
+ "version": "1.19.858",
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.857",
3
+ "version": "1.19.858",
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",
@@ -403,6 +403,19 @@ function transformSettings(srcPath) {
403
403
  }
404
404
  }
405
405
  }
406
+ // Permission rules name the SAME commands the hooks and skills do, so they take the same
407
+ // rewrite — a rule left as `node scripts/gds/ship.js` matches nothing once the instance's
408
+ // skills run `bongos ship` (task 1004012). `allow` gets the one spelling the skills use; a
409
+ // restrictive list gets BOTH ways an instance can reach the script, or it guards only one.
410
+ const perms = json && json.permissions;
411
+ if (perms && typeof perms === 'object') {
412
+ for (const [key, rules] of Object.entries(perms)) {
413
+ if (!Array.isArray(rules)) continue;
414
+ // an empty verb table makes bongosify emit the `bongos exec scripts/gds/<x>.js` spelling
415
+ const spellings =(r) => (key === 'allow' ? [bongosify(r)] : [bongosify(r), bongosify(r, {})]);
416
+ perms[key] = [...new Set(rules.flatMap((r) => (typeof r === 'string' ? spellings(r) : [r])))];
417
+ }
418
+ }
406
419
  return JSON.stringify(json, null, 2) + '\n';
407
420
  }
408
421
 
@@ -600,7 +613,7 @@ function materializeClaude({ coreRoot, instanceDir, dryRun = false, overwrite =
600
613
  }
601
614
  addWritten('.claude/settings.json');
602
615
  summary.settings = true;
603
- log(` ${dryRun ? '[dry-run] would write' : '✓ wrote'} .claude/settings.json (hook commands→bongos, identity rebranded)`);
616
+ log(` ${dryRun ? '[dry-run] would write' : '✓ wrote'} .claude/settings.json (hook commands + permission rules→bongos, identity rebranded)`);
604
617
  }
605
618
  } else {
606
619
  // Package-only install: the core root carries no settings.json to copy, so
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.857'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.858'; // 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');
@@ -6,7 +6,7 @@
6
6
  // $CLAUDE_PROJECT_DIR/quotes stripped; args preserved; .claude/hooks/ refs left instance-local;
7
7
  // idempotent.
8
8
  // 2. scriptToVerb — excludes prefixArgs verbs so api.js never mis-maps to `bongos box`.
9
- // 3. transformSettings — rewrites only the scripts/gds hook commands, keeps .claude/hooks/ ones.
9
+ // 3. transformSettings — rewrites the scripts/gds hook commands AND permission rules, keeps .claude/hooks/ ones.
10
10
  // 4. materializeClaude — copies + transforms skills into a target dir (no leftover node scripts/gds),
11
11
  // writes settings.json, copies hooks; and NO-OPS when the target IS the core root (self-copy guard).
12
12
  // 5. task 1003486 — a UI task brings its own tools: the `materializeModuleSkills` opt-in on a
@@ -104,6 +104,44 @@ t('transformSettings: rewrites scripts/gds hook commands, keeps .claude/hooks/ o
104
104
  rmSync(dir, { recursive: true, force: true });
105
105
  });
106
106
 
107
+ // task 1004012: the skills an instance receives run `bongos ship`, so a rule that still says
108
+ // `node scripts/gds/ship.js` matches nothing and every blessed command meets the prompt.
109
+ t('transformSettings: permission rules are rewritten to the form the instance\'s skills actually run', () => {
110
+ const dir = mkdtempSync(join(tmpdir(), 'w3-perm-'));
111
+ const p = join(dir, 'settings.json');
112
+ writeFileSync(p, JSON.stringify({
113
+ permissions: {
114
+ // two spellings of one command, a script with no verb of its own, and a rule that names no script
115
+ allow: ['Bash(node scripts/gds/ship.js:*)', 'Bash(node ./scripts/gds/ship.js:*)', 'Bash(node scripts/gds/me.js:*)', 'Bash(git status:*)'],
116
+ deny: ['Bash(node scripts/gds/release.js:*)', 'Bash(node scripts/gds/me.js:*)', 'Read(./.env)'],
117
+ ask: ['Bash(node scripts/gds/claim.js:*)'],
118
+ defaultMode: 'acceptEdits',
119
+ },
120
+ }, null, 2));
121
+ const out = JSON.parse(m.transformSettings(p)).permissions;
122
+ assert.deepEqual(out.allow, ['Bash(bongos ship:*)', 'Bash(bongos exec scripts/gds/me.js:*)', 'Bash(git status:*)'],
123
+ 'allow takes the ONE spelling the skills use, and two spellings of a command collapse to one rule');
124
+ // An instance can reach a script two ways — `bongos release` and `bongos exec scripts/gds/release.js` —
125
+ // so a restrictive rule that named only one would still LOOK like a guard while guarding half.
126
+ assert.deepEqual(out.deny, ['Bash(bongos release:*)', 'Bash(bongos exec scripts/gds/release.js:*)', 'Bash(bongos exec scripts/gds/me.js:*)', 'Read(./.env)']);
127
+ assert.deepEqual(out.ask, ['Bash(bongos claim:*)', 'Bash(bongos exec scripts/gds/claim.js:*)']);
128
+ assert.equal(out.defaultMode, 'acceptEdits', 'a non-list permission key passes through untouched');
129
+ rmSync(dir, { recursive: true, force: true });
130
+ });
131
+
132
+ t('transformSettings: run on the core\'s OWN settings.json, no list keeps a rule in the path form', () => {
133
+ const perms = JSON.parse(m.transformSettings(join(ROOT, '.claude', 'settings.json'))).permissions;
134
+ for (const [key, rules] of Object.entries(perms)) {
135
+ if (!Array.isArray(rules)) continue;
136
+ // A rule bongosify cannot match (a glob in the script name, say) would land on an instance
137
+ // naming a path nothing runs. Adding one to the core must fail HERE, where someone can decide.
138
+ assert.deepEqual(rules.filter((r) => /\bnode\b[^)]*scripts\//.test(r)), [], `permissions.${key}`);
139
+ }
140
+ // compared as sets: the two lists are authored in different orders, and rule order means nothing
141
+ assert.deepEqual([...perms.allow].sort(), [...m.STARTER_ALLOW].sort(),
142
+ 'a checkout-materialized instance and a package-only one must end up with the same blessed commands');
143
+ });
144
+
107
145
  // ---- materializeClaude -----------------------------------------------------
108
146
  t('materializeClaude: copies + rewrites skills into a fresh instance dir (no leftover node scripts/gds)', () => {
109
147
  const dir = mkdtempSync(join(tmpdir(), 'w3-inst-'));
@@ -762,6 +800,24 @@ t('a package-only install (no settings.json at the core root) GETS the starter',
762
800
  rmSync(inst, { recursive: true, force: true });
763
801
  });
764
802
 
803
+ // task 1004012 — the other source: a CHECKOUT core root does carry a settings.json, and the
804
+ // instance used to receive its allow-list verbatim, naming scripts its skills no longer run.
805
+ t('a checkout-materialized instance gets allow-rules in the bongos form, end to end', () => {
806
+ const core = mkdtempSync(join(tmpdir(), 'w3-checkout-core-'));
807
+ const inst = mkdtempSync(join(tmpdir(), 'w3-checkout-inst-'));
808
+ mkdirSync(join(core, '.claude', 'skills'), { recursive: true });
809
+ writeFileSync(join(core, '.claude', 'settings.json'), JSON.stringify({
810
+ permissions: { allow: ['Bash(node scripts/gds/claim.js:*)', 'Bash(node scripts/gds/api.js:*)', 'Bash(gh pr list:*)'] },
811
+ }));
812
+ const res = m.materializeClaude({ coreRoot: core, instanceDir: inst, dryRun: false });
813
+ assert.equal(res.settings, true);
814
+ const allow = JSON.parse(readFileSync(join(inst, '.claude', 'settings.json'), 'utf8')).permissions.allow;
815
+ assert.deepEqual(allow, ['Bash(bongos claim:*)', 'Bash(bongos exec scripts/gds/api.js:*)', 'Bash(gh pr list:*)']);
816
+ for (const rule of allow) assert.ok(m.STARTER_ALLOW.includes(rule), `${rule} is the starter's spelling too — one form, two sources`);
817
+ rmSync(core, { recursive: true, force: true });
818
+ rmSync(inst, { recursive: true, force: true });
819
+ });
820
+
765
821
  t("an instance's OWN settings.json is never clobbered", () => {
766
822
  const core = mkdtempSync(join(tmpdir(), 'w3-keep-core-'));
767
823
  const inst = mkdtempSync(join(tmpdir(), 'w3-keep-inst-'));