voratiq 0.1.0-beta.21 → 0.1.0-beta.23

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 (222) hide show
  1. package/README.md +19 -23
  2. package/dist/agents/launch/chat.d.ts +3 -1
  3. package/dist/agents/launch/chat.js +2 -0
  4. package/dist/agents/runtime/policy.js +2 -1
  5. package/dist/auth/providers/utils.js +1 -1
  6. package/dist/bin.js +28 -7
  7. package/dist/cli/auto.js +4 -16
  8. package/dist/cli/contract.d.ts +26 -17
  9. package/dist/cli/contract.js +3 -1
  10. package/dist/cli/doctor.d.ts +12 -0
  11. package/dist/cli/doctor.js +115 -0
  12. package/dist/cli/list.js +5 -1
  13. package/dist/cli/message.js +16 -11
  14. package/dist/cli/operator-envelope.d.ts +27 -7
  15. package/dist/cli/operator-envelope.js +95 -3
  16. package/dist/cli/option-parsers.d.ts +2 -0
  17. package/dist/cli/option-parsers.js +7 -0
  18. package/dist/cli/output.d.ts +1 -5
  19. package/dist/cli/reduce.js +5 -13
  20. package/dist/cli/run.js +5 -12
  21. package/dist/cli/spec.js +4 -10
  22. package/dist/cli/verify.d.ts +1 -1
  23. package/dist/cli/verify.js +51 -22
  24. package/dist/commands/auto/command.d.ts +1 -0
  25. package/dist/commands/auto/command.js +22 -15
  26. package/dist/commands/auto/errors.js +1 -1
  27. package/dist/commands/auto/validation.js +3 -1
  28. package/dist/commands/doctor/agents.d.ts +5 -0
  29. package/dist/commands/{init → doctor}/agents.js +40 -20
  30. package/dist/commands/doctor/command.d.ts +22 -0
  31. package/dist/commands/doctor/command.js +100 -0
  32. package/dist/commands/doctor/environment.d.ts +2 -0
  33. package/dist/commands/{init → doctor}/environment.js +41 -7
  34. package/dist/commands/{init/types.d.ts → doctor/fix-types.d.ts} +30 -9
  35. package/dist/commands/doctor/fix.d.ts +2 -0
  36. package/dist/commands/{init/command.js → doctor/fix.js} +109 -11
  37. package/dist/commands/doctor/reconcile.d.ts +2 -0
  38. package/dist/commands/doctor/reconcile.js +103 -0
  39. package/dist/commands/interactive/lifecycle.d.ts +2 -0
  40. package/dist/commands/interactive/lifecycle.js +16 -0
  41. package/dist/commands/list/command.d.ts +1 -0
  42. package/dist/commands/list/command.js +241 -361
  43. package/dist/commands/list/normalization.d.ts +51 -0
  44. package/dist/commands/list/normalization.js +309 -0
  45. package/dist/commands/list/records.d.ts +9 -0
  46. package/dist/commands/list/records.js +6 -0
  47. package/dist/commands/message/command.d.ts +2 -2
  48. package/dist/commands/message/command.js +29 -16
  49. package/dist/commands/message/errors.d.ts +12 -3
  50. package/dist/commands/message/errors.js +19 -3
  51. package/dist/commands/prune/command.js +4 -1
  52. package/dist/commands/reduce/command.js +16 -17
  53. package/dist/commands/reduce/errors.d.ts +2 -2
  54. package/dist/commands/reduce/errors.js +3 -3
  55. package/dist/commands/reduce/targets.js +12 -3
  56. package/dist/commands/root-launcher/command.js +12 -6
  57. package/dist/commands/run/command.d.ts +1 -0
  58. package/dist/commands/run/command.js +4 -1
  59. package/dist/commands/run/record-init.d.ts +2 -0
  60. package/dist/commands/run/record-init.js +8 -1
  61. package/dist/commands/run/spec-provenance.d.ts +37 -0
  62. package/dist/commands/run/spec-provenance.js +384 -0
  63. package/dist/commands/run/validation.d.ts +4 -0
  64. package/dist/commands/run/validation.js +25 -62
  65. package/dist/commands/shared/resolve-stage-competitors.js +2 -1
  66. package/dist/commands/spec/command.js +64 -138
  67. package/dist/commands/spec/errors.d.ts +5 -0
  68. package/dist/commands/spec/errors.js +9 -0
  69. package/dist/commands/verify/agents.d.ts +4 -2
  70. package/dist/commands/verify/agents.js +4 -11
  71. package/dist/commands/verify/command.js +23 -6
  72. package/dist/commands/verify/errors.d.ts +12 -0
  73. package/dist/commands/verify/errors.js +22 -0
  74. package/dist/commands/verify/lifecycle.js +1 -1
  75. package/dist/commands/verify/targets.js +108 -12
  76. package/dist/competition/shared/preflight.d.ts +1 -1
  77. package/dist/competition/shared/preflight.js +15 -2
  78. package/dist/competition/shared/teardown.d.ts +7 -0
  79. package/dist/competition/shared/teardown.js +6 -0
  80. package/dist/configs/agents/defaults.js +13 -44
  81. package/dist/configs/agents/loader.js +1 -1
  82. package/dist/configs/environment/loader.js +2 -1
  83. package/dist/configs/orchestration/loader.js +2 -1
  84. package/dist/configs/sandbox/loader.js +2 -1
  85. package/dist/configs/settings/loader.js +1 -1
  86. package/dist/configs/verification/loader.js +2 -1
  87. package/dist/contracts/list.d.ts +129 -149
  88. package/dist/contracts/list.js +47 -99
  89. package/dist/domain/interactive/model/types.d.ts +2 -0
  90. package/dist/domain/interactive/model/types.js +16 -1
  91. package/dist/domain/interactive/persistence/adapter.d.ts +23 -0
  92. package/dist/domain/interactive/persistence/adapter.js +67 -5
  93. package/dist/domain/interactive/prompt.d.ts +1 -1
  94. package/dist/domain/interactive/prompt.js +1 -1
  95. package/dist/domain/interactive/session-env.d.ts +10 -0
  96. package/dist/domain/interactive/session-env.js +25 -0
  97. package/dist/domain/message/competition/adapter.js +3 -9
  98. package/dist/domain/message/model/types.d.ts +32 -1
  99. package/dist/domain/message/model/types.js +25 -1
  100. package/dist/domain/reduce/competition/adapter.js +30 -16
  101. package/dist/domain/reduce/competition/finalize.d.ts +7 -0
  102. package/dist/domain/reduce/competition/finalize.js +19 -0
  103. package/dist/domain/reduce/model/types.d.ts +3 -3
  104. package/dist/domain/run/competition/agents/artifacts.js +4 -2
  105. package/dist/domain/run/competition/agents/lifecycle.js +1 -1
  106. package/dist/domain/run/competition/agents/workspace.js +2 -1
  107. package/dist/domain/run/competition/errors.d.ts +1 -1
  108. package/dist/domain/run/competition/errors.js +4 -7
  109. package/dist/domain/run/competition/reports.js +2 -1
  110. package/dist/domain/run/model/enhanced.d.ts +1 -1
  111. package/dist/domain/run/model/enhanced.js +2 -1
  112. package/dist/domain/run/model/types.d.ts +384 -0
  113. package/dist/domain/run/model/types.js +87 -0
  114. package/dist/domain/spec/competition/adapter.d.ts +1 -0
  115. package/dist/domain/spec/competition/adapter.js +9 -10
  116. package/dist/domain/spec/model/mutators.d.ts +20 -0
  117. package/dist/domain/spec/model/mutators.js +146 -0
  118. package/dist/domain/spec/model/types.d.ts +3 -0
  119. package/dist/domain/spec/model/types.js +5 -0
  120. package/dist/domain/spec/persistence/adapter.d.ts +1 -0
  121. package/dist/domain/spec/persistence/adapter.js +7 -2
  122. package/dist/domain/verify/competition/adapter.d.ts +1 -1
  123. package/dist/domain/verify/competition/adapter.js +4 -9
  124. package/dist/domain/verify/competition/finalize.d.ts +9 -0
  125. package/dist/domain/verify/competition/finalize.js +22 -3
  126. package/dist/domain/verify/competition/programmatic.js +2 -1
  127. package/dist/domain/verify/competition/prompt.js +1 -1
  128. package/dist/domain/verify/competition/shared-layout.js +1 -1
  129. package/dist/domain/verify/model/types.d.ts +2 -2
  130. package/dist/interactive/providers/launch.d.ts +2 -0
  131. package/dist/interactive/providers/launch.js +19 -2
  132. package/dist/interactive/providers/mcp.d.ts +1 -0
  133. package/dist/interactive/providers/mcp.js +45 -7
  134. package/dist/interactive/substrate.js +32 -5
  135. package/dist/mcp/server.d.ts +1 -0
  136. package/dist/mcp/server.js +337 -44
  137. package/dist/policy/auto.d.ts +0 -1
  138. package/dist/policy/auto.js +3 -14
  139. package/dist/policy/verification.js +18 -1
  140. package/dist/preflight/agents.d.ts +24 -0
  141. package/dist/preflight/agents.js +71 -0
  142. package/dist/preflight/environment.d.ts +6 -0
  143. package/dist/preflight/environment.js +17 -0
  144. package/dist/preflight/formatting.d.ts +5 -0
  145. package/dist/preflight/formatting.js +20 -0
  146. package/dist/preflight/index.d.ts +2 -0
  147. package/dist/preflight/index.js +6 -9
  148. package/dist/preflight/operator.d.ts +32 -0
  149. package/dist/preflight/operator.js +40 -0
  150. package/dist/preflight/settings.d.ts +2 -0
  151. package/dist/preflight/settings.js +17 -0
  152. package/dist/render/transcripts/apply.js +2 -1
  153. package/dist/render/transcripts/interactive.d.ts +16 -0
  154. package/dist/render/transcripts/interactive.js +42 -0
  155. package/dist/render/transcripts/list.d.ts +41 -0
  156. package/dist/render/transcripts/list.js +152 -3
  157. package/dist/render/transcripts/message.d.ts +3 -5
  158. package/dist/render/transcripts/message.js +29 -74
  159. package/dist/render/transcripts/reduce.d.ts +2 -4
  160. package/dist/render/transcripts/reduce.js +31 -75
  161. package/dist/render/transcripts/root-launcher.js +2 -12
  162. package/dist/render/transcripts/run.d.ts +4 -4
  163. package/dist/render/transcripts/run.js +36 -47
  164. package/dist/render/transcripts/spec.d.ts +1 -4
  165. package/dist/render/transcripts/spec.js +15 -62
  166. package/dist/render/transcripts/verify.d.ts +6 -7
  167. package/dist/render/transcripts/verify.js +54 -85
  168. package/dist/render/utils/cli-writer.d.ts +4 -0
  169. package/dist/render/utils/cli-writer.js +1 -0
  170. package/dist/render/utils/duration.d.ts +5 -0
  171. package/dist/render/utils/duration.js +6 -0
  172. package/dist/render/utils/progressive-render.d.ts +3 -0
  173. package/dist/render/utils/progressive-render.js +44 -0
  174. package/dist/render/utils/runs.d.ts +1 -0
  175. package/dist/render/utils/runs.js +1 -0
  176. package/dist/render/utils/transcript-shell.d.ts +2 -1
  177. package/dist/render/utils/transcript-shell.js +19 -6
  178. package/dist/utils/diff.d.ts +2 -0
  179. package/dist/utils/diff.js +1 -0
  180. package/dist/utils/errors.d.ts +2 -1
  181. package/dist/utils/errors.js +3 -1
  182. package/dist/utils/git.d.ts +1 -1
  183. package/dist/utils/git.js +25 -2
  184. package/dist/utils/list-target.d.ts +4 -0
  185. package/dist/utils/list-target.js +35 -0
  186. package/dist/utils/swarm-session-ack.d.ts +9 -0
  187. package/dist/utils/swarm-session-ack.js +17 -0
  188. package/dist/utils/terminal.d.ts +1 -0
  189. package/dist/utils/terminal.js +11 -0
  190. package/dist/workspace/artifact-paths.d.ts +55 -0
  191. package/dist/workspace/artifact-paths.js +106 -0
  192. package/dist/workspace/chat/artifacts.d.ts +7 -0
  193. package/dist/workspace/chat/artifacts.js +95 -4
  194. package/dist/workspace/chat/native-usage.js +1 -1
  195. package/dist/workspace/chat/sources.d.ts +2 -5
  196. package/dist/workspace/chat/sources.js +4 -4
  197. package/dist/workspace/constants.d.ts +47 -0
  198. package/dist/workspace/constants.js +47 -0
  199. package/dist/workspace/errors.js +2 -2
  200. package/dist/workspace/layout.js +3 -1
  201. package/dist/workspace/managed-state.d.ts +32 -0
  202. package/dist/workspace/managed-state.js +104 -0
  203. package/dist/workspace/path-formatters.d.ts +9 -0
  204. package/dist/workspace/path-formatters.js +46 -0
  205. package/dist/workspace/path-resolvers.d.ts +1 -0
  206. package/dist/workspace/path-resolvers.js +5 -0
  207. package/dist/workspace/session-paths.d.ts +16 -0
  208. package/dist/workspace/session-paths.js +59 -0
  209. package/dist/workspace/setup.js +67 -2
  210. package/dist/workspace/shim.d.ts +1 -0
  211. package/dist/workspace/shim.js +3 -3
  212. package/package.json +2 -2
  213. package/dist/cli/init.d.ts +0 -15
  214. package/dist/cli/init.js +0 -70
  215. package/dist/commands/init/agents.d.ts +0 -4
  216. package/dist/commands/init/command.d.ts +0 -2
  217. package/dist/commands/init/environment.d.ts +0 -2
  218. package/dist/render/transcripts/init.d.ts +0 -7
  219. package/dist/render/transcripts/init.js +0 -83
  220. package/dist/workspace/structure.d.ts +0 -143
  221. package/dist/workspace/structure.js +0 -319
  222. /package/dist/commands/{init/types.js → doctor/fix-types.js} +0 -0
@@ -0,0 +1,146 @@
1
+ import { buildLifecycleStartFields, buildOperationLifecycleCompleteFields, buildRecordLifecycleCompleteFields, } from "../../shared/lifecycle.js";
2
+ import { rewriteSpecRecord } from "../persistence/adapter.js";
3
+ export function createSpecRecordMutators(input) {
4
+ const { root, specsFilePath, sessionId } = input;
5
+ const updateAgent = async (agentId, builder, forceFlush = false) => await rewriteSpecRecord({
6
+ root,
7
+ specsFilePath,
8
+ sessionId,
9
+ forceFlush,
10
+ mutate: (record) => {
11
+ const agents = [...record.agents];
12
+ const index = agents.findIndex((agent) => agent.agentId === agentId);
13
+ const current = index >= 0 ? agents[index] : undefined;
14
+ const updated = builder(current);
15
+ if (index >= 0) {
16
+ agents[index] = updated;
17
+ }
18
+ else {
19
+ agents.push(updated);
20
+ }
21
+ return {
22
+ ...record,
23
+ agents,
24
+ };
25
+ },
26
+ });
27
+ return {
28
+ recordAgentRunning: async ({ agentId, timestamp = new Date().toISOString(), }) => await updateAgent(agentId, (existing) => {
29
+ if (existing && isTerminalSpecAgentStatus(existing.status)) {
30
+ return existing;
31
+ }
32
+ return {
33
+ ...(existing ?? { agentId }),
34
+ status: "running",
35
+ ...buildLifecycleStartFields({
36
+ existingStartedAt: existing?.startedAt,
37
+ timestamp,
38
+ }),
39
+ completedAt: undefined,
40
+ outputPath: existing?.outputPath,
41
+ dataPath: existing?.dataPath,
42
+ contentHash: existing?.contentHash,
43
+ tokenUsage: existing?.tokenUsage,
44
+ error: null,
45
+ };
46
+ }),
47
+ recordAgentSnapshot: async (agent) => await updateAgent(agent.agentId, (existing) => existing
48
+ ? mergeSpecAgentEntries(existing, agent)
49
+ : normalizeSpecAgentEntry(agent), isTerminalSpecAgentStatus(agent.status)),
50
+ completeSpec: async ({ status, agents, error }) => await rewriteSpecRecord({
51
+ root,
52
+ specsFilePath,
53
+ sessionId,
54
+ mutate: (existing) => ({
55
+ ...existing,
56
+ status,
57
+ ...buildRecordLifecycleCompleteFields({ existing }),
58
+ ...(agents ? { agents: [...agents] } : {}),
59
+ ...(error !== undefined ? { error } : {}),
60
+ }),
61
+ forceFlush: true,
62
+ }),
63
+ readRecord: async () => await rewriteSpecRecord({
64
+ root,
65
+ specsFilePath,
66
+ sessionId,
67
+ mutate: (record) => record,
68
+ }),
69
+ };
70
+ }
71
+ function mergeSpecAgentEntries(existing, incoming) {
72
+ if (isTerminalSpecAgentStatus(existing.status) &&
73
+ !isTerminalSpecAgentStatus(incoming.status)) {
74
+ return existing;
75
+ }
76
+ if (incoming.status === "running") {
77
+ return {
78
+ ...existing,
79
+ ...incoming,
80
+ status: "running",
81
+ ...buildLifecycleStartFields({
82
+ existingStartedAt: existing.startedAt,
83
+ timestamp: incoming.startedAt,
84
+ }),
85
+ completedAt: undefined,
86
+ outputPath: incoming.outputPath ?? existing.outputPath,
87
+ dataPath: incoming.dataPath ?? existing.dataPath,
88
+ contentHash: incoming.contentHash ?? existing.contentHash,
89
+ tokenUsage: incoming.tokenUsage ?? existing.tokenUsage,
90
+ error: incoming.error !== undefined
91
+ ? incoming.error
92
+ : (existing.error ?? null),
93
+ };
94
+ }
95
+ const completedAt = incoming.completedAt ?? new Date().toISOString();
96
+ const startedAt = buildLifecycleStartFields({
97
+ existingStartedAt: existing.startedAt,
98
+ timestamp: incoming.startedAt ?? completedAt,
99
+ }).startedAt;
100
+ const lifecycle = buildOperationLifecycleCompleteFields({
101
+ existing: {
102
+ startedAt,
103
+ completedAt: existing.completedAt,
104
+ },
105
+ completedAt,
106
+ });
107
+ return {
108
+ ...existing,
109
+ ...incoming,
110
+ ...lifecycle,
111
+ outputPath: incoming.outputPath ?? existing.outputPath,
112
+ dataPath: incoming.dataPath ?? existing.dataPath,
113
+ contentHash: incoming.contentHash ?? existing.contentHash,
114
+ tokenUsage: incoming.tokenUsage ?? existing.tokenUsage,
115
+ error: incoming.error !== undefined ? incoming.error : (existing.error ?? null),
116
+ };
117
+ }
118
+ function normalizeSpecAgentEntry(agent) {
119
+ if (agent.status === "running") {
120
+ return {
121
+ ...agent,
122
+ ...buildLifecycleStartFields({
123
+ existingStartedAt: undefined,
124
+ timestamp: agent.startedAt,
125
+ }),
126
+ completedAt: undefined,
127
+ error: agent.error ?? null,
128
+ };
129
+ }
130
+ const completedAt = agent.completedAt ?? new Date().toISOString();
131
+ const startedAt = buildLifecycleStartFields({
132
+ existingStartedAt: undefined,
133
+ timestamp: agent.startedAt ?? completedAt,
134
+ }).startedAt;
135
+ return {
136
+ ...agent,
137
+ ...buildOperationLifecycleCompleteFields({
138
+ existing: { startedAt, completedAt: undefined },
139
+ completedAt,
140
+ }),
141
+ error: agent.error ?? null,
142
+ };
143
+ }
144
+ function isTerminalSpecAgentStatus(status) {
145
+ return status === "succeeded" || status === "failed";
146
+ }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { type SpecAgentStatus, specAgentStatusSchema, type SpecRecordStatus, specRecordStatusSchema, TERMINAL_SPEC_AGENT_STATUSES, TERMINAL_SPEC_STATUSES } from "../../../status/index.js";
3
3
  export type { SpecAgentStatus, SpecRecordStatus };
4
4
  export { specAgentStatusSchema, specRecordStatusSchema, TERMINAL_SPEC_AGENT_STATUSES, TERMINAL_SPEC_STATUSES, };
5
+ export declare const specContentHashSchema: z.ZodString;
5
6
  export declare const specAgentEntrySchema: z.ZodObject<{
6
7
  agentId: z.ZodString;
7
8
  status: z.ZodEnum<{
@@ -14,6 +15,7 @@ export declare const specAgentEntrySchema: z.ZodObject<{
14
15
  completedAt: z.ZodOptional<z.ZodString>;
15
16
  outputPath: z.ZodOptional<z.ZodString>;
16
17
  dataPath: z.ZodOptional<z.ZodString>;
18
+ contentHash: z.ZodOptional<z.ZodString>;
17
19
  tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
18
20
  input_tokens: z.ZodOptional<z.ZodNumber>;
19
21
  output_tokens: z.ZodOptional<z.ZodNumber>;
@@ -66,6 +68,7 @@ export declare const specRecordSchema: z.ZodObject<{
66
68
  completedAt: z.ZodOptional<z.ZodString>;
67
69
  outputPath: z.ZodOptional<z.ZodString>;
68
70
  dataPath: z.ZodOptional<z.ZodString>;
71
+ contentHash: z.ZodOptional<z.ZodString>;
69
72
  tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
70
73
  input_tokens: z.ZodOptional<z.ZodNumber>;
71
74
  output_tokens: z.ZodOptional<z.ZodNumber>;
@@ -9,6 +9,10 @@ export { specAgentStatusSchema, specRecordStatusSchema, TERMINAL_SPEC_AGENT_STAT
9
9
  const IN_PROGRESS_SPEC_STATUSES = [
10
10
  "running",
11
11
  ];
12
+ const SPEC_CONTENT_HASH_PATTERN = /^sha256:[a-f0-9]{64}$/u;
13
+ export const specContentHashSchema = z
14
+ .string()
15
+ .regex(SPEC_CONTENT_HASH_PATTERN);
12
16
  export const specAgentEntrySchema = z
13
17
  .object({
14
18
  agentId: agentIdSchema,
@@ -17,6 +21,7 @@ export const specAgentEntrySchema = z
17
21
  completedAt: z.string().optional(),
18
22
  outputPath: repoRelativeRecordPathSchema.optional(),
19
23
  dataPath: repoRelativeRecordPathSchema.optional(),
24
+ contentHash: specContentHashSchema.optional(),
20
25
  tokenUsage: extractedTokenUsageSchema.optional(),
21
26
  error: z.string().nullable().optional(),
22
27
  })
@@ -26,6 +26,7 @@ export interface RewriteSpecRecordOptions {
26
26
  specsFilePath: string;
27
27
  sessionId: string;
28
28
  mutate: (record: SpecRecord) => SpecRecord;
29
+ forceFlush?: boolean;
29
30
  }
30
31
  export interface AppendSpecRecordOptions {
31
32
  root: string;
@@ -68,10 +68,15 @@ export async function appendSpecRecord(options) {
68
68
  }
69
69
  }
70
70
  export async function rewriteSpecRecord(options) {
71
- const { root, specsFilePath, sessionId, mutate } = options;
71
+ const { root, specsFilePath, sessionId, mutate, forceFlush } = options;
72
72
  const paths = buildSpecPaths(root, specsFilePath);
73
73
  try {
74
- return await specPersistence.rewriteRecord({ paths, sessionId, mutate });
74
+ return await specPersistence.rewriteRecord({
75
+ paths,
76
+ sessionId,
77
+ mutate,
78
+ forceFlush,
79
+ });
75
80
  }
76
81
  catch (error) {
77
82
  throw mapSessionStoreError(error, sessionStoreErrorMapper);
@@ -1,6 +1,6 @@
1
1
  import type { CompetitionCommandAdapter } from "../../../competition/command-adapter.js";
2
2
  import { type ResolvedExtraContextFile } from "../../../competition/shared/extra-context.js";
3
- import type { TeardownController } from "../../../competition/shared/teardown.js";
3
+ import { type TeardownController } from "../../../competition/shared/teardown.js";
4
4
  import type { AgentDefinition } from "../../../configs/agents/types.js";
5
5
  import type { EnvironmentConfig } from "../../../configs/environment/types.js";
6
6
  import type { VerifyProgressRenderer } from "../../../render/transcripts/verify.js";
@@ -4,15 +4,17 @@ import { detectAgentProcessFailureDetail } from "../../../agents/runtime/failure
4
4
  import { runSandboxedAgent } from "../../../agents/runtime/harness.js";
5
5
  import { stageExtraContextFiles, } from "../../../competition/shared/extra-context.js";
6
6
  import { composeStageSandboxPolicy } from "../../../competition/shared/sandbox-policy.js";
7
+ import { registerScratchWorkspaceTeardownPaths, } from "../../../competition/shared/teardown.js";
7
8
  import { buildUnavailableTokenUsageResult, resolveTokenUsage, } from "../../../domain/shared/token-usage.js";
8
9
  import { emitStageProgressEvent } from "../../../render/transcripts/stage-progress.js";
9
10
  import { toErrorMessage } from "../../../utils/errors.js";
10
11
  import { pathExists } from "../../../utils/fs.js";
11
12
  import { prepareScratchAgentWorkspace } from "../../../workspace/agents.js";
13
+ import { getVerificationRubricExecutionDirectoryPath, getVerificationRubricResultPath, } from "../../../workspace/artifact-paths.js";
12
14
  import { extractProviderNativeTokenUsageForSession } from "../../../workspace/chat/native-usage.js";
15
+ import { VORATIQ_VERIFICATION_DIR } from "../../../workspace/constants.js";
13
16
  import { ensureWorkspaceDependencies } from "../../../workspace/dependencies.js";
14
17
  import { buildScopedAgentWorkspacePaths, } from "../../../workspace/layout.js";
15
- import { getVerificationRubricExecutionDirectoryPath, getVerificationRubricResultPath, VORATIQ_VERIFICATION_DIR, } from "../../../workspace/structure.js";
16
18
  import { verificationResultArtifactSchema, } from "../model/types.js";
17
19
  import { writeVerificationArtifact } from "./artifacts.js";
18
20
  import { assertNoVerificationIdentityLeak, assertRubricResultSelectorsMatchAliasMap, buildForbiddenVerificationIdentityTokens, parseRubricResultPayload, } from "./blinding.js";
@@ -34,7 +36,7 @@ export function createVerifyCompetitionAdapter(input) {
34
36
  verifierId: candidate.agent.id,
35
37
  template: candidate.template.template,
36
38
  });
37
- registerScratchWorkspaceTeardown(teardown, workspacePaths, candidate.agent.id, candidate.template.template);
39
+ registerScratchWorkspaceTeardownPaths(teardown, workspacePaths, `${candidate.agent.id}/${candidate.template.template}`);
38
40
  return { candidate, workspacePaths };
39
41
  }),
40
42
  failures: [],
@@ -435,10 +437,3 @@ function compareVerificationsByTemplateThenVerifierId(left, right) {
435
437
  return (left.template.localeCompare(right.template) ||
436
438
  left.verifierId.localeCompare(right.verifierId));
437
439
  }
438
- function registerScratchWorkspaceTeardown(teardown, workspacePaths, verifierId, template) {
439
- const labelPrefix = `${verifierId}/${template}`;
440
- teardown.addPath(workspacePaths.workspacePath, `${labelPrefix} workspace`);
441
- teardown.addPath(workspacePaths.contextPath, `${labelPrefix} context`);
442
- teardown.addPath(workspacePaths.runtimePath, `${labelPrefix} runtime`);
443
- teardown.addPath(workspacePaths.sandboxPath, `${labelPrefix} sandbox`);
444
- }
@@ -1,5 +1,14 @@
1
1
  import type { VerificationMethodResultRef, VerificationStatus } from "../model/types.js";
2
2
  import type { ResolvedVerificationTarget } from "./target.js";
3
+ /**
4
+ * Derive the session-level verification status from per-method outcomes.
5
+ *
6
+ * Session status is "succeeded" when at least one terminal method succeeds.
7
+ * Session status is "aborted" only when all terminal methods are aborted.
8
+ * Otherwise, the session is treated as "failed". When no terminal method
9
+ * snapshots exist yet, preserve the historical default of reporting
10
+ * "succeeded" rather than manufacturing a failure.
11
+ */
3
12
  export declare function deriveVerificationStatusFromMethods(methods: readonly VerificationMethodResultRef[]): VerificationStatus;
4
13
  export declare function maybePersistSelectedSpecPath(options: {
5
14
  root: string;
@@ -1,12 +1,31 @@
1
1
  import { loadVerificationSelectionPolicyOutput } from "../../../policy/index.js";
2
2
  import { rewriteVerificationRecord } from "../persistence/adapter.js";
3
+ /**
4
+ * Derive the session-level verification status from per-method outcomes.
5
+ *
6
+ * Session status is "succeeded" when at least one terminal method succeeds.
7
+ * Session status is "aborted" only when all terminal methods are aborted.
8
+ * Otherwise, the session is treated as "failed". When no terminal method
9
+ * snapshots exist yet, preserve the historical default of reporting
10
+ * "succeeded" rather than manufacturing a failure.
11
+ */
3
12
  export function deriveVerificationStatusFromMethods(methods) {
4
- if (methods.some((method) => method.status === "failed")) {
5
- return "failed";
13
+ const terminalMethods = methods.filter((method) => method.status === "succeeded" ||
14
+ method.status === "failed" ||
15
+ method.status === "aborted");
16
+ const hasSucceeded = terminalMethods.some((method) => method.status === "succeeded");
17
+ if (hasSucceeded) {
18
+ return "succeeded";
6
19
  }
7
- if (methods.some((method) => method.status === "aborted")) {
20
+ const hasTerminalMethods = terminalMethods.length > 0;
21
+ const allTerminalAborted = hasTerminalMethods &&
22
+ terminalMethods.every((method) => method.status === "aborted");
23
+ if (allTerminalAborted) {
8
24
  return "aborted";
9
25
  }
26
+ if (terminalMethods.some((method) => method.status === "failed")) {
27
+ return "failed";
28
+ }
10
29
  return "succeeded";
11
30
  }
12
31
  export async function maybePersistSelectedSpecPath(options) {
@@ -5,8 +5,9 @@ import { emitStageProgressEvent } from "../../../render/transcripts/stage-progre
5
5
  import { toErrorMessage } from "../../../utils/errors.js";
6
6
  import { pathExists } from "../../../utils/fs.js";
7
7
  import { createDetachedWorktree, getGitStderr, removeWorktree, runGitCommand, } from "../../../utils/git.js";
8
+ import { getVerificationProgrammaticResultPath } from "../../../workspace/artifact-paths.js";
9
+ import { VORATIQ_VERIFICATION_DIR } from "../../../workspace/constants.js";
8
10
  import { buildAgentWorkspacePaths } from "../../../workspace/layout.js";
9
- import { getVerificationProgrammaticResultPath, VORATIQ_VERIFICATION_DIR, } from "../../../workspace/structure.js";
10
11
  import { executeProgrammaticChecks } from "../programmatic/runner.js";
11
12
  import { writeVerificationArtifact } from "./artifacts.js";
12
13
  const PROGRAMMATIC_CANDIDATE_MAX_PARALLEL = 2;
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
3
  import { appendConstraints, appendOutputRequirements, buildWorkspaceArtifactRequirements, } from "../../../competition/shared/prompt-helpers.js";
4
4
  import { toExtraContextContextSubpath } from "../../../extra-context/contract.js";
5
- import { VORATIQ_VERIFICATION_DIR } from "../../../workspace/structure.js";
5
+ import { VORATIQ_VERIFICATION_DIR } from "../../../workspace/constants.js";
6
6
  export async function loadRubricTemplate(options) {
7
7
  const { root, template } = options;
8
8
  const base = resolve(root, ".voratiq", VORATIQ_VERIFICATION_DIR, "templates", template);
@@ -2,9 +2,9 @@ import { copyFile, mkdir, rm, symlink, writeFile } from "node:fs/promises";
2
2
  import { basename, dirname, join, relative as relativePath, resolve, sep, } from "node:path";
3
3
  import { pathExists } from "../../../utils/fs.js";
4
4
  import { createDetachedWorktree, removeWorktree } from "../../../utils/git.js";
5
+ import { MESSAGE_RESPONSE_FILENAME, VORATIQ_VERIFICATION_SESSIONS_DIR, } from "../../../workspace/constants.js";
5
6
  import { ensureWorkspaceDependencies } from "../../../workspace/dependencies.js";
6
7
  import { buildAgentWorkspacePaths, } from "../../../workspace/layout.js";
7
- import { MESSAGE_RESPONSE_FILENAME, VORATIQ_VERIFICATION_SESSIONS_DIR, } from "../../../workspace/structure.js";
8
8
  import { aliasForCandidate } from "./blinding.js";
9
9
  const BLINDED_VERIFY_SPEC_ARTIFACT_ALLOWLIST = [
10
10
  {
@@ -11,8 +11,8 @@ export type VerificationMethodKind = (typeof VERIFICATION_METHOD_KIND_VALUES)[nu
11
11
  export type VerificationScopeKind = (typeof VERIFICATION_SCOPE_KIND_VALUES)[number];
12
12
  export declare const verificationTargetKindSchema: z.ZodEnum<{
13
13
  message: "message";
14
- reduce: "reduce";
15
14
  spec: "spec";
15
+ reduce: "reduce";
16
16
  run: "run";
17
17
  }>;
18
18
  export declare const verificationMethodKindSchema: z.ZodEnum<{
@@ -399,8 +399,8 @@ export declare const verificationIndexEntrySchema: z.ZodObject<{
399
399
  }>;
400
400
  targetKind: z.ZodEnum<{
401
401
  message: "message";
402
- reduce: "reduce";
403
402
  spec: "spec";
403
+ reduce: "reduce";
404
404
  run: "run";
405
405
  }>;
406
406
  targetSessionId: z.ZodString;
@@ -6,6 +6,7 @@ export interface ProviderLaunchPreparationInput {
6
6
  agent: AgentDefinition;
7
7
  root: string;
8
8
  toolDeclarations: readonly NativeToolDeclaration[];
9
+ sessionScopedMcpEnv?: Record<string, string>;
9
10
  prompt?: string;
10
11
  launchMode?: "default" | "first-party";
11
12
  firstPartyMcpResolution?: FirstPartyMcpStatusAndArgs;
@@ -19,5 +20,6 @@ export interface ProviderLaunchPreparationResult {
19
20
  export declare function createBundledVoratiqToolDeclaration(options: {
20
21
  command: string;
21
22
  argsPrefix: readonly string[];
23
+ env?: Record<string, string>;
22
24
  }): NativeToolDeclaration;
23
25
  export declare function prepareProviderNativeLaunch(options: ProviderLaunchPreparationInput): Promise<ProviderLaunchPreparationResult>;
@@ -10,6 +10,9 @@ export function createBundledVoratiqToolDeclaration(options) {
10
10
  name: BUNDLED_VORATIQ_TOOL_TARGET_NAME,
11
11
  command: options.command,
12
12
  args: [...options.argsPrefix, "mcp", "--stdio"],
13
+ ...(options.env && Object.keys(options.env).length > 0
14
+ ? { env: { ...options.env } }
15
+ : {}),
13
16
  };
14
17
  }
15
18
  export async function prepareProviderNativeLaunch(options) {
@@ -19,14 +22,18 @@ export async function prepareProviderNativeLaunch(options) {
19
22
  return await adapter.prepare(options);
20
23
  }
21
24
  function prepareCodexLaunch(options) {
22
- const args = applyPositionalPrompt(applyNativeQaLaunchArgs("codex", sanitizeCodexArgs(options.agent)), options.prompt);
23
25
  const mcp = resolveFirstPartyMcpStatusAndArgs({
24
26
  launchMode: options.launchMode,
25
27
  toolDeclarations: options.toolDeclarations,
26
28
  firstPartyMcpResolution: options.firstPartyMcpResolution,
27
29
  });
30
+ const args = applyPositionalPrompt([
31
+ ...applyNativeQaLaunchArgs("codex", sanitizeCodexArgs(options.agent)),
32
+ ...buildCodexLaunchScopedMcpEnvArgs(options.sessionScopedMcpEnv),
33
+ ...mcp.additionalArgs,
34
+ ], options.prompt);
28
35
  return Promise.resolve({
29
- args: [...args, ...mcp.additionalArgs],
36
+ args,
30
37
  env: {},
31
38
  toolAttachmentStatus: mcp.toolAttachmentStatus,
32
39
  artifactCaptureSupported: true,
@@ -144,6 +151,16 @@ function sanitizeGeminiArgs(agent) {
144
151
  }
145
152
  return ensureModelArg(sanitized, agent.model);
146
153
  }
154
+ function buildCodexLaunchScopedMcpEnvArgs(env) {
155
+ if (!env) {
156
+ return [];
157
+ }
158
+ const args = [];
159
+ for (const [key, value] of Object.entries(env)) {
160
+ args.push("-c", `mcp_servers.${BUNDLED_VORATIQ_TOOL_TARGET_NAME}.env.${key}=${JSON.stringify(value)}`);
161
+ }
162
+ return args;
163
+ }
147
164
  function ensureModelArg(argv, model) {
148
165
  const sanitized = [...argv];
149
166
  for (let index = 0; index < sanitized.length; index += 1) {
@@ -6,6 +6,7 @@ export interface FirstPartyMcpStatusAndArgs {
6
6
  }
7
7
  export declare function resolveFirstPartyMcpStatus(options: {
8
8
  providerId: FirstPartyProviderId;
9
+ providerBinary?: string;
9
10
  root: string;
10
11
  toolDeclarations: readonly NativeToolDeclaration[];
11
12
  promptForMcpInstall?: PromptForMcpInstall;
@@ -1,4 +1,5 @@
1
1
  import { spawn } from "node:child_process";
2
+ import { basename } from "node:path";
2
3
  import { setTimeout as delay } from "node:timers/promises";
3
4
  import { loadRepoSettings } from "../../configs/settings/loader.js";
4
5
  import { BUNDLED_VORATIQ_TOOL_TARGET_NAME, } from "./shared.js";
@@ -44,9 +45,11 @@ export async function resolveFirstPartyMcpStatus(options) {
44
45
  }
45
46
  const runCommand = options.mcpCommandRunner ?? runProviderMcpCommand;
46
47
  const adapter = firstPartyMcpAdapters[options.providerId];
48
+ const providerBinary = resolveProviderBinary(options.providerBinary, adapter.providerCommand);
47
49
  const initialInspection = summarizeFirstPartyMcpInspection({
48
50
  toolDeclarations: options.toolDeclarations,
49
51
  inspections: await adapter.inspectTools({
52
+ providerBinary,
50
53
  root: options.root,
51
54
  toolDeclarations: options.toolDeclarations,
52
55
  runCommand,
@@ -84,12 +87,14 @@ export async function resolveFirstPartyMcpStatus(options) {
84
87
  }
85
88
  await installVoratiqMcpForProvider({
86
89
  adapter,
90
+ providerBinary,
87
91
  root: options.root,
88
92
  toolDeclarations: initialInspection.missingToolDeclarations,
89
93
  runCommand,
90
94
  });
91
95
  const verifiedInspection = await verifyFirstPartyMcpStatus({
92
96
  adapter,
97
+ providerBinary,
93
98
  root: options.root,
94
99
  toolDeclarations: options.toolDeclarations,
95
100
  runCommand,
@@ -141,6 +146,7 @@ async function verifyFirstPartyMcpStatus(options) {
141
146
  lastSummary = summarizeFirstPartyMcpInspection({
142
147
  toolDeclarations: options.toolDeclarations,
143
148
  inspections: await options.adapter.inspectTools({
149
+ providerBinary: options.providerBinary,
144
150
  root: options.root,
145
151
  toolDeclarations: options.toolDeclarations,
146
152
  runCommand: options.runCommand,
@@ -176,7 +182,7 @@ async function inspectGeminiMcpTools(options) {
176
182
  return inspections;
177
183
  }
178
184
  const result = await options.runCommand({
179
- command: "gemini",
185
+ command: options.providerBinary,
180
186
  args: ["mcp", "list"],
181
187
  cwd: options.root,
182
188
  });
@@ -203,6 +209,7 @@ async function inspectCliMcpToolsViaGet(options) {
203
209
  const inspections = new Map();
204
210
  for (const tool of options.toolDeclarations) {
205
211
  inspections.set(tool.name, await inspectCliMcpTool({
212
+ providerBinary: options.providerBinary,
206
213
  providerCommand: options.providerCommand,
207
214
  root: options.root,
208
215
  declaration: tool,
@@ -213,6 +220,7 @@ async function inspectCliMcpToolsViaGet(options) {
213
220
  }
214
221
  async function inspectCodexMcpTools(options) {
215
222
  return await inspectCliMcpToolsViaGet({
223
+ providerBinary: options.providerBinary,
216
224
  providerCommand: "codex",
217
225
  root: options.root,
218
226
  toolDeclarations: options.toolDeclarations,
@@ -221,6 +229,7 @@ async function inspectCodexMcpTools(options) {
221
229
  }
222
230
  async function inspectClaudeMcpTools(options) {
223
231
  return await inspectCliMcpToolsViaGet({
232
+ providerBinary: options.providerBinary,
224
233
  providerCommand: "claude",
225
234
  root: options.root,
226
235
  toolDeclarations: options.toolDeclarations,
@@ -230,7 +239,7 @@ async function inspectClaudeMcpTools(options) {
230
239
  async function inspectCliMcpTool(options) {
231
240
  if (options.providerCommand === "codex") {
232
241
  const result = await options.runCommand({
233
- command: "codex",
242
+ command: options.providerBinary,
234
243
  args: ["mcp", "get", "--json", options.declaration.name],
235
244
  cwd: options.root,
236
245
  });
@@ -260,7 +269,7 @@ async function inspectCliMcpTool(options) {
260
269
  };
261
270
  }
262
271
  const result = await options.runCommand({
263
- command: "claude",
272
+ command: options.providerBinary,
264
273
  args: ["mcp", "get", options.declaration.name],
265
274
  cwd: options.root,
266
275
  });
@@ -345,11 +354,11 @@ function normalizeStringArray(value) {
345
354
  return [...value];
346
355
  }
347
356
  function matchesDeclarationCommandAndArgs(declaration, value) {
348
- if (value.command !== declaration.command) {
357
+ const expectedArgs = declaration.args ? [...declaration.args] : [];
358
+ if (!areStringArraysEqual(value.args, expectedArgs)) {
349
359
  return false;
350
360
  }
351
- const expectedArgs = declaration.args ? [...declaration.args] : [];
352
- return areStringArraysEqual(value.args, expectedArgs);
361
+ return areEquivalentMcpCommands(value.command, declaration.command);
353
362
  }
354
363
  function areStringArraysEqual(left, right) {
355
364
  if (left.length !== right.length) {
@@ -362,6 +371,16 @@ function areStringArraysEqual(left, right) {
362
371
  }
363
372
  return true;
364
373
  }
374
+ function areEquivalentMcpCommands(left, right) {
375
+ if (left === right) {
376
+ return true;
377
+ }
378
+ return isNodeExecutableCommand(left) && isNodeExecutableCommand(right);
379
+ }
380
+ function isNodeExecutableCommand(value) {
381
+ const normalized = basename(value).toLowerCase();
382
+ return normalized === "node" || normalized === "node.exe";
383
+ }
365
384
  function buildCommandMismatchDetail(declaration, actual) {
366
385
  return [
367
386
  `Expected \`${formatCommandAndArgs(declaration.command, declaration.args ?? [])}\`,`,
@@ -425,7 +444,7 @@ function splitCommandLine(value) {
425
444
  async function installVoratiqMcpForProvider(options) {
426
445
  for (const toolDeclaration of options.toolDeclarations) {
427
446
  const result = await options.runCommand({
428
- command: options.adapter.providerCommand,
447
+ command: options.providerBinary,
429
448
  args: options.adapter.buildAddArgs(toolDeclaration),
430
449
  cwd: options.root,
431
450
  });
@@ -535,7 +554,22 @@ async function runProviderMcpCommand(input) {
535
554
  stderr += chunk;
536
555
  });
537
556
  const exitCode = await new Promise((resolve) => {
557
+ let settled = false;
558
+ child.on("error", (error) => {
559
+ if (settled) {
560
+ return;
561
+ }
562
+ settled = true;
563
+ if (stderr.trim().length === 0) {
564
+ stderr = error.message;
565
+ }
566
+ resolve(null);
567
+ });
538
568
  child.on("close", (code) => {
569
+ if (settled) {
570
+ return;
571
+ }
572
+ settled = true;
539
573
  resolve(typeof code === "number" ? code : null);
540
574
  });
541
575
  });
@@ -545,3 +579,7 @@ async function runProviderMcpCommand(input) {
545
579
  stderr,
546
580
  };
547
581
  }
582
+ function resolveProviderBinary(candidate, fallback) {
583
+ const normalized = candidate?.trim();
584
+ return normalized && normalized.length > 0 ? normalized : fallback;
585
+ }