@bongos/core 1.19.1011 → 1.19.1012
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 +11 -11
- package/docs/module-api-changelog.md +2 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/gen-file-map.js +29 -12
- package/src/module-api.js +1 -1
- package/tests/file_map.mjs +35 -3
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.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.1012",
|
|
6
|
+
"core_contract": "1.19.1012",
|
|
7
|
+
"source_commit": "67c8c7ea6e9225abe84f04ee97d072e125b78671",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-24T22:
|
|
9
|
+
"built_at": "2026-09-24T22:32:49.600Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 523,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 2975,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "43775a7c655de35e08a0b90ecee94c1ccad0cc2e460df21d0b3b5d463e6fb7e2",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2727,7 +2727,7 @@
|
|
|
2727
2727
|
{
|
|
2728
2728
|
"path": "docs/module-api-changelog.md",
|
|
2729
2729
|
"mode": "0000644",
|
|
2730
|
-
"sha256": "
|
|
2730
|
+
"sha256": "6a78c943439f5d8b591f285c69db81d7a468e4e18656d04330685885ed2cbbd8"
|
|
2731
2731
|
},
|
|
2732
2732
|
{
|
|
2733
2733
|
"path": "docs/modules-contract.md",
|
|
@@ -8242,12 +8242,12 @@
|
|
|
8242
8242
|
{
|
|
8243
8243
|
"path": "package-lock.json",
|
|
8244
8244
|
"mode": "0000644",
|
|
8245
|
-
"sha256": "
|
|
8245
|
+
"sha256": "b26e2dff351ba48f806de1851a00dc5657a52ceb0f6c2ec66bf0b407f074ca49"
|
|
8246
8246
|
},
|
|
8247
8247
|
{
|
|
8248
8248
|
"path": "package.json",
|
|
8249
8249
|
"mode": "0000644",
|
|
8250
|
-
"sha256": "
|
|
8250
|
+
"sha256": "05dadaedb82b7aac68954714ab5dba673cc5e19adc0bea7109c2951bfe8692c3"
|
|
8251
8251
|
},
|
|
8252
8252
|
{
|
|
8253
8253
|
"path": "public-docs/index.html",
|
|
@@ -8897,7 +8897,7 @@
|
|
|
8897
8897
|
{
|
|
8898
8898
|
"path": "scripts/gds/gen-file-map.js",
|
|
8899
8899
|
"mode": "0000644",
|
|
8900
|
-
"sha256": "
|
|
8900
|
+
"sha256": "38505bcbacd92114abbbd06cbc41bc841e1269cb11ebaace395f3ad22104ba1a"
|
|
8901
8901
|
},
|
|
8902
8902
|
{
|
|
8903
8903
|
"path": "scripts/gds/gen-freshness.js",
|
|
@@ -10292,7 +10292,7 @@
|
|
|
10292
10292
|
{
|
|
10293
10293
|
"path": "src/module-api.js",
|
|
10294
10294
|
"mode": "0000644",
|
|
10295
|
-
"sha256": "
|
|
10295
|
+
"sha256": "d575c9f71dfced09c23cf793d5e0d048d240621a588e65f375d47bf96cd6e006"
|
|
10296
10296
|
},
|
|
10297
10297
|
{
|
|
10298
10298
|
"path": "src/module-loader/catalog.js",
|
|
@@ -11562,7 +11562,7 @@
|
|
|
11562
11562
|
{
|
|
11563
11563
|
"path": "tests/file_map.mjs",
|
|
11564
11564
|
"mode": "0000644",
|
|
11565
|
-
"sha256": "
|
|
11565
|
+
"sha256": "b4bdd09b0c11bb8d12677b48d1758603d3bc210511b090d7cc6de2f6d2b37cc0"
|
|
11566
11566
|
},
|
|
11567
11567
|
{
|
|
11568
11568
|
"path": "tests/filing_abuse_matrix.mjs",
|
|
@@ -2496,5 +2496,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2496
2496
|
landed since 1.19.1009 with no explicit bump. run 36064558803. (task 1002620)
|
|
2497
2497
|
1.19.1011 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2498
2498
|
landed since 1.19.1010 with no explicit bump. run 36066617514. (task 1002620)
|
|
2499
|
+
1.19.1012 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2500
|
+
landed since 1.19.1011 with no explicit bump. run 36067980398. (task 1002620)
|
|
2499
2501
|
---------------------------------------------------------------------------
|
|
2500
2502
|
```
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.1012",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.1012",
|
|
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.
|
|
3
|
+
"version": "1.19.1012",
|
|
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",
|
|
@@ -91,16 +91,31 @@ function materializedNames(absDir) { return new Set(Object.keys(readModuleSkills
|
|
|
91
91
|
// The subdirs of `relDir` holding at least one TRACKED file (task 1004213). An untracked one is the
|
|
92
92
|
// builder's own — a locally-installed plugin skill, or the empty husk a plugin extract leaves — and
|
|
93
93
|
// listing it would publish one machine's tooling into a shared doc on every post-merge regen.
|
|
94
|
-
// null when `root` is not the top of a git work tree (a packaged install, ADR 0108 §1)
|
|
94
|
+
// tracked: null when `root` is not the top of a git work tree (a packaged install, ADR 0108 §1).
|
|
95
|
+
// gitError: git COULD not answer (task 1004222) — a safe.directory refusal, git off PATH, a broken
|
|
96
|
+
// GIT_DIR, ENOBUFS. That also falls back to the disk listing, but loudly: main() warns and fails --check.
|
|
97
|
+
const GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
98
|
+
// Discovery's own refusal. A broken GIT_DIR also exits 128 "not a git repository: '<dir>'", without this tail.
|
|
99
|
+
const NOT_A_REPO = /not a git repository \(or any (of the )?parent/;
|
|
95
100
|
function trackedSubdirs(root, relDir) {
|
|
96
|
-
|
|
101
|
+
// LC_ALL=C: the refusal is matched by its text, which a translated git would not print.
|
|
102
|
+
const git = (args) => execFileSync('git', args, {
|
|
103
|
+
cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: GIT_MAX_BUFFER, env: { ...process.env, LC_ALL: 'C' },
|
|
104
|
+
});
|
|
97
105
|
try {
|
|
98
|
-
if (git(['rev-parse', '--show-prefix']).trim() !== '') return null;
|
|
99
|
-
return
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
if (git(['rev-parse', '--show-prefix']).trim() !== '') return { tracked: null, gitError: null };
|
|
107
|
+
return {
|
|
108
|
+
tracked: new Set(git(['ls-files', '-z', '--', relDir]).split('\0')
|
|
109
|
+
.map((p) => p.slice(relDir.length + 1).split('/'))
|
|
110
|
+
.filter((segs) => segs.length > 1)
|
|
111
|
+
.map((segs) => segs[0])),
|
|
112
|
+
gitError: null,
|
|
113
|
+
};
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const stderr = String(err.stderr || '').trim();
|
|
116
|
+
if (err.status === 128 && NOT_A_REPO.test(stderr)) return { tracked: null, gitError: null };
|
|
117
|
+
return { tracked: null, gitError: stderr.split('\n')[0] || err.code || err.message };
|
|
118
|
+
}
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
// Immediate subdirectories of an absolute dir, sorted by name (deterministic); materialised
|
|
@@ -120,7 +135,7 @@ function listSubdirs(absDir) {
|
|
|
120
135
|
function buildSection(section, notes) {
|
|
121
136
|
const absDir = path.join(REPO_ROOT, section.dir);
|
|
122
137
|
const present = listSubdirs(absDir);
|
|
123
|
-
const tracked = trackedSubdirs(REPO_ROOT, section.dir);
|
|
138
|
+
const { tracked, gitError } = trackedSubdirs(REPO_ROOT, section.dir);
|
|
124
139
|
const names = tracked ? present.filter((n) => tracked.has(n)) : present;
|
|
125
140
|
const sectionNotes = (notes && notes[section.notesKey]) || {};
|
|
126
141
|
const entries = names.map((name) => {
|
|
@@ -135,7 +150,7 @@ function buildSection(section, notes) {
|
|
|
135
150
|
// A note is a ghost only when its dir is gone from disk — one not yet `git add`ed is not.
|
|
136
151
|
const onDisk = new Set(present);
|
|
137
152
|
const stale = Object.keys(sectionNotes).filter((k) => !onDisk.has(k)).map((k) => `${section.notesKey}.${k}`);
|
|
138
|
-
return { ...section, absDir, entries, missing, stale };
|
|
153
|
+
return { ...section, absDir, entries, missing, stale, gitError };
|
|
139
154
|
}
|
|
140
155
|
|
|
141
156
|
function buildModel() {
|
|
@@ -244,6 +259,7 @@ function computeWrites() {
|
|
|
244
259
|
const model = buildModel();
|
|
245
260
|
const missing = model.flatMap((m) => m.missing);
|
|
246
261
|
const stale = model.flatMap((m) => m.stale);
|
|
262
|
+
const gitErrors = [...new Set(model.map((m) => m.gitError).filter(Boolean))];
|
|
247
263
|
const writes = [];
|
|
248
264
|
let markersMissing = [];
|
|
249
265
|
let mapText = '';
|
|
@@ -258,7 +274,7 @@ function computeWrites() {
|
|
|
258
274
|
mapText = next; // coverage reads the POST-generation text, so a regen never changes the verdict
|
|
259
275
|
}
|
|
260
276
|
const modules = moduleCoverage(mapText);
|
|
261
|
-
return { model, writes, missing, stale, markersMissing, modules };
|
|
277
|
+
return { model, writes, missing, stale, gitErrors, markersMissing, modules };
|
|
262
278
|
}
|
|
263
279
|
|
|
264
280
|
function main() {
|
|
@@ -267,7 +283,7 @@ function main() {
|
|
|
267
283
|
process.stdout.write(JSON.stringify(buildModel(), null, 2) + '\n');
|
|
268
284
|
return;
|
|
269
285
|
}
|
|
270
|
-
const { writes, missing, stale, markersMissing, modules } = computeWrites();
|
|
286
|
+
const { writes, missing, stale, gitErrors, markersMissing, modules } = computeWrites();
|
|
271
287
|
|
|
272
288
|
// A missing note (dir without a note) or a stale note (note without a dir) is a hard failure in
|
|
273
289
|
// BOTH modes: in --check it fails CI; in write mode we still report it (and render a visible
|
|
@@ -275,6 +291,7 @@ function main() {
|
|
|
275
291
|
const problems = [];
|
|
276
292
|
if (missing.length) problems.push(`notes MISSING for: ${missing.join(', ')} — add a one-line note to docs/file-map.notes.json`);
|
|
277
293
|
if (stale.length) problems.push(`notes are STALE (no such dir) — remove from docs/file-map.notes.json: ${stale.join(', ')}`);
|
|
294
|
+
for (const e of gitErrors) problems.push(`git could not list tracked files (${e}) — every dir on disk was listed, untracked plugin installs included; fix git (PATH, safe.directory) and re-run (task 1004222)`);
|
|
278
295
|
if (markersMissing.length) problems.push(`docs/file-map.md is missing generated markers for: ${markersMissing.join(', ')}`);
|
|
279
296
|
if (modules.undocumented.length) problems.push(`modules with NO docs/file-map.md entry: ${modules.undocumented.map((k) => `${MODULES_DIR}/${k}`).join(', ')} — add an entry to the modules/ block of docs/file-map.md (task 1004066)`);
|
|
280
297
|
for (const d of modules.defects) problems.push(`module-coverage SCAN DEFECT — ${d}`);
|
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.
|
|
74
|
+
const CORE_VERSION = '1.19.1012'; // 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');
|
package/tests/file_map.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// (task 1276 / ADR 0066). Mirrors tests/session_index.mjs + tests/repo_map.mjs.
|
|
3
3
|
import assert from 'node:assert/strict';
|
|
4
4
|
import { test } from 'node:test';
|
|
5
|
-
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
6
6
|
import { readFileSync, existsSync, readdirSync, mkdirSync, writeFileSync, rmSync, mkdtempSync } from 'node:fs';
|
|
7
7
|
import { tmpdir } from 'node:os';
|
|
8
8
|
import { createRequire } from 'node:module';
|
|
@@ -90,10 +90,19 @@ function fixtureRoot({ git }) {
|
|
|
90
90
|
}
|
|
91
91
|
return root;
|
|
92
92
|
}
|
|
93
|
-
const skillsSectionAt = (cwd) => JSON.parse(execFileSync(process.execPath,
|
|
93
|
+
const skillsSectionAt = (cwd, env) => JSON.parse(execFileSync(process.execPath,
|
|
94
94
|
['-e', `process.stdout.write(JSON.stringify(require(${JSON.stringify(GEN)}).buildModel()))`],
|
|
95
|
-
{ cwd, encoding: 'utf8' })).find((s) => s.id === 'skills');
|
|
95
|
+
{ cwd, encoding: 'utf8', env })).find((s) => s.id === 'skills');
|
|
96
96
|
const skillNamesAt = (cwd) => skillsSectionAt(cwd).entries.map((e) => e.name);
|
|
97
|
+
function genAt(cwd, args, env) {
|
|
98
|
+
const r = spawnSync(process.execPath, [GEN, ...args], { cwd, encoding: 'utf8', env });
|
|
99
|
+
return { code: r.status, stderr: r.stderr };
|
|
100
|
+
}
|
|
101
|
+
// Two ways git fails to answer inside a real work tree (task 1004222): no git on PATH (ENOENT), and a
|
|
102
|
+
// GIT_DIR naming nothing — exit 128 like "not a repository", but not discovery's own refusal.
|
|
103
|
+
// PATH is dropped under every casing: Windows spells it `Path`, and a copy of both keys is ambiguous.
|
|
104
|
+
const withoutGit = (root) => ({ ...Object.fromEntries(Object.entries(process.env).filter(([k]) => k.toUpperCase() !== 'PATH')), PATH: path.join(root, 'no-bin') });
|
|
105
|
+
const brokenGitDir = (root) => ({ ...process.env, GIT_DIR: path.join(root, 'no-such-git-dir') });
|
|
97
106
|
|
|
98
107
|
test('--check FAILS (exit 2) when a new tracked skill has no note — a skill can no longer land undescribed', () => {
|
|
99
108
|
const root = fixtureRoot({ git: true });
|
|
@@ -128,15 +137,38 @@ test('outside a git work tree (a packaged install) every dir on disk is still li
|
|
|
128
137
|
const nested = path.join(parent, 'instance');
|
|
129
138
|
try {
|
|
130
139
|
assert.deepEqual(skillNamesAt(root), ['empty-husk', 'local-plugin', 'new-skill']);
|
|
140
|
+
// Silently: not being in a repository is the packaged install's normal state, not a git failure.
|
|
141
|
+
assert.equal(skillsSectionAt(root).gitError, null);
|
|
142
|
+
assert.doesNotMatch(genAt(root, ['--check']).stderr, /git could not/);
|
|
131
143
|
// A root that is a SUBDIR of some repo is not that repo's top: its files are not the repo's to judge.
|
|
132
144
|
mkdirSync(path.join(nested, '.claude', 'skills', 'inner'), { recursive: true });
|
|
133
145
|
assert.deepEqual(skillNamesAt(nested), ['inner']);
|
|
146
|
+
assert.equal(skillsSectionAt(nested).gitError, null);
|
|
134
147
|
} finally {
|
|
135
148
|
rmSync(root, { recursive: true, force: true });
|
|
136
149
|
rmSync(parent, { recursive: true, force: true });
|
|
137
150
|
}
|
|
138
151
|
});
|
|
139
152
|
|
|
153
|
+
test('a git failure inside a work tree is NOT "not a repository" — it warns in write mode and fails --check', () => {
|
|
154
|
+
const root = fixtureRoot({ git: true });
|
|
155
|
+
try {
|
|
156
|
+
for (const [shape, env, named] of [['git missing from PATH', withoutGit(root), /ENOENT/], ['GIT_DIR naming nothing', brokenGitDir(root), /not a git repository: /]]) {
|
|
157
|
+
assert.match(skillsSectionAt(root, env).gitError || '', named, `${shape}: the model names the git error`);
|
|
158
|
+
const check = genAt(root, ['--check'], env);
|
|
159
|
+
assert.equal(check.code, 2, `${shape}: --check must fail rather than pass on an unfiltered listing`);
|
|
160
|
+
assert.match(check.stderr, /gen-file-map --check: git could not list tracked files/, shape);
|
|
161
|
+
const write = genAt(root, [], env);
|
|
162
|
+
assert.equal(write.code, 2, `${shape}: write mode exits non-zero`);
|
|
163
|
+
assert.match(write.stderr, /gen-file-map: WARN git could not list tracked files/, shape);
|
|
164
|
+
}
|
|
165
|
+
// The same root with git answering carries no git error: the failure above is the env, not the fixture.
|
|
166
|
+
assert.equal(skillsSectionAt(root).gitError, null);
|
|
167
|
+
} finally {
|
|
168
|
+
rmSync(root, { recursive: true, force: true });
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
140
172
|
test('generation is deterministic + idempotent (a second run is a no-op)', () => {
|
|
141
173
|
const r1 = run([]);
|
|
142
174
|
assert.equal(r1.code, 0);
|