voratiq 0.1.0-beta.24 → 0.1.0-beta.26

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 (58) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/runtime/harness.js +10 -1
  3. package/dist/bin.js +50 -6
  4. package/dist/cli/contract.d.ts +17 -21
  5. package/dist/cli/contract.js +33 -9
  6. package/dist/cli/list.d.ts +1 -0
  7. package/dist/cli/list.js +15 -12
  8. package/dist/commands/auto/command.d.ts +1 -1
  9. package/dist/commands/auto/command.js +39 -8
  10. package/dist/commands/list/command.d.ts +1 -0
  11. package/dist/commands/list/command.js +79 -13
  12. package/dist/commands/list/normalization.d.ts +2 -1
  13. package/dist/commands/reduce/targets.js +7 -9
  14. package/dist/commands/run/command.js +8 -2
  15. package/dist/commands/run/spec-path.d.ts +10 -0
  16. package/dist/commands/run/spec-path.js +20 -0
  17. package/dist/commands/verify/command.js +6 -6
  18. package/dist/configs/agents/defaults.js +21 -13
  19. package/dist/contracts/list.d.ts +160 -12
  20. package/dist/contracts/list.js +95 -6
  21. package/dist/domain/interactive/prompt.d.ts +1 -1
  22. package/dist/domain/interactive/prompt.js +1 -1
  23. package/dist/domain/message/model/types.d.ts +4 -0
  24. package/dist/domain/reduce/competition/adapter.js +3 -1
  25. package/dist/domain/reduce/model/types.d.ts +4 -0
  26. package/dist/domain/run/competition/agents/artifacts.d.ts +1 -0
  27. package/dist/domain/run/competition/agents/artifacts.js +56 -42
  28. package/dist/domain/run/competition/agents/run-context.d.ts +1 -0
  29. package/dist/domain/run/competition/agents/run-context.js +8 -1
  30. package/dist/domain/run/model/types.d.ts +14 -1
  31. package/dist/domain/run/model/types.js +3 -0
  32. package/dist/domain/spec/model/types.d.ts +4 -0
  33. package/dist/domain/verify/model/mutators.js +1 -0
  34. package/dist/domain/verify/model/types.d.ts +4 -0
  35. package/dist/interactive/providers/launch.js +6 -2
  36. package/dist/mcp/server.js +139 -63
  37. package/dist/render/transcripts/auto.d.ts +1 -1
  38. package/dist/render/transcripts/auto.js +6 -2
  39. package/dist/render/transcripts/interactive.d.ts +1 -0
  40. package/dist/render/transcripts/interactive.js +7 -1
  41. package/dist/render/transcripts/message.d.ts +1 -0
  42. package/dist/render/transcripts/message.js +5 -2
  43. package/dist/render/transcripts/reduce.d.ts +1 -0
  44. package/dist/render/transcripts/reduce.js +5 -2
  45. package/dist/render/transcripts/run.d.ts +1 -0
  46. package/dist/render/transcripts/run.js +2 -1
  47. package/dist/render/transcripts/spec.d.ts +1 -0
  48. package/dist/render/transcripts/spec.js +5 -2
  49. package/dist/render/transcripts/verify.d.ts +1 -0
  50. package/dist/render/transcripts/verify.js +5 -2
  51. package/dist/workspace/chat/usage-extractor.d.ts +2 -2
  52. package/dist/workspace/chat/usage-extractor.js +85 -103
  53. package/dist/workspace/chat/usage-mappings.d.ts +1 -0
  54. package/dist/workspace/chat/usage-mappings.js +20 -10
  55. package/dist/workspace/dependencies.js +80 -31
  56. package/dist/workspace/run.d.ts +9 -0
  57. package/dist/workspace/run.js +28 -2
  58. package/package.json +1 -1
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install -g voratiq
15
15
 
16
16
  - Node 20+
17
17
  - git
18
- - 1+ AI coding agent (Claude [>=2.1.111](https://github.com/anthropics/claude-code?tab=readme-ov-file#get-started), Codex [>=0.122.0](https://github.com/openai/codex?tab=readme-ov-file#quickstart), or Gemini [>=0.31.0](https://github.com/google-gemini/gemini-cli?tab=readme-ov-file#quick-install))
18
+ - 1+ AI coding agent (Claude [>=2.1.111](https://github.com/anthropics/claude-code?tab=readme-ov-file#get-started), Codex [>=0.122.0](https://github.com/openai/codex?tab=readme-ov-file#quickstart), or Gemini [>=0.40.0](https://github.com/google-gemini/gemini-cli?tab=readme-ov-file#quick-install))
19
19
  - macOS: `ripgrep`
20
20
  - Linux (Debian/Ubuntu): `bubblewrap`, `socat`, `ripgrep`
21
21
 
@@ -42,7 +42,7 @@ export async function runSandboxedAgent(input) {
42
42
  runtimeManifestPath: paths.runtimeManifestPath,
43
43
  promptPath,
44
44
  workspacePath: paths.workspacePath,
45
- env: staged.env,
45
+ env: applyProviderRunEnvironmentOverrides(providerId, staged.env),
46
46
  environment,
47
47
  });
48
48
  const denialBackoff = resolveDenialBackoff({
@@ -111,6 +111,15 @@ export async function runSandboxedAgent(input) {
111
111
  }
112
112
  }
113
113
  }
114
+ function applyProviderRunEnvironmentOverrides(providerId, env) {
115
+ if (providerId !== "gemini") {
116
+ return env;
117
+ }
118
+ return {
119
+ ...env,
120
+ GEMINI_CLI_TRUST_WORKSPACE: "true",
121
+ };
122
+ }
114
123
  function resolveDenialBackoff(options) {
115
124
  if (options.override) {
116
125
  return options.override;
package/dist/bin.js CHANGED
@@ -8,24 +8,68 @@ const SIGNAL_EXIT_CODES = {
8
8
  SIGINT: 130,
9
9
  SIGTERM: 143,
10
10
  };
11
+ const PROCESS_GUARD_SIGNALS = ["SIGHUP", "SIGINT", "SIGTERM"];
11
12
  let activeJsonEnvelopeOperator;
12
13
  let processGuardsInstalled = false;
14
+ let activeShutdownState;
13
15
  function installProcessGuards() {
14
16
  if (processGuardsInstalled) {
15
17
  return;
16
18
  }
17
19
  processGuardsInstalled = true;
18
- for (const signal of ["SIGHUP", "SIGINT", "SIGTERM"]) {
19
- process.once(signal, () => {
20
- void handleSignal(signal);
21
- });
20
+ for (const signal of PROCESS_GUARD_SIGNALS) {
21
+ installSignalGuard(signal);
22
22
  }
23
23
  process.on("uncaughtException", (error) => {
24
- void handleFatalError("uncaught exception", error);
24
+ void beginFatalShutdown("uncaught exception", error);
25
25
  });
26
26
  process.on("unhandledRejection", (reason) => {
27
- void handleFatalError("unhandled rejection", reason);
27
+ void beginFatalShutdown("unhandled rejection", reason);
28
+ });
29
+ }
30
+ function installSignalGuard(signal) {
31
+ const handler = () => {
32
+ // Re-arm the listener before awaiting teardown so repeated interrupts stay
33
+ // inside the coordinated abort path instead of falling through to the
34
+ // process default signal exit.
35
+ process.once(signal, handler);
36
+ void beginSignalShutdown(signal);
37
+ };
38
+ process.once(signal, handler);
39
+ }
40
+ async function beginFatalShutdown(context, error) {
41
+ if (activeShutdownState) {
42
+ if (activeShutdownState.kind === "signal") {
43
+ return;
44
+ }
45
+ await activeShutdownState.promise;
46
+ return;
47
+ }
48
+ const promise = handleFatalError(context, error).finally(() => {
49
+ if (activeShutdownState?.promise === promise) {
50
+ activeShutdownState = undefined;
51
+ }
52
+ });
53
+ activeShutdownState = { kind: "fatal", promise };
54
+ await promise;
55
+ }
56
+ async function beginSignalShutdown(signal) {
57
+ if (activeShutdownState) {
58
+ if (activeShutdownState.kind === "signal") {
59
+ process.exitCode = activeShutdownState.exitCode;
60
+ await activeShutdownState.promise;
61
+ }
62
+ return;
63
+ }
64
+ const exitCode = SIGNAL_EXIT_CODES[signal] ?? 1;
65
+ process.exitCode = exitCode;
66
+ const promise = handleSignal(signal).finally(() => {
67
+ if (activeShutdownState?.promise === promise) {
68
+ activeShutdownState = undefined;
69
+ }
28
70
  });
71
+ activeShutdownState = { kind: "signal", exitCode, promise };
72
+ await promise;
29
73
  }
30
74
  async function handleFatalError(context, error) {
31
75
  await terminateActiveSessionsSafe("failed", context);
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  import { type ListMode, type ListOperator } from "../contracts/list.js";
4
4
  export declare const externalExecutionOperators: readonly ["spec", "run", "reduce", "verify", "message", "apply"];
5
5
  export declare const externalInspectionOperators: readonly ["spec", "run", "reduce", "verify", "message", "interactive"];
6
- export declare const externalInspectionModes: readonly ["table", "detail"];
6
+ export declare const externalInspectionModes: readonly ["summary", "detail"];
7
7
  export type ExternalExecutionOperator = (typeof externalExecutionOperators)[number];
8
8
  export type ExternalInspectionOperator = ListOperator;
9
9
  export type ExternalInspectionMode = ListMode;
@@ -25,7 +25,7 @@ export declare const externalInspectionOperatorSchema: z.ZodEnum<{
25
25
  }>;
26
26
  export declare const externalInspectionModeSchema: z.ZodEnum<{
27
27
  detail: "detail";
28
- table: "table";
28
+ summary: "summary";
29
29
  }>;
30
30
  export declare const externalSpecExecutionInputSchema: z.ZodObject<{
31
31
  description: z.ZodString;
@@ -87,7 +87,7 @@ export declare const externalApplyExecutionInputSchema: z.ZodObject<{
87
87
  ignoreBaseMismatch: z.ZodOptional<z.ZodBoolean>;
88
88
  commit: z.ZodOptional<z.ZodBoolean>;
89
89
  }, z.core.$strict>;
90
- export declare const externalListTableInputSchema: z.ZodObject<{
90
+ export declare const externalListSummaryInputSchema: z.ZodObject<{
91
91
  operator: z.ZodEnum<{
92
92
  message: "message";
93
93
  spec: "spec";
@@ -96,9 +96,9 @@ export declare const externalListTableInputSchema: z.ZodObject<{
96
96
  verify: "verify";
97
97
  interactive: "interactive";
98
98
  }>;
99
- verbose: z.ZodOptional<z.ZodBoolean>;
99
+ mode: z.ZodLiteral<"summary">;
100
+ allStatuses: z.ZodOptional<z.ZodBoolean>;
100
101
  limit: z.ZodOptional<z.ZodNumber>;
101
- mode: z.ZodLiteral<"table">;
102
102
  }, z.core.$strict>;
103
103
  export declare const externalListDetailInputSchema: z.ZodObject<{
104
104
  operator: z.ZodEnum<{
@@ -109,10 +109,9 @@ export declare const externalListDetailInputSchema: z.ZodObject<{
109
109
  verify: "verify";
110
110
  interactive: "interactive";
111
111
  }>;
112
- verbose: z.ZodOptional<z.ZodBoolean>;
113
- limit: z.ZodOptional<z.ZodNumber>;
114
112
  mode: z.ZodLiteral<"detail">;
115
113
  sessionId: z.ZodString;
114
+ verbose: z.ZodOptional<z.ZodBoolean>;
116
115
  }, z.core.$strict>;
117
116
  export declare const externalListInspectionInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
118
117
  operator: z.ZodEnum<{
@@ -123,9 +122,9 @@ export declare const externalListInspectionInputSchema: z.ZodDiscriminatedUnion<
123
122
  verify: "verify";
124
123
  interactive: "interactive";
125
124
  }>;
126
- verbose: z.ZodOptional<z.ZodBoolean>;
125
+ mode: z.ZodLiteral<"summary">;
126
+ allStatuses: z.ZodOptional<z.ZodBoolean>;
127
127
  limit: z.ZodOptional<z.ZodNumber>;
128
- mode: z.ZodLiteral<"table">;
129
128
  }, z.core.$strict>, z.ZodObject<{
130
129
  operator: z.ZodEnum<{
131
130
  message: "message";
@@ -135,10 +134,9 @@ export declare const externalListInspectionInputSchema: z.ZodDiscriminatedUnion<
135
134
  verify: "verify";
136
135
  interactive: "interactive";
137
136
  }>;
138
- verbose: z.ZodOptional<z.ZodBoolean>;
139
- limit: z.ZodOptional<z.ZodNumber>;
140
137
  mode: z.ZodLiteral<"detail">;
141
138
  sessionId: z.ZodString;
139
+ verbose: z.ZodOptional<z.ZodBoolean>;
142
140
  }, z.core.$strict>], "mode">;
143
141
  export declare const externalExecutionInputSchemas: {
144
142
  readonly spec: z.ZodObject<{
@@ -204,7 +202,7 @@ export declare const externalExecutionInputSchemas: {
204
202
  };
205
203
  export declare const externalInspectionInputSchemas: {
206
204
  readonly list: {
207
- readonly table: z.ZodObject<{
205
+ readonly summary: z.ZodObject<{
208
206
  operator: z.ZodEnum<{
209
207
  message: "message";
210
208
  spec: "spec";
@@ -213,9 +211,9 @@ export declare const externalInspectionInputSchemas: {
213
211
  verify: "verify";
214
212
  interactive: "interactive";
215
213
  }>;
216
- verbose: z.ZodOptional<z.ZodBoolean>;
214
+ mode: z.ZodLiteral<"summary">;
215
+ allStatuses: z.ZodOptional<z.ZodBoolean>;
217
216
  limit: z.ZodOptional<z.ZodNumber>;
218
- mode: z.ZodLiteral<"table">;
219
217
  }, z.core.$strict>;
220
218
  readonly detail: z.ZodObject<{
221
219
  operator: z.ZodEnum<{
@@ -226,10 +224,9 @@ export declare const externalInspectionInputSchemas: {
226
224
  verify: "verify";
227
225
  interactive: "interactive";
228
226
  }>;
229
- verbose: z.ZodOptional<z.ZodBoolean>;
230
- limit: z.ZodOptional<z.ZodNumber>;
231
227
  mode: z.ZodLiteral<"detail">;
232
228
  sessionId: z.ZodString;
229
+ verbose: z.ZodOptional<z.ZodBoolean>;
233
230
  }, z.core.$strict>;
234
231
  readonly union: z.ZodDiscriminatedUnion<[z.ZodObject<{
235
232
  operator: z.ZodEnum<{
@@ -240,9 +237,9 @@ export declare const externalInspectionInputSchemas: {
240
237
  verify: "verify";
241
238
  interactive: "interactive";
242
239
  }>;
243
- verbose: z.ZodOptional<z.ZodBoolean>;
240
+ mode: z.ZodLiteral<"summary">;
241
+ allStatuses: z.ZodOptional<z.ZodBoolean>;
244
242
  limit: z.ZodOptional<z.ZodNumber>;
245
- mode: z.ZodLiteral<"table">;
246
243
  }, z.core.$strict>, z.ZodObject<{
247
244
  operator: z.ZodEnum<{
248
245
  message: "message";
@@ -252,10 +249,9 @@ export declare const externalInspectionInputSchemas: {
252
249
  verify: "verify";
253
250
  interactive: "interactive";
254
251
  }>;
255
- verbose: z.ZodOptional<z.ZodBoolean>;
256
- limit: z.ZodOptional<z.ZodNumber>;
257
252
  mode: z.ZodLiteral<"detail">;
258
253
  sessionId: z.ZodString;
254
+ verbose: z.ZodOptional<z.ZodBoolean>;
259
255
  }, z.core.$strict>], "mode">;
260
256
  };
261
257
  };
@@ -279,7 +275,7 @@ export declare const externalAdapterContractReference: {
279
275
  readonly command: "list";
280
276
  readonly jsonOnly: true;
281
277
  readonly operators: readonly ["spec", "run", "reduce", "verify", "message", "interactive"];
282
- readonly modes: readonly ["table", "detail"];
278
+ readonly modes: readonly ["summary", "detail"];
283
279
  readonly authoritativeType: "ListJsonOutput";
284
280
  readonly versioned: false;
285
281
  };
@@ -90,19 +90,20 @@ export const externalApplyExecutionInputSchema = z
90
90
  const externalListInspectionBaseSchema = z
91
91
  .object({
92
92
  operator: externalInspectionOperatorSchema,
93
- verbose: z.boolean().optional(),
94
- limit: positiveIntegerSchema.optional(),
95
93
  })
96
94
  .strict();
97
- export const externalListTableInputSchema = externalListInspectionBaseSchema.extend({
98
- mode: z.literal("table"),
95
+ export const externalListSummaryInputSchema = externalListInspectionBaseSchema.extend({
96
+ mode: z.literal("summary"),
97
+ allStatuses: z.boolean().optional(),
98
+ limit: positiveIntegerSchema.optional(),
99
99
  });
100
100
  export const externalListDetailInputSchema = externalListInspectionBaseSchema.extend({
101
101
  mode: z.literal("detail"),
102
102
  sessionId: nonEmptyStringSchema,
103
+ verbose: z.boolean().optional(),
103
104
  });
104
105
  export const externalListInspectionInputSchema = z.discriminatedUnion("mode", [
105
- externalListTableInputSchema,
106
+ externalListSummaryInputSchema,
106
107
  externalListDetailInputSchema,
107
108
  ]);
108
109
  export const externalExecutionInputSchemas = {
@@ -115,7 +116,7 @@ export const externalExecutionInputSchemas = {
115
116
  };
116
117
  export const externalInspectionInputSchemas = {
117
118
  list: {
118
- table: externalListTableInputSchema,
119
+ summary: externalListSummaryInputSchema,
119
120
  detail: externalListDetailInputSchema,
120
121
  union: externalListInspectionInputSchema,
121
122
  },
@@ -234,6 +235,7 @@ const listCommandActionOptionsSchema = z
234
235
  message: z.union([z.literal(true), nonEmptyStringSchema]).optional(),
235
236
  interactive: z.union([z.literal(true), nonEmptyStringSchema]).optional(),
236
237
  limit: positiveIntegerSchema.optional(),
238
+ allStatuses: z.boolean().optional(),
237
239
  verbose: z.boolean().optional(),
238
240
  json: z.boolean().optional(),
239
241
  })
@@ -328,12 +330,34 @@ export function parseListInspectionCommandOptions(options, command) {
328
330
  { key: "message", flag: "--message", value: "message" },
329
331
  { key: "interactive", flag: "--interactive", value: "interactive" },
330
332
  ], parsed, command, "operator flag");
333
+ const mode = selected.argument ? "detail" : "summary";
334
+ const verbose = normalizeOptionalBoolean(parsed.verbose);
335
+ const allStatuses = normalizeOptionalBoolean(parsed.allStatuses);
336
+ const json = normalizeOptionalBoolean(parsed.json);
337
+ if (verbose && json) {
338
+ failCommand(command, "`--verbose` cannot be used with JSON output.");
339
+ }
340
+ if (mode === "summary" && verbose) {
341
+ failCommand(command, "`--verbose` requires detail scope.");
342
+ }
343
+ if (mode === "detail" && allStatuses) {
344
+ failCommand(command, "`--all-statuses` applies only to summary scope.");
345
+ }
346
+ if (mode === "detail" && parsed.limit !== undefined) {
347
+ failCommand(command, "`--limit` applies only to summary scope.");
348
+ }
331
349
  return parseCommandOptions(externalListInspectionInputSchema, {
332
350
  operator: selected.value,
333
- mode: selected.argument ? "detail" : "table",
351
+ mode,
334
352
  ...(selected.argument ? { sessionId: selected.argument } : {}),
335
- limit: parsed.limit,
336
- verbose: normalizeOptionalBoolean(parsed.verbose),
353
+ ...(mode === "summary"
354
+ ? {
355
+ limit: parsed.limit,
356
+ allStatuses,
357
+ }
358
+ : {
359
+ verbose,
360
+ }),
337
361
  }, command);
338
362
  }
339
363
  function parseCommandOptions(schema, input, command) {
@@ -5,6 +5,7 @@ export interface ListCommandOptions {
5
5
  operator: ListOperator;
6
6
  sessionId?: string;
7
7
  limit?: number;
8
+ allStatuses?: boolean;
8
9
  verbose?: boolean;
9
10
  }
10
11
  export interface ListCommandResult {
package/dist/cli/list.js CHANGED
@@ -25,10 +25,11 @@ export async function runListCommand(options) {
25
25
  operator: options.operator,
26
26
  sessionId: options.sessionId,
27
27
  limit: options.limit,
28
+ allStatuses: options.allStatuses,
28
29
  verbose: options.verbose,
29
30
  });
30
31
  const body = execution.output ??
31
- (execution.mode === "table"
32
+ (execution.mode === "summary"
32
33
  ? `No ${options.operator} sessions recorded.`
33
34
  : `${options.operator} session \`${options.sessionId}\` not found.`);
34
35
  const alerts = execution.warnings.map((warning) => ({
@@ -42,15 +43,16 @@ function parseLimitOption(value) {
42
43
  }
43
44
  export function createListCommand() {
44
45
  return new Command("list")
45
- .description("List recorded sessions for an operator")
46
- .option("--spec [session-id]", "List spec sessions or show one spec session")
47
- .option("--run [session-id]", "List run sessions or show one run session")
48
- .option("--reduce [session-id]", "List reduction sessions or show one reduction session")
49
- .option("--verify [session-id]", "List verification sessions or show one verification session")
50
- .option("--message [session-id]", "List message sessions or show one message session")
51
- .option("--interactive [session-id]", "List interactive sessions or show one interactive session")
52
- .option("--limit <count>", "Show only the N most recent sessions (default: 10)", parseLimitOption)
53
- .option("--verbose", "Show all statuses for the selected operator in table mode")
46
+ .description("Inspect recorded sessions for an operator in summary or detail scope")
47
+ .option("--spec [session-id]", "Inspect spec sessions in summary scope or one spec session in detail scope")
48
+ .option("--run [session-id]", "Inspect run sessions in summary scope or one run session in detail scope")
49
+ .option("--reduce [session-id]", "Inspect reduction sessions in summary scope or one reduction session in detail scope")
50
+ .option("--verify [session-id]", "Inspect verification sessions in summary scope or one verification session in detail scope")
51
+ .option("--message [session-id]", "Inspect message sessions in summary scope or one message session in detail scope")
52
+ .option("--interactive [session-id]", "Inspect interactive sessions in summary scope or one interactive session in detail scope")
53
+ .option("--limit <count>", "Show only the N most recent summary sessions (default: 10)", parseLimitOption)
54
+ .option("--all-statuses", "Include sessions normally hidden by the default summary filter")
55
+ .option("--verbose", "Show expanded human detail output (requires detail scope)")
54
56
  .option("--json", "Emit machine-readable list output")
55
57
  .allowExcessArguments(false)
56
58
  .action(async (options, command) => {
@@ -58,8 +60,9 @@ export function createListCommand() {
58
60
  const result = await runListCommand({
59
61
  operator: selection.operator,
60
62
  sessionId: selection.mode === "detail" ? selection.sessionId : undefined,
61
- limit: selection.limit,
62
- verbose: selection.verbose ?? false,
63
+ limit: selection.mode === "summary" ? selection.limit : undefined,
64
+ allStatuses: selection.mode === "summary" ? selection.allStatuses : undefined,
65
+ verbose: selection.mode === "detail" ? (selection.verbose ?? false) : false,
63
66
  });
64
67
  if (options.json) {
65
68
  writeCommandOutput({
@@ -98,7 +98,7 @@ export type AutoCommandEvent = {
98
98
  separateWithDivider: boolean;
99
99
  };
100
100
  export interface AutoPhaseSummary {
101
- status: "succeeded" | "failed" | "skipped";
101
+ status: "succeeded" | "failed" | "aborted" | "skipped";
102
102
  durationMs?: number;
103
103
  detail?: string;
104
104
  }
@@ -19,6 +19,7 @@ export async function executeAutoCommand(options, dependencies) {
19
19
  dependencies.onEvent?.(event);
20
20
  };
21
21
  let hardFailure = false;
22
+ let hardAbort = false;
22
23
  let actionRequired = false;
23
24
  let actionRequiredDetail;
24
25
  let specStartedAt;
@@ -74,7 +75,7 @@ export async function executeAutoCommand(options, dependencies) {
74
75
  recordEvent({ kind: "error", error });
75
76
  }
76
77
  }
77
- if (!hardFailure && !actionRequired && hasDescription) {
78
+ if (!hardFailure && !hardAbort && !actionRequired && hasDescription) {
78
79
  if (!specSessionId) {
79
80
  specStatus = "failed";
80
81
  specDetail = "Spec stage did not return a session id.";
@@ -138,12 +139,16 @@ export async function executeAutoCommand(options, dependencies) {
138
139
  }
139
140
  }
140
141
  }
141
- if (!resolvedSpecPath && !hardFailure && !actionRequired && hasDescription) {
142
+ if (!resolvedSpecPath &&
143
+ !hardFailure &&
144
+ !hardAbort &&
145
+ !actionRequired &&
146
+ hasDescription) {
142
147
  specStatus = "failed";
143
148
  specDetail = "Spec verification did not select a spec path.";
144
149
  hardFailure = true;
145
150
  }
146
- if (!hardFailure && !actionRequired && resolvedSpecPath) {
151
+ if (!hardFailure && !hardAbort && !actionRequired && resolvedSpecPath) {
147
152
  runStartedAt = now();
148
153
  try {
149
154
  const runResult = await dependencies.runRunStage({
@@ -168,20 +173,30 @@ export async function executeAutoCommand(options, dependencies) {
168
173
  hintLines: ["Re-run the command."],
169
174
  });
170
175
  }
171
- runStatus = resolvedRunExitCode === 0 ? "succeeded" : "failed";
176
+ runStatus =
177
+ resolvedRunExitCode === 0
178
+ ? "succeeded"
179
+ : runResult.report.status === "aborted"
180
+ ? "aborted"
181
+ : "failed";
172
182
  runId = runResult.report.runId;
173
183
  runRecordStatus = runResult.report.status;
174
184
  runCreatedAt = runResult.report.createdAt;
175
185
  runSpecPath = runResult.report.spec?.path;
176
186
  runBaseRevisionSha = runResult.report.baseRevisionSha;
177
- if (runStatus === "failed") {
187
+ if (runStatus !== "succeeded") {
178
188
  const statusDetail = runRecordStatus
179
189
  ? `status \`${runRecordStatus}\``
180
190
  : "a non-success status";
181
191
  runDetail =
182
192
  runDetail ??
183
193
  `Run completed with ${statusDetail} (exit code ${resolvedRunExitCode}).`;
184
- hardFailure = true;
194
+ if (runStatus === "aborted") {
195
+ hardAbort = true;
196
+ }
197
+ else {
198
+ hardFailure = true;
199
+ }
185
200
  }
186
201
  recordEvent({
187
202
  kind: "body",
@@ -197,7 +212,10 @@ export async function executeAutoCommand(options, dependencies) {
197
212
  }
198
213
  }
199
214
  const shouldAttemptVerifyRun = runId !== undefined &&
200
- (!hardFailure || (!hasDescription && runStatus !== "skipped"));
215
+ runStatus === "succeeded" &&
216
+ !hardFailure &&
217
+ !hardAbort &&
218
+ !actionRequired;
201
219
  if (shouldAttemptVerifyRun && runId) {
202
220
  verifyStartedAt = now();
203
221
  try {
@@ -321,6 +339,7 @@ export async function executeAutoCommand(options, dependencies) {
321
339
  const applyDurationMs = applyStartedAt !== undefined ? now() - applyStartedAt : undefined;
322
340
  const autoStatus = resolveAutoTerminalStatus({
323
341
  hardFailure,
342
+ hardAbort,
324
343
  actionRequired,
325
344
  });
326
345
  const autoDetail = resolveAutoTerminalDetail({
@@ -391,6 +410,9 @@ function assertAutoOptionCompatibility(options) {
391
410
  validateAutoCommandOptions(options);
392
411
  }
393
412
  function resolveAutoTerminalStatus(options) {
413
+ if (options.hardAbort) {
414
+ return "aborted";
415
+ }
394
416
  if (options.hardFailure) {
395
417
  return "failed";
396
418
  }
@@ -400,7 +422,13 @@ function resolveAutoTerminalStatus(options) {
400
422
  return "succeeded";
401
423
  }
402
424
  function mapAutoTerminalStatusToExitCode(status) {
403
- return status === "succeeded" ? 0 : 1;
425
+ if (status === "succeeded") {
426
+ return 0;
427
+ }
428
+ if (status === "aborted") {
429
+ return 3;
430
+ }
431
+ return 1;
404
432
  }
405
433
  function truncateOutcomeDetail(detail) {
406
434
  if (!detail) {
@@ -422,6 +450,9 @@ function resolveAutoTerminalDetail(options) {
422
450
  options.runDetail ??
423
451
  options.specDetail);
424
452
  }
453
+ if (options.status === "aborted") {
454
+ return truncateOutcomeDetail(options.runDetail ?? options.verifyDetail);
455
+ }
425
456
  return undefined;
426
457
  }
427
458
  function toHeadline(error) {
@@ -10,6 +10,7 @@ export interface ListCommandInput {
10
10
  operator: ListOperator;
11
11
  sessionId?: string;
12
12
  limit?: number;
13
+ allStatuses?: boolean;
13
14
  verbose?: boolean;
14
15
  }
15
16
  export interface ListCommandResult {