@bongos/core 1.19.919 → 1.19.921
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 +73 -53
- package/.claude/skills/grade-audit/SKILL.md +9 -0
- package/docs/adr/0320-an-empty-diff-is-not-an-ungraded-diff.md +159 -0
- package/docs/adr/README.md +1 -0
- package/docs/module-api-changelog.md +4 -0
- package/modules/grading/grader-no-artifact.js +347 -0
- package/modules/grading/grader.js +6 -0
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/run-unit-tests.js +17 -1
- package/scripts/gds/ship-flow.js +54 -7
- package/scripts/gds/ship-grade-steps.js +43 -5
- package/scripts/gds/ship-grade.js +36 -0
- package/src/bongos/routes/me.js +9 -1
- package/src/module-api.js +1 -1
- package/tests/core_update_banner.mjs +28 -0
- package/tests/git_merge_regen.mjs +87 -3
- package/tests/grader_no_artifact.mjs +360 -0
- package/tests/grader_prompt_fencing.mjs +46 -0
- package/tests/nav_permission_atoms.mjs +110 -0
- package/tests/no_artifact_escalation.mjs +13 -3
- package/tests/skip_is_not_pass.mjs +91 -1
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
import assert from 'node:assert/strict';
|
|
29
29
|
import { test } from 'node:test';
|
|
30
30
|
import { execFileSync } from 'node:child_process';
|
|
31
|
+
import fs from 'node:fs';
|
|
32
|
+
import os from 'node:os';
|
|
31
33
|
import path from 'node:path';
|
|
32
34
|
import { fileURLToPath } from 'node:url';
|
|
33
35
|
import { countSkips } from '../scripts/gds/run-unit-tests.js';
|
|
@@ -43,6 +45,52 @@ const SUITES = [
|
|
|
43
45
|
{ file: 'modules/security/tests/mirror.mjs', skips: 1 },
|
|
44
46
|
];
|
|
45
47
|
|
|
48
|
+
// realSymlinkReason — why the CONTROL run cannot be evaluated here, or null (task 1004112).
|
|
49
|
+
//
|
|
50
|
+
// Every case below that passes `forceNoSymlink: true` is evaluable anywhere: it asks a suite to
|
|
51
|
+
// take its skip path and checks the accounting. But the pair's second case also runs a CONTROL
|
|
52
|
+
// (`forceNoSymlink: false`) and asserts `ran.skipped === 0` — "where symlinks work, nothing is
|
|
53
|
+
// skipped". That carries an unstated precondition: symlinks work HERE.
|
|
54
|
+
//
|
|
55
|
+
// On Windows without Developer Mode they do not. A directory JUNCTION can be created, which is
|
|
56
|
+
// why link cases elsewhere still run and the failure looks selective, but `fs.symlinkSync` refuses
|
|
57
|
+
// with EPERM — so the control run legitimately skips, `ran.skipped` is 1 or 2 rather than 0, and
|
|
58
|
+
// four cases go red over a platform fact nobody claimed.
|
|
59
|
+
//
|
|
60
|
+
// That is a FALSE FAIL, and it is this file's own defect in mirror image: a case that does not
|
|
61
|
+
// apply to the platform, asserted anyway instead of skipped. The shape task 1004051 fixed in
|
|
62
|
+
// tests/quarantine_canonical.mjs, and the inverse of the false PASS in task 1003993 that this file
|
|
63
|
+
// exists to police. The file whose job is skip honesty was inferring its platform instead of
|
|
64
|
+
// asking.
|
|
65
|
+
//
|
|
66
|
+
// So ASK, with the same probe the suites use (mirror.mjs `canSymlink`): try to make a real
|
|
67
|
+
// symlink. Not `process.platform` — the question is a CAPABILITY, and Windows in Developer Mode
|
|
68
|
+
// answers yes while a container without CAP_SYMLINK answers no.
|
|
69
|
+
//
|
|
70
|
+
// Returns a REASON for node:test's skip, never a bare early `return`, which prints as a pass and
|
|
71
|
+
// is precisely the 1003993 defect.
|
|
72
|
+
function realSymlinkReason() {
|
|
73
|
+
// Deliberately ignores BONGOS_TEST_FORCE_NO_SYMLINK: that hook is how this file ASKS a suite to
|
|
74
|
+
// take its skip path, and honouring it here would skip the control run on every box, deleting
|
|
75
|
+
// the coverage instead of gating it.
|
|
76
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'skip-is-not-pass-probe-'));
|
|
77
|
+
const target = path.join(dir, 'probe-target');
|
|
78
|
+
const link = path.join(dir, 'probe-link');
|
|
79
|
+
try {
|
|
80
|
+
fs.writeFileSync(target, 'probe', 'utf8');
|
|
81
|
+
fs.symlinkSync(target, link);
|
|
82
|
+
return null;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return 'this platform cannot create a REAL symlink '
|
|
85
|
+
+ `(${err.code || err.message}), so the control run's own link cases skip too and `
|
|
86
|
+
+ '"where symlinks work, nothing is skipped" cannot be evaluated here. On Windows, '
|
|
87
|
+
+ 'Developer Mode or an elevated shell makes this case run.';
|
|
88
|
+
} finally {
|
|
89
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const NO_REAL_SYMLINK = realSymlinkReason();
|
|
93
|
+
|
|
46
94
|
function runSuite(file, { forceNoSymlink }) {
|
|
47
95
|
const env = { ...process.env, NODE_ENV: 'test' };
|
|
48
96
|
if (forceNoSymlink) env.BONGOS_TEST_FORCE_NO_SYMLINK = '1';
|
|
@@ -65,7 +113,11 @@ for (const { file, skips } of SUITES) {
|
|
|
65
113
|
assert.equal(r.failed, 0, 'a skip is not a failure');
|
|
66
114
|
});
|
|
67
115
|
|
|
68
|
-
|
|
116
|
+
// The only case here that needs a real symlink: it compares the skip run against a CONTROL run
|
|
117
|
+
// in which nothing skips. Gated, not deleted — wherever symlinks work (every CI runner, Linux,
|
|
118
|
+
// macOS, Windows in Developer Mode) it asserts in full.
|
|
119
|
+
test(`${file}: THE BUG — skipped cases no longer inflate the passed count`,
|
|
120
|
+
{ skip: NO_REAL_SYMLINK ?? false }, () => {
|
|
69
121
|
// The heart of it. Under the old code BOTH runs printed the same pass count: the cases
|
|
70
122
|
// that did not run were indistinguishable from the ones that did. If these two ever
|
|
71
123
|
// agree again, the fake pass is back, whatever the summary line claims.
|
|
@@ -96,6 +148,31 @@ for (const { file, skips } of SUITES) {
|
|
|
96
148
|
});
|
|
97
149
|
}
|
|
98
150
|
|
|
151
|
+
// THE SKIP HAS TO JUSTIFY ITSELF, or it is the defect this file polices.
|
|
152
|
+
//
|
|
153
|
+
// The gate above is the dangerous kind of fix: if `realSymlinkReason()` ever returns a reason on a
|
|
154
|
+
// box where symlinks DO work, four cases quietly stop running and the suite still reads green —
|
|
155
|
+
// task 1003993's false pass, reintroduced by the file written to prevent it. A skip is only honest
|
|
156
|
+
// if its stated reason is TRUE.
|
|
157
|
+
//
|
|
158
|
+
// So each half checks the other, and exactly one of them runs on any given box:
|
|
159
|
+
//
|
|
160
|
+
// - where the probe says it CANNOT symlink, the control run must genuinely skip. If the probe is
|
|
161
|
+
// lying, the control run skips nothing and this reds.
|
|
162
|
+
// - where the probe says it CAN, the four gated cases are running, and their own
|
|
163
|
+
// `ran.skipped === 0` is the same assertion from the other side.
|
|
164
|
+
//
|
|
165
|
+
// Neither box can verify the other's branch, which is why the reason is CHECKED rather than
|
|
166
|
+
// trusted: "this platform cannot create a real symlink" is falsifiable right here.
|
|
167
|
+
test('the skip reason is TRUE — a platform that claims it cannot symlink really does skip',
|
|
168
|
+
{ skip: NO_REAL_SYMLINK ? false : 'symlinks work here, so the gated cases are running and assert it themselves' }, () => {
|
|
169
|
+
const ran = runSuite('modules/security/tests/mirror.mjs', { forceNoSymlink: false });
|
|
170
|
+
assert.ok(ran.skipped > 0,
|
|
171
|
+
'realSymlinkReason() claimed this platform cannot create a real symlink, but the control run '
|
|
172
|
+
+ `skipped nothing (${ran.skipped}) — the probe is wrong and it is silently deleting the `
|
|
173
|
+
+ 'coverage this file exists to protect');
|
|
174
|
+
});
|
|
175
|
+
|
|
99
176
|
test('sanitize_rebuild names both physical-confinement cases it lost', () => {
|
|
100
177
|
// The two that matter most: they are the ONLY coverage of physical confinement, and the
|
|
101
178
|
// pair whose silent absence let task 1003848 reach CI red.
|
|
@@ -119,3 +196,16 @@ test('the runner counts those SKIP lines, so a green roll-up still says coverage
|
|
|
119
196
|
// NAME contains the word must not be miscounted.
|
|
120
197
|
assert.equal(countSkips(' ok refuses to SKIP a dangerous entry\n'), 0);
|
|
121
198
|
});
|
|
199
|
+
|
|
200
|
+
test('countSkips also reads node:test\'s own summary — otherwise THIS file\'s skips are invisible', () => {
|
|
201
|
+
// The gap this file's own fix opened (task 1004112). node:test suites print no SKIP lines; they
|
|
202
|
+
// report `ℹ skipped N`. Uncounted, the roll-up says "all passed" over unrun coverage — the
|
|
203
|
+
// 1003993 defect one layer up, and exactly what gating the four cases above would have caused.
|
|
204
|
+
assert.equal(countSkips('ℹ tests 15\nℹ pass 11\nℹ fail 0\nℹ skipped 4\nℹ todo 0\n'), 4);
|
|
205
|
+
assert.equal(countSkips('ℹ tests 3\nℹ pass 3\nℹ skipped 0\n'), 0);
|
|
206
|
+
// A suite printing both formats SUMS rather than picking one — under-reporting is the failure
|
|
207
|
+
// mode this counter exists to prevent.
|
|
208
|
+
assert.equal(countSkips(' SKIP one\n SKIP two\nℹ skipped 3\n'), 5);
|
|
209
|
+
// The word in a case NAME must not be counted, same discipline as the SKIP line rule.
|
|
210
|
+
assert.equal(countSkips(' ok reports how many it skipped 9\n'), 0);
|
|
211
|
+
});
|