harness-engineering-agent 0.1.7 → 0.1.9

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 (276) hide show
  1. package/README.md +161 -62
  2. package/dist/agent/harness-agent-capabilities.d.ts +4 -0
  3. package/dist/agent/harness-agent-capabilities.d.ts.map +1 -0
  4. package/dist/agent/harness-agent-capabilities.js +4 -0
  5. package/dist/agent/harness-agent-capabilities.js.map +1 -0
  6. package/dist/agent/harness-agent-capability-builders.d.ts +11 -0
  7. package/dist/agent/harness-agent-capability-builders.d.ts.map +1 -0
  8. package/dist/agent/harness-agent-capability-builders.js +57 -0
  9. package/dist/agent/harness-agent-capability-builders.js.map +1 -0
  10. package/dist/agent/harness-agent-capability-data.d.ts +3 -0
  11. package/dist/agent/harness-agent-capability-data.d.ts.map +1 -0
  12. package/dist/agent/harness-agent-capability-data.js +23 -0
  13. package/dist/agent/harness-agent-capability-data.js.map +1 -0
  14. package/dist/agent/harness-agent-capability-types.d.ts +50 -0
  15. package/dist/agent/harness-agent-capability-types.d.ts.map +1 -0
  16. package/dist/agent/harness-agent-capability-types.js +3 -0
  17. package/dist/agent/harness-agent-capability-types.js.map +1 -0
  18. package/dist/agent/harness-role-capability-directory-data.d.ts +3 -0
  19. package/dist/agent/harness-role-capability-directory-data.d.ts.map +1 -0
  20. package/dist/agent/harness-role-capability-directory-data.js +208 -0
  21. package/dist/agent/harness-role-capability-directory-data.js.map +1 -0
  22. package/dist/agent/harness-role-capability-directory.d.ts +43 -0
  23. package/dist/agent/harness-role-capability-directory.d.ts.map +1 -0
  24. package/dist/agent/harness-role-capability-directory.js +57 -0
  25. package/dist/agent/harness-role-capability-directory.js.map +1 -0
  26. package/dist/agent/index.d.ts +7 -0
  27. package/dist/agent/index.d.ts.map +1 -0
  28. package/dist/agent/index.js +6 -0
  29. package/dist/agent/index.js.map +1 -0
  30. package/dist/config/config-defaults.d.ts +22 -0
  31. package/dist/config/config-defaults.d.ts.map +1 -1
  32. package/dist/config/config-defaults.js +22 -0
  33. package/dist/config/config-defaults.js.map +1 -1
  34. package/dist/config/config-merge.d.ts.map +1 -1
  35. package/dist/config/config-merge.js +30 -0
  36. package/dist/config/config-merge.js.map +1 -1
  37. package/dist/config/config-schema.d.ts +59 -0
  38. package/dist/config/config-schema.d.ts.map +1 -1
  39. package/dist/config/config-schema.js +18 -1
  40. package/dist/config/config-schema.js.map +1 -1
  41. package/dist/config/config-types.d.ts +5 -1
  42. package/dist/config/config-types.d.ts.map +1 -1
  43. package/dist/config/harness-config.d.ts +2 -1
  44. package/dist/config/harness-config.d.ts.map +1 -1
  45. package/dist/config/harness-config.js +1 -0
  46. package/dist/config/harness-config.js.map +1 -1
  47. package/dist/config/index.d.ts +1 -1
  48. package/dist/config/index.d.ts.map +1 -1
  49. package/dist/config/index.js.map +1 -1
  50. package/dist/config/opencode-compatibility.d.ts +37 -0
  51. package/dist/config/opencode-compatibility.d.ts.map +1 -0
  52. package/dist/config/opencode-compatibility.js +99 -0
  53. package/dist/config/opencode-compatibility.js.map +1 -0
  54. package/dist/controller/agent-output.d.ts +1 -1
  55. package/dist/controller/agent-output.d.ts.map +1 -1
  56. package/dist/controller/agent-output.js +18 -1
  57. package/dist/controller/agent-output.js.map +1 -1
  58. package/dist/controller/agent-session-types.d.ts +56 -0
  59. package/dist/controller/agent-session-types.d.ts.map +1 -0
  60. package/dist/controller/agent-session-types.js +2 -0
  61. package/dist/controller/agent-session-types.js.map +1 -0
  62. package/dist/controller/agent-session-utils.d.ts +52 -0
  63. package/dist/controller/agent-session-utils.d.ts.map +1 -0
  64. package/dist/controller/agent-session-utils.js +118 -0
  65. package/dist/controller/agent-session-utils.js.map +1 -0
  66. package/dist/controller/agent-session.d.ts +2 -40
  67. package/dist/controller/agent-session.d.ts.map +1 -1
  68. package/dist/controller/agent-session.js +126 -128
  69. package/dist/controller/agent-session.js.map +1 -1
  70. package/dist/controller/contracts.d.ts +4 -2
  71. package/dist/controller/contracts.d.ts.map +1 -1
  72. package/dist/controller/contracts.js.map +1 -1
  73. package/dist/controller/errors.d.ts +5 -0
  74. package/dist/controller/errors.d.ts.map +1 -1
  75. package/dist/controller/errors.js +8 -0
  76. package/dist/controller/errors.js.map +1 -1
  77. package/dist/controller/evidence-factory.js +7 -1
  78. package/dist/controller/evidence-factory.js.map +1 -1
  79. package/dist/controller/failure-analysis.d.ts +12 -0
  80. package/dist/controller/failure-analysis.d.ts.map +1 -1
  81. package/dist/controller/failure-analysis.js +41 -0
  82. package/dist/controller/failure-analysis.js.map +1 -1
  83. package/dist/controller/failure-analyzer-schemas.d.ts +87 -0
  84. package/dist/controller/failure-analyzer-schemas.d.ts.map +1 -0
  85. package/dist/controller/failure-analyzer-schemas.js +117 -0
  86. package/dist/controller/failure-analyzer-schemas.js.map +1 -0
  87. package/dist/controller/graph-validator.js +18 -4
  88. package/dist/controller/graph-validator.js.map +1 -1
  89. package/dist/controller/index.d.ts +7 -2
  90. package/dist/controller/index.d.ts.map +1 -1
  91. package/dist/controller/index.js +4 -1
  92. package/dist/controller/index.js.map +1 -1
  93. package/dist/controller/repair-loop.d.ts +1 -1
  94. package/dist/controller/repair-loop.d.ts.map +1 -1
  95. package/dist/controller/repair-loop.js +28 -0
  96. package/dist/controller/repair-loop.js.map +1 -1
  97. package/dist/controller/report-factory.d.ts.map +1 -1
  98. package/dist/controller/report-factory.js +49 -21
  99. package/dist/controller/report-factory.js.map +1 -1
  100. package/dist/controller/role-prompts.d.ts +2 -1
  101. package/dist/controller/role-prompts.d.ts.map +1 -1
  102. package/dist/controller/role-prompts.js +3 -9
  103. package/dist/controller/role-prompts.js.map +1 -1
  104. package/dist/controller/run-acceptance.d.ts +17 -0
  105. package/dist/controller/run-acceptance.d.ts.map +1 -0
  106. package/dist/controller/run-acceptance.js +179 -0
  107. package/dist/controller/run-acceptance.js.map +1 -0
  108. package/dist/controller/run-controller.d.ts.map +1 -1
  109. package/dist/controller/run-controller.js +379 -96
  110. package/dist/controller/run-controller.js.map +1 -1
  111. package/dist/controller/run-state.d.ts +1 -0
  112. package/dist/controller/run-state.d.ts.map +1 -1
  113. package/dist/controller/run-state.js +12 -0
  114. package/dist/controller/run-state.js.map +1 -1
  115. package/dist/controller/session-tool-authorization.d.ts +14 -0
  116. package/dist/controller/session-tool-authorization.d.ts.map +1 -0
  117. package/dist/controller/session-tool-authorization.js +88 -0
  118. package/dist/controller/session-tool-authorization.js.map +1 -0
  119. package/dist/controller/task-agent-output.d.ts +13 -2
  120. package/dist/controller/task-agent-output.d.ts.map +1 -1
  121. package/dist/controller/task-agent-output.js +58 -1
  122. package/dist/controller/task-agent-output.js.map +1 -1
  123. package/dist/controller/task-agent-schemas.d.ts +745 -26
  124. package/dist/controller/task-agent-schemas.d.ts.map +1 -1
  125. package/dist/controller/task-agent-schemas.js +70 -21
  126. package/dist/controller/task-agent-schemas.js.map +1 -1
  127. package/dist/controller/task-executor.d.ts +2 -1
  128. package/dist/controller/task-executor.d.ts.map +1 -1
  129. package/dist/controller/task-executor.js +304 -105
  130. package/dist/controller/task-executor.js.map +1 -1
  131. package/dist/doctor/cli.d.ts +3 -0
  132. package/dist/doctor/cli.d.ts.map +1 -0
  133. package/dist/doctor/cli.js +10 -0
  134. package/dist/doctor/cli.js.map +1 -0
  135. package/dist/doctor/index.d.ts +7 -0
  136. package/dist/doctor/index.d.ts.map +1 -0
  137. package/dist/doctor/index.js +16 -0
  138. package/dist/doctor/index.js.map +1 -0
  139. package/dist/doctor/local-mcp-probe.d.ts +3 -0
  140. package/dist/doctor/local-mcp-probe.d.ts.map +1 -0
  141. package/dist/doctor/local-mcp-probe.js +151 -0
  142. package/dist/doctor/local-mcp-probe.js.map +1 -0
  143. package/dist/doctor/opencode-config.d.ts +43 -0
  144. package/dist/doctor/opencode-config.d.ts.map +1 -0
  145. package/dist/doctor/opencode-config.js +103 -0
  146. package/dist/doctor/opencode-config.js.map +1 -0
  147. package/dist/doctor/run-harness-doctor.d.ts +23 -0
  148. package/dist/doctor/run-harness-doctor.d.ts.map +1 -0
  149. package/dist/doctor/run-harness-doctor.js +176 -0
  150. package/dist/doctor/run-harness-doctor.js.map +1 -0
  151. package/dist/doctor/types.d.ts +69 -0
  152. package/dist/doctor/types.d.ts.map +1 -0
  153. package/dist/doctor/types.js +8 -0
  154. package/dist/doctor/types.js.map +1 -0
  155. package/dist/domain/acceptance-criteria.d.ts +9 -0
  156. package/dist/domain/acceptance-criteria.d.ts.map +1 -0
  157. package/dist/domain/acceptance-criteria.js +38 -0
  158. package/dist/domain/acceptance-criteria.js.map +1 -0
  159. package/dist/domain/context-package.d.ts +43 -0
  160. package/dist/domain/context-package.d.ts.map +1 -0
  161. package/dist/domain/context-package.js +54 -0
  162. package/dist/domain/context-package.js.map +1 -0
  163. package/dist/domain/evidence.d.ts +1 -0
  164. package/dist/domain/evidence.d.ts.map +1 -1
  165. package/dist/domain/evidence.js +1 -2
  166. package/dist/domain/evidence.js.map +1 -1
  167. package/dist/domain/index.d.ts +12 -4
  168. package/dist/domain/index.d.ts.map +1 -1
  169. package/dist/domain/index.js +6 -2
  170. package/dist/domain/index.js.map +1 -1
  171. package/dist/domain/plan-artifacts.d.ts +170 -0
  172. package/dist/domain/plan-artifacts.d.ts.map +1 -0
  173. package/dist/domain/plan-artifacts.js +187 -0
  174. package/dist/domain/plan-artifacts.js.map +1 -0
  175. package/dist/domain/report.d.ts +608 -11
  176. package/dist/domain/report.d.ts.map +1 -1
  177. package/dist/domain/report.js +6 -4
  178. package/dist/domain/report.js.map +1 -1
  179. package/dist/domain/requirement.d.ts +22 -2
  180. package/dist/domain/requirement.d.ts.map +1 -1
  181. package/dist/domain/requirement.js +26 -3
  182. package/dist/domain/requirement.js.map +1 -1
  183. package/dist/domain/run-acceptance.d.ts +33 -0
  184. package/dist/domain/run-acceptance.d.ts.map +1 -0
  185. package/dist/domain/run-acceptance.js +29 -0
  186. package/dist/domain/run-acceptance.js.map +1 -0
  187. package/dist/domain/run.d.ts +596 -7
  188. package/dist/domain/run.d.ts.map +1 -1
  189. package/dist/domain/run.js +58 -0
  190. package/dist/domain/run.js.map +1 -1
  191. package/dist/domain/shared.d.ts +40 -2
  192. package/dist/domain/shared.d.ts.map +1 -1
  193. package/dist/domain/shared.js +26 -0
  194. package/dist/domain/shared.js.map +1 -1
  195. package/dist/domain/task-review.d.ts +57 -0
  196. package/dist/domain/task-review.d.ts.map +1 -0
  197. package/dist/domain/task-review.js +63 -0
  198. package/dist/domain/task-review.js.map +1 -0
  199. package/dist/domain/task.d.ts +24 -2
  200. package/dist/domain/task.d.ts.map +1 -1
  201. package/dist/domain/task.js +20 -12
  202. package/dist/domain/task.js.map +1 -1
  203. package/dist/index.d.ts +5 -0
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +5 -0
  206. package/dist/index.js.map +1 -1
  207. package/dist/plugin/create-harness-plugin.d.ts +4 -28
  208. package/dist/plugin/create-harness-plugin.d.ts.map +1 -1
  209. package/dist/plugin/create-harness-plugin.js +33 -118
  210. package/dist/plugin/create-harness-plugin.js.map +1 -1
  211. package/dist/plugin/harness-agent-config.d.ts +7 -0
  212. package/dist/plugin/harness-agent-config.d.ts.map +1 -1
  213. package/dist/plugin/harness-agent-config.js +72 -118
  214. package/dist/plugin/harness-agent-config.js.map +1 -1
  215. package/dist/plugin/harness-chat-hook.d.ts +1 -1
  216. package/dist/plugin/harness-chat-hook.d.ts.map +1 -1
  217. package/dist/plugin/harness-chat-hook.js +15 -23
  218. package/dist/plugin/harness-chat-hook.js.map +1 -1
  219. package/dist/plugin/harness-chat-protocol.d.ts +2 -2
  220. package/dist/plugin/harness-chat-protocol.d.ts.map +1 -1
  221. package/dist/plugin/harness-chat-protocol.js +13 -2
  222. package/dist/plugin/harness-chat-protocol.js.map +1 -1
  223. package/dist/plugin/harness-coordinator.d.ts +4 -0
  224. package/dist/plugin/harness-coordinator.d.ts.map +1 -1
  225. package/dist/plugin/harness-coordinator.js +7 -1
  226. package/dist/plugin/harness-coordinator.js.map +1 -1
  227. package/dist/plugin/harness-plugin-identifiers.d.ts +5 -0
  228. package/dist/plugin/harness-plugin-identifiers.d.ts.map +1 -0
  229. package/dist/plugin/harness-plugin-identifiers.js +24 -0
  230. package/dist/plugin/harness-plugin-identifiers.js.map +1 -0
  231. package/dist/plugin/harness-plugin-runtime.d.ts +64 -0
  232. package/dist/plugin/harness-plugin-runtime.d.ts.map +1 -0
  233. package/dist/plugin/harness-plugin-runtime.js +125 -0
  234. package/dist/plugin/harness-plugin-runtime.js.map +1 -0
  235. package/dist/plugin/harness-plugin-scheduler.d.ts +16 -0
  236. package/dist/plugin/harness-plugin-scheduler.d.ts.map +1 -0
  237. package/dist/plugin/harness-plugin-scheduler.js +51 -0
  238. package/dist/plugin/harness-plugin-scheduler.js.map +1 -0
  239. package/dist/plugin/harness-request-router.d.ts.map +1 -1
  240. package/dist/plugin/harness-request-router.js +14 -23
  241. package/dist/plugin/harness-request-router.js.map +1 -1
  242. package/dist/plugin/harness-requirement.d.ts +1 -1
  243. package/dist/plugin/harness-requirement.d.ts.map +1 -1
  244. package/dist/plugin/harness-requirement.js +2 -3
  245. package/dist/plugin/harness-requirement.js.map +1 -1
  246. package/dist/session/contracts.d.ts +9 -0
  247. package/dist/session/contracts.d.ts.map +1 -1
  248. package/dist/session/contracts.js.map +1 -1
  249. package/dist/session/fake-session-adapter.d.ts.map +1 -1
  250. package/dist/session/fake-session-adapter.js +1 -0
  251. package/dist/session/fake-session-adapter.js.map +1 -1
  252. package/dist/session/index.d.ts +1 -1
  253. package/dist/session/index.d.ts.map +1 -1
  254. package/dist/session/index.js.map +1 -1
  255. package/dist/session/opencode-session-adapter.d.ts +2 -1
  256. package/dist/session/opencode-session-adapter.d.ts.map +1 -1
  257. package/dist/session/opencode-session-adapter.js +7 -2
  258. package/dist/session/opencode-session-adapter.js.map +1 -1
  259. package/dist/session/opencode-session-prompts.d.ts +2 -10
  260. package/dist/session/opencode-session-prompts.d.ts.map +1 -1
  261. package/dist/session/opencode-session-prompts.js +7 -9
  262. package/dist/session/opencode-session-prompts.js.map +1 -1
  263. package/dist/store/run-event.d.ts +596 -7
  264. package/dist/store/run-event.d.ts.map +1 -1
  265. package/dist/tools/harness-research-tools.d.ts +22 -0
  266. package/dist/tools/harness-research-tools.d.ts.map +1 -1
  267. package/dist/tools/harness-research-tools.js +173 -64
  268. package/dist/tools/harness-research-tools.js.map +1 -1
  269. package/dist/tools/harness-tool-capabilities.d.ts +342 -0
  270. package/dist/tools/harness-tool-capabilities.d.ts.map +1 -0
  271. package/dist/tools/harness-tool-capabilities.js +170 -0
  272. package/dist/tools/harness-tool-capabilities.js.map +1 -0
  273. package/dist/verification/command-policy.d.ts.map +1 -1
  274. package/dist/verification/command-policy.js +2 -2
  275. package/dist/verification/command-policy.js.map +1 -1
  276. package/package.json +6 -1
@@ -1,19 +1,129 @@
1
1
  import { AgentResultSchema } from "../domain/index.js";
2
+ import { normalizeVerificationCommand } from "../verification/command-policy.js";
2
3
  import { VerificationExecutionStatus } from "../verification/index.js";
3
4
  import { createGitWorkspaceAdapter, createGitWorktreeAdapter } from "../workspace/index.js";
4
5
  import { createEvidence } from "./evidence-factory.js";
5
6
  import { resolveFailureAnalysis } from "./failure-analysis.js";
6
- import { createAcceptanceFailure, createContextGapFailure, createImplementationFailure, createMergeConflictFailure, createModelFailure, createScopeDriftFailure, createVerificationEnvironmentFailure, } from "./failure-factory.js";
7
+ import { createContextGapFailure, createImplementationFailure, createMergeConflictFailure, createModelFailure, createScopeDriftFailure, createVerificationEnvironmentFailure, } from "./failure-factory.js";
7
8
  import { orderTasks } from "./graph-validator.js";
8
9
  import { runRepairLoop } from "./repair-loop.js";
10
+ import { finalizeRunAcceptance } from "./run-acceptance.js";
9
11
  import { consumeBudget, parsePlannedRun, RunBudgetExceededError, withParts, withPlannedStatus, withTask, } from "./run-state.js";
10
- import { readAcceptanceOutput, readFailureAnalyzerOutput, readVerifierOutput, readWorkerOutput, } from "./task-agent-output.js";
12
+ import { readFailureAnalyzerOutput, readTaskReviewOutput, readWorkerOutput, } from "./task-agent-output.js";
11
13
  import { isAllowedPath } from "./task-paths.js";
12
14
  import { persistTaskFailed, persistTaskRetry } from "./task-retry.js";
13
15
  import { createWorktreeScheduler } from "./worktree-scheduler.js";
14
16
  export const createTaskExecutor = (input) => {
15
17
  const workspaceAdapter = input.options.workspaceAdapter ?? createGitWorkspaceAdapter(input.options.workingDirectory);
16
18
  const workspaceAdapterFactory = input.options.workspaceAdapterFactory ?? createGitWorkspaceAdapter;
19
+ const refreshRunBoundary = async (run) => {
20
+ const latest = await input.loadRun(run.runId);
21
+ if (!("taskGraph" in latest)) {
22
+ throw new TypeError(`run ${run.runId} lost its task graph during advancement`);
23
+ }
24
+ switch (latest.status) {
25
+ case "plan_ready":
26
+ case "executing":
27
+ case "verifying":
28
+ return parsePlannedRun(latest.status === "executing" ? latest : { ...latest, status: "executing" });
29
+ case "paused":
30
+ case "cancelled":
31
+ case "failed":
32
+ case "completed":
33
+ case "evidence_gap":
34
+ case "blocked":
35
+ return parsePlannedRun(latest);
36
+ default:
37
+ return assertNever(latest);
38
+ }
39
+ };
40
+ const runDiagnosticProbe = async (params) => {
41
+ try {
42
+ normalizeVerificationCommand({
43
+ workspaceRoot: input.options.workingDirectory,
44
+ command: params.probe.verificationCommand,
45
+ });
46
+ }
47
+ catch (error) {
48
+ if (!(error instanceof Error)) {
49
+ throw error;
50
+ }
51
+ return {
52
+ kind: "failed",
53
+ failure: createImplementationFailure({
54
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-policy`),
55
+ runId: params.run.runId,
56
+ taskId: params.task.taskId,
57
+ summary: "Failure analyzer proposed an invalid diagnostic probe.",
58
+ detail: error.message,
59
+ recoveryPlan: "Reject the probe and require a minimal read-only verification command.",
60
+ }),
61
+ };
62
+ }
63
+ await input.writer.persist(withPlannedStatus(params.run, "verifying"), input.writer.createEvent(params.run.runId, "task.diagnostic.probe.started", {
64
+ taskId: params.task.taskId,
65
+ attempt: params.attempt,
66
+ commandName: params.probe.verificationCommand.name,
67
+ }));
68
+ let verificationResult;
69
+ try {
70
+ verificationResult = await input.options.verificationRunner.run({
71
+ verificationCommands: [params.probe.verificationCommand],
72
+ defaultWorkingDirectory: input.options.workingDirectory,
73
+ });
74
+ }
75
+ catch (error) {
76
+ if (!(error instanceof Error)) {
77
+ throw error;
78
+ }
79
+ return {
80
+ kind: "failed",
81
+ failure: createVerificationEnvironmentFailure({
82
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-environment`),
83
+ runId: params.run.runId,
84
+ taskId: params.task.taskId,
85
+ commandName: params.probe.verificationCommand.name,
86
+ detail: error.message,
87
+ }),
88
+ };
89
+ }
90
+ if (verificationResult.records.length === 0) {
91
+ return {
92
+ kind: "failed",
93
+ failure: createContextGapFailure({
94
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-diagnostic-probe-empty`),
95
+ runId: params.run.runId,
96
+ taskId: params.task.taskId,
97
+ relatedEvidenceIds: [],
98
+ summary: "Diagnostic probe produced no verification records.",
99
+ detail: params.probe.summary,
100
+ recoveryPlan: "Capture a real read-only verification record before confirming the root cause.",
101
+ missingContext: ["diagnostic-probe-record"],
102
+ }),
103
+ };
104
+ }
105
+ const evidence = verificationResult.records.map((record, index) => createEvidence({
106
+ ids: input.options.ids,
107
+ runId: params.run.runId,
108
+ task: params.task,
109
+ record,
110
+ label: `${params.task.taskId}-${params.attempt}-diagnostic-probe-${index}`,
111
+ kind: "verification",
112
+ summary: `diagnostic-probe:${record.command.name}`,
113
+ }));
114
+ const nextRun = withParts(params.run, {
115
+ evidence: [...params.run.evidence, ...evidence],
116
+ failures: params.run.failures,
117
+ agentResults: params.run.agentResults,
118
+ workspace: params.run.workspace,
119
+ });
120
+ await input.writer.persist(withPlannedStatus(nextRun, "executing"), input.writer.createEvent(params.run.runId, "task.diagnostic.probe.completed", {
121
+ taskId: params.task.taskId,
122
+ attempt: params.attempt,
123
+ evidenceIds: evidence.map((item) => item.evidenceId),
124
+ }));
125
+ return { kind: "approved", evidence };
126
+ };
17
127
  const analyzeFailure = async (params) => {
18
128
  const analysisResult = await readFailureAnalyzerOutput({
19
129
  input,
@@ -50,6 +160,50 @@ export const createTaskExecutor = (input) => {
50
160
  evidence: params.evidence,
51
161
  analysis: analysisResult.output,
52
162
  });
163
+ if (analysisResult.output.action === "probe") {
164
+ const probeResult = await runDiagnosticProbe({
165
+ run: params.run,
166
+ task: params.task,
167
+ attempt: params.attempt,
168
+ probe: analysisResult.output.diagnosticProbe,
169
+ });
170
+ if (probeResult.kind === "failed") {
171
+ const failedRun = withParts(withTask(params.run, { ...params.task, status: "failed" }), {
172
+ evidence: params.run.evidence,
173
+ failures: [
174
+ ...params.run.failures,
175
+ params.failure,
176
+ resolution.failure,
177
+ probeResult.failure,
178
+ ],
179
+ agentResults: [...params.run.agentResults, resolution.result],
180
+ workspace: params.run.workspace,
181
+ });
182
+ await input.writer.persist(withPlannedStatus(failedRun, "failed"), input.writer.createEvent(params.run.runId, "task.failed", {
183
+ taskId: params.task.taskId,
184
+ attempt: params.attempt,
185
+ failureId: probeResult.failure.failureId,
186
+ }));
187
+ return {
188
+ run: withPlannedStatus(failedRun, "failed"),
189
+ repairRequested: false,
190
+ failure: probeResult.failure,
191
+ };
192
+ }
193
+ const probeRun = withParts(params.run, {
194
+ evidence: [...params.run.evidence, ...probeResult.evidence],
195
+ failures: params.run.failures,
196
+ agentResults: params.run.agentResults,
197
+ workspace: params.run.workspace,
198
+ });
199
+ return analyzeFailure({
200
+ run: probeRun,
201
+ task: params.task,
202
+ attempt: params.attempt,
203
+ failure: params.failure,
204
+ evidence: [...params.evidence, ...probeResult.evidence],
205
+ });
206
+ }
53
207
  const nextTask = { ...params.task, status: resolution.taskStatus };
54
208
  const nextRun = withParts(withTask(params.run, nextTask), {
55
209
  evidence: params.run.evidence,
@@ -64,13 +218,14 @@ export const createTaskExecutor = (input) => {
64
218
  failure: resolution.failure,
65
219
  };
66
220
  };
67
- const verifyAndAccept = async (params) => {
68
- const verifierOutput = await readVerifierOutput({
221
+ const reviewTask = async (params) => {
222
+ const verifierOutput = await readTaskReviewOutput({
69
223
  input,
70
224
  run: params.run,
71
225
  task: params.task,
72
226
  attempt: params.attempt,
73
227
  evidence: params.evidence,
228
+ changedPaths: params.changedPaths,
74
229
  });
75
230
  if (verifierOutput.kind === "failed") {
76
231
  const resolution = await analyzeFailure({
@@ -82,38 +237,6 @@ export const createTaskExecutor = (input) => {
82
237
  });
83
238
  return resolution.run;
84
239
  }
85
- if (verifierOutput.output.status !== "passed") {
86
- const verifierFailure = verifierOutput.output.status === "evidence_gap"
87
- ? createContextGapFailure({
88
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier-evidence-gap`),
89
- runId: params.run.runId,
90
- taskId: params.task.taskId,
91
- relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
92
- summary: verifierOutput.output.summary,
93
- detail: verifierOutput.output.missingEvidenceKinds.join(", "),
94
- recoveryPlan: "Collect the missing verification evidence before retrying.",
95
- missingContext: verifierOutput.output.missingEvidenceKinds,
96
- })
97
- : createImplementationFailure({
98
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier`),
99
- runId: params.run.runId,
100
- taskId: params.task.taskId,
101
- ...(params.evidence[0] === undefined
102
- ? {}
103
- : { failingEvidenceId: params.evidence[0].evidenceId }),
104
- summary: verifierOutput.output.summary,
105
- detail: verifierOutput.output.status,
106
- recoveryPlan: "Retry the task with fresh evidence.",
107
- });
108
- const resolution = await analyzeFailure({
109
- run: params.run,
110
- task: params.task,
111
- attempt: params.attempt,
112
- failure: verifierFailure,
113
- evidence: params.evidence,
114
- });
115
- return resolution.run;
116
- }
117
240
  const workerResult = AgentResultSchema.parse({
118
241
  schemaVersion: "1.0.0",
119
242
  resultId: input.options.ids.createAgentResultId(`worker-${params.task.taskId}-${params.attempt}`),
@@ -127,7 +250,7 @@ export const createTaskExecutor = (input) => {
127
250
  });
128
251
  const verifierResult = AgentResultSchema.parse({
129
252
  schemaVersion: "1.0.0",
130
- resultId: input.options.ids.createAgentResultId(`verifier-${params.task.taskId}-${params.attempt}`),
253
+ resultId: input.options.ids.createAgentResultId(`task-review-${params.task.taskId}-${params.attempt}`),
131
254
  runId: params.run.runId,
132
255
  taskId: params.task.taskId,
133
256
  role: "verifier",
@@ -136,71 +259,58 @@ export const createTaskExecutor = (input) => {
136
259
  evidenceIds: params.evidence.map((item) => item.evidenceId),
137
260
  changedPaths: [],
138
261
  });
139
- const acceptedRun = withParts(params.run, {
262
+ const reviewedRun = withParts(params.run, {
140
263
  evidence: params.run.evidence,
141
264
  failures: params.run.failures,
142
265
  agentResults: [...params.run.agentResults, workerResult, verifierResult],
143
266
  workspace: params.run.workspace,
144
267
  });
145
- const accepting = withPlannedStatus(acceptedRun, "verifying");
146
- await input.writer.persist(accepting, input.writer.createEvent(params.run.runId, "task.acceptance.started", {
268
+ const runWithTaskReview = parsePlannedRun({
269
+ ...reviewedRun,
270
+ taskReviews: [...reviewedRun.taskReviews, verifierOutput.output.taskReview],
271
+ });
272
+ const reviewing = withPlannedStatus(runWithTaskReview, "verifying");
273
+ await input.writer.persist(reviewing, input.writer.createEvent(params.run.runId, "task.review.started", {
147
274
  taskId: params.task.taskId,
148
275
  attempt: params.attempt,
149
276
  }));
150
- const acceptanceOutput = await readAcceptanceOutput({
151
- input,
152
- run: accepting,
153
- task: params.task,
154
- attempt: params.attempt,
155
- evidence: params.evidence,
156
- });
157
- if (acceptanceOutput.kind === "failed") {
158
- const resolution = await analyzeFailure({
159
- run: accepting,
160
- task: params.task,
161
- attempt: params.attempt,
162
- failure: acceptanceOutput.failure,
163
- evidence: params.evidence,
164
- });
165
- return resolution.run;
166
- }
167
- if (acceptanceOutput.output.status !== "accepted") {
168
- const acceptanceFailure = acceptanceOutput.output.status === "evidence_gap"
277
+ if (verifierOutput.output.status !== "passed") {
278
+ const taskReviewFailure = verifierOutput.output.status === "evidence_gap"
169
279
  ? createContextGapFailure({
170
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-acceptance-evidence-gap`),
280
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review-evidence-gap`),
171
281
  runId: params.run.runId,
172
282
  taskId: params.task.taskId,
173
283
  relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
174
- summary: acceptanceOutput.output.summary,
175
- detail: acceptanceOutput.output.missingEvidenceKinds.join(", "),
176
- recoveryPlan: "Collect the missing acceptance evidence before completing.",
177
- missingContext: acceptanceOutput.output.missingEvidenceKinds,
284
+ summary: verifierOutput.output.summary,
285
+ detail: verifierOutput.output.missingEvidenceKinds.join(", "),
286
+ recoveryPlan: "Collect the missing task review evidence before completing.",
287
+ missingContext: verifierOutput.output.missingEvidenceKinds,
178
288
  })
179
289
  : params.evidence[0] === undefined
180
290
  ? createContextGapFailure({
181
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-acceptance-missing-evidence`),
291
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review-missing-evidence`),
182
292
  runId: params.run.runId,
183
293
  taskId: params.task.taskId,
184
294
  relatedEvidenceIds: [],
185
- summary: acceptanceOutput.output.summary,
186
- detail: "Acceptance reported failed but no deterministic evidence exists.",
187
- recoveryPlan: "Capture real deterministic evidence before processing acceptance failure.",
188
- missingContext: ["acceptance-evidence"],
295
+ summary: verifierOutput.output.summary,
296
+ detail: "TaskReview reported failed but no deterministic evidence exists.",
297
+ recoveryPlan: "Capture real deterministic evidence before processing task review failure.",
298
+ missingContext: ["task-review-evidence"],
189
299
  })
190
- : createAcceptanceFailure({
191
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-acceptance`),
300
+ : createImplementationFailure({
301
+ failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-task-review`),
192
302
  runId: params.run.runId,
193
303
  taskId: params.task.taskId,
194
304
  failingEvidenceId: params.evidence[0].evidenceId,
195
- summary: acceptanceOutput.output.summary,
196
- detail: acceptanceOutput.output.status,
197
- recoveryPlan: "Address the acceptance findings before completing the task.",
305
+ summary: verifierOutput.output.summary,
306
+ detail: verifierOutput.output.taskReview?.summary ?? verifierOutput.output.status,
307
+ recoveryPlan: "Address the task review findings before completing the task.",
198
308
  });
199
309
  const resolution = await analyzeFailure({
200
- run: accepting,
310
+ run: reviewing,
201
311
  task: params.task,
202
312
  attempt: params.attempt,
203
- failure: acceptanceFailure,
313
+ failure: taskReviewFailure,
204
314
  evidence: params.evidence,
205
315
  });
206
316
  return resolution.run;
@@ -213,22 +323,11 @@ export const createTaskExecutor = (input) => {
213
323
  ...params.evidence.map((item) => item.evidenceId),
214
324
  ],
215
325
  };
216
- const acceptanceResult = AgentResultSchema.parse({
217
- schemaVersion: "1.0.0",
218
- resultId: input.options.ids.createAgentResultId(`acceptance-${params.task.taskId}-${params.attempt}`),
219
- runId: params.run.runId,
220
- taskId: params.task.taskId,
221
- role: "acceptance",
222
- status: "completed",
223
- summary: acceptanceOutput.output.summary,
224
- evidenceIds: params.evidence.map((item) => item.evidenceId),
225
- changedPaths: [],
226
- });
227
- const currentRun = withPlannedStatus(withParts(withTask(accepting, completedTask), {
228
- evidence: accepting.evidence,
229
- failures: accepting.failures,
230
- agentResults: [...accepting.agentResults, acceptanceResult],
231
- workspace: accepting.workspace,
326
+ const currentRun = withPlannedStatus(withParts(withTask(reviewing, completedTask), {
327
+ evidence: reviewing.evidence,
328
+ failures: reviewing.failures,
329
+ agentResults: reviewing.agentResults,
330
+ workspace: reviewing.workspace,
232
331
  }), "executing");
233
332
  await input.writer.persist(currentRun, input.writer.createEvent(params.run.runId, "task.completed", {
234
333
  taskId: params.task.taskId,
@@ -264,7 +363,7 @@ export const createTaskExecutor = (input) => {
264
363
  if (repaired.kind === "terminal") {
265
364
  return repaired.run;
266
365
  }
267
- return verifyAndAccept({
366
+ return reviewTask({
268
367
  run: repaired.run,
269
368
  task: params.task,
270
369
  attempt: params.attempt,
@@ -280,6 +379,10 @@ export const createTaskExecutor = (input) => {
280
379
  let currentRun = run;
281
380
  let lastFailure;
282
381
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
382
+ currentRun = await refreshRunBoundary(currentRun);
383
+ if (currentRun.status !== "executing") {
384
+ return currentRun;
385
+ }
283
386
  try {
284
387
  currentRun = claimTaskAttemptBudget(currentRun, attempt);
285
388
  }
@@ -307,6 +410,10 @@ export const createTaskExecutor = (input) => {
307
410
  attempt,
308
411
  workingDirectory: executionCwd,
309
412
  });
413
+ currentRun = await refreshRunBoundary(currentRun);
414
+ if (currentRun.status !== "executing") {
415
+ return currentRun;
416
+ }
310
417
  const workspaceAfterWorker = await taskWorkspaceAdapter.captureCurrentState();
311
418
  if (workerOutput.kind === "failed") {
312
419
  lastFailure = workerOutput.failure;
@@ -328,12 +435,16 @@ export const createTaskExecutor = (input) => {
328
435
  taskId: task.taskId,
329
436
  attempt,
330
437
  }));
438
+ const taskVerificationCommands = task.verificationPlan.filter((command) => command.scope !== "integration");
331
439
  let verificationResult;
332
440
  try {
333
- verificationResult = await input.options.verificationRunner.run({
334
- verificationCommands: task.verificationPlan,
335
- defaultWorkingDirectory: executionCwd,
336
- });
441
+ verificationResult =
442
+ taskVerificationCommands.length === 0
443
+ ? { records: [], stoppedEarly: false }
444
+ : await input.options.verificationRunner.run({
445
+ verificationCommands: taskVerificationCommands,
446
+ defaultWorkingDirectory: executionCwd,
447
+ });
337
448
  }
338
449
  catch (error) {
339
450
  if (!(error instanceof Error)) {
@@ -343,10 +454,14 @@ export const createTaskExecutor = (input) => {
343
454
  failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-environment`),
344
455
  runId: run.runId,
345
456
  taskId: task.taskId,
346
- commandName: task.verificationPlan[0]?.name ?? "verification",
457
+ commandName: taskVerificationCommands[0]?.name ?? "verification",
347
458
  detail: error.message,
348
459
  });
349
460
  }
461
+ currentRun = await refreshRunBoundary(currentRun);
462
+ if (currentRun.status !== "executing") {
463
+ return currentRun;
464
+ }
350
465
  const workspaceAfterVerification = await taskWorkspaceAdapter.captureCurrentState();
351
466
  if (currentRun.workspace.git.mode === "git") {
352
467
  const workspaceAssessment = await taskWorkspaceAdapter.assessTaskChanges({
@@ -417,7 +532,7 @@ export const createTaskExecutor = (input) => {
417
532
  });
418
533
  }
419
534
  }
420
- else if (verificationResult.records.length === 0) {
535
+ else if (verificationResult.records.length === 0 && taskVerificationCommands.length > 0) {
421
536
  lastFailure = createContextGapFailure({
422
537
  failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-empty`),
423
538
  runId: run.runId,
@@ -456,7 +571,7 @@ export const createTaskExecutor = (input) => {
456
571
  record,
457
572
  label: `${task.taskId}-${attempt}-${index}`,
458
573
  changedPaths: workerOutput.output.changedPaths,
459
- acceptanceCriterionIds: paramsAcceptanceCriterionIds(run),
574
+ acceptanceCriterionIds: [],
460
575
  }));
461
576
  currentRun = withParts(currentRun, {
462
577
  evidence: [...currentRun.evidence, ...evidence],
@@ -496,12 +611,15 @@ export const createTaskExecutor = (input) => {
496
611
  }
497
612
  }
498
613
  else {
499
- const finalized = await verifyAndAccept({
614
+ const reconciledChangedPaths = currentRun.workspace.git.mode === "git"
615
+ ? currentRun.workspace.git.harnessChangedPaths.filter((path) => task.allowedPaths.some((allowedPath) => path === allowedPath || path.startsWith(`${allowedPath}/`)))
616
+ : workerOutput.output.changedPaths;
617
+ const finalized = await reviewTask({
500
618
  run: currentRun,
501
619
  task,
502
620
  attempt,
503
621
  evidence,
504
- changedPaths: workerOutput.output.changedPaths,
622
+ changedPaths: reconciledChangedPaths,
505
623
  });
506
624
  if (finalized.status !== "executing") {
507
625
  return finalized;
@@ -564,10 +682,89 @@ export const createTaskExecutor = (input) => {
564
682
  return currentRun;
565
683
  }
566
684
  }
567
- const completed = withPlannedStatus(currentRun, "completed");
568
- await input.writer.persist(completed, input.writer.createEvent(completed.runId, "run.completed", { status: "completed" }));
685
+ currentRun = await runIntegrationVerification(currentRun);
686
+ const runAcceptanceResult = await finalizeRunAcceptance({
687
+ options: input.options,
688
+ runtime: input.runtime,
689
+ run: currentRun,
690
+ });
691
+ const completed = withPlannedStatus(withParts(parsePlannedRun({
692
+ ...currentRun,
693
+ runAcceptance: runAcceptanceResult.runAcceptance,
694
+ }), {
695
+ evidence: currentRun.evidence,
696
+ failures: runAcceptanceResult.failure === undefined
697
+ ? currentRun.failures
698
+ : [...currentRun.failures, runAcceptanceResult.failure],
699
+ agentResults: runAcceptanceResult.agentResult === undefined
700
+ ? currentRun.agentResults
701
+ : [...currentRun.agentResults, runAcceptanceResult.agentResult],
702
+ workspace: currentRun.workspace,
703
+ }), runAcceptanceResult.status);
704
+ await input.writer.persist(completed, input.writer.createEvent(completed.runId, "run.completed", { status: completed.status }));
569
705
  return completed;
570
706
  };
707
+ const runIntegrationVerification = async (run) => {
708
+ const commands = run.taskGraph.tasks.flatMap((task) => task.verificationPlan.filter((command) => command.scope === "integration"));
709
+ if (commands.length === 0)
710
+ return run;
711
+ const task = run.taskGraph.tasks.at(-1);
712
+ if (task === undefined)
713
+ return run;
714
+ try {
715
+ const result = await input.options.verificationRunner.run({
716
+ verificationCommands: commands,
717
+ defaultWorkingDirectory: input.options.workingDirectory,
718
+ });
719
+ if (result.records.length === 0 ||
720
+ result.records.some((record) => record.status !== VerificationExecutionStatus.passed)) {
721
+ return persistIntegrationVerificationFailure(run, task, "integration verification failed");
722
+ }
723
+ const evidence = result.records.map((record, index) => createEvidence({
724
+ ids: input.options.ids,
725
+ runId: run.runId,
726
+ task,
727
+ record,
728
+ label: `integration-${task.taskId}-${index}`,
729
+ changedPaths: [],
730
+ acceptanceCriterionIds: [],
731
+ }));
732
+ const verified = withParts(run, {
733
+ evidence: [...run.evidence, ...evidence],
734
+ failures: run.failures,
735
+ agentResults: run.agentResults,
736
+ workspace: run.workspace,
737
+ });
738
+ await input.writer.persist(verified, input.writer.createEvent(run.runId, "run.integration.verified", {
739
+ evidenceIds: evidence.map((item) => item.evidenceId),
740
+ }));
741
+ return verified;
742
+ }
743
+ catch (error) {
744
+ if (!(error instanceof Error))
745
+ throw error;
746
+ return persistIntegrationVerificationFailure(run, task, error.message);
747
+ }
748
+ };
749
+ const persistIntegrationVerificationFailure = async (run, task, detail) => {
750
+ const failure = createVerificationEnvironmentFailure({
751
+ failureId: input.options.ids.createFailureId(`${run.runId}-integration`),
752
+ runId: run.runId,
753
+ taskId: task.taskId,
754
+ commandName: "integration verification",
755
+ detail,
756
+ });
757
+ const nextRun = withParts(run, {
758
+ evidence: run.evidence,
759
+ failures: [...run.failures, failure],
760
+ agentResults: run.agentResults,
761
+ workspace: run.workspace,
762
+ });
763
+ await input.writer.persist(nextRun, input.writer.createEvent(run.runId, "run.integration.failed", {
764
+ failureId: failure.failureId,
765
+ }));
766
+ return nextRun;
767
+ };
571
768
  return { runTasks };
572
769
  async function runParallelReadyBatch(run, orderedTasks) {
573
770
  if (run.workspace.git.mode !== "git") {
@@ -719,6 +916,9 @@ export const createTaskExecutor = (input) => {
719
916
  return paused;
720
917
  }
721
918
  };
919
+ const assertNever = (value) => {
920
+ throw new TypeError(`Unexpected run state: ${JSON.stringify(value)}`);
921
+ };
722
922
  const uniqueById = (items, getId) => {
723
923
  const seen = new Set();
724
924
  const unique = [];
@@ -747,5 +947,4 @@ const claimTaskAttemptBudget = (run, attempt) => {
747
947
  }
748
948
  return parsePlannedRun(consumeBudget(consumedOverallBudget, "repair"));
749
949
  };
750
- const paramsAcceptanceCriterionIds = (run) => run.requirement.acceptanceCriteria.map((_criterion, index) => `${run.requirement.requirementId}-ac-${index + 1}`);
751
950
  //# sourceMappingURL=task-executor.js.map