The merge normalises master's registry copy on every landing; --check refuses a row outside the four decisions

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-08 19:35:04 +00:00
parent bbdc4eb14c
commit e7668becda
2 changed files with 4 additions and 0 deletions

View file

@ -138,6 +138,7 @@ merge_with_batches() {
fi
if [ -n "$BATCHES" ]; then
git checkout -q "$tip" -- "$REGISTRY_PATH" # master's copy, never the branch's
node tools/ci/test-record.mjs --normalize >/dev/null 2>&1 || true # the master's decision vocabulary and record schema on every landing (idempotent)
if [ -f tools/ci/review-suite.mjs ] && [ -f docs/analysis/review-2026-10-08-b/findings.json ]; then
node tools/ci/review-suite.mjs --findings docs/analysis/review-2026-10-08-b/findings.json --dispatch docs/analysis/review-2026-10-08-b/dispatch.md --prefix REV --write >/dev/null || { echo "merge-to-master: the REV suite does not regenerate on the merged tree" >&2; git merge --abort 2>/dev/null; return 1; }
echo "merge-to-master: regenerated the REV suite on master's registry"

View file

@ -47,6 +47,7 @@ function check(reg, map) {
if (!isAutomated(c)) continue; const id = idOf(c);
if (!mapped.has(id) && !notRun[id]) { out.push(`case ${id} (Automated) has no harness in the map and no NOT RUN reason`); bad++; }
}
for (const c of cases) { const st = c.run_status; if (st && !DECISIONS.has(st)) { out.push(`case ${idOf(c)} reads ${st}: the decision vocabulary is NOT RUN, BLOCKED, FAIL, PASS (run --normalize)`); bad++; } }
for (const [cell, m] of Object.entries(map.cells || {})) { if (!m.command) { out.push(`map: cell ${cell} has no command`); bad++; } if (!m.box_class) { out.push(`map: cell ${cell} has no box class`); bad++; } if (!Array.isArray(m.fixtures)) { out.push(`map: cell ${cell} has no fixtures list (F0 onward, or empty)`); bad++; } }
return { bad, lines: out, automated: cases.filter(isAutomated).length, mapped: [...mapped].length, notRun: Object.keys(notRun).length };
}
@ -118,6 +119,8 @@ if (args.includes('--self-test')) {
const map = { cells: { 'pow': { command: 'cargo test --release', box_class: 'suite', fixtures: ['F0'], cases: ['C1'] } }, not_run: { C2: 'no malformed-case corpus yet', C4: 'the hostile-load rig is not built' } };
fs.writeFileSync(`${d}/reg.json`, JSON.stringify(reg)); fs.writeFileSync(`${d}/map.json`, JSON.stringify(map));
let r = check(reg, map); if (r.bad !== 0) { console.log(`self-test failed: a complete map was refused: ${r.lines.join('; ')}`); fails = 1; }
const regV = { cases: [{ id: 'V1', method: 'Automated', accept: 'a', run_status: 'RUNNING' }] }; const rv = check(regV, { cells: { c: { command: 'x', box_class: 'b', fixtures: [], cases: ['V1'] } }, not_run: {} });
if (!(rv.bad === 1 && /vocabulary/.test(rv.lines[0]))) { console.log(`self-test failed: a RUNNING row passed --check: ${rv.lines}`); fails = 1; }
const map2 = { cells: { pow: { ...map.cells.pow, cases: ['C1', 'C9'] } }, not_run: {} };
r = check(reg, map2); if (!(r.bad >= 2 && r.lines.some((l) => l.includes('unknown case C9')) && r.lines.some((l) => l.includes('C2') && l.includes('no harness')))) { console.log(`self-test failed: an unknown id or an unmapped Automated case was not refused: ${r.lines.join('; ')}`); fails = 1; }
const before = acceptSnapshot(reg); const touched = record(reg, map, { run_id: 'r1', manifest_sha: 'abc', evidence_dir: '/e', method: 'native', cells: [{ cell: 'pow', status: 'PASS', evidence: '/e/pow.log' }] });