@bongos/core 1.19.315 → 1.19.317

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.
Files changed (38) hide show
  1. package/.bongos-core.json +104 -29
  2. package/.claude/skills/merge-mode/SKILL.md +16 -0
  3. package/.claude/skills/planning-session/SKILL.md +10 -0
  4. package/modules/lifecycle/db-analytics.js +719 -0
  5. package/modules/lifecycle/db-claim-reads.js +165 -0
  6. package/modules/lifecycle/db-claims.js +934 -0
  7. package/modules/lifecycle/db-deps-criteria.js +441 -0
  8. package/modules/lifecycle/db-goals.js +763 -0
  9. package/modules/lifecycle/db-grade.js +233 -0
  10. package/modules/lifecycle/db-overrides.js +181 -0
  11. package/modules/lifecycle/db-rank-authz.js +446 -0
  12. package/modules/lifecycle/db-shared.js +115 -0
  13. package/modules/lifecycle/db-ship.js +994 -0
  14. package/modules/lifecycle/db-tasks.js +810 -0
  15. package/modules/lifecycle/db-versions.js +118 -0
  16. package/modules/lifecycle/db.js +167 -5564
  17. package/package-lock.json +2 -2
  18. package/package.json +1 -1
  19. package/scripts/gds/coreB-carve-proof.sh +18 -9
  20. package/scripts/gds/fitness.js +35 -27
  21. package/scripts/gds/identity-strip.js +75 -0
  22. package/scripts/gds/preflight.js +25 -2
  23. package/scripts/gds/provision.js +7 -3
  24. package/scripts/gds/skill-preflight.js +336 -0
  25. package/src/module-api.js +5 -1
  26. package/tests/auto_satisfy_criteria.mjs +3 -2
  27. package/tests/dependencies_migration.mjs +3 -2
  28. package/tests/fitness.mjs +43 -0
  29. package/tests/goal_abuse_matrix.mjs +3 -2
  30. package/tests/goal_advisory.mjs +3 -2
  31. package/tests/government_claim_eligibility.mjs +3 -1
  32. package/tests/government_rank_sync.mjs +9 -2
  33. package/tests/helpers.mjs +19 -0
  34. package/tests/migration_allocation.mjs +3 -1
  35. package/tests/publish_reconciler.mjs +3 -1
  36. package/tests/rank_gate.mjs +3 -1
  37. package/tests/reward_gate.mjs +3 -1
  38. package/tests/skill_preflight.mjs +251 -0
@@ -0,0 +1,251 @@
1
+ // tests/skill_preflight.mjs — G03, task 1003167, goal 1000077, criterion
2
+ // guards-skill-declares-machine.
3
+ //
4
+ // THE INCIDENT. /merge-mode states in its own prose that it assumes the Archon's
5
+ // Mac or the droplet. It was run on a dev box anyway — and ship.js ALREADY knew,
6
+ // because strandNextStep() tells a box "/merge-mode is NOT available here". The
7
+ // knowledge existed in two places and neither stopped the run: prose cannot
8
+ // refuse, and the one executable copy sat on a different code path.
9
+ //
10
+ // So these tests care about two things: that the preflight actually REFUSES, and
11
+ // that the scan behind the fitness check does not cry wolf. Both false-positive
12
+ // classes below were real defects in my own first drafts.
13
+ import { strict as assert } from 'node:assert';
14
+ import { test } from 'node:test';
15
+ import { createRequire } from 'node:module';
16
+
17
+ const require = createRequire(import.meta.url);
18
+ const sp = require('../scripts/gds/skill-preflight.js');
19
+
20
+ // ---- the declaration ------------------------------------------------------
21
+ test('parseRequires reads the inline form', () => {
22
+ const r = sp.parseRequires('---\nname: x\nrequires: [gh, main-checkout]\n---\nbody');
23
+ assert.deepEqual(r.requires, ['gh', 'main-checkout']);
24
+ assert.equal(r.declared, true);
25
+ });
26
+
27
+ test('parseRequires reads the dash-list form', () => {
28
+ const r = sp.parseRequires('---\nname: x\nrequires:\n - gh\n - tty\n---\nbody');
29
+ assert.deepEqual(r.requires, ['gh', 'tty']);
30
+ });
31
+
32
+ test('no requires: is "declared nothing", NOT "declared an empty list"', () => {
33
+ // The fitness check needs to tell those apart.
34
+ const r = sp.parseRequires('---\nname: x\n---\nbody');
35
+ assert.equal(r.declared, false);
36
+ assert.deepEqual(r.requires, []);
37
+ });
38
+
39
+ test('a malformed requires: is an ERROR, not silently zero requirements', () => {
40
+ // Reporting zero would read as "declared, needs nothing" — a scan that finds
41
+ // nothing must never be indistinguishable from a clean pass.
42
+ const r = sp.parseRequires('---\nname: x\nrequires: gh\n---\nbody');
43
+ assert.ok(r.error, 'a scalar requires: must be flagged');
44
+ assert.equal(r.declared, true);
45
+ });
46
+
47
+ // ---- the scan must not cry wolf -------------------------------------------
48
+ test('PROSE that names a command is not an instruction to run it', () => {
49
+ // dev/SKILL.md FORBIDS `git push origin main`. An earlier draft flagged it for
50
+ // saying so — the scan read code spans and prose alike.
51
+ const md = '---\nname: dev\n---\n- never run raw `git push origin main` or `~/deploy.sh`; that is Bongos\'s job.\n';
52
+ assert.deepEqual(sp.inferRequired(md), [], 'a prohibition must not imply a requirement');
53
+ });
54
+
55
+ test('a FENCED command is an instruction, and is picked up', () => {
56
+ const md = '---\nname: x\n---\n```bash\nnode scripts/gds/push-main.js\n```\n';
57
+ assert.deepEqual(sp.inferRequired(md), ['push-credential']);
58
+ });
59
+
60
+ test('a shell COMMENT inside a fence is discussion, not an instruction', () => {
61
+ const md = '---\nname: x\n---\n```bash\n# node scripts/gds/push-main.js is the sanctioned push\necho hi\n```\n';
62
+ assert.deepEqual(sp.inferRequired(md), []);
63
+ });
64
+
65
+ test('"through" does not match the gh signal', () => {
66
+ // `gh ` is a substring of "throu(gh )". The first draft flagged
67
+ // priority-session for a comment containing the word "through".
68
+ // NOT in a comment: comment-stripping would remove it and the boundary would
69
+ // never be exercised. The first version of this test made exactly that mistake
70
+ // and stayed green when the boundary was deleted.
71
+ const md = '---\nname: x\n---\n```bash\necho "routed through the gateway"\n```\n';
72
+ assert.deepEqual(sp.inferRequired(md), [], 'a word containing "gh " is not the gh CLI');
73
+ const inComment = '---\nname: x\n---\n```bash\n# API through it rather than re-deriving the token\necho ok\n```\n';
74
+ assert.deepEqual(sp.inferRequired(inComment), [], 'and a comment is discussion regardless');
75
+ const real = '---\nname: y\n---\n```bash\ngh pr view 12 --json state\n```\n';
76
+ assert.deepEqual(sp.inferRequired(real), ['gh'], 'the real gh command still matches');
77
+ });
78
+
79
+ test('ssh and the deploy host both imply droplet-ssh', () => {
80
+ for (const cmd of ['ssh -o ConnectTimeout=10 someone@host "~/deploy.sh"', 'ssh someone@host "psql -d x"']) {
81
+ assert.deepEqual(sp.inferRequired(`---\nname: x\n---\n\`\`\`bash\n${cmd}\n\`\`\`\n`), ['droplet-ssh'], cmd);
82
+ }
83
+ });
84
+
85
+ // ---- the refusal ----------------------------------------------------------
86
+ const caps = {
87
+ present: { what: 'a present thing', probe: () => true, missing: 'absent' },
88
+ absent: { what: 'an absent thing', probe: () => false, missing: 'go get it' },
89
+ unknowable: { what: 'an unprovable thing', probe: () => null, missing: 'unreachable' },
90
+ thrower: { what: 'a probe that dies', probe: () => { throw new Error('boom'); }, missing: 'never printed' },
91
+ };
92
+
93
+ test('a FALSE probe refuses, and names the remedy', () => {
94
+ const r = sp.preflight(['present', 'absent'], caps);
95
+ assert.equal(r.ok, false);
96
+ assert.equal(r.missing.length, 1);
97
+ assert.equal(r.missing[0].name, 'absent');
98
+ assert.match(r.missing[0].why, /go get it/);
99
+ });
100
+
101
+ test('the refusal names ONLY what is missing, not the whole list', () => {
102
+ // The task's wording: name the MISSING capability, not the list. A satisfied
103
+ // capability must not appear in `missing`.
104
+ const r = sp.preflight(['present', 'absent'], caps);
105
+ assert.ok(!r.missing.some((m) => m.name === 'present'));
106
+ });
107
+
108
+ test('a NULL probe warns and does NOT block', () => {
109
+ // Refusing on "could not tell" would block legitimate machines; passing it
110
+ // silently would rebuild the hole. So: warn, proceed.
111
+ const r = sp.preflight(['unknowable'], caps);
112
+ assert.equal(r.ok, true, 'unknown must not refuse');
113
+ assert.equal(r.unknown.length, 1);
114
+ });
115
+
116
+ test('a probe that THROWS degrades to unknown, never to a pass-as-satisfied', () => {
117
+ const r = sp.preflight(['thrower'], caps);
118
+ assert.equal(r.unknown.length, 1);
119
+ assert.equal(r.missing.length, 0);
120
+ });
121
+
122
+ test('an undeclared capability name is caught rather than ignored', () => {
123
+ // A typo in a skill's requires: would otherwise be a silent no-op.
124
+ const r = sp.preflight(['no-such-capability'], caps);
125
+ assert.equal(r.ok, false);
126
+ assert.match(r.missing[0].why, /unknown capability/);
127
+ });
128
+
129
+ // ---- the live tree --------------------------------------------------------
130
+ test('every registry capability has a probe and a remedy sentence', () => {
131
+ for (const [name, cap] of Object.entries(sp.CAPABILITIES)) {
132
+ assert.equal(typeof cap.probe, 'function', `${name} needs a probe`);
133
+ assert.ok(cap.what && cap.missing, `${name} needs what/missing text`);
134
+ assert.ok(cap.missing.length > 40, `${name}'s remedy must be actionable, not a label`);
135
+ }
136
+ });
137
+
138
+ test('the live tree passes the declare-check', () => {
139
+ const r = sp.checkOpsSkillsDeclareMachine();
140
+ assert.equal(r.hardFail, false, `unexpected:\n ${r.violations.join('\n ')}`);
141
+ });
142
+
143
+ test('merge-mode really declares the machine it needs', () => {
144
+ // The skill at the centre of the incident.
145
+ const r = sp.preflightSkill('merge-mode', caps);
146
+ assert.ok(r.requires.includes('main-checkout'));
147
+ assert.ok(r.requires.includes('push-credential'));
148
+ });
149
+
150
+ test('an UNDECLARED fenced ops command is caught', () => {
151
+ // Injected names, so this exercises the real comparison rather than
152
+ // short-circuiting on an empty enumeration — the first version of this test
153
+ // passed a bad dir and therefore proved nothing about the undeclared path.
154
+ const r = sp.checkOpsSkillsDeclareMachine({
155
+ names: ['rogue'],
156
+ read: () => '---\nname: rogue\n---\n```bash\nnode scripts/gds/push-main.js\nssh me@host "~/deploy.sh"\n```\n',
157
+ });
158
+ assert.equal(r.hardFail, true, 'a skill fencing a main-push with no declaration must fail');
159
+ const text = r.violations.join('\n');
160
+ assert.match(text, /push-credential/);
161
+ assert.match(text, /droplet-ssh/);
162
+ assert.match(text, /requires:/, 'the violation must name the remedy');
163
+ });
164
+
165
+ test('a skill that DOES declare its fenced commands passes', () => {
166
+ const r = sp.checkOpsSkillsDeclareMachine({
167
+ names: ['good'],
168
+ read: () => '---\nname: good\nrequires: [push-credential]\n---\n```bash\nnode scripts/gds/skill-preflight.js good\nnode scripts/gds/push-main.js\n```\n',
169
+ });
170
+ assert.equal(r.hardFail, false, r.violations.join('\n'));
171
+ });
172
+
173
+ test('declaring MORE than the fences imply is allowed', () => {
174
+ // A human knows things the scan cannot see; punishing over-declaration would
175
+ // train people to declare less.
176
+ const r = sp.checkOpsSkillsDeclareMachine({
177
+ names: ['careful'],
178
+ read: () => '---\nname: careful\nrequires: [gh, tty, main-checkout]\n---\nRun `node scripts/gds/skill-preflight.js careful` first.\n',
179
+ });
180
+ assert.equal(r.hardFail, false, r.violations.join('\n'));
181
+ });
182
+
183
+ test('a declared capability that is not in the registry is caught', () => {
184
+ const r = sp.checkOpsSkillsDeclareMachine({
185
+ names: ['typo'],
186
+ read: () => '---\nname: typo\nrequires: [man-checkout]\n---\nbody\n',
187
+ });
188
+ assert.equal(r.hardFail, true);
189
+ assert.match(r.violations.join('\n'), /unknown capability "man-checkout"/);
190
+ });
191
+
192
+ test('an empty skills dir FAILS rather than reporting all-clear', () => {
193
+ const r = sp.checkOpsSkillsDeclareMachine({ dir: '/definitely/not/here' });
194
+ assert.equal(r.hardFail, true);
195
+ assert.match(r.violations[0], /scan defect/);
196
+ });
197
+
198
+ // ---- the three findings from the first grader pass ------------------------
199
+ test('ghAuthed is memoized — one preflight must not spawn `gh` twice', () => {
200
+ // merge-mode declares BOTH gh and push-credential, and push-credential's probe
201
+ // also consults gh. Unmemoized that was two 15s-timeout subprocesses in one
202
+ // run, and a preflight slow enough to skip is one nobody runs.
203
+ const a = sp.ghAuthed();
204
+ const b = sp.ghAuthed();
205
+ assert.equal(a, b, 'repeat calls must agree');
206
+ assert.equal(typeof a, 'boolean');
207
+ });
208
+
209
+ test('a skill name must be a single path segment', () => {
210
+ // `skill-preflight.js ../../../etc` must not read outside .claude/skills.
211
+ for (const bad of ['../../../etc', '..', '.', 'a/b', '', 'x/../../y']) {
212
+ assert.equal(sp.skillPath(bad), null, `${JSON.stringify(bad)} must be refused`);
213
+ }
214
+ assert.ok(String(sp.skillPath('merge-mode')).endsWith('merge-mode/SKILL.md'.replace('/', require('node:path').sep)));
215
+ });
216
+
217
+ test('a traversal name is refused with a message, not a crash', () => {
218
+ const r = sp.preflightSkill('../../../etc');
219
+ assert.equal(r.ok, false);
220
+ assert.match(r.missing[0].why, /not a skill name/);
221
+ });
222
+
223
+ test('DECLARING without ENFORCING is caught', () => {
224
+ // The gap the grader found in planning-session: a `requires:` with no
225
+ // preflight call is a contract stated where nothing checks it — the same
226
+ // shape as the original bug.
227
+ const r = sp.checkOpsSkillsDeclareMachine({
228
+ names: ['claims-but-never-checks'],
229
+ read: () => '---\nname: x\nrequires: [gh]\n---\nprose only, no preflight call\n',
230
+ });
231
+ assert.equal(r.hardFail, true);
232
+ assert.match(r.violations.join('\n'), /never runs/);
233
+ });
234
+
235
+ test('invoking the preflight anywhere satisfies enforcement — top OR at the step', () => {
236
+ // merge-mode gates at Step 0 (capabilities are preconditions for the whole
237
+ // procedure); planning-session gates at the one step that needs ssh. Both are
238
+ // legitimate, so the check must not demand a particular position.
239
+ const md = '---\nname: x\nrequires: [gh]\n---\nlater on:\n```bash\nnode scripts/gds/skill-preflight.js x\ngh pr view 1 --json state\n```\n';
240
+ const r = sp.checkOpsSkillsDeclareMachine({ names: ['x'], read: () => md });
241
+ assert.equal(r.hardFail, false, r.violations.join('\n'));
242
+ });
243
+
244
+ test('both live declaring skills actually invoke the preflight', () => {
245
+ const r = sp.checkOpsSkillsDeclareMachine();
246
+ assert.equal(r.hardFail, false, r.violations.join('\n'));
247
+ for (const name of ['merge-mode', 'planning-session']) {
248
+ const md = require('node:fs').readFileSync(sp.skillPath(name), 'utf8');
249
+ assert.match(md, /skill-preflight\.js\s+\S/, `${name} must run its own preflight`);
250
+ }
251
+ });