diff --git a/tools/ci/README.md b/tools/ci/README.md index 132c96c73..4557b253a 100644 --- a/tools/ci/README.md +++ b/tools/ci/README.md @@ -13,6 +13,9 @@ | F02 (Review B): the proof-rule test bypass cannot reach a release build (`proof-rule-bypass-check.sh`; a cell of the node matrix) | An env read of IGNEUM_TEST_SKIP_PROOF_RULE with no cfg(test) or cfg(feature) guard in the 12 lines above, or under a feature in the crate's default features; a release igneumd carrying the bypass string. Red on every node sha until the proving lane's change (the read under a non-default feature or cfg(test)) lands | 8 Oct 2026 | | the test map merges structurally at a landing (`test-map-merge.py`) and the harness page regenerates from the merged map (`merge-to-master.sh`) | Nothing by itself: two lanes adding cells collided as text and the regenerated page lost rule 26's race; the merge now keeps master's cells plus the branch's, minus what the branch removed and master left, and regenerates the page | 8 Oct 2026 | | a push that lost the ref race retries without re-running the hook (`merge-to-master.sh` `push_race`, 12 tries) | Nothing by itself: under one landing a minute a 70-second hook per try never won master's compare-and-swap (Review B's landing lost three in a row); once the hook has passed on the first try and the rejection is a ref race, later tries push --no-verify (both parents gated) | 8 Oct 2026 | +| the kit ISA check (`kit-isa-check.sh`; in the gate as a self-test, in `merge-to-master.sh` over any executable a landing adds under packaging/kits or bin, and in the shipper's cut gate over the kit) | Any binary whose disassembly carries a zmm register, an EVEX opmask or an EVEX-only mnemonic (AVX-512): a fleet binary comes only from the cross-build kit at the x86-64-v3 baseline, never from a box's native gate build (79 fleet hosts died on one, 8 Oct 2026) | 8 Oct 2026 | +| kill-by-name rule 5 and the no-kill shim (`kill-by-name-check.sh`, `no-kill-shim/{pkill,killall}` exit 97 when first in PATH) | A `pgrep -f`/`pkill -f` pattern that is a bare path, a log name or an unanchored word; only `^`-anchored command patterns, the bracket form, a variable, -x or -F pass (fifteen Mac processes died to a grep, 8 Oct 2026) | 8 Oct 2026 | +| a "cut" batch needs its read-back (`test-record.mjs`) | A batch declaring `cut` without the binary's build-N:/srv path, its commit string read back equal to the manifest sha, and the kit ISA check's clean line; a sha is cut only when its binary exists on build-1 with its commit string read back | 8 Oct 2026 | | the INT suite is generated from the master edition's integration gates (`int-suite.mjs`; the owner per the coordinator's crosswalk) and INT-17 is a rule of the writer: a cell declaring a missing oracle, pinned keys or mandatory real-proof fixture writes BLOCKED, never PASS | A registry whose INT suite drifts from traceability.json; a batch cell with `prereqs` where any is not "present" written as anything but BLOCKED | 8 Oct 2026 | | the REV suite is generated from an external review's findings.json and dispatch.md (`review-suite.mjs`; one case per required regression, NOT RUN, the owner from the dispatch table) | A registry whose REV suite differs from the generator's output (--check) | 8 Oct 2026 | | a registry landing carries its batches (`tools/ci/batches/.json`; `merge-to-master.sh` replays them onto master's copy at the merge) | Nothing by itself: the registry is a hot file, and a branch whose own copy of it was recorded during a seven-minute gate lost the race to another lane's rows three times in a row (8 Oct 2026, 19:1x UK). A branch that adds batch files is merged with master's registry, every added batch replayed through `test-record.mjs --record` (idempotent), and the evidence rules run on the merged result; rule 26 does not bind the registry path for such a branch | 8 Oct 2026 | diff --git a/tools/ci/checks.txt b/tools/ci/checks.txt index 3605b81bf..293e8ac87 100644 --- a/tools/ci/checks.txt +++ b/tools/ci/checks.txt @@ -75,6 +75,7 @@ the test map: every automated case of the registry maps to a cell or carries a N the harness map page is generated from tools/ci/test-map.json and current P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker) the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test) +the kit ISA check: a distribution kit's binaries carry no AVX-512 encoding (the x86-64-v3 baseline; self-test with a fake objdump) F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test) the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test) the REV suite is generated from Review B's findings and dispatch and matches them (self-test, then the tree) diff --git a/tools/ci/kill-by-name-check.sh b/tools/ci/kill-by-name-check.sh index 694871c8e..6f080b593 100755 --- a/tools/ci/kill-by-name-check.sh +++ b/tools/ci/kill-by-name-check.sh @@ -20,6 +20,10 @@ # pattern can match a gate or a merge run of another lane. A gate is killed by its pid file only # (.git/igneum-gate.pid, .git/igneum-merge.pid under the worktree: `kill "$(cut -d' ' -f1 )"`). # +# 5. (8 October 2026, 20:21 UK, the founder's word after fifteen Mac processes died to a grep) a `pgrep -f`/`pkill -f` pattern passes +# only when it is anchored on the exact command line (`^/full/path` or `^command`), is the bracket form, a variable, -x on a +# binary name or -F on a pid file; a bare path, a log name or a word is red. The fix is a pid file or the anchored pattern. +# # tools/ci/kill-by-name-check.sh # exit 1 with file:line and the reason # tools/ci/kill-by-name-check.sh --self-test # fires on each banned shape, passes each allowed one set -euo pipefail @@ -50,9 +54,13 @@ check_line() { # -> prints the reason, returns 1, when the line carrie rest="${rest#*"$m"}" if [[ "$pat" =~ \.(log|txt|jsonl?|out|err|pid|csv|md|toml|ya?ml|lock)(\"|\'|$|[^A-Za-z0-9]) ]]; then echo "pkill/pgrep -f on a file name ($pat): a file name is a redirect or an argument, never the command line; use a pid file (tools/fleet/fleet-bg.sh) or the binary's full path"; return 1; fi [[ "$pat" == *'$'* ]] && continue # a variable: the caller anchored it (reviewed by hand) - [[ "$pat" == /* ]] && continue # an anchored full path + # rule 5 (the founder's word, 8 October 2026, 20:21 UK, after fifteen Mac processes died to a grep): a pattern passes only when it + # is anchored on the exact command line (^/full/path or ^command) or is the bracket form; a bare path, a log name or a word is red + [[ "$pat" == ^/* ]] && continue # an anchored full path + [[ "$pat" =~ ^\^[A-Za-z0-9_./-]+ ]] && continue # an anchored command + [[ "$pat" == /* ]] && { echo "pgrep/pkill -f on a bare path ($pat): anchor it on the exact command line (^$pat) or use a pid file (rule 5)"; return 1; } [[ "$pat" =~ ^\[.\] ]] && continue # the bracket form never matches its own command line - echo "pgrep/pkill -f with a plain literal ($pat): it matches the calling shell's own command line; use the bracket form ([${pat:0:1}]${pat:1}), -x on the binary name, or a pid file"; return 1 + echo "pgrep/pkill -f with a plain literal ($pat): it matches the calling shell's own command line; use the bracket form ([${pat:0:1}]${pat:1}), an anchored ^command, -x on the binary name, or a pid file (rule 5)"; return 1 done if [[ "$code" =~ (^|[^A-Za-z0-9_./-])(pgrep|pkill)[[:space:]]+(-[A-Za-z0-9]+[[:space:]]+)*(\"[^\"]*\"|\'[^\']*\'|[^[:space:]|;\)-][^[:space:]|;\)]*) ]]; then pat="${BASH_REMATCH[4]}"; pat="${pat#[\"\']}"; pat="${pat%[\"\']}" @@ -90,6 +98,9 @@ if [ "${1:-}" = "--self-test" ]; then 'pkill node-1.pid' "bash -c 'pkill -f \"[i]gneum-prove-host\"; pkill -f prove-shard.sh; true'" "pgrep -fl 'igneumd --' | grep -v Wallet" + 'pkill -f /opt/igneum/bin/igneumd' + 'pgrep -f "/srv/fleet/bin/igneum-miner --pool"' + 'pkill -f /srv/builds/igneum-wt-ca3-v4-node/tools/build-remote.sh' ) good=( 'kill "$(cut -d" " -f1 .git/igneum-gate.pid)"' @@ -103,8 +114,9 @@ if [ "${1:-}" = "--self-test" ]; then 'pkill -F /srv/hands/node1.pid' 'kill "$(cat "$PIDFILE")"' 'pkill -f "$EXACT_CMD"' - 'pkill -f /opt/igneum/bin/igneumd' - 'pgrep -f "/srv/fleet/bin/igneum-miner --pool"' + 'pkill -f "^/opt/igneum/bin/igneumd"' + 'pgrep -f "^/srv/fleet/bin/igneum-miner --pool"' + 'pkill -f "^igneumd --"' '# pgrep -f igneumd is banned (a comment)' '// pkill -f wave.log in a comment' 'ps aux | grep "[i]gneumd"' diff --git a/tools/ci/kit-isa-check.sh b/tools/ci/kit-isa-check.sh new file mode 100755 index 000000000..08f56ac45 --- /dev/null +++ b/tools/ci/kit-isa-check.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# The kit ISA check (the founder's order through the coordinator, 8 October 2026, 20:2x UK): every binary in a distribution kit +# (igneumd, igneum-miner, the workers, the pool) is disassembled and RED if any AVX-512 instruction appears: a zmm register, an +# EVEX opmask ({k1}..{k7}, {z}), or an EVEX-only mnemonic (vpternlog, vpcompress, vpexpand, vpconflict, vplzcnt, vpermt2, vpermi2, +# vprol, vpror, vrndscale, vscalef, vfixupimm, vrange, vreduce, vgetexp, vgetmant, vpmovm2, vpmov*2m, kmov/kand/kor/kxor/kunpck, +# vscatter, vpbroadcastm, vcvtt*2usi, vdbpsadbw, vpmadd52). The fleet's 79 non-AVX-512 hosts died on a box's native gate build of +# 7cfa422a: a fleet binary comes only from the shipper's cross-build kit at the x86-64-v3 baseline, never a box's native build. +# tools/ci/kit-isa-check.sh [...] exit 0 clean, 1 red (the binary and the first offending lines named) +# tools/ci/kit-isa-check.sh --self-test a fake objdump (KIT_ISA_OBJDUMP) proves the rule both ways +set -euo pipefail +OBJDUMP="${KIT_ISA_OBJDUMP:-$(command -v llvm-objdump || command -v objdump || true)}" +PAT='%?zmm[0-9]|\{%?k[1-7]\}|\{z\}|\bvpternlog|\bvpcompress|\bvpexpand|\bvpconflict|\bvplzcnt|\bvpermt2|\bvpermi2|\bvprol|\bvpror|\bvrndscale|\bvscalef|\bvfixupimm|\bvrange|\bvreduce|\bvgetexp|\bvgetmant|\bvpmovm2|\bvpmov[a-z]*2m\b|\bk(mov|and|or|xor|unpck|not|test|ortest|add|shift)[a-z]*\b|\bvscatter|\bvpbroadcastm|\bvcvtt?[a-z]*2usi|\bvdbpsadbw|\bvpmadd52' +scan() { # -> prints "red : AVX-512 lines; first: " ; returns 1 when any + local b="$1" hits n + [ -n "$OBJDUMP" ] || { echo "red $b: no objdump on this machine (install llvm or run the check on a box)"; return 1; } + hits=$("$OBJDUMP" -d --no-show-raw-insn "$b" 2>/dev/null | grep -E "$PAT" || true) + n=$(printf '%s' "$hits" | grep -c . || true) + if [ "${n:-0}" -gt 0 ]; then echo "red $b: $n AVX-512 lines; first: $(printf '%s\n' "$hits" | head -1 | tr -s ' \t' ' ' | cut -c1-120)"; return 1; fi + echo "ok $b: no AVX-512 instruction"; return 0 +} +if [ "${1:-}" = --self-test ]; then + d=$(mktemp -d); trap 'rm -rf "$d"' EXIT; fails=0 + cat > "$d/objdump" <<'FAKE' +#!/usr/bin/env bash +b="${@: -1}" +case "$b" in + *avx512*) printf ' 401000: vmovdqu64 %%zmm0, (%%rax)\n 401006: vpternlogd $0x96, %%zmm1, %%zmm2, %%zmm3\n 40100c: vmovdqu8 %%ymm0, (%%rax){%%k1}\n' ;; + *mask*) printf ' 401000: vaddps %%ymm0, %%ymm1, %%ymm2{k2}{z}\n' ;; + *) printf ' 401000: vmovdqu %%ymm0, (%%rax)\n 401004: vpaddd %%ymm1, %%ymm2, %%ymm3\n 401008: mov %%rax, %%rbx\n 40100c: vpermq $0x1b, %%ymm0, %%ymm1\n' ;; +esac +FAKE + chmod +x "$d/objdump"; : > "$d/node-avx512"; : > "$d/node-mask"; : > "$d/node-v3" + out=$(KIT_ISA_OBJDUMP="$d/objdump" bash "$0" "$d/node-avx512" 2>&1) && { echo "self-test failed: a zmm/vpternlog binary passed"; fails=1; }; case "$out" in *"3 AVX-512 lines"*) ;; *) echo "self-test failed: the three lines were not counted: $out"; fails=1 ;; esac + out=$(KIT_ISA_OBJDUMP="$d/objdump" bash "$0" "$d/node-mask" 2>&1) && { echo "self-test failed: an opmask-only line passed"; fails=1; } + KIT_ISA_OBJDUMP="$d/objdump" bash "$0" "$d/node-v3" >/dev/null 2>&1 || { echo "self-test failed: an AVX2-only binary was refused: $(KIT_ISA_OBJDUMP="$d/objdump" bash "$0" "$d/node-v3" 2>&1)"; fails=1; } + mkdir -p "$d/kit"; : > "$d/kit/igneumd-v3"; : > "$d/kit/worker-avx512"; chmod +x "$d/kit/igneumd-v3" "$d/kit/worker-avx512" + out=$(KIT_ISA_OBJDUMP="$d/objdump" bash "$0" "$d/kit" 2>&1) && { echo "self-test failed: a kit dir with one AVX-512 binary passed"; fails=1; }; case "$out" in *"worker-avx512"*) ;; *) echo "self-test failed: the offending binary in the kit was not named: $out"; fails=1 ;; esac + [ "$fails" = 0 ] && echo "self-test passed: a binary with zmm registers, EVEX-only mnemonics or an opmask is red and counted; an AVX2 (x86-64-v3) binary passes; a kit directory names its offending binary" + exit $fails +fi +[ $# -ge 1 ] || { echo "usage: kit-isa-check.sh [...] | --self-test" >&2; exit 2; } +rc=0 +for a in "$@"; do + if [ -d "$a" ]; then while IFS= read -r b; do scan "$b" | sed 's/^red /kit-isa: RED: /; s/^ok /kit-isa: ok /' || rc=1; done < <(find "$a" -type f -perm -u+x ! -name '*.sh' ! -name '*.py' ! -name '*.ps1' ! -name '*.conf' ! -name '*.txt' ! -name '*.json' ! -name '*.sha256' | sort) + else scan "$a" | sed 's/^red /kit-isa: RED: /; s/^ok /kit-isa: ok /' || rc=1; fi +done +[ "$rc" = 0 ] && echo "kit-isa: every binary is clean of AVX-512 (the x86-64-v3 baseline)" +exit $rc diff --git a/tools/ci/merge-to-master.sh b/tools/ci/merge-to-master.sh index e38dd623f..65d20af58 100755 --- a/tools/ci/merge-to-master.sh +++ b/tools/ci/merge-to-master.sh @@ -319,6 +319,9 @@ RULE26_SKIP_PATHS=""; [ -n "$BATCHES" ] && RULE26_SKIP_PATHS="$REGISTRY_PATH" MAP_PATH="${MAP_PATH:-tools/ci/test-map.json}"; PAGE_PATH="${PAGE_PATH:-docs/plans/igneum-2.0-test-harness-map.md}" MAP_CHANGED=0; git diff --quiet "$BASE" "$SHA" -- "$MAP_PATH" 2>/dev/null || MAP_CHANGED=1 [ "$MAP_CHANGED" = 1 ] && RULE26_SKIP_PATHS="$RULE26_SKIP_PATHS $PAGE_PATH" +# the founder's word (8 October 2026, 20:21 UK): a kit landed in the tree is scanned for AVX-512 before the merge (packaging/kits/**, bin/**) +KITBINS=$(git diff --name-only --diff-filter=AM "$BASE" "$SHA" -- packaging/kits bin 2>/dev/null | while read -r f; do [ -f "$f" ] && [ -x "$f" ] && echo "$f"; done || true) +if [ -n "$KITBINS" ]; then bash tools/ci/kit-isa-check.sh $KITBINS || { echo "merge-to-master: REFUSED: a kit binary carries AVX-512 (above); a fleet binary comes only from the cross-build kit at x86-64-v3" >&2; exit 1; }; fi # rule 26 (8 October 2026, 17:5x UK): a site/ or docs/ path another lane landed since the branch point is merged, never replaced RULE26_SKIP_PATHS="$RULE26_SKIP_PATHS" bash tools/ci/rule26-no-revert.sh "$BASE" "$SHA" "$REMOTE/master" || { echo "merge-to-master: REFUSED by rule 26 (above)" >&2; exit 1; } # the registry's evidence rules (8 October 2026, 18:4x UK): a PASS carries existing evidence, a touched evidence file moves with its diff --git a/tools/ci/no-kill-shim/killall b/tools/ci/no-kill-shim/killall new file mode 100755 index 000000000..df6bd645c --- /dev/null +++ b/tools/ci/no-kill-shim/killall @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# The founder's word, 8 October 2026, 20:21 UK: killall refuses on the Mac. A process is stopped by its pid file (.git/igneum-gate.pid, +# .git/igneum-merge.pid, a hand's own pid file: `kill "$(cut -d' ' -f1 )"`) or by an exact pid read from a listing, never by a +# name or a pattern. Put this directory first in PATH: export PATH="$HOME/Projects/igneum/tools/ci/no-kill-shim:$PATH" +echo "killall: refused on this machine (the founder's word, 8 October 2026): kill by pid file or by an exact pid; never by a name or a pattern. Arguments were: $*" >&2 +exit 97 diff --git a/tools/ci/no-kill-shim/pkill b/tools/ci/no-kill-shim/pkill new file mode 100755 index 000000000..b72ca94d0 --- /dev/null +++ b/tools/ci/no-kill-shim/pkill @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# The founder's word, 8 October 2026, 20:21 UK: pkill refuses on the Mac. A process is stopped by its pid file (.git/igneum-gate.pid, +# .git/igneum-merge.pid, a hand's own pid file: `kill "$(cut -d' ' -f1 )"`) or by an exact pid read from a listing, never by a +# name or a pattern. Put this directory first in PATH: export PATH="$HOME/Projects/igneum/tools/ci/no-kill-shim:$PATH" +echo "pkill: refused on this machine (the founder's word, 8 October 2026): kill by pid file or by an exact pid; never by a name or a pattern. Arguments were: $*" >&2 +exit 97 diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index 1b0c3fa51..db2444ea6 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -174,6 +174,7 @@ tree_checks() { run "the harness map page is generated from tools/ci/test-map.json and current" node tools/ci/test-map-doc.mjs --check run "P01 part A, the million-vector driver: a clean run is PASS, one wrong hash or one unanswered nonce is FAIL naming it (self-test, a fake worker)" python3 tools/ci/p01-vectors.py --self-test run "the registry's evidence rules: a PASS names evidence that exists, a touched evidence file moves with its row, stale evidence never reads PASS, a run_status needs the approval (self-test)" bash tools/ci/registry-evidence-check.sh --self-test + run "the kit ISA check: a distribution kit's binaries carry no AVX-512 encoding (the x86-64-v3 baseline; self-test with a fake objdump)" bash tools/ci/kit-isa-check.sh --self-test run "F02 (Review B): the proof-rule test bypass cannot reach a release build: an env read with no cfg guard or under a default feature is red; a release binary carrying the bypass string is red (self-test)" bash tools/ci/proof-rule-bypass-check.sh --self-test run "the test map merges structurally at a landing: master's cells plus the branch's, minus what the branch removed and master left (self-test)" python3 tools/ci/test-map-merge.py --self-test run "the REV suite is generated from Review B's findings and dispatch and matches them (self-test, then the tree)" bash tools/ci/review-suite-check.sh diff --git a/tools/ci/test-record.mjs b/tools/ci/test-record.mjs index 6a4b5f49c..768b41e4e 100644 --- a/tools/ci/test-record.mjs +++ b/tools/ci/test-record.mjs @@ -36,6 +36,15 @@ function check(reg, map) { return { bad, lines: out, automated: cases.filter(isAutomated).length, mapped: [...mapped].length, notRun: Object.keys(notRun).length }; } function record(reg, map, batch) { + // the founder's word (8 October 2026, 20:21 UK): a sha is "cut" only when its binary exists on build-1 with its commit string read + // back, and a fleet binary only from the cross-build kit scanned clean of AVX-512; a batch that declares a cut carries all three + if (batch.cut) { + const c = batch.cut; const errs = []; + if (!/^build-\d+:\/srv\//.test(String(c.binary || ''))) errs.push('cut.binary must be a build-N:/srv/... path on a build box'); + if (!c.commit_string || !(String(c.commit_string).startsWith(String(batch.manifest_sha)) || String(batch.manifest_sha).startsWith(String(c.commit_string)))) errs.push(`cut.commit_string (${c.commit_string}) must be the read-back of the batch's manifest sha (${batch.manifest_sha})`); + if (!/every binary is clean of AVX-512/.test(String(c.kit_isa || ''))) errs.push('cut.kit_isa must carry tools/ci/kit-isa-check.sh\'s clean line over the kit'); + if (errs.length) throw new Error(`a cut batch is refused: ${errs.join('; ')}`); + } const cases = casesOf(reg); const byId = new Map(cases.map((c) => [idOf(c), c])); const touched = []; const now = new Date().toISOString(); for (const cell of batch.cells || []) { @@ -83,10 +92,14 @@ if (args.includes('--self-test')) { if (!(reg.cases[0].run_status === 'BLOCKED' && reg.cases[0].evidence_record.blocked_on?.[0] === 'pinned_keys')) { console.log(`self-test failed: a PASS with a missing prerequisite was not BLOCKED (INT-17): ${JSON.stringify(reg.cases[0].run_status)}`); fails = 1; } record(reg, map, { run_id: 'r4', manifest_sha: 'abc', cells: [{ cell: 'pow', status: 'PASS', evidence: '/e/pow.log', prereqs: { oracle: 'present', pinned_keys: 'present', real_proof_fixture: 'present' } }] }); if (reg.cases[0].run_status !== 'PASS') { console.log('self-test failed: a PASS with every prerequisite present was not written'); fails = 1; } + let cutThrew = false; try { record(reg, map, { run_id: 'c1', manifest_sha: 'abc', cut: { binary: '/root/x', commit_string: 'abc', kit_isa: 'clean' }, cells: [] }); } catch (e) { cutThrew = /cut batch is refused/.test(e.message); } + if (!cutThrew) { console.log('self-test failed: a cut batch without a box path and the ISA clean line was accepted'); fails = 1; } + let cutOk = true; try { record(reg, map, { run_id: 'c2', manifest_sha: 'abc1234', cut: { binary: 'build-1:/srv/artefacts/x/igneumd', commit_string: 'abc1234', kit_isa: 'kit-isa: every binary is clean of AVX-512 (the x86-64-v3 baseline)' }, cells: [] }); } catch { cutOk = false; } + if (!cutOk) { console.log('self-test failed: a cut batch with the read-back and the ISA line was refused'); fails = 1; } let threw = false; try { record(reg, map, { run_id: 'r2', manifest_sha: 'x', cells: [{ cell: 'ghost', status: 'PASS' }] }); } catch { threw = true; } if (!threw) { console.log('self-test failed: a batch naming a cell not in the map was accepted'); fails = 1; } fs.rmSync(d, { recursive: true, force: true }); - if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused; --note appends a dated note to a suite and never touches an accept text; an unchanged NOT RUN row is not re-stamped; a cell with a missing prerequisite is BLOCKED, never PASS (INT-17)'); + if (!fails) console.log('self-test passed: a complete map checks; an unknown case id and an unmapped Automated case are refused; a run batch writes run_status, run_id, evidence_path, updated and the evidence record to the mapped cases only, leaves every accept text byte-identical, gives an unmapped Automated case NOT RUN with its reason and a manual case nothing; a batch naming an unknown cell is refused; --note appends a dated note to a suite and never touches an accept text; an unchanged NOT RUN row is not re-stamped; a cell with a missing prerequisite is BLOCKED, never PASS (INT-17); a cut batch needs the binary on a box, the commit string read back and the kit ISA clean line'); process.exit(fails); } const reg = load(REG); const map = load(MAP);