@bongos/core 1.19.841 → 1.19.842

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.841",
6
- "core_contract": "1.19.841",
7
- "source_commit": "fd701dc457a5344486573c53ca1f4efcc1948007",
5
+ "core_version": "1.19.842",
6
+ "core_contract": "1.19.842",
7
+ "source_commit": "ffa8d1ce17675d5981142ca6588ef641d0893058",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-17T18:13:18.546Z",
9
+ "built_at": "2026-09-17T18:21:47.399Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 495,
13
13
  "agent_docs_stubbed": 26,
14
- "functional_verbatim": 2265,
14
+ "functional_verbatim": 2266,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2786,
20
- "tree_sha256": "a54472eaf1c55f1c7f905fb6fd2712a9ab44e8e9f3a731ffba11037c3d9f5b69",
19
+ "file_count": 2787,
20
+ "tree_sha256": "204ee5631e422b90ff1d79a7fde81706ca492bea501801a162421ebd04f6bfdb",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -2577,7 +2577,7 @@
2577
2577
  {
2578
2578
  "path": "docs/module-api-changelog.md",
2579
2579
  "mode": "0000644",
2580
- "sha256": "79b20e6155f002dd63671b994cbbb8e2f269c3634cd213b5695c0de8bb031cc7"
2580
+ "sha256": "033de93b8ea7781edf94b6b1146741c2bde76443ecf7b6c8b1bf47d8919d6bab"
2581
2581
  },
2582
2582
  {
2583
2583
  "path": "docs/modules-contract.md",
@@ -7892,12 +7892,12 @@
7892
7892
  {
7893
7893
  "path": "package-lock.json",
7894
7894
  "mode": "0000644",
7895
- "sha256": "d507a842a2ad14e85f0e5564998ab1288afad232febc358f932736b51fd12bd7"
7895
+ "sha256": "21b80f9aba47da61edcb4a374ad4aad35f2e5c563cccb1daae278b6d892d0255"
7896
7896
  },
7897
7897
  {
7898
7898
  "path": "package.json",
7899
7899
  "mode": "0000644",
7900
- "sha256": "81e581275d29c80dc0c2496d83b2a5317da29e43d65aabf7a49309aed72b1003"
7900
+ "sha256": "61f48c57b02632310e7ba92115fdc6939efe7967f2ee7542fa7b12834f8af6c2"
7901
7901
  },
7902
7902
  {
7903
7903
  "path": "public-docs/index.html",
@@ -9827,7 +9827,7 @@
9827
9827
  {
9828
9828
  "path": "src/module-api.js",
9829
9829
  "mode": "0000644",
9830
- "sha256": "d01a900eabeae11f0d03aa7aff1ea89af23f58a3e01c07fc79a4e4ea8b68f4a4"
9830
+ "sha256": "84e310a550189d0d3d86f825cc04d61d81e0c0dc78428056661357a1a5076e74"
9831
9831
  },
9832
9832
  {
9833
9833
  "path": "src/module-loader/catalog.js",
@@ -9969,6 +9969,11 @@
9969
9969
  "mode": "0000644",
9970
9970
  "sha256": "919ca0ea3fe5f78a194781f6b634b9da23212073cf0c7cbe8ae36a65cc3fecdb"
9971
9971
  },
9972
+ {
9973
+ "path": "tests/agents_roster.mjs",
9974
+ "mode": "0000644",
9975
+ "sha256": "acc25f4d72cb22719d6977f939b41f9f17e0d102880976699b6ebcda1c64c523"
9976
+ },
9972
9977
  {
9973
9978
  "path": "tests/agents_routes.mjs",
9974
9979
  "mode": "0000644",
@@ -2156,5 +2156,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
2156
2156
  landed since 1.19.839 with no explicit bump. run 35254616836. (task 1002620)
2157
2157
  1.19.841 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2158
2158
  landed since 1.19.840 with no explicit bump. run 35257419225. (task 1002620)
2159
+ 1.19.842 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2160
+ landed since 1.19.841 with no explicit bump. run 35258288930. (task 1002620)
2159
2161
  ---------------------------------------------------------------------------
2160
2162
  ```
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.841",
3
+ "version": "1.19.842",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.841",
9
+ "version": "1.19.842",
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.841",
3
+ "version": "1.19.842",
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
@@ -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.841'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
74
+ const CORE_VERSION = '1.19.842'; // 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');
@@ -0,0 +1,132 @@
1
+ // tests/agents_roster.mjs — the SHIPPED roster in `.claude/agents/` (task
2
+ // 1002496, goal 1000095).
3
+ //
4
+ // The definitions are prose files, so nothing about them is checked by the type
5
+ // system, and the sync that imports them is fail-open at deploy (a bad file makes
6
+ // the registry smaller, never aborts the deploy — tests/agents_sync.mjs pins
7
+ // that). The consequence is that a malformed definition is INVISIBLE until
8
+ // someone goes looking in the registry for an agent that quietly never imported.
9
+ // This file is the guard: every roster file must survive the REAL parser and the
10
+ // REAL validator, not a hand-built object that resembles one.
11
+ //
12
+ // Tested at the round-trip altitude on purpose. A test over parseAgentFile alone
13
+ // passes on a key the validator later drops, which is exactly the defect task
14
+ // 1004007 records: a top-level `touches:` validates ok and is silently normalized
15
+ // away. Parse and validate together, or the test agrees with the bug.
16
+ //
17
+ // In tests/ rather than modules/agents/tests/ for the same reason as
18
+ // tests/agents_sync.mjs: the module is default:false and module-local tests are
19
+ // discovered only when the module is ENABLED, so they would never run here.
20
+ //
21
+ // Run: node tests/agents_roster.mjs
22
+
23
+ import { strict as assert } from 'node:assert';
24
+ import { createRequire } from 'node:module';
25
+ import fs from 'node:fs';
26
+ import path from 'node:path';
27
+
28
+ const require = createRequire(import.meta.url);
29
+ const sync = require('../scripts/gds/agents-sync.js');
30
+ const validate = require('../modules/agents/lib/validate.js');
31
+
32
+ const validateDefinition = validate.validateAgentDefinition || validate;
33
+
34
+ let passed = 0;
35
+ let failed = 0;
36
+ function t(name, fn) {
37
+ try { fn(); console.log(` PASS ${name}`); passed += 1; }
38
+ catch (err) { console.log(` FAIL ${name}\n ${err.message}`); failed += 1; }
39
+ }
40
+
41
+ const ROSTER_DIR = new URL('../.claude/agents/', import.meta.url);
42
+ const files = fs.readdirSync(ROSTER_DIR)
43
+ .filter((f) => f.endsWith('.md'))
44
+ .sort();
45
+
46
+ // Parse once, reuse across the cases below. The name comes from the FILENAME,
47
+ // which is how agents-sync identifies a file-sourced definition.
48
+ const roster = files.map((f) => {
49
+ const name = f.replace(/\.md$/, '');
50
+ const text = fs.readFileSync(new URL(f, ROSTER_DIR), 'utf8');
51
+ return { name, file: f, candidate: sync.parseAgentFile(text, { name }) };
52
+ });
53
+
54
+ console.log('every shipped definition survives parse + validate:');
55
+
56
+ // An empty roster would pass every per-file assertion below by vacuity — the
57
+ // failure mode where a green suite means "nothing ran". Pin the floor.
58
+ t('the roster is not empty', () => {
59
+ assert.ok(roster.length > 0, '.claude/agents/ holds no definitions — a vacuous pass');
60
+ });
61
+
62
+ for (const { name, file, candidate } of roster) {
63
+ t(`${file} validates against the real validator`, () => {
64
+ // authorRank archon so a scoped definition is judged on its shape rather
65
+ // than refused for rank; allowedModules mirrors what the sync passes.
66
+ const verdict = validateDefinition(candidate, {
67
+ authorRank: 'archon',
68
+ allowedModules: ['agents'],
69
+ protectedModules: [],
70
+ });
71
+ assert.ok(
72
+ verdict.ok,
73
+ `${file} would not import: ${JSON.stringify(verdict.errors)}`,
74
+ );
75
+ });
76
+
77
+ t(`${file} carries a persona worth sending`, () => {
78
+ // The BODY is the persona, and it is sent to a paid model on every fire. A
79
+ // file whose frontmatter parsed but whose body did not is the quiet failure
80
+ // this catches — it validates as a string and says nothing.
81
+ const persona = String(candidate.persona || '');
82
+ assert.ok(persona.length > 200, `${file}: persona is ${persona.length} chars — too thin to be a role prompt`);
83
+ assert.match(persona, new RegExp(name.replace(/-/g, '[- ]')), `${file}: the persona never names the agent it defines`);
84
+ });
85
+ }
86
+
87
+ console.log('\nthe on-demand roster this task shipped:');
88
+
89
+ t('historian, planner and onboarding-buddy are all present', () => {
90
+ const names = roster.map((r) => r.name);
91
+ for (const want of ['historian', 'planner', 'onboarding-buddy']) {
92
+ assert.ok(names.includes(want), `${want} is missing from the roster`);
93
+ }
94
+ });
95
+
96
+ t('each of the three is on-demand', () => {
97
+ for (const want of ['historian', 'planner', 'onboarding-buddy']) {
98
+ const entry = roster.find((r) => r.name === want);
99
+ assert.equal(entry.candidate.trigger_type, 'on-demand',
100
+ `${want} must be on-demand — an event trigger here would fire on ships nobody asked it about`);
101
+ }
102
+ });
103
+
104
+ console.log('\nthe trap an event definition would walk into:');
105
+
106
+ // TRIPWIRE for task 1004007, and the reason it is HERE rather than in that task:
107
+ // this directory is where the mistake gets made. A file cannot express
108
+ // `trigger_spec.touches` today (agents-sync.js parses a flat frontmatter and
109
+ // folds only `event:` into the spec), and event-router.js:168 reads an absent
110
+ // filter as FIRES ON EVERY SHIP at roughly $0.90 a fire. So the first
111
+ // file-authored event agent is a standing bill, silently.
112
+ //
113
+ // This reds the moment someone adds one, which is the moment the warning is
114
+ // worth something. Once 1004007 lands, tighten it to assert the filter SURVIVED
115
+ // into trigger_spec rather than refusing event definitions outright.
116
+ t('no file-authored event agent until a file can declare its filter', () => {
117
+ const eventBacked = roster.filter((r) => r.candidate.trigger_type === 'event');
118
+ for (const entry of eventBacked) {
119
+ const spec = entry.candidate.trigger_spec;
120
+ const globs = spec && Array.isArray(spec.touches) ? spec.touches
121
+ : spec && Array.isArray(spec.touches_globs) ? spec.touches_globs
122
+ : [];
123
+ assert.ok(
124
+ globs.length > 0,
125
+ `${entry.file} is an event definition with no touches filter, so it would fire on EVERY ship (~$0.90 each). `
126
+ + 'A file cannot declare one until task 1004007 lands — see tests/agents_roster.mjs.',
127
+ );
128
+ }
129
+ });
130
+
131
+ console.log(`\nagents_roster: ${passed} passed, ${failed} failed`);
132
+ process.exit(failed ? 1 : 0);