harness-engineering-agent 0.1.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 (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/dist/config/config-defaults.d.ts +32 -0
  4. package/dist/config/config-defaults.d.ts.map +1 -0
  5. package/dist/config/config-defaults.js +32 -0
  6. package/dist/config/config-defaults.js.map +1 -0
  7. package/dist/config/config-errors.d.ts +7 -0
  8. package/dist/config/config-errors.d.ts.map +1 -0
  9. package/dist/config/config-errors.js +11 -0
  10. package/dist/config/config-errors.js.map +1 -0
  11. package/dist/config/config-file.d.ts +3 -0
  12. package/dist/config/config-file.d.ts.map +1 -0
  13. package/dist/config/config-file.js +31 -0
  14. package/dist/config/config-file.js.map +1 -0
  15. package/dist/config/config-merge.d.ts +8 -0
  16. package/dist/config/config-merge.d.ts.map +1 -0
  17. package/dist/config/config-merge.js +50 -0
  18. package/dist/config/config-merge.js.map +1 -0
  19. package/dist/config/config-schema.d.ts +135 -0
  20. package/dist/config/config-schema.d.ts.map +1 -0
  21. package/dist/config/config-schema.js +94 -0
  22. package/dist/config/config-schema.js.map +1 -0
  23. package/dist/config/config-types.d.ts +21 -0
  24. package/dist/config/config-types.d.ts.map +1 -0
  25. package/dist/config/config-types.js +2 -0
  26. package/dist/config/config-types.js.map +1 -0
  27. package/dist/config/harness-config.d.ts +6 -0
  28. package/dist/config/harness-config.d.ts.map +1 -0
  29. package/dist/config/harness-config.js +4 -0
  30. package/dist/config/harness-config.js.map +1 -0
  31. package/dist/config/index.d.ts +2 -0
  32. package/dist/config/index.d.ts.map +1 -0
  33. package/dist/config/index.js +2 -0
  34. package/dist/config/index.js.map +1 -0
  35. package/dist/config/load-harness-config.d.ts +9 -0
  36. package/dist/config/load-harness-config.d.ts.map +1 -0
  37. package/dist/config/load-harness-config.js +25 -0
  38. package/dist/config/load-harness-config.js.map +1 -0
  39. package/dist/controller/agent-output.d.ts +21 -0
  40. package/dist/controller/agent-output.d.ts.map +1 -0
  41. package/dist/controller/agent-output.js +75 -0
  42. package/dist/controller/agent-output.js.map +1 -0
  43. package/dist/controller/agent-session.d.ts +49 -0
  44. package/dist/controller/agent-session.d.ts.map +1 -0
  45. package/dist/controller/agent-session.js +220 -0
  46. package/dist/controller/agent-session.js.map +1 -0
  47. package/dist/controller/contracts.d.ts +65 -0
  48. package/dist/controller/contracts.d.ts.map +1 -0
  49. package/dist/controller/contracts.js +2 -0
  50. package/dist/controller/contracts.js.map +1 -0
  51. package/dist/controller/errors.d.ts +23 -0
  52. package/dist/controller/errors.d.ts.map +1 -0
  53. package/dist/controller/errors.js +37 -0
  54. package/dist/controller/errors.js.map +1 -0
  55. package/dist/controller/evidence-factory.d.ts +15 -0
  56. package/dist/controller/evidence-factory.d.ts.map +1 -0
  57. package/dist/controller/evidence-factory.js +38 -0
  58. package/dist/controller/evidence-factory.js.map +1 -0
  59. package/dist/controller/failure-analysis.d.ts +36 -0
  60. package/dist/controller/failure-analysis.d.ts.map +1 -0
  61. package/dist/controller/failure-analysis.js +175 -0
  62. package/dist/controller/failure-analysis.js.map +1 -0
  63. package/dist/controller/failure-factory.d.ts +85 -0
  64. package/dist/controller/failure-factory.d.ts.map +1 -0
  65. package/dist/controller/failure-factory.js +124 -0
  66. package/dist/controller/failure-factory.js.map +1 -0
  67. package/dist/controller/graph-validator.d.ts +4 -0
  68. package/dist/controller/graph-validator.d.ts.map +1 -0
  69. package/dist/controller/graph-validator.js +102 -0
  70. package/dist/controller/graph-validator.js.map +1 -0
  71. package/dist/controller/index.d.ts +15 -0
  72. package/dist/controller/index.d.ts.map +1 -0
  73. package/dist/controller/index.js +11 -0
  74. package/dist/controller/index.js.map +1 -0
  75. package/dist/controller/repair-loop.d.ts +42 -0
  76. package/dist/controller/repair-loop.d.ts.map +1 -0
  77. package/dist/controller/repair-loop.js +385 -0
  78. package/dist/controller/repair-loop.js.map +1 -0
  79. package/dist/controller/report-factory.d.ts +4 -0
  80. package/dist/controller/report-factory.d.ts.map +1 -0
  81. package/dist/controller/report-factory.js +107 -0
  82. package/dist/controller/report-factory.js.map +1 -0
  83. package/dist/controller/role-prompts.d.ts +8 -0
  84. package/dist/controller/role-prompts.d.ts.map +1 -0
  85. package/dist/controller/role-prompts.js +35 -0
  86. package/dist/controller/role-prompts.js.map +1 -0
  87. package/dist/controller/run-controller.d.ts +3 -0
  88. package/dist/controller/run-controller.d.ts.map +1 -0
  89. package/dist/controller/run-controller.js +291 -0
  90. package/dist/controller/run-controller.js.map +1 -0
  91. package/dist/controller/run-persistence.d.ts +15 -0
  92. package/dist/controller/run-persistence.d.ts.map +1 -0
  93. package/dist/controller/run-persistence.js +83 -0
  94. package/dist/controller/run-persistence.js.map +1 -0
  95. package/dist/controller/run-state.d.ts +61 -0
  96. package/dist/controller/run-state.d.ts.map +1 -0
  97. package/dist/controller/run-state.js +151 -0
  98. package/dist/controller/run-state.js.map +1 -0
  99. package/dist/controller/task-agent-output.d.ts +70 -0
  100. package/dist/controller/task-agent-output.d.ts.map +1 -0
  101. package/dist/controller/task-agent-output.js +256 -0
  102. package/dist/controller/task-agent-output.js.map +1 -0
  103. package/dist/controller/task-agent-schemas.d.ts +217 -0
  104. package/dist/controller/task-agent-schemas.d.ts.map +1 -0
  105. package/dist/controller/task-agent-schemas.js +171 -0
  106. package/dist/controller/task-agent-schemas.js.map +1 -0
  107. package/dist/controller/task-executor.d.ts +15 -0
  108. package/dist/controller/task-executor.d.ts.map +1 -0
  109. package/dist/controller/task-executor.js +751 -0
  110. package/dist/controller/task-executor.js.map +1 -0
  111. package/dist/controller/task-paths.d.ts +3 -0
  112. package/dist/controller/task-paths.d.ts.map +1 -0
  113. package/dist/controller/task-paths.js +20 -0
  114. package/dist/controller/task-paths.js.map +1 -0
  115. package/dist/controller/task-retry.d.ts +24 -0
  116. package/dist/controller/task-retry.d.ts.map +1 -0
  117. package/dist/controller/task-retry.js +42 -0
  118. package/dist/controller/task-retry.js.map +1 -0
  119. package/dist/controller/worktree-eligibility.d.ts +15 -0
  120. package/dist/controller/worktree-eligibility.d.ts.map +1 -0
  121. package/dist/controller/worktree-eligibility.js +38 -0
  122. package/dist/controller/worktree-eligibility.js.map +1 -0
  123. package/dist/controller/worktree-scheduler.d.ts +72 -0
  124. package/dist/controller/worktree-scheduler.d.ts.map +1 -0
  125. package/dist/controller/worktree-scheduler.js +142 -0
  126. package/dist/controller/worktree-scheduler.js.map +1 -0
  127. package/dist/domain/agent-result.d.ts +83 -0
  128. package/dist/domain/agent-result.d.ts.map +1 -0
  129. package/dist/domain/agent-result.js +44 -0
  130. package/dist/domain/agent-result.js.map +1 -0
  131. package/dist/domain/evidence.d.ts +97 -0
  132. package/dist/domain/evidence.d.ts.map +1 -0
  133. package/dist/domain/evidence.js +85 -0
  134. package/dist/domain/evidence.js.map +1 -0
  135. package/dist/domain/failure.d.ts +121 -0
  136. package/dist/domain/failure.d.ts.map +1 -0
  137. package/dist/domain/failure.js +72 -0
  138. package/dist/domain/failure.js.map +1 -0
  139. package/dist/domain/index.d.ts +19 -0
  140. package/dist/domain/index.d.ts.map +1 -0
  141. package/dist/domain/index.js +10 -0
  142. package/dist/domain/index.js.map +1 -0
  143. package/dist/domain/report.d.ts +904 -0
  144. package/dist/domain/report.d.ts.map +1 -0
  145. package/dist/domain/report.js +90 -0
  146. package/dist/domain/report.js.map +1 -0
  147. package/dist/domain/requirement.d.ts +10 -0
  148. package/dist/domain/requirement.d.ts.map +1 -0
  149. package/dist/domain/requirement.js +12 -0
  150. package/dist/domain/requirement.js.map +1 -0
  151. package/dist/domain/run.d.ts +857 -0
  152. package/dist/domain/run.d.ts.map +1 -0
  153. package/dist/domain/run.js +129 -0
  154. package/dist/domain/run.js.map +1 -0
  155. package/dist/domain/shared.d.ts +60 -0
  156. package/dist/domain/shared.d.ts.map +1 -0
  157. package/dist/domain/shared.js +66 -0
  158. package/dist/domain/shared.js.map +1 -0
  159. package/dist/domain/task.d.ts +316 -0
  160. package/dist/domain/task.d.ts.map +1 -0
  161. package/dist/domain/task.js +116 -0
  162. package/dist/domain/task.js.map +1 -0
  163. package/dist/index.d.ts +15 -0
  164. package/dist/index.d.ts.map +1 -0
  165. package/dist/index.js +15 -0
  166. package/dist/index.js.map +1 -0
  167. package/dist/path/workspace-path.d.ts +6 -0
  168. package/dist/path/workspace-path.d.ts.map +1 -0
  169. package/dist/path/workspace-path.js +36 -0
  170. package/dist/path/workspace-path.js.map +1 -0
  171. package/dist/plugin/create-harness-plugin.d.ts +40 -0
  172. package/dist/plugin/create-harness-plugin.d.ts.map +1 -0
  173. package/dist/plugin/create-harness-plugin.js +169 -0
  174. package/dist/plugin/create-harness-plugin.js.map +1 -0
  175. package/dist/plugin/harness-agent-config.d.ts +6 -0
  176. package/dist/plugin/harness-agent-config.d.ts.map +1 -0
  177. package/dist/plugin/harness-agent-config.js +130 -0
  178. package/dist/plugin/harness-agent-config.js.map +1 -0
  179. package/dist/plugin/harness-chat-hook.d.ts +27 -0
  180. package/dist/plugin/harness-chat-hook.d.ts.map +1 -0
  181. package/dist/plugin/harness-chat-hook.js +72 -0
  182. package/dist/plugin/harness-chat-hook.js.map +1 -0
  183. package/dist/plugin/harness-chat-parts.d.ts +10 -0
  184. package/dist/plugin/harness-chat-parts.d.ts.map +1 -0
  185. package/dist/plugin/harness-chat-parts.js +36 -0
  186. package/dist/plugin/harness-chat-parts.js.map +1 -0
  187. package/dist/plugin/harness-chat-protocol.d.ts +9 -0
  188. package/dist/plugin/harness-chat-protocol.d.ts.map +1 -0
  189. package/dist/plugin/harness-chat-protocol.js +23 -0
  190. package/dist/plugin/harness-chat-protocol.js.map +1 -0
  191. package/dist/plugin/harness-coordinator.d.ts +33 -0
  192. package/dist/plugin/harness-coordinator.d.ts.map +1 -0
  193. package/dist/plugin/harness-coordinator.js +188 -0
  194. package/dist/plugin/harness-coordinator.js.map +1 -0
  195. package/dist/plugin/harness-intake-prompt.d.ts +2 -0
  196. package/dist/plugin/harness-intake-prompt.d.ts.map +1 -0
  197. package/dist/plugin/harness-intake-prompt.js +52 -0
  198. package/dist/plugin/harness-intake-prompt.js.map +1 -0
  199. package/dist/plugin/harness-intent.d.ts +72 -0
  200. package/dist/plugin/harness-intent.d.ts.map +1 -0
  201. package/dist/plugin/harness-intent.js +82 -0
  202. package/dist/plugin/harness-intent.js.map +1 -0
  203. package/dist/plugin/harness-parent-session-dispatcher.d.ts +46 -0
  204. package/dist/plugin/harness-parent-session-dispatcher.d.ts.map +1 -0
  205. package/dist/plugin/harness-parent-session-dispatcher.js +33 -0
  206. package/dist/plugin/harness-parent-session-dispatcher.js.map +1 -0
  207. package/dist/plugin/harness-requirement.d.ts +4 -0
  208. package/dist/plugin/harness-requirement.d.ts.map +1 -0
  209. package/dist/plugin/harness-requirement.js +37 -0
  210. package/dist/plugin/harness-requirement.js.map +1 -0
  211. package/dist/session/contracts.d.ts +178 -0
  212. package/dist/session/contracts.d.ts.map +1 -0
  213. package/dist/session/contracts.js +28 -0
  214. package/dist/session/contracts.js.map +1 -0
  215. package/dist/session/fake-session-adapter.d.ts +22 -0
  216. package/dist/session/fake-session-adapter.d.ts.map +1 -0
  217. package/dist/session/fake-session-adapter.js +238 -0
  218. package/dist/session/fake-session-adapter.js.map +1 -0
  219. package/dist/session/fake-session-errors.d.ts +23 -0
  220. package/dist/session/fake-session-errors.d.ts.map +1 -0
  221. package/dist/session/fake-session-errors.js +37 -0
  222. package/dist/session/fake-session-errors.js.map +1 -0
  223. package/dist/session/harness-agent-names.d.ts +51 -0
  224. package/dist/session/harness-agent-names.d.ts.map +1 -0
  225. package/dist/session/harness-agent-names.js +98 -0
  226. package/dist/session/harness-agent-names.js.map +1 -0
  227. package/dist/session/index.d.ts +9 -0
  228. package/dist/session/index.d.ts.map +1 -0
  229. package/dist/session/index.js +9 -0
  230. package/dist/session/index.js.map +1 -0
  231. package/dist/session/opencode-session-adapter.d.ts +9 -0
  232. package/dist/session/opencode-session-adapter.d.ts.map +1 -0
  233. package/dist/session/opencode-session-adapter.js +243 -0
  234. package/dist/session/opencode-session-adapter.js.map +1 -0
  235. package/dist/session/opencode-session-client.d.ts +58 -0
  236. package/dist/session/opencode-session-client.d.ts.map +1 -0
  237. package/dist/session/opencode-session-client.js +17 -0
  238. package/dist/session/opencode-session-client.js.map +1 -0
  239. package/dist/session/opencode-session-errors.d.ts +15 -0
  240. package/dist/session/opencode-session-errors.d.ts.map +1 -0
  241. package/dist/session/opencode-session-errors.js +19 -0
  242. package/dist/session/opencode-session-errors.js.map +1 -0
  243. package/dist/session/opencode-session-prompts.d.ts +12 -0
  244. package/dist/session/opencode-session-prompts.d.ts.map +1 -0
  245. package/dist/session/opencode-session-prompts.js +16 -0
  246. package/dist/session/opencode-session-prompts.js.map +1 -0
  247. package/dist/store/filesystem-run-store-io.d.ts +9 -0
  248. package/dist/store/filesystem-run-store-io.d.ts.map +1 -0
  249. package/dist/store/filesystem-run-store-io.js +85 -0
  250. package/dist/store/filesystem-run-store-io.js.map +1 -0
  251. package/dist/store/filesystem-run-store.d.ts +16 -0
  252. package/dist/store/filesystem-run-store.d.ts.map +1 -0
  253. package/dist/store/filesystem-run-store.js +286 -0
  254. package/dist/store/filesystem-run-store.js.map +1 -0
  255. package/dist/store/index.d.ts +5 -0
  256. package/dist/store/index.d.ts.map +1 -0
  257. package/dist/store/index.js +4 -0
  258. package/dist/store/index.js.map +1 -0
  259. package/dist/store/run-event.d.ts +786 -0
  260. package/dist/store/run-event.d.ts.map +1 -0
  261. package/dist/store/run-event.js +24 -0
  262. package/dist/store/run-event.js.map +1 -0
  263. package/dist/store/run-store-errors.d.ts +38 -0
  264. package/dist/store/run-store-errors.d.ts.map +1 -0
  265. package/dist/store/run-store-errors.js +62 -0
  266. package/dist/store/run-store-errors.js.map +1 -0
  267. package/dist/tools/context7-client.d.ts +22 -0
  268. package/dist/tools/context7-client.d.ts.map +1 -0
  269. package/dist/tools/context7-client.js +108 -0
  270. package/dist/tools/context7-client.js.map +1 -0
  271. package/dist/tools/grep-app-client.d.ts +21 -0
  272. package/dist/tools/grep-app-client.d.ts.map +1 -0
  273. package/dist/tools/grep-app-client.js +136 -0
  274. package/dist/tools/grep-app-client.js.map +1 -0
  275. package/dist/tools/harness-research-tools.d.ts +21 -0
  276. package/dist/tools/harness-research-tools.d.ts.map +1 -0
  277. package/dist/tools/harness-research-tools.js +101 -0
  278. package/dist/tools/harness-research-tools.js.map +1 -0
  279. package/dist/tools/lsp-client.d.ts +32 -0
  280. package/dist/tools/lsp-client.d.ts.map +1 -0
  281. package/dist/tools/lsp-client.js +234 -0
  282. package/dist/tools/lsp-client.js.map +1 -0
  283. package/dist/tools/lsp-json-rpc.d.ts +13 -0
  284. package/dist/tools/lsp-json-rpc.d.ts.map +1 -0
  285. package/dist/tools/lsp-json-rpc.js +98 -0
  286. package/dist/tools/lsp-json-rpc.js.map +1 -0
  287. package/dist/verification/command-policy.d.ts +11 -0
  288. package/dist/verification/command-policy.d.ts.map +1 -0
  289. package/dist/verification/command-policy.js +262 -0
  290. package/dist/verification/command-policy.js.map +1 -0
  291. package/dist/verification/contracts.d.ts +82 -0
  292. package/dist/verification/contracts.d.ts.map +1 -0
  293. package/dist/verification/contracts.js +6 -0
  294. package/dist/verification/contracts.js.map +1 -0
  295. package/dist/verification/fake-process-runner.d.ts +16 -0
  296. package/dist/verification/fake-process-runner.d.ts.map +1 -0
  297. package/dist/verification/fake-process-runner.js +28 -0
  298. package/dist/verification/fake-process-runner.js.map +1 -0
  299. package/dist/verification/index.d.ts +6 -0
  300. package/dist/verification/index.d.ts.map +1 -0
  301. package/dist/verification/index.js +5 -0
  302. package/dist/verification/index.js.map +1 -0
  303. package/dist/verification/node-process-runner.d.ts +12 -0
  304. package/dist/verification/node-process-runner.d.ts.map +1 -0
  305. package/dist/verification/node-process-runner.js +103 -0
  306. package/dist/verification/node-process-runner.js.map +1 -0
  307. package/dist/verification/verification-runner.d.ts +3 -0
  308. package/dist/verification/verification-runner.d.ts.map +1 -0
  309. package/dist/verification/verification-runner.js +101 -0
  310. package/dist/verification/verification-runner.js.map +1 -0
  311. package/dist/workspace/git-baseline.d.ts +63 -0
  312. package/dist/workspace/git-baseline.d.ts.map +1 -0
  313. package/dist/workspace/git-baseline.js +53 -0
  314. package/dist/workspace/git-baseline.js.map +1 -0
  315. package/dist/workspace/git-workspace-adapter.d.ts +43 -0
  316. package/dist/workspace/git-workspace-adapter.d.ts.map +1 -0
  317. package/dist/workspace/git-workspace-adapter.js +279 -0
  318. package/dist/workspace/git-workspace-adapter.js.map +1 -0
  319. package/dist/workspace/git-worktree-adapter.d.ts +45 -0
  320. package/dist/workspace/git-worktree-adapter.d.ts.map +1 -0
  321. package/dist/workspace/git-worktree-adapter.js +104 -0
  322. package/dist/workspace/git-worktree-adapter.js.map +1 -0
  323. package/dist/workspace/index.d.ts +7 -0
  324. package/dist/workspace/index.d.ts.map +1 -0
  325. package/dist/workspace/index.js +4 -0
  326. package/dist/workspace/index.js.map +1 -0
  327. package/package.json +45 -0
@@ -0,0 +1,291 @@
1
+ import { RequirementSchema, RunSchema, TaskGraphSchema, } from "../domain/index.js";
2
+ import { HARNESS_SESSION_ROLE } from "../session/index.js";
3
+ import { createGitWorkspaceAdapter } from "../workspace/index.js";
4
+ import { parseAgentJson } from "./agent-output.js";
5
+ import { createAgentSessionRuntime } from "./agent-session.js";
6
+ import { AgentOutputParseError, AgentRunFailedError, GraphValidationError, RunCancellationError, } from "./errors.js";
7
+ import { validateTaskGraph } from "./graph-validator.js";
8
+ import { createReport } from "./report-factory.js";
9
+ import { plannerTaskPrompt } from "./role-prompts.js";
10
+ import { createRunPersistence } from "./run-persistence.js";
11
+ import { appendAnswer, appendWaiver, canAnswer, canCancel, canPause, canWaive, consumeBudget, createBlockedQuestionId, createInitialRunBudgets, createInitialRunGovernance, hasAnswer, hasWaiver, isTerminalRunStatus, parsePlannedRun, RunBudgetExceededError, requireTransition, requireWaivableRequirement, setPaused, withGovernance, withStatus, } from "./run-state.js";
12
+ import { createTaskExecutor } from "./task-executor.js";
13
+ export const createRunController = (options) => {
14
+ const workspacePolicy = options.workspacePolicy ?? { allowDirty: false };
15
+ const workspaceAdapter = options.workspaceAdapter ?? createGitWorkspaceAdapter(options.workingDirectory);
16
+ const writer = createRunPersistence(options);
17
+ const runtime = createAgentSessionRuntime({
18
+ sessionAdapter: options.sessionAdapter,
19
+ ids: options.ids,
20
+ store: options.store,
21
+ workingDirectory: options.workingDirectory,
22
+ });
23
+ const { runTasks } = createTaskExecutor({
24
+ options,
25
+ runtime,
26
+ writer,
27
+ });
28
+ const requestPlan = async (run, requirement) => {
29
+ const maxPlannerAttempts = run.budgets.planner.limit;
30
+ let planningRun = run;
31
+ let lastError;
32
+ for (let attempt = 1; attempt <= maxPlannerAttempts; attempt += 1) {
33
+ try {
34
+ planningRun = consumeBudget(planningRun, "planner");
35
+ planningRun = consumeBudget(planningRun, "overall");
36
+ const output = await runtime.sendAgent({
37
+ runId: planningRun.runId,
38
+ role: HARNESS_SESSION_ROLE.planner,
39
+ title: requirement.title,
40
+ brief: plannerTaskPrompt({ requirement, runId: planningRun.runId }),
41
+ constraints: [
42
+ "只允许根据 requirement 生成任务图。",
43
+ "不得执行任务或请求父会话完整历史。",
44
+ "只输出符合 TaskGraph 契约的 JSON。",
45
+ ],
46
+ evidence: [],
47
+ outputContract: {
48
+ schemaVersion: "1.0.0",
49
+ type: "TaskGraph",
50
+ requiredFields: ["schemaVersion", "graphId", "runId", "version", "tasks", "edges"],
51
+ },
52
+ messageLabel: `planner-${planningRun.runId}-${attempt}`,
53
+ });
54
+ return parsePlannerGraph(output);
55
+ }
56
+ catch (error) {
57
+ if (error instanceof RunBudgetExceededError) {
58
+ throw error;
59
+ }
60
+ if (!(error instanceof AgentRunFailedError || error instanceof AgentOutputParseError)) {
61
+ throw error;
62
+ }
63
+ lastError = error;
64
+ if (attempt < maxPlannerAttempts) {
65
+ const planning = withStatus(planningRun, "planning");
66
+ await writer.persist(planning, writer.createEvent(planningRun.runId, "run.planning.retrying", { attempt }));
67
+ }
68
+ }
69
+ }
70
+ if (lastError === undefined) {
71
+ throw new AgentRunFailedError("planner", "retry loop completed without a result");
72
+ }
73
+ throw lastError;
74
+ };
75
+ const loadRunWithRetry = async (runId) => {
76
+ for (let attempt = 0; attempt < 3; attempt += 1) {
77
+ try {
78
+ return await options.store.loadState(runId);
79
+ }
80
+ catch (error) {
81
+ if (!isMissingRunError(error, runId) || attempt === 2) {
82
+ throw error;
83
+ }
84
+ await waitForNextTurn();
85
+ }
86
+ }
87
+ throw new TypeError(`missing run ${runId}`);
88
+ };
89
+ return {
90
+ async start(input) {
91
+ const requirement = RequirementSchema.parse({ schemaVersion: "1.0.0", ...input });
92
+ const created = RunSchema.parse({
93
+ schemaVersion: "1.0.0",
94
+ runId: options.ids.createRunId(),
95
+ status: "created",
96
+ requirement,
97
+ evidence: [],
98
+ failures: [],
99
+ agentResults: [],
100
+ budgets: createInitialRunBudgets(options.maxRunAttempts),
101
+ governance: createInitialRunGovernance(),
102
+ workspace: { git: await workspaceAdapter.captureBaseline(workspacePolicy) },
103
+ });
104
+ await writer.persist(created, writer.createEvent(created.runId, "run.created", { status: "created" }));
105
+ if (created.workspace.git.mode === "non-git") {
106
+ const blocked = withStatus(withGovernance(created, {
107
+ ...created.governance,
108
+ blockingQuestionId: createBlockedQuestionId(created),
109
+ }), "clarification_required");
110
+ await writer.persist(blocked, writer.createEvent(created.runId, "run.blocked.non_git", {
111
+ reason: "implementation requires a git workspace baseline",
112
+ blockingQuestionId: blocked.governance.blockingQuestionId,
113
+ }));
114
+ return blocked;
115
+ }
116
+ if (!workspacePolicy.allowDirty && created.workspace.git.initialDirtyPaths.length > 0) {
117
+ const blocked = withStatus(withGovernance(created, {
118
+ ...created.governance,
119
+ blockingQuestionId: createBlockedQuestionId(created),
120
+ }), "clarification_required");
121
+ await writer.persist(blocked, writer.createEvent(created.runId, "run.blocked.dirty_workspace", {
122
+ dirtyPaths: created.workspace.git.initialDirtyPaths,
123
+ blockingQuestionId: blocked.governance.blockingQuestionId,
124
+ }));
125
+ return blocked;
126
+ }
127
+ const planning = withStatus(created, "planning");
128
+ await writer.persist(planning, writer.createEvent(created.runId, "run.planning", { status: "planning" }));
129
+ try {
130
+ const graph = await requestPlan(created, requirement);
131
+ validateTaskGraph(graph, requirement, created.runId);
132
+ const executing = parsePlannedRun({ ...planning, status: "executing", taskGraph: graph });
133
+ await writer.persist(executing, writer.createEvent(created.runId, "run.executing", { status: "executing" }));
134
+ return await runTasks(executing);
135
+ }
136
+ catch (error) {
137
+ if (error instanceof GraphValidationError ||
138
+ error instanceof AgentRunFailedError ||
139
+ error instanceof AgentOutputParseError ||
140
+ error instanceof RunBudgetExceededError) {
141
+ const failed = withStatus(withGovernance(planning, {
142
+ ...planning.governance,
143
+ blockingQuestionId: error instanceof RunBudgetExceededError ? createBlockedQuestionId(planning) : null,
144
+ }), error instanceof RunBudgetExceededError ? "paused" : "failed");
145
+ await writer.persist(failed, writer.createEvent(created.runId, error instanceof RunBudgetExceededError ? "run.paused" : "run.failed", {
146
+ reason: error.message,
147
+ ...(error instanceof RunBudgetExceededError
148
+ ? {
149
+ budget: error.budget,
150
+ blockingQuestionId: failed.governance.blockingQuestionId,
151
+ }
152
+ : {}),
153
+ }));
154
+ if (error instanceof RunBudgetExceededError) {
155
+ return failed;
156
+ }
157
+ }
158
+ if (error instanceof RunCancellationError) {
159
+ const latest = await options.store.loadState(created.runId);
160
+ if (latest.status === "cancelled") {
161
+ return latest;
162
+ }
163
+ const cancelled = withStatus(latest, "cancelled");
164
+ await writer.persist(cancelled, writer.createEvent(created.runId, "run.cancelled", { status: "cancelled" }));
165
+ return cancelled;
166
+ }
167
+ throw error;
168
+ }
169
+ },
170
+ async status(runId) {
171
+ return loadRunWithRetry(runId);
172
+ },
173
+ async pause(input) {
174
+ const current = await loadRunWithRetry(input.runId);
175
+ if (current.status === "paused") {
176
+ return current;
177
+ }
178
+ if (isTerminalRunStatus(current)) {
179
+ return current;
180
+ }
181
+ requireTransition(current, "pause", canPause);
182
+ await runtime.abortActiveSession(input.runId);
183
+ const pausedAt = options.clock.now().toISOString();
184
+ const paused = withStatus(setPaused(current, {
185
+ pauseId: options.ids.createEventId(`pause-${input.runId}`),
186
+ actor: input.actor,
187
+ reason: input.reason,
188
+ pausedAt,
189
+ }), "paused");
190
+ await writer.persist(paused, writer.createEvent(input.runId, "run.paused", {
191
+ pauseId: paused.governance.paused?.pauseId ?? null,
192
+ actor: input.actor,
193
+ reason: input.reason,
194
+ }));
195
+ return paused;
196
+ },
197
+ async answer(input) {
198
+ const current = await loadRunWithRetry(input.runId);
199
+ if (hasAnswer(current, input.questionId)) {
200
+ return current;
201
+ }
202
+ requireTransition(current, "answer", canAnswer);
203
+ const answeredAt = options.clock.now().toISOString();
204
+ const updated = withStatus(appendAnswer(current, {
205
+ answerId: options.ids.createEventId(`answer-${input.questionId}`),
206
+ questionId: input.questionId,
207
+ answer: input.answer,
208
+ actor: input.actor,
209
+ answeredAt,
210
+ }), "planning");
211
+ await writer.persist(updated, writer.createEvent(input.runId, "run.answered", {
212
+ answerId: updated.governance.answers.at(-1)?.answerId ?? null,
213
+ questionId: input.questionId,
214
+ actor: input.actor,
215
+ }));
216
+ return updated;
217
+ },
218
+ async resume(runId) {
219
+ const run = await loadRunWithRetry(runId);
220
+ switch (run.status) {
221
+ case "completed":
222
+ case "cancelled":
223
+ case "failed":
224
+ return run;
225
+ case "created":
226
+ case "analyzing":
227
+ case "planning":
228
+ case "clarification_required":
229
+ return run;
230
+ case "plan_ready":
231
+ case "executing":
232
+ case "verifying":
233
+ case "paused":
234
+ if (runtime.hasActiveSession(runId)) {
235
+ return run;
236
+ }
237
+ return "taskGraph" in run ? await runTasks(parsePlannedRun(setPaused(run, null))) : run;
238
+ default:
239
+ return run;
240
+ }
241
+ },
242
+ async cancel(runId) {
243
+ const current = await loadRunWithRetry(runId);
244
+ if (current.status === "completed" ||
245
+ current.status === "cancelled" ||
246
+ current.status === "failed") {
247
+ return current;
248
+ }
249
+ requireTransition(current, "cancel", canCancel);
250
+ await runtime.abortActiveSession(runId);
251
+ const latest = await loadRunWithRetry(runId);
252
+ if (latest.status === "completed" ||
253
+ latest.status === "cancelled" ||
254
+ latest.status === "failed") {
255
+ return latest;
256
+ }
257
+ const cancelled = withStatus(latest, "cancelled");
258
+ await writer.persist(cancelled, writer.createEvent(runId, "run.cancelled", { status: "cancelled" }));
259
+ return cancelled;
260
+ },
261
+ async waive(input) {
262
+ const current = await loadRunWithRetry(input.runId);
263
+ if (hasWaiver(current, input.requirementId)) {
264
+ return current;
265
+ }
266
+ requireTransition(current, "waive", canWaive);
267
+ requireWaivableRequirement(input.requirementId);
268
+ const waiver = {
269
+ waiverId: options.ids.createEventId(`waive-${input.requirementId}`),
270
+ requirementId: input.requirementId,
271
+ actor: input.actor,
272
+ reason: input.reason,
273
+ residualRisk: input.residualRisk,
274
+ waivedAt: options.clock.now().toISOString(),
275
+ };
276
+ const waivedRun = appendWaiver(current, waiver);
277
+ await writer.persist(waivedRun, writer.createEvent(input.runId, "run.waived", waiver));
278
+ return waivedRun;
279
+ },
280
+ async report(runId) {
281
+ const run = await loadRunWithRetry(runId);
282
+ return createReport(run, options.clock);
283
+ },
284
+ };
285
+ };
286
+ const parsePlannerGraph = (text) => parseAgentJson(text, TaskGraphSchema, "planner");
287
+ const waitForNextTurn = async () => await new Promise((resolve) => {
288
+ setTimeout(resolve, 0);
289
+ });
290
+ const isMissingRunError = (error, runId) => error instanceof TypeError && error.message === `missing run ${runId}`;
291
+ //# sourceMappingURL=run-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-controller.js","sourceRoot":"","sources":["../../src/controller/run-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Run, RunId } from "../domain/index.js";
2
+ import type { RunEvent, RunStore } from "../store/index.js";
3
+ import type { ControllerClock, ControllerIdSource } from "./contracts.js";
4
+ type RunPersistenceOptions = {
5
+ readonly store: RunStore;
6
+ readonly clock: ControllerClock;
7
+ readonly ids: Pick<ControllerIdSource, "createEventId">;
8
+ };
9
+ export type RunPersistence = {
10
+ readonly createEvent: (runId: RunId, type: string, payload: RunEvent["payload"]) => RunEvent;
11
+ readonly persist: (run: Run, event: RunEvent) => Promise<void>;
12
+ };
13
+ export declare const createRunPersistence: (options: RunPersistenceOptions) => RunPersistence;
14
+ export {};
15
+ //# sourceMappingURL=run-persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-persistence.d.ts","sourceRoot":"","sources":["../../src/controller/run-persistence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAEzE,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAA;CACxD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAA;IAC5F,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,SAAS,qBAAqB,KAAG,cAiDrE,CAAA"}
@@ -0,0 +1,83 @@
1
+ import { createHash } from "node:crypto";
2
+ export const createRunPersistence = (options) => {
3
+ const bootstrapSnapshotRunIds = new Set();
4
+ let writeChain;
5
+ const persistedIdempotencyKeys = new Map();
6
+ const createEvent = (runId, type, payload) => {
7
+ const semanticKey = createSemanticEventKey(runId, type, payload);
8
+ return {
9
+ schemaVersion: "1.0.0",
10
+ eventId: options.ids.createEventId(`event-${semanticKey}`),
11
+ idempotencyKey: `idempotency-${semanticKey}`,
12
+ runId,
13
+ type,
14
+ timestamp: options.clock.now().toISOString(),
15
+ payload,
16
+ };
17
+ };
18
+ return {
19
+ createEvent,
20
+ persist(run, event) {
21
+ const committedEvent = {
22
+ ...event,
23
+ idempotencyKey: event.idempotencyKey ?? event.eventId,
24
+ state: run,
25
+ };
26
+ const previousOperation = writeChain;
27
+ const operation = (async () => {
28
+ if (previousOperation !== undefined) {
29
+ await previousOperation;
30
+ }
31
+ const knownKeys = persistedIdempotencyKeys.get(run.runId) ?? new Set();
32
+ if (knownKeys.has(committedEvent.idempotencyKey ?? committedEvent.eventId)) {
33
+ await options.store.saveState(run, committedEvent.eventId);
34
+ return;
35
+ }
36
+ if (!bootstrapSnapshotRunIds.has(run.runId)) {
37
+ await options.store.saveState(run);
38
+ bootstrapSnapshotRunIds.add(run.runId);
39
+ }
40
+ await options.store.appendEvents(run.runId, [committedEvent]);
41
+ await options.store.saveState(run, committedEvent.eventId);
42
+ knownKeys.add(committedEvent.idempotencyKey ?? committedEvent.eventId);
43
+ persistedIdempotencyKeys.set(run.runId, knownKeys);
44
+ })();
45
+ writeChain = operation.catch(() => undefined);
46
+ return operation;
47
+ },
48
+ };
49
+ };
50
+ const createSemanticEventKey = (runId, type, payload) => {
51
+ const hash = createHash("sha256")
52
+ .update(type)
53
+ .update("\n")
54
+ .update(runId)
55
+ .update("\n")
56
+ .update(stableStringify(payload))
57
+ .digest("hex")
58
+ .slice(0, 16);
59
+ return `${runId}-${type.replaceAll(".", "-")}-${hash}`;
60
+ };
61
+ const stableStringify = (value) => JSON.stringify(sortJsonValue(value));
62
+ const sortJsonValue = (value) => {
63
+ if (Array.isArray(value)) {
64
+ return value.map(sortJsonValue);
65
+ }
66
+ if (typeof value !== "object" || value === null) {
67
+ return value;
68
+ }
69
+ if (!isJsonObject(value)) {
70
+ return value;
71
+ }
72
+ return Object.keys(value)
73
+ .sort((left, right) => left.localeCompare(right))
74
+ .reduce((result, key) => {
75
+ const propertyValue = value[key];
76
+ if (propertyValue !== undefined) {
77
+ result[key] = sortJsonValue(propertyValue);
78
+ }
79
+ return result;
80
+ }, {});
81
+ };
82
+ const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
83
+ //# sourceMappingURL=run-persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-persistence.js","sourceRoot":"","sources":["../../src/controller/run-persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { type AgentResult, type Evidence, type Failure, type Run, type RunAnswerRecord, type RunBudgetState, type RunGovernance, type RunPauseRecord, type RunWaiverRecord, type Task, type TaskGraph } from "../domain/index.js";
2
+ import type { RunWorkspace } from "../workspace/index.js";
3
+ import type { RunBudgetKind } from "./contracts.js";
4
+ type MutableRunParts = {
5
+ readonly evidence: readonly Evidence[];
6
+ readonly failures: readonly Failure[];
7
+ readonly agentResults: readonly AgentResult[];
8
+ readonly workspace: RunWorkspace;
9
+ };
10
+ type MutableGovernance = {
11
+ readonly blockingQuestionId: string | null;
12
+ readonly answers: readonly RunAnswerRecord[];
13
+ readonly waivers: readonly RunWaiverRecord[];
14
+ readonly paused: RunPauseRecord | null;
15
+ };
16
+ export type PlannedRun = Run & {
17
+ readonly taskGraph: TaskGraph;
18
+ };
19
+ export declare class RunStateTransitionError extends Error {
20
+ readonly runId: Run["runId"];
21
+ readonly operation: string;
22
+ readonly status: Run["status"];
23
+ readonly name = "RunStateTransitionError";
24
+ constructor(runId: Run["runId"], operation: string, status: Run["status"]);
25
+ }
26
+ export declare class RunGovernanceError extends Error {
27
+ readonly name = "RunGovernanceError";
28
+ }
29
+ export declare class RunBudgetExceededError extends Error {
30
+ readonly runId: Run["runId"];
31
+ readonly budget: RunBudgetKind;
32
+ readonly limit: number;
33
+ readonly name = "RunBudgetExceededError";
34
+ constructor(runId: Run["runId"], budget: RunBudgetKind, limit: number);
35
+ }
36
+ export declare const withStatus: (run: Run, status: Run["status"]) => Run;
37
+ export declare const withPlannedStatus: (run: PlannedRun, status: Run["status"]) => PlannedRun;
38
+ export declare const withTask: (run: PlannedRun, task: Task) => PlannedRun;
39
+ export declare const withParts: (run: PlannedRun, parts: MutableRunParts) => PlannedRun;
40
+ export declare const createInitialRunBudgets: (limit: number) => RunBudgetState;
41
+ export declare const createInitialRunGovernance: () => RunGovernance;
42
+ export declare const withGovernance: (run: Run, governance: MutableGovernance) => Run;
43
+ export declare const consumeBudget: (run: Run, budget: RunBudgetKind) => Run;
44
+ export declare const canResume: (run: Run) => boolean;
45
+ export declare const canPause: (run: Run) => boolean;
46
+ export declare const canAnswer: (run: Run) => boolean;
47
+ export declare const canCancel: (run: Run) => boolean;
48
+ export declare const canWaive: (run: Run) => boolean;
49
+ export declare const isTerminalRunStatus: (run: Run) => boolean;
50
+ export declare const isActiveRunStatus: (run: Run) => boolean;
51
+ export declare const requireTransition: (run: Run, operation: string, predicate: (candidate: Run) => boolean) => void;
52
+ export declare const hasAnswer: (run: Run, questionId: string) => boolean;
53
+ export declare const hasWaiver: (run: Run, requirementId: string) => boolean;
54
+ export declare const appendAnswer: (run: Run, answer: RunAnswerRecord) => Run;
55
+ export declare const appendWaiver: (run: Run, waiver: RunWaiverRecord) => Run;
56
+ export declare const setPaused: (run: Run, paused: RunPauseRecord | null) => Run;
57
+ export declare const createBlockedQuestionId: (run: Run) => string;
58
+ export declare const requireWaivableRequirement: (requirementId: string) => void;
59
+ export declare const parsePlannedRun: (value: unknown) => PlannedRun;
60
+ export {};
61
+ //# sourceMappingURL=run-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-state.d.ts","sourceRoot":"","sources":["../../src/controller/run-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ import { RunSchema, } from "../domain/index.js";
2
+ const ACTIVE_RUN_STATUSES = [
3
+ "planning",
4
+ "plan_ready",
5
+ "executing",
6
+ "verifying",
7
+ ];
8
+ const PAUSEABLE_RUN_STATUSES = [
9
+ "planning",
10
+ "plan_ready",
11
+ "executing",
12
+ "verifying",
13
+ ];
14
+ const RESUMEABLE_RUN_STATUSES = [
15
+ "plan_ready",
16
+ "executing",
17
+ "verifying",
18
+ "paused",
19
+ ];
20
+ const ANSWERABLE_RUN_STATUSES = ["clarification_required"];
21
+ const CANCELLABLE_RUN_STATUSES = [
22
+ "created",
23
+ "analyzing",
24
+ "planning",
25
+ "plan_ready",
26
+ "executing",
27
+ "verifying",
28
+ "evidence_gap",
29
+ "clarification_required",
30
+ "paused",
31
+ ];
32
+ const WAIVABLE_RUN_STATUSES = [
33
+ "clarification_required",
34
+ "paused",
35
+ "failed",
36
+ ];
37
+ const AUTO_WAIVE_BLOCKED_REQUIREMENT_IDS = [
38
+ "security",
39
+ "permission",
40
+ "destructive",
41
+ "verification",
42
+ ];
43
+ const hasAllowedStatus = (allowed, status) => allowed.includes(status);
44
+ export class RunStateTransitionError extends Error {
45
+ runId;
46
+ operation;
47
+ status;
48
+ name = "RunStateTransitionError";
49
+ constructor(runId, operation, status) {
50
+ super(`Cannot ${operation} run ${runId} from status ${status}`);
51
+ this.runId = runId;
52
+ this.operation = operation;
53
+ this.status = status;
54
+ }
55
+ }
56
+ export class RunGovernanceError extends Error {
57
+ name = "RunGovernanceError";
58
+ }
59
+ export class RunBudgetExceededError extends Error {
60
+ runId;
61
+ budget;
62
+ limit;
63
+ name = "RunBudgetExceededError";
64
+ constructor(runId, budget, limit) {
65
+ super(`Run ${runId} exhausted the ${budget} budget at limit ${limit}`);
66
+ this.runId = runId;
67
+ this.budget = budget;
68
+ this.limit = limit;
69
+ }
70
+ }
71
+ export const withStatus = (run, status) => RunSchema.parse({ ...run, status });
72
+ export const withPlannedStatus = (run, status) => parsePlannedRun({ ...run, status });
73
+ export const withTask = (run, task) => parsePlannedRun({
74
+ ...run,
75
+ taskGraph: {
76
+ ...run.taskGraph,
77
+ tasks: run.taskGraph.tasks.map((candidate) => candidate.taskId === task.taskId ? task : candidate),
78
+ },
79
+ });
80
+ export const withParts = (run, parts) => parsePlannedRun({ ...run, ...parts });
81
+ export const createInitialRunBudgets = (limit) => {
82
+ const parsedLimit = Math.max(1, limit);
83
+ const initialBudget = { limit: parsedLimit, used: 0 };
84
+ return {
85
+ intake: initialBudget,
86
+ planner: initialBudget,
87
+ task: initialBudget,
88
+ repair: initialBudget,
89
+ overall: initialBudget,
90
+ };
91
+ };
92
+ export const createInitialRunGovernance = () => ({
93
+ blockingQuestionId: null,
94
+ answers: [],
95
+ waivers: [],
96
+ paused: null,
97
+ });
98
+ export const withGovernance = (run, governance) => RunSchema.parse({ ...run, governance });
99
+ export const consumeBudget = (run, budget) => {
100
+ const counter = run.budgets[budget];
101
+ if (counter.used >= counter.limit) {
102
+ throw new RunBudgetExceededError(run.runId, budget, counter.limit);
103
+ }
104
+ return RunSchema.parse({
105
+ ...run,
106
+ budgets: {
107
+ ...run.budgets,
108
+ [budget]: { ...counter, used: counter.used + 1 },
109
+ },
110
+ });
111
+ };
112
+ export const canResume = (run) => hasAllowedStatus(RESUMEABLE_RUN_STATUSES, run.status);
113
+ export const canPause = (run) => hasAllowedStatus(PAUSEABLE_RUN_STATUSES, run.status);
114
+ export const canAnswer = (run) => hasAllowedStatus(ANSWERABLE_RUN_STATUSES, run.status);
115
+ export const canCancel = (run) => hasAllowedStatus(CANCELLABLE_RUN_STATUSES, run.status);
116
+ export const canWaive = (run) => hasAllowedStatus(WAIVABLE_RUN_STATUSES, run.status);
117
+ export const isTerminalRunStatus = (run) => run.status === "completed" || run.status === "cancelled" || run.status === "failed";
118
+ export const isActiveRunStatus = (run) => hasAllowedStatus(ACTIVE_RUN_STATUSES, run.status);
119
+ export const requireTransition = (run, operation, predicate) => {
120
+ if (!predicate(run)) {
121
+ throw new RunStateTransitionError(run.runId, operation, run.status);
122
+ }
123
+ };
124
+ export const hasAnswer = (run, questionId) => run.governance.answers.some((answer) => answer.questionId === questionId);
125
+ export const hasWaiver = (run, requirementId) => run.governance.waivers.some((waiver) => waiver.requirementId === requirementId);
126
+ export const appendAnswer = (run, answer) => withGovernance(run, {
127
+ ...run.governance,
128
+ blockingQuestionId: null,
129
+ answers: [...run.governance.answers, answer],
130
+ paused: null,
131
+ });
132
+ export const appendWaiver = (run, waiver) => withGovernance(run, {
133
+ ...run.governance,
134
+ waivers: [...run.governance.waivers, waiver],
135
+ });
136
+ export const setPaused = (run, paused) => withGovernance(run, { ...run.governance, paused });
137
+ export const createBlockedQuestionId = (run) => `question-${run.runId}`;
138
+ export const requireWaivableRequirement = (requirementId) => {
139
+ const normalizedRequirement = requirementId.toLowerCase();
140
+ if (AUTO_WAIVE_BLOCKED_REQUIREMENT_IDS.some((blockedWord) => normalizedRequirement.includes(blockedWord))) {
141
+ throw new RunGovernanceError(`Requirement ${requirementId} cannot be waived automatically because it is safety- or verification-critical.`);
142
+ }
143
+ };
144
+ export const parsePlannedRun = (value) => {
145
+ const run = RunSchema.parse(value);
146
+ if ("taskGraph" in run) {
147
+ return run;
148
+ }
149
+ throw new TypeError("planned run must include a taskGraph");
150
+ };
151
+ //# sourceMappingURL=run-state.js.map