@tea-agent/loop-agent 0.42.0-next.1 → 0.42.0-next.11

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 (247) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +321 -1
  3. package/dist/application/dag/generate-task-dag.js +75 -19
  4. package/dist/application/dag/run-dag.js +41 -0
  5. package/dist/application/task-lifecycle/advance.js +24 -5
  6. package/dist/application/task-lifecycle/observe.js +171 -17
  7. package/dist/application/task-lifecycle/plan-transitions.js +42 -7
  8. package/dist/application/task-lifecycle/recommendations.js +13 -2
  9. package/dist/build-stamp.json +3 -3
  10. package/dist/cli/command-definitions.js +7 -0
  11. package/dist/cli/program.js +6 -1
  12. package/dist/commands/client-recovery.js +3 -0
  13. package/dist/commands/dag-follow-up.js +138 -0
  14. package/dist/commands/dag-rerun-task.js +2 -0
  15. package/dist/commands/init.js +27 -1
  16. package/dist/commands/task-advance.js +19 -0
  17. package/dist/executors/dag-pi-executor.js +4010 -78
  18. package/dist/executors/pi-executor.js +15 -4
  19. package/dist/executors/pi-extension-resolver.js +14 -2
  20. package/dist/executors/pi-read-budget-policy.js +239 -0
  21. package/dist/executors/shell-executor.js +978 -188
  22. package/dist/executors/shell-write-guard.js +7 -0
  23. package/dist/infrastructure/console/operation-store.js +226 -6
  24. package/dist/shared/dag-failure-category.js +12 -0
  25. package/dist/shared/openspec-spec.js +70 -4
  26. package/dist/shared/operator/capabilities.js +7 -0
  27. package/dist/task/config-types.js +105 -5
  28. package/dist/task/contract/adopt.js +4 -0
  29. package/dist/task/contract/import-revision.js +4 -0
  30. package/dist/task/contract/project.js +3 -0
  31. package/dist/task/contract/schema.js +2 -1
  32. package/dist/task/frontend-project-capability.js +203 -20
  33. package/dist/task/runtime.js +5 -2
  34. package/dist/task/source-prepare/build-draft.js +3 -3
  35. package/dist/task/source-prepare/fragment-inventory.js +64 -25
  36. package/dist/task/source-prepare/prepare.js +126 -21
  37. package/dist/task/source-prepare/semantic-intake.js +6 -2
  38. package/dist/task/source-references.js +22 -1
  39. package/dist/worker/console/chat/chat-ui-policy.js +4 -2
  40. package/dist/worker/console/chat/model-resolver.js +7 -4
  41. package/dist/worker/console/chat/pi-runtime.js +258 -11
  42. package/dist/worker/console/chat/repo-browser.js +10 -3
  43. package/dist/worker/console/chat/routes.js +165 -71
  44. package/dist/worker/console/chat/sdd-data-alignment.js +222 -0
  45. package/dist/worker/console/chat/session-catalog.js +2 -0
  46. package/dist/worker/console/chat/session-store.js +159 -70
  47. package/dist/worker/console/chat/shortcuts.js +19 -3
  48. package/dist/worker/console/chat/turn-process.js +111 -56
  49. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  50. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  51. package/dist/worker/console/index.js +3 -0
  52. package/dist/worker/console/operator-actions.js +169 -7
  53. package/dist/worker/console/pi-readiness.js +3 -2
  54. package/dist/worker/console/server.js +23 -1
  55. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DZZ8m3PO.js → abnfDiagram-N423BO3Z-CcS17TBr.js} +1 -1
  56. package/dist/worker/console/static/assets/{arc-D6PvaVd-.js → arc-COptKq2S.js} +1 -1
  57. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-B_OTOiI8.js → architectureDiagram-T3A2C74G-h4LKMHjP.js} +1 -1
  58. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Bv6rqHBg.js → blockDiagram-VBNYF7ZC-COA1MOH0.js} +1 -1
  59. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B8eHr0oz.js → c4Diagram-5PPSVZJV-DJUf0QPm.js} +1 -1
  60. package/dist/worker/console/static/assets/channel-DdBCaOJ6.js +1 -0
  61. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DYwR0im2.js → chunk-2GRJ4B5K-mtWfKrUX.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-D2WPGqXt.js → chunk-2Q5K7J3B-B8pXsxDQ.js} +1 -1
  63. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CQISJ_I7.js → chunk-5RXB4S5H-ipKzByl1.js} +1 -1
  64. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C0o2Du1e.js → chunk-5VM5RSS4-DYi3Ald_.js} +1 -1
  65. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-4f8kr-U7.js → chunk-6Q2QTUOP-DQtGYoty.js} +1 -1
  66. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D_OWvXzX.js → chunk-GF5L2VYU-BU0qS2YV.js} +1 -1
  67. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CasdPz5X.js → chunk-JWPE2WC7-DVH9dIGE.js} +1 -1
  68. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Cj8lRrla.js → chunk-KBJHAD2P-Dt60SmgM.js} +1 -1
  69. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CUvD1FSd.js → chunk-RYQCIY6F-BoaUGuEY.js} +1 -1
  70. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CqLw_eqB.js → chunk-XXDRQBXY-_WHFDTp2.js} +1 -1
  71. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DZFra1GO.js +1 -0
  72. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DZFra1GO.js +1 -0
  73. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-ku-WqJPx.js → cose-bilkent-JH36ORCC-BxkbTIRd.js} +1 -1
  74. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-Bq_PYDhl.js → cynefin-VYW2F7L2-Bf2UVnoG.js} +1 -1
  75. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BiGZV641.js → cynefinDiagram-MW4NZA55-Bo23q1J_.js} +1 -1
  76. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-C4JRlglF.js → dagre-VZM6K2ZE-Dd_UU49i.js} +1 -1
  77. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B0dNeWYG.js → diagram-7IWD3JNH-ebUa1a9y.js} +1 -1
  78. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-Cj35YvYM.js → diagram-B4RE2ZJO-BucthU8r.js} +1 -1
  79. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-uzQoJ2-8.js → diagram-LBJQPF4R-BgqNpAkm.js} +1 -1
  80. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D1a-Buoz.js → diagram-Q27KOJAE-DC4q5NGa.js} +1 -1
  81. package/dist/worker/console/static/assets/{diagram-UB23O5K3-XjRrLRSs.js → diagram-UB23O5K3-CBqCaMeb.js} +1 -1
  82. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Da_O24cW.js → ebnfDiagram-BXEA7PRR-CGtnbQ3-.js} +1 -1
  83. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BLJ8jrYU.js → erDiagram-JOGREHBK-CG3LUao5.js} +1 -1
  84. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-B9GrLjM0.js → flowDiagram-UKHOOZJN-D2ZVgoFS.js} +1 -1
  85. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CeJ0TqiK.js → ganttDiagram-PKOTCBZU-DoYFZiKt.js} +1 -1
  86. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bm2eNNFX.js → gitGraphDiagram-DS77QQ5N-CKoP1s6j.js} +1 -1
  87. package/dist/worker/console/static/assets/index-CAZ2fC_X.css +1 -0
  88. package/dist/worker/console/static/assets/index-vbTcFnFs.js +449 -0
  89. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DB26i3d8.js → infoDiagram-6WML65LV-Duofv8p2.js} +1 -1
  90. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BOGRyeZT.js → ishikawaDiagram-WSZJBQD7-D2nlCkA1.js} +1 -1
  91. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CZRoBO_6.js → journeyDiagram-NVQOT4AX-Dd4IHdus.js} +1 -1
  92. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-qlWhJyoB.js → kanban-definition-27J2QSJJ-Bi20AOdt.js} +1 -1
  93. package/dist/worker/console/static/assets/{linear-CfUiDDB3.js → linear-D59YJ9kB.js} +1 -1
  94. package/dist/worker/console/static/assets/{mermaid.core-BQe6fpqj.js → mermaid.core-Bl13LpNa.js} +5 -5
  95. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-zFzWHw64.js → mindmap-definition-FAOFIHXS-C6DLP5eY.js} +1 -1
  96. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DFGUqjZO.js → pegDiagram-VL7TDLO6-BjO4cy64.js} +1 -1
  97. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BB5i0l8Z.js → pieDiagram-7S7Q4E2Y-D7i2qZTG.js} +1 -1
  98. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-obbVZ_X5.js → quadrantDiagram-CIZ2JOQS-Dx8o_h0y.js} +1 -1
  99. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BwdaNzc1.js → railroadDiagram-AXF67PYL-B55orI_t.js} +1 -1
  100. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CkTJaugh.js → requirementDiagram-LRYGKXZP-zWaehp6f.js} +1 -1
  101. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-BwJ-hIgq.js → sankeyDiagram-W5VNT64P-CcA-pjvD.js} +1 -1
  102. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BzSgmm7w.js → sequenceDiagram-SI44F4Z6-BOFbzNHI.js} +1 -1
  103. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-Bn3oj5Q1.js → sizeCapture-X5ZJPWSS-BjAejah1.js} +1 -1
  104. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-dxhGtL8K.js → stateDiagram-OKZ733FA-DXYwxJwZ.js} +1 -1
  105. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Clg3V9t1.js +1 -0
  106. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BLpEInya.js → swimlanes-SLNWSIFB-OYiOch8n.js} +2 -2
  107. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DX1dxAAW.js +8 -0
  108. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ChJGYcXy.js → timeline-definition-Z64GVDOM-cZfH3nmU.js} +1 -1
  109. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DK-qjRer.js → vennDiagram-T6HMQDX7-BDE7b3E1.js} +1 -1
  110. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-3qeaWAg-.js → wardleyDiagram-T6FBY63Y-kyyGy9WJ.js} +1 -1
  111. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CootlyP9.js → xychartDiagram-ELKLHX3M-CJj6VTog.js} +1 -1
  112. package/dist/worker/console/static/index.html +2 -2
  113. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  114. package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -5
  115. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +19 -8
  116. package/dist/worker/console/static-src/operator-chat/input-history.js +8 -6
  117. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +15 -7
  118. package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
  119. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +258 -23
  120. package/dist/worker/console/static-src/operator-chat/useChatThread.js +112 -4
  121. package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -4
  122. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
  123. package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
  124. package/dist/worker/console/static-src/shell/console-update-reload.js +36 -9
  125. package/dist/worker/console/static-src/shell/workspace-route.js +11 -0
  126. package/dist/worker/console/workspace-context.js +115 -1
  127. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  128. package/dist/worker/observe/routes.js +4 -0
  129. package/dist/worker/observe/static/constants.js +22 -22
  130. package/dist/worker/observe/static/dag-context-reason-labels.js +19 -0
  131. package/dist/worker/observe/static/dag-helpers.js +4 -2
  132. package/dist/worker/observe/static/dag-history-labels.js +1 -0
  133. package/dist/worker/observe/static/dag-inspector-humanize.d.ts +16 -0
  134. package/dist/worker/observe/static/dag-inspector-humanize.js +339 -0
  135. package/dist/worker/observe/static/dag-node-purpose.js +13 -8
  136. package/dist/worker/observe/static/index.html +4 -4
  137. package/dist/worker/observe/static/inspect-workspace.js +23 -0
  138. package/dist/worker/observe/static/kpi.js +2 -2
  139. package/dist/worker/observe/static/operator-chrome.d.ts +10 -2
  140. package/dist/worker/observe/static/operator-chrome.js +37 -23
  141. package/dist/worker/observe/static/prompt-restart-candidates.js +4 -2
  142. package/dist/worker/observe/static/relations.js +7 -7
  143. package/dist/worker/observe/static/router.d.ts +12 -1
  144. package/dist/worker/observe/static/router.js +48 -6
  145. package/dist/worker/observe/static/run-processing.js +4 -2
  146. package/dist/worker/observe/static/shell-chrome.js +2 -2
  147. package/dist/worker/observe/static/state.js +5 -0
  148. package/dist/worker/observe/static/styles.css +231 -0
  149. package/dist/worker/observe/static/views/dag-graph.js +1 -1
  150. package/dist/worker/observe/static/views/dag-inspector.js +336 -181
  151. package/dist/worker/observe/static/views/dag.js +26 -14
  152. package/dist/worker/observe/static/views/dags.js +3 -1
  153. package/dist/worker/observe/static/views/dashboard.js +14 -6
  154. package/dist/worker/observe/static/views/pool.js +7 -2
  155. package/dist/worker/observe/static/views/run.js +12 -3
  156. package/dist/worker/observe/static/views/session-timeline.js +74 -13
  157. package/dist/worker/observe/static/views/task.js +7 -2
  158. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +215 -28
  159. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  160. package/dist/workflows/dag/backend-test-plan-protocol.js +210 -0
  161. package/dist/workflows/dag/backend-test-scenario-param.js +172 -25
  162. package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
  163. package/dist/workflows/dag/backend-test-writer-completeness.js +104 -12
  164. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  165. package/dist/workflows/dag/dag-retry-schema.js +138 -0
  166. package/dist/workflows/dag/frontend-closeout.js +221 -0
  167. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  168. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  169. package/dist/workflows/dag/frontend-implementation-contract.js +1237 -192
  170. package/dist/workflows/dag/frontend-plan-render.js +2 -1
  171. package/dist/workflows/dag/frontend-prewrite-gate.js +256 -350
  172. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  173. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  174. package/dist/workflows/dag/frontend-recovery-controller.js +226 -0
  175. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  176. package/dist/workflows/dag/frontend-recovery-plan.js +21 -10
  177. package/dist/workflows/dag/frontend-recovery-run.js +166 -34
  178. package/dist/workflows/dag/frontend-repair.js +1 -432
  179. package/dist/workflows/dag/frontend-review-context.js +261 -15
  180. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  181. package/dist/workflows/dag/frontend-shadow-dual-write.js +941 -0
  182. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  183. package/dist/workflows/dag/frontend-shape-facts.js +419 -0
  184. package/dist/workflows/dag/frontend-shape.js +435 -0
  185. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  186. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  187. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  188. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  189. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  190. package/dist/workflows/dag/frontend-verification-trace.js +252 -25
  191. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  192. package/dist/workflows/dag/frontend-writer-admission.js +319 -0
  193. package/dist/workflows/dag/frontend-writer-status.js +256 -0
  194. package/dist/workflows/dag/init-hybrid.js +1031 -564
  195. package/dist/workflows/dag/interrupt-request.js +7 -0
  196. package/dist/workflows/dag/node-execution.js +854 -4
  197. package/dist/workflows/dag/prompt.js +70 -3
  198. package/dist/workflows/dag/recovery-lease.js +170 -0
  199. package/dist/workflows/dag/report.js +37 -1
  200. package/dist/workflows/dag/rerun-feedback.js +315 -1
  201. package/dist/workflows/dag/rerun-plan.js +17 -6
  202. package/dist/workflows/dag/rerun-run.js +44 -6
  203. package/dist/workflows/dag/rerun-task.js +251 -13
  204. package/dist/workflows/dag/retry-policy.js +230 -104
  205. package/dist/workflows/dag/runner.js +580 -124
  206. package/dist/workflows/dag/scheduler.js +133 -20
  207. package/dist/workflows/dag/types.js +244 -16
  208. package/dist/workflows/dag/validate.js +28 -12
  209. package/docs/examples/README.md +5 -0
  210. package/docs/init-surface.manifest.json +30 -12
  211. package/docs/skills/vetted-skill-registry.md +4 -2
  212. package/docs/templates/README.md +2 -0
  213. package/docs/templates/agent-dag-report.schema.json +8 -2
  214. package/docs/templates/agent-dag.schema.json +1 -1
  215. package/docs/templates/backend-test-dag.json +25 -20
  216. package/docs/templates/frontend-implementation-contract.schema.json +4 -1
  217. package/docs/templates/frontend-implementation-dag.json +89 -0
  218. package/docs/templates/spec-registry.schema.json +45 -0
  219. package/harness.json +1 -1
  220. package/package.json +4 -3
  221. package/skills/frontend-bounded-implement/SKILL.md +15 -14
  222. package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
  223. package/skills/frontend-contract/SKILL.md +23 -0
  224. package/skills/frontend-contract/references/contract-protocol.md +34 -0
  225. package/skills/frontend-design-review/SKILL.md +22 -41
  226. package/skills/frontend-plan/SKILL.md +26 -0
  227. package/skills/frontend-plan/references/decision-contract.md +37 -0
  228. package/skills/frontend-plan/references/design-decisions.md +17 -0
  229. package/skills/frontend-review/SKILL.md +20 -15
  230. package/skills/frontend-review/references/review-findings.md +6 -7
  231. package/skills/frontend-scout/SKILL.md +25 -0
  232. package/skills/frontend-scout/references/design-evidence.md +16 -0
  233. package/skills/frontend-scout/references/scout-evidence.md +23 -0
  234. package/skills/frontend-verification/SKILL.md +1 -1
  235. package/skills/loop-agent/references/command-reference.md +1 -0
  236. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  237. package/dist/worker/console/static/assets/channel-BU5gOilw.js +0 -1
  238. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DIzKJGHr.js +0 -1
  239. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DIzKJGHr.js +0 -1
  240. package/dist/worker/console/static/assets/index-H9rFJiGL.css +0 -1
  241. package/dist/worker/console/static/assets/index-xwu9GxEc.js +0 -451
  242. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cld2qK9v.js +0 -1
  243. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-TIHpiT7w.js +0 -8
  244. package/skills/frontend-implementation/SKILL.md +0 -52
  245. package/skills/frontend-implementation/references/code-standards.md +0 -33
  246. package/skills/frontend-implementation/references/design-spec.md +0 -56
  247. package/skills/frontend-implementation/references/node-contracts.md +0 -31
@@ -3,10 +3,10 @@ import path from "node:path";
3
3
  import { writeJsonAtomic } from "../../infrastructure/harness/atomic-write.js";
4
4
  import { sha256Hex } from "./frontend-implementation-contract.js";
5
5
  import { FRONTEND_RECOVERY_IMPORT_MANIFEST_REL_PATH, FRONTEND_RECOVERY_INTENT_REL_DIR, FRONTEND_RECOVERY_STAGING_PREFIX, computeFrontendRecoveryPlan, computeFrontendRecoveryPlanForSource, } from "./frontend-recovery-plan.js";
6
- import { dagRunDirExists, getDagRunDir, readDagRunSpec, readDagRunState, transferDagRunDir, writeDagRunState, } from "./lifecycle.js";
6
+ import { dagRunDirExists, getDagRunDir, locateDagRun, readDagRunSpec, readDagRunState, transferDagRunDir, writeDagRunState, } from "./lifecycle.js";
7
7
  import { buildDagRunId } from "./runner.js";
8
8
  import { prepareRunDir, writeNodeRecord } from "./run-store.js";
9
- import { FRONTEND_PREWRITE_RESULT_SOURCE_ARTIFACT, readFrontendPrewriteResult, } from "./scheduler.js";
9
+ import { FRONTEND_WRITER_ADMISSION_RESULT_ARTIFACT, readFrontendWriterAdmissionResult, } from "./scheduler.js";
10
10
  import { topoSortToRanks } from "./topo.js";
11
11
  /**
12
12
  * Candidate-continuation child creation kernel (phase 3b).
@@ -19,8 +19,8 @@ import { topoSortToRanks } from "./topo.js";
19
19
  * phase=child-running. Scheduling/execution of the child is phase 3c and out
20
20
  * of scope here.
21
21
  */
22
- /** Canonical contract artifact default location; overridden by the prewrite
23
- * gate's configured outputDir/artifactName when present. */
22
+ /** Canonical contract artifact default location; overridden by the design
23
+ * policy shell's configured outputDir/artifactName when present. */
24
24
  const FRONTEND_CANONICAL_CONTRACT_DEFAULT_REL_PATH = "contracts/frontend-implementation-contract.json";
25
25
  function resolveDeps(deps) {
26
26
  return {
@@ -62,6 +62,9 @@ function isValidFrontendRecoveryMarker(raw) {
62
62
  * Read + validate the activation marker. Missing or invalid markers return
63
63
  * `undefined` so the phase-3c gate and tests can treat an unmarked active
64
64
  * child as not executable (AC-2 / AC-5d).
65
+ *
66
+ * @deprecated Read-only/scheduler compatibility only; the runner no longer
67
+ * uses activation markers as the authoritative recovery entry point.
65
68
  */
66
69
  export async function readFrontendRecoveryMarker(parentRunDir, requestId) {
67
70
  let raw;
@@ -79,8 +82,8 @@ export async function readFrontendRecoveryMarker(parentRunDir, requestId) {
79
82
  return raw;
80
83
  }
81
84
  function classifyFrontendFactKind(nodeId) {
82
- if (/prewrite/i.test(nodeId))
83
- return "prewrite";
85
+ if (/admission|design-policy|verify|policy/i.test(nodeId))
86
+ return "gate";
84
87
  if (/scout/i.test(nodeId))
85
88
  return "scout";
86
89
  if (/contract/i.test(nodeId))
@@ -91,9 +94,9 @@ function classifyFrontendFactKind(nodeId) {
91
94
  }
92
95
  function resolveCanonicalContractRelPath(spec) {
93
96
  for (const task of spec.tasks) {
94
- const gate = task.shell?.frontendPrewriteGate;
95
- if (gate) {
96
- return path.posix.join(gate.outputDir, gate.artifactName);
97
+ const policy = task.shell?.frontendDesignPolicy;
98
+ if (policy) {
99
+ return path.posix.join(policy.outputDir, policy.artifactName);
97
100
  }
98
101
  }
99
102
  return FRONTEND_CANONICAL_CONTRACT_DEFAULT_REL_PATH;
@@ -270,14 +273,63 @@ async function casUpdateFrontendRecoveryState(parentRunDir, expectedRevision, de
270
273
  await deps.writeParentState(parentRunDir, state);
271
274
  }
272
275
  async function materializeChildStaging(input) {
273
- const { cwd, parentRunDir, parentRunId, parentSpec, parentState, recovery, requestId, childRunId, stagingDir, createdAt, } = input;
276
+ const { cwd, parentRunDir, parentRunId, parentSpec, parentState, recovery, recoveryPlan, requestId, childRunId, stagingDir, createdAt, } = input;
274
277
  await prepareRunDir(stagingDir);
275
- await writeJsonVerified(stagingDir, "run.json", parentSpec);
278
+ // Design-review rejection must be visible to the reset planner. Recovery
279
+ // children otherwise copy the old spec and only rerun design review, which
280
+ // deterministically re-rejects the unchanged plan. Bind the parent's typed
281
+ // findings into the child spec as ordinary rerun feedback.
282
+ let childSpec = parentSpec;
283
+ if (recovery.failureSource === "frontend-plan-pi" ||
284
+ recovery.failureSource === "frontend-review-pi") {
285
+ const designRecovery = parentState.terminalReason === "design-request-changes";
286
+ const reviewRecovery = recovery.failureSource === "frontend-review-pi" ||
287
+ parentState.terminalReason === "review-request-changes";
288
+ let feedback;
289
+ try {
290
+ const { deriveDagRerunFeedback } = await import("./rerun-feedback.js");
291
+ const taskId = parentSpec.taskContractBinding?.taskId ??
292
+ parentSpec.sourceBinding?.taskId ??
293
+ parentRunId;
294
+ feedback = await deriveDagRerunFeedback({
295
+ parentRunId,
296
+ taskId,
297
+ runDir: parentRunDir,
298
+ spec: parentSpec,
299
+ state: parentState,
300
+ });
301
+ if (reviewRecovery &&
302
+ feedback &&
303
+ feedback.sourceNodeId !== "frontend-review-pi") {
304
+ // Do not accidentally carry an older design/verify finding when a
305
+ // review-triggered continuation has lost its typed review fact.
306
+ feedback = undefined;
307
+ }
308
+ }
309
+ catch (error) {
310
+ if (designRecovery || reviewRecovery) {
311
+ throw new Error(`frontend recovery feedback unavailable: ${error instanceof Error ? error.message : String(error)}`);
312
+ }
313
+ }
314
+ if (feedback) {
315
+ childSpec = { ...parentSpec, rerunFeedback: feedback };
316
+ }
317
+ else if (designRecovery || reviewRecovery) {
318
+ // A design/review rejection cannot be safely retried without its typed
319
+ // findings. Fail closed instead of deterministically re-running the
320
+ // unchanged plan and producing another rejection.
321
+ throw new Error(`frontend recovery feedback unavailable: no typed ${reviewRecovery ? "review" : "design"} findings were found for recovery`);
322
+ }
323
+ }
324
+ await writeJsonVerified(stagingDir, "run.json", childSpec);
276
325
  // Phase 5: writer transient partial-write recovery resets the writer subtree
277
326
  // (frontend-implement-pi) instead of the candidate producer; everything
278
327
  // upstream is imported as verified parent facts.
279
328
  let plan;
280
- if (recovery.failureSource) {
329
+ if (recoveryPlan) {
330
+ plan = recoveryPlan;
331
+ }
332
+ else if (recovery.failureSource) {
281
333
  plan = computeFrontendRecoveryPlanForSource({
282
334
  spec: parentSpec,
283
335
  parentRunId,
@@ -286,21 +338,21 @@ async function materializeChildStaging(input) {
286
338
  });
287
339
  }
288
340
  else {
289
- const prewriteRead = await readFrontendPrewriteResult(parentRunDir);
290
- if (!prewriteRead.ok) {
291
- throw new Error(prewriteRead.reason);
341
+ const admissionRead = await readFrontendWriterAdmissionResult(parentRunDir);
342
+ if (!admissionRead.ok) {
343
+ throw new Error(admissionRead.reason);
292
344
  }
293
345
  plan = computeFrontendRecoveryPlan({
294
346
  spec: parentSpec,
295
347
  parentRunId,
296
348
  requestId,
297
- result: prewriteRead.result,
349
+ result: admissionRead.result,
298
350
  });
299
351
  }
300
- const { ranks } = topoSortToRanks(parentSpec);
352
+ const { ranks } = topoSortToRanks(childSpec);
301
353
  const resetSet = new Set(plan.resetNodeIds);
302
354
  const importedSet = new Set(plan.importedNodeIds);
303
- const tasksById = new Map(parentSpec.tasks.map((task) => [task.id, task]));
355
+ const tasksById = new Map(childSpec.tasks.map((task) => [task.id, task]));
304
356
  const nodes = {};
305
357
  const importedFacts = [];
306
358
  for (const nodeId of plan.importedNodeIds) {
@@ -325,22 +377,22 @@ async function materializeChildStaging(input) {
325
377
  }
326
378
  nodes[nodeId] = buildPendingNodeRecord(task);
327
379
  }
328
- for (const task of parentSpec.tasks) {
380
+ for (const task of childSpec.tasks) {
329
381
  if (!resetSet.has(task.id) && !importedSet.has(task.id)) {
330
382
  throw new Error(`node ${task.id} missing from frontend recovery plan partition`);
331
383
  }
332
384
  }
333
- // Canonical contract + prewrite-result identity facts are copied alongside
385
+ // Canonical contract + writer-admission identity facts are copied alongside
334
386
  // the per-node facts so reset nodes can re-read them (AC-4).
335
387
  const canonicalContract = await copyArtifactVerified({
336
388
  parentRunDir,
337
389
  newRunDir: stagingDir,
338
- relativePath: resolveCanonicalContractRelPath(parentSpec),
390
+ relativePath: resolveCanonicalContractRelPath(childSpec),
339
391
  });
340
- const prewriteResult = await copyArtifactVerified({
392
+ const writerAdmissionResult = await copyArtifactVerified({
341
393
  parentRunDir,
342
394
  newRunDir: stagingDir,
343
- relativePath: FRONTEND_PREWRITE_RESULT_SOURCE_ARTIFACT,
395
+ relativePath: FRONTEND_WRITER_ADMISSION_RESULT_ARTIFACT,
344
396
  });
345
397
  const childState = {
346
398
  version: 1,
@@ -359,8 +411,11 @@ async function materializeChildStaging(input) {
359
411
  parentRunId,
360
412
  childRunId,
361
413
  attemptId: recovery.attemptId,
362
- attemptIndex: 1,
363
- continuationCount: 1,
414
+ attemptIndex: recovery.attemptIndex + 1,
415
+ continuationCount: recovery.continuationCount + 1,
416
+ ...(recovery.failureSource
417
+ ? { failureSource: recovery.failureSource }
418
+ : {}),
364
419
  revision: 0,
365
420
  },
366
421
  ...(parentState.evaluation
@@ -377,9 +432,9 @@ async function materializeChildStaging(input) {
377
432
  relativePath: canonicalContract.destinationRelativePath,
378
433
  sha256: canonicalContract.sha256,
379
434
  },
380
- prewriteResult: {
381
- relativePath: prewriteResult.destinationRelativePath,
382
- sha256: prewriteResult.sha256,
435
+ writerAdmissionResult: {
436
+ relativePath: writerAdmissionResult.destinationRelativePath,
437
+ sha256: writerAdmissionResult.sha256,
383
438
  },
384
439
  importedFacts,
385
440
  };
@@ -417,6 +472,9 @@ async function verifyThreeWayConsistency(input) {
417
472
  * intent. Single-writer: the recovery coordinator is the only caller.
418
473
  * Fail-closed on revision drift, missing intent, unreadable prewrite result,
419
474
  * hash mismatch, marker-write failure, or consistency failure.
475
+ *
476
+ * @deprecated The M6 operation controller is the authoritative recovery loop;
477
+ * this kernel is retained only for read-only/scheduler compatibility.
420
478
  */
421
479
  export async function stageRecoveryChild(options) {
422
480
  const { cwd, parentRunId } = options;
@@ -426,7 +484,41 @@ export async function stageRecoveryChild(options) {
426
484
  const parentRunDir = getDagRunDir(cwd, "active", parentRunId);
427
485
  const parentState = await deps.readParentState(parentRunDir);
428
486
  const parentSpec = await readDagRunSpec(parentRunDir);
429
- const recovery = parentState.frontendRecoveryState;
487
+ let recovery = parentState.frontendRecoveryState;
488
+ if (options.recoveryIntent) {
489
+ const intent = options.recoveryIntent;
490
+ if (intent.parentRunId !== parentRunId ||
491
+ intent.requestId.length === 0 ||
492
+ intent.phase !== "child-staging" ||
493
+ intent.childRunId !== undefined ||
494
+ intent.revision !== 0) {
495
+ throw new Error("frontend recovery intent binding mismatch");
496
+ }
497
+ if (recovery?.requestId === intent.requestId) {
498
+ if (recovery.parentRunId !== intent.parentRunId ||
499
+ recovery.recoveryRootRunId !== intent.recoveryRootRunId ||
500
+ recovery.attemptIndex !== intent.attemptIndex ||
501
+ recovery.continuationCount !== intent.continuationCount ||
502
+ recovery.failureSource !== intent.failureSource) {
503
+ throw new Error("frontend recovery intent replay binding mismatch");
504
+ }
505
+ }
506
+ else {
507
+ const previousAttemptIndex = recovery?.attemptIndex ?? 0;
508
+ const previousContinuationCount = recovery?.continuationCount ?? 0;
509
+ const expectedRoot = recovery?.recoveryRootRunId ?? parentRunId;
510
+ if (intent.recoveryRootRunId !== expectedRoot ||
511
+ intent.attemptIndex !== previousAttemptIndex ||
512
+ intent.continuationCount !== previousContinuationCount) {
513
+ throw new Error("frontend recovery intent lineage mismatch");
514
+ }
515
+ recovery = structuredClone(intent);
516
+ await deps.writeParentState(parentRunDir, {
517
+ ...parentState,
518
+ frontendRecoveryState: recovery,
519
+ });
520
+ }
521
+ }
430
522
  if (!recovery) {
431
523
  throw new Error(`parent run ${parentRunId} has no frontend recovery intent`);
432
524
  }
@@ -434,17 +526,49 @@ export async function stageRecoveryChild(options) {
434
526
  if (!requestId) {
435
527
  throw new Error(`parent run ${parentRunId} recovery intent has no requestId`);
436
528
  }
529
+ if (options.recoveryPlan) {
530
+ if (options.recoveryPlan.parentRunId !== parentRunId ||
531
+ options.recoveryPlan.requestId !== requestId ||
532
+ options.recoveryPlan.failureSource !== recovery.failureSource) {
533
+ throw new Error("frontend recovery plan binding mismatch");
534
+ }
535
+ const expectedPlan = computeFrontendRecoveryPlanForSource({
536
+ spec: parentSpec,
537
+ parentRunId,
538
+ requestId,
539
+ failureSource: recovery.failureSource,
540
+ });
541
+ if (JSON.stringify(expectedPlan.resetNodeIds) !==
542
+ JSON.stringify(options.recoveryPlan.resetNodeIds) ||
543
+ JSON.stringify(expectedPlan.importedNodeIds) !==
544
+ JSON.stringify(options.recoveryPlan.importedNodeIds)) {
545
+ throw new Error("frontend recovery plan drifted from parent DAG");
546
+ }
547
+ }
437
548
  // Idempotent short-circuit (D4.2): reserved childRunId + activated marker +
438
549
  // existing child dir means the request was already fully committed.
439
550
  if (recovery.childRunId) {
440
551
  const existingMarker = await readFrontendRecoveryMarker(parentRunDir, requestId);
441
552
  if (existingMarker) {
442
- const existingChildDir = getDagRunDir(cwd, "active", existingMarker.childRunId);
443
- if (await dagRunDirExists(existingChildDir)) {
553
+ const existingChild = await locateDagRun(cwd, existingMarker.childRunId);
554
+ if (existingChild &&
555
+ (existingChild.lifecycle === "active" ||
556
+ existingChild.lifecycle === "paused" ||
557
+ existingChild.lifecycle === "completed")) {
558
+ await verifyThreeWayConsistency({
559
+ parentRunDir,
560
+ activeChildDir: existingChild.runDir,
561
+ marker: existingMarker,
562
+ parentRunId,
563
+ requestId,
564
+ recoveryRootRunId: recovery.recoveryRootRunId,
565
+ childRunId: existingMarker.childRunId,
566
+ deps,
567
+ });
444
568
  return {
445
569
  ok: true,
446
570
  childRunId: existingMarker.childRunId,
447
- childRunDir: existingChildDir,
571
+ childRunDir: existingChild.runDir,
448
572
  marker: existingMarker,
449
573
  idempotentReplay: true,
450
574
  };
@@ -452,8 +576,15 @@ export async function stageRecoveryChild(options) {
452
576
  }
453
577
  }
454
578
  // Derive the childRunId exactly once; replay always reuses a reserved id.
455
- const childRunId = recovery.childRunId ??
456
- (await (options.buildChildRunId ?? buildDagRunId)(parentSpec, cwd));
579
+ // buildDagRunId is deterministic for the same task title on the same day. A
580
+ // recovery child must never reuse its still-active parent directory, or the
581
+ // staging path aliases the parent and the required import manifest is absent.
582
+ const childRunId = recovery.childRunId ?? await (async () => {
583
+ const generatedChildRunId = await (options.buildChildRunId ?? buildDagRunId)(parentSpec, cwd);
584
+ return generatedChildRunId === parentRunId
585
+ ? `${generatedChildRunId}-recovery-${requestId.slice(0, 8)}`
586
+ : generatedChildRunId;
587
+ })();
457
588
  // Orphan staging cleanup (D4.3): remove any in-flight staging dir for this id.
458
589
  const activeRootDir = getDagRunDir(cwd, "active", "");
459
590
  const stagingDir = path.join(activeRootDir, `${FRONTEND_RECOVERY_STAGING_PREFIX}${childRunId}`);
@@ -487,6 +618,7 @@ export async function stageRecoveryChild(options) {
487
618
  parentSpec,
488
619
  parentState,
489
620
  recovery,
621
+ recoveryPlan: options.recoveryPlan,
490
622
  requestId,
491
623
  childRunId,
492
624
  stagingDir,