@open-agent-toolkit/cli 0.2.23 → 0.2.24

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.
@@ -717,8 +717,21 @@ Each liveness tick keeps stdout-idle time and also reports `processAlive` plus
717
717
  the latest metadata-only transcript activity as `lastActivityEvidence` when
718
718
  available. The probe performs bounded depth-two traversal and compares newest
719
719
  mtime plus total size with its spawn baseline. It never reads transcript
720
- contents, never extends a budget, and never changes pass/fail or receive
721
- eligibility.
720
+ contents and never changes pass/fail or receive eligibility.
721
+
722
+ When the hard timeout fires, OAT stops periodic liveness ticks, sends `SIGTERM`,
723
+ schedules the existing `SIGKILL` fallback, and then starts one final transcript
724
+ observation with the timeout timestamp. Once the child closes, result resolution
725
+ waits no longer than the one-second observation grace and does not delay either
726
+ signal. A final sample available before result resolution supersedes older
727
+ in-flight periodic work; otherwise OAT retains the latest valid periodic
728
+ evidence.
729
+
730
+ On a normal child close, OAT waits within the same one-second grace only when a
731
+ periodic transcript observation is already in flight. This preserves late
732
+ evidence but can add up to one second to an otherwise successful execution. The
733
+ one-second observation grace and five-second force-kill fallback are fixed
734
+ safety bounds, not environment-tunable settings.
722
735
 
723
736
  Claude and Cursor evidence has `scope: project-dir`. Codex's date-sharded
724
737
  sessions directory is shared across the runtime, so its evidence has
@@ -726,7 +739,18 @@ sessions directory is shared across the runtime, so its evidence has
726
739
  attributable to this gate child).” Probe errors fail soft to process and stdout
727
740
  telemetry.
728
741
 
729
- Timeout and child-failure envelopes include the latest `activityEvidence`.
742
+ Timeout and child-failure JSON envelopes include the latest `activityEvidence`.
743
+ For human timeout and non-refusal child-failure output, OAT prints a second line
744
+ with this shape:
745
+
746
+ ```text
747
+ Activity evidence: <runtime> <project|ambient> transcript metadata <changed|did not change> since baseline; observed <milliseconds>ms ago; latest transcript change was <milliseconds>ms before observation.
748
+ ```
749
+
750
+ When the evidence scope is ambient, the line ends with `This activity is not
751
+ attributable to this gate child.` Structured refusals omit the extra human
752
+ diagnostic because the refusal itself explains why execution stopped.
753
+
730
754
  Before spawn, the gate also writes a transient marker under the system temp
731
755
  directory at `oat-gate-runs/<runId>.json`; startup diagnostics print its path.
732
756
  The marker records target, runtime, project, review type/scope, start time,
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.2.23",
3
- "docs-config": "0.2.23",
4
- "docs-theme": "0.2.23",
5
- "docs-transforms": "0.2.23"
2
+ "cli": "0.2.24",
3
+ "docs-config": "0.2.24",
4
+ "docs-theme": "0.2.24",
5
+ "docs-transforms": "0.2.24"
6
6
  }
@@ -0,0 +1,32 @@
1
+ import type { GateActivityEvidence, GateActivityProbe, GateActivityProbeStatus } from './activity-probes.js';
2
+ export interface ProcessRunOptions {
3
+ activityProbe?: GateActivityProbe;
4
+ cwd: string;
5
+ env: NodeJS.ProcessEnv;
6
+ livenessIntervalMs?: number;
7
+ onLiveness?: (snapshot: GateLivenessSnapshot) => void;
8
+ purpose: 'host-detection' | 'availability' | 'execute';
9
+ stdin: 'ignore' | 'inherit';
10
+ stdio: 'ignore' | 'inherit' | 'pipe';
11
+ stdoutDestination?: 'stdout' | 'stderr';
12
+ timeoutMs: number;
13
+ }
14
+ export interface ProcessRunResult {
15
+ activityEvidence?: GateActivityEvidence;
16
+ exitCode: number;
17
+ refusal?: string;
18
+ stderrBytes: number;
19
+ stdoutBytes: number;
20
+ timedOut?: boolean;
21
+ }
22
+ export interface GateLivenessSnapshot {
23
+ elapsedMs: number;
24
+ hardBudgetMs: number;
25
+ idleMs: number;
26
+ processAlive: boolean;
27
+ activityProbeStatus?: GateActivityProbeStatus;
28
+ lastActivityEvidence?: GateActivityEvidence;
29
+ }
30
+ export declare function runChildProcess(command: string, args: string[], options: ProcessRunOptions): Promise<ProcessRunResult>;
31
+ export declare function extractStructuredRefusal(output: string): string | undefined;
32
+ //# sourceMappingURL=child-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/child-process.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAS3B,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACvD,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,uBAAuB,CAAC;IAC9C,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAgN3B;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG3E"}
@@ -0,0 +1,210 @@
1
+ import { spawn } from 'node:child_process';
2
+ // Keep these safety bounds fixed rather than environment-tunable. In particular,
3
+ // changing the force-kill fallback would alter the hard-timeout contract.
4
+ // Revisit the observation grace only if field evidence shows large transcript
5
+ // directories routinely exceed it.
6
+ const FORCE_KILL_GRACE_MS = 5_000;
7
+ const ACTIVITY_OBSERVATION_GRACE_MS = 1_000;
8
+ export async function runChildProcess(command, args, options) {
9
+ return new Promise((resolve, reject) => {
10
+ let timedOut = false;
11
+ let suppressLiveness = false;
12
+ let killTimeout = null;
13
+ let stderrBytes = 0;
14
+ let stdoutBytes = 0;
15
+ let refusal;
16
+ let stdoutLineBuffer = '';
17
+ let stderrLineBuffer = '';
18
+ let latestActivityEvidence;
19
+ let latestActivityProbeStatus;
20
+ let activityObservationSequence = 0;
21
+ let latestActivityEvidenceSequence = 0;
22
+ let livenessProbePending = false;
23
+ let pendingPeriodicObservation;
24
+ let finalActivityObservation;
25
+ const startedAt = Date.now();
26
+ let lastActivityAt = startedAt;
27
+ const child = spawn(command, args, {
28
+ cwd: options.cwd,
29
+ env: options.env,
30
+ stdio: options.stdio === 'pipe'
31
+ ? [options.stdin, 'pipe', 'pipe']
32
+ : options.stdio,
33
+ });
34
+ const recordActivity = () => {
35
+ lastActivityAt = Date.now();
36
+ };
37
+ const scanChunk = (buffer, chunk) => {
38
+ const combined = buffer + chunk.toString('utf8');
39
+ const lines = combined.split('\n');
40
+ const remainder = lines.pop() ?? '';
41
+ if (!refusal) {
42
+ for (const line of lines) {
43
+ refusal = extractStructuredRefusal(line.replace(/\r$/, ''));
44
+ if (refusal) {
45
+ break;
46
+ }
47
+ }
48
+ }
49
+ return remainder;
50
+ };
51
+ child.stdout?.on('data', (chunk) => {
52
+ stdoutBytes += chunk.byteLength;
53
+ stdoutLineBuffer = scanChunk(stdoutLineBuffer, chunk);
54
+ recordActivity();
55
+ const destination = options.stdoutDestination === 'stderr'
56
+ ? process.stderr
57
+ : process.stdout;
58
+ destination.write(chunk);
59
+ });
60
+ child.stderr?.on('data', (chunk) => {
61
+ stderrBytes += chunk.byteLength;
62
+ stderrLineBuffer = scanChunk(stderrLineBuffer, chunk);
63
+ recordActivity();
64
+ process.stderr.write(chunk);
65
+ });
66
+ const processAlive = () => {
67
+ if (child.pid === undefined)
68
+ return false;
69
+ try {
70
+ process.kill(child.pid, 0);
71
+ return true;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ };
77
+ const observeActivity = async (observedAt) => {
78
+ if (!options.activityProbe)
79
+ return undefined;
80
+ const sequence = ++activityObservationSequence;
81
+ try {
82
+ const activityProbeStatus = await options.activityProbe.observe(observedAt);
83
+ const evidence = activityProbeStatus.evidence;
84
+ if (evidence && sequence > latestActivityEvidenceSequence) {
85
+ latestActivityEvidence = evidence;
86
+ latestActivityEvidenceSequence = sequence;
87
+ }
88
+ return activityProbeStatus;
89
+ }
90
+ catch {
91
+ // Activity evidence is diagnostic only. Preserve the last valid sample.
92
+ return undefined;
93
+ }
94
+ };
95
+ const settleWithinActivityGrace = (observation) => new Promise((resolveObservation) => {
96
+ // Keep this timer referenced so a closed child cannot end the process
97
+ // before the bounded diagnostic observation settles.
98
+ const graceTimeout = setTimeout(resolveObservation, ACTIVITY_OBSERVATION_GRACE_MS);
99
+ const settle = () => {
100
+ clearTimeout(graceTimeout);
101
+ resolveObservation();
102
+ };
103
+ void observation.then(settle, settle);
104
+ });
105
+ const livenessInterval = options.onLiveness && options.livenessIntervalMs
106
+ ? setInterval(() => {
107
+ if (livenessProbePending)
108
+ return;
109
+ livenessProbePending = true;
110
+ const now = Date.now();
111
+ const observation = (async () => {
112
+ const activityProbeStatus = await observeActivity(now);
113
+ if (activityProbeStatus) {
114
+ latestActivityProbeStatus = activityProbeStatus;
115
+ }
116
+ if (suppressLiveness)
117
+ return;
118
+ options.onLiveness?.({
119
+ elapsedMs: now - startedAt,
120
+ hardBudgetMs: options.timeoutMs,
121
+ idleMs: now - lastActivityAt,
122
+ processAlive: processAlive(),
123
+ ...(latestActivityProbeStatus
124
+ ? { activityProbeStatus: latestActivityProbeStatus }
125
+ : {}),
126
+ ...(latestActivityEvidence
127
+ ? { lastActivityEvidence: latestActivityEvidence }
128
+ : {}),
129
+ });
130
+ })();
131
+ pendingPeriodicObservation = observation;
132
+ const clearPending = () => {
133
+ if (pendingPeriodicObservation === observation) {
134
+ pendingPeriodicObservation = undefined;
135
+ }
136
+ livenessProbePending = false;
137
+ };
138
+ void observation.then(clearPending, clearPending);
139
+ }, options.livenessIntervalMs)
140
+ : null;
141
+ livenessInterval?.unref();
142
+ const timeout = setTimeout(() => {
143
+ timedOut = true;
144
+ suppressLiveness = true;
145
+ if (livenessInterval) {
146
+ clearInterval(livenessInterval);
147
+ }
148
+ child.kill('SIGTERM');
149
+ killTimeout = setTimeout(() => {
150
+ child.kill('SIGKILL');
151
+ }, FORCE_KILL_GRACE_MS);
152
+ killTimeout.unref();
153
+ finalActivityObservation = observeActivity(Date.now());
154
+ }, options.timeoutMs);
155
+ timeout.unref();
156
+ child.on('error', (error) => {
157
+ clearTimeout(timeout);
158
+ if (livenessInterval) {
159
+ clearInterval(livenessInterval);
160
+ }
161
+ if (killTimeout) {
162
+ clearTimeout(killTimeout);
163
+ }
164
+ reject(error);
165
+ });
166
+ child.on('close', (code) => {
167
+ suppressLiveness = true;
168
+ clearTimeout(timeout);
169
+ if (livenessInterval) {
170
+ clearInterval(livenessInterval);
171
+ }
172
+ if (killTimeout) {
173
+ clearTimeout(killTimeout);
174
+ }
175
+ void (async () => {
176
+ if (finalActivityObservation) {
177
+ const periodicObservation = pendingPeriodicObservation;
178
+ const finalThenFallback = finalActivityObservation.then(async (activityProbeStatus) => {
179
+ if (!activityProbeStatus?.evidence && periodicObservation) {
180
+ await periodicObservation;
181
+ }
182
+ });
183
+ await settleWithinActivityGrace(finalThenFallback);
184
+ }
185
+ else if (pendingPeriodicObservation) {
186
+ // Preserve evidence already in flight on a normal close. This can add
187
+ // up to the bounded grace to an otherwise successful execution.
188
+ await settleWithinActivityGrace(pendingPeriodicObservation);
189
+ }
190
+ refusal ??=
191
+ extractStructuredRefusal(stdoutLineBuffer.replace(/\r$/, '')) ??
192
+ extractStructuredRefusal(stderrLineBuffer.replace(/\r$/, ''));
193
+ resolve({
194
+ ...(latestActivityEvidence
195
+ ? { activityEvidence: latestActivityEvidence }
196
+ : {}),
197
+ exitCode: timedOut ? 124 : (code ?? 1),
198
+ ...(refusal ? { refusal } : {}),
199
+ stderrBytes,
200
+ stdoutBytes,
201
+ ...(timedOut ? { timedOut: true } : {}),
202
+ });
203
+ })();
204
+ });
205
+ });
206
+ }
207
+ export function extractStructuredRefusal(output) {
208
+ const match = output.match(/^OAT_GATE_REFUSAL: (.*)$/m);
209
+ return match?.[1]?.replace(/\r$/, '');
210
+ }
@@ -5,8 +5,9 @@ import { type ResolvedConfig } from '../../config/resolve.js';
5
5
  import { type ModelFamily } from '../../providers/identity/family.js';
6
6
  import { type IdentityConfidence, type IdentityProvenance } from '../../providers/identity/provenance.js';
7
7
  import { Command } from 'commander';
8
- import { createGateActivityProbe, type GateActivityEvidence, type GateActivityProbe, type GateActivityProbeStatus } from './activity-probes.js';
8
+ import { createGateActivityProbe } from './activity-probes.js';
9
9
  import { createBranchLocalGateCli, currentGateCliLaunch, readGateRouteReceipt, removeBranchLocalGateCli } from './branch-local-cli.js';
10
+ import { type ProcessRunOptions, type ProcessRunResult } from './child-process.js';
10
11
  import { parseReviewGateVerdict } from './review-verdict.js';
11
12
  interface GateCommandDependencies {
12
13
  buildCommandContext: (options: GlobalOptions) => CommandContext;
@@ -31,36 +32,6 @@ interface GateCommandDependencies {
31
32
  removeGateRunMarker: (path: string, warn: (message: string) => void) => Promise<void>;
32
33
  writeDiagnostic: (message: string) => void;
33
34
  }
34
- interface ProcessRunOptions {
35
- activityProbe?: GateActivityProbe;
36
- cwd: string;
37
- env: NodeJS.ProcessEnv;
38
- livenessIntervalMs?: number;
39
- onLiveness?: (snapshot: GateLivenessSnapshot) => void;
40
- purpose: 'host-detection' | 'availability' | 'execute';
41
- stdin: 'ignore' | 'inherit';
42
- stdio: 'ignore' | 'inherit' | 'pipe';
43
- stdoutDestination?: 'stdout' | 'stderr';
44
- timeoutMs: number;
45
- }
46
- interface ProcessRunResult {
47
- activityEvidence?: GateActivityEvidence;
48
- activityProbeStatus?: GateActivityProbeStatus;
49
- capturedOutput?: string;
50
- exitCode: number;
51
- refusal?: string;
52
- stderrBytes: number;
53
- stdoutBytes: number;
54
- timedOut?: boolean;
55
- }
56
- interface GateLivenessSnapshot {
57
- elapsedMs: number;
58
- hardBudgetMs: number;
59
- idleMs: number;
60
- processAlive: boolean;
61
- activityProbeStatus?: GateActivityProbeStatus;
62
- lastActivityEvidence?: GateActivityEvidence;
63
- }
64
35
  type GateTimeoutSource = 'cli' | 'target' | 'config' | 'env' | 'scope-default' | 'default';
65
36
  interface GateRunMarker {
66
37
  runId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { execFileSync, spawn } from 'node:child_process';
1
+ import { execFileSync } from 'node:child_process';
2
2
  import { createHash, randomUUID } from 'node:crypto';
3
3
  import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
4
4
  import { tmpdir } from 'node:os';
@@ -20,6 +20,7 @@ import { Command } from 'commander';
20
20
  import YAML from 'yaml';
21
21
  import { createGateActivityProbe, } from './activity-probes.js';
22
22
  import { createBranchLocalGateCli, currentGateCliLaunch, readGateRouteReceipt, removeBranchLocalGateCli, } from './branch-local-cli.js';
23
+ import { runChildProcess, } from './child-process.js';
23
24
  import { parseReviewGateVerdict, severityDisplayName, } from './review-verdict.js';
24
25
  import { createGateRouteCommand } from './route.js';
25
26
  const DEFAULT_DEPENDENCIES = {
@@ -75,6 +76,7 @@ const REVIEW_GATE_CONTEXT_NOTE = [
75
76
  const GATE_CHECK_TIMEOUT_MS = 5_000;
76
77
  const GATE_EXEC_TIMEOUT_MS = 15 * 60 * 1_000;
77
78
  const GATE_LIVENESS_INTERVAL_MS = 30_000;
79
+ const AMBIENT_ACTIVITY_ATTRIBUTION = 'not attributable to this gate child';
78
80
  async function writeGateRunMarker(path, marker, warn) {
79
81
  try {
80
82
  await mkdir(join(tmpdir(), 'oat-gate-runs'), { recursive: true });
@@ -239,152 +241,6 @@ function corroborateGateInvocation(expected, actual, targetCorroboration) {
239
241
  },
240
242
  };
241
243
  }
242
- async function runChildProcess(command, args, options) {
243
- return new Promise((resolve, reject) => {
244
- let timedOut = false;
245
- let killTimeout = null;
246
- let stderrBytes = 0;
247
- let stdoutBytes = 0;
248
- let refusal;
249
- let stdoutLineBuffer = '';
250
- let stderrLineBuffer = '';
251
- let latestActivityEvidence;
252
- let latestActivityProbeStatus;
253
- let livenessProbePending = false;
254
- const startedAt = Date.now();
255
- let lastActivityAt = startedAt;
256
- const child = spawn(command, args, {
257
- cwd: options.cwd,
258
- env: options.env,
259
- stdio: options.stdio === 'pipe'
260
- ? [options.stdin, 'pipe', 'pipe']
261
- : options.stdio,
262
- });
263
- const recordActivity = () => {
264
- lastActivityAt = Date.now();
265
- };
266
- const scanChunk = (buffer, chunk) => {
267
- const combined = buffer + chunk.toString('utf8');
268
- const lines = combined.split('\n');
269
- const remainder = lines.pop() ?? '';
270
- if (!refusal) {
271
- for (const line of lines) {
272
- refusal = extractStructuredRefusal(line.replace(/\r$/, ''));
273
- if (refusal) {
274
- break;
275
- }
276
- }
277
- }
278
- return remainder;
279
- };
280
- child.stdout?.on('data', (chunk) => {
281
- stdoutBytes += chunk.byteLength;
282
- stdoutLineBuffer = scanChunk(stdoutLineBuffer, chunk);
283
- recordActivity();
284
- const destination = options.stdoutDestination === 'stderr'
285
- ? process.stderr
286
- : process.stdout;
287
- destination.write(chunk);
288
- });
289
- child.stderr?.on('data', (chunk) => {
290
- stderrBytes += chunk.byteLength;
291
- stderrLineBuffer = scanChunk(stderrLineBuffer, chunk);
292
- recordActivity();
293
- process.stderr.write(chunk);
294
- });
295
- const processAlive = () => {
296
- if (child.pid === undefined)
297
- return false;
298
- try {
299
- process.kill(child.pid, 0);
300
- return true;
301
- }
302
- catch {
303
- return false;
304
- }
305
- };
306
- const livenessInterval = options.onLiveness && options.livenessIntervalMs
307
- ? setInterval(() => {
308
- if (livenessProbePending)
309
- return;
310
- livenessProbePending = true;
311
- const now = Date.now();
312
- void (async () => {
313
- const activityProbeStatus = await options.activityProbe?.observe(now);
314
- const evidence = activityProbeStatus?.evidence;
315
- if (activityProbeStatus) {
316
- latestActivityProbeStatus = activityProbeStatus;
317
- }
318
- if (evidence)
319
- latestActivityEvidence = evidence;
320
- options.onLiveness?.({
321
- elapsedMs: now - startedAt,
322
- hardBudgetMs: options.timeoutMs,
323
- idleMs: now - lastActivityAt,
324
- processAlive: processAlive(),
325
- ...(latestActivityProbeStatus
326
- ? { activityProbeStatus: latestActivityProbeStatus }
327
- : {}),
328
- ...(latestActivityEvidence
329
- ? { lastActivityEvidence: latestActivityEvidence }
330
- : {}),
331
- });
332
- })().finally(() => {
333
- livenessProbePending = false;
334
- });
335
- }, options.livenessIntervalMs)
336
- : null;
337
- livenessInterval?.unref();
338
- const timeout = setTimeout(() => {
339
- timedOut = true;
340
- child.kill('SIGTERM');
341
- killTimeout = setTimeout(() => {
342
- child.kill('SIGKILL');
343
- }, 5_000);
344
- killTimeout.unref();
345
- }, options.timeoutMs);
346
- timeout.unref();
347
- child.on('error', (error) => {
348
- clearTimeout(timeout);
349
- if (livenessInterval) {
350
- clearInterval(livenessInterval);
351
- }
352
- if (killTimeout) {
353
- clearTimeout(killTimeout);
354
- }
355
- reject(error);
356
- });
357
- child.on('close', (code) => {
358
- clearTimeout(timeout);
359
- if (livenessInterval) {
360
- clearInterval(livenessInterval);
361
- }
362
- if (killTimeout) {
363
- clearTimeout(killTimeout);
364
- }
365
- refusal ??=
366
- extractStructuredRefusal(stdoutLineBuffer.replace(/\r$/, '')) ??
367
- extractStructuredRefusal(stderrLineBuffer.replace(/\r$/, ''));
368
- resolve({
369
- ...(latestActivityEvidence
370
- ? { activityEvidence: latestActivityEvidence }
371
- : {}),
372
- ...(latestActivityProbeStatus
373
- ? { activityProbeStatus: latestActivityProbeStatus }
374
- : {}),
375
- exitCode: timedOut ? 124 : (code ?? 1),
376
- ...(refusal ? { refusal } : {}),
377
- stderrBytes,
378
- stdoutBytes,
379
- ...(timedOut ? { timedOut: true } : {}),
380
- });
381
- });
382
- });
383
- }
384
- function extractStructuredRefusal(output) {
385
- const match = output.match(/^OAT_GATE_REFUSAL: (.*)$/m);
386
- return match?.[1]?.replace(/\r$/, '');
387
- }
388
244
  function isGateWriteLayer(value) {
389
245
  return VALID_WRITE_LAYERS.includes(value);
390
246
  }
@@ -1184,7 +1040,7 @@ async function executeTarget(selected, prompt, context, dependencies, timeout) {
1184
1040
  else {
1185
1041
  const activityDescription = lastActivityEvidence
1186
1042
  ? lastActivityEvidence.scope === 'ambient-runtime'
1187
- ? 'ambient runtime activity (not attributable to this gate child)'
1043
+ ? `ambient runtime activity (${AMBIENT_ACTIVITY_ATTRIBUTION})`
1188
1044
  : 'project-directory activity'
1189
1045
  : `${activityProbeStatus?.status ?? 'unavailable'} (${activityProbeStatus?.attemptedPath ?? 'no path'})`;
1190
1046
  context.logger.info(`Gate liveness: target=${selected.id} elapsed_ms=${elapsedMs} idle_ms=${idleMs} hard_budget_ms=${hardBudgetMs} process_alive=${processAlive} activity_evidence=${activityDescription}.`);
@@ -1606,6 +1462,25 @@ function writeReviewGateExecutionFailure(context, payload) {
1606
1462
  return;
1607
1463
  }
1608
1464
  context.logger.error(message);
1465
+ if (payload.activityEvidence && !payload.refusal) {
1466
+ context.logger.error(formatGateActivityEvidenceDiagnostic(payload.activityEvidence));
1467
+ }
1468
+ }
1469
+ function formatGateActivityEvidenceDiagnostic(evidence, now = Date.now()) {
1470
+ const transcriptScope = evidence.scope === 'ambient-runtime'
1471
+ ? `${evidence.runtime} ambient transcript`
1472
+ : `${evidence.runtime} project transcript`;
1473
+ const baselineState = evidence.changedSinceBaseline
1474
+ ? 'changed since baseline'
1475
+ : 'did not change since baseline';
1476
+ const observedAgoMs = Math.max(0, now - evidence.observedAt);
1477
+ const lastChangeTiming = evidence.lastChangeAt === null
1478
+ ? 'latest transcript change time unavailable'
1479
+ : `latest transcript change was ${Math.max(0, evidence.observedAt - evidence.lastChangeAt)}ms before observation`;
1480
+ const attributionWarning = evidence.scope === 'ambient-runtime'
1481
+ ? ` This activity is ${AMBIENT_ACTIVITY_ATTRIBUTION}.`
1482
+ : '';
1483
+ return `Activity evidence: ${transcriptScope} metadata ${baselineState}; observed ${observedAgoMs}ms ago; ${lastChangeTiming}.${attributionWarning}`;
1609
1484
  }
1610
1485
  function writeReviewGateUnexpectedFailure(context, payload) {
1611
1486
  const message = payload.error instanceof Error
@@ -2085,8 +1960,7 @@ async function runReviewGate(prompt, options, context, dependencies) {
2085
1960
  ...routeReceipt,
2086
1961
  })}\n`);
2087
1962
  const childExitCode = childResult.exitCode;
2088
- const refusal = childResult.refusal ??
2089
- extractStructuredRefusal(childResult.capturedOutput ?? '');
1963
+ const refusal = childResult.refusal;
2090
1964
  const writeRefusalFailure = () => {
2091
1965
  if (!refusal) {
2092
1966
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "private": false,
5
5
  "description": "Open Agent Toolkit CLI",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.0.0",
35
35
  "yaml": "2.8.2",
36
36
  "zod": "^3.25.76",
37
- "@open-agent-toolkit/control-plane": "0.2.23"
37
+ "@open-agent-toolkit/control-plane": "0.2.24"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",