@sabaiway/agent-workflow-kit 6.0.0 → 7.0.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 (32) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -0
  3. package/SKILL.md +5 -1
  4. package/bridges/antigravity-cli-bridge/bin/agy-review-await-guard.test.mjs +176 -0
  5. package/bridges/antigravity-cli-bridge/bin/agy-review.sh +61 -14
  6. package/bridges/antigravity-cli-bridge/bin/agy-review.test.mjs +606 -467
  7. package/bridges/antigravity-cli-bridge/references/review-prompt.md +42 -4
  8. package/bridges/codex-cli-bridge/SKILL.md +18 -5
  9. package/bridges/codex-cli-bridge/bin/codex-await-guard.test.mjs +161 -0
  10. package/bridges/codex-cli-bridge/bin/codex-exec.sh +22 -17
  11. package/bridges/codex-cli-bridge/bin/codex-exec.test.mjs +356 -363
  12. package/bridges/codex-cli-bridge/bin/codex-review.sh +6 -6
  13. package/bridges/codex-cli-bridge/bin/codex-review.test.mjs +275 -286
  14. package/bridges/codex-cli-bridge/capability.json +1 -1
  15. package/bridges/codex-cli-bridge/references/driving-codex.md +4 -2
  16. package/bridges/codex-cli-bridge/references/sandbox-and-flags.md +3 -2
  17. package/bridges/codex-cli-bridge/setup/README.md +3 -1
  18. package/capability.json +1 -1
  19. package/package.json +1 -1
  20. package/references/hooks/gate-approve.mjs +1 -1
  21. package/references/modes/mcp.md +37 -0
  22. package/references/modes/recommendations.md +1 -0
  23. package/references/modes/uninstall.md +2 -1
  24. package/tools/commands.mjs +7 -0
  25. package/tools/direct-run.mjs +3 -0
  26. package/tools/doc-parity.mjs +18 -2
  27. package/tools/mcp-registration.mjs +283 -0
  28. package/tools/mcp-server.mjs +314 -0
  29. package/tools/mcp-stdio.mjs +229 -0
  30. package/tools/mcp.mjs +299 -0
  31. package/tools/recommendations.mjs +90 -1
  32. package/tools/uninstall.mjs +356 -45
@@ -115,15 +115,19 @@ const makePathWithout = (root, exclude = []) => {
115
115
  return dir;
116
116
  };
117
117
 
118
- const run = ({ repo, bin }, { args = ['code'], env = {}, path, cwd } = {}) => {
118
+ // ASYNCHRONOUS on purpose: a blocking dispatch holds the event loop for its whole duration, which
119
+ // pins this file to one core. Awaiting the child lets a `{ concurrency }` describe overlap its
120
+ // tests; the per-test environment still rides the CHILD's options, never `process.env`.
121
+ const run = ({ repo, bin }, { args = ['code'], env = {}, path, cwd } = {}) => new Promise((settle) => {
119
122
  const argvFile = join(repo, '.cap-argv');
120
123
  const envFile = join(repo, '.cap-env');
121
124
  const stdinFile = join(repo, '.cap-stdin');
122
125
  const codexHome = join(repo, '..', 'codex-home');
123
- const r = spawnSync('bash', [WRAPPER, ...args], {
126
+ const child = execFile('bash', [WRAPPER, ...args], {
124
127
  cwd: cwd || repo,
125
128
  encoding: 'utf8',
126
129
  timeout: 30000,
130
+ maxBuffer: 64 * 1024 * 1024,
127
131
  env: {
128
132
  PATH: path || `${bin}:${process.env.PATH}`,
129
133
  HOME: repo,
@@ -137,80 +141,65 @@ const run = ({ repo, bin }, { args = ['code'], env = {}, path, cwd } = {}) => {
137
141
  CODEX_FAKE_STDIN: stdinFile,
138
142
  ...env,
139
143
  },
140
- });
141
- const readIf = (p) => (existsSync(p) ? readFileSync(p, 'utf8') : '');
142
- return { ...r, codexHome, argv: readIf(argvFile), capEnv: readIf(envFile), capStdin: readIf(stdinFile) };
143
- };
144
-
145
- // Async twin of run() for the sleep-bound timeout test: spawnSync blocks the event loop for
146
- // the whole deliberate wait, so a concurrent describe could not overlap it. Same contract.
147
- const runAsync = ({ repo, bin }, { args = ['code'], env = {}, path, cwd } = {}) =>
148
- new Promise((done) => {
149
- const argvFile = join(repo, '.cap-argv');
150
- const envFile = join(repo, '.cap-env');
151
- const stdinFile = join(repo, '.cap-stdin');
152
- const codexHome = join(repo, '..', 'codex-home');
153
- const child = execFile('bash', [WRAPPER, ...args], {
154
- cwd: cwd || repo,
155
- encoding: 'utf8',
156
- timeout: 30000,
157
- env: {
158
- PATH: path || `${bin}:${process.env.PATH}`,
159
- HOME: repo,
160
- TMPDIR: process.env.TMPDIR ?? '/tmp',
161
- CODEX_HOME: codexHome,
162
- CODEX_FAKE_ARGV: argvFile,
163
- CODEX_FAKE_ENV: envFile,
164
- CODEX_FAKE_STDIN: stdinFile,
165
- ...env,
166
- },
167
- }, (error, stdout, stderr) => {
168
- const readIf = (p) => (existsSync(p) ? readFileSync(p, 'utf8') : '');
169
- done({ status: error ? (error.code ?? 1) : 0, stdout, stderr, codexHome, argv: readIf(argvFile), capEnv: readIf(envFile), capStdin: readIf(stdinFile) });
144
+ }, (error, stdout, stderr) => {
145
+ const readIf = (p) => (existsSync(p) ? readFileSync(p, 'utf8') : '');
146
+ settle({
147
+ status: error ? (error.code ?? 1) : 0, signal: error?.signal ?? null, stdout, stderr,
148
+ codexHome, argv: readIf(argvFile), capEnv: readIf(envFile), capStdin: readIf(stdinFile),
170
149
  });
171
- child.stdin.end();
172
150
  });
151
+ // The wrapper refuses many inputs BEFORE it reads stdin, so the pipe can already be closed here.
152
+ // The blocking spawn swallowed that; an async one throws EPIPE at the test. A closed pipe is the
153
+ // refusal working — but ONLY EPIPE is: any other write failure is a real fault and must reach
154
+ // the test instead of passing as a green.
155
+ child.stdin.on('error', (err) => { if (err.code !== 'EPIPE') throw err; });
156
+ child.stdin.end();
157
+ });
158
+
159
+ // runAsync was the async twin kept for the sleep-bound timeout test, back when run() blocked.
160
+ // run() IS that twin now, so the twin is one name pointing at it — two spawn paths could only drift.
161
+ const runAsync = run;
173
162
 
174
- describe('codex-review.sh — quality-first model/effort guard (1.1)', () => {
175
- it('refuses a non-default CODEX_MODEL', () => {
163
+ describe('codex-review.sh — quality-first model/effort guard (1.1)', { concurrency: 2 }, () => {
164
+ it('refuses a non-default CODEX_MODEL', async () => {
176
165
  const sb = makeSandbox();
177
- const r = run(sb, { env: { CODEX_MODEL: 'gpt-5.4-mini' } });
166
+ const r = await run(sb, { env: { CODEX_MODEL: 'gpt-5.4-mini' } });
178
167
  rmSync(sb.root, { recursive: true, force: true });
179
168
  assert.notEqual(r.status, 0);
180
- assert.match(r.stderr, /not the pinned frontier model/);
169
+ assert.match(r.stderr, /not the pinned model/);
181
170
  assert.equal(r.capStdin, '', 'codex must not be invoked when the guard fires');
182
171
  });
183
172
 
184
- it('refuses a non-default CODEX_EFFORT', () => {
173
+ it('refuses a non-default CODEX_EFFORT', async () => {
185
174
  const sb = makeSandbox();
186
- const r = run(sb, { env: { CODEX_EFFORT: 'high' } });
175
+ const r = await run(sb, { env: { CODEX_EFFORT: 'high' } });
187
176
  rmSync(sb.root, { recursive: true, force: true });
188
177
  assert.notEqual(r.status, 0);
189
178
  assert.match(r.stderr, /not the pinned max effort/);
190
179
  });
191
180
 
192
- it('CODEX_PROBE=1 relaxes the guard and warns', () => {
181
+ it('CODEX_PROBE=1 relaxes the guard and warns', async () => {
193
182
  const sb = makeSandbox();
194
- const r = run(sb, { env: { CODEX_PROBE: '1', CODEX_EFFORT: 'low' } });
183
+ const r = await run(sb, { env: { CODEX_PROBE: '1', CODEX_EFFORT: 'low' } });
195
184
  rmSync(sb.root, { recursive: true, force: true });
196
185
  assert.equal(r.status, 0, r.stderr);
197
186
  assert.match(r.stderr, /THROWAWAY PROBE MODE/);
198
187
  });
199
188
  });
200
189
 
201
- describe('codex-review.sh — clean output + session capture (1.2)', () => {
202
- it('prints ONLY the final findings, not the JSON event stream', () => {
190
+ describe('codex-review.sh — clean output + session capture (1.2)', { concurrency: 2 }, () => {
191
+ it('prints ONLY the final findings, not the JSON event stream', async () => {
203
192
  const sb = makeSandbox();
204
- const r = run(sb);
193
+ const r = await run(sb);
205
194
  rmSync(sb.root, { recursive: true, force: true });
206
195
  assert.equal(r.status, 0, r.stderr);
207
196
  assert.match(r.stdout, /FAKE_FINAL_MESSAGE/);
208
197
  assert.doesNotMatch(r.stdout, /thread\.started/);
209
198
  });
210
199
 
211
- it('passes the clean-capture flags and read-only sandbox to codex', () => {
200
+ it('passes the clean-capture flags and read-only sandbox to codex', async () => {
212
201
  const sb = makeSandbox();
213
- const r = run(sb);
202
+ const r = await run(sb);
214
203
  rmSync(sb.root, { recursive: true, force: true });
215
204
  for (const f of [/(^|\n)-o(\n|$)/, /(^|\n)--json(\n|$)/, /hide_agent_reasoning=true/,
216
205
  /(^|\n)read-only(\n|$)/]) {
@@ -218,9 +207,9 @@ describe('codex-review.sh — clean output + session capture (1.2)', () => {
218
207
  }
219
208
  });
220
209
 
221
- it('surfaces the session id on STDERR only — never the shared resume sidecar', () => {
210
+ it('surfaces the session id on STDERR only — never the shared resume sidecar', async () => {
222
211
  const sb = makeSandbox();
223
- const r = run(sb);
212
+ const r = await run(sb);
224
213
  const sidecar = join(sb.repo, '.codex-last-session');
225
214
  const wrote = existsSync(sidecar);
226
215
  rmSync(sb.root, { recursive: true, force: true });
@@ -228,35 +217,35 @@ describe('codex-review.sh — clean output + session capture (1.2)', () => {
228
217
  assert.equal(wrote, false, 'a review must NOT clobber codex-exec --resume-last target');
229
218
  });
230
219
 
231
- it('on a codex failure, prints the trace tail and exits codex code', () => {
220
+ it('on a codex failure, prints the trace tail and exits codex code', async () => {
232
221
  const sb = makeSandbox();
233
- const r = run(sb, { env: { CODEX_FAKE_EXIT: '5' } });
222
+ const r = await run(sb, { env: { CODEX_FAKE_EXIT: '5' } });
234
223
  rmSync(sb.root, { recursive: true, force: true });
235
224
  assert.equal(r.status, 5);
236
225
  assert.match(r.stderr, /codex review failed \(exit 5\)/);
237
226
  });
238
227
  });
239
228
 
240
- describe('codex-review.sh — leaner prompt + read-fence line (1.4 / 1.5)', () => {
241
- it('code mode: obeys AGENTS.md from context, states the read fence, no read-AGENTS action', () => {
229
+ describe('codex-review.sh — leaner prompt + read-fence line (1.4 / 1.5)', { concurrency: 2 }, () => {
230
+ it('code mode: obeys AGENTS.md from context, states the read fence, no read-AGENTS action', async () => {
242
231
  const sb = makeSandbox();
243
- const r = run(sb, { args: ['code'] });
232
+ const r = await run(sb, { args: ['code'] });
244
233
  rmSync(sb.root, { recursive: true, force: true });
245
234
  assert.match(r.capStdin, /already merged into your context/);
246
235
  assert.doesNotMatch(r.capStdin, /Also read the project's root AGENTS\.md/);
247
236
  assert.match(r.capStdin, /Do not read files outside this git working tree/);
248
237
  });
249
238
 
250
- it('code mode: appends extra focus', () => {
239
+ it('code mode: appends extra focus', async () => {
251
240
  const sb = makeSandbox();
252
- const r = run(sb, { args: ['code', 'the new reducer'] });
241
+ const r = await run(sb, { args: ['code', 'the new reducer'] });
253
242
  rmSync(sb.root, { recursive: true, force: true });
254
243
  assert.match(r.capStdin, /Extra focus: the new reducer/);
255
244
  });
256
245
 
257
- it('plan mode: includes the plan body and a PLAN-specific read fence', () => {
246
+ it('plan mode: includes the plan body and a PLAN-specific read fence', async () => {
258
247
  const sb = makeSandbox();
259
- const r = run(sb, { args: ['plan', 'plan.md'] });
248
+ const r = await run(sb, { args: ['plan', 'plan.md'] });
260
249
  rmSync(sb.root, { recursive: true, force: true });
261
250
  assert.match(r.capStdin, /Do a thing in two steps/);
262
251
  assert.match(r.capStdin, /the plan above plus the in-repo code/);
@@ -264,10 +253,10 @@ describe('codex-review.sh — leaner prompt + read-fence line (1.4 / 1.5)', () =
264
253
  });
265
254
  });
266
255
 
267
- describe('codex-review.sh — best-effort env read-fence (1.5)', () => {
268
- it('repoints HOME/XDG to a throwaway dir while keeping an absolute CODEX_HOME', () => {
256
+ describe('codex-review.sh — best-effort env read-fence (1.5)', { concurrency: 2 }, () => {
257
+ it('repoints HOME/XDG to a throwaway dir while keeping an absolute CODEX_HOME', async () => {
269
258
  const sb = makeSandbox();
270
- const r = run(sb);
259
+ const r = await run(sb);
271
260
  const home = (r.capEnv.match(/^HOME=(.*)$/m) || [])[1];
272
261
  const codexHome = (r.capEnv.match(/^CODEX_HOME=(.*)$/m) || [])[1];
273
262
  const xdg = (r.capEnv.match(/^XDG_CONFIG_HOME=(.*)$/m) || [])[1];
@@ -277,9 +266,9 @@ describe('codex-review.sh — best-effort env read-fence (1.5)', () => {
277
266
  assert.ok(xdg && xdg.startsWith(home), 'XDG_CONFIG_HOME must live under the fenced HOME');
278
267
  });
279
268
 
280
- it('resolves a literal ~/ in CODEX_HOME against HOME, not $PWD', () => {
269
+ it('resolves a literal ~/ in CODEX_HOME against HOME, not $PWD', async () => {
281
270
  const sb = makeSandbox();
282
- const r = run(sb, { env: { CODEX_HOME: '~/.codex' } });
271
+ const r = await run(sb, { env: { CODEX_HOME: '~/.codex' } });
283
272
  const codexHome = (r.capEnv.match(/^CODEX_HOME=(.*)$/m) || [])[1];
284
273
  rmSync(sb.root, { recursive: true, force: true });
285
274
  // HOME handed to the wrapper is sb.repo → ~/.codex must expand to <repo>/.codex,
@@ -288,10 +277,10 @@ describe('codex-review.sh — best-effort env read-fence (1.5)', () => {
288
277
  });
289
278
  });
290
279
 
291
- describe('codex-review.sh — subscription / config isolation (invariant)', () => {
292
- it('clears every *_API_KEY + OPENAI_BASE_URL and passes --ignore-user-config', () => {
280
+ describe('codex-review.sh — subscription / config isolation (invariant)', { concurrency: 2 }, () => {
281
+ it('clears every *_API_KEY + OPENAI_BASE_URL and passes --ignore-user-config', async () => {
293
282
  const sb = makeSandbox();
294
- const r = run(sb, { env: {
283
+ const r = await run(sb, { env: {
295
284
  OPENAI_API_KEY: 'sk-x', OPENAI_BASE_URL: 'http://evil.example', FOO_API_KEY: 'bar',
296
285
  } });
297
286
  rmSync(sb.root, { recursive: true, force: true });
@@ -303,7 +292,7 @@ describe('codex-review.sh — subscription / config isolation (invariant)', () =
303
292
  });
304
293
  });
305
294
 
306
- describe('codex-review.sh — hard timeout (1.3)', { concurrency: true }, () => {
295
+ describe('codex-review.sh — hard timeout (1.3)', { concurrency: 2 }, () => {
307
296
  it('kills a hung review at CODEX_HARD_TIMEOUT and reports it', async () => {
308
297
  const sb = makeSandbox();
309
298
  const started = Date.now();
@@ -317,10 +306,10 @@ describe('codex-review.sh — hard timeout (1.3)', { concurrency: true }, () =>
317
306
 
318
307
  // Flow-orchestration Phase 4.2 (#26): the uncapped lane is CLOSED — without a capping binary the
319
308
  // preflight refuses by name BEFORE any CLI run (the pre-fix wrapper warned and ran uncapped).
320
- it('fails CLOSED when neither timeout nor gtimeout is on PATH — refuses by name, codex never runs', () => {
309
+ it('fails CLOSED when neither timeout nor gtimeout is on PATH — refuses by name, codex never runs', async () => {
321
310
  const sb = makeSandbox();
322
311
  const path = `${sb.bin}:${farmFor(['timeout', 'gtimeout'])}`;
323
- const r = run(sb, { path });
312
+ const r = await run(sb, { path });
324
313
  rmSync(sb.root, { recursive: true, force: true });
325
314
  assert.equal(r.status, 127, 'the hard-timeout preflight is a refusal, never a warned uncapped run');
326
315
  assert.match(r.stderr, /hard-timeout preflight fails CLOSED/);
@@ -328,23 +317,23 @@ describe('codex-review.sh — hard timeout (1.3)', { concurrency: true }, () =>
328
317
  });
329
318
  });
330
319
 
331
- describe('codex-review.sh — precomputed diff for code mode (2.1)', () => {
332
- it('no-diff preflight: a clean tree exits 0 without spending a codex run', () => {
320
+ describe('codex-review.sh — precomputed diff for code mode (2.1)', { concurrency: 2 }, () => {
321
+ it('no-diff preflight: a clean tree exits 0 without spending a codex run', async () => {
333
322
  const sb = makeSandbox({ clean: true });
334
- const r = run(sb, { args: ['code'] });
323
+ const r = await run(sb, { args: ['code'] });
335
324
  rmSync(sb.root, { recursive: true, force: true });
336
325
  assert.equal(r.status, 0);
337
326
  assert.match(r.stderr, /no uncommitted changes to review/);
338
327
  assert.equal(r.capStdin, '', 'codex must NOT be invoked on a clean tree');
339
328
  });
340
329
 
341
- it('assembles repo map, status, staged + unstaged diffs; drops the run-git-yourself directive', () => {
330
+ it('assembles repo map, status, staged + unstaged diffs; drops the run-git-yourself directive', async () => {
342
331
  const sb = makeSandbox();
343
332
  const g = (...a) => spawnSync('git', a, { cwd: sb.repo, encoding: 'utf8' });
344
333
  writeFileSync(join(sb.repo, 'AGENTS.md'), '# AGENTS\n\nHard Constraints: none.\nan unstaged edit\n');
345
334
  writeFileSync(join(sb.repo, 'staged.mjs'), 'export const s = 1\n');
346
335
  g('add', 'staged.mjs');
347
- const r = run(sb, { args: ['code'] });
336
+ const r = await run(sb, { args: ['code'] });
348
337
  rmSync(sb.root, { recursive: true, force: true });
349
338
  assert.equal(r.status, 0, r.stderr);
350
339
  for (const sec of [/repo file map/, /git status/, /staged diff/, /unstaged diff/, /staged\.mjs/]) {
@@ -353,50 +342,50 @@ describe('codex-review.sh — precomputed diff for code mode (2.1)', () => {
353
342
  assert.doesNotMatch(r.capStdin, /Run `git status --short`/, 'the old self-discovery directive must be gone');
354
343
  });
355
344
 
356
- it('inlines untracked file CONTENTS, not just the path', () => {
345
+ it('inlines untracked file CONTENTS, not just the path', async () => {
357
346
  const sb = makeSandbox();
358
347
  writeFileSync(join(sb.repo, 'untra.txt'), 'UNIQUE_UNTRACKED_BODY\n');
359
- const r = run(sb, { args: ['code'] });
348
+ const r = await run(sb, { args: ['code'] });
360
349
  rmSync(sb.root, { recursive: true, force: true });
361
350
  assert.match(r.capStdin, /untracked: untra\.txt/);
362
351
  assert.match(r.capStdin, /UNIQUE_UNTRACKED_BODY/);
363
352
  });
364
353
 
365
- it('skips binary untracked files (noted; raw bytes not inlined)', () => {
354
+ it('skips binary untracked files (noted; raw bytes not inlined)', async () => {
366
355
  const sb = makeSandbox();
367
356
  writeFileSync(join(sb.repo, 'blob.bin'), Buffer.from([0x00, 0x01, 0x02, 0x00, 0x42]));
368
- const r = run(sb, { args: ['code'] });
357
+ const r = await run(sb, { args: ['code'] });
369
358
  rmSync(sb.root, { recursive: true, force: true });
370
359
  assert.match(r.capStdin, /binary, skipped\): blob\.bin/);
371
360
  });
372
361
 
373
- it('handles untracked paths with spaces (NUL-safe)', () => {
362
+ it('handles untracked paths with spaces (NUL-safe)', async () => {
374
363
  const sb = makeSandbox();
375
364
  writeFileSync(join(sb.repo, 'a b c.txt'), 'SPACED_BODY\n');
376
- const r = run(sb, { args: ['code'] });
365
+ const r = await run(sb, { args: ['code'] });
377
366
  rmSync(sb.root, { recursive: true, force: true });
378
367
  assert.match(r.capStdin, /untracked: a b c\.txt/);
379
368
  assert.match(r.capStdin, /SPACED_BODY/);
380
369
  });
381
370
 
382
- it('does not follow untracked symlinks (no out-of-tree content leak)', () => {
371
+ it('does not follow untracked symlinks (no out-of-tree content leak)', async () => {
383
372
  const sb = makeSandbox();
384
373
  const secret = join(sb.root, 'outside-secret.txt'); // OUTSIDE the repo
385
374
  writeFileSync(secret, 'TOP_SECRET_LEAK_MARKER\n');
386
375
  symlinkSync(secret, join(sb.repo, 'link-to-outside')); // untracked symlink → outside
387
- const r = run(sb, { args: ['code'] });
376
+ const r = await run(sb, { args: ['code'] });
388
377
  rmSync(sb.root, { recursive: true, force: true });
389
378
  assert.match(r.capStdin, /untracked \(symlink\): link-to-outside -> /);
390
379
  assert.doesNotMatch(r.capStdin, /TOP_SECRET_LEAK_MARKER/, 'symlink target content must never leak');
391
380
  });
392
381
 
393
- it('oversized → git-dir temp file: 600 perms, untruncated, carve-out fence, cleaned up', () => {
382
+ it('oversized → git-dir temp file: 600 perms, untruncated, carve-out fence, cleaned up', async () => {
394
383
  const sb = makeSandbox();
395
384
  writeFileSync(join(sb.repo, 'unique.txt'), 'OVERSIZE_UNIQUE_MARKER\n');
396
385
  writeFileSync(join(sb.repo, 'big.txt'), 'x'.repeat(5000));
397
386
  const perms = join(sb.root, 'cap-perms');
398
387
  const copy = join(sb.root, 'cap-diffcopy');
399
- const r = run(sb, { args: ['code'], env: {
388
+ const r = await run(sb, { args: ['code'], env: {
400
389
  CODEX_REVIEW_MAX_TOTAL_BYTES: '100', CODEX_FAKE_DIFF_PERMS: perms, CODEX_FAKE_DIFF_COPY: copy,
401
390
  } });
402
391
  const leftover = readdirSync(join(sb.repo, '.git')).filter((f) => f.startsWith('codex-review-diff.'));
@@ -415,29 +404,29 @@ describe('codex-review.sh — precomputed diff for code mode (2.1)', () => {
415
404
  });
416
405
  });
417
406
 
418
- describe('codex-review.sh — optional structured findings (2.2)', () => {
419
- it('CODEX_REVIEW_SCHEMA=1 passes --output-schema to codex', () => {
407
+ describe('codex-review.sh — optional structured findings (2.2)', { concurrency: 2 }, () => {
408
+ it('CODEX_REVIEW_SCHEMA=1 passes --output-schema to codex', async () => {
420
409
  const sb = makeSandbox();
421
410
  // Schema mode parses the schema's verdict FIELD (D4) — the fixture output must carry it.
422
- const r = run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1', CODEX_FAKE_FINAL: '{"verdict":"ship","findings":[]}' } });
411
+ const r = await run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1', CODEX_FAKE_FINAL: '{"verdict":"ship","findings":[]}' } });
423
412
  rmSync(sb.root, { recursive: true, force: true });
424
413
  assert.equal(r.status, 0, r.stderr);
425
414
  assert.match(r.argv, /(^|\n)--output-schema(\n|$)/);
426
415
  });
427
416
 
428
- it('is OFF by default — no --output-schema', () => {
417
+ it('is OFF by default — no --output-schema', async () => {
429
418
  const sb = makeSandbox();
430
- const r = run(sb, { args: ['code'] });
419
+ const r = await run(sb, { args: ['code'] });
431
420
  rmSync(sb.root, { recursive: true, force: true });
432
421
  assert.doesNotMatch(r.argv, /--output-schema/);
433
422
  });
434
423
 
435
- it('falls back to a raw-text run when the schema run fails (loud; exit 0) — and parses the TEXT verdict', () => {
424
+ it('falls back to a raw-text run when the schema run fails (loud; exit 0) — and parses the TEXT verdict', async () => {
436
425
  const sb = makeSandbox();
437
426
  // No CODEX_FAKE_FINAL: the fallback run emits the TEXT default (FAKE_FINAL_MESSAGE +
438
427
  // Verdict: ship) — the wrapper must parse the mode of the run that actually SUCCEEDED,
439
428
  // or every fallback would read verdict-less and die on the D4 arm.
440
- const r = run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1', CODEX_FAKE_FAIL_ON_SCHEMA: '1' } });
429
+ const r = await run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1', CODEX_FAKE_FAIL_ON_SCHEMA: '1' } });
441
430
  rmSync(sb.root, { recursive: true, force: true });
442
431
  assert.equal(r.status, 0, r.stderr);
443
432
  assert.match(r.stderr, /without the schema constraint/);
@@ -445,117 +434,117 @@ describe('codex-review.sh — optional structured findings (2.2)', () => {
445
434
  assert.match(r.stdout, /FAKE_FINAL_MESSAGE/);
446
435
  });
447
436
 
448
- it('schema ON makes the directive ask for schema JSON, not one-per-line text', () => {
437
+ it('schema ON makes the directive ask for schema JSON, not one-per-line text', async () => {
449
438
  const sb = makeSandbox();
450
- const r = run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1' } });
439
+ const r = await run(sb, { args: ['code'], env: { CODEX_REVIEW_SCHEMA: '1' } });
451
440
  rmSync(sb.root, { recursive: true, force: true });
452
441
  assert.match(r.capStdin, /JSON object matching the provided output schema/);
453
442
  assert.doesNotMatch(r.capStdin, /one per line/);
454
443
  });
455
444
 
456
- it('schema OFF (default) asks for one-finding-per-line text', () => {
445
+ it('schema OFF (default) asks for one-finding-per-line text', async () => {
457
446
  const sb = makeSandbox();
458
- const r = run(sb, { args: ['code'] });
447
+ const r = await run(sb, { args: ['code'] });
459
448
  rmSync(sb.root, { recursive: true, force: true });
460
449
  assert.match(r.capStdin, /one per line/);
461
450
  });
462
451
  });
463
452
 
464
- describe('codex-review.sh — environment preflight (fail fast, before a run)', () => {
465
- it('STOPs with 127 when codex is not on PATH', () => {
453
+ describe('codex-review.sh — environment preflight (fail fast, before a run)', { concurrency: 2 }, () => {
454
+ it('STOPs with 127 when codex is not on PATH', async () => {
466
455
  const sb = makeSandbox();
467
456
  const path = farmFor(['codex']); // no fake codex, no real codex
468
- const r = run(sb, { args: ['code'], path });
457
+ const r = await run(sb, { args: ['code'], path });
469
458
  rmSync(sb.root, { recursive: true, force: true });
470
459
  assert.equal(r.status, 127);
471
460
  assert.match(r.stderr, /'codex'.*not found on PATH/);
472
461
  assert.equal(r.capStdin, '', 'codex must never be invoked');
473
462
  });
474
463
 
475
- it('STOPs (exit 1) when codex is not on a ChatGPT subscription', () => {
464
+ it('STOPs (exit 1) when codex is not on a ChatGPT subscription', async () => {
476
465
  const sb = makeSandbox();
477
- const r = run(sb, { args: ['code'], env: { CODEX_FAKE_LOGIN: 'Logged in using API key' } });
466
+ const r = await run(sb, { args: ['code'], env: { CODEX_FAKE_LOGIN: 'Logged in using API key' } });
478
467
  rmSync(sb.root, { recursive: true, force: true });
479
468
  assert.equal(r.status, 1);
480
469
  assert.match(r.stderr, /not on a ChatGPT subscription/);
481
470
  assert.equal(r.capStdin, '', 'a wrong login must never spend a run');
482
471
  });
483
472
 
484
- it('STOPs (exit 2) when not inside a git work tree', () => {
473
+ it('STOPs (exit 2) when not inside a git work tree', async () => {
485
474
  const sb = makeSandbox();
486
475
  const nongit = join(sb.root, 'nongit');
487
476
  mkdirSync(nongit, { recursive: true });
488
477
  writeFileSync(join(nongit, 'AGENTS.md'), '# AGENTS\n');
489
- const r = run(sb, { args: ['code'], cwd: nongit });
478
+ const r = await run(sb, { args: ['code'], cwd: nongit });
490
479
  rmSync(sb.root, { recursive: true, force: true });
491
480
  assert.equal(r.status, 2);
492
481
  assert.match(r.stderr, /must run inside a git working tree/);
493
482
  });
494
483
 
495
- it('STOPs (exit 2) when there is no root AGENTS.md', () => {
484
+ it('STOPs (exit 2) when there is no root AGENTS.md', async () => {
496
485
  const sb = makeSandbox();
497
486
  rmSync(join(sb.repo, 'AGENTS.md'));
498
- const r = run(sb, { args: ['code'] });
487
+ const r = await run(sb, { args: ['code'] });
499
488
  rmSync(sb.root, { recursive: true, force: true });
500
489
  assert.equal(r.status, 2);
501
490
  assert.match(r.stderr, /no root AGENTS\.md/);
502
491
  });
503
492
  });
504
493
 
505
- describe('codex-review.sh — CODEX_HOME resolution arms (1.5)', () => {
506
- it('resolves a bare ~ in CODEX_HOME to HOME', () => {
494
+ describe('codex-review.sh — CODEX_HOME resolution arms (1.5)', { concurrency: 2 }, () => {
495
+ it('resolves a bare ~ in CODEX_HOME to HOME', async () => {
507
496
  const sb = makeSandbox();
508
- const r = run(sb, { args: ['code'], env: { CODEX_HOME: '~' } });
497
+ const r = await run(sb, { args: ['code'], env: { CODEX_HOME: '~' } });
509
498
  const codexHome = (r.capEnv.match(/^CODEX_HOME=(.*)$/m) || [])[1];
510
499
  rmSync(sb.root, { recursive: true, force: true });
511
500
  assert.equal(codexHome, sb.repo, 'bare ~ → the HOME handed to the wrapper');
512
501
  });
513
502
 
514
- it('anchors a relative CODEX_HOME to $PWD', () => {
503
+ it('anchors a relative CODEX_HOME to $PWD', async () => {
515
504
  const sb = makeSandbox();
516
- const r = run(sb, { args: ['code'], env: { CODEX_HOME: 'rel/.codex' } });
505
+ const r = await run(sb, { args: ['code'], env: { CODEX_HOME: 'rel/.codex' } });
517
506
  const codexHome = (r.capEnv.match(/^CODEX_HOME=(.*)$/m) || [])[1];
518
507
  rmSync(sb.root, { recursive: true, force: true });
519
508
  assert.equal(codexHome, join(sb.repo, 'rel/.codex'), 'a relative path anchors to cwd, never left bare');
520
509
  });
521
510
  });
522
511
 
523
- describe('codex-review.sh — mode dispatch & plan validation', () => {
524
- it('unknown mode prints usage and STOPs (exit 2)', () => {
512
+ describe('codex-review.sh — mode dispatch & plan validation', { concurrency: 2 }, () => {
513
+ it('unknown mode prints usage and STOPs (exit 2)', async () => {
525
514
  const sb = makeSandbox();
526
- const r = run(sb, { args: ['bogus'] });
515
+ const r = await run(sb, { args: ['bogus'] });
527
516
  rmSync(sb.root, { recursive: true, force: true });
528
517
  assert.equal(r.status, 2);
529
518
  assert.match(r.stderr, /usage: .* plan <plan-file> \[--nonce <n>\] \| code \[--nonce <n>\]/);
530
519
  });
531
520
 
532
- it('no mode prints usage and STOPs (exit 2)', () => {
521
+ it('no mode prints usage and STOPs (exit 2)', async () => {
533
522
  const sb = makeSandbox();
534
- const r = run(sb, { args: [] });
523
+ const r = await run(sb, { args: [] });
535
524
  rmSync(sb.root, { recursive: true, force: true });
536
525
  assert.equal(r.status, 2);
537
526
  assert.match(r.stderr, /usage:/);
538
527
  });
539
528
 
540
- it('plan mode: STOPs (exit 2) when the plan file is missing', () => {
529
+ it('plan mode: STOPs (exit 2) when the plan file is missing', async () => {
541
530
  const sb = makeSandbox();
542
- const r = run(sb, { args: ['plan', 'nope.md'] });
531
+ const r = await run(sb, { args: ['plan', 'nope.md'] });
543
532
  rmSync(sb.root, { recursive: true, force: true });
544
533
  assert.equal(r.status, 2);
545
534
  assert.match(r.stderr, /plan file 'nope\.md' not found/);
546
535
  });
547
536
 
548
- it('plan mode: STOPs (exit 2) on unexpected trailing arguments', () => {
537
+ it('plan mode: STOPs (exit 2) on unexpected trailing arguments', async () => {
549
538
  const sb = makeSandbox();
550
- const r = run(sb, { args: ['plan', 'plan.md', 'extra', 'junk'] });
539
+ const r = await run(sb, { args: ['plan', 'plan.md', 'extra', 'junk'] });
551
540
  rmSync(sb.root, { recursive: true, force: true });
552
541
  assert.equal(r.status, 2);
553
542
  assert.match(r.stderr, /unexpected arguments after plan file: extra junk/);
554
543
  });
555
544
  });
556
545
 
557
- describe('codex-review.sh — assemble & output edge cases', () => {
558
- it('skips a non-regular untracked path (an embedded git repo dir) without reading it', () => {
546
+ describe('codex-review.sh — assemble & output edge cases', { concurrency: 2 }, () => {
547
+ it('skips a non-regular untracked path (an embedded git repo dir) without reading it', async () => {
559
548
  // git enumerates an untracked path as non-regular only as a DIRECTORY: a FIFO /
560
549
  // socket / device is not listed by `git ls-files --others` at all, but an embedded
561
550
  // git repo surfaces as `nested/` — a directory, so `[[ ! -f ]]` skips it (and a
@@ -566,35 +555,35 @@ describe('codex-review.sh — assemble & output edge cases', () => {
566
555
  const g = (...a) => spawnSync('git', a, { cwd: nested, encoding: 'utf8' });
567
556
  g('init', '-q');
568
557
  writeFileSync(join(nested, 'inner.txt'), 'INNER_SHOULD_NOT_BE_INLINED\n');
569
- const r = run(sb, { args: ['code'] });
558
+ const r = await run(sb, { args: ['code'] });
570
559
  rmSync(sb.root, { recursive: true, force: true });
571
560
  assert.equal(r.status, 0, r.stderr);
572
561
  assert.match(r.capStdin, /non-regular, skipped\): nested\//);
573
562
  assert.doesNotMatch(r.capStdin, /INNER_SHOULD_NOT_BE_INLINED/, 'a non-regular path must not be inlined');
574
563
  });
575
564
 
576
- it('appends extra focus on the oversized (temp-file) path too', () => {
565
+ it('appends extra focus on the oversized (temp-file) path too', async () => {
577
566
  const sb = makeSandbox();
578
567
  writeFileSync(join(sb.repo, 'big.txt'), 'x'.repeat(5000));
579
- const r = run(sb, { args: ['code', 'watch the parser'], env: { CODEX_REVIEW_MAX_TOTAL_BYTES: '100' } });
568
+ const r = await run(sb, { args: ['code', 'watch the parser'], env: { CODEX_REVIEW_MAX_TOTAL_BYTES: '100' } });
580
569
  rmSync(sb.root, { recursive: true, force: true });
581
570
  assert.equal(r.status, 0, r.stderr);
582
571
  assert.match(r.capStdin, /with ONE exception/, 'this is the oversized temp-file path');
583
572
  assert.match(r.capStdin, /Extra focus: watch the parser/);
584
573
  });
585
574
 
586
- it('warns and prints the trace tail when codex writes no final-message file (then fails the D4 arm)', () => {
575
+ it('warns and prints the trace tail when codex writes no final-message file (then fails the D4 arm)', async () => {
587
576
  const sb = makeSandbox();
588
- const r = run(sb, { args: ['code'], env: { CODEX_FAKE_NO_OUT: '1' } });
577
+ const r = await run(sb, { args: ['code'], env: { CODEX_FAKE_NO_OUT: '1' } });
589
578
  rmSync(sb.root, { recursive: true, force: true });
590
579
  assert.notEqual(r.status, 0, 'no final message ⇒ no verdict ⇒ a FAILED review (D4)');
591
580
  assert.match(r.stderr, /no final-message file/);
592
581
  assert.match(r.stdout, /turn\.completed/, 'the trace tail still carries the event stream');
593
582
  });
594
583
 
595
- it('prints no session line when codex emits no thread id', () => {
584
+ it('prints no session line when codex emits no thread id', async () => {
596
585
  const sb = makeSandbox();
597
- const r = run(sb, { args: ['code'], env: { CODEX_FAKE_NO_THREAD: '1' } });
586
+ const r = await run(sb, { args: ['code'], env: { CODEX_FAKE_NO_THREAD: '1' } });
598
587
  rmSync(sb.root, { recursive: true, force: true });
599
588
  assert.equal(r.status, 0, r.stderr);
600
589
  assert.doesNotMatch(r.stderr, /session:/);
@@ -700,8 +689,8 @@ const consultsEnv = (source, name) =>
700
689
  // `<facts-file>` behind a stray character) — the catalog declares the whole token a user types.
701
690
  const SLOT_RE = /@?<[^<>]+>|\[[^[\]]*\]/g;
702
691
 
703
- describe('codex-review.sh — --help contract (manifest-pinned)', () => {
704
- it('--help and -h exit 0 pre-preflight (no codex, no git, no AGENTS.md)', () => {
692
+ describe('codex-review.sh — --help contract (manifest-pinned)', { concurrency: 2 }, () => {
693
+ it('--help and -h exit 0 pre-preflight (no codex, no git, no AGENTS.md)', async () => {
705
694
  for (const arg of ['--help', '-h']) {
706
695
  const r = runHelp(arg);
707
696
  assert.equal(r.status, 0, `${arg}: ${r.stderr}`);
@@ -710,57 +699,57 @@ describe('codex-review.sh — --help contract (manifest-pinned)', () => {
710
699
  }
711
700
  });
712
701
 
713
- it('Usage set-EQUALS the manifest invocation descriptors (both directions)', () => {
702
+ it('Usage set-EQUALS the manifest invocation descriptors (both directions)', async () => {
714
703
  const help = runHelp('--help').stdout;
715
704
  const got = helpSection(help, 'Usage:').filter((l) => l.startsWith('codex-review')).map(norm);
716
705
  assert.ok(REVIEW_CONTRACT.invocations.length > 0, 'manifest invocations must be non-empty');
717
706
  setEq(got, REVIEW_CONTRACT.invocations.map(norm), 'help Usage ⟷ manifest invocations');
718
707
  });
719
708
 
720
- it('Grounding renders the manifest grounding note verbatim', () => {
709
+ it('Grounding renders the manifest grounding note verbatim', async () => {
721
710
  const help = runHelp('--help').stdout;
722
711
  assert.equal(norm(helpSection(help, 'Grounding:').join(' ')), norm(REVIEW_CONTRACT.grounding));
723
712
  });
724
713
 
725
- it('Round-2 / resume set-EQUALS the manifest continue descriptors (empty — one-shot)', () => {
714
+ it('Round-2 / resume set-EQUALS the manifest continue descriptors (empty — one-shot)', async () => {
726
715
  const help = runHelp('--help').stdout;
727
716
  const got = helpSection(help, 'Round-2 / resume:').filter((l) => l.startsWith('codex-review')).map(norm);
728
717
  setEq(got, (REVIEW_CONTRACT.continue ?? []).map(norm), 'help continue ⟷ manifest continue');
729
718
  assert.deepEqual(REVIEW_CONTRACT.continue, [], 'codex-review is one-shot — no continue descriptor');
730
719
  });
731
720
 
732
- it('Receipt renders the manifest receipt contract verbatim (AD-038 three-way lockstep)', () => {
721
+ it('Receipt renders the manifest receipt contract verbatim (AD-038 three-way lockstep)', async () => {
733
722
  const help = runHelp('--help').stdout;
734
723
  assert.equal(norm(helpSection(help, 'Receipt:').join(' ')), norm(REVIEW_CONTRACT.receipt));
735
724
  assert.match(REVIEW_CONTRACT.receipt, /sha256 over the canonical uncommitted-state payload/, 'the fingerprint definition lives in the manifest contract');
736
725
  });
737
726
 
738
- it('Notes renders the manifest review contract.notes verbatim (AD-061 — a typed contract key that MUST surface)', () => {
727
+ it('Notes renders the manifest review contract.notes verbatim (AD-061 — a typed contract key that MUST surface)', async () => {
739
728
  const help = runHelp('--help').stdout;
740
729
  assert.ok((REVIEW_CONTRACT.notes ?? []).length >= 2, 'the review contract declares the banner-only-timeout + quote-verbatim notes');
741
730
  assert.equal(norm(helpSection(help, 'Notes:').join(' ')), norm(REVIEW_CONTRACT.notes.join(' ')));
742
731
  });
743
732
  });
744
733
 
745
- describe('codex-review.sh — source-level reverse guard (parser arms ⟷ manifest)', () => {
734
+ describe('codex-review.sh — source-level reverse guard (parser arms ⟷ manifest)', { concurrency: 2 }, () => {
746
735
  const arms = extractArgCaseArms(readFileSync(WRAPPER, 'utf8'));
747
736
 
748
- it('the real mode arms equal the manifest modes (adding a mode without the manifest fails here)', () => {
737
+ it('the real mode arms equal the manifest modes (adding a mode without the manifest fails here)', async () => {
749
738
  const modes = splitArms(arms.get('"$mode"')).filter((a) => a !== '*');
750
739
  assert.ok(MANIFEST.roles.review.modes.length > 0, 'manifest modes must be non-empty');
751
740
  setEq(new Set(modes), MANIFEST.roles.review.modes, 'parser mode arms ⟷ manifest modes');
752
741
  });
753
742
 
754
- it('the first-arg entrypoints are exactly --help/-h (no undeclared resume/flag entrypoint)', () => {
743
+ it('the first-arg entrypoints are exactly --help/-h (no undeclared resume/flag entrypoint)', async () => {
755
744
  setEq(new Set(splitArms(arms.get('"${1:-}"'))), ['--help', '-h']);
756
745
  });
757
746
 
758
- it('every manifest mode is really accepted (forward guard)', () => {
747
+ it('every manifest mode is really accepted (forward guard)', async () => {
759
748
  const drive = { plan: ['plan', 'plan.md'], code: ['code'] };
760
749
  for (const mode of MANIFEST.roles.review.modes) {
761
750
  assert.ok(drive[mode], `no test drive for manifest mode "${mode}" — add one`);
762
751
  const sb = makeSandbox();
763
- const r = run(sb, { args: drive[mode] });
752
+ const r = await run(sb, { args: drive[mode] });
764
753
  rmSync(sb.root, { recursive: true, force: true });
765
754
  assert.equal(r.status, 0, `mode ${mode}: ${r.stderr}`);
766
755
  }
@@ -773,10 +762,10 @@ describe('codex-review.sh — source-level reverse guard (parser arms ⟷ manife
773
762
  // a git-dir temp file — so its budget is set at the default inline cap: the map can never outgrow
774
763
  // the whole payload, and every realistic repo's map assembles byte-UNCHANGED. Behaviour alone
775
764
  // cannot tell "a huge budget" from "no budget at all", so the pinned value is asserted at source.
776
- describe('codex-review.sh — repo file map budget (Phase 2)', () => {
765
+ describe('codex-review.sh — repo file map budget (Phase 2)', { concurrency: 2 }, () => {
777
766
  const MAP_DIR = 'deeply/nested/fixture/directory/for/the/repo/file/map/budget';
778
767
 
779
- it("codex-review's assembled payload is byte-unchanged by the map budget", () => {
768
+ it("codex-review's assembled payload is byte-unchanged by the map budget", async () => {
780
769
  const sb = makeSandbox();
781
770
  const g = (...a) => spawnSync('git', a, { cwd: sb.repo, encoding: 'utf8' });
782
771
  mkdirSync(join(sb.repo, MAP_DIR), { recursive: true });
@@ -787,7 +776,7 @@ describe('codex-review.sh — repo file map budget (Phase 2)', () => {
787
776
  g('add', '-A');
788
777
  g('commit', '-qm', 'map fixture');
789
778
  for (let i = 0; i < 100; i += 1) writeFileSync(join(sb.repo, `${MAP_DIR}/zz-modified-file-${String(i).padStart(3, '0')}.txt`), `body ${i} v2 — changed\n`);
790
- const r = run(sb, { args: ['code'] });
779
+ const r = await run(sb, { args: ['code'] });
791
780
  rmSync(sb.root, { recursive: true, force: true });
792
781
  assert.equal(r.status, 0, r.stderr);
793
782
  assert.doesNotMatch(r.capStdin, /TRUNCATED/, 'a 17 KB map is far inside the budget — no degradation');
@@ -795,7 +784,7 @@ describe('codex-review.sh — repo file map budget (Phase 2)', () => {
795
784
  assert.ok(r.capStdin.includes(`${MAP_DIR}/aa-untouched-file-099.txt`), 'including its last entry');
796
785
  });
797
786
 
798
- it('the wrapper pins a map budget no smaller than its default inline-payload cap', () => {
787
+ it('the wrapper pins a map budget no smaller than its default inline-payload cap', async () => {
799
788
  const source = readFileSync(WRAPPER, 'utf8');
800
789
  const pinned = source.match(/^AW_REVIEW_MAP_BUDGET_BYTES=(\d+)$/m);
801
790
  assert.ok(pinned, 'codex-review.sh must PIN AW_REVIEW_MAP_BUDGET_BYTES (a plain assignment, never an env knob)');
@@ -809,20 +798,20 @@ describe('codex-review.sh — repo file map budget (Phase 2)', () => {
809
798
  // The kit validator owns the catalog's INTERNAL shape; these arms pin what only the wrapper source
810
799
  // can settle — the catalog documents THIS wrapper's real modes and real escape hatches, and every
811
800
  // contract invocation the wrapper honours is cataloged (adding a mode without one fails here).
812
- describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)', () => {
801
+ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)', { concurrency: 2 }, () => {
813
802
  const source = readFileSync(WRAPPER, 'utf8');
814
803
  const arms = extractArgCaseArms(source);
815
804
  const catalog = MANIFEST.modeCatalog ?? [];
816
805
  const reviewEntries = catalog.filter((e) => e.role === 'review');
817
806
  const reviewPrimaries = reviewEntries.filter((e) => e.kind === 'primary');
818
807
 
819
- it('the catalog submodes ARE the wrapper\'s real parser mode arms (both directions)', () => {
808
+ it('the catalog submodes ARE the wrapper\'s real parser mode arms (both directions)', async () => {
820
809
  const modes = splitArms(arms.get('"$mode"')).filter((a) => a !== '*');
821
810
  assert.ok(reviewPrimaries.length > 0, 'the manifest must catalog its review modes');
822
811
  setEq(reviewPrimaries.map((e) => e.submode), modes, 'catalog submodes ⟷ real parser mode arms');
823
812
  });
824
813
 
825
- it('every review entry composes BY REFERENCE and every reference resolves', () => {
814
+ it('every review entry composes BY REFERENCE and every reference resolves', async () => {
826
815
  for (const entry of reviewEntries) {
827
816
  assert.ok(
828
817
  Array.isArray(entry.invocationRefs) && entry.invocationRefs.length > 0,
@@ -838,7 +827,7 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
838
827
  }
839
828
  });
840
829
 
841
- it('every review contract invocation is claimed by exactly ONE catalog entry (no uncataloged mode)', () => {
830
+ it('every review contract invocation is claimed by exactly ONE catalog entry (no uncataloged mode)', async () => {
842
831
  const claims = reviewEntries.flatMap((e) => e.invocationRefs.map((r) => `${r.contractField}[${r.index}]`));
843
832
  assert.equal(new Set(claims).size, claims.length, 'a contract invocation is claimed at most once');
844
833
  const declared = [
@@ -848,7 +837,7 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
848
837
  setEq(new Set(claims), declared, 'catalog claims ⟷ declared contract invocations');
849
838
  });
850
839
 
851
- it('every env-hook the catalog aims at a review mode is a real EXECUTABLE guard, not a mention', () => {
840
+ it('every env-hook the catalog aims at a review mode is a real EXECUTABLE guard, not a mention', async () => {
852
841
  const hooks = catalog.filter((e) => e.kind === 'env-hook' && e.parents.some((p) => reviewPrimaries.some((r) => r.key === p)));
853
842
  assert.ok(hooks.length > 0, 'CODEX_PROBE must be cataloged as an env-hook over the review modes');
854
843
  for (const hook of hooks) {
@@ -859,7 +848,7 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
859
848
  }
860
849
  });
861
850
 
862
- it('the catalog operand slots set-EQUAL the slots its rendered forms really carry (both directions)', () => {
851
+ it('the catalog operand slots set-EQUAL the slots its rendered forms really carry (both directions)', async () => {
863
852
  for (const entry of reviewEntries) {
864
853
  const forms = entry.invocationRefs.map((r) => REVIEW_CONTRACT[r.contractField][r.index]);
865
854
  // The DEDUPLICATED UNION over every resolved form: a plural-ref entry legitimately spreads its
@@ -869,7 +858,7 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
869
858
  }
870
859
  });
871
860
 
872
- it('an entry rendering a LITERAL descriptor is slot-checked too (env-hooks have no role to filter on)', () => {
861
+ it('an entry rendering a LITERAL descriptor is slot-checked too (env-hooks have no role to filter on)', async () => {
873
862
  // The contract-backed arm above filters by role — and an env-hook HAS no role, so its descriptor
874
863
  // would never be slot-checked. That is exactly how a hardcoded dead path can reach the discovery
875
864
  // surface looking ready-to-run. Every literal-descriptor kind is covered here: env-hooks and
@@ -882,7 +871,7 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
882
871
  }
883
872
  });
884
873
 
885
- it('CODEX_PROBE really relaxes the guard on EVERY review parent the catalog claims (behavioural)', () => {
874
+ it('CODEX_PROBE really relaxes the guard on EVERY review parent the catalog claims (behavioural)', async () => {
886
875
  // The catalog CLAIMS these modes are modified by the hook; prove it per parent rather than
887
876
  // trusting a source scan: an off-pin model is exit 2 normally, exit 0 under probe.
888
877
  const hook = catalog.find((e) => e.key === 'CODEX_PROBE');
@@ -894,13 +883,13 @@ describe('codex-review.sh — mode catalog ⟷ wrapper reality (manifest-pinned)
894
883
  // The exit code alone is weak evidence: pin the real DISPATCH too (capStdin is non-empty only
895
884
  // when codex was actually invoked), so a run that dies early can never pass the probe-on branch.
896
885
  const guarded = makeSandbox();
897
- const off = run(guarded, { args: drive[parent], env: { CODEX_MODEL: 'not-the-pinned-model' } });
886
+ const off = await run(guarded, { args: drive[parent], env: { CODEX_MODEL: 'not-the-pinned-model' } });
898
887
  rmSync(guarded.root, { recursive: true, force: true });
899
888
  assert.equal(off.status, 2, `${parent}: the quality guard must refuse an off-pin model without the hook`);
900
889
  assert.equal(off.capStdin, '', `${parent}: the guard must refuse BEFORE spending a run`);
901
890
 
902
891
  const probed = makeSandbox();
903
- const on = run(probed, { args: drive[parent], env: { CODEX_MODEL: 'not-the-pinned-model', CODEX_PROBE: '1' } });
892
+ const on = await run(probed, { args: drive[parent], env: { CODEX_MODEL: 'not-the-pinned-model', CODEX_PROBE: '1' } });
904
893
  rmSync(probed.root, { recursive: true, force: true });
905
894
  assert.equal(on.status, 0, `${parent}: CODEX_PROBE=1 must really relax the guard — the catalog claims it does`);
906
895
  assert.notEqual(on.capStdin, '', `${parent}: CODEX_PROBE=1 must really reach codex, not merely exit 0`);
@@ -922,10 +911,10 @@ const readReceipts = (repo) => {
922
911
  };
923
912
  const sha256Hex = (buf) => createHash('sha256').update(buf).digest('hex');
924
913
 
925
- describe('codex-review.sh — review receipts (AD-038)', () => {
926
- it('a successful code review appends ONE fixture-shaped receipt (text-mode verdict parse)', () => {
914
+ describe('codex-review.sh — review receipts (AD-038)', { concurrency: 2 }, () => {
915
+ it('a successful code review appends ONE fixture-shaped receipt (text-mode verdict parse)', async () => {
927
916
  const sb = makeSandbox();
928
- const r = run(sb, { env: { CODEX_FAKE_FINAL: '[major] — a.txt:1 — x — y\nVerdict: revise' } });
917
+ const r = await run(sb, { env: { CODEX_FAKE_FINAL: '[major] — a.txt:1 — x — y\nVerdict: revise' } });
929
918
  const receipts = readReceipts(sb.repo);
930
919
  rmSync(sb.root, { recursive: true, force: true });
931
920
  assert.equal(r.status, 0, r.stderr);
@@ -945,13 +934,13 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
945
934
  });
946
935
 
947
936
  // The probe marker (BRIDGE-MODES-CATALOG, D3): a CODEX_PROBE=1 review runs with the
948
- // frontier-model/max-effort guard OFF, so its receipt must be distinguishable — the kit's
937
+ // pinned-model/max-effort guard OFF, so its receipt must be distinguishable — the kit's
949
938
  // review-state gate rejects a probe-marked receipt. EVERY receipt carries the marker (true or
950
939
  // false): it self-declares, so the gate reads the fact rather than inferring it from a version
951
940
  // string that bumps in a different release phase. Silence is not a declaration.
952
- it('CODEX_PROBE=1 stamps probe:true — a throwaway probe can never attest a tree (D3)', () => {
941
+ it('CODEX_PROBE=1 stamps probe:true — a throwaway probe can never attest a tree (D3)', async () => {
953
942
  const sb = makeSandbox();
954
- const r = run(sb, { env: { CODEX_PROBE: '1', CODEX_FAKE_FINAL: 'Verdict: ship' } });
943
+ const r = await run(sb, { env: { CODEX_PROBE: '1', CODEX_FAKE_FINAL: 'Verdict: ship' } });
955
944
  const receipts = readReceipts(sb.repo);
956
945
  rmSync(sb.root, { recursive: true, force: true });
957
946
  assert.equal(r.status, 0, r.stderr);
@@ -961,32 +950,32 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
961
950
 
962
951
  // Every receipt SELF-DECLARES: the kit's gate reads the marker, never the wrapper version — so
963
952
  // the marker must not depend on a version bump landing in the same release phase.
964
- it('a normal review self-declares probe:false — the receipt states the fact, not a version', () => {
953
+ it('a normal review self-declares probe:false — the receipt states the fact, not a version', async () => {
965
954
  const sb = makeSandbox();
966
- run(sb, { env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
955
+ await run(sb, { env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
967
956
  const receipts = readReceipts(sb.repo);
968
957
  rmSync(sb.root, { recursive: true, force: true });
969
958
  assert.equal(receipts[0].probe, false, 'silence is not a declaration — the gate rejects an unmarked receipt');
970
959
  });
971
960
 
972
- it('the marker tracks the RELAXED GUARD, not the model — a probe on an off-pinned model still marks', () => {
961
+ it('the marker tracks the RELAXED GUARD, not the model — a probe on an off-pinned model still marks', async () => {
973
962
  const sb = makeSandbox();
974
- const r = run(sb, { env: { CODEX_PROBE: '1', CODEX_MODEL: 'gpt-5-mini', CODEX_EFFORT: 'low', CODEX_FAKE_FINAL: 'Verdict: ship' } });
963
+ const r = await run(sb, { env: { CODEX_PROBE: '1', CODEX_MODEL: 'gpt-5-mini', CODEX_EFFORT: 'low', CODEX_FAKE_FINAL: 'Verdict: ship' } });
975
964
  const receipts = readReceipts(sb.repo);
976
965
  rmSync(sb.root, { recursive: true, force: true });
977
966
  assert.equal(r.status, 0, r.stderr);
978
967
  assert.equal(receipts[0].probe, true, 'exactly the runs the guard let through unpinned are marked');
979
968
  });
980
969
 
981
- it('the code-mode fingerprint tracks the uncommitted state (same tree → same hash; edit → different)', () => {
970
+ it('the code-mode fingerprint tracks the uncommitted state (same tree → same hash; edit → different)', async () => {
982
971
  const sb = makeSandbox();
983
972
  // Route the fake-codex capture files to /dev/null so the runs themselves leave the repo
984
973
  // byte-identical (the default capture files land inside the repo and would change the tree).
985
974
  const quiet = { CODEX_FAKE_ARGV: '/dev/null', CODEX_FAKE_ENV: '/dev/null', CODEX_FAKE_STDIN: '/dev/null', CODEX_FAKE_FINAL: 'Verdict: ship' };
986
- run(sb, { env: quiet });
987
- run(sb, { env: quiet });
975
+ await run(sb, { env: quiet });
976
+ await run(sb, { env: quiet });
988
977
  writeFileSync(join(sb.repo, 'pending.txt'), 'edited after the first two reviews\n');
989
- run(sb, { env: quiet });
978
+ await run(sb, { env: quiet });
990
979
  const receipts = readReceipts(sb.repo);
991
980
  rmSync(sb.root, { recursive: true, force: true });
992
981
  assert.equal(receipts.length, 3);
@@ -994,9 +983,9 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
994
983
  assert.notEqual(receipts[1].fingerprint, receipts[2].fingerprint, 'an edited tree changes the fingerprint');
995
984
  });
996
985
 
997
- it('CODEX_REVIEW_SCHEMA=1 reads the schema verdict field', () => {
986
+ it('CODEX_REVIEW_SCHEMA=1 reads the schema verdict field', async () => {
998
987
  const sb = makeSandbox();
999
- const r = run(sb, {
988
+ const r = await run(sb, {
1000
989
  env: { CODEX_REVIEW_SCHEMA: '1', CODEX_FAKE_FINAL: '{"findings":[],"verdict":"ship","notes":"ok"}' },
1001
990
  });
1002
991
  const receipts = readReceipts(sb.repo);
@@ -1005,19 +994,19 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1005
994
  assert.equal(receipts[0].verdict, 'ship');
1006
995
  });
1007
996
 
1008
- it('no parseable verdict is a FAILED run — never recorded as "unknown" (D4 owns the arm)', () => {
997
+ it('no parseable verdict is a FAILED run — never recorded as "unknown" (D4 owns the arm)', async () => {
1009
998
  const sb = makeSandbox();
1010
- const r = run(sb, { env: { CODEX_FAKE_FINAL: 'looks fine to me overall' } });
999
+ const r = await run(sb, { env: { CODEX_FAKE_FINAL: 'looks fine to me overall' } });
1011
1000
  const receipts = readReceipts(sb.repo);
1012
1001
  rmSync(sb.root, { recursive: true, force: true });
1013
1002
  assert.notEqual(r.status, 0);
1014
1003
  assert.equal(receipts.length, 0, 'an unknown verdict never reaches the receipt store');
1015
1004
  });
1016
1005
 
1017
- it('plan mode: artifact "plan", fingerprint = the artifact-file sha256', () => {
1006
+ it('plan mode: artifact "plan", fingerprint = the artifact-file sha256', async () => {
1018
1007
  const sb = makeSandbox();
1019
1008
  const planBytes = readFileSync(join(sb.repo, 'plan.md'));
1020
- const r = run(sb, { args: ['plan', 'plan.md'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1009
+ const r = await run(sb, { args: ['plan', 'plan.md'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1021
1010
  const receipts = readReceipts(sb.repo);
1022
1011
  rmSync(sb.root, { recursive: true, force: true });
1023
1012
  assert.equal(r.status, 0, r.stderr);
@@ -1025,10 +1014,10 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1025
1014
  assert.equal(receipts[0].fingerprint, sha256Hex(planBytes), 'plan fingerprint = file sha256');
1026
1015
  });
1027
1016
 
1028
- it('AW_REVIEW_RECEIPTS overrides the receipt destination', () => {
1017
+ it('AW_REVIEW_RECEIPTS overrides the receipt destination', async () => {
1029
1018
  const sb = makeSandbox();
1030
1019
  const override = join(sb.root, 'my-receipts.jsonl');
1031
- const r = run(sb, { env: { AW_REVIEW_RECEIPTS: override, CODEX_FAKE_FINAL: 'Verdict: ship' } });
1020
+ const r = await run(sb, { env: { AW_REVIEW_RECEIPTS: override, CODEX_FAKE_FINAL: 'Verdict: ship' } });
1032
1021
  const inGitDir = readReceipts(sb.repo);
1033
1022
  const atOverride = existsSync(override) ? readFileSync(override, 'utf8') : '';
1034
1023
  rmSync(sb.root, { recursive: true, force: true });
@@ -1040,15 +1029,15 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1040
1029
  // The wrapper-minted finding manifest (flow-orchestration Phase 4.2, Decision 2/P5/P24-25):
1041
1030
  // nonce-supplied dispatches mint {schema, backend, nonce, fingerprint, findings} beside the
1042
1031
  // receipt, atomic + no-clobber + ORDERED — a failed mint EXCLUDES the receipt append.
1043
- describe('finding manifest (AW_REVIEW_NONCE)', () => {
1032
+ describe('finding manifest (AW_REVIEW_NONCE)', { concurrency: 2 }, () => {
1044
1033
  const manifestPath = (repo, nonce) => join(repo, '.git', `agent-workflow-finding-manifest-codex-${nonce}.json`);
1045
1034
  // Capture files ride /dev/null so repeated runs see an UNCHANGED tree (the manifest binds the
1046
1035
  // fingerprint — a moved tree would legitimately change its bytes).
1047
1036
  const quiet = { CODEX_FAKE_ARGV: '/dev/null', CODEX_FAKE_ENV: '/dev/null', CODEX_FAKE_STDIN: '/dev/null', CODEX_FAKE_FINAL: 'Verdict: ship' };
1048
1037
 
1049
- it('a nonce-supplied code dispatch mints the {backend, nonce}-named manifest carrying the captured findings + the receipt fingerprint', () => {
1038
+ it('a nonce-supplied code dispatch mints the {backend, nonce}-named manifest carrying the captured findings + the receipt fingerprint', async () => {
1050
1039
  const sb = makeSandbox();
1051
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1040
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1052
1041
  const receipts = readReceipts(sb.repo);
1053
1042
  const manifest = JSON.parse(readFileSync(manifestPath(sb.repo, 'r1-d1'), 'utf8'));
1054
1043
  rmSync(sb.root, { recursive: true, force: true });
@@ -1063,9 +1052,9 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1063
1052
  assert.equal(receipts[0].nonce, 'r1-d1', 'a nonce-supplied receipt carries the dispatch nonce — the flow round-land matcher requires exact equality (dispatch identity end-to-end)');
1064
1053
  });
1065
1054
 
1066
- it('a nonce-less invocation mints NO manifest and adds NO nonce field — the receipt field set is unchanged (Decision 2 both branches)', () => {
1055
+ it('a nonce-less invocation mints NO manifest and adds NO nonce field — the receipt field set is unchanged (Decision 2 both branches)', async () => {
1067
1056
  const sb = makeSandbox();
1068
- const r = run(sb, { env: { ...quiet } });
1057
+ const r = await run(sb, { env: { ...quiet } });
1069
1058
  const receipts = readReceipts(sb.repo);
1070
1059
  const gitEntries = readdirSync(join(sb.repo, '.git')).filter((n) => n.startsWith('agent-workflow-finding-manifest-'));
1071
1060
  rmSync(sb.root, { recursive: true, force: true });
@@ -1074,11 +1063,11 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1074
1063
  assert.deepEqual(Object.keys(receipts[0]), Object.keys(RECEIPT_FIXTURE), 'the receipt line field set is unchanged');
1075
1064
  });
1076
1065
 
1077
- it('a byte-identical re-mint is an idempotent no-op — the second receipt still lands', () => {
1066
+ it('a byte-identical re-mint is an idempotent no-op — the second receipt still lands', async () => {
1078
1067
  const sb = makeSandbox();
1079
- assert.equal(run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } }).status, 0);
1068
+ assert.equal((await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } })).status, 0);
1080
1069
  const before = readFileSync(manifestPath(sb.repo, 'r1-d1'), 'utf8');
1081
- const r2 = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1070
+ const r2 = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1082
1071
  const receipts = readReceipts(sb.repo);
1083
1072
  const after = readFileSync(manifestPath(sb.repo, 'r1-d1'), 'utf8');
1084
1073
  rmSync(sb.root, { recursive: true, force: true });
@@ -1087,10 +1076,10 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1087
1076
  assert.equal(after, before, 'the manifest bytes are untouched');
1088
1077
  });
1089
1078
 
1090
- it('DIFFERENT bytes at the derived name refuse loudly AND EXCLUDE the receipt append (ordering, behaviorally)', () => {
1079
+ it('DIFFERENT bytes at the derived name refuse loudly AND EXCLUDE the receipt append (ordering, behaviorally)', async () => {
1091
1080
  const sb = makeSandbox();
1092
1081
  writeFileSync(manifestPath(sb.repo, 'r1-d1'), '{"schema":1,"backend":"codex","nonce":"r1-d1","fingerprint":null,"findings":"other bytes"}\n');
1093
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1082
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'r1-d1' } });
1094
1083
  const receipts = readReceipts(sb.repo);
1095
1084
  const manifest = readFileSync(manifestPath(sb.repo, 'r1-d1'), 'utf8');
1096
1085
  rmSync(sb.root, { recursive: true, force: true });
@@ -1101,11 +1090,11 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1101
1090
  assert.match(manifest, /other bytes/, 'the pre-existing manifest is never clobbered');
1102
1091
  });
1103
1092
 
1104
- it('a tmp-unlink failure after a successful mint warns with the ORPHAN PATH and still appends the receipt (preload-forced; parity carries the agy twin)', () => {
1093
+ it('a tmp-unlink failure after a successful mint warns with the ORPHAN PATH and still appends the receipt (preload-forced; parity carries the agy twin)', async () => {
1105
1094
  const sb = makeSandbox();
1106
1095
  const preload = join(sb.root, 'unlink-fail-preload.cjs');
1107
1096
  writeFileSync(preload, "const fs = require('node:fs');\nconst real = fs.unlinkSync;\nfs.unlinkSync = (p) => { if (String(p).includes('.tmp')) { const e = new Error('EPERM'); e.code = 'EPERM'; throw e; } return real(p); };\n");
1108
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orph1', NODE_OPTIONS: `--require ${preload}` } });
1097
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orph1', NODE_OPTIONS: `--require ${preload}` } });
1109
1098
  const receipts = readReceipts(sb.repo);
1110
1099
  const manifestExists = existsSync(manifestPath(sb.repo, 'orph1'));
1111
1100
  rmSync(sb.root, { recursive: true, force: true });
@@ -1124,12 +1113,12 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1124
1113
  { rc: 3, name: 'no-clobber (rc 3)', preload: UNLINK_FAIL, plant: true, errRe: /DIFFERENT bytes or is not a regular file/ },
1125
1114
  { rc: 1, name: 'fs failure (rc 1)', preload: UNLINK_FAIL + LINK_FAIL, plant: false, errRe: /could not compose or write the finding manifest/ },
1126
1115
  ]) {
1127
- it(`a FAILURE exit (${failure.name}) whose temp unlink also fails names the ORPHAN PATH in the error`, () => {
1116
+ it(`a FAILURE exit (${failure.name}) whose temp unlink also fails names the ORPHAN PATH in the error`, async () => {
1128
1117
  const sb = makeSandbox();
1129
1118
  if (failure.plant) writeFileSync(manifestPath(sb.repo, 'orphf1'), 'planted different bytes\n');
1130
1119
  const preload = join(sb.root, 'orphan-fail-preload.cjs');
1131
1120
  writeFileSync(preload, failure.preload);
1132
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orphf1', NODE_OPTIONS: `--require ${preload}` } });
1121
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orphf1', NODE_OPTIONS: `--require ${preload}` } });
1133
1122
  const receipts = readReceipts(sb.repo);
1134
1123
  rmSync(sb.root, { recursive: true, force: true });
1135
1124
  assert.equal(r.status, 0, 'the review itself still succeeds (the artifact lane failed loudly)');
@@ -1139,10 +1128,10 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1139
1128
  });
1140
1129
  }
1141
1130
 
1142
- it('a FAILURE exit whose temp IS removable stays orphan-silent (no leftover, no orphan line)', () => {
1131
+ it('a FAILURE exit whose temp IS removable stays orphan-silent (no leftover, no orphan line)', async () => {
1143
1132
  const sb = makeSandbox();
1144
1133
  writeFileSync(manifestPath(sb.repo, 'orphf2'), 'planted different bytes\n');
1145
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orphf2' } });
1134
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'orphf2' } });
1146
1135
  const leftovers = readdirSync(join(sb.repo, '.git')).filter((n) => n.endsWith('.tmp'));
1147
1136
  rmSync(sb.root, { recursive: true, force: true });
1148
1137
  assert.equal(r.status, 0, 'the review itself still succeeds (the artifact lane failed loudly)');
@@ -1151,15 +1140,15 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1151
1140
  assert.deepEqual(leftovers, [], 'the temp really was removed');
1152
1141
  });
1153
1142
 
1154
- it('a SYMLINK at the derived manifest path refuses and EXCLUDES the receipt — even when its target is byte-identical', () => {
1143
+ it('a SYMLINK at the derived manifest path refuses and EXCLUDES the receipt — even when its target is byte-identical', async () => {
1155
1144
  const sb = makeSandbox();
1156
- assert.equal(run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'sym1' } }).status, 0);
1145
+ assert.equal((await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'sym1' } })).status, 0);
1157
1146
  const mPath = manifestPath(sb.repo, 'sym1');
1158
1147
  const target = join(sb.repo, '.git', 'manifest-target-copy.json');
1159
1148
  writeFileSync(target, readFileSync(mPath));
1160
1149
  rmSync(mPath);
1161
1150
  symlinkSync(target, mPath);
1162
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'sym1' } });
1151
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'sym1' } });
1163
1152
  const receipts = readReceipts(sb.repo);
1164
1153
  rmSync(sb.root, { recursive: true, force: true });
1165
1154
  assert.equal(r.status, 0, 'the review itself still succeeds (the artifact lane failed loudly)');
@@ -1167,11 +1156,11 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1167
1156
  assert.equal(receipts.length, 1, 'the second receipt is EXCLUDED — a symlinked manifest is never read through as the idempotent no-op');
1168
1157
  });
1169
1158
 
1170
- it('a FIFO at the derived manifest path refuses fast and EXCLUDES the receipt (O_NONBLOCK — no hang; fix characterization)', () => {
1159
+ it('a FIFO at the derived manifest path refuses fast and EXCLUDES the receipt (O_NONBLOCK — no hang; fix characterization)', async () => {
1171
1160
  const sb = makeSandbox();
1172
1161
  const mPath = manifestPath(sb.repo, 'fifo1');
1173
1162
  assert.equal(spawnSync('mkfifo', [mPath], { encoding: 'utf8' }).status, 0, 'mkfifo fixture');
1174
- const r = run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'fifo1' } });
1163
+ const r = await run(sb, { env: { ...quiet, AW_REVIEW_NONCE: 'fifo1' } });
1175
1164
  const receipts = readReceipts(sb.repo);
1176
1165
  rmSync(sb.root, { recursive: true, force: true });
1177
1166
  assert.equal(r.status, 0, r.stderr);
@@ -1179,18 +1168,18 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1179
1168
  assert.equal(receipts.length, 0, 'a FIFO manifest is never read (fstat-first) and the receipt is excluded');
1180
1169
  });
1181
1170
 
1182
- it('a BOM-prefixed findings payload round-trips VERBATIM into the manifest (U+FEFF preserved)', () => {
1171
+ it('a BOM-prefixed findings payload round-trips VERBATIM into the manifest (U+FEFF preserved)', async () => {
1183
1172
  const sb = makeSandbox();
1184
- const r = run(sb, { env: { ...quiet, CODEX_FAKE_FINAL: '\uFEFFFinding A\nVerdict: ship', AW_REVIEW_NONCE: 'b1' } });
1173
+ const r = await run(sb, { env: { ...quiet, CODEX_FAKE_FINAL: '\uFEFFFinding A\nVerdict: ship', AW_REVIEW_NONCE: 'b1' } });
1185
1174
  const manifest = JSON.parse(readFileSync(manifestPath(sb.repo, 'b1'), 'utf8'));
1186
1175
  rmSync(sb.root, { recursive: true, force: true });
1187
1176
  assert.equal(r.status, 0, r.stderr);
1188
1177
  assert.equal(manifest.findings, '\uFEFFFinding A\nVerdict: ship\n', 'the captured findings are VERBATIM — a stripped BOM would move the findingDigest');
1189
1178
  });
1190
1179
 
1191
- it('an unsafe nonce refuses PRE-SPEND (exit 2, codex never runs) — a non-ASCII letter refuses under a UTF-8 locale too', () => {
1180
+ it('an unsafe nonce refuses PRE-SPEND (exit 2, codex never runs) — a non-ASCII letter refuses under a UTF-8 locale too', async () => {
1192
1181
  const sb = makeSandbox();
1193
- const r = run(sb, { env: { AW_REVIEW_NONCE: '../escape' } });
1182
+ const r = await run(sb, { env: { AW_REVIEW_NONCE: '../escape' } });
1194
1183
  rmSync(sb.root, { recursive: true, force: true });
1195
1184
  assert.equal(r.status, 2);
1196
1185
  assert.match(r.stderr, /safe nonce grammar/);
@@ -1198,25 +1187,25 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1198
1187
  // The grammar ENUMERATES the ASCII set (no ranges): a locale-collated [A-Za-z] could admit a
1199
1188
  // non-ASCII letter the kit's JS reader then refuses, breaking correlation after a paid run.
1200
1189
  const utf8 = makeSandbox();
1201
- const r2 = run(utf8, { env: { AW_REVIEW_NONCE: 'r\u00e91', LC_ALL: 'en_US.UTF-8', LANG: 'en_US.UTF-8' } });
1190
+ const r2 = await run(utf8, { env: { AW_REVIEW_NONCE: 'r\u00e91', LC_ALL: 'en_US.UTF-8', LANG: 'en_US.UTF-8' } });
1202
1191
  rmSync(utf8.root, { recursive: true, force: true });
1203
1192
  assert.equal(r2.status, 2, 'a non-ASCII nonce letter refuses whatever the locale collation says');
1204
1193
  assert.match(r2.stderr, /safe nonce grammar/);
1205
1194
  });
1206
1195
 
1207
- it('plan mode with a nonce mints the manifest too (fingerprint = the artifact sha256)', () => {
1196
+ it('plan mode with a nonce mints the manifest too (fingerprint = the artifact sha256)', async () => {
1208
1197
  const sb = makeSandbox();
1209
1198
  const planBytes = readFileSync(join(sb.repo, 'plan.md'));
1210
- const r = run(sb, { args: ['plan', 'plan.md'], env: { CODEX_FAKE_FINAL: 'Verdict: ship', AW_REVIEW_NONCE: 'p1' } });
1199
+ const r = await run(sb, { args: ['plan', 'plan.md'], env: { CODEX_FAKE_FINAL: 'Verdict: ship', AW_REVIEW_NONCE: 'p1' } });
1211
1200
  const manifest = JSON.parse(readFileSync(manifestPath(sb.repo, 'p1'), 'utf8'));
1212
1201
  rmSync(sb.root, { recursive: true, force: true });
1213
1202
  assert.equal(r.status, 0, r.stderr);
1214
1203
  assert.equal(manifest.fingerprint, sha256Hex(planBytes));
1215
1204
  });
1216
1205
 
1217
- it('a FAILED review (no verdict) mints neither receipt nor manifest — the pair rides success only', () => {
1206
+ it('a FAILED review (no verdict) mints neither receipt nor manifest — the pair rides success only', async () => {
1218
1207
  const sb = makeSandbox();
1219
- const r = run(sb, { env: { CODEX_FAKE_FINAL: 'no verdict here', AW_REVIEW_NONCE: 'r9' } });
1208
+ const r = await run(sb, { env: { CODEX_FAKE_FINAL: 'no verdict here', AW_REVIEW_NONCE: 'r9' } });
1220
1209
  const receipts = readReceipts(sb.repo);
1221
1210
  const exists = existsSync(manifestPath(sb.repo, 'r9'));
1222
1211
  rmSync(sb.root, { recursive: true, force: true });
@@ -1227,9 +1216,9 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1227
1216
 
1228
1217
  // The --nonce flag (FLOW-NONCE-DISPATCH-LANE): the plain-argument lane onto the SAME seam —
1229
1218
  // for hosts whose dispatch policy has no env-prefix form.
1230
- it('--nonce in code mode rides the AW_REVIEW_NONCE seam: manifest minted, receipt nonce-stamped, focus words intact', () => {
1219
+ it('--nonce in code mode rides the AW_REVIEW_NONCE seam: manifest minted, receipt nonce-stamped, focus words intact', async () => {
1231
1220
  const sb = makeSandbox();
1232
- const r = run(sb, { args: ['code', '--nonce', 'f1-d1', 'look', 'harder'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1221
+ const r = await run(sb, { args: ['code', '--nonce', 'f1-d1', 'look', 'harder'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1233
1222
  const receipts = readReceipts(sb.repo);
1234
1223
  const manifest = JSON.parse(readFileSync(manifestPath(sb.repo, 'f1-d1'), 'utf8'));
1235
1224
  const stdin = r.capStdin;
@@ -1240,45 +1229,45 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1240
1229
  assert.match(stdin, /Extra focus: look harder/, 'the flag pair is stripped — trailing focus words still ride');
1241
1230
  });
1242
1231
 
1243
- it('--nonce in plan mode mints the manifest (the consult-dispatch lane) — the flag never trips the no-extra-args refusal', () => {
1232
+ it('--nonce in plan mode mints the manifest (the consult-dispatch lane) — the flag never trips the no-extra-args refusal', async () => {
1244
1233
  const sb = makeSandbox();
1245
- const r = run(sb, { args: ['plan', 'plan.md', '--nonce', 'p2'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1234
+ const r = await run(sb, { args: ['plan', 'plan.md', '--nonce', 'p2'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1246
1235
  const exists = existsSync(manifestPath(sb.repo, 'p2'));
1247
1236
  rmSync(sb.root, { recursive: true, force: true });
1248
1237
  assert.equal(r.status, 0, r.stderr);
1249
1238
  assert.equal(exists, true);
1250
1239
  });
1251
1240
 
1252
- it('an unsafe --nonce value refuses PRE-SPEND (exit 2, codex never runs) — same grammar as the env screen', () => {
1241
+ it('an unsafe --nonce value refuses PRE-SPEND (exit 2, codex never runs) — same grammar as the env screen', async () => {
1253
1242
  const sb = makeSandbox();
1254
- const r = run(sb, { args: ['code', '--nonce', 'a/b'] });
1243
+ const r = await run(sb, { args: ['code', '--nonce', 'a/b'] });
1255
1244
  rmSync(sb.root, { recursive: true, force: true });
1256
1245
  assert.equal(r.status, 2);
1257
1246
  assert.match(r.stderr, /safe nonce grammar/);
1258
1247
  assert.equal(r.capStdin, '', 'the refusal fires before any CLI spend');
1259
1248
  });
1260
1249
 
1261
- it('a missing value, a duplicate flag, and a disagreeing env+flag pair each refuse (exit 2); an agreeing pair proceeds', () => {
1250
+ it('a missing value, a duplicate flag, and a disagreeing env+flag pair each refuse (exit 2); an agreeing pair proceeds', async () => {
1262
1251
  const sb = makeSandbox();
1263
- const missing = run(sb, { args: ['code', '--nonce'] });
1252
+ const missing = await run(sb, { args: ['code', '--nonce'] });
1264
1253
  assert.equal(missing.status, 2);
1265
1254
  assert.match(missing.stderr, /--nonce needs a value/);
1266
- const dup = run(sb, { args: ['code', '--nonce', 'n1', '--nonce', 'n2'] });
1255
+ const dup = await run(sb, { args: ['code', '--nonce', 'n1', '--nonce', 'n2'] });
1267
1256
  assert.equal(dup.status, 2);
1268
1257
  assert.match(dup.stderr, /duplicate --nonce/);
1269
- const clash = run(sb, { args: ['code', '--nonce', 'n1'], env: { AW_REVIEW_NONCE: 'n2' } });
1258
+ const clash = await run(sb, { args: ['code', '--nonce', 'n1'], env: { AW_REVIEW_NONCE: 'n2' } });
1270
1259
  assert.equal(clash.status, 2);
1271
1260
  assert.match(clash.stderr, /disagrees with the AW_REVIEW_NONCE environment value/);
1272
- const agree = run(sb, { args: ['code', '--nonce', 'n3'], env: { AW_REVIEW_NONCE: 'n3', CODEX_FAKE_FINAL: 'Verdict: ship' } });
1261
+ const agree = await run(sb, { args: ['code', '--nonce', 'n3'], env: { AW_REVIEW_NONCE: 'n3', CODEX_FAKE_FINAL: 'Verdict: ship' } });
1273
1262
  const exists = existsSync(manifestPath(sb.repo, 'n3'));
1274
1263
  rmSync(sb.root, { recursive: true, force: true });
1275
1264
  assert.equal(agree.status, 0, agree.stderr);
1276
1265
  assert.equal(exists, true, 'an agreeing pair is ONE seam value — the dispatch proceeds');
1277
1266
  });
1278
1267
 
1279
- it('a grammar-valid leading-dash --nonce value is ACCEPTED — the flag lane spans the whole declared grammar', () => {
1268
+ it('a grammar-valid leading-dash --nonce value is ACCEPTED — the flag lane spans the whole declared grammar', async () => {
1280
1269
  const sb = makeSandbox();
1281
- const r = run(sb, { args: ['code', '--nonce', '--n1'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1270
+ const r = await run(sb, { args: ['code', '--nonce', '--n1'], env: { CODEX_FAKE_FINAL: 'Verdict: ship' } });
1282
1271
  const receipts = readReceipts(sb.repo);
1283
1272
  const exists = existsSync(manifestPath(sb.repo, '--n1'));
1284
1273
  rmSync(sb.root, { recursive: true, force: true });
@@ -1287,18 +1276,18 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1287
1276
  assert.equal(receipts[0].nonce, '--n1', 'the receipt carries the exact grammar-valid value — flag lane ≡ env lane');
1288
1277
  });
1289
1278
 
1290
- it('an EMPTY --nonce value refuses pre-spend under the grammar screen (presence is tracked separately from the value)', () => {
1279
+ it('an EMPTY --nonce value refuses pre-spend under the grammar screen (presence is tracked separately from the value)', async () => {
1291
1280
  const sb = makeSandbox();
1292
- const r = run(sb, { args: ['code', '--nonce', ''] });
1281
+ const r = await run(sb, { args: ['code', '--nonce', ''] });
1293
1282
  rmSync(sb.root, { recursive: true, force: true });
1294
1283
  assert.equal(r.status, 2);
1295
1284
  assert.match(r.stderr, /safe nonce grammar/);
1296
1285
  assert.equal(r.capStdin, '', 'the refusal fires before any CLI spend');
1297
1286
  });
1298
1287
 
1299
- it('a duplicate --nonce after an EMPTY first value still refuses as a duplicate — an empty value never erases presence', () => {
1288
+ it('a duplicate --nonce after an EMPTY first value still refuses as a duplicate — an empty value never erases presence', async () => {
1300
1289
  const sb = makeSandbox();
1301
- const r = run(sb, { args: ['code', '--nonce', '', '--nonce', 'n2'] });
1290
+ const r = await run(sb, { args: ['code', '--nonce', '', '--nonce', 'n2'] });
1302
1291
  rmSync(sb.root, { recursive: true, force: true });
1303
1292
  assert.equal(r.status, 2);
1304
1293
  assert.match(r.stderr, /duplicate --nonce/);
@@ -1306,9 +1295,9 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1306
1295
  });
1307
1296
  });
1308
1297
 
1309
- it('a receipt write failure warns loudly but never fails the review (fail-safe direction)', () => {
1298
+ it('a receipt write failure warns loudly but never fails the review (fail-safe direction)', async () => {
1310
1299
  const sb = makeSandbox();
1311
- const r = run(sb, {
1300
+ const r = await run(sb, {
1312
1301
  env: { AW_REVIEW_RECEIPTS: join(sb.repo, 'no-such-dir', 'r.jsonl'), CODEX_FAKE_FINAL: 'Verdict: ship' },
1313
1302
  });
1314
1303
  rmSync(sb.root, { recursive: true, force: true });
@@ -1317,18 +1306,18 @@ describe('codex-review.sh — review receipts (AD-038)', () => {
1317
1306
  assert.match(r.stdout, /Verdict: ship/, 'the findings still reach stdout');
1318
1307
  });
1319
1308
 
1320
- it('a failed codex run writes NO receipt (only a successful review attests)', () => {
1309
+ it('a failed codex run writes NO receipt (only a successful review attests)', async () => {
1321
1310
  const sb = makeSandbox();
1322
- const r = run(sb, { env: { CODEX_FAKE_EXIT: '5' } });
1311
+ const r = await run(sb, { env: { CODEX_FAKE_EXIT: '5' } });
1323
1312
  const receipts = readReceipts(sb.repo);
1324
1313
  rmSync(sb.root, { recursive: true, force: true });
1325
1314
  assert.notEqual(r.status, 0);
1326
1315
  assert.equal(receipts.length, 0);
1327
1316
  });
1328
1317
 
1329
- it('the clean-tree preflight exits before any receipt is written', () => {
1318
+ it('the clean-tree preflight exits before any receipt is written', async () => {
1330
1319
  const sb = makeSandbox({ clean: true });
1331
- const r = run(sb);
1320
+ const r = await run(sb);
1332
1321
  const receipts = readReceipts(sb.repo);
1333
1322
  rmSync(sb.root, { recursive: true, force: true });
1334
1323
  assert.equal(r.status, 0);
@@ -1351,45 +1340,45 @@ const writeSettings = (sb, text) => {
1351
1340
  };
1352
1341
  const isRoot = typeof process.getuid === 'function' && process.getuid() === 0;
1353
1342
 
1354
- describe('codex-review.sh — service tier knob (bridges 2.3.0)', () => {
1355
- it('default: no env, no file → NO service_tier flag in codex argv', () => {
1343
+ describe('codex-review.sh — service tier knob (bridges 2.3.0)', { concurrency: 2 }, () => {
1344
+ it('default: no env, no file → NO service_tier flag in codex argv', async () => {
1356
1345
  const sb = makeSandbox();
1357
- const r = run(sb);
1346
+ const r = await run(sb);
1358
1347
  rmSync(sb.root, { recursive: true, force: true });
1359
1348
  assert.equal(r.status, 0, r.stderr);
1360
1349
  assert.doesNotMatch(r.argv, /service_tier/, 'default OFF: the flag must be absent');
1361
1350
  assert.doesNotMatch(r.stderr, /bridge settings/, 'no file → no settings chatter');
1362
1351
  });
1363
1352
 
1364
- it('env CODEX_SERVICE_TIER=priority → -c service_tier=priority reaches codex argv', () => {
1353
+ it('env CODEX_SERVICE_TIER=priority → -c service_tier=priority reaches codex argv', async () => {
1365
1354
  const sb = makeSandbox();
1366
- const r = run(sb, { env: { CODEX_SERVICE_TIER: 'priority' } });
1355
+ const r = await run(sb, { env: { CODEX_SERVICE_TIER: 'priority' } });
1367
1356
  rmSync(sb.root, { recursive: true, force: true });
1368
1357
  assert.equal(r.status, 0, r.stderr);
1369
1358
  assert.match(r.argv, /(^|\n)service_tier=priority(\n|$)/);
1370
1359
  });
1371
1360
 
1372
- it('a file-set tier lands (file wins over the built-in default)', () => {
1361
+ it('a file-set tier lands (file wins over the built-in default)', async () => {
1373
1362
  const sb = makeSandbox();
1374
1363
  writeSettings(sb, 'CODEX_SERVICE_TIER=priority\n');
1375
- const r = run(sb);
1364
+ const r = await run(sb);
1376
1365
  rmSync(sb.root, { recursive: true, force: true });
1377
1366
  assert.equal(r.status, 0, r.stderr);
1378
1367
  assert.match(r.argv, /(^|\n)service_tier=priority(\n|$)/);
1379
1368
  });
1380
1369
 
1381
- it('an EXPLICITLY EMPTY env (CODEX_SERVICE_TIER=) disables a file-set tier for one run', () => {
1370
+ it('an EXPLICITLY EMPTY env (CODEX_SERVICE_TIER=) disables a file-set tier for one run', async () => {
1382
1371
  const sb = makeSandbox();
1383
1372
  writeSettings(sb, 'CODEX_SERVICE_TIER=priority\n');
1384
- const r = run(sb, { env: { CODEX_SERVICE_TIER: '' } });
1373
+ const r = await run(sb, { env: { CODEX_SERVICE_TIER: '' } });
1385
1374
  rmSync(sb.root, { recursive: true, force: true });
1386
1375
  assert.equal(r.status, 0, r.stderr);
1387
1376
  assert.doesNotMatch(r.argv, /service_tier/, 'env wins over file — empty means knob off');
1388
1377
  });
1389
1378
 
1390
- it('an invalid env tier warns and reviews on the standard tier (never passed to codex)', () => {
1379
+ it('an invalid env tier warns and reviews on the standard tier (never passed to codex)', async () => {
1391
1380
  const sb = makeSandbox();
1392
- const r = run(sb, { env: { CODEX_SERVICE_TIER: 'turbo' } });
1381
+ const r = await run(sb, { env: { CODEX_SERVICE_TIER: 'turbo' } });
1393
1382
  rmSync(sb.root, { recursive: true, force: true });
1394
1383
  assert.equal(r.status, 0, r.stderr);
1395
1384
  assert.match(r.stderr, /not a supported service tier/);
@@ -1397,52 +1386,52 @@ describe('codex-review.sh — service tier knob (bridges 2.3.0)', () => {
1397
1386
  });
1398
1387
  });
1399
1388
 
1400
- describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', () => {
1401
- it('a file-set CODEX_REVIEW_MAX_TOTAL_BYTES is effective (switches to the temp-file path)', () => {
1389
+ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', { concurrency: 2 }, () => {
1390
+ it('a file-set CODEX_REVIEW_MAX_TOTAL_BYTES is effective (switches to the temp-file path)', async () => {
1402
1391
  const sb = makeSandbox();
1403
1392
  writeFileSync(join(sb.repo, 'big.txt'), 'B'.repeat(5000));
1404
1393
  writeSettings(sb, 'CODEX_REVIEW_MAX_TOTAL_BYTES=100\n');
1405
- const r = run(sb);
1394
+ const r = await run(sb);
1406
1395
  rmSync(sb.root, { recursive: true, force: true });
1407
1396
  assert.equal(r.status, 0, r.stderr);
1408
1397
  assert.match(r.capStdin, /codex-review-diff\./, 'the tiny file cap must force the temp-file path');
1409
1398
  assert.doesNotMatch(r.capStdin, /ASSEMBLED CHANGE SET:/, 'the payload must not ALSO ride inline');
1410
1399
  });
1411
1400
 
1412
- it('env overrides file: a large env cap keeps the payload inline', () => {
1401
+ it('env overrides file: a large env cap keeps the payload inline', async () => {
1413
1402
  const sb = makeSandbox();
1414
1403
  writeFileSync(join(sb.repo, 'big.txt'), 'B'.repeat(5000));
1415
1404
  writeSettings(sb, 'CODEX_REVIEW_MAX_TOTAL_BYTES=100\n');
1416
- const r = run(sb, { env: { CODEX_REVIEW_MAX_TOTAL_BYTES: '5000000' } });
1405
+ const r = await run(sb, { env: { CODEX_REVIEW_MAX_TOTAL_BYTES: '5000000' } });
1417
1406
  rmSync(sb.root, { recursive: true, force: true });
1418
1407
  assert.equal(r.status, 0, r.stderr);
1419
1408
  assert.match(r.capStdin, /ASSEMBLED CHANGE SET:/, 'the env cap (large) must win over the file cap (100)');
1420
1409
  assert.doesNotMatch(r.capStdin, /codex-review-diff\./);
1421
1410
  });
1422
1411
 
1423
- it('duplicate key → the LAST occurrence wins (100 then 5000000 → inline)', () => {
1412
+ it('duplicate key → the LAST occurrence wins (100 then 5000000 → inline)', async () => {
1424
1413
  const sb = makeSandbox();
1425
1414
  writeFileSync(join(sb.repo, 'big.txt'), 'B'.repeat(5000));
1426
1415
  writeSettings(sb, 'CODEX_REVIEW_MAX_TOTAL_BYTES=100\nCODEX_REVIEW_MAX_TOTAL_BYTES=5000000\n');
1427
- const r = run(sb);
1416
+ const r = await run(sb);
1428
1417
  rmSync(sb.root, { recursive: true, force: true });
1429
1418
  assert.equal(r.status, 0, r.stderr);
1430
1419
  assert.match(r.capStdin, /ASSEMBLED CHANGE SET:/);
1431
1420
  });
1432
1421
 
1433
- it("another wrapper's / another bridge's valid key is skipped silently", () => {
1422
+ it("another wrapper's / another bridge's valid key is skipped silently", async () => {
1434
1423
  const sb = makeSandbox();
1435
1424
  writeSettings(sb, 'AGY_HARD_TIMEOUT=30m\nAGY_REVIEW_ALLOW_ADDDIR=1\n');
1436
- const r = run(sb);
1425
+ const r = await run(sb);
1437
1426
  rmSync(sb.root, { recursive: true, force: true });
1438
1427
  assert.equal(r.status, 0, r.stderr);
1439
1428
  assert.doesNotMatch(r.stderr, /bridge settings/, 'a recognized non-applied key earns NO warning');
1440
1429
  });
1441
1430
 
1442
- it('a truly unknown key warns ONCE naming the file; the review is unaffected', () => {
1431
+ it('a truly unknown key warns ONCE naming the file; the review is unaffected', async () => {
1443
1432
  const sb = makeSandbox();
1444
1433
  writeSettings(sb, 'TOTALLY_UNKNOWN=1\nTOTALLY_UNKNOWN=2\n');
1445
- const r = run(sb);
1434
+ const r = await run(sb);
1446
1435
  rmSync(sb.root, { recursive: true, force: true });
1447
1436
  assert.equal(r.status, 0, r.stderr);
1448
1437
  const warns = r.stderr.match(/unknown key 'TOTALLY_UNKNOWN'/g) ?? [];
@@ -1450,10 +1439,10 @@ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', (
1450
1439
  assert.match(r.stderr, /bridge-settings\.conf/, 'the warning must name the settings file');
1451
1440
  });
1452
1441
 
1453
- it('malformed lines warn and are ignored; comments and blank lines are silent', () => {
1442
+ it('malformed lines warn and are ignored; comments and blank lines are silent', async () => {
1454
1443
  const sb = makeSandbox();
1455
1444
  writeSettings(sb, '# a comment\n\nNOT A KEY VALUE LINE\nCODEX_SERVICE_TIER=priority\n');
1456
- const r = run(sb);
1445
+ const r = await run(sb);
1457
1446
  rmSync(sb.root, { recursive: true, force: true });
1458
1447
  assert.equal(r.status, 0, r.stderr);
1459
1448
  const malformed = r.stderr.match(/malformed line/g) ?? [];
@@ -1461,7 +1450,7 @@ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', (
1461
1450
  assert.match(r.argv, /(^|\n)service_tier=priority(\n|$)/, 'valid lines still apply');
1462
1451
  });
1463
1452
 
1464
- it('an existing-but-unreadable file warns loudly and falls back to built-ins', { skip: isRoot }, () => {
1453
+ it('an existing-but-unreadable file warns loudly and falls back to built-ins', { skip: isRoot }, async () => {
1465
1454
  // The settings file goes OUTSIDE the repo (XDG_CONFIG_HOME): an unreadable file INSIDE the
1466
1455
  // work tree would fail the review-payload assembly itself (untracked contents are cat'ed),
1467
1456
  // which is pre-existing behaviour unrelated to the settings reader.
@@ -1471,14 +1460,14 @@ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', (
1471
1460
  const file = join(xdg, 'agent-workflow', 'bridge-settings.conf');
1472
1461
  writeFileSync(file, 'CODEX_SERVICE_TIER=priority\n');
1473
1462
  chmodSync(file, 0o000);
1474
- const r = run(sb, { env: { XDG_CONFIG_HOME: xdg } });
1463
+ const r = await run(sb, { env: { XDG_CONFIG_HOME: xdg } });
1475
1464
  rmSync(sb.root, { recursive: true, force: true });
1476
1465
  assert.equal(r.status, 0, r.stderr);
1477
1466
  assert.match(r.stderr, /unreadable/);
1478
1467
  assert.doesNotMatch(r.argv, /service_tier/, 'an unreadable file must yield built-in defaults');
1479
1468
  });
1480
1469
 
1481
- it('a settings line can NEVER execute code (command-substitution payload inert)', () => {
1470
+ it('a settings line can NEVER execute code (command-substitution payload inert)', async () => {
1482
1471
  const sb = makeSandbox();
1483
1472
  const pwned = join(sb.repo, 'pwned');
1484
1473
  const pwned2 = join(sb.repo, 'pwned2');
@@ -1486,7 +1475,7 @@ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', (
1486
1475
  sb,
1487
1476
  `CODEX_SERVICE_TIER=$(touch ${pwned})\nEVIL_KEY=\`touch ${pwned2}\`\n`,
1488
1477
  );
1489
- const r = run(sb);
1478
+ const r = await run(sb);
1490
1479
  const executed = existsSync(pwned) || existsSync(pwned2);
1491
1480
  rmSync(sb.root, { recursive: true, force: true });
1492
1481
  assert.equal(r.status, 0, r.stderr);
@@ -1494,13 +1483,13 @@ describe('codex-review.sh — bridge settings file semantics (bridges 2.3.0)', (
1494
1483
  assert.doesNotMatch(r.argv, /service_tier/, 'the payload value must fail validation');
1495
1484
  });
1496
1485
 
1497
- it('a DIRECTORY at the settings path warns loudly and falls back to built-ins (no crash)', () => {
1486
+ it('a DIRECTORY at the settings path warns loudly and falls back to built-ins (no crash)', async () => {
1498
1487
  // Outside the repo (XDG) — an unreadable path INSIDE the work tree would fail the
1499
1488
  // review-payload assembly itself (pre-existing behaviour, unrelated to the reader).
1500
1489
  const sb = makeSandbox();
1501
1490
  const xdg = join(sb.root, 'xdg');
1502
1491
  mkdirSync(join(xdg, 'agent-workflow', 'bridge-settings.conf'), { recursive: true });
1503
- const r = run(sb, { env: { XDG_CONFIG_HOME: xdg } });
1492
+ const r = await run(sb, { env: { XDG_CONFIG_HOME: xdg } });
1504
1493
  rmSync(sb.root, { recursive: true, force: true });
1505
1494
  assert.equal(r.status, 0, `a directory must degrade honestly, not kill the run: ${r.stderr}`);
1506
1495
  assert.match(r.stderr, /unreadable or not a regular file/);
@@ -1514,8 +1503,8 @@ const SIBLING_MANIFEST = JSON.parse(readFileSync(join(HERE, '..', '..', 'antigra
1514
1503
  const ALL_SETTINGS = [...(MANIFEST.settings ?? []), ...(SIBLING_MANIFEST.settings ?? [])];
1515
1504
  const SETTINGS_CMD = 'codex-review';
1516
1505
 
1517
- describe('codex-review.sh — settings surface ⟷ manifest (D6, manifest-pinned)', () => {
1518
- it('--help Settings section keys set-EQUAL the manifest appliesTo subset', () => {
1506
+ describe('codex-review.sh — settings surface ⟷ manifest (D6, manifest-pinned)', { concurrency: 2 }, () => {
1507
+ it('--help Settings section keys set-EQUAL the manifest appliesTo subset', async () => {
1519
1508
  const help = runHelp('--help').stdout;
1520
1509
  const section = helpSection(help, SETTINGS_HEADER);
1521
1510
  const got = section.filter((l) => /^[A-Z][A-Z0-9_]+ —/.test(l)).map((l) => l.split(' ')[0]);
@@ -1527,14 +1516,14 @@ describe('codex-review.sh — settings surface ⟷ manifest (D6, manifest-pinned
1527
1516
 
1528
1517
  const source = readFileSync(WRAPPER, 'utf8');
1529
1518
 
1530
- it('aw_settings_known carries exactly the UNION of both bridges settings keys', () => {
1519
+ it('aw_settings_known carries exactly the UNION of both bridges settings keys', async () => {
1531
1520
  const m = source.match(/aw_settings_known\(\) \{\n case " ([^"]+) " in/);
1532
1521
  assert.ok(m, 'aw_settings_known registry case not found');
1533
1522
  assert.ok(ALL_SETTINGS.length >= 5, 'both manifests must contribute settings');
1534
1523
  setEq(m[1].trim().split(/\s+/), ALL_SETTINGS.map((s) => s.key), 'shell registry ⟷ manifest union');
1535
1524
  });
1536
1525
 
1537
- it('AW_SETTINGS_APPLIED equals the manifest appliesTo subset for this wrapper', () => {
1526
+ it('AW_SETTINGS_APPLIED equals the manifest appliesTo subset for this wrapper', async () => {
1538
1527
  const m = source.match(/^AW_SETTINGS_APPLIED="([^"]*)"$/m);
1539
1528
  assert.ok(m, 'AW_SETTINGS_APPLIED not found');
1540
1529
  const want = ALL_SETTINGS.filter((s) => s.appliesTo.includes(SETTINGS_CMD)).map((s) => s.key);
@@ -1542,7 +1531,7 @@ describe('codex-review.sh — settings surface ⟷ manifest (D6, manifest-pinned
1542
1531
  setEq(m[1].trim().split(/\s+/), want, 'applied subset ⟷ manifest appliesTo');
1543
1532
  });
1544
1533
 
1545
- it('aw_settings_valid arms carry the manifest typed constants per key', () => {
1534
+ it('aw_settings_valid arms carry the manifest typed constants per key', async () => {
1546
1535
  const body = source.match(/aw_settings_valid\(\) \{[\s\S]*?\n\}/);
1547
1536
  assert.ok(body, 'aw_settings_valid not found');
1548
1537
  const armKeys = [...body[0].matchAll(/^ ([A-Z][A-Z0-9_]*)\)/gm)].map((x) => x[1]);
@@ -1566,10 +1555,10 @@ describe('codex-review.sh — settings surface ⟷ manifest (D6, manifest-pinned
1566
1555
  });
1567
1556
 
1568
1557
  // ── strip-the-kit Phase 4: wrapper honesty (D4) + dispatch-posture labeling (D5) ────────────────
1569
- describe('codex-review.sh — wrapper honesty: a verdict-less run is a FAILED review (D4)', () => {
1570
- it('a VERDICT-LESS final message: non-zero exit, NO receipt, the stated re-run recovery', () => {
1558
+ describe('codex-review.sh — wrapper honesty: a verdict-less run is a FAILED review (D4)', { concurrency: 2 }, () => {
1559
+ it('a VERDICT-LESS final message: non-zero exit, NO receipt, the stated re-run recovery', async () => {
1571
1560
  const sb = makeSandbox();
1572
- const r = run(sb, { env: { CODEX_FAKE_FINAL: 'prose without the mandated verdict line' } });
1561
+ const r = await run(sb, { env: { CODEX_FAKE_FINAL: 'prose without the mandated verdict line' } });
1573
1562
  const receipts = readReceipts(sb.repo);
1574
1563
  rmSync(sb.root, { recursive: true, force: true });
1575
1564
  assert.notEqual(r.status, 0, 'a verdict-less review never exits 0');
@@ -1578,18 +1567,18 @@ describe('codex-review.sh — wrapper honesty: a verdict-less run is a FAILED re
1578
1567
  assert.match(r.stderr, /re-run/i, 'documented as a failed review — re-run, never fatal');
1579
1568
  });
1580
1569
 
1581
- it('an EMPTY final message is the same failed run (non-zero, no receipt)', () => {
1570
+ it('an EMPTY final message is the same failed run (non-zero, no receipt)', async () => {
1582
1571
  const sb = makeSandbox();
1583
- const r = run(sb, { env: { CODEX_FAKE_FINAL: '' } });
1572
+ const r = await run(sb, { env: { CODEX_FAKE_FINAL: '' } });
1584
1573
  const receipts = readReceipts(sb.repo);
1585
1574
  rmSync(sb.root, { recursive: true, force: true });
1586
1575
  assert.notEqual(r.status, 0);
1587
1576
  assert.equal(receipts.length, 0);
1588
1577
  });
1589
1578
 
1590
- it('a MISSING final-message file is the same failed run', () => {
1579
+ it('a MISSING final-message file is the same failed run', async () => {
1591
1580
  const sb = makeSandbox();
1592
- const r = run(sb, { env: { CODEX_FAKE_NO_OUT: '1' } });
1581
+ const r = await run(sb, { env: { CODEX_FAKE_NO_OUT: '1' } });
1593
1582
  const receipts = readReceipts(sb.repo);
1594
1583
  rmSync(sb.root, { recursive: true, force: true });
1595
1584
  assert.notEqual(r.status, 0);
@@ -1597,10 +1586,10 @@ describe('codex-review.sh — wrapper honesty: a verdict-less run is a FAILED re
1597
1586
  });
1598
1587
  });
1599
1588
 
1600
- describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1601
- it('ONE banner line carries the ACTUAL {model, effort, tier} and the receipt carries the SAME posture', () => {
1589
+ describe('codex-review.sh — dispatch-posture labeling (D5)', { concurrency: 2 }, () => {
1590
+ it('ONE banner line carries the ACTUAL {model, effort, tier} and the receipt carries the SAME posture', async () => {
1602
1591
  const sb = makeSandbox();
1603
- const r = run(sb, {});
1592
+ const r = await run(sb, {});
1604
1593
  const receipts = readReceipts(sb.repo);
1605
1594
  rmSync(sb.root, { recursive: true, force: true });
1606
1595
  assert.equal(r.status, 0, r.stderr);
@@ -1609,9 +1598,9 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1609
1598
  assert.deepEqual(Object.keys(receipts[0]), Object.keys(RECEIPT_FIXTURE), 'fixture key set + order');
1610
1599
  });
1611
1600
 
1612
- it('an ARMED Fast tier rides both surfaces (banner tier=priority; receipt tier "priority")', () => {
1601
+ it('an ARMED Fast tier rides both surfaces (banner tier=priority; receipt tier "priority")', async () => {
1613
1602
  const sb = makeSandbox();
1614
- const r = run(sb, { env: { CODEX_SERVICE_TIER: 'priority' } });
1603
+ const r = await run(sb, { env: { CODEX_SERVICE_TIER: 'priority' } });
1615
1604
  const receipts = readReceipts(sb.repo);
1616
1605
  rmSync(sb.root, { recursive: true, force: true });
1617
1606
  assert.equal(r.status, 0, r.stderr);
@@ -1619,10 +1608,10 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1619
1608
  assert.equal(receipts[0].posture.tier, 'priority');
1620
1609
  });
1621
1610
 
1622
- it('a HOSTILE model string (quotes + backslash) rides the receipt strictly JSON-encoded (probe lane)', () => {
1611
+ it('a HOSTILE model string (quotes + backslash) rides the receipt strictly JSON-encoded (probe lane)', async () => {
1623
1612
  const hostile = 'we"ird \\ mo"del';
1624
1613
  const sb = makeSandbox();
1625
- const r = run(sb, { env: { CODEX_PROBE: '1', CODEX_MODEL: hostile } });
1614
+ const r = await run(sb, { env: { CODEX_PROBE: '1', CODEX_MODEL: hostile } });
1626
1615
  const receipts = readReceipts(sb.repo); // JSON.parse throwing here IS the encoding failure
1627
1616
  rmSync(sb.root, { recursive: true, force: true });
1628
1617
  assert.equal(r.status, 0, r.stderr);
@@ -1630,9 +1619,9 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1630
1619
  assert.equal(receipts[0].probe, true, 'an off-pinned model runs only on the probe lane');
1631
1620
  });
1632
1621
 
1633
- it('a posture value carrying CONTROL BYTES refuses pre-spend, BEFORE the frontier guard', () => {
1622
+ it('a posture value carrying CONTROL BYTES refuses pre-spend, BEFORE the pinned-model guard', async () => {
1634
1623
  const sb = makeSandbox();
1635
- const r = run(sb, { env: { CODEX_MODEL: `gpt-5.6-sol${String.fromCharCode(1)}` } });
1624
+ const r = await run(sb, { env: { CODEX_MODEL: `gpt-5.6-sol${String.fromCharCode(1)}` } });
1636
1625
  const receipts = readReceipts(sb.repo);
1637
1626
  rmSync(sb.root, { recursive: true, force: true });
1638
1627
  assert.notEqual(r.status, 0);
@@ -1641,9 +1630,9 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1641
1630
  assert.match(r.stderr, /control/i, 'named as the control-byte class, not a policy refusal');
1642
1631
  });
1643
1632
 
1644
- it('the banner appends the RESOLVED hard timeout — banner-only, never in the receipt (AD-061)', () => {
1633
+ it('the banner appends the RESOLVED hard timeout — banner-only, never in the receipt (AD-061)', async () => {
1645
1634
  const sb = makeSandbox();
1646
- const r = run(sb, {});
1635
+ const r = await run(sb, {});
1647
1636
  const receipts = readReceipts(sb.repo);
1648
1637
  rmSync(sb.root, { recursive: true, force: true });
1649
1638
  assert.equal(r.status, 0, r.stderr);
@@ -1651,18 +1640,18 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1651
1640
  assert.deepEqual(Object.keys(receipts[0].posture), ['model', 'effort', 'tier'], 'timeout never enters the receipt posture');
1652
1641
  });
1653
1642
 
1654
- it('an INVALID effective CODEX_HARD_TIMEOUT (env — the closed aw_settings_valid bypass) warns and the banner prints the default', () => {
1643
+ it('an INVALID effective CODEX_HARD_TIMEOUT (env — the closed aw_settings_valid bypass) warns and the banner prints the default', async () => {
1655
1644
  const sb = makeSandbox();
1656
- const r = run(sb, { env: { CODEX_HARD_TIMEOUT: 'nonsense' } });
1645
+ const r = await run(sb, { env: { CODEX_HARD_TIMEOUT: 'nonsense' } });
1657
1646
  rmSync(sb.root, { recursive: true, force: true });
1658
1647
  assert.equal(r.status, 0, r.stderr);
1659
1648
  assert.match(r.stderr, /invalid value 'nonsense' for CODEX_HARD_TIMEOUT/, 'the fallback is loud');
1660
1649
  assert.match(r.stderr, /^review posture: .* timeout=1800s$/m, 'the banner prints the built-in default');
1661
1650
  });
1662
1651
 
1663
- it('a CODEX_HARD_TIMEOUT carrying CONTROL BYTES refuses pre-spend (the banner-field screen)', () => {
1652
+ it('a CODEX_HARD_TIMEOUT carrying CONTROL BYTES refuses pre-spend (the banner-field screen)', async () => {
1664
1653
  const sb = makeSandbox();
1665
- const r = run(sb, { env: { CODEX_HARD_TIMEOUT: `1800${String.fromCharCode(1)}` } });
1654
+ const r = await run(sb, { env: { CODEX_HARD_TIMEOUT: `1800${String.fromCharCode(1)}` } });
1666
1655
  const receipts = readReceipts(sb.repo);
1667
1656
  rmSync(sb.root, { recursive: true, force: true });
1668
1657
  assert.notEqual(r.status, 0);
@@ -1671,9 +1660,9 @@ describe('codex-review.sh — dispatch-posture labeling (D5)', () => {
1671
1660
  assert.match(r.stderr, /control/i);
1672
1661
  });
1673
1662
 
1674
- it('a DEL (0x7f) byte in a banner field refuses pre-spend like the C0 range', () => {
1663
+ it('a DEL (0x7f) byte in a banner field refuses pre-spend like the C0 range', async () => {
1675
1664
  const sb = makeSandbox();
1676
- const r = run(sb, { env: { CODEX_MODEL: `gpt-5.6-sol${String.fromCharCode(127)}` } });
1665
+ const r = await run(sb, { env: { CODEX_MODEL: `gpt-5.6-sol${String.fromCharCode(127)}` } });
1677
1666
  const receipts = readReceipts(sb.repo);
1678
1667
  rmSync(sb.root, { recursive: true, force: true });
1679
1668
  assert.notEqual(r.status, 0);