@bongos/core 1.21.177 → 1.21.178
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 +140 -150
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +0 -6
- package/clients/bongos-client/index.cjs +0 -6
- package/clients/bongos-client/index.d.ts +0 -6
- package/clients/bongos-client/index.mjs +0 -6
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +3 -2
- package/docs/api/openapi.json +1 -87
- package/docs/api-reference.md +1 -8
- package/docs/canonical-permissions.md +3 -3
- package/docs/copy-inventory.md +25 -39
- package/docs/copy-registry.json +73 -200
- package/docs/file-map.md +3 -3
- package/docs/module-api-changelog.md +2 -0
- package/docs/modules-contract.md +2 -2
- package/docs/page-inventory.json +4 -7
- package/docs/page-readings.json +1520 -1569
- package/modules/government/catalog.js +10 -7
- package/modules/government/decision-board.js +0 -1
- package/modules/government/decision-rules.js +0 -1
- package/modules/government/docket.js +0 -1
- package/modules/government/protected-surfaces.js +1 -1
- package/modules/government/protected-surfaces.json +2 -3
- 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/city.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.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/fleet.html +1 -1
- package/modules/hall-ui/public/gate.css +4 -26
- package/modules/hall-ui/public/gate.html +12 -27
- package/modules/hall-ui/public/gate.js +26 -176
- package/modules/hall-ui/public/gate.states.json +4 -22
- package/modules/hall-ui/public/goal-map.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/my-agents.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/shell.js +1 -1
- package/modules/hall-ui/public/street-card.js +5 -9
- package/modules/hall-ui/public/street-desk.js +2 -2
- package/modules/hall-ui/public/street-inside.js +1 -1
- package/modules/hall-ui/public/street.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/thinking.html +1 -1
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/lifecycle/matter-acts.js +0 -6
- package/modules/lifecycle/module.json +0 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +22 -0
- package/scripts/bongos/adopt-preflight.js +3 -3
- package/scripts/bongos/audit-authorship.sh +1 -3
- package/scripts/bongos/bump-version.js +46 -9
- package/scripts/bongos/doc-cli-guard.js +2 -0
- package/scripts/bongos/doc-control-claims.js +2 -2
- package/scripts/bongos/government-walk.js +3 -9
- package/scripts/bongos/hard-floor.js +52 -0
- package/scripts/bongos/publish-manifest.js +3 -3
- package/scripts/bongos/run-unit-tests.js +17 -5
- package/scripts/gds/hard-floor.js +6 -0
- package/src/bongos/module-scope-map.js +2 -2
- package/src/bongos/permission-path-check.js +1 -1
- package/src/bongos/route-rank-check.js +1 -8
- package/src/bongos/routes.js +1 -2
- package/src/module-api.js +1 -1
- package/src/modules.js +1 -1
- package/tests/acclaim_feed_evidence_db.mjs +42 -23
- package/tests/adr_0089_scope.mjs +7 -5
- package/tests/bump_version.mjs +52 -18
- package/tests/copy_desk_flags_db.mjs +22 -14
- package/tests/gating_review_retired.mjs +1 -1
- package/tests/government_act_alone_buildings.mjs +1 -3
- package/tests/government_board_membership_db.mjs +35 -22
- package/tests/government_protected_surfaces.mjs +29 -13
- package/tests/governor_docket.mjs +0 -2
- package/tests/governor_matter_acts.mjs +6 -8
- package/tests/hall_city.mjs +1 -1
- package/tests/hall_matter_card.mjs +2 -2
- package/tests/hall_oversight_world.mjs +16 -12
- package/tests/hall_street_desk.mjs +4 -3
- package/tests/hall_street_inside.mjs +1 -1
- package/tests/helpers.mjs +34 -0
- package/tests/howto_state.mjs +33 -56
- package/tests/howto_state_db.mjs +68 -0
- package/tests/idea_credit_streams_db.mjs +11 -3
- package/tests/integration_parked_ratchet.mjs +7 -1
- package/tests/nav_permission_atoms.mjs +1 -1
- package/tests/page_notes_db.mjs +12 -8
- package/tests/page_tweak_no_rearm.mjs +50 -0
- package/tests/publish_manifest.mjs +64 -0
- package/tests/search_isolation.mjs +5 -103
- package/tests/search_isolation_db.mjs +140 -0
- package/tests/session_earnings_mirror_db.mjs +2 -0
- package/tests/workflow_exec_paths.mjs +9 -11
- package/modules/lifecycle/routes/gate-approvals.js +0 -299
- package/scripts/bongos/ci-grade.js +0 -82
- package/scripts/bongos/gate-review.js +0 -330
- package/scripts/gds/ci-grade.js +0 -7
- package/scripts/gds/gate-review.js +0 -7
- package/tests/gate_approvals.mjs +0 -611
- package/tests/gate_review.mjs +0 -152
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
// node scripts/bongos/bump-version.js # dry-run: print the plan
|
|
31
31
|
// node scripts/bongos/bump-version.js --apply # rewrite both files
|
|
32
32
|
// node scripts/bongos/bump-version.js --apply --note "run 123456" # extra provenance
|
|
33
|
+
// node scripts/bongos/bump-version.js --apply --taken-file versions.json
|
|
34
|
+
// # skip every version in that JSON array (`npm view @bongos/core versions --json`)
|
|
33
35
|
// stdout (both modes): one JSON line { from, to, applied } for CI to capture.
|
|
34
36
|
|
|
35
37
|
'use strict';
|
|
@@ -51,12 +53,18 @@ const DIVIDER = '---------------------------------------------------------------
|
|
|
51
53
|
// entry appended too; omit it to bump the literal alone (the unit tests do).
|
|
52
54
|
// Throws with a precise message on any shape it does not recognize — a silent
|
|
53
55
|
// mis-edit of the version literal is the worst possible failure mode here.
|
|
54
|
-
|
|
56
|
+
//
|
|
57
|
+
// `taken` (task 1004886): versions that already exist on the registry. The bump
|
|
58
|
+
// lands on the first patch past `from` that is NOT taken, because npm never lets a
|
|
59
|
+
// version be published twice — and a run that "re-publishes" a taken number ships
|
|
60
|
+
// nothing new while main is told it did. That is how 1.21.175 got recorded on main
|
|
61
|
+
// on 2026-10-25 for a tree the registry's 1.21.175 (built 2026-10-23) never held.
|
|
62
|
+
function bumpPatch(src, { note = '', changelog = null, taken = new Set() } = {}) {
|
|
55
63
|
const m = src.match(CONST_RE);
|
|
56
64
|
if (!m) throw new Error(`bump-version: could not find the CORE_VERSION literal in ${TARGET} (expected: const CORE_VERSION = 'x.y.z';)`);
|
|
57
65
|
const [major, minor, patch] = [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
58
66
|
const from = `${major}.${minor}.${patch}`;
|
|
59
|
-
const to =
|
|
67
|
+
const to = nextFreePatch(major, minor, patch, taken);
|
|
60
68
|
|
|
61
69
|
// 1. The literal — same line shape deploy-divergence greps for.
|
|
62
70
|
const newConstLine = `const CORE_VERSION = '${to}'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md`;
|
|
@@ -79,17 +87,40 @@ function bumpPatch(src, { note = '', changelog = null } = {}) {
|
|
|
79
87
|
return { from, to, text, changelogText };
|
|
80
88
|
}
|
|
81
89
|
|
|
90
|
+
// The first patch after `patch` whose version is not in `taken`. Bounded, so a
|
|
91
|
+
// corrupt taken-list can never spin: 10,000 consecutive taken patches is not a
|
|
92
|
+
// registry, it is a bug, and it throws.
|
|
93
|
+
function nextFreePatch(major, minor, patch, taken = new Set()) {
|
|
94
|
+
for (let p = patch + 1; p <= patch + 10000; p += 1) {
|
|
95
|
+
const v = `${major}.${minor}.${p}`;
|
|
96
|
+
if (!taken.has(v)) return v;
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`bump-version: no free patch within 10000 of ${major}.${minor}.${patch} — the taken-list is not a registry listing`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Parse `npm view <pkg> versions --json` output into a Set of x.y.z strings. npm
|
|
102
|
+
// prints a bare string (not an array) when exactly one version exists. Anything
|
|
103
|
+
// that is not a strict x.y.z is dropped, so a stray line cannot become a version.
|
|
104
|
+
function registryVersions(jsonText) {
|
|
105
|
+
let v;
|
|
106
|
+
try { v = JSON.parse(String(jsonText)); } catch { return new Set(); }
|
|
107
|
+
const list = Array.isArray(v) ? v : (typeof v === 'string' ? [v] : []);
|
|
108
|
+
return new Set(list.filter((x) => typeof x === 'string' && /^\d+\.\d+\.\d+$/.test(x)));
|
|
109
|
+
}
|
|
110
|
+
|
|
82
111
|
function main() {
|
|
83
112
|
const apply = process.argv.includes('--apply');
|
|
84
113
|
const noteIdx = process.argv.indexOf('--note');
|
|
85
114
|
const note = noteIdx !== -1 ? (process.argv[noteIdx + 1] || '') : '';
|
|
115
|
+
const takenIdx = process.argv.indexOf('--taken-file');
|
|
116
|
+
const taken = takenIdx !== -1 ? registryVersions(fs.readFileSync(process.argv[takenIdx + 1], 'utf8')) : new Set();
|
|
86
117
|
|
|
87
118
|
// Read and transform BOTH files before writing EITHER: a half-applied bump
|
|
88
119
|
// (literal moved, ledger silent) is precisely the drift this script exists
|
|
89
120
|
// to prevent, and it would be committed and pushed to main before anyone saw it.
|
|
90
121
|
const src = fs.readFileSync(TARGET, 'utf8');
|
|
91
122
|
const changelog = fs.readFileSync(CHANGELOG, 'utf8');
|
|
92
|
-
const { from, to, text, changelogText } = bumpPatch(src, { note, changelog });
|
|
123
|
+
const { from, to, text, changelogText } = bumpPatch(src, { note, changelog, taken });
|
|
93
124
|
if (changelogText === null) throw new Error('bump-version: the ledger was not rewritten — refusing to write a versionless release');
|
|
94
125
|
if (apply) {
|
|
95
126
|
fs.writeFileSync(TARGET, text);
|
|
@@ -143,10 +174,13 @@ function isReleaseCommit(subject) {
|
|
|
143
174
|
// • pack or publish failed → the bump commit was never pushed (it only ever
|
|
144
175
|
// existed on the discarded runner), so no version looks taken and the next
|
|
145
176
|
// run recomputes and retries the SAME version. No gap, nothing burned.
|
|
146
|
-
// • published, push then failed → version looks free,
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
177
|
+
// • published, push then failed → version looks free to git, but the registry
|
|
178
|
+
// listing publish.yml passes as --taken-file has it, so the next run bumps PAST
|
|
179
|
+
// it (a gap in main's ledger, harmless). Task 1003914 used to treat npm's
|
|
180
|
+
// duplicate refusal as success and record the version instead — but the push
|
|
181
|
+
// fails precisely because main MOVED, so the recorded tree was never the one on
|
|
182
|
+
// the registry. That recorded 1.21.175 for 200+ commits npm never had (task
|
|
183
|
+
// 1004886). A duplicate refusal now fails the run and records nothing.
|
|
150
184
|
//
|
|
151
185
|
// Before that reorder the first case was the lossy one: the push landed first,
|
|
152
186
|
// so a failed publish left main declaring a version the registry never had, the
|
|
@@ -196,8 +230,9 @@ function isHumanReleaseCommit(subject) {
|
|
|
196
230
|
//
|
|
197
231
|
// BOTH failure directions stay safe, which is what makes this acceptable here. A
|
|
198
232
|
// subject wrongly counted → the lane bumps PAST a free version (a gap, harmless). A
|
|
199
|
-
// real release missed →
|
|
200
|
-
//
|
|
233
|
+
// real release missed → the registry listing marks it taken and the lane bumps past
|
|
234
|
+
// it; if even that read failed, npm refuses the duplicate and the run fails without
|
|
235
|
+
// recording anything (task 1004886). Neither direction can double-publish or mislabel.
|
|
201
236
|
function laneReleasedVersions(subjects = []) {
|
|
202
237
|
const out = new Set();
|
|
203
238
|
for (const subject of subjects) {
|
|
@@ -211,6 +246,8 @@ function laneReleasedVersions(subjects = []) {
|
|
|
211
246
|
|
|
212
247
|
module.exports = {
|
|
213
248
|
bumpPatch,
|
|
249
|
+
nextFreePatch,
|
|
250
|
+
registryVersions,
|
|
214
251
|
CONST_RE,
|
|
215
252
|
RELEASE_COMMIT_RE,
|
|
216
253
|
HUMAN_RELEASE_COMMIT_RE,
|
|
@@ -48,6 +48,8 @@ const DOC_CLI_ALLOW = new Map([
|
|
|
48
48
|
'an accepted ADR recording how its evidence was measured; the spike harness was deleted once the verdict stood (task 1004857) and the ADR names the commit to recover it from.'],
|
|
49
49
|
['docs/session-logs/2026-08-28-goal-1000072-stale-timer-and-network-map-spike.md::scripts/bongos/spike-task-map.js',
|
|
50
50
|
'a dated session log — the historical record, never rewritten — of the spike whose harness task 1004857 deleted; it describes what was run then, not what to run now.'],
|
|
51
|
+
['docs/session-logs/2026-09-16-task-1003752-stranded-detector-never-ran.md::scripts/bongos/gate-review.js',
|
|
52
|
+
'a dated session log — the historical record, never rewritten — naming the gate-review classifier task 1004859 deleted (its CI check never ran); it describes what was run then, not what to run now.'],
|
|
51
53
|
]);
|
|
52
54
|
|
|
53
55
|
// `node scripts/bongos/foo.js` … up to the end of the line/segment, so the flags that
|
|
@@ -77,8 +77,8 @@ const SKIP_PREFIXES = ['docs/session-logs/', 'docs/audits/', 'limitations/'];
|
|
|
77
77
|
const ALLOW = new Map([
|
|
78
78
|
['docs/adr/0025-structured-criterion-task-link.md::scripts/bongos/seed-v3-tasks.js',
|
|
79
79
|
'describes the grep a session HAD to do before this ADR; a seed script, not a control'],
|
|
80
|
-
['docs/adr/
|
|
81
|
-
'
|
|
80
|
+
['docs/adr/0089-modular-multi-model-adversarial-grader.md::scripts/bongos/gate-review.js',
|
|
81
|
+
'ADR 0089 section 8 names the ADR 0058 gatekeeper as a surface the grading engine does not own; task 1004859 deleted it (the CI check it drove never ran) and moved its hard-floor list to scripts/bongos/hard-floor.js'],
|
|
82
82
|
['docs/adr/0111-instance-hosting-provisioning-module.md::scripts/bongos/box.js',
|
|
83
83
|
'the dev-box control-plane runner, retired with dev boxes by ADR 0346 (dev-box-guard.js keeps it out)'],
|
|
84
84
|
['docs/adr/0150-box-first-boot-bringup-vendored-instances.md::scripts/bongos/box.js',
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
// an in-memory fake with the same row shapes and the same guards (one open sitting
|
|
38
38
|
// per subject, one vote per member, single-winner close, the decision-rules write
|
|
39
39
|
// only from a passed decision-rules amendment), and the few writes a passed matter
|
|
40
|
-
// makes into other modules are recorded in memory instead of written to a database
|
|
41
|
-
//
|
|
40
|
+
// makes into other modules are recorded in memory instead of written to a database.
|
|
41
|
+
// The table says which mode ran.
|
|
42
42
|
//
|
|
43
43
|
// Usage:
|
|
44
44
|
// node scripts/bongos/government-walk.js run it and print the table
|
|
@@ -102,7 +102,6 @@ const REQUESTS = Object.freeze({
|
|
|
102
102
|
'POST /autonomy/builders/:builderId/pause': ['POST', `/autonomy/builders/${BAD}/pause`, { paused: false }],
|
|
103
103
|
'POST /done-when/:criterionId/satisfy': ['POST', `/done-when/${BAD}/satisfy`, {}],
|
|
104
104
|
'POST /done-when/:criterionId/unsatisfy': ['POST', `/done-when/${BAD}/unsatisfy`, {}],
|
|
105
|
-
'POST /gate-approvals/:pr/approve': ['POST', `/gate-approvals/${BAD}/approve`, {}],
|
|
106
105
|
'POST /override-requests/:id/decide': ['POST', `/override-requests/${BAD}/decide`, { decision: 'approve' }],
|
|
107
106
|
'POST /provisioning/instances/:id/core-upgrade': ['POST', `/provisioning/instances/${BAD}/core-upgrade`, { to: '1.2.3' }],
|
|
108
107
|
'POST /provisioning/instances/:id/update-channel': ['POST', `/provisioning/instances/${BAD}/update-channel`, { channel: 'nightly' }],
|
|
@@ -122,7 +121,6 @@ const MATTER_PLAN = Object.freeze([
|
|
|
122
121
|
['automation', 'Switch unattended building off', { type: 'switch_off' }, 'fence off'],
|
|
123
122
|
['automation', 'Allow goal 77 to build unattended', { type: 'allow_goal', goal_id: 77 }, 'goal 77 allowed'],
|
|
124
123
|
['release', 'Approve override request 5', { type: 'approve_override', request_id: 5 }, 'request 5 approved'],
|
|
125
|
-
['release', 'Clear the gate on PR 1500', { type: 'approve_gate', pr: 1500 }, 'PR 1500 cleared'],
|
|
126
124
|
['review', 'Sign off criterion 9', { type: 'satisfy_criterion', criterion_id: 9 }, 'criterion 9 satisfied'],
|
|
127
125
|
['treasury', 'Dee gets $50 a month', { type: 'set_budget', builder_id: 45, monthly_usd: 50 }, 'Dee\'s limit is $50'],
|
|
128
126
|
]);
|
|
@@ -135,7 +133,6 @@ const ROUTERS = Object.freeze([
|
|
|
135
133
|
// no HTTP surface; it contributes the Release and Review matter acts, as at boot
|
|
136
134
|
'modules/lifecycle/routes/lifecycle.js',
|
|
137
135
|
'modules/lifecycle/routes/done-when.js',
|
|
138
|
-
'modules/lifecycle/routes/gate-approvals.js',
|
|
139
136
|
'modules/lifecycle/routes/tasks.js',
|
|
140
137
|
'modules/lifecycle/routes/goals.js',
|
|
141
138
|
'modules/lifecycle/routes/versions.js',
|
|
@@ -618,7 +615,6 @@ async function runWalk() {
|
|
|
618
615
|
const lifeDb = req('modules/lifecycle/db.js');
|
|
619
616
|
const doneWhen = req('modules/lifecycle/done-when.js');
|
|
620
617
|
const doneWhenRoutes = req('modules/lifecycle/routes/done-when.js');
|
|
621
|
-
const gateRoutes = req('modules/lifecycle/routes/gate-approvals.js');
|
|
622
618
|
const express = require('express');
|
|
623
619
|
const http = require('http');
|
|
624
620
|
|
|
@@ -634,11 +630,10 @@ async function runWalk() {
|
|
|
634
630
|
projectSettings.setSetting = async (k, v) => { settings.set(k, String(v)); return { key: k, value: String(v) }; };
|
|
635
631
|
|
|
636
632
|
// What passed matters write into other modules, recorded.
|
|
637
|
-
const effects = { fence: null, allowedGoals: [], overrides: [],
|
|
633
|
+
const effects = { fence: null, allowedGoals: [], overrides: [], criteria: new Map([['9', false]]), budgets: new Map() };
|
|
638
634
|
autoDb.setFenceEnabled = async ({ enabled }) => { effects.fence = enabled; return { enabled }; };
|
|
639
635
|
autoDb.allowGoal = async ({ goalId }) => { effects.allowedGoals.push(String(goalId)); return { goal_id: goalId }; };
|
|
640
636
|
lifeDb.decideOverrideRequest = async ({ requestId, decision }) => { effects.overrides.push([String(requestId), decision]); return {}; };
|
|
641
|
-
gateRoutes.approveGatePr = async ({ number }) => { effects.gates.push(String(number)); return { ok: true, body: {} }; };
|
|
642
637
|
doneWhen.getCriterion = async (id) => (effects.criteria.has(String(id)) ? { id, satisfied: effects.criteria.get(String(id)) } : null);
|
|
643
638
|
doneWhenRoutes.satisfyByOverride = async ({ criterionId }) => { effects.criteria.set(String(criterionId), true); return { updated: {}, goalResult: {} }; };
|
|
644
639
|
|
|
@@ -971,7 +966,6 @@ async function runWalk() {
|
|
|
971
966
|
'automation.switch_off': () => effects.fence === false,
|
|
972
967
|
'automation.allow_goal': () => effects.allowedGoals.includes('77'),
|
|
973
968
|
'release.approve_override': () => effects.overrides.some(([id, d]) => id === '5' && d === 'approve'),
|
|
974
|
-
'release.approve_gate': () => effects.gates.includes('1500'),
|
|
975
969
|
'review.satisfy_criterion': () => effects.criteria.get('9') === true,
|
|
976
970
|
'treasury.set_budget': () => effects.budgets.get('45') === 50,
|
|
977
971
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// scripts/bongos/hard-floor.js — the trust-boundary HARD FLOOR: the repo paths that,
|
|
4
|
+
// if a compromised or injected senior session changed them, would disable the safety
|
|
5
|
+
// system itself or the deploy switch. A subset of PROTECTED_GLOBS (the protected-surface
|
|
6
|
+
// registry, modules/government/protected-surfaces.json); tests/government_protected_surfaces.mjs
|
|
7
|
+
// holds the subset honest.
|
|
8
|
+
//
|
|
9
|
+
// WHERE IT CAME FROM. This list lived in scripts/bongos/gate-review.js, the ADR 0058
|
|
10
|
+
// classifier a planned gate-review CI check was meant to run. That check never ran on
|
|
11
|
+
// main, and task 1004859 removed the classifier with the hall Gate page that waited on
|
|
12
|
+
// it. Two live readers still need the list, so it moved here unchanged (minus the two
|
|
13
|
+
// deleted drivers that named themselves):
|
|
14
|
+
// - scripts/bongos/publish-manifest.js — what the public mirror must never carry;
|
|
15
|
+
// - scripts/bongos/adopt-preflight.js — whether an adopted repo lands on the floor.
|
|
16
|
+
//
|
|
17
|
+
// Imported, never re-typed: a consumer that needs the floor requires this file.
|
|
18
|
+
// Kept as globs so the matcher is the one permission-path-check builds (trailing '/' =
|
|
19
|
+
// subtree, case- and NFC-folded — task 1002874: a byte-exact matcher let an uppercased
|
|
20
|
+
// spelling of a floor surface walk past).
|
|
21
|
+
|
|
22
|
+
const { compileGlobMatcher } = require('../../src/bongos/permission-path-check');
|
|
23
|
+
|
|
24
|
+
const HARD_FLOOR_GLOBS = [
|
|
25
|
+
'scripts/bongos/hard-floor.js', // self
|
|
26
|
+
'src/bongos/permission-path-check.js', // defines the protected set
|
|
27
|
+
'src/bongos/route-rank-check.js', // the route-gate auditor
|
|
28
|
+
'src/bongos/auth.js', // requireRank / requireBuilder — the enforcement point
|
|
29
|
+
'modules/grading/grader.js', // BV1.R73: grading carved to modules/grading/
|
|
30
|
+
'modules/grading/grader-workers/',
|
|
31
|
+
'modules/grading/grader-rubric.json',
|
|
32
|
+
'scripts/bongos/grade-smoke.js', // grade-smoke driver
|
|
33
|
+
'scripts/bongos/conductor-dispatch.js', // mid-flight grader dispatch
|
|
34
|
+
'scripts/bongos/main-audit.js', // the authoritative deploy-time audit (the backstop)
|
|
35
|
+
'scripts/bongos/push-main.js', // the sanctioned main-push carrying the override
|
|
36
|
+
'scripts/bongos/run-unit-tests.js', // the unit-gate test selector
|
|
37
|
+
'scripts/bongos/install-git-hooks.js',
|
|
38
|
+
'scripts/bongos/hooks/',
|
|
39
|
+
'scripts/migrate.sh',
|
|
40
|
+
'scripts/deploy/',
|
|
41
|
+
'config/deploy.json', // the laptop/ci/bypass deploy switch
|
|
42
|
+
'infra/', // branch-protection.json + deploy substrate
|
|
43
|
+
'.github/', // CI workflows: the unit gate, secret scan, publish
|
|
44
|
+
'CODEOWNERS',
|
|
45
|
+
'.husky/', // pre-push/pre-commit gate delivery
|
|
46
|
+
'.claude/hooks/',
|
|
47
|
+
'.claude/settings.json',
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const matchesHardFloor = compileGlobMatcher(HARD_FLOOR_GLOBS);
|
|
51
|
+
|
|
52
|
+
module.exports = { HARD_FLOOR_GLOBS, matchesHardFloor };
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// that falls inside an allowlisted subtree is dropped if the denylist forbids it.
|
|
17
17
|
// isPublishable(p) == matchesDeny(p) ? false : matchesAllow(p)
|
|
18
18
|
//
|
|
19
|
-
// REUSE, NEVER RE-TYPE (the task's explicit instruction; the
|
|
19
|
+
// REUSE, NEVER RE-TYPE (the task's explicit instruction; the hard-floor.js doctrine):
|
|
20
20
|
// The three canonical sensitive-surface inventories are IMPORTED, never copied —
|
|
21
21
|
// PROTECTED_GLOBS (write-protection over trust/pipeline/infra code),
|
|
22
22
|
// HARD_FLOOR_GLOBS (the rank-independent escalate subset), and
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
// cross-checks the partition against the live inventory so it cannot silently drift.
|
|
29
29
|
|
|
30
30
|
// The three canonical sensitive-surface inventories — imported from their homes,
|
|
31
|
-
// NEVER re-typed (the
|
|
31
|
+
// NEVER re-typed (the "imported, never hand-retyped" doctrine). All
|
|
32
32
|
// three are pure to require (no DB/network at load; their CLIs are require.main-guarded).
|
|
33
33
|
const { PROTECTED_GLOBS, globToRegExp } = require('../../src/bongos/permission-path-check');
|
|
34
|
-
const { HARD_FLOOR_GLOBS } = require('./
|
|
34
|
+
const { HARD_FLOOR_GLOBS } = require('./hard-floor');
|
|
35
35
|
const { SENSITIVE_DOC_GLOBS } = require('./search-ingest-md');
|
|
36
36
|
|
|
37
37
|
// ---------------------------------------------------------------------------
|
|
@@ -258,6 +258,14 @@ const INTEGRATION = new Set([
|
|
|
258
258
|
// branch over a fake table; only a real engine runs the one-shot DO block and
|
|
259
259
|
// shows a legacy account published again and marked apart from a sign-in.
|
|
260
260
|
'terms_grandfather_db',
|
|
261
|
+
// task 1004863: three database halves that no lane ran. page_notes_db (the page
|
|
262
|
+
// feedback doc schema rules; modules/page-notes is live and on by default) self-skipped
|
|
263
|
+
// in the unit lane and was in no set. howto_state_db and search_isolation_db are the
|
|
264
|
+
// database halves split out of howto_state and search_isolation, whose DB-free halves
|
|
265
|
+
// stay in the unit lane: the first runs the how-to read contract on the real schema,
|
|
266
|
+
// the second proves the search index never widens a caller past their rank or into
|
|
267
|
+
// another builder memory. Each skipped in CI before, so none had ever been gated.
|
|
268
|
+
'page_notes_db', 'howto_state_db', 'search_isolation_db',
|
|
261
269
|
]);
|
|
262
270
|
|
|
263
271
|
// Excluded so this gate is trustworthy in a CLEAN checkout (the CI condition):
|
|
@@ -448,6 +456,15 @@ function discoverModuleTests({ modulesDir = MODULES_DIR, isEnabled = isModuleEna
|
|
|
448
456
|
// needed terms_accepted_at stamped: the public read requires both consent columns since
|
|
449
457
|
// ADR 0213. If one of them reds again, check the module flag is still set first.
|
|
450
458
|
//
|
|
459
|
+
// FIVE LEFT THIS LIST under task 1004863, each repaired against a freshly migrated
|
|
460
|
+
// database: copy_desk_flags_db, government_board_membership_db (builders.github_id is
|
|
461
|
+
// NOT NULL now; their rows go through insertTestBuilders in tests/helpers.mjs, and the
|
|
462
|
+
// stand-in tables that hid the drift are gone), idea_credit_streams_db and
|
|
463
|
+
// session_earnings_mirror_db (fixture rows named a version status and a task discipline
|
|
464
|
+
// the CHECK constraints no longer admit), and acclaim_feed_evidence_db, which now calls
|
|
465
|
+
// the real feed route handler instead of a sliced copy of its SQL and owns a building
|
|
466
|
+
// version rather than colliding with the seeded planning one (the oscillation above).
|
|
467
|
+
//
|
|
451
468
|
// consumer_layout_boot LEFT THIS LIST under task 1002863. Its "missing core tarball" was
|
|
452
469
|
// package-core's fail-closed leak gate reading the lane's throwaway database password (the
|
|
453
470
|
// word postgres, present in hundreds of core files) as a leaked credential and refusing to
|
|
@@ -464,11 +481,6 @@ function discoverModuleTests({ modulesDir = MODULES_DIR, isEnabled = isModuleEna
|
|
|
464
481
|
// with no blocker_ref, and db.shipTask called without the land assurance task 1002483
|
|
465
482
|
// made mandatory. Each passes alone on a freshly migrated database.
|
|
466
483
|
const INTEGRATION_PARKED = new Set([
|
|
467
|
-
'acclaim_feed_evidence_db',
|
|
468
|
-
'copy_desk_flags_db',
|
|
469
|
-
'government_board_membership_db',
|
|
470
|
-
'idea_credit_streams_db',
|
|
471
|
-
'session_earnings_mirror_db',
|
|
472
484
|
]);
|
|
473
485
|
|
|
474
486
|
function main() {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// scripts/gds/hard-floor.js — @bongos-forwarder (task 1004848). Generated by
|
|
2
|
+
// scripts/bongos/codemod-rename-scripts-gds.js; do not edit.
|
|
3
|
+
// The real script is scripts/bongos/hard-floor.js. This forwarder keeps callers that still name
|
|
4
|
+
// the old path working, and warns once so they get repointed. Task 1003706 removes it.
|
|
5
|
+
'use strict';
|
|
6
|
+
require('../bongos/forwarder.js').forward(module, 'hard-floor.js');
|
|
@@ -93,7 +93,7 @@ const MODULE_GLOBS = {
|
|
|
93
93
|
],
|
|
94
94
|
// --- the build state machine + ship/grade/deploy orchestration + schema ---
|
|
95
95
|
// Carved into modules/lifecycle/ (BV1.R86 / ADR 0093 §1,§3): the task/claim/
|
|
96
|
-
// version/goal/done-when/dependency
|
|
96
|
+
// version/goal/done-when/dependency routes + the db slice, the
|
|
97
97
|
// task-classifier + hierarchy + done-when libs, github-push + ship-card +
|
|
98
98
|
// ship-preflight + merge-lock + conflict-resolve + publish-reconciler +
|
|
99
99
|
// version-close, and the `lifecycle` kernel PORT — all under the
|
|
@@ -115,7 +115,7 @@ const MODULE_GLOBS = {
|
|
|
115
115
|
'scripts/bongos/ship-regen.js', 'scripts/bongos/ship-resume.js', 'scripts/bongos/ship-session-upload.js',
|
|
116
116
|
'scripts/bongos/ship-state.js', 'scripts/bongos/ship-surprise.js', 'scripts/bongos/ship-visual.js',
|
|
117
117
|
'scripts/bongos/merge-mode.js', 'scripts/bongos/confirm.js', 'scripts/bongos/main-audit.js',
|
|
118
|
-
'scripts/bongos/
|
|
118
|
+
'scripts/bongos/hard-floor.js', 'scripts/bongos/push-main.js',
|
|
119
119
|
'scripts/bongos/merge-lock.js', 'scripts/bongos/version-close.js',
|
|
120
120
|
'migrations/',
|
|
121
121
|
|
|
@@ -43,7 +43,7 @@ const RANK_TIER = { xenos: 1, thetes: 2, metic: 3, archon: 4 };
|
|
|
43
43
|
// modules/government/protected-surfaces.json — no longer a constant baked into
|
|
44
44
|
// this file. Re-mapping a floor there is a POLICY edit. It cannot move
|
|
45
45
|
// enforcement into the app: the three layers above (git pre-push hook, grader
|
|
46
|
-
// pre-pass, post-push main audit) plus
|
|
46
|
+
// pre-pass, post-push main audit) plus the goal-scope check
|
|
47
47
|
// read the registry out of band — no DB, no server, no HTTP — and remain the
|
|
48
48
|
// authority (ADR 0043). Making the request path the enforcer is the exact
|
|
49
49
|
// regression this task exists to prevent.
|
|
@@ -220,7 +220,7 @@ const EXPECTED_RANKS = {
|
|
|
220
220
|
'GET /builders/directory': 'any-builder',
|
|
221
221
|
// (the lifecycle fleet pins — task authoring/promotion/abandonment, override
|
|
222
222
|
// adjudication, polymorphic dependency edges, goal tier + ask-to-widen,
|
|
223
|
-
// criterion confirmation
|
|
223
|
+
// and criterion confirmation — moved to MODULE_EXPECTED_RANKS
|
|
224
224
|
// ['lifecycle'] below in BV1.R86. They live in the lifecycle module now
|
|
225
225
|
// (modules/lifecycle/routes/…), so they're verified only when that module is in
|
|
226
226
|
// scope, not unconditionally from this core list — the pins follow the routes.)
|
|
@@ -500,13 +500,6 @@ const MODULE_EXPECTED_RANKS = {
|
|
|
500
500
|
'POST /done-when/:criterionId/uat/recording': 'perm:criterion.review',
|
|
501
501
|
'POST /done-when/:criterionId/uat': 'perm:criterion.review',
|
|
502
502
|
'PUT /done-when/:criterionId/backend-only': 'perm:criterion.create',
|
|
503
|
-
// gate-surface PR approval from the hall (task 1179, ADR 0058 amendment). ADR 0157
|
|
504
|
-
// SPLIT these two: the list route is `gate_approval.read` (metic — the Gate page
|
|
505
|
-
// opens to the working rank), while APPROVING still clears the gate-review hard
|
|
506
|
-
// floor and stays `gate_approval.decide` (archon, system). The split is the reason
|
|
507
|
-
// the page is usable at all — see the atom's note in catalog.js.
|
|
508
|
-
'GET /gate-approvals': 'perm:gate_approval.read',
|
|
509
|
-
'POST /gate-approvals/:pr/approve': 'perm:gate_approval.decide',
|
|
510
503
|
},
|
|
511
504
|
// Ratifying a criterion proposal WRITES scope-truth (it creates a done-when
|
|
512
505
|
// criterion). Metic+ may file the proposal; ADR 0157 also lets Metic ratify it
|
package/src/bongos/routes.js
CHANGED
|
@@ -31,7 +31,7 @@ const buildMySessionsRouter = require('./routes/my-sessions');
|
|
|
31
31
|
const buildMyPasskeysRouter = require('./routes/my-passkeys');
|
|
32
32
|
const buildBuildersRouter = require('./routes/builders');
|
|
33
33
|
// The LIFECYCLE routes (tasks · claims · versions · done-when · goals ·
|
|
34
|
-
// dependencies ·
|
|
34
|
+
// dependencies · analytics) carved into modules/lifecycle/
|
|
35
35
|
// (BV1.R86 / ADR 0093 §1,§3); moduleLoader.mountModuleRoutes (below) mounts them
|
|
36
36
|
// via the lifecycle module's route factories — no core require. The `/tasks/:id/
|
|
37
37
|
// publish-branch` body-parser bypass below STAYS (the route carries its own larger
|
|
@@ -187,7 +187,6 @@ function buildGdsRouter() {
|
|
|
187
187
|
// and discord (with its bug-attachments route) have both graduated
|
|
188
188
|
// into real modules (modules/<key>/) — they are discovered + mounted by
|
|
189
189
|
// moduleLoader.mountModuleRoutes below, not here (BV1.R43 / R48 / R47 / R72).
|
|
190
|
-
// gate-approvals likewise moved to the lifecycle module (BV1.R86).
|
|
191
190
|
router.use(buildLlmCacheRouter());
|
|
192
191
|
|
|
193
192
|
// Loader-mounted module routers (ADR 0083 / BV1.R41). Discovers + mounts every
|
package/src/module-api.js
CHANGED
|
@@ -75,7 +75,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
75
75
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
76
76
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
77
77
|
|
|
78
|
-
const CORE_VERSION = '1.21.
|
|
78
|
+
const CORE_VERSION = '1.21.178'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
79
79
|
|
|
80
80
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
81
81
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
package/src/modules.js
CHANGED
|
@@ -44,7 +44,7 @@ const INSTANCE_PATH = path.join(resolveInstanceRoot(), 'config', 'modules.json')
|
|
|
44
44
|
//
|
|
45
45
|
// CORE (always on, never a module): auth, builders, tasks, claims, versions,
|
|
46
46
|
// done-when, credits/cost, inbox, blockers, leaderboard, analytics,
|
|
47
|
-
// audit-log, security, access-requests, sessions,
|
|
47
|
+
// audit-log, security, access-requests, sessions, healthz,
|
|
48
48
|
// public. These mount unconditionally. The optional feature modules AND the
|
|
49
49
|
// first TWO carved CORE-domain modules have graduated to modules/<key>/ (discord
|
|
50
50
|
// BV1.R47, art-pipeline BV1.R48, game BV1.R49, memory BV1.R72 —
|
|
@@ -16,21 +16,22 @@
|
|
|
16
16
|
// - a ship with several cost rows must sum them, not pick one;
|
|
17
17
|
// - the two LATERALs and the grades join must not multiply the row out.
|
|
18
18
|
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
19
|
+
// Calls the REAL route handler (GET /tasks/peer-votes/feed from the lifecycle
|
|
20
|
+
// router) against the database, so a future edit to the route is tested rather
|
|
21
|
+
// than a copy of it. It used to slice the query text out of the route's source and
|
|
22
|
+
// re-interpolate it by hand; the route grew a second interpolation (the helper
|
|
23
|
+
// join), the copy stopped resolving, and the test failed on its own scaffolding
|
|
24
|
+
// rather than on the route (task 1004863). Driving the handler cannot drift that way.
|
|
21
25
|
// Self-skips without a reachable Postgres; in the INTEGRATION set, so the
|
|
22
26
|
// DB-free unit gate never runs it and .github/workflows/integration.yml does.
|
|
23
27
|
//
|
|
24
28
|
// Run: DATABASE_URL=... node tests/acclaim_feed_evidence_db.mjs
|
|
25
29
|
import { createRequire } from 'node:module';
|
|
26
30
|
import { strict as assert } from 'node:assert';
|
|
27
|
-
import
|
|
28
|
-
import path from 'node:path';
|
|
29
|
-
import { fileURLToPath } from 'node:url';
|
|
31
|
+
import { insertTestBuilders } from './helpers.mjs';
|
|
30
32
|
|
|
31
33
|
const require = createRequire(import.meta.url);
|
|
32
34
|
const { Pool } = require('pg');
|
|
33
|
-
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
34
35
|
|
|
35
36
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL || undefined });
|
|
36
37
|
try {
|
|
@@ -41,18 +42,30 @@ try {
|
|
|
41
42
|
process.exit(0);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
// The
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
assert.ok(
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
// The handler under test: the last stack entry of the shipped route (the first is
|
|
46
|
+
// auth.requireBuilder, which needs a session; the handler reads req.builder, which
|
|
47
|
+
// we supply). The router's pool is the core pool, which reads DATABASE_URL — the
|
|
48
|
+
// same database this file writes its fixtures to.
|
|
49
|
+
const buildTasksRouter = require('../modules/lifecycle/routes/tasks.js');
|
|
50
|
+
const feedLayer = buildTasksRouter().stack
|
|
51
|
+
.find((l) => l.route && l.route.path === '/tasks/peer-votes/feed' && l.route.methods.get);
|
|
52
|
+
assert.ok(feedLayer, 'the lifecycle router still serves GET /tasks/peer-votes/feed');
|
|
53
|
+
const feedHandler = feedLayer.route.stack[feedLayer.route.stack.length - 1].handle;
|
|
54
|
+
|
|
55
|
+
// Call the route as `builder` and return its JSON body; a failure surfaces as a throw.
|
|
56
|
+
async function feed(builder, limit = 100) {
|
|
57
|
+
let body = null;
|
|
58
|
+
let failure = null;
|
|
59
|
+
const res = {
|
|
60
|
+
json(b) { body = b; return res; },
|
|
61
|
+
fail(code, opts) { failure = { code, opts }; return res; },
|
|
62
|
+
status() { return res; },
|
|
63
|
+
};
|
|
64
|
+
await feedHandler({ builder, query: { limit: String(limit) }, params: {}, headers: {}, get: () => undefined }, res);
|
|
65
|
+
if (failure) throw new Error(`the feed route failed: ${JSON.stringify(failure)}`);
|
|
66
|
+
assert.ok(body && Array.isArray(body.tasks), 'the feed answered with a task list');
|
|
67
|
+
return body;
|
|
68
|
+
}
|
|
56
69
|
|
|
57
70
|
const VOTER = 90000801;
|
|
58
71
|
const SHIPPER = 90000802;
|
|
@@ -82,10 +95,13 @@ const check = (name, fn) => {
|
|
|
82
95
|
try {
|
|
83
96
|
await cleanup();
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
// 'building', not 'planning': versions_one_planning_idx allows ONE planning row and
|
|
99
|
+
// the seeds own it — the collision that parked this test (task 1004042).
|
|
100
|
+
await q("INSERT INTO versions (id, name, status) VALUES ($1, 'acclaim evidence fixture', 'building')", [VER]);
|
|
101
|
+
await insertTestBuilders(pool, [
|
|
102
|
+
{ id: VOTER, login: 'zz-acc-voter', rank: 'metic' },
|
|
103
|
+
{ id: SHIPPER, login: 'zz-acc-shipper', rank: 'metic' },
|
|
104
|
+
], { onConflict: '' });
|
|
89
105
|
for (const [id, title] of [
|
|
90
106
|
[T.GOOD, '__acc__ graded and costed'],
|
|
91
107
|
[T.OUTAGE, '__acc__ grader outage'],
|
|
@@ -123,7 +139,10 @@ try {
|
|
|
123
139
|
await cost(T.FREE, '0');
|
|
124
140
|
// T.OUTAGE and T.UNGRADED get no cost row at all.
|
|
125
141
|
|
|
126
|
-
|
|
142
|
+
// A metic caller: cost reaches only the ranks that can vote, so this is the view
|
|
143
|
+
// that carries every figure under test.
|
|
144
|
+
const body = await feed({ id: VOTER, rank: 'metic' });
|
|
145
|
+
const rows = body.tasks;
|
|
127
146
|
const byId = new Map(rows.map((r) => [String(r.id), r]));
|
|
128
147
|
const got = (id) => {
|
|
129
148
|
const row = byId.get(String(id));
|
package/tests/adr_0089_scope.mjs
CHANGED
|
@@ -28,9 +28,11 @@ const adr = read('docs/adr/0089-modular-multi-model-adversarial-grader.md');
|
|
|
28
28
|
const section = adr.slice(adr.indexOf('### 8. Scope: what the engine does NOT own'), adr.indexOf('## Consequences'))
|
|
29
29
|
.replaceAll('scripts/gds/', 'scripts/bongos/'); // rename-keep
|
|
30
30
|
|
|
31
|
+
// §8 also names scripts/bongos/gate-review.js. Task 1004859 deleted it (the CI check it
|
|
32
|
+
// drove never ran), so there is nothing left to hold to the boundary; the ADR keeps the
|
|
33
|
+
// name as history.
|
|
31
34
|
const SURFACES = [
|
|
32
35
|
'scripts/bongos/session-eval.js',
|
|
33
|
-
'scripts/bongos/gate-review.js',
|
|
34
36
|
'scripts/bongos/main-audit.js',
|
|
35
37
|
'scripts/bongos/architect-audit.js',
|
|
36
38
|
];
|
|
@@ -40,7 +42,7 @@ test('ADR 0089 carries the §8 scope section, before Consequences', () => {
|
|
|
40
42
|
assert.ok(section.length > 200, 'the section sits between §7 and Consequences');
|
|
41
43
|
});
|
|
42
44
|
|
|
43
|
-
test('§8 names each of the
|
|
45
|
+
test('§8 names each of the remaining surfaces by path, and each path exists', () => {
|
|
44
46
|
for (const p of SURFACES) {
|
|
45
47
|
assert.ok(section.includes(p), `§8 names ${p}`);
|
|
46
48
|
assert.ok(fs.existsSync(new URL(`../${p}`, import.meta.url)), `${p} exists`);
|
|
@@ -56,14 +58,14 @@ test('the Architect uses exactly the three grader helpers §8 names — nothing
|
|
|
56
58
|
for (const name of used) assert.ok(section.includes(name), `§8 names ${name}`);
|
|
57
59
|
});
|
|
58
60
|
|
|
59
|
-
test('session-eval
|
|
61
|
+
test('session-eval and main-audit import no grading module', () => {
|
|
60
62
|
for (const p of SURFACES.filter((s) => !s.endsWith('architect-audit.js'))) {
|
|
61
63
|
assert.doesNotMatch(read(p), /require\([^)]*modules\/grading/, `${p} must not require grading code`);
|
|
62
64
|
}
|
|
63
65
|
});
|
|
64
66
|
|
|
65
|
-
test('main-audit
|
|
66
|
-
for (const p of ['scripts/bongos/main-audit.js'
|
|
67
|
+
test('main-audit reads the rank-permission checker §8 names', () => {
|
|
68
|
+
for (const p of ['scripts/bongos/main-audit.js']) {
|
|
67
69
|
assert.match(read(p), /permission-path-check/, `${p} reads the checker`);
|
|
68
70
|
}
|
|
69
71
|
assert.ok(section.includes('src/bongos/permission-path-check.js'), '§8 names the shared checker');
|