@tea-agent/loop-agent 0.41.1-beta.0 → 0.42.0-next.2

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 (277) hide show
  1. package/CHANGELOG.md +78 -206
  2. package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
  3. package/dist/adapters/context-transfer/pi-session.js +61 -0
  4. package/dist/application/dag/generate-task-dag.js +19 -75
  5. package/dist/application/task-lifecycle/advance.js +5 -24
  6. package/dist/application/task-lifecycle/observe.js +17 -171
  7. package/dist/application/task-lifecycle/plan-transitions.js +7 -42
  8. package/dist/application/task-lifecycle/recommendations.js +2 -13
  9. package/dist/build-stamp.json +3 -3
  10. package/dist/cli/command-definitions.js +12 -7
  11. package/dist/cli/program.js +23 -6
  12. package/dist/commands/client-recovery.js +0 -3
  13. package/dist/commands/dag-artifact.js +284 -0
  14. package/dist/commands/dag-context.js +184 -0
  15. package/dist/commands/dag-rerun.js +206 -1
  16. package/dist/commands/init.js +1 -27
  17. package/dist/commands/task-advance.js +0 -19
  18. package/dist/executors/dag-pi-executor.js +266 -3792
  19. package/dist/executors/pi-executor.js +4 -15
  20. package/dist/executors/pi-sdk-executor.js +3 -0
  21. package/dist/executors/shell-executor.js +217 -945
  22. package/dist/executors/shell-write-guard.js +0 -7
  23. package/dist/{worker → infrastructure}/console/app-data.js +4 -0
  24. package/dist/infrastructure/console/artifact-revision-store.js +430 -0
  25. package/dist/infrastructure/console/context-export-store.js +160 -0
  26. package/dist/infrastructure/console/dir-lock.js +132 -0
  27. package/dist/infrastructure/console/operation-store.js +197 -0
  28. package/dist/infrastructure/harness/artifact-store.js +10 -1
  29. package/dist/infrastructure/harness/atomic-write.js +12 -2
  30. package/dist/shared/context-transfer/artifact-revision.js +172 -0
  31. package/dist/shared/context-transfer.js +418 -0
  32. package/dist/shared/dag-failure-category.js +0 -12
  33. package/dist/shared/openspec-spec.js +4 -70
  34. package/dist/shared/operator/capabilities.js +14 -7
  35. package/dist/shared/operator/safe-run-summary.js +1 -0
  36. package/dist/shared/path-safety.js +93 -0
  37. package/dist/shared/preview.js +28 -4
  38. package/dist/task/config-types.js +80 -35
  39. package/dist/task/contract/adopt.js +0 -4
  40. package/dist/task/contract/import-revision.js +0 -4
  41. package/dist/task/contract/project.js +0 -3
  42. package/dist/task/contract/schema.js +1 -2
  43. package/dist/task/frontend-project-capability.js +20 -203
  44. package/dist/task/runtime.js +2 -5
  45. package/dist/task/source-prepare/build-draft.js +3 -3
  46. package/dist/task/source-prepare/fragment-inventory.js +9 -15
  47. package/dist/task/source-prepare/prepare.js +1 -89
  48. package/dist/task/source-prepare/semantic-intake.js +2 -6
  49. package/dist/task/source-references.js +1 -22
  50. package/dist/task/task-demand-routing.js +3 -0
  51. package/dist/worker/console/chat/chat-event-store.js +2 -2
  52. package/dist/worker/console/chat/pi-runtime.js +3 -2
  53. package/dist/worker/console/chat/resource-preferences-store.js +1 -1
  54. package/dist/worker/console/chat/routes.js +13 -4
  55. package/dist/worker/console/chat/semantic-activity.js +12 -11
  56. package/dist/worker/console/chat/session-stats.js +96 -0
  57. package/dist/worker/console/chat/session-store.js +1 -1
  58. package/dist/worker/console/chat/turn-process.js +28 -4
  59. package/dist/worker/console/chat/user-questions.js +1 -1
  60. package/dist/worker/console/console-update-runtime.js +1 -1
  61. package/dist/worker/console/context-transfer-diagnostics.js +198 -0
  62. package/dist/worker/console/dag-confirmation.js +1 -1
  63. package/dist/worker/console/dag-execution-receipt.js +1 -1
  64. package/dist/worker/console/doctor.js +1 -1
  65. package/dist/worker/console/draft-store.js +1 -1
  66. package/dist/worker/console/human-gate-token.js +1 -1
  67. package/dist/worker/console/index.js +3 -6
  68. package/dist/worker/console/interview/assessment.js +1 -1
  69. package/dist/worker/console/interview/session.js +1 -1
  70. package/dist/worker/console/operation-runner.js +45 -4
  71. package/dist/worker/console/operation-sse.js +1 -1
  72. package/dist/worker/console/operation-wait.js +1 -1
  73. package/dist/worker/console/operator-actions.js +107 -168
  74. package/dist/worker/console/operator-surface-health.js +1 -1
  75. package/dist/worker/console/operator-user-error.js +169 -0
  76. package/dist/worker/console/pi-plugins.js +60 -1
  77. package/dist/worker/console/routes.js +637 -8
  78. package/dist/worker/console/security.js +35 -0
  79. package/dist/worker/console/server.js +6 -6
  80. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bho4we4c.js → abnfDiagram-N423BO3Z-DZZ8m3PO.js} +1 -1
  81. package/dist/worker/console/static/assets/{arc-TBDkTeK0.js → arc-D6PvaVd-.js} +1 -1
  82. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BF_fZrn2.js → architectureDiagram-T3A2C74G-B_OTOiI8.js} +1 -1
  83. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CCnPgUe2.js → blockDiagram-VBNYF7ZC-Bv6rqHBg.js} +1 -1
  84. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BCYZJLAT.js → c4Diagram-5PPSVZJV-B8eHr0oz.js} +1 -1
  85. package/dist/worker/console/static/assets/channel-BU5gOilw.js +1 -0
  86. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D8K6adhU.js → chunk-2GRJ4B5K-DYwR0im2.js} +1 -1
  87. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DkT1Q78b.js → chunk-2Q5K7J3B-D2WPGqXt.js} +1 -1
  88. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DuhvpIr7.js → chunk-5RXB4S5H-CQISJ_I7.js} +1 -1
  89. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BnK6dC49.js → chunk-5VM5RSS4-C0o2Du1e.js} +1 -1
  90. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DPz__z7r.js → chunk-6Q2QTUOP-4f8kr-U7.js} +1 -1
  91. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-0kkppM2j.js → chunk-GF5L2VYU-D_OWvXzX.js} +1 -1
  92. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BB41iK5t.js → chunk-JWPE2WC7-CasdPz5X.js} +1 -1
  93. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CiVrxKHU.js → chunk-KBJHAD2P-Cj8lRrla.js} +1 -1
  94. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-C2h9Xje1.js → chunk-RYQCIY6F-CUvD1FSd.js} +1 -1
  95. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-3iOSHdbM.js → chunk-XXDRQBXY-CqLw_eqB.js} +1 -1
  96. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DIzKJGHr.js +1 -0
  97. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DIzKJGHr.js +1 -0
  98. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BN3A7tkk.js → cose-bilkent-JH36ORCC-ku-WqJPx.js} +1 -1
  99. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CTuBy0Or.js → cynefin-VYW2F7L2-Bq_PYDhl.js} +1 -1
  100. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-wb6tUlMN.js → cynefinDiagram-MW4NZA55-BiGZV641.js} +1 -1
  101. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-GP1Ivx8B.js → dagre-VZM6K2ZE-C4JRlglF.js} +1 -1
  102. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-ejrcK6L0.js → diagram-7IWD3JNH-B0dNeWYG.js} +1 -1
  103. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-YFkCCvUU.js → diagram-B4RE2ZJO-Cj35YvYM.js} +1 -1
  104. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-B4rrvIaL.js → diagram-LBJQPF4R-uzQoJ2-8.js} +1 -1
  105. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C-YIZcUf.js → diagram-Q27KOJAE-D1a-Buoz.js} +1 -1
  106. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPF5wcL1.js → diagram-UB23O5K3-XjRrLRSs.js} +1 -1
  107. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CU5SzXjO.js → ebnfDiagram-BXEA7PRR-Da_O24cW.js} +1 -1
  108. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CpL414DE.js → erDiagram-JOGREHBK-BLJ8jrYU.js} +1 -1
  109. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-MrhLzNau.js → flowDiagram-UKHOOZJN-B9GrLjM0.js} +1 -1
  110. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Bg4qFuUo.js → ganttDiagram-PKOTCBZU-CeJ0TqiK.js} +1 -1
  111. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-ColxSXLR.js → gitGraphDiagram-DS77QQ5N-Bm2eNNFX.js} +1 -1
  112. package/dist/worker/console/static/assets/index-H9rFJiGL.css +1 -0
  113. package/dist/worker/console/static/assets/index-xwu9GxEc.js +451 -0
  114. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czvtm6gc.js → infoDiagram-6WML65LV-DB26i3d8.js} +1 -1
  115. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B7Xp8HyJ.js → ishikawaDiagram-WSZJBQD7-BOGRyeZT.js} +1 -1
  116. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DWYZcvph.js → journeyDiagram-NVQOT4AX-CZRoBO_6.js} +1 -1
  117. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-KTLZRUjx.js → kanban-definition-27J2QSJJ-qlWhJyoB.js} +1 -1
  118. package/dist/worker/console/static/assets/{linear-_Exn7bfl.js → linear-CfUiDDB3.js} +1 -1
  119. package/dist/worker/console/static/assets/{mermaid.core-Cxg8kX8V.js → mermaid.core-BQe6fpqj.js} +5 -5
  120. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-oKrlo2Bt.js → mindmap-definition-FAOFIHXS-zFzWHw64.js} +1 -1
  121. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-XAeteiNd.js → pegDiagram-VL7TDLO6-DFGUqjZO.js} +1 -1
  122. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BTf1K-lp.js → pieDiagram-7S7Q4E2Y-BB5i0l8Z.js} +1 -1
  123. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-C0IlY0Jf.js → quadrantDiagram-CIZ2JOQS-obbVZ_X5.js} +1 -1
  124. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BVbKtZhW.js → railroadDiagram-AXF67PYL-BwdaNzc1.js} +1 -1
  125. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C5e4JFcr.js → requirementDiagram-LRYGKXZP-CkTJaugh.js} +1 -1
  126. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cz30hc29.js → sankeyDiagram-W5VNT64P-BwJ-hIgq.js} +1 -1
  127. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DS33n6d0.js → sequenceDiagram-SI44F4Z6-BzSgmm7w.js} +1 -1
  128. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-46w7v-9T.js → sizeCapture-X5ZJPWSS-Bn3oj5Q1.js} +1 -1
  129. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-pbcD5SsZ.js → stateDiagram-OKZ733FA-dxhGtL8K.js} +1 -1
  130. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cld2qK9v.js +1 -0
  131. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DuivYBSj.js → swimlanes-SLNWSIFB-BLpEInya.js} +2 -2
  132. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-TIHpiT7w.js +8 -0
  133. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cb9VZVIl.js → timeline-definition-Z64GVDOM-ChJGYcXy.js} +1 -1
  134. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D2-mfOgR.js → vennDiagram-T6HMQDX7-DK-qjRer.js} +1 -1
  135. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DeS2aC76.js → wardleyDiagram-T6FBY63Y-3qeaWAg-.js} +1 -1
  136. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-WGsrFjxH.js → xychartDiagram-ELKLHX3M-CootlyP9.js} +1 -1
  137. package/dist/worker/console/static/index.html +7 -2
  138. package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
  139. package/dist/worker/console/static-src/app/useRunProgress.js +9 -2
  140. package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +22 -0
  141. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
  142. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -0
  143. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
  144. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +106 -0
  145. package/dist/worker/console/static-src/shell/console-update-reload.js +25 -0
  146. package/dist/worker/console/workspace-context.js +28 -112
  147. package/dist/worker/console/workspace-registry.js +2 -2
  148. package/dist/worker/continuation/worker-continuation.js +278 -0
  149. package/dist/worker/observability/read-model.js +4 -0
  150. package/dist/worker/observe/health.js +1 -1
  151. package/dist/worker/observe/node-transparency.js +572 -0
  152. package/dist/worker/observe/routes.js +51 -1
  153. package/dist/worker/observe/static/api.js +69 -5
  154. package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
  155. package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
  156. package/dist/worker/observe/static/dag-node-purpose.js +0 -5
  157. package/dist/worker/observe/static/state.js +3 -1
  158. package/dist/worker/observe/static/styles.css +1037 -126
  159. package/dist/worker/observe/static/views/dag-inspector.js +1217 -65
  160. package/dist/worker/observe/static/views/session-timeline.js +121 -25
  161. package/dist/worker/outcomes/adapters.js +19 -0
  162. package/dist/worker/outcomes/types.js +1 -0
  163. package/dist/worker/pool/attempt-lease.js +97 -66
  164. package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
  165. package/dist/worker/pool/reconcile.js +46 -1
  166. package/dist/worker/pool/run-store.js +2 -0
  167. package/dist/worker/pool/state-projection.js +2 -0
  168. package/dist/worker/task-spec/workflow-routing.js +8 -3
  169. package/dist/workflows/dag/artifact-bindings.js +149 -0
  170. package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
  171. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +99 -4
  172. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  173. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  174. package/dist/workflows/dag/backend-test-writer-completeness.js +45 -3
  175. package/dist/workflows/dag/budget-enforcement.js +10 -0
  176. package/dist/workflows/dag/context-receipt.js +305 -0
  177. package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
  178. package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
  179. package/dist/workflows/dag/context-transfer/renderers.js +93 -0
  180. package/dist/workflows/dag/contract-validator-registrations.js +2 -1
  181. package/dist/workflows/dag/frontend-implementation-contract.js +162 -932
  182. package/dist/workflows/dag/frontend-plan-render.js +1 -2
  183. package/dist/workflows/dag/frontend-prewrite-gate.js +349 -255
  184. package/dist/workflows/dag/frontend-recovery-plan.js +10 -17
  185. package/dist/workflows/dag/frontend-recovery-run.js +20 -33
  186. package/dist/workflows/dag/frontend-repair.js +432 -1
  187. package/dist/workflows/dag/frontend-review-context.js +15 -261
  188. package/dist/workflows/dag/frontend-verification-trace.js +24 -249
  189. package/dist/workflows/dag/frontend-worktree-diff.js +17 -250
  190. package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
  191. package/dist/workflows/dag/init-hybrid.js +740 -718
  192. package/dist/workflows/dag/interrupt-request.js +0 -7
  193. package/dist/workflows/dag/node-execution.js +136 -759
  194. package/dist/workflows/dag/path-safety.js +1 -0
  195. package/dist/workflows/dag/prompt.js +30 -38
  196. package/dist/workflows/dag/report.js +1 -37
  197. package/dist/workflows/dag/rerun-feedback.js +1 -256
  198. package/dist/workflows/dag/rerun-plan.js +557 -11
  199. package/dist/workflows/dag/rerun-run.js +601 -38
  200. package/dist/workflows/dag/rerun-task.js +0 -29
  201. package/dist/workflows/dag/retry-policy.js +109 -214
  202. package/dist/workflows/dag/runner.js +142 -430
  203. package/dist/workflows/dag/scheduler.js +16 -114
  204. package/dist/workflows/dag/skill-snapshot.js +17 -0
  205. package/dist/workflows/dag/types.js +195 -246
  206. package/dist/workflows/dag/validate.js +12 -28
  207. package/docs/architecture/runtime-boundaries.md +6 -6
  208. package/docs/architecture/worker-and-feature.md +1 -1
  209. package/docs/init-surface.manifest.json +12 -30
  210. package/docs/skills/vetted-skill-registry.md +2 -4
  211. package/docs/templates/README.md +0 -2
  212. package/docs/templates/agent-dag-report.schema.json +2 -8
  213. package/docs/templates/agent-dag.schema.json +33 -1
  214. package/docs/templates/backend-test-dag.json +18 -18
  215. package/docs/templates/frontend-implementation-contract.schema.json +1 -4
  216. package/docs/templates/product-line/task.yaml +1 -1
  217. package/harness.json +3 -3
  218. package/package.json +3 -1
  219. package/skills/frontend-bounded-implement/SKILL.md +14 -15
  220. package/skills/frontend-design-review/SKILL.md +41 -22
  221. package/skills/frontend-implementation/SKILL.md +52 -0
  222. package/skills/frontend-implementation/references/code-standards.md +33 -0
  223. package/skills/frontend-implementation/references/design-spec.md +56 -0
  224. package/skills/frontend-implementation/references/node-contracts.md +31 -0
  225. package/skills/frontend-review/SKILL.md +15 -20
  226. package/skills/frontend-review/references/review-findings.md +7 -6
  227. package/skills/frontend-verification/SKILL.md +1 -1
  228. package/skills/loop-agent/references/command-reference.md +6 -1
  229. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  230. package/dist/commands/dag-follow-up.js +0 -138
  231. package/dist/executors/pi-read-budget-policy.js +0 -239
  232. package/dist/worker/console/frontend-human-decision-adapter.js +0 -19
  233. package/dist/worker/console/frontend-split-operation-adapter.js +0 -20
  234. package/dist/worker/console/operation-store.js +0 -389
  235. package/dist/worker/console/static/assets/channel-bnXW0U3C.js +0 -1
  236. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-rZpq_twR.js +0 -1
  237. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-rZpq_twR.js +0 -1
  238. package/dist/worker/console/static/assets/index-D3CC4eUz.css +0 -1
  239. package/dist/worker/console/static/assets/index-DLt4ZFvD.js +0 -437
  240. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-zBMYiUyi.js +0 -1
  241. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-d_rms-5i.js +0 -8
  242. package/dist/worker/console/static-src/active-run-badge.js +0 -17
  243. package/dist/worker/materialize/frontend-split-task-materializer.js +0 -72
  244. package/dist/workflows/dag/dag-retry-schema.js +0 -138
  245. package/dist/workflows/dag/frontend-closeout.js +0 -221
  246. package/dist/workflows/dag/frontend-design-policy.js +0 -400
  247. package/dist/workflows/dag/frontend-human-decision.js +0 -182
  248. package/dist/workflows/dag/frontend-provider-capability-matrix.js +0 -159
  249. package/dist/workflows/dag/frontend-read-budgets.js +0 -12
  250. package/dist/workflows/dag/frontend-recovery-capsule.js +0 -455
  251. package/dist/workflows/dag/frontend-recovery-controller.js +0 -202
  252. package/dist/workflows/dag/frontend-recovery-lineage.js +0 -178
  253. package/dist/workflows/dag/frontend-review-findings.js +0 -270
  254. package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -914
  255. package/dist/workflows/dag/frontend-shape-capsule-store.js +0 -191
  256. package/dist/workflows/dag/frontend-shape-facts.js +0 -409
  257. package/dist/workflows/dag/frontend-shape.js +0 -427
  258. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +0 -108
  259. package/dist/workflows/dag/frontend-split-application-service.js +0 -203
  260. package/dist/workflows/dag/frontend-split-orchestrator.js +0 -899
  261. package/dist/workflows/dag/frontend-typed-event-store.js +0 -452
  262. package/dist/workflows/dag/frontend-typed-event-transaction.js +0 -180
  263. package/dist/workflows/dag/frontend-writer-admission.js +0 -285
  264. package/dist/workflows/dag/frontend-writer-status.js +0 -256
  265. package/dist/workflows/dag/recovery-lease.js +0 -80
  266. package/docs/templates/frontend-implementation-dag.json +0 -89
  267. package/docs/templates/spec-registry.schema.json +0 -45
  268. package/skills/frontend-bounded-implement/references/code-standards.md +0 -19
  269. package/skills/frontend-contract/SKILL.md +0 -23
  270. package/skills/frontend-contract/references/contract-protocol.md +0 -34
  271. package/skills/frontend-plan/SKILL.md +0 -26
  272. package/skills/frontend-plan/references/decision-contract.md +0 -37
  273. package/skills/frontend-plan/references/design-decisions.md +0 -17
  274. package/skills/frontend-scout/SKILL.md +0 -25
  275. package/skills/frontend-scout/references/design-evidence.md +0 -16
  276. package/skills/frontend-scout/references/scout-evidence.md +0 -23
  277. /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
@@ -4,7 +4,6 @@ import { generateTaskDagUseCase } from "../../application/dag/generate-task-dag.
4
4
  import { writeJsonAtomic } from "../../infrastructure/harness/atomic-write.js";
5
5
  import { DAG_RUNS_DIR, isTerminalDagRunStatus, locateDagRun, readDagRunSpec, readDagRunState, } from "./lifecycle.js";
6
6
  import { deriveDagRerunFeedback } from "./rerun-feedback.js";
7
- import { acquireDagRecoveryLease, bindDagRecoveryLeaseExecution, } from "./recovery-lease.js";
8
7
  import { parseDagSpec, } from "./types.js";
9
8
  export const RERUN_TASK_LINEAGE_REL_PATH = ".runtime/rerun-task-lineage.json";
10
9
  export function parseDagRerunTaskArgs(args) {
@@ -370,34 +369,6 @@ export async function rerunStandaloneTask(input) {
370
369
  }
371
370
  }
372
371
  }
373
- const recoveryLease = execute
374
- ? await acquireDagRecoveryLease({
375
- cwd: input.cwd,
376
- parentRunId: input.parentRunId,
377
- requestId: input.requestId,
378
- kind: "standalone-task-rerun",
379
- })
380
- : undefined;
381
- if (recoveryLease?.kind === "held") {
382
- return blockedResult({
383
- parentRunId: input.parentRunId,
384
- reason: input.reason,
385
- requestId: input.requestId,
386
- blockedReason: "recovery-lease-held",
387
- note: `parent run recovery is already claimed by ${recoveryLease.lease.kind} request ${recoveryLease.lease.requestId}`,
388
- taskId: taskResolution.taskId,
389
- });
390
- }
391
- if (recoveryLease?.kind === "acquired") {
392
- // Persist a non-empty execution identity before generateTaskDagUseCase can
393
- // execute its new DAG. The generated run id is not available yet, so the
394
- // request id is the stable lineage handle for this entry point.
395
- await bindDagRecoveryLeaseExecution({
396
- leasePath: recoveryLease.leasePath,
397
- lease: recoveryLease.lease,
398
- executionRef: `standalone-task-rerun:${input.requestId}`,
399
- });
400
- }
401
372
  const generateResult = await generateTaskDagUseCase({
402
373
  repoRoot: input.cwd,
403
374
  taskId: taskResolution.taskId,
@@ -1,14 +1,61 @@
1
- import { projectProtocolFailureReason, } from "./frontend-recovery-capsule.js";
2
- import { TYPED_EVENT_FACT_KINDS } from "./frontend-typed-event-store.js";
1
+ import { z } from "zod";
3
2
  /**
4
- * Failure-category constants, the zod retry-policy schema, and the
5
- * target-template transient retry profile live in the leaf module
6
- * `dag-retry-schema.ts` (see its header for the cycle rationale). Everything
7
- * is re-exported here unchanged so retry-policy stays the single import
8
- * surface for retry policies and helpers.
3
+ * Failure categories that are safe to auto-retry for read-only Pi nodes.
4
+ *
5
+ * These are failures with no repository write side-effects: model connection
6
+ * interruption, provider rate-limiting, temporary provider unavailability,
7
+ * request timeout, or a settled read-only turn with no assistant text.
8
+ *
9
+ * `quota` is intentionally NOT included: a quota exhaustion is an account
10
+ * billing/plan state, not a transient rate limit, and retrying immediately
11
+ * will not help and may waste budget.
12
+ */
13
+ export const DEFAULT_DAG_RETRY_CATEGORIES = [
14
+ "timeout",
15
+ "network",
16
+ "rate-limit",
17
+ "unavailable",
18
+ "empty-output",
19
+ ];
20
+ export const STRUCTURED_OUTPUT_RETRY_CATEGORY = "output-too-large";
21
+ export const PROTOCOL_INVALID_RETRY_CATEGORY = "protocol-invalid";
22
+ /** Recoverable model artifact/schema formatting failure on read-only structured nodes. */
23
+ export const STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY = "invalid-output";
24
+ /** Provider stopReason=length truncated the response before the JSON contract completed. */
25
+ export const STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY = "structured-output-truncated";
26
+ /** Retry only a proven no-op from an explicitly opt-in bounded Pi writer. */
27
+ export const WRITER_EMPTY_DIFF_RETRY_CATEGORY = "writer-empty-diff";
28
+ /** Retry when a backend-test writer finished but Completeness Gate found missing/broken targets. */
29
+ export const INCOMPLETE_WRITE_SET_RETRY_CATEGORY = "incomplete-write-set";
30
+ /**
31
+ * Provider/transport stall or absolute timeout on a Pi exclusive writer that
32
+ * left zero attributed workspace writes and zero write-tool calls. Safe to
33
+ * retry once because the attempt was a pure provider flake (no side effects).
34
+ * Partial writes keep the original `timeout` category and do NOT retry.
9
35
  */
10
- export { ALL_DAG_RETRY_CATEGORIES, CONTEXT_OVERFLOW_RETRY_CATEGORY, DEFAULT_DAG_RETRY_CATEGORIES, INCOMPLETE_WRITE_SET_RETRY_CATEGORY, PROTOCOL_AWARE_DAG_RETRY_CATEGORIES, PROTOCOL_INVALID_RETRY_CATEGORY, READ_BURST_RETRY_CATEGORY, REVIEW_TERMINAL_MISSING_RETRY_CATEGORY, STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY, STRUCTURED_OUTPUT_RETRY_CATEGORY, STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY, STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES, TARGET_TEMPLATE_TRANSIENT_RETRY_PROFILE, WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY, WRITER_EMPTY_DIFF_RETRY_CATEGORY, dagRetryBackoffSchema, dagRetryCategorySchema, dagRetryPolicySchema, } from "./dag-retry-schema.js";
11
- import { CONTEXT_OVERFLOW_RETRY_CATEGORY, DEFAULT_DAG_RETRY_CATEGORIES, INCOMPLETE_WRITE_SET_RETRY_CATEGORY, PROTOCOL_AWARE_DAG_RETRY_CATEGORIES, READ_BURST_RETRY_CATEGORY, REVIEW_TERMINAL_MISSING_RETRY_CATEGORY, STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY, STRUCTURED_OUTPUT_RETRY_CATEGORY, STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES, TARGET_TEMPLATE_TRANSIENT_RETRY_PROFILE, WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY, WRITER_EMPTY_DIFF_RETRY_CATEGORY, } from "./dag-retry-schema.js";
36
+ export const WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY = "writer-clean-timeout";
37
+ export const STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES = [
38
+ ...DEFAULT_DAG_RETRY_CATEGORIES,
39
+ STRUCTURED_OUTPUT_RETRY_CATEGORY,
40
+ STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
41
+ STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY,
42
+ ];
43
+ /** Categories allowed on nodes that declare a machine-readable outputProtocol. */
44
+ export const PROTOCOL_AWARE_DAG_RETRY_CATEGORIES = [
45
+ ...DEFAULT_DAG_RETRY_CATEGORIES,
46
+ PROTOCOL_INVALID_RETRY_CATEGORY,
47
+ STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
48
+ ];
49
+ export const ALL_DAG_RETRY_CATEGORIES = [
50
+ ...DEFAULT_DAG_RETRY_CATEGORIES,
51
+ STRUCTURED_OUTPUT_RETRY_CATEGORY,
52
+ PROTOCOL_INVALID_RETRY_CATEGORY,
53
+ STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
54
+ STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY,
55
+ WRITER_EMPTY_DIFF_RETRY_CATEGORY,
56
+ INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
57
+ WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY,
58
+ ];
12
59
  const RETRY_SAFE_PI_ROLES = new Set([
13
60
  "planner",
14
61
  "scout",
@@ -17,38 +64,53 @@ const RETRY_SAFE_PI_ROLES = new Set([
17
64
  "supervisor",
18
65
  "closeout",
19
66
  ]);
67
+ export const dagRetryCategorySchema = z.enum(ALL_DAG_RETRY_CATEGORIES);
68
+ export const dagRetryBackoffSchema = z.enum(["exponential"]);
69
+ /**
70
+ * Opt-in retry policy for a DagTask. Generated for safe read-only Pi nodes,
71
+ * except the single validation-gated writer-empty-diff policy. Validation
72
+ * rejects all other writers, dynamic, shell, static, and decision-gate nodes.
73
+ */
74
+ export const dagRetryPolicySchema = z
75
+ .object({
76
+ /**
77
+ * Total number of attempts (including the first try). Must be 1..5.
78
+ * A value of 1 disables retry (one attempt, no retry).
79
+ */
80
+ maxAttempts: z.number().int().positive().max(5),
81
+ backoff: dagRetryBackoffSchema.default("exponential"),
82
+ /** Initial delay before the second attempt, in milliseconds. */
83
+ initialDelayMs: z.number().int().nonnegative().default(2000),
84
+ /** Upper bound on a single backoff delay, in milliseconds. */
85
+ maxDelayMs: z.number().int().nonnegative().default(30000),
86
+ /**
87
+ * Explicit set of failure categories eligible for retry. Defaults to
88
+ * {@link DEFAULT_DAG_RETRY_CATEGORIES}. `quota` and other categories
89
+ * are never retried.
90
+ */
91
+ retryCategories: z
92
+ .array(dagRetryCategorySchema)
93
+ .default([...DEFAULT_DAG_RETRY_CATEGORIES]),
94
+ })
95
+ .superRefine((policy, ctx) => {
96
+ if (policy.maxDelayMs < policy.initialDelayMs) {
97
+ ctx.addIssue({
98
+ code: z.ZodIssueCode.custom,
99
+ message: "retryPolicy.maxDelayMs must be >= retryPolicy.initialDelayMs",
100
+ path: ["maxDelayMs"],
101
+ });
102
+ }
103
+ });
20
104
  /**
21
105
  * The default retry policy applied to safe generated read-only Pi nodes.
22
106
  * Total attempts: 3, exponential backoff with cap.
23
- *
24
- * Includes `context-overflow`: a read-only node that blew the context window
25
- * (400 request too large, e.g. a review node accumulating too many reads) is a
26
- * transient, safe-to-retry failure — the retry re-runs the node with a
27
- * compact-context instruction instead of failing the whole run. Previously
28
- * only writer transport policies had context-overflow; contract/scout/
29
- * design-review/review fell straight to ERROR without a retry attempt.
30
107
  */
31
108
  export const DEFAULT_READ_ONLY_PI_RETRY_POLICY = {
32
109
  maxAttempts: 3,
33
110
  backoff: "exponential",
34
111
  initialDelayMs: 2000,
35
112
  maxDelayMs: 30000,
36
- retryCategories: [
37
- ...DEFAULT_DAG_RETRY_CATEGORIES,
38
- READ_BURST_RETRY_CATEGORY,
39
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
40
- ],
41
- };
42
- /** Scout is the discovery authority. A missing/incomplete typed target surface
43
- * is safe to retry in-node, rather than making Plan rediscover the repository. */
44
- export const FRONTEND_SCOUT_COMPLETENESS_RETRY_POLICY = {
45
- ...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
46
- retryCategories: [
47
- ...DEFAULT_DAG_RETRY_CATEGORIES,
48
- STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
49
- READ_BURST_RETRY_CATEGORY,
50
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
51
- ],
113
+ retryCategories: [...DEFAULT_DAG_RETRY_CATEGORIES],
52
114
  };
53
115
  /**
54
116
  * Structured planner nodes may retry with a compact-output instruction
@@ -58,11 +120,7 @@ export const FRONTEND_SCOUT_COMPLETENESS_RETRY_POLICY = {
58
120
  */
59
121
  export const STRUCTURED_REQUIRED_PI_RETRY_POLICY = {
60
122
  ...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
61
- retryCategories: [
62
- ...STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES,
63
- READ_BURST_RETRY_CATEGORY,
64
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
65
- ],
123
+ retryCategories: [...STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES],
66
124
  };
67
125
  /**
68
126
  * Planner read-only nodes (standard DAG contract-pi / plan-pi) may retry with
@@ -73,12 +131,7 @@ export const STRUCTURED_REQUIRED_PI_RETRY_POLICY = {
73
131
  */
74
132
  export const PLANNER_OUTPUT_LIMIT_RETRY_POLICY = {
75
133
  ...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
76
- retryCategories: [
77
- ...DEFAULT_DAG_RETRY_CATEGORIES,
78
- STRUCTURED_OUTPUT_RETRY_CATEGORY,
79
- READ_BURST_RETRY_CATEGORY,
80
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
81
- ],
134
+ retryCategories: [...DEFAULT_DAG_RETRY_CATEGORIES, STRUCTURED_OUTPUT_RETRY_CATEGORY],
82
135
  };
83
136
  /**
84
137
  * Default retry for reviewer / recovery nodes that declare outputProtocol.
@@ -88,22 +141,6 @@ export const PROTOCOL_AWARE_PI_RETRY_POLICY = {
88
141
  ...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
89
142
  retryCategories: [...PROTOCOL_AWARE_DAG_RETRY_CATEGORIES],
90
143
  };
91
- /**
92
- * frontend-review-pi retry policy. The review verdict must be committed
93
- * through the typed terminal tools (approve_review / request_review_changes);
94
- * a model that only echoes "VERDICT: pass" text fails as
95
- * review-terminal-missing. That is read-only and safe to retry with a
96
- * corrected instruction so a single model slip does not burn the whole run.
97
- */
98
- export const FRONTEND_REVIEW_TERMINAL_RETRY_POLICY = {
99
- ...DEFAULT_READ_ONLY_PI_RETRY_POLICY,
100
- retryCategories: [
101
- ...DEFAULT_DAG_RETRY_CATEGORIES,
102
- READ_BURST_RETRY_CATEGORY,
103
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
104
- REVIEW_TERMINAL_MISSING_RETRY_CATEGORY,
105
- ],
106
- };
107
144
  /**
108
145
  * The sole writer retry policy for requireChangedFiles writers. It is
109
146
  * intentionally not included in any read-only default: a writer may retry only
@@ -126,10 +163,7 @@ export const WRITER_TRANSPORT_RETRY_POLICY = {
126
163
  backoff: "exponential",
127
164
  initialDelayMs: 5000,
128
165
  maxDelayMs: 30000,
129
- retryCategories: [
130
- WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY,
131
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
132
- ],
166
+ retryCategories: [WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY],
133
167
  };
134
168
  /**
135
169
  * Implicit runtime retry for canonical final verify shells. Not a DagRetryPolicy:
@@ -148,23 +182,18 @@ export const VERIFY_SHELL_RETRY_POLICY = {
148
182
  maxDelayMs: 30000,
149
183
  retryCategories: VERIFY_SHELL_RETRY_CATEGORIES,
150
184
  };
185
+ export const TARGET_TEMPLATE_TRANSIENT_RETRY_PROFILE = "standard-reviewed-supervised-v1";
151
186
  /**
152
187
  * Target-template exclusive implement-pi transport retry. Same schema category
153
188
  * as frontend (`writer-clean-timeout`) so DagSpec validation stays unchanged;
154
- * only the delay cap is wider. Context overflow is added so a writer whose
155
- * session hit the context window (compact+retry inside the SDK) can retry once
156
- * more at the DAG level with a fresh attempt. Do not mutate
157
- * {@link WRITER_TRANSPORT_RETRY_POLICY}.
189
+ * only the delay cap is wider. Do not mutate {@link WRITER_TRANSPORT_RETRY_POLICY}.
158
190
  */
159
191
  export const TARGET_TEMPLATE_WRITER_TRANSPORT_RETRY_POLICY = {
160
192
  maxAttempts: 2,
161
193
  backoff: "exponential",
162
194
  initialDelayMs: 5000,
163
195
  maxDelayMs: 60000,
164
- retryCategories: [
165
- WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY,
166
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
167
- ],
196
+ retryCategories: [WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY],
168
197
  };
169
198
  /**
170
199
  * Backend-test generation writers: empty-diff once, plus bounded incomplete-write-set
@@ -180,6 +209,11 @@ export const BACKEND_TEST_WRITER_COMPLETENESS_RETRY_POLICY = {
180
209
  INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
181
210
  ],
182
211
  };
212
+ /** Markdown shard writers use one full attempt plus at most one bounded binding repair. */
213
+ export const BACKEND_TEST_MARKDOWN_BINDING_RETRY_POLICY = {
214
+ ...BACKEND_TEST_WRITER_COMPLETENESS_RETRY_POLICY,
215
+ maxAttempts: 2,
216
+ };
183
217
  /**
184
218
  * Deterministic helper: is this raw failure category eligible for retry under
185
219
  * the given policy? Pure function; executor never decides retry eligibility.
@@ -230,14 +264,13 @@ export function isWriterEmptyDiffRetryCandidate(task) {
230
264
  task.writerOutcomePolicy?.requireChangedFiles === true);
231
265
  }
232
266
  /**
233
- * Standard exclusive implementers (implementation-outcome and frontend-facts
234
- * writers) may take a single clean-timeout transport retry. Backend
235
- * completeness writers already have their own policy and are excluded here.
267
+ * Standard exclusive implementers (implementation-outcome writers) may take a
268
+ * single clean-timeout transport retry. Backend completeness writers already
269
+ * have their own policy and are excluded here.
236
270
  */
237
271
  export function isWriterTransportRetryCandidate(task) {
238
272
  return (isExclusivePiImplementer(task) &&
239
- (task.writerOutcomePolicy?.type === "implementation-outcome-v1" ||
240
- task.writerOutcomePolicy?.type === "frontend-facts-v1") &&
273
+ task.writerOutcomePolicy?.type === "implementation-outcome-v1" &&
241
274
  task.writerOutcomePolicy.requireChangedFiles !== true);
242
275
  }
243
276
  /**
@@ -342,141 +375,3 @@ export function computeBackoffDelayMs(attemptNumber, policy) {
342
375
  const raw = policy.initialDelayMs * 2 ** exponent;
343
376
  return Math.min(raw, policy.maxDelayMs);
344
377
  }
345
- /**
346
- * A+B (AC-001/AC-005): project raw executor signals to the canonical 7-value
347
- * protocol failure reason. Specific signals win first, then the existing
348
- * alias/enum passthrough; unknown signals fail closed to `undefined`.
349
- */
350
- export function projectFrontendNodeProtocolFailureReason(input) {
351
- // 1. length stop reason without a terminal → length-before-terminal.
352
- if (input.stopReason === "length" && input.hasTerminalFact === false) {
353
- return "length-before-terminal";
354
- }
355
- // 2. timeout with reasoning-side evidence → reasoning-timeout.
356
- if (input.failureCategory === "timeout" &&
357
- /(?:reasoning|thinking|thought)/i.test(input.assistantText ?? "")) {
358
- return "reasoning-timeout";
359
- }
360
- // 3. empty output without a terminal → provider-ended-without-terminal.
361
- if (input.failureCategory === "empty-output" &&
362
- input.hasTerminalFact === false) {
363
- return "provider-ended-without-terminal";
364
- }
365
- // 4. Alias/enum passthrough; unknown fails closed to undefined.
366
- return projectProtocolFailureReason(input.failureCategory ?? "");
367
- }
368
- export const FRONTEND_PLAN_LADDER = [
369
- "normal",
370
- "compact-terminal-first",
371
- "bounded-tool-only",
372
- "backup-model",
373
- ];
374
- /**
375
- * Map a 7-value protocol failure reason to the closest provider capability
376
- * fact kind for backup-model routing. `unsupported-tool-capability` is a
377
- * protocol reason, not a provider capability kind, so it is deliberately NOT
378
- * a valid route (fail-closed to `unsupported-provider-capability`).
379
- */
380
- export function frontendPlanProtocolReasonToCapabilityKind(reason) {
381
- switch (reason) {
382
- case "length-before-terminal":
383
- return "length-before-terminal";
384
- case "reasoning-timeout":
385
- return "reasoning-timeout";
386
- case "provider-ended-without-terminal":
387
- return "provider-ended-without-terminal";
388
- case "terminal-event-missing":
389
- case "terminal-conflict":
390
- return "terminal-commit";
391
- case "typed-fact-invalid":
392
- return "read-only-fact-channel";
393
- case "unsupported-tool-capability":
394
- return "unsupported-tool-capability";
395
- default:
396
- return undefined;
397
- }
398
- }
399
- /**
400
- * A+B (AC-003): resolve a backup-model route against the frozen seven-kind
401
- * provider capability catalog (the exact set `routeFrontendProviderCapability`
402
- * consults). `unsupported-tool-capability` is a protocol reason, not a
403
- * provider capability kind, so it (and any unmapped reason) fails closed to
404
- * `unsupported-provider-capability` — never swapped for the 7-value reason.
405
- */
406
- export function resolveFrontendPlanBackupRoute(reason) {
407
- const factKind = frontendPlanProtocolReasonToCapabilityKind(reason);
408
- if (!factKind) {
409
- return { ok: false, reason: "unsupported-provider-capability" };
410
- }
411
- return TYPED_EVENT_FACT_KINDS.includes(factKind)
412
- ? { ok: true, factKind }
413
- : { ok: false, reason: "unsupported-provider-capability" };
414
- }
415
- /**
416
- * A+B (AC-002): deterministic ladder resolution. Reason-mandated upgrades
417
- * (length → compact-terminal-first; terminal/timeout/empty → bounded-tool-only)
418
- * never regress below the current rung. A repeated failure fingerprint with no
419
- * new committed fact escalates one rung instead of re-running the same step;
420
- * at `backup-model` that becomes `non-converging`, and an unavailable backup
421
- * provider route fails closed to `unsupported-provider-capability`.
422
- */
423
- export function resolveFrontendPlanRetryStep(input) {
424
- if (input.currentStep === "non-converging" ||
425
- input.currentStep === "unsupported-provider-capability") {
426
- return input.currentStep;
427
- }
428
- const currentIndex = FRONTEND_PLAN_LADDER.indexOf(input.currentStep);
429
- const reasonStep = reasonMandatedFrontendPlanRetryStep(input.protocolFailureReason);
430
- const reasonIndex = reasonStep
431
- ? FRONTEND_PLAN_LADDER.indexOf(reasonStep)
432
- : -1;
433
- let nextIndex = Math.max(currentIndex, reasonIndex);
434
- const repeated = input.priorFingerprints.includes(input.fingerprint);
435
- if (repeated && !input.hasNewCommittedFact) {
436
- nextIndex = Math.max(nextIndex, currentIndex + 1);
437
- }
438
- const nextStep = nextIndex >= FRONTEND_PLAN_LADDER.length
439
- ? "non-converging"
440
- : (FRONTEND_PLAN_LADDER[nextIndex] ?? "non-converging");
441
- if (nextStep === "backup-model" && input.backupRouteAvailable === false) {
442
- return "unsupported-provider-capability";
443
- }
444
- return nextStep;
445
- }
446
- function reasonMandatedFrontendPlanRetryStep(reason) {
447
- switch (reason) {
448
- case "length-before-terminal":
449
- return "compact-terminal-first";
450
- case "terminal-event-missing":
451
- case "reasoning-timeout":
452
- case "provider-ended-without-terminal":
453
- return "bounded-tool-only";
454
- default:
455
- return undefined;
456
- }
457
- }
458
- /**
459
- * Opt-in retry policy mounted on the frontend-plan-pi node. maxAttempts=3
460
- * bounds plan retry cost: the four-rung ladder is only partially traversable
461
- * before the run fails non-converging (rungs: normal → bounded-tool-only →
462
- * compact-terminal-first → backup-model). `invalid-output` (typed-fact schema
463
- * violations, e.g. verification targets referencing undeclared UI states)
464
- * retries at the `normal` rung with the contractCheck reason injected via
465
- * `<retry_instruction>` (§5.1 ladder).
466
- */
467
- export const FRONTEND_PLAN_LADDER_RETRY_POLICY = {
468
- // Extreme-environment (small output window) plan nodes submit dozens of
469
- // incremental record_* calls; dense call bursts hit provider rate limits
470
- // whose windows exceed the old 30s cap. Longer backoff gives the limit
471
- // window time to expire before the next attempt.
472
- maxAttempts: 3,
473
- backoff: "exponential",
474
- initialDelayMs: 5000,
475
- maxDelayMs: 60000,
476
- retryCategories: [
477
- ...DEFAULT_DAG_RETRY_CATEGORIES,
478
- STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
479
- READ_BURST_RETRY_CATEGORY,
480
- CONTEXT_OVERFLOW_RETRY_CATEGORY,
481
- ],
482
- };