harness-engineering-agent 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +146 -60
  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 -55
  67. package/dist/controller/agent-session.d.ts.map +1 -1
  68. package/dist/controller/agent-session.js +82 -129
  69. package/dist/controller/agent-session.js.map +1 -1
  70. package/dist/controller/contracts.d.ts +3 -2
  71. package/dist/controller/contracts.d.ts.map +1 -1
  72. package/dist/controller/contracts.js.map +1 -1
  73. package/dist/controller/evidence-factory.js +7 -1
  74. package/dist/controller/evidence-factory.js.map +1 -1
  75. package/dist/controller/failure-analysis.d.ts +12 -0
  76. package/dist/controller/failure-analysis.d.ts.map +1 -1
  77. package/dist/controller/failure-analysis.js +41 -0
  78. package/dist/controller/failure-analysis.js.map +1 -1
  79. package/dist/controller/failure-analyzer-schemas.d.ts +87 -0
  80. package/dist/controller/failure-analyzer-schemas.d.ts.map +1 -0
  81. package/dist/controller/failure-analyzer-schemas.js +117 -0
  82. package/dist/controller/failure-analyzer-schemas.js.map +1 -0
  83. package/dist/controller/graph-validator.js +18 -4
  84. package/dist/controller/graph-validator.js.map +1 -1
  85. package/dist/controller/index.d.ts +7 -2
  86. package/dist/controller/index.d.ts.map +1 -1
  87. package/dist/controller/index.js +4 -1
  88. package/dist/controller/index.js.map +1 -1
  89. package/dist/controller/repair-loop.d.ts +1 -1
  90. package/dist/controller/repair-loop.d.ts.map +1 -1
  91. package/dist/controller/repair-loop.js +28 -0
  92. package/dist/controller/repair-loop.js.map +1 -1
  93. package/dist/controller/report-factory.d.ts.map +1 -1
  94. package/dist/controller/report-factory.js +49 -21
  95. package/dist/controller/report-factory.js.map +1 -1
  96. package/dist/controller/role-prompts.d.ts +2 -1
  97. package/dist/controller/role-prompts.d.ts.map +1 -1
  98. package/dist/controller/role-prompts.js +3 -9
  99. package/dist/controller/role-prompts.js.map +1 -1
  100. package/dist/controller/run-acceptance.d.ts +17 -0
  101. package/dist/controller/run-acceptance.d.ts.map +1 -0
  102. package/dist/controller/run-acceptance.js +179 -0
  103. package/dist/controller/run-acceptance.js.map +1 -0
  104. package/dist/controller/run-controller.d.ts.map +1 -1
  105. package/dist/controller/run-controller.js +244 -22
  106. package/dist/controller/run-controller.js.map +1 -1
  107. package/dist/controller/session-tool-authorization.d.ts +14 -0
  108. package/dist/controller/session-tool-authorization.d.ts.map +1 -0
  109. package/dist/controller/session-tool-authorization.js +88 -0
  110. package/dist/controller/session-tool-authorization.js.map +1 -0
  111. package/dist/controller/task-agent-output.d.ts +13 -2
  112. package/dist/controller/task-agent-output.d.ts.map +1 -1
  113. package/dist/controller/task-agent-output.js +58 -1
  114. package/dist/controller/task-agent-output.js.map +1 -1
  115. package/dist/controller/task-agent-schemas.d.ts +745 -26
  116. package/dist/controller/task-agent-schemas.d.ts.map +1 -1
  117. package/dist/controller/task-agent-schemas.js +70 -21
  118. package/dist/controller/task-agent-schemas.js.map +1 -1
  119. package/dist/controller/task-executor.d.ts +1 -1
  120. package/dist/controller/task-executor.d.ts.map +1 -1
  121. package/dist/controller/task-executor.js +269 -105
  122. package/dist/controller/task-executor.js.map +1 -1
  123. package/dist/doctor/cli.d.ts +3 -0
  124. package/dist/doctor/cli.d.ts.map +1 -0
  125. package/dist/doctor/cli.js +10 -0
  126. package/dist/doctor/cli.js.map +1 -0
  127. package/dist/doctor/index.d.ts +7 -0
  128. package/dist/doctor/index.d.ts.map +1 -0
  129. package/dist/doctor/index.js +16 -0
  130. package/dist/doctor/index.js.map +1 -0
  131. package/dist/doctor/local-mcp-probe.d.ts +3 -0
  132. package/dist/doctor/local-mcp-probe.d.ts.map +1 -0
  133. package/dist/doctor/local-mcp-probe.js +151 -0
  134. package/dist/doctor/local-mcp-probe.js.map +1 -0
  135. package/dist/doctor/opencode-config.d.ts +43 -0
  136. package/dist/doctor/opencode-config.d.ts.map +1 -0
  137. package/dist/doctor/opencode-config.js +103 -0
  138. package/dist/doctor/opencode-config.js.map +1 -0
  139. package/dist/doctor/run-harness-doctor.d.ts +23 -0
  140. package/dist/doctor/run-harness-doctor.d.ts.map +1 -0
  141. package/dist/doctor/run-harness-doctor.js +176 -0
  142. package/dist/doctor/run-harness-doctor.js.map +1 -0
  143. package/dist/doctor/types.d.ts +69 -0
  144. package/dist/doctor/types.d.ts.map +1 -0
  145. package/dist/doctor/types.js +8 -0
  146. package/dist/doctor/types.js.map +1 -0
  147. package/dist/domain/acceptance-criteria.d.ts +9 -0
  148. package/dist/domain/acceptance-criteria.d.ts.map +1 -0
  149. package/dist/domain/acceptance-criteria.js +38 -0
  150. package/dist/domain/acceptance-criteria.js.map +1 -0
  151. package/dist/domain/context-package.d.ts +43 -0
  152. package/dist/domain/context-package.d.ts.map +1 -0
  153. package/dist/domain/context-package.js +54 -0
  154. package/dist/domain/context-package.js.map +1 -0
  155. package/dist/domain/evidence.d.ts +1 -0
  156. package/dist/domain/evidence.d.ts.map +1 -1
  157. package/dist/domain/evidence.js +1 -2
  158. package/dist/domain/evidence.js.map +1 -1
  159. package/dist/domain/index.d.ts +14 -4
  160. package/dist/domain/index.d.ts.map +1 -1
  161. package/dist/domain/index.js +7 -2
  162. package/dist/domain/index.js.map +1 -1
  163. package/dist/domain/plan-artifacts.d.ts +170 -0
  164. package/dist/domain/plan-artifacts.d.ts.map +1 -0
  165. package/dist/domain/plan-artifacts.js +187 -0
  166. package/dist/domain/plan-artifacts.js.map +1 -0
  167. package/dist/domain/project-context.d.ts +10 -0
  168. package/dist/domain/project-context.d.ts.map +1 -0
  169. package/dist/domain/project-context.js +11 -0
  170. package/dist/domain/project-context.js.map +1 -0
  171. package/dist/domain/report.d.ts +608 -11
  172. package/dist/domain/report.d.ts.map +1 -1
  173. package/dist/domain/report.js +6 -4
  174. package/dist/domain/report.js.map +1 -1
  175. package/dist/domain/requirement.d.ts +22 -2
  176. package/dist/domain/requirement.d.ts.map +1 -1
  177. package/dist/domain/requirement.js +26 -3
  178. package/dist/domain/requirement.js.map +1 -1
  179. package/dist/domain/run-acceptance.d.ts +33 -0
  180. package/dist/domain/run-acceptance.d.ts.map +1 -0
  181. package/dist/domain/run-acceptance.js +29 -0
  182. package/dist/domain/run-acceptance.js.map +1 -0
  183. package/dist/domain/run.d.ts +596 -7
  184. package/dist/domain/run.d.ts.map +1 -1
  185. package/dist/domain/run.js +58 -0
  186. package/dist/domain/run.js.map +1 -1
  187. package/dist/domain/shared.d.ts +40 -2
  188. package/dist/domain/shared.d.ts.map +1 -1
  189. package/dist/domain/shared.js +26 -0
  190. package/dist/domain/shared.js.map +1 -1
  191. package/dist/domain/task-review.d.ts +57 -0
  192. package/dist/domain/task-review.d.ts.map +1 -0
  193. package/dist/domain/task-review.js +63 -0
  194. package/dist/domain/task-review.js.map +1 -0
  195. package/dist/domain/task.d.ts +24 -2
  196. package/dist/domain/task.d.ts.map +1 -1
  197. package/dist/domain/task.js +20 -12
  198. package/dist/domain/task.js.map +1 -1
  199. package/dist/index.d.ts +5 -0
  200. package/dist/index.d.ts.map +1 -1
  201. package/dist/index.js +5 -0
  202. package/dist/index.js.map +1 -1
  203. package/dist/plugin/create-harness-plugin.d.ts +4 -28
  204. package/dist/plugin/create-harness-plugin.d.ts.map +1 -1
  205. package/dist/plugin/create-harness-plugin.js +33 -166
  206. package/dist/plugin/create-harness-plugin.js.map +1 -1
  207. package/dist/plugin/harness-agent-config.d.ts +7 -0
  208. package/dist/plugin/harness-agent-config.d.ts.map +1 -1
  209. package/dist/plugin/harness-agent-config.js +72 -118
  210. package/dist/plugin/harness-agent-config.js.map +1 -1
  211. package/dist/plugin/harness-chat-protocol.d.ts.map +1 -1
  212. package/dist/plugin/harness-chat-protocol.js +29 -6
  213. package/dist/plugin/harness-chat-protocol.js.map +1 -1
  214. package/dist/plugin/harness-plugin-identifiers.d.ts +5 -0
  215. package/dist/plugin/harness-plugin-identifiers.d.ts.map +1 -0
  216. package/dist/plugin/harness-plugin-identifiers.js +24 -0
  217. package/dist/plugin/harness-plugin-identifiers.js.map +1 -0
  218. package/dist/plugin/harness-plugin-runtime.d.ts +64 -0
  219. package/dist/plugin/harness-plugin-runtime.d.ts.map +1 -0
  220. package/dist/plugin/harness-plugin-runtime.js +125 -0
  221. package/dist/plugin/harness-plugin-runtime.js.map +1 -0
  222. package/dist/plugin/harness-plugin-scheduler.d.ts +16 -0
  223. package/dist/plugin/harness-plugin-scheduler.d.ts.map +1 -0
  224. package/dist/plugin/harness-plugin-scheduler.js +51 -0
  225. package/dist/plugin/harness-plugin-scheduler.js.map +1 -0
  226. package/dist/plugin/harness-requirement.d.ts +1 -1
  227. package/dist/plugin/harness-requirement.d.ts.map +1 -1
  228. package/dist/plugin/harness-requirement.js +2 -3
  229. package/dist/plugin/harness-requirement.js.map +1 -1
  230. package/dist/session/contracts.d.ts +9 -0
  231. package/dist/session/contracts.d.ts.map +1 -1
  232. package/dist/session/contracts.js.map +1 -1
  233. package/dist/session/fake-session-adapter.d.ts.map +1 -1
  234. package/dist/session/fake-session-adapter.js +1 -0
  235. package/dist/session/fake-session-adapter.js.map +1 -1
  236. package/dist/session/index.d.ts +1 -1
  237. package/dist/session/index.d.ts.map +1 -1
  238. package/dist/session/index.js.map +1 -1
  239. package/dist/session/opencode-session-adapter.d.ts +2 -1
  240. package/dist/session/opencode-session-adapter.d.ts.map +1 -1
  241. package/dist/session/opencode-session-adapter.js +7 -2
  242. package/dist/session/opencode-session-adapter.js.map +1 -1
  243. package/dist/session/opencode-session-prompts.d.ts +2 -10
  244. package/dist/session/opencode-session-prompts.d.ts.map +1 -1
  245. package/dist/session/opencode-session-prompts.js +7 -9
  246. package/dist/session/opencode-session-prompts.js.map +1 -1
  247. package/dist/store/run-event.d.ts +596 -7
  248. package/dist/store/run-event.d.ts.map +1 -1
  249. package/dist/tools/harness-research-tools.d.ts +22 -0
  250. package/dist/tools/harness-research-tools.d.ts.map +1 -1
  251. package/dist/tools/harness-research-tools.js +173 -64
  252. package/dist/tools/harness-research-tools.js.map +1 -1
  253. package/dist/tools/harness-tool-capabilities.d.ts +342 -0
  254. package/dist/tools/harness-tool-capabilities.d.ts.map +1 -0
  255. package/dist/tools/harness-tool-capabilities.js +170 -0
  256. package/dist/tools/harness-tool-capabilities.js.map +1 -0
  257. package/dist/verification/command-policy.d.ts.map +1 -1
  258. package/dist/verification/command-policy.js +2 -2
  259. package/dist/verification/command-policy.js.map +1 -1
  260. package/dist/workspace/collect-project-context.d.ts +3 -0
  261. package/dist/workspace/collect-project-context.d.ts.map +1 -0
  262. package/dist/workspace/collect-project-context.js +92 -0
  263. package/dist/workspace/collect-project-context.js.map +1 -0
  264. package/dist/workspace/index.d.ts +1 -0
  265. package/dist/workspace/index.d.ts.map +1 -1
  266. package/dist/workspace/index.js +1 -0
  267. package/dist/workspace/index.js.map +1 -1
  268. package/package.json +6 -1
@@ -1,13 +1,15 @@
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";
@@ -29,11 +31,99 @@ export const createTaskExecutor = (input) => {
29
31
  case "failed":
30
32
  case "completed":
31
33
  case "evidence_gap":
34
+ case "blocked":
32
35
  return parsePlannedRun(latest);
33
36
  default:
34
37
  return assertNever(latest);
35
38
  }
36
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
+ };
37
127
  const analyzeFailure = async (params) => {
38
128
  const analysisResult = await readFailureAnalyzerOutput({
39
129
  input,
@@ -70,6 +160,50 @@ export const createTaskExecutor = (input) => {
70
160
  evidence: params.evidence,
71
161
  analysis: analysisResult.output,
72
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
+ }
73
207
  const nextTask = { ...params.task, status: resolution.taskStatus };
74
208
  const nextRun = withParts(withTask(params.run, nextTask), {
75
209
  evidence: params.run.evidence,
@@ -84,13 +218,14 @@ export const createTaskExecutor = (input) => {
84
218
  failure: resolution.failure,
85
219
  };
86
220
  };
87
- const verifyAndAccept = async (params) => {
88
- const verifierOutput = await readVerifierOutput({
221
+ const reviewTask = async (params) => {
222
+ const verifierOutput = await readTaskReviewOutput({
89
223
  input,
90
224
  run: params.run,
91
225
  task: params.task,
92
226
  attempt: params.attempt,
93
227
  evidence: params.evidence,
228
+ changedPaths: params.changedPaths,
94
229
  });
95
230
  if (verifierOutput.kind === "failed") {
96
231
  const resolution = await analyzeFailure({
@@ -102,38 +237,6 @@ export const createTaskExecutor = (input) => {
102
237
  });
103
238
  return resolution.run;
104
239
  }
105
- if (verifierOutput.output.status !== "passed") {
106
- const verifierFailure = verifierOutput.output.status === "evidence_gap"
107
- ? createContextGapFailure({
108
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier-evidence-gap`),
109
- runId: params.run.runId,
110
- taskId: params.task.taskId,
111
- relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
112
- summary: verifierOutput.output.summary,
113
- detail: verifierOutput.output.missingEvidenceKinds.join(", "),
114
- recoveryPlan: "Collect the missing verification evidence before retrying.",
115
- missingContext: verifierOutput.output.missingEvidenceKinds,
116
- })
117
- : createImplementationFailure({
118
- failureId: input.options.ids.createFailureId(`${params.task.taskId}-${params.attempt}-verifier`),
119
- runId: params.run.runId,
120
- taskId: params.task.taskId,
121
- ...(params.evidence[0] === undefined
122
- ? {}
123
- : { failingEvidenceId: params.evidence[0].evidenceId }),
124
- summary: verifierOutput.output.summary,
125
- detail: verifierOutput.output.status,
126
- recoveryPlan: "Retry the task with fresh evidence.",
127
- });
128
- const resolution = await analyzeFailure({
129
- run: params.run,
130
- task: params.task,
131
- attempt: params.attempt,
132
- failure: verifierFailure,
133
- evidence: params.evidence,
134
- });
135
- return resolution.run;
136
- }
137
240
  const workerResult = AgentResultSchema.parse({
138
241
  schemaVersion: "1.0.0",
139
242
  resultId: input.options.ids.createAgentResultId(`worker-${params.task.taskId}-${params.attempt}`),
@@ -147,7 +250,7 @@ export const createTaskExecutor = (input) => {
147
250
  });
148
251
  const verifierResult = AgentResultSchema.parse({
149
252
  schemaVersion: "1.0.0",
150
- resultId: input.options.ids.createAgentResultId(`verifier-${params.task.taskId}-${params.attempt}`),
253
+ resultId: input.options.ids.createAgentResultId(`task-review-${params.task.taskId}-${params.attempt}`),
151
254
  runId: params.run.runId,
152
255
  taskId: params.task.taskId,
153
256
  role: "verifier",
@@ -156,71 +259,58 @@ export const createTaskExecutor = (input) => {
156
259
  evidenceIds: params.evidence.map((item) => item.evidenceId),
157
260
  changedPaths: [],
158
261
  });
159
- const acceptedRun = withParts(params.run, {
262
+ const reviewedRun = withParts(params.run, {
160
263
  evidence: params.run.evidence,
161
264
  failures: params.run.failures,
162
265
  agentResults: [...params.run.agentResults, workerResult, verifierResult],
163
266
  workspace: params.run.workspace,
164
267
  });
165
- const accepting = withPlannedStatus(acceptedRun, "verifying");
166
- 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", {
167
274
  taskId: params.task.taskId,
168
275
  attempt: params.attempt,
169
276
  }));
170
- const acceptanceOutput = await readAcceptanceOutput({
171
- input,
172
- run: accepting,
173
- task: params.task,
174
- attempt: params.attempt,
175
- evidence: params.evidence,
176
- });
177
- if (acceptanceOutput.kind === "failed") {
178
- const resolution = await analyzeFailure({
179
- run: accepting,
180
- task: params.task,
181
- attempt: params.attempt,
182
- failure: acceptanceOutput.failure,
183
- evidence: params.evidence,
184
- });
185
- return resolution.run;
186
- }
187
- if (acceptanceOutput.output.status !== "accepted") {
188
- const acceptanceFailure = acceptanceOutput.output.status === "evidence_gap"
277
+ if (verifierOutput.output.status !== "passed") {
278
+ const taskReviewFailure = verifierOutput.output.status === "evidence_gap"
189
279
  ? createContextGapFailure({
190
- 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`),
191
281
  runId: params.run.runId,
192
282
  taskId: params.task.taskId,
193
283
  relatedEvidenceIds: params.evidence.map((item) => item.evidenceId),
194
- summary: acceptanceOutput.output.summary,
195
- detail: acceptanceOutput.output.missingEvidenceKinds.join(", "),
196
- recoveryPlan: "Collect the missing acceptance evidence before completing.",
197
- 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,
198
288
  })
199
289
  : params.evidence[0] === undefined
200
290
  ? createContextGapFailure({
201
- 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`),
202
292
  runId: params.run.runId,
203
293
  taskId: params.task.taskId,
204
294
  relatedEvidenceIds: [],
205
- summary: acceptanceOutput.output.summary,
206
- detail: "Acceptance reported failed but no deterministic evidence exists.",
207
- recoveryPlan: "Capture real deterministic evidence before processing acceptance failure.",
208
- 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"],
209
299
  })
210
- : createAcceptanceFailure({
211
- 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`),
212
302
  runId: params.run.runId,
213
303
  taskId: params.task.taskId,
214
304
  failingEvidenceId: params.evidence[0].evidenceId,
215
- summary: acceptanceOutput.output.summary,
216
- detail: acceptanceOutput.output.status,
217
- 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.",
218
308
  });
219
309
  const resolution = await analyzeFailure({
220
- run: accepting,
310
+ run: reviewing,
221
311
  task: params.task,
222
312
  attempt: params.attempt,
223
- failure: acceptanceFailure,
313
+ failure: taskReviewFailure,
224
314
  evidence: params.evidence,
225
315
  });
226
316
  return resolution.run;
@@ -233,22 +323,11 @@ export const createTaskExecutor = (input) => {
233
323
  ...params.evidence.map((item) => item.evidenceId),
234
324
  ],
235
325
  };
236
- const acceptanceResult = AgentResultSchema.parse({
237
- schemaVersion: "1.0.0",
238
- resultId: input.options.ids.createAgentResultId(`acceptance-${params.task.taskId}-${params.attempt}`),
239
- runId: params.run.runId,
240
- taskId: params.task.taskId,
241
- role: "acceptance",
242
- status: "completed",
243
- summary: acceptanceOutput.output.summary,
244
- evidenceIds: params.evidence.map((item) => item.evidenceId),
245
- changedPaths: [],
246
- });
247
- const currentRun = withPlannedStatus(withParts(withTask(accepting, completedTask), {
248
- evidence: accepting.evidence,
249
- failures: accepting.failures,
250
- agentResults: [...accepting.agentResults, acceptanceResult],
251
- 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,
252
331
  }), "executing");
253
332
  await input.writer.persist(currentRun, input.writer.createEvent(params.run.runId, "task.completed", {
254
333
  taskId: params.task.taskId,
@@ -284,7 +363,7 @@ export const createTaskExecutor = (input) => {
284
363
  if (repaired.kind === "terminal") {
285
364
  return repaired.run;
286
365
  }
287
- return verifyAndAccept({
366
+ return reviewTask({
288
367
  run: repaired.run,
289
368
  task: params.task,
290
369
  attempt: params.attempt,
@@ -356,12 +435,16 @@ export const createTaskExecutor = (input) => {
356
435
  taskId: task.taskId,
357
436
  attempt,
358
437
  }));
438
+ const taskVerificationCommands = task.verificationPlan.filter((command) => command.scope !== "integration");
359
439
  let verificationResult;
360
440
  try {
361
- verificationResult = await input.options.verificationRunner.run({
362
- verificationCommands: task.verificationPlan,
363
- defaultWorkingDirectory: executionCwd,
364
- });
441
+ verificationResult =
442
+ taskVerificationCommands.length === 0
443
+ ? { records: [], stoppedEarly: false }
444
+ : await input.options.verificationRunner.run({
445
+ verificationCommands: taskVerificationCommands,
446
+ defaultWorkingDirectory: executionCwd,
447
+ });
365
448
  }
366
449
  catch (error) {
367
450
  if (!(error instanceof Error)) {
@@ -371,7 +454,7 @@ export const createTaskExecutor = (input) => {
371
454
  failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-environment`),
372
455
  runId: run.runId,
373
456
  taskId: task.taskId,
374
- commandName: task.verificationPlan[0]?.name ?? "verification",
457
+ commandName: taskVerificationCommands[0]?.name ?? "verification",
375
458
  detail: error.message,
376
459
  });
377
460
  }
@@ -449,7 +532,7 @@ export const createTaskExecutor = (input) => {
449
532
  });
450
533
  }
451
534
  }
452
- else if (verificationResult.records.length === 0) {
535
+ else if (verificationResult.records.length === 0 && taskVerificationCommands.length > 0) {
453
536
  lastFailure = createContextGapFailure({
454
537
  failureId: input.options.ids.createFailureId(`${task.taskId}-${attempt}-verification-empty`),
455
538
  runId: run.runId,
@@ -488,7 +571,7 @@ export const createTaskExecutor = (input) => {
488
571
  record,
489
572
  label: `${task.taskId}-${attempt}-${index}`,
490
573
  changedPaths: workerOutput.output.changedPaths,
491
- acceptanceCriterionIds: paramsAcceptanceCriterionIds(run),
574
+ acceptanceCriterionIds: [],
492
575
  }));
493
576
  currentRun = withParts(currentRun, {
494
577
  evidence: [...currentRun.evidence, ...evidence],
@@ -528,12 +611,15 @@ export const createTaskExecutor = (input) => {
528
611
  }
529
612
  }
530
613
  else {
531
- 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({
532
618
  run: currentRun,
533
619
  task,
534
620
  attempt,
535
621
  evidence,
536
- changedPaths: workerOutput.output.changedPaths,
622
+ changedPaths: reconciledChangedPaths,
537
623
  });
538
624
  if (finalized.status !== "executing") {
539
625
  return finalized;
@@ -596,10 +682,89 @@ export const createTaskExecutor = (input) => {
596
682
  return currentRun;
597
683
  }
598
684
  }
599
- const completed = withPlannedStatus(currentRun, "completed");
600
- 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 }));
601
705
  return completed;
602
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
+ };
603
768
  return { runTasks };
604
769
  async function runParallelReadyBatch(run, orderedTasks) {
605
770
  if (run.workspace.git.mode !== "git") {
@@ -782,5 +947,4 @@ const claimTaskAttemptBudget = (run, attempt) => {
782
947
  }
783
948
  return parsePlannedRun(consumeBudget(consumedOverallBudget, "repair"));
784
949
  };
785
- const paramsAcceptanceCriterionIds = (run) => run.requirement.acceptanceCriteria.map((_criterion, index) => `${run.requirement.requirementId}-ac-${index + 1}`);
786
950
  //# sourceMappingURL=task-executor.js.map