@sabaiway/agent-workflow-kit 5.4.0 → 5.6.0

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 (49) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +1 -0
  3. package/SKILL.md +5 -1
  4. package/bridges/antigravity-cli-bridge/SKILL.md +1 -1
  5. package/bridges/antigravity-cli-bridge/bin/agy-review.sh +1 -1
  6. package/bridges/antigravity-cli-bridge/capability.json +1 -1
  7. package/bridges/codex-cli-bridge/SKILL.md +51 -4
  8. package/bridges/codex-cli-bridge/bin/codex-exec.sh +616 -24
  9. package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +700 -1
  10. package/bridges/codex-cli-bridge/bin/codex-review.sh +1 -1
  11. package/bridges/codex-cli-bridge/capability.json +15 -10
  12. package/capability.json +1 -1
  13. package/package.json +1 -1
  14. package/references/modes/dispatch.md +29 -0
  15. package/references/modes/gates.md +6 -3
  16. package/references/modes/procedures.md +2 -0
  17. package/references/modes/receipt-deadline.md +3 -3
  18. package/references/modes/recommendations.md +1 -1
  19. package/references/modes/velocity.md +1 -0
  20. package/tools/commands.mjs +7 -0
  21. package/tools/core-evidence.mjs +37 -3
  22. package/tools/detect-backends.mjs +5 -4
  23. package/tools/dispatch-record.mjs +10 -3
  24. package/tools/dispatch-store.mjs +392 -0
  25. package/tools/dispatch.mjs +1779 -0
  26. package/tools/doc-parity.mjs +10 -2
  27. package/tools/exec-producer.mjs +483 -0
  28. package/tools/exec-receipt.mjs +263 -0
  29. package/tools/flow-check-cores.mjs +253 -0
  30. package/tools/flow-check-git-lane.mjs +56 -0
  31. package/tools/flow-check-rungs.mjs +330 -0
  32. package/tools/flow-check.mjs +23 -611
  33. package/tools/flow-store.mjs +111 -462
  34. package/tools/gates-declaration.mjs +13 -1
  35. package/tools/gates-init.mjs +134 -22
  36. package/tools/procedures.mjs +64 -5
  37. package/tools/receipt-deadline.mjs +25 -3
  38. package/tools/recommendations.mjs +108 -7
  39. package/tools/release-scan.mjs +33 -0
  40. package/tools/source-size-check.mjs +320 -0
  41. package/tools/source-size-config.mjs +244 -0
  42. package/tools/source-size-core.mjs +53 -0
  43. package/tools/source-size-gate-cmd.mjs +55 -0
  44. package/tools/source-size-judge.mjs +114 -0
  45. package/tools/source-size-refusal.mjs +70 -0
  46. package/tools/source-size-report.mjs +254 -0
  47. package/tools/source-size-scope.mjs +145 -0
  48. package/tools/store-append.mjs +444 -0
  49. package/tools/velocity-profile.mjs +24 -3
@@ -8,6 +8,7 @@ import { tmpdir } from 'node:os';
8
8
  import { join, dirname, resolve } from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import { spawnSync, execFile } from 'node:child_process';
11
+ import { createHash } from 'node:crypto';
11
12
 
12
13
  const HERE = dirname(fileURLToPath(import.meta.url));
13
14
  const WRAPPER = join(HERE, 'codex-exec.sh');
@@ -29,6 +30,21 @@ const FAKE_CODEX = [
29
30
  '{ echo "HOME=${HOME:-}"; echo "CODEX_HOME=${CODEX_HOME:-}"; echo "XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-}"; echo "OPENAI_API_KEY=${OPENAI_API_KEY:-<unset>}"; echo "OPENAI_BASE_URL=${OPENAI_BASE_URL:-<unset>}"; echo "FOO_API_KEY=${FOO_API_KEY:-<unset>}"; echo "CODEX_REAL_GIT=${CODEX_REAL_GIT:-<unset>}"; } >"$CODEX_FAKE_ENV"',
30
31
  'cat >"$CODEX_FAKE_STDIN"',
31
32
  'if [[ "${CODEX_FAKE_GIT_PROBE:-}" == "1" ]]; then { echo "realgit_env=${CODEX_REAL_GIT:-unset}"; echo "status=$(git status --short >/dev/null 2>&1; echo $?)"; echo "diff=$(git --no-pager diff >/dev/null 2>&1; echo $?)"; echo "dashC_read=$(git -C . status --short >/dev/null 2>&1; echo $?)"; echo "dashc_read=$(git -c core.pager=cat status --short >/dev/null 2>&1; echo $?)"; echo "bare=$(git >/dev/null 2>&1; echo $?)"; echo "commit=$(git commit -m x >/dev/null 2>&1; echo $?)"; echo "add=$(git add -A >/dev/null 2>&1; echo $?)"; echo "checkout=$(git checkout -- . >/dev/null 2>&1; echo $?)"; echo "unknown=$(git frobnicate >/dev/null 2>&1; echo $?)"; echo "config_read=$(git config user.name >/dev/null 2>&1; echo $?)"; echo "config_list=$(git config --list >/dev/null 2>&1; echo $?)"; echo "config_bare=$(git config >/dev/null 2>&1; echo $?)"; echo "config_write=$(git config user.name HACKED >/dev/null 2>&1; echo $?)"; echo "config_bypass=$(git config --get --add a.b v >/dev/null 2>&1; echo $?)"; echo "symref_write=$(git symbolic-ref HEAD refs/heads/x >/dev/null 2>&1; echo $?)"; echo "reflog_write=$(git reflog expire --all >/dev/null 2>&1; echo $?)"; echo "cdaway=$(cd / && git --version >/dev/null 2>&1; echo $?)"; } > "${CODEX_FAKE_GIT_RESULT:-/dev/null}" 2>&1; fi',
33
+ // Delegation seams: the fake runs BETWEEN the pre-spend reservation and the terminal publication,
34
+ // which is the only moment a fixture can disturb either. TAMPER forges a foreign owner into the
35
+ // reservation; MKDIR plants a directory where an artifact must land; RO_DIR turns the store
36
+ // directory read-only. Each is inert when its variable is unset.
37
+ 'if [[ -n "${CODEX_FAKE_TAMPER:-}" ]]; then',
38
+ ' cat >"$CODEX_FAKE_TAMPER" <<EOF',
39
+ '{"schema":1,"kind":"exec-receipt","state":"reserved","backend":"codex","nonce":"${CODEX_FAKE_TAMPER_NONCE:-n1}","owner":"a-foreign-run","contractDigest":"${CODEX_FAKE_TAMPER_DIGEST:-0000000000000000000000000000000000000000000000000000000000000000}","wrapperVersion":"0.0.0","posture":{"model":"m","effort":"e","tier":null},"capS":1,"killGraceS":0,"sessionId":null,"exitStatus":null,"outcome":null,"reportDigest":null,"reportLength":null,"timestamp":"2026-01-01T00:00:00.000Z"}',
40
+ 'EOF',
41
+ 'fi',
42
+ 'if [[ -n "${CODEX_FAKE_MKDIR:-}" ]]; then mkdir -p "$CODEX_FAKE_MKDIR"; fi',
43
+ 'if [[ -n "${CODEX_FAKE_RO_DIR:-}" ]]; then chmod 500 "$CODEX_FAKE_RO_DIR"; fi',
44
+ // SNAPSHOT copies a file WHILE the CLI runs — the only way to observe what existed mid-flight.
45
+ // ABSENT is written rather than nothing, so "the file was not there" and "the seam never fired"
46
+ // stay distinguishable.
47
+ 'if [[ -n "${CODEX_FAKE_SNAPSHOT_SRC:-}" ]]; then cp "$CODEX_FAKE_SNAPSHOT_SRC" "$CODEX_FAKE_SNAPSHOT_DST" || echo ABSENT >"$CODEX_FAKE_SNAPSHOT_DST"; fi',
32
48
  'if [[ -n "${CODEX_FAKE_SLEEP:-}" ]]; then sleep "${CODEX_FAKE_SLEEP}"; fi',
33
49
  'out=""',
34
50
  'prev=""',
@@ -37,7 +53,9 @@ const FAKE_CODEX = [
37
53
  ' prev="$a"',
38
54
  'done',
39
55
  'if [[ -n "$out" ]]; then',
40
- ' if [[ "${CODEX_FAKE_NO_OUT:-}" != "1" ]]; then echo "${CODEX_FAKE_FINAL:-FAKE_FINAL_MESSAGE}" >"$out"; fi',
56
+ // EMPTY_OUT creates the capture file and writes NOTHING into it — the case that must stay
57
+ // distinguishable from NO_OUT, where the file is never created at all.
58
+ ' if [[ "${CODEX_FAKE_EMPTY_OUT:-}" == "1" ]]; then : >"$out"; elif [[ "${CODEX_FAKE_NO_OUT:-}" != "1" ]]; then echo "${CODEX_FAKE_FINAL:-FAKE_FINAL_MESSAGE}" >"$out"; fi',
41
59
  ' if [[ "${CODEX_FAKE_NO_THREAD:-}" != "1" ]]; then',
42
60
  ' cat <<EOF',
43
61
  '{"type":"thread.started","thread_id":"${CODEX_FAKE_THREAD_ID:-fake-thread-123}"}',
@@ -1733,3 +1751,684 @@ describe('codex-exec.sh — dispatch-posture labeling (D5, AD-061)', () => {
1733
1751
  }
1734
1752
  });
1735
1753
  });
1754
+
1755
+ // ── the delegation dispatch identity: nonce seam, reservation, fail-closed receipt ────────────────
1756
+ // The exec lane's arrival identity (delegation Plan 2, Phase 3). Two halves are load-bearing and
1757
+ // tested apart: the PRE-SPEND reservation, which is what makes one nonce mean one dispatch, and the
1758
+ // TERMINAL publication, which is fail-closed where the review lane's receipt only warns.
1759
+ // A nonce-LESS run is the no-regression pin — every suite above drives one, and none of them may
1760
+ // see an artifact.
1761
+
1762
+ const STORE_BASENAME = 'agent-workflow-delegation.jsonl';
1763
+ const receiptName = (nonce, backend = 'codex') => `agent-workflow-exec-receipt-${backend.length}-${backend}-${nonce}.json`;
1764
+ const reportName = (nonce, backend = 'codex') => `agent-workflow-exec-report-${backend.length}-${backend}-${nonce}.txt`;
1765
+ // The store directory a nonce-less-by-default sandbox resolves to: the git common dir of the repo.
1766
+ const storeDirOf = (sb) => join(sb.repo, '.git');
1767
+ const execArtifacts = (dir) => {
1768
+ let names;
1769
+ try { names = readdirSync(dir); } catch { return []; }
1770
+ return names.filter((n) => n.startsWith('agent-workflow-exec-')).sort();
1771
+ };
1772
+ const readReceipt = (dir, nonce) => JSON.parse(readFileSync(join(dir, receiptName(nonce)), 'utf8'));
1773
+
1774
+ // A dispatch file carrying exactly ONE top-level contract block — the same shape `dispatch open
1775
+ // --contract` parses, so the digest the wrapper computes here is the digest the ledger recorded.
1776
+ const CONTRACT_FENCE = '```';
1777
+ const writeContract = (sb, nonce, over = {}) => {
1778
+ const contract = {
1779
+ schema: 1,
1780
+ nonce,
1781
+ stepClass: 'code',
1782
+ vehicle: { requested: 'codex-exec', selected: 'codex-exec' },
1783
+ scope: 'the bounded sub-task', inputs: 'the files it may touch', acceptance: 'the named tests',
1784
+ returnShape: 'a diff plus a report', producerContract: 'wrapper-git',
1785
+ deadlineS: 3700,
1786
+ retry: { cap: 1, index: 0 },
1787
+ ...over,
1788
+ };
1789
+ const rel = `${nonce}-dispatch.md`;
1790
+ writeFileSync(join(sb.repo, rel),
1791
+ `# sub-task\n\n${CONTRACT_FENCE}aw-dispatch-contract\n${JSON.stringify(contract, null, 2)}\n${CONTRACT_FENCE}\n`);
1792
+ return rel;
1793
+ };
1794
+
1795
+ // run() reads the capture files the PREVIOUS run left behind, so a test proving "the CLI was never
1796
+ // invoked" has to clear them first — otherwise a stale argv reads as a fresh invocation.
1797
+ const clearCaptures = (sb) => {
1798
+ for (const name of ['.cap-argv', '.cap-env', '.cap-stdin']) rmSync(join(sb.repo, name), { force: true });
1799
+ };
1800
+
1801
+ describe('codex-exec.sh — the nonce seam (D11)', () => {
1802
+ it('a nonce-LESS run writes NO artifact into the store directory', () => {
1803
+ const sb = makeSandbox();
1804
+ const file = writeContract(sb, 'unused');
1805
+ const r = run(sb, { args: [file] });
1806
+ const artifacts = execArtifacts(storeDirOf(sb));
1807
+ rmSync(sb.root, { recursive: true, force: true });
1808
+ assert.equal(r.status, 0, r.stderr);
1809
+ assert.deepEqual(artifacts, [], 'a nonce-less invocation is byte-unchanged — no reservation, no receipt');
1810
+ assert.doesNotMatch(r.stderr, /exec receipt:/, 'and it says nothing about a receipt either');
1811
+ });
1812
+
1813
+ it('each of the three D11 argv forms is accepted and reaches the right mode', () => {
1814
+ const cases = [
1815
+ { label: 'fresh', args: (f) => ['--nonce', 'nf', f], nonce: 'nf', wantSession: 'fake-thread-123', resume: false },
1816
+ { label: 'resume-last', args: (f) => ['--resume-last', '--nonce', 'nl', f], nonce: 'nl', wantSession: 'sess-from-sidecar', resume: true },
1817
+ { label: 'resume', args: (f) => ['--resume', 'sess-xyz', '--nonce', 'nr', f], nonce: 'nr', wantSession: 'sess-xyz', resume: true },
1818
+ ];
1819
+ for (const c of cases) {
1820
+ const sb = makeSandbox();
1821
+ writeFileSync(join(sb.repo, '.codex-last-session'), 'sess-from-sidecar\n');
1822
+ const file = writeContract(sb, c.nonce);
1823
+ const r = run(sb, { args: c.args(file) });
1824
+ const receipt = r.status === 0 ? readReceipt(storeDirOf(sb), c.nonce) : null;
1825
+ rmSync(sb.root, { recursive: true, force: true });
1826
+ assert.equal(r.status, 0, `${c.label}: ${r.stderr}`);
1827
+ assert.match(r.argv, /(^|\n)exec(\n|$)/, `${c.label}: codex exec was really reached`);
1828
+ assert.equal(/(^|\n)resume(\n|$)/.test(r.argv), c.resume, `${c.label}: the mode selector survived the nonce strip`);
1829
+ assert.equal(receipt.state, 'terminal', `${c.label}: the run published its terminal receipt`);
1830
+ assert.equal(receipt.nonce, c.nonce);
1831
+ assert.equal(receipt.sessionId, c.wantSession, `${c.label}: the session id is the run's own`);
1832
+ }
1833
+ });
1834
+
1835
+ it('a --nonce AFTER the prompt operand or after -- is payload, never a flag', () => {
1836
+ const sb = makeSandbox();
1837
+ const file = writeContract(sb, 'late');
1838
+ const passthrough = run(sb, { args: [file, '--', '--nonce', 'late'] });
1839
+ const afterOperand = run(sb, { args: [file, '--nonce', 'late'] });
1840
+ const artifacts = execArtifacts(storeDirOf(sb));
1841
+ rmSync(sb.root, { recursive: true, force: true });
1842
+ assert.equal(passthrough.status, 0, passthrough.stderr);
1843
+ assert.match(passthrough.argv, /(^|\n)--nonce(\n|$)/, 'after -- it reaches codex argv as payload');
1844
+ assert.deepEqual(artifacts, [], 'and it never minted a dispatch identity');
1845
+ assert.equal(afterOperand.status, 2, 'without -- an extra argument is the existing loud refusal');
1846
+ assert.match(afterOperand.stderr, /unexpected argument '--nonce'/);
1847
+ });
1848
+
1849
+ it('the flag and the environment value are ONE seam: agreeing runs, disagreeing refuses pre-spend', () => {
1850
+ const agree = makeSandbox();
1851
+ const agreeFile = writeContract(agree, 'same');
1852
+ const ok = run(agree, { args: ['--nonce', 'same', agreeFile], env: { AW_DISPATCH_NONCE: 'same' } });
1853
+ const okState = ok.status === 0 ? readReceipt(storeDirOf(agree), 'same').state : null;
1854
+ rmSync(agree.root, { recursive: true, force: true });
1855
+ assert.equal(ok.status, 0, ok.stderr);
1856
+ assert.equal(okState, 'terminal');
1857
+
1858
+ const clash = makeSandbox();
1859
+ const clashFile = writeContract(clash, 'flagnonce');
1860
+ const bad = run(clash, { args: ['--nonce', 'flagnonce', clashFile], env: { AW_DISPATCH_NONCE: 'envnonce' } });
1861
+ const artifacts = execArtifacts(storeDirOf(clash));
1862
+ rmSync(clash.root, { recursive: true, force: true });
1863
+ assert.equal(bad.status, 2);
1864
+ assert.match(bad.stderr, /--nonce disagrees with the AW_DISPATCH_NONCE environment value/);
1865
+ assert.equal(bad.argv, '', 'the refusal precedes any spend');
1866
+ assert.deepEqual(artifacts, [], 'and it reserves nothing');
1867
+ });
1868
+
1869
+ it('a nonce outside the safe grammar refuses pre-spend, from either source', () => {
1870
+ for (const bad of ['a/b', '../x', 'a b', 'x'.repeat(65), '']) {
1871
+ const viaFlag = makeSandbox();
1872
+ const file = writeContract(viaFlag, 'grammar');
1873
+ const f = run(viaFlag, { args: ['--nonce', bad, file] });
1874
+ const flagArtifacts = execArtifacts(storeDirOf(viaFlag));
1875
+ rmSync(viaFlag.root, { recursive: true, force: true });
1876
+ assert.equal(f.status, 2, `--nonce "${bad}" must refuse`);
1877
+ assert.match(f.stderr, /fails the safe nonce grammar/);
1878
+ assert.equal(f.argv, '', 'nothing was spent');
1879
+ assert.deepEqual(flagArtifacts, [], 'nothing was reserved');
1880
+
1881
+ if (bad === '') continue; // an EMPTY env value is "unset" to the seam, not a bad nonce
1882
+ const viaEnv = makeSandbox();
1883
+ const e = run(viaEnv, { args: [writeContract(viaEnv, 'grammar')], env: { AW_DISPATCH_NONCE: bad } });
1884
+ rmSync(viaEnv.root, { recursive: true, force: true });
1885
+ assert.equal(e.status, 2, `AW_DISPATCH_NONCE "${bad}" must refuse`);
1886
+ assert.match(e.stderr, /AW_DISPATCH_NONCE fails the safe nonce grammar/);
1887
+ }
1888
+ });
1889
+
1890
+ it('a duplicate --nonce refuses, and a --nonce with no value refuses', () => {
1891
+ const sb = makeSandbox();
1892
+ const file = writeContract(sb, 'dup');
1893
+ const dup = run(sb, { args: ['--nonce', 'dup', '--nonce', 'other', file] });
1894
+ const bare = run(sb, { args: ['--nonce'] });
1895
+ rmSync(sb.root, { recursive: true, force: true });
1896
+ assert.equal(dup.status, 2);
1897
+ assert.match(dup.stderr, /duplicate --nonce — one dispatch carries one nonce/);
1898
+ assert.equal(bare.status, 2);
1899
+ assert.match(bare.stderr, /--nonce needs a value/);
1900
+ });
1901
+
1902
+ it('an accounted dispatch needs a contract FILE: stdin and a header-less file both refuse pre-spend', () => {
1903
+ const sb = makeSandbox();
1904
+ const stdin = run(sb, { args: ['--nonce', 'n1', '-'], input: 'do the thing' });
1905
+ writeFileSync(join(sb.repo, 'plain.md'), '# just a plan\n\nno contract block here\n');
1906
+ clearCaptures(sb);
1907
+ const headerless = run(sb, { args: ['--nonce', 'n1', 'plain.md'] });
1908
+ const artifacts = execArtifacts(storeDirOf(sb));
1909
+ rmSync(sb.root, { recursive: true, force: true });
1910
+ assert.equal(stdin.status, 2);
1911
+ assert.match(stdin.stderr, /a nonced dispatch runs a contract FILE, not stdin/);
1912
+ assert.equal(headerless.status, 2);
1913
+ assert.match(headerless.stderr, /no top-level ```aw-dispatch-contract block found/);
1914
+ assert.equal(headerless.argv, '', 'neither refusal spent a run');
1915
+ assert.deepEqual(artifacts, [], 'neither refusal reserved a nonce');
1916
+ });
1917
+ });
1918
+
1919
+ describe('codex-exec.sh — the pre-spend reservation (D1/D8)', () => {
1920
+ it('the reservation EXISTS, in state reserved, while the CLI is still running', () => {
1921
+ // The ordering claim needs a mid-flight observation. Asserting it from a SECOND run would prove
1922
+ // nothing: by then the first run has finished and left a TERMINAL artifact, so moving the
1923
+ // reservation to after the CLI would keep such a test green. The fake copies the receipt while
1924
+ // it runs; only a genuinely pre-spend reservation can be `reserved` at that moment.
1925
+ const sb = makeSandbox();
1926
+ const file = writeContract(sb, 'midflight');
1927
+ const snapshot = join(sb.root, 'receipt-during-the-run.json');
1928
+ const r = run(sb, {
1929
+ args: ['--nonce', 'midflight', file],
1930
+ env: { CODEX_FAKE_SNAPSHOT_SRC: join(storeDirOf(sb), receiptName('midflight')), CODEX_FAKE_SNAPSHOT_DST: snapshot },
1931
+ });
1932
+ const seen = readFileSync(snapshot, 'utf8');
1933
+ rmSync(sb.root, { recursive: true, force: true });
1934
+ assert.equal(r.status, 0, r.stderr);
1935
+ assert.notEqual(seen.trim(), 'ABSENT', 'the receipt must already exist when the CLI starts');
1936
+ assert.equal(JSON.parse(seen).state, 'reserved', 'and it is the RESERVATION — the terminal receipt comes later');
1937
+ });
1938
+
1939
+ it('a second dispatch on the same nonce refuses unspent, leaving the first run\'s evidence untouched', () => {
1940
+ const sb = makeSandbox();
1941
+ const file = writeContract(sb, 'once');
1942
+ const first = run(sb, { args: ['--nonce', 'once', file] });
1943
+ const receiptPath = join(storeDirOf(sb), receiptName('once'));
1944
+ const afterFirst = readFileSync(receiptPath, 'utf8');
1945
+ clearCaptures(sb);
1946
+ const second = run(sb, { args: ['--nonce', 'once', file] });
1947
+ const afterSecond = readFileSync(receiptPath, 'utf8');
1948
+ rmSync(sb.root, { recursive: true, force: true });
1949
+ assert.equal(first.status, 0, first.stderr);
1950
+ assert.equal(second.status, 2, 'one nonce, one dispatch');
1951
+ assert.match(second.stderr, /already exists at .* one nonce, one dispatch: refusing PRE-SPEND/);
1952
+ assert.equal(second.argv, '', 'the CLI was never invoked — the refusal is PRE-spend, proven by the fake recording nothing');
1953
+ assert.equal(afterSecond, afterFirst, 'the first dispatch\'s evidence is byte-untouched');
1954
+ });
1955
+
1956
+ it('the dispatch nonce must equal the contract header\'s nonce — a disagreement refuses unspent', () => {
1957
+ // `dispatch open` COPIES the nonce from the header, so a disagreeing --nonce could only reserve
1958
+ // an identity no return would ever absorb — after paying for the run.
1959
+ const sb = makeSandbox();
1960
+ const file = writeContract(sb, 'header');
1961
+ const r = run(sb, { args: ['--nonce', 'other', file] });
1962
+ const artifacts = execArtifacts(storeDirOf(sb));
1963
+ rmSync(sb.root, { recursive: true, force: true });
1964
+ assert.equal(r.status, 2);
1965
+ assert.match(r.stderr, /the dispatch nonce 'other' does not match the contract header's nonce 'header'/);
1966
+ assert.equal(r.argv, '', 'the refusal precedes the spend');
1967
+ assert.deepEqual(artifacts, [], 'and precedes the reservation');
1968
+ });
1969
+
1970
+ it('a nonce-LESS run of a contract-bearing file never compares nonces — the accounted lane owns that rule', () => {
1971
+ const sb = makeSandbox();
1972
+ const file = writeContract(sb, 'header');
1973
+ const r = run(sb, { args: [file] });
1974
+ const artifacts = execArtifacts(storeDirOf(sb));
1975
+ rmSync(sb.root, { recursive: true, force: true });
1976
+ assert.equal(r.status, 0, r.stderr);
1977
+ assert.deepEqual(artifacts, [], 'an ordinary plan file that happens to carry a contract block still runs unaccounted');
1978
+ });
1979
+
1980
+ it('a store directory whose parent name ends in a NEWLINE resolves as the kit resolves it', () => {
1981
+ // `$( )` strips every trailing newline; the kit's own reader strips exactly ONE (git's
1982
+ // terminator). Without a sentinel the two sides would resolve different directories here, and the
1983
+ // wrapper would write beside a ledger the kit never reads.
1984
+ const sb = makeSandbox();
1985
+ const weird = join(sb.root, 'ledger\n');
1986
+ mkdirSync(weird, { recursive: true });
1987
+ const file = writeContract(sb, 'nlstore');
1988
+ const r = run(sb, { args: ['--nonce', 'nlstore', file], env: { AW_DELEGATION_STORE: join(weird, STORE_BASENAME) } });
1989
+ const landed = execArtifacts(weird);
1990
+ rmSync(sb.root, { recursive: true, force: true });
1991
+ assert.equal(r.status, 0, r.stderr);
1992
+ assert.deepEqual(landed, [receiptName('nlstore'), reportName('nlstore')].sort(),
1993
+ 'the artifacts land in the directory the kit would compute, newline and all');
1994
+ });
1995
+
1996
+ it('an already-taken REPORT name refuses the reservation too — the kit refuses on either name', () => {
1997
+ const sb = makeSandbox();
1998
+ const file = writeContract(sb, 'leftover');
1999
+ writeFileSync(join(storeDirOf(sb), reportName('leftover')), 'a report from something else\n');
2000
+ const r = run(sb, { args: ['--nonce', 'leftover', file] });
2001
+ rmSync(sb.root, { recursive: true, force: true });
2002
+ assert.equal(r.status, 2);
2003
+ assert.match(r.stderr, /already exists at .*agent-workflow-exec-report-5-codex-leftover\.txt/);
2004
+ assert.equal(r.argv, '', 'nothing was spent');
2005
+ });
2006
+
2007
+ it('a NONCED run with no capping binary refuses pre-spend, while a nonce-less one still warns and runs', () => {
2008
+ const sb = makeSandbox();
2009
+ const file = writeContract(sb, 'uncapped');
2010
+ const path = `${sb.bin}:${farmFor(['timeout', 'gtimeout'])}`;
2011
+ const nonced = run(sb, { args: ['--nonce', 'uncapped', file], path });
2012
+ const artifacts = execArtifacts(storeDirOf(sb));
2013
+ clearCaptures(sb);
2014
+ const plain = run(sb, { args: [file], path });
2015
+ rmSync(sb.root, { recursive: true, force: true });
2016
+ assert.equal(nonced.status, 2, nonced.stderr);
2017
+ assert.match(nonced.stderr, /a nonced dispatch refuses to run uncapped/);
2018
+ assert.equal(nonced.argv, '', 'the refusal precedes the spend');
2019
+ assert.deepEqual(artifacts, [], 'and precedes the reservation');
2020
+ assert.equal(plain.status, 0, plain.stderr);
2021
+ assert.match(plain.stderr, /running codex WITHOUT a hard wall-clock cap/, 'the nonce-less lane is unchanged');
2022
+ });
2023
+
2024
+ it('a PREFLIGHT refusal leaves NO reservation (login guard, missing AGENTS.md, off-pin model)', () => {
2025
+ const cases = [
2026
+ { label: 'login', env: { CODEX_FAKE_LOGIN: 'Not logged in' } },
2027
+ { label: 'model', env: { CODEX_MODEL: 'gpt-5.4-mini' } },
2028
+ { label: 'agents', env: {}, drop: true },
2029
+ ];
2030
+ for (const c of cases) {
2031
+ const sb = makeSandbox();
2032
+ const file = writeContract(sb, 'preflight');
2033
+ if (c.drop) rmSync(join(sb.repo, 'AGENTS.md'), { force: true });
2034
+ const r = run(sb, { args: ['--nonce', 'preflight', file], env: c.env });
2035
+ const artifacts = execArtifacts(storeDirOf(sb));
2036
+ rmSync(sb.root, { recursive: true, force: true });
2037
+ assert.notEqual(r.status, 0, `${c.label}: the preflight must refuse`);
2038
+ assert.deepEqual(artifacts, [], `${c.label}: a refused run leaves no reservation`);
2039
+ }
2040
+ });
2041
+
2042
+ it('the reservation carries everything knowable PRE-SPEND and nulls every terminal-only field', () => {
2043
+ // Proven on the artifact the CLI-blocking refusal leaves behind: a second dispatch is refused
2044
+ // pre-spend, so the FIRST run's reservation is the only shape a fixture can observe mid-flight —
2045
+ // instead, block the terminal publication and read the surviving reservation.
2046
+ const sb = makeSandbox();
2047
+ const file = writeContract(sb, 'resv');
2048
+ const r = run(sb, {
2049
+ args: ['--nonce', 'resv', file],
2050
+ env: { CODEX_FAKE_MKDIR: join(storeDirOf(sb), reportName('resv')) },
2051
+ });
2052
+ const held = readReceipt(storeDirOf(sb), 'resv');
2053
+ rmSync(sb.root, { recursive: true, force: true });
2054
+ assert.equal(r.status, 71, r.stderr);
2055
+ assert.equal(held.state, 'reserved');
2056
+ assert.equal(held.wrapperVersion, MANIFEST.version, 'the receipt stamps the bridge version version-sync bumps');
2057
+ assert.deepEqual(held.posture, { model: 'gpt-5.6-sol', effort: 'xhigh', tier: null });
2058
+ assert.equal(held.capS, 3600);
2059
+ assert.equal(held.killGraceS, 15);
2060
+ assert.match(held.contractDigest, /^[0-9a-f]{64}$/);
2061
+ for (const field of ['sessionId', 'exitStatus', 'outcome', 'reportDigest', 'reportLength']) {
2062
+ assert.equal(held[field], null, `a reservation proves nothing about ${field}`);
2063
+ }
2064
+ });
2065
+
2066
+ it('the store directory resolves as the kit resolves it: absolute override wins, relative and trailing-separator refuse', () => {
2067
+ const sb = makeSandbox();
2068
+ const file = writeContract(sb, 'store');
2069
+ const elsewhere = join(sb.root, 'ledger');
2070
+ mkdirSync(elsewhere, { recursive: true });
2071
+ const ok = run(sb, { args: ['--nonce', 'store', file], env: { AW_DELEGATION_STORE: join(elsewhere, STORE_BASENAME) } });
2072
+ const landed = execArtifacts(elsewhere);
2073
+ clearCaptures(sb);
2074
+ const rel = run(sb, { args: ['--nonce', 'store2', writeContract(sb, 'store2')], env: { AW_DELEGATION_STORE: `ledger/${STORE_BASENAME}` } });
2075
+ clearCaptures(sb);
2076
+ const trailing = run(sb, { args: ['--nonce', 'store3', writeContract(sb, 'store3')], env: { AW_DELEGATION_STORE: `${elsewhere}/` } });
2077
+ rmSync(sb.root, { recursive: true, force: true });
2078
+ assert.equal(ok.status, 0, ok.stderr);
2079
+ assert.deepEqual(landed, [receiptName('store'), reportName('store')].sort(), 'both artifacts land in the override\'s dirname');
2080
+ assert.equal(rel.status, 2);
2081
+ assert.match(rel.stderr, /AW_DELEGATION_STORE must be an ABSOLUTE path/);
2082
+ assert.equal(trailing.status, 2);
2083
+ assert.match(trailing.stderr, /must not end with a path separator/);
2084
+ });
2085
+ });
2086
+
2087
+ describe('codex-exec.sh — the fail-closed terminal receipt (D1/D3/3.1.d)', () => {
2088
+ it('a SUCCESSFUL run publishes a complete report and a terminal receipt that describes it', () => {
2089
+ const sb = makeSandbox();
2090
+ const file = writeContract(sb, 'ok');
2091
+ const r = run(sb, { args: ['--nonce', 'ok', file] });
2092
+ const dir = storeDirOf(sb);
2093
+ const receipt = readReceipt(dir, 'ok');
2094
+ const report = readFileSync(join(dir, reportName('ok')));
2095
+ rmSync(sb.root, { recursive: true, force: true });
2096
+ assert.equal(r.status, 0, r.stderr);
2097
+ assert.equal(receipt.state, 'terminal');
2098
+ assert.equal(receipt.outcome, 'success');
2099
+ assert.equal(receipt.exitStatus, 0);
2100
+ assert.equal(receipt.reportLength, report.length, 'the receipt describes the bytes on disk');
2101
+ assert.equal(receipt.reportDigest, createHash('sha256').update(report).digest('hex'));
2102
+ assert.equal(report.toString(), 'FAKE_FINAL_MESSAGE\n', 'the report IS the delegate\'s final message');
2103
+ assert.match(r.stderr, /exec receipt: nonce=ok outcome=success exit=0 session=fake-thread-123/);
2104
+ });
2105
+
2106
+ it('a FAILED run still publishes a terminal receipt — with its exit status, outcome and session id', () => {
2107
+ const sb = makeSandbox();
2108
+ const file = writeContract(sb, 'boom');
2109
+ const r = run(sb, { args: ['--nonce', 'boom', file], env: { CODEX_FAKE_EXIT: '5' } });
2110
+ const receipt = readReceipt(storeDirOf(sb), 'boom');
2111
+ rmSync(sb.root, { recursive: true, force: true });
2112
+ assert.equal(r.status, 5, 'the wrapper still exits with the run\'s own status');
2113
+ assert.equal(receipt.state, 'terminal');
2114
+ assert.equal(receipt.exitStatus, 5);
2115
+ assert.equal(receipt.outcome, 'transport-failure');
2116
+ assert.equal(receipt.sessionId, 'fake-thread-123', 'the session id is captured BEFORE outcome branching — a failed run has one too');
2117
+ assert.match(r.stderr, /error: codex exec failed \(exit 5\)/, 'the failure diagnostics still print, and BEFORE the receipt line');
2118
+ assert.ok(r.stderr.indexOf('codex exec failed') < r.stderr.indexOf('exec receipt:'), 'a publication never swallows the trace tail');
2119
+ });
2120
+
2121
+ it('an ABSENT capture and an EXISTING EMPTY one both record zero bytes — and neither is a failed probe', () => {
2122
+ // `mktemp` used to pre-create the capture file, so ENOENT could never occur and "absent" was not
2123
+ // a case the publisher could even see. It matters because of what it collides with: once an
2124
+ // absent capture is possible, the fail-closed read-error branch has to tell it apart from a
2125
+ // genuinely UNREADABLE one (the test below) instead of treating every errno alike.
2126
+ // What the two cases here do NOT get is a difference in the RECEIPT: the D2 key set is frozen and
2127
+ // has no field for "the delegate wrote nothing at all", so both record the sha256 of no bytes —
2128
+ // stated rather than papered over, and the outcome stays D3's (rc 0 + a session id is success).
2129
+ const absent = makeSandbox();
2130
+ const absentFile = writeContract(absent, 'noout');
2131
+ const a = run(absent, { args: ['--nonce', 'noout', absentFile], env: { CODEX_FAKE_NO_OUT: '1' } });
2132
+ const absentReceipt = readReceipt(storeDirOf(absent), 'noout');
2133
+ const absentReport = readFileSync(join(storeDirOf(absent), reportName('noout')));
2134
+ rmSync(absent.root, { recursive: true, force: true });
2135
+ assert.equal(a.status, 0, a.stderr);
2136
+ assert.match(a.stderr, /codex produced no final-message file/, 'the run says it has no answer rather than printing an empty one');
2137
+ assert.equal(absentReport.length, 0);
2138
+ assert.equal(absentReceipt.reportLength, 0);
2139
+ assert.equal(absentReceipt.reportDigest, createHash('sha256').update(Buffer.alloc(0)).digest('hex'),
2140
+ 'an absent final message is recorded as the sha256 of NO bytes, never as a failed probe');
2141
+
2142
+ const empty = makeSandbox();
2143
+ const emptyFile = writeContract(empty, 'emptyout');
2144
+ const e = run(empty, { args: ['--nonce', 'emptyout', emptyFile], env: { CODEX_FAKE_EMPTY_OUT: '1' } });
2145
+ const emptyReceipt = readReceipt(storeDirOf(empty), 'emptyout');
2146
+ rmSync(empty.root, { recursive: true, force: true });
2147
+ assert.equal(e.status, 0, e.stderr);
2148
+ assert.equal(emptyReceipt.reportLength, 0, 'an EXISTING empty capture records zero bytes too');
2149
+ assert.equal(emptyReceipt.reportDigest, absentReceipt.reportDigest,
2150
+ 'DELIBERATE: the frozen D2 key set has no field that separates them, so the receipt does not pretend to');
2151
+ assert.match(e.stderr, /codex produced no final-message file/,
2152
+ 'the existing-but-EMPTY capture takes the same -s fallback — it too has no answer to print');
2153
+ });
2154
+
2155
+ it('an UNREADABLE final message is a failed probe — exit 71, never a silent empty report', () => {
2156
+ const sb = makeSandbox();
2157
+ const file = writeContract(sb, 'unread');
2158
+ // A DIRECTORY at the capture path: readable-as-a-path, unreadable as a file (EISDIR), and
2159
+ // distinct from ENOENT — which is exactly the errno split the fold turns on.
2160
+ nodeShimWith(sb, 'eisdir.cjs', `
2161
+ const fs = require('node:fs');
2162
+ const real = fs.readFileSync;
2163
+ fs.readFileSync = (target, ...rest) => {
2164
+ if (typeof target === 'string' && target.endsWith('final-message.txt')) {
2165
+ const err = new Error('EISDIR: injected unreadable capture');
2166
+ err.code = 'EISDIR';
2167
+ throw err;
2168
+ }
2169
+ return real(target, ...rest);
2170
+ };
2171
+ `);
2172
+ const r = run(sb, { args: ['--nonce', 'unread', file] });
2173
+ const receipt = readReceipt(storeDirOf(sb), 'unread');
2174
+ rmSync(sb.root, { recursive: true, force: true });
2175
+ assert.equal(r.status, 71, r.stderr);
2176
+ assert.match(r.stderr, /is a FAILED probe, not an absent one/);
2177
+ assert.equal(receipt.state, 'reserved', 'nothing terminal was published over a probe that failed');
2178
+ });
2179
+
2180
+ it('a DANGLING SYMLINK at the capture path is a failed probe, never a clean empty report', () => {
2181
+ // The trap the ENOENT split set for itself: readFileSync FOLLOWS the link, so a dangling one
2182
+ // reports ENOENT — indistinguishable from "the delegate wrote nothing" — and a corrupt capture
2183
+ // would be published as an empty report on a `success` receipt. lstat decides first.
2184
+ const sb = makeSandbox();
2185
+ const file = writeContract(sb, 'dangle');
2186
+ nodeShimWith(sb, 'dangling.cjs', `
2187
+ const fs = require('node:fs');
2188
+ const realLstat = fs.lstatSync;
2189
+ fs.lstatSync = (target, ...rest) => {
2190
+ if (typeof target === 'string' && target.endsWith('final-message.txt')) {
2191
+ return { isFile: () => false, isSymbolicLink: () => true, isDirectory: () => false };
2192
+ }
2193
+ return realLstat(target, ...rest);
2194
+ };
2195
+ `);
2196
+ const r = run(sb, { args: ['--nonce', 'dangle', file] });
2197
+ const receipt = readReceipt(storeDirOf(sb), 'dangle');
2198
+ rmSync(sb.root, { recursive: true, force: true });
2199
+ assert.equal(r.status, 71, r.stderr);
2200
+ assert.match(r.stderr, /is a symlink, not a regular file — a CORRUPT capture is a FAILED probe/);
2201
+ assert.equal(receipt.state, 'reserved', 'nothing terminal was published over a corrupt capture');
2202
+ });
2203
+
2204
+ it('a run that identified no session records sessionId null with outcome missing-identity', () => {
2205
+ const sb = makeSandbox();
2206
+ const file = writeContract(sb, 'anon');
2207
+ const r = run(sb, { args: ['--nonce', 'anon', file], env: { CODEX_FAKE_NO_THREAD: '1' } });
2208
+ const receipt = readReceipt(storeDirOf(sb), 'anon');
2209
+ rmSync(sb.root, { recursive: true, force: true });
2210
+ assert.equal(r.status, 0, r.stderr);
2211
+ assert.equal(receipt.sessionId, null);
2212
+ assert.equal(receipt.outcome, 'missing-identity', 'exit 0 without an identity is never "success"');
2213
+ });
2214
+
2215
+ it('a TIMEOUT publishes exitStatus 124 with outcome transport-failure', async () => {
2216
+ const sb = makeSandbox();
2217
+ const file = writeContract(sb, 'slow');
2218
+ const r = await runAsync(sb, {
2219
+ args: ['--nonce', 'slow', file],
2220
+ env: { CODEX_FAKE_SLEEP: '3', CODEX_HARD_TIMEOUT: '1' },
2221
+ });
2222
+ const receipt = readReceipt(storeDirOf(sb), 'slow');
2223
+ rmSync(sb.root, { recursive: true, force: true });
2224
+ assert.equal(r.status, 124, r.stderr);
2225
+ assert.equal(receipt.exitStatus, 124);
2226
+ assert.equal(receipt.outcome, 'transport-failure', 'the timeout codes are transport-failure like any other nonzero exit');
2227
+ assert.match(r.stderr, /exceeded the hard cap/);
2228
+ });
2229
+
2230
+ it('a FOREIGN owner refuses with NOTHING published — both artifacts stay byte-unchanged', () => {
2231
+ const sb = makeSandbox();
2232
+ const file = writeContract(sb, 'tamper');
2233
+ const dir = storeDirOf(sb);
2234
+ const r = run(sb, {
2235
+ args: ['--nonce', 'tamper', file],
2236
+ env: { CODEX_FAKE_TAMPER: join(dir, receiptName('tamper')), CODEX_FAKE_TAMPER_NONCE: 'tamper' },
2237
+ });
2238
+ const receipt = readFileSync(join(dir, receiptName('tamper')), 'utf8');
2239
+ const reportExists = existsSync(join(dir, reportName('tamper')));
2240
+ rmSync(sb.root, { recursive: true, force: true });
2241
+ assert.equal(r.status, 70, r.stderr);
2242
+ assert.match(r.stderr, /is not this run’s reservation before any publication/);
2243
+ assert.match(JSON.parse(receipt).owner, /^a-foreign-run$/, 'the foreign reservation is left exactly as it was found');
2244
+ assert.equal(reportExists, false, 'a foreign owner publishes NOTHING — not even the report');
2245
+ assert.match(r.stderr, /PARTIALLY EDITED/, 'and the tree is named dirtied, never silently accepted');
2246
+ });
2247
+
2248
+ it('a failed REPORT write exits 71 naming the report, and the reservation survives for --no-receipt', () => {
2249
+ const sb = makeSandbox();
2250
+ const file = writeContract(sb, 'noreport');
2251
+ const dir = storeDirOf(sb);
2252
+ const r = run(sb, {
2253
+ args: ['--nonce', 'noreport', file],
2254
+ env: { CODEX_FAKE_MKDIR: join(dir, reportName('noreport')) },
2255
+ });
2256
+ const receipt = readReceipt(dir, 'noreport');
2257
+ rmSync(sb.root, { recursive: true, force: true });
2258
+ assert.equal(r.status, 71, r.stderr);
2259
+ assert.match(r.stderr, /the delegate’s report could not be published/);
2260
+ assert.equal(receipt.state, 'reserved', 'no terminal receipt EVER appears without a complete report behind it');
2261
+ assert.match(r.stderr, /dispatch return --nonce noreport --no-receipt --exit-status 0 --outcome <o>/);
2262
+ });
2263
+
2264
+ it('an UNWRITABLE store directory stops the REPORT lane nonzero and says the tree is dirtied — NOT the review lane\'s warn-only receipt', () => {
2265
+ // Named for the branch it really reaches. Both artifacts live in one directory, so a directory
2266
+ // turned read-only stops the FIRST write — the report. The two POST-report branches need a
2267
+ // failure injected between the writes, which the two tests below do.
2268
+ const sb = makeSandbox();
2269
+ const file = writeContract(sb, 'rodir');
2270
+ const store = join(sb.root, 'ledger');
2271
+ mkdirSync(store, { recursive: true });
2272
+ const r = run(sb, {
2273
+ args: ['--nonce', 'rodir', file],
2274
+ env: { AW_DELEGATION_STORE: join(store, STORE_BASENAME), CODEX_FAKE_RO_DIR: store },
2275
+ });
2276
+ chmodSync(store, 0o700);
2277
+ const surviving = readReceipt(store, 'rodir');
2278
+ rmSync(sb.root, { recursive: true, force: true });
2279
+ assert.notEqual(r.status, 0, 'codex-review.sh warns and returns 0 here; the exec lane must not');
2280
+ assert.equal(r.status, 71, r.stderr);
2281
+ assert.match(r.stderr, /the delegate’s report could not be published/);
2282
+ assert.match(r.stderr, /Nothing beyond the reservation was published/);
2283
+ assert.match(r.stderr, /the working tree may be PARTIALLY EDITED/);
2284
+ assert.equal(surviving.state, 'reserved', 'the reservation survives, so --no-receipt can still absorb the thread');
2285
+ });
2286
+ });
2287
+
2288
+ // ── the two POST-report branches ─────────────────────────────────────────────────────────────────
2289
+ // Reaching them needs a failure BETWEEN the report write and the terminal replace, and no filesystem
2290
+ // state a fixture can set up does that: both artifacts share one directory, so every such condition
2291
+ // stops the report first. The failure is injected instead — through a `node` shim on the sandbox
2292
+ // PATH, the SAME mechanism this suite already uses to exercise missing binaries. It is deliberately
2293
+ // NOT NODE_OPTIONS: the wrapper CLEARS that for every mint core precisely so an inherited
2294
+ // `--require` cannot rewrite `fs` under the owner checks and the publication, and a test that leaned
2295
+ // on it would be testing a hole rather than the behaviour.
2296
+ const nodeShimWith = (sb, name, body) => {
2297
+ const hook = join(sb.root, name);
2298
+ writeFileSync(hook, body);
2299
+ writeFileSync(join(sb.bin, 'node'), [
2300
+ '#!/usr/bin/env bash',
2301
+ 'set -u',
2302
+ `exec ${process.execPath} --require ${hook} "$@"`,
2303
+ '',
2304
+ ].join('\n'), { mode: 0o755 });
2305
+ };
2306
+
2307
+ // Let the report rename through, then break the NEXT one — the terminal receipt is the only other
2308
+ // `.json` rename the publisher performs.
2309
+ const BREAK_RECEIPT_RENAME = `
2310
+ const fs = require('node:fs');
2311
+ const real = fs.renameSync;
2312
+ fs.renameSync = (from, to) => {
2313
+ if (String(to).endsWith('.json')) {
2314
+ const err = new Error('EACCES: injected terminal-receipt failure');
2315
+ err.code = 'EACCES';
2316
+ throw err;
2317
+ }
2318
+ return real(from, to);
2319
+ };
2320
+ `;
2321
+
2322
+ // Let the report rename through, then hand the SECOND owner check a foreign reservation.
2323
+ const FORGE_SECOND_CLAIM = `
2324
+ const fs = require('node:fs');
2325
+ const realRead = fs.readFileSync;
2326
+ const realRename = fs.renameSync;
2327
+ let reportPublished = false;
2328
+ fs.renameSync = (from, to) => {
2329
+ const out = realRename(from, to);
2330
+ if (String(to).endsWith('.txt')) reportPublished = true;
2331
+ return out;
2332
+ };
2333
+ fs.readFileSync = (target, ...rest) => {
2334
+ const bytes = realRead(target, ...rest);
2335
+ if (reportPublished && typeof target === 'string' && target.endsWith('.json')) {
2336
+ const held = JSON.parse(String(bytes));
2337
+ held.owner = 'a-foreign-run';
2338
+ return JSON.stringify(held);
2339
+ }
2340
+ return bytes;
2341
+ };
2342
+ `;
2343
+
2344
+ describe('codex-exec.sh — the POST-report failure lanes never claim an untouched tree', () => {
2345
+ it('a terminal-receipt write that fails AFTER the report exits 71 and says the report IS published', () => {
2346
+ const sb = makeSandbox();
2347
+ const file = writeContract(sb, 'postr');
2348
+ nodeShimWith(sb, 'break-receipt.cjs', BREAK_RECEIPT_RENAME);
2349
+ const dir = storeDirOf(sb);
2350
+ const r = run(sb, { args: ['--nonce', 'postr', file] });
2351
+ const receipt = readReceipt(dir, 'postr');
2352
+ const report = readFileSync(join(dir, reportName('postr')), 'utf8');
2353
+ rmSync(sb.root, { recursive: true, force: true });
2354
+ assert.equal(r.status, 71, r.stderr);
2355
+ assert.match(r.stderr, /the terminal exec receipt could not be published/);
2356
+ assert.match(r.stderr, /The REPORT is published; the terminal receipt was NOT completed/);
2357
+ assert.doesNotMatch(r.stderr, /NOTHING was published/, 'the message must not deny bytes that are on disk');
2358
+ assert.equal(report, 'FAKE_FINAL_MESSAGE\n', 'the published report is complete and readable');
2359
+ assert.equal(receipt.state, 'reserved', 'the replace never happened, so the reservation is what survives here');
2360
+ });
2361
+
2362
+ it('a SECOND owner check that fails after the report exits 71 without claiming nothing was published', () => {
2363
+ const sb = makeSandbox();
2364
+ const file = writeContract(sb, 'forge');
2365
+ nodeShimWith(sb, 'forge-owner.cjs', FORGE_SECOND_CLAIM);
2366
+ const dir = storeDirOf(sb);
2367
+ const r = run(sb, { args: ['--nonce', 'forge', file] });
2368
+ const reportExists = existsSync(join(dir, reportName('forge')));
2369
+ rmSync(sb.root, { recursive: true, force: true });
2370
+ assert.equal(r.status, 71, r.stderr);
2371
+ assert.match(r.stderr, /is not this run’s reservation immediately before the terminal replace: its owner token belongs to ANOTHER run/);
2372
+ assert.match(r.stderr, /The REPORT is published; the terminal receipt was NOT completed/);
2373
+ assert.doesNotMatch(r.stderr, /NOTHING was published/, 'after the report is on disk that claim is false');
2374
+ assert.equal(reportExists, true, 'and the report really is there — which is what the message says');
2375
+ });
2376
+
2377
+ it('an inherited NODE_OPTIONS cannot reach the mint cores — the wrapper clears it', () => {
2378
+ // The regression guard for the hole the two tests above used to lean on: a --require inherited
2379
+ // from the caller's environment could rewrite `fs` inside the owner checks and the publication.
2380
+ // Here the SAME preload that breaks the receipt rename is handed to the wrapper as NODE_OPTIONS
2381
+ // rather than through the PATH shim; the run must be entirely unaffected.
2382
+ const sb = makeSandbox();
2383
+ const file = writeContract(sb, 'envopt');
2384
+ const hook = join(sb.root, 'break-receipt.cjs');
2385
+ writeFileSync(hook, BREAK_RECEIPT_RENAME);
2386
+ const r = run(sb, { args: ['--nonce', 'envopt', file], env: { NODE_OPTIONS: `--require=${hook}` } });
2387
+ const receipt = readReceipt(storeDirOf(sb), 'envopt');
2388
+ rmSync(sb.root, { recursive: true, force: true });
2389
+ assert.equal(r.status, 0, r.stderr);
2390
+ assert.equal(receipt.state, 'terminal', 'the publication completed — the injected failure never reached it');
2391
+ assert.equal(receipt.outcome, 'success');
2392
+ });
2393
+
2394
+ it('a FIRST owner check that fails is the only lane that may claim NOTHING was published', () => {
2395
+ const sb = makeSandbox();
2396
+ const file = writeContract(sb, 'first');
2397
+ const dir = storeDirOf(sb);
2398
+ const r = run(sb, {
2399
+ args: ['--nonce', 'first', file],
2400
+ env: { CODEX_FAKE_TAMPER: join(dir, receiptName('first')), CODEX_FAKE_TAMPER_NONCE: 'first' },
2401
+ });
2402
+ const reportExists = existsSync(join(dir, reportName('first')));
2403
+ rmSync(sb.root, { recursive: true, force: true });
2404
+ assert.equal(r.status, 70, r.stderr);
2405
+ assert.match(r.stderr, /NOTHING was published — not the report, not the receipt/);
2406
+ assert.doesNotMatch(r.stderr, /--no-receipt --exit-status/, 'a foreign reservation is never a --no-receipt source: its posture belongs to another run');
2407
+ assert.equal(reportExists, false);
2408
+ });
2409
+ });
2410
+
2411
+ describe('codex-exec.sh — the inline node mint cores stay intact', () => {
2412
+ it('the wrapper parses', () => {
2413
+ // The apostrophe SCANNER this replaced is gone with the class it policed: every mint core now
2414
+ // rides a QUOTED heredoc, where an apostrophe is ordinary text. A scanner that had to model
2415
+ // shell quoting was a second parser for a problem the quoting choice created — and it had its own
2416
+ // blind spot (a JS line beginning `' ` read as a closing quote and ended the scan early).
2417
+ const syntax = spawnSync('bash', ['-n', WRAPPER], { encoding: 'utf8' });
2418
+ assert.equal(syntax.status, 0, syntax.stderr);
2419
+ });
2420
+
2421
+ it('every mint core is read by a BUILTIN, run with NODE_OPTIONS cleared, and asserted non-empty', () => {
2422
+ const source = readFileSync(WRAPPER, 'utf8');
2423
+ assert.equal((source.match(/^ *IFS= read -r -d '' aw_js <<'AW_JS' \|\| true$/gm) ?? []).length, 4,
2424
+ 'the four cores: the store-dir resolver, the contract header, the reservation, the terminal publication');
2425
+ assert.equal((source.match(/^AW_JS$/gm) ?? []).length, 4, 'each heredoc is terminated');
2426
+ assert.equal((source.match(/NODE_OPTIONS= node -e "\$aw_js"/g) ?? []).length, 4, 'every core runs with NODE_OPTIONS cleared');
2427
+ assert.equal((source.match(/aw_require_core "\$aw_js"/g) ?? []).length, 4, 'and none runs before it is proven non-empty');
2428
+ // The regressions this replaces, both live: a single-quoted -e string truncates on an apostrophe,
2429
+ // and a `$(cat …)` substitution turns a missing `cat` into `node -e ""` exiting 0 — a run that
2430
+ // publishes nothing and reports success.
2431
+ assert.equal((source.match(/node -e '/g) ?? []).length, 0, 'no core may go back to a single-quoted -e string');
2432
+ assert.equal((source.match(/node -e "\$\(cat/g) ?? []).length, 0, 'no core may go back to a cat substitution');
2433
+ });
2434
+ });