@tea-agent/loop-agent 0.43.0-next.8 → 0.43.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 (291) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +41 -2312
  3. package/README.md +7 -0
  4. package/dist/application/dag/args.js +8 -0
  5. package/dist/application/task-lifecycle/advance.js +38 -7
  6. package/dist/build-stamp.json +3 -3
  7. package/dist/cli/command-definitions.js +2 -0
  8. package/dist/cli/program.js +3 -1
  9. package/dist/cli/update/init-surface-notifier.js +2 -0
  10. package/dist/cli/update/policy.js +2 -0
  11. package/dist/commands/client-recovery.js +20 -55
  12. package/dist/commands/cursor-prompt.js +2 -0
  13. package/dist/commands/dag-approve.js +2 -0
  14. package/dist/commands/dag-final-verification.js +2 -0
  15. package/dist/commands/dag-init-hybrid.js +2 -0
  16. package/dist/commands/dag-reconcile-tasks.js +2 -0
  17. package/dist/commands/dag-reject.js +2 -0
  18. package/dist/commands/dag-report.js +2 -0
  19. package/dist/commands/dag-rerun.js +2 -0
  20. package/dist/commands/dag-resume.js +2 -0
  21. package/dist/commands/dag-workflow-compile.js +2 -0
  22. package/dist/commands/dag-workflow-plan.js +2 -0
  23. package/dist/commands/dag-workflow-validate.js +2 -0
  24. package/dist/commands/delegate.js +2 -0
  25. package/dist/commands/examples.js +2 -0
  26. package/dist/commands/import-prd.js +2 -0
  27. package/dist/commands/init-model-catalog.js +2 -0
  28. package/dist/commands/init.js +19 -13
  29. package/dist/commands/instructions.js +2 -0
  30. package/dist/commands/knowledge.js +2 -0
  31. package/dist/commands/loop-benchmark.js +2 -0
  32. package/dist/commands/pi-prompt.js +2 -0
  33. package/dist/commands/pi-reuse-benchmark.js +2 -0
  34. package/dist/commands/promote-run.js +2 -0
  35. package/dist/commands/stats.js +1 -1
  36. package/dist/commands/study-init.js +2 -0
  37. package/dist/commands/task-advance.js +34 -0
  38. package/dist/commands/task-source-prepare.js +2 -0
  39. package/dist/commands/worktree-create.js +2 -0
  40. package/dist/commands/worktree-remove.js +2 -0
  41. package/dist/executors/dag-pi-executor.js +1650 -198
  42. package/dist/executors/pi-executor.js +85 -3
  43. package/dist/executors/pi-sdk-executor.js +18 -0
  44. package/dist/executors/shell-executor.js +93 -7
  45. package/dist/executors/shell-verification.js +3 -0
  46. package/dist/executors/shell-write-guard.js +27 -32
  47. package/dist/governance/exec-plans.js +6 -3
  48. package/dist/infrastructure/console/app-data.js +6 -0
  49. package/dist/shared/artifacts-core.js +2 -0
  50. package/dist/shared/backend-dogfood-preflight.js +47 -0
  51. package/dist/shared/dag-failure-category.js +3 -0
  52. package/dist/shared/git-progress.js +2 -0
  53. package/dist/shared/one-shot-prompt-args.js +2 -0
  54. package/dist/shared/operator/capabilities.js +180 -0
  55. package/dist/shared/package-metadata.js +6 -4
  56. package/dist/shared/pi-context-pressure/extension.js +26 -16
  57. package/dist/shared/pi-context-pressure/sift-bridge.js +1 -1
  58. package/dist/shared/pi-provider-recovery.js +182 -0
  59. package/dist/shared/pi-retry-settings.js +40 -0
  60. package/dist/shared/reference-context.js +2 -0
  61. package/dist/task/config-types.js +29 -0
  62. package/dist/task/contract/project.js +9 -0
  63. package/dist/task/contract/recover.js +6 -0
  64. package/dist/task/contract/schema.js +17 -0
  65. package/dist/task/source-prepare/artifact-meta.js +9 -2
  66. package/dist/task/source-prepare/build-draft.js +60 -0
  67. package/dist/task/source-prepare/fragment-inventory.js +4 -1
  68. package/dist/task/source-prepare/parse-intent.js +36 -11
  69. package/dist/task/task-demand-routing.js +5 -2
  70. package/dist/worker/console/chat/browser-automation.js +523 -0
  71. package/dist/worker/console/chat/browser-policy.js +6 -36
  72. package/dist/worker/console/chat/browser-routes.js +188 -56
  73. package/dist/worker/console/chat/explore-tools.js +5 -2
  74. package/dist/worker/console/chat/pi-mode-loop-isolation.js +155 -0
  75. package/dist/worker/console/chat/pi-runtime/custom-tools/ask-user-question.js +44 -0
  76. package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +184 -0
  77. package/dist/worker/console/chat/pi-runtime/custom-tools/explore-tools.js +202 -0
  78. package/dist/worker/console/chat/pi-runtime/custom-tools/goal-tools.js +79 -0
  79. package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +94 -0
  80. package/dist/worker/console/chat/pi-runtime/custom-tools/scheduled-goal-tools.js +22 -0
  81. package/dist/worker/console/chat/pi-runtime/custom-tools/todo-write.js +38 -0
  82. package/dist/worker/console/chat/pi-runtime/inspection-types.js +28 -0
  83. package/dist/worker/console/chat/pi-runtime/inspection.js +439 -0
  84. package/dist/worker/console/chat/pi-runtime/progressive-tools.js +195 -0
  85. package/dist/worker/console/chat/pi-runtime/sdk-bindings.js +153 -0
  86. package/dist/worker/console/chat/pi-runtime/sdk-session.js +5 -0
  87. package/dist/worker/console/chat/pi-runtime.js +208 -1138
  88. package/dist/worker/console/chat/routes.js +59 -24
  89. package/dist/worker/console/chat/scheduled-goal-booking.js +59 -0
  90. package/dist/worker/console/chat/scheduled-goal-delivery.js +27 -0
  91. package/dist/worker/console/chat/scheduled-goal-request.js +190 -0
  92. package/dist/worker/console/chat/sdd-data-alignment.js +1 -1
  93. package/dist/worker/console/chat/session-mode-view.js +5 -4
  94. package/dist/worker/console/chat/session-mode.js +18 -12
  95. package/dist/worker/console/chat/session-store.js +42 -9
  96. package/dist/worker/console/chat/terminal-sessions.js +65 -1
  97. package/dist/worker/console/chat/terminal-tools.js +17 -5
  98. package/dist/worker/console/chat/tool-preview.js +115 -0
  99. package/dist/worker/console/chat/tools.js +10 -0
  100. package/dist/worker/console/chat/turn-order.js +13 -0
  101. package/dist/worker/console/chat/turn-process.js +32 -30
  102. package/dist/worker/console/console-update-and-init.js +1 -19
  103. package/dist/worker/console/console-update-runtime.js +5 -20
  104. package/dist/worker/console/operator-actions.js +63 -1
  105. package/dist/worker/console/prd-intake-bridge.js +54 -1
  106. package/dist/worker/console/routes.js +8 -0
  107. package/dist/worker/console/scheduled-goal-host.js +98 -0
  108. package/dist/worker/console/scheduled-goal-operation-adapter.js +127 -0
  109. package/dist/worker/console/server.js +24 -1
  110. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CwAxHSAM.js → abnfDiagram-N423BO3Z-8-j6y-sd.js} +1 -1
  111. package/dist/worker/console/static/assets/{arc-Bozf-oeF.js → arc-eoQiMvuk.js} +1 -1
  112. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEypbEQv.js → architectureDiagram-T3A2C74G-C4A3uMcI.js} +1 -1
  113. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-B1BQWCbE.js → blockDiagram-VBNYF7ZC-D4zD2F-Q.js} +1 -1
  114. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B3u5-yZz.js → c4Diagram-5PPSVZJV-j1RkJziL.js} +1 -1
  115. package/dist/worker/console/static/assets/channel-ChE7y-cx.js +1 -0
  116. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DSUc2NTh.js → chunk-2GRJ4B5K-YBHmhik1.js} +1 -1
  117. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DZouMIvT.js → chunk-2Q5K7J3B-COfWyo9P.js} +1 -1
  118. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-B3bhB5hh.js → chunk-5RXB4S5H-I99OUkHY.js} +1 -1
  119. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CZFP_BOz.js → chunk-5VM5RSS4-XKxoJNJ4.js} +1 -1
  120. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DnE_wb-X.js → chunk-6Q2QTUOP-DLT_cYx1.js} +1 -1
  121. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C2OfoiWm.js → chunk-GF5L2VYU-CxcKZ9mV.js} +1 -1
  122. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BKUTL8mm.js → chunk-JWPE2WC7-V1EqXdjY.js} +1 -1
  123. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BT5oz0tg.js → chunk-KBJHAD2P-DebTtdFp.js} +1 -1
  124. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-D8vk-GJi.js → chunk-RYQCIY6F-B-ivNRDf.js} +1 -1
  125. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CkUIm3zu.js → chunk-XXDRQBXY-DC_Ds11b.js} +1 -1
  126. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +1 -0
  127. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +1 -0
  128. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CO9QNHmR.js → cose-bilkent-JH36ORCC-sWEqKwIb.js} +1 -1
  129. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-s52EPl2Z.js → cynefin-VYW2F7L2-BXa_dcu4.js} +1 -1
  130. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BHaseJfW.js → cynefinDiagram-MW4NZA55-C-Mle84F.js} +1 -1
  131. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CTVhRG_R.js → dagre-VZM6K2ZE-CXPDBITe.js} +1 -1
  132. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B6pYeOMR.js → diagram-7IWD3JNH-CC-WJQfa.js} +1 -1
  133. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CXXRzw5j.js → diagram-B4RE2ZJO-CDAV5Vs4.js} +1 -1
  134. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BOeJHiLA.js → diagram-LBJQPF4R-CmFiAcNz.js} +1 -1
  135. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DbEg6h_l.js → diagram-Q27KOJAE-DPBZHuyn.js} +1 -1
  136. package/dist/worker/console/static/assets/{diagram-UB23O5K3-CjlEcbX6.js → diagram-UB23O5K3-jUlm_Ds3.js} +1 -1
  137. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BcqMPbD_.js → ebnfDiagram-BXEA7PRR-DWhQ3mfY.js} +1 -1
  138. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DWfRyHe5.js → erDiagram-JOGREHBK-Tr2gMqet.js} +1 -1
  139. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-Bz7TeIc8.js → flowDiagram-UKHOOZJN-DJjVQHPA.js} +1 -1
  140. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BD-JxYjU.js → ganttDiagram-PKOTCBZU-D74dQ4u0.js} +1 -1
  141. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Cv16vMHK.js → gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js} +1 -1
  142. package/dist/worker/console/static/assets/index-BWkIfcrK.css +1 -0
  143. package/dist/worker/console/static/assets/index-Cdkvw_H6.js +469 -0
  144. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BlWO0HQQ.js → infoDiagram-6WML65LV-ILCbxJyb.js} +1 -1
  145. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-C4mbsn97.js → ishikawaDiagram-WSZJBQD7-DeuWBQ89.js} +1 -1
  146. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CBPvVKjw.js → journeyDiagram-NVQOT4AX-CF5ih8Fk.js} +1 -1
  147. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DPHLp54K.js → kanban-definition-27J2QSJJ-C7yOSuRO.js} +1 -1
  148. package/dist/worker/console/static/assets/{linear-CXx_9o6k.js → linear-BDZ9riWi.js} +1 -1
  149. package/dist/worker/console/static/assets/{mermaid.core-DU3IxMq9.js → mermaid.core-7pKqYtpZ.js} +5 -5
  150. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-COm4a2ud.js → mindmap-definition-FAOFIHXS-LeJDybSU.js} +1 -1
  151. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Cbt7OA5d.js → pegDiagram-VL7TDLO6-BJvT3pMD.js} +1 -1
  152. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BiYV_4Wl.js → pieDiagram-7S7Q4E2Y-_rGqpMan.js} +1 -1
  153. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-lg2zhvbp.js → quadrantDiagram-CIZ2JOQS-DPcSv5aA.js} +1 -1
  154. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-cBLvtf0p.js → railroadDiagram-AXF67PYL-Drxx4hkJ.js} +1 -1
  155. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BoekU3Bg.js → requirementDiagram-LRYGKXZP-BCTUdU4z.js} +1 -1
  156. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-D_DMZYga.js → sankeyDiagram-W5VNT64P-B6wzbZmB.js} +1 -1
  157. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-Lzmzn8lz.js → sequenceDiagram-SI44F4Z6-BGt8d3QQ.js} +1 -1
  158. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-Cos3HpIe.js → sizeCapture-X5ZJPWSS-7nlhJKo7.js} +1 -1
  159. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-D-hFBGsx.js → stateDiagram-OKZ733FA-Cv2stqMA.js} +1 -1
  160. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +1 -0
  161. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BY95sCVI.js → swimlanes-SLNWSIFB-qDAo4Yc1.js} +2 -2
  162. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +8 -0
  163. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-D1iCgWHS.js → timeline-definition-Z64GVDOM-CKbDNKTr.js} +1 -1
  164. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D9IYy4WK.js → vennDiagram-T6HMQDX7-DI-9EHic.js} +1 -1
  165. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C9yJwO-R.js → wardleyDiagram-T6FBY63Y-BrzzRDpX.js} +1 -1
  166. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CC2llyou.js → xychartDiagram-ELKLHX3M-BclH5hGh.js} +1 -1
  167. package/dist/worker/console/static/index.html +2 -2
  168. package/dist/worker/console/static-src/operator-chat/active-turn-tail.js +10 -0
  169. package/dist/worker/console/static-src/operator-chat/chat-scroll-position.js +24 -0
  170. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +41 -11
  171. package/dist/worker/console/static-src/operator-chat/compaction-message.js +10 -17
  172. package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +192 -0
  173. package/dist/worker/console/static-src/operator-chat/pending-user-message.js +9 -1
  174. package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +15 -5
  175. package/dist/worker/console/static-src/operator-chat/timeline-merge.js +29 -0
  176. package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +10 -0
  177. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +105 -44
  178. package/dist/worker/console/static-src/operator-chat/useChatStream.js +145 -70
  179. package/dist/worker/console/static-src/operator-chat/useChatThread.js +38 -57
  180. package/dist/worker/console/static-src/operator-chat/useComposer.js +195 -73
  181. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +2 -0
  182. package/dist/worker/console/static-src/prd-file-import.js +3 -1
  183. package/dist/worker/console/workspace-context.js +22 -0
  184. package/dist/worker/console/workspace-initialization.js +209 -0
  185. package/dist/worker/delivery/git-transaction.js +2 -0
  186. package/dist/worker/feature/fullstack-validate.js +2 -0
  187. package/dist/worker/loop-agent/loop-agent-client.js +8 -2
  188. package/dist/worker/materialize/harness-task-materializer.js +4 -1
  189. package/dist/worker/metrics/projector.js +1 -1
  190. package/dist/worker/observability/event-store.js +4 -1
  191. package/dist/worker/observability/read-model.js +4 -1
  192. package/dist/worker/observe/node-transparency.js +23 -1
  193. package/dist/worker/observe/routes.js +4 -0
  194. package/dist/worker/observe/static/operator-chrome.js +3 -1
  195. package/dist/worker/observe/static/styles.css +7 -4
  196. package/dist/worker/observe/static/views/dag-inspector.js +5 -19
  197. package/dist/worker/outcomes/declared-artifacts.js +2 -0
  198. package/dist/worker/preflight.js +3 -0
  199. package/dist/worker/scheduler/scheduled-goal-dispatch.js +117 -0
  200. package/dist/worker/scheduler/scheduled-goal-evidence.js +167 -0
  201. package/dist/worker/scheduler/scheduled-goal-recovery.js +62 -0
  202. package/dist/worker/scheduler/scheduled-goal-store.js +699 -0
  203. package/dist/worker/scheduler/scheduled-goal-supervisor.js +132 -0
  204. package/dist/worker/scheduler/scheduled-goal-time.js +102 -0
  205. package/dist/worker/scheduler/scheduled-goal-types.js +95 -0
  206. package/dist/worker/task-spec/validate.js +4 -1
  207. package/dist/workflows/dag/backend-test-markdown-workflow.js +6 -24
  208. package/dist/workflows/dag/backend-test-plan-protocol.js +82 -5
  209. package/dist/workflows/dag/dag-retry-schema.js +11 -0
  210. package/dist/workflows/dag/decision-envelope.js +2 -0
  211. package/dist/workflows/dag/dynamic-runtime/shared.js +2 -2
  212. package/dist/workflows/dag/frontend-closeout.js +3 -1
  213. package/dist/workflows/dag/frontend-committed-facts.js +461 -0
  214. package/dist/workflows/dag/frontend-durable-tools.js +15 -3
  215. package/dist/workflows/dag/frontend-implementation-contract.js +369 -12
  216. package/dist/workflows/dag/frontend-plan-canary.js +53 -0
  217. package/dist/workflows/dag/frontend-plan-decision-contract.js +803 -0
  218. package/dist/workflows/dag/frontend-plan-render.js +0 -2
  219. package/dist/workflows/dag/frontend-provider-capability-matrix.js +8 -61
  220. package/dist/workflows/dag/frontend-recovery-run.js +57 -0
  221. package/dist/workflows/dag/frontend-repair.js +55 -76
  222. package/dist/workflows/dag/frontend-review-context.js +42 -68
  223. package/dist/workflows/dag/frontend-review-scopes.js +2 -2
  224. package/dist/workflows/dag/frontend-risk.js +92 -10
  225. package/dist/workflows/dag/frontend-session-budget.js +117 -3
  226. package/dist/workflows/dag/frontend-shape.js +11 -55
  227. package/dist/workflows/dag/frontend-test-execution-evidence.js +35 -10
  228. package/dist/workflows/dag/frontend-typed-event-store.js +32 -25
  229. package/dist/workflows/dag/frontend-verification-trace.js +33 -54
  230. package/dist/workflows/dag/frontend-writer-admission.js +3 -47
  231. package/dist/workflows/dag/frontend-writer-status.js +0 -23
  232. package/dist/workflows/dag/init-hybrid.js +47 -19
  233. package/dist/workflows/dag/interrupt-request.js +2 -0
  234. package/dist/workflows/dag/lifecycle.js +11 -2
  235. package/dist/workflows/dag/node-execution.js +50 -13
  236. package/dist/workflows/dag/reconcile-run.js +2 -0
  237. package/dist/workflows/dag/repair-artifact.js +3 -1
  238. package/dist/workflows/dag/report.js +2 -0
  239. package/dist/workflows/dag/rerun-plan.js +10 -0
  240. package/dist/workflows/dag/rerun-task.js +79 -1
  241. package/dist/workflows/dag/retry-policy.js +18 -0
  242. package/dist/workflows/dag/scheduler.js +2 -4
  243. package/dist/workflows/dag/types.js +44 -6
  244. package/dist/workflows/dag/validate.js +4 -0
  245. package/docs/README.md +1 -0
  246. package/docs/architecture/runtime-boundaries.md +3 -3
  247. package/docs/governance/README.md +1 -0
  248. package/docs/init-surface.manifest.json +1 -0
  249. package/docs/operations/README.md +2 -0
  250. package/docs/templates/README.md +1 -1
  251. package/docs/templates/agent-dag.schema.json +2 -2
  252. package/docs/templates/backend-test-dag.json +14 -10
  253. package/docs/templates/frontend-implementation-contract.schema.json +0 -7
  254. package/package.json +9 -3
  255. package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
  256. package/skills/frontend-contract/references/contract-protocol.md +3 -1
  257. package/skills/frontend-plan/SKILL.md +8 -6
  258. package/skills/frontend-plan/references/decision-contract.md +3 -3
  259. package/skills/frontend-review/SKILL.md +18 -28
  260. package/skills/frontend-review/references/review-findings.md +8 -3
  261. package/dist/commands/new-task.js +0 -5
  262. package/dist/commands/status.js +0 -57
  263. package/dist/commands/task-contract.js +0 -269
  264. package/dist/shared/prompts.js +0 -26
  265. package/dist/task/config.js +0 -2
  266. package/dist/task/contract/validate-draft.js +0 -106
  267. package/dist/task/goal.js +0 -3
  268. package/dist/task/index.js +0 -12
  269. package/dist/task/lifecycle.js +0 -1
  270. package/dist/task/operator/capabilities.js +0 -6
  271. package/dist/task/operator/envelope.js +0 -2
  272. package/dist/task/operator/index.js +0 -5
  273. package/dist/task/operator/registry.js +0 -2
  274. package/dist/task/operator/types.js +0 -1
  275. package/dist/task/paths.js +0 -1
  276. package/dist/task/source-state.js +0 -1
  277. package/dist/task/subagent-guidance.js +0 -1
  278. package/dist/worker/console/chat/sift-bridge.js +0 -1
  279. package/dist/worker/console/index.js +0 -20
  280. package/dist/worker/console/static/assets/channel-JM-I_b0s.js +0 -1
  281. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DuQQAYEg.js +0 -1
  282. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DuQQAYEg.js +0 -1
  283. package/dist/worker/console/static/assets/index-B5H-giS2.js +0 -468
  284. package/dist/worker/console/static/assets/index-Bf7dxfm-.css +0 -1
  285. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-img0hVJ4.js +0 -1
  286. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B4acZJvk.js +0 -8
  287. package/dist/worker/scheduler/index.js +0 -25
  288. package/dist/workflows/dag/facts.js +0 -4
  289. package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -975
  290. package/dist/workflows/dag/index.js +0 -6
  291. package/dist/workflows/dynamic/index.js +0 -7
@@ -392,6 +392,147 @@ const COMMON_MUTATION_ERRORS = [
392
392
  ];
393
393
  export function buildOperatorCapabilitiesDocument() {
394
394
  const actions = [
395
+ {
396
+ action: "prepareScheduledTask", cli: "console scheduled task preparation", kind: "mutation",
397
+ inputSchemaVersion: 1, resultSchemaVersion: 1, envelopeSchemaVersion: 1, requiredErrorCodes: ["INVALID_INPUT"],
398
+ description: "Preferred entry for natural-language one-time scheduled tasks, including read-only inspection reports. Call this directly after understanding the goal, output scope, executable acceptance and time; the server uses the CURRENT project directory and creates the immutable PRD, managed Task and strict writeSet gate, binds THIS Chat automatically and returns a REAL planned goal/confirmation card. No pre-existing task, worktree or session ID is needed: never ask the user for these internal fields and do not manually create/edit them with bash/write/newTask/importPrd. Keep preparation concise: preserve the user goal without inventing extra requirements. Omit budget for ordinary tasks. Use minimal independent acceptance commands (AC-1, AC-2), preferably existing test/build scripts or test -s scheduled-report.md for a report; no compound shell/pipelines/substitution, language-specific grep checks or redundant scope assertions (the host enforces scope). Infer routine defaults and verification commands from the repository; ask only about genuinely ambiguous goal/scope/time. For read-only requests allow just an ordinary report file in the current project directory, e.g. scheduled-report.md, not .harness/. Use schedule.delayMinutes for relative time (counted after preparation finishes), or localAt + IANA timezone for an exact date/time. The current workspace must match committed HEAD; never auto-commit/stash/reset existing changes. The card exposes the exact time, bounded defaults and committed base before one human confirmation. Same request in this Chat is idempotent. Only a returned goalId with state=planned is a prepared reservation; textual drafts, Tasks or failed operations are NOT bookings. Never replace a requested schedule with immediate execution or sleep, never call runDag or self-confirm. On failure explain the returned stage, correct business inputs and retry this tool; do not mutate imported PRD/runtime artifacts. For a new distinct appointment, make its goal/time distinct.",
399
+ inputParams: [{ name: "request", type: "object", required: true, description: "Business goal, workflow, allowedPaths, acceptance and schedule; optional forbiddenPaths/budget. Runtime identity is server-owned." }],
400
+ modelCallable: "always", humanConfirmation: "none",
401
+ },
402
+ {
403
+ "action": "prepareScheduledGoal",
404
+ "cli": "console scheduled goal service",
405
+ "kind": "mutation",
406
+ "inputSchemaVersion": 1,
407
+ "resultSchemaVersion": 1,
408
+ "envelopeSchemaVersion": 1,
409
+ "requiredErrorCodes": [
410
+ "INVALID_INPUT"
411
+ ],
412
+ "description": "Advanced entry ONLY for an already prepared Task. For a new natural-language reservation use prepareScheduledTask instead. Requires the current repository or its linked worktree at frozenBase and a managed Task already strict-prepared at its writeSet gate. booking must include managedTaskId, originalGoal, chatSessionRef, workflow, worktreeRef, frozenBase, allowedPaths, forbiddenPaths, acceptance {policy, criteria [{acId,description,command}]}, budget {maxTurns,maxDagRuns,maxSupervisorCalls}, time {executeAtUtc,latestStartUtc,stopAtUtc,expiresAt,timezone,allowedHours,misfirePolicy}. Resolve natural-language dates with the user timezone; ask about ambiguous time/AC/scope. No execution or authorization occurs. Show the complete scope/time/budget for one browser confirmation. Never call runDag for this reservation.",
413
+ "inputParams": [
414
+ {
415
+ "name": "booking",
416
+ "type": "object",
417
+ "required": true,
418
+ "description": "Complete frozen booking inputs; never supply prepared, controllerRef, approval or owner tokens."
419
+ }
420
+ ],
421
+ "modelCallable": "always",
422
+ "humanConfirmation": "none"
423
+ },
424
+ {
425
+ "action": "confirmScheduledGoal",
426
+ "cli": "console scheduled goal service",
427
+ "kind": "mutation",
428
+ "inputSchemaVersion": 1,
429
+ "resultSchemaVersion": 1,
430
+ "envelopeSchemaVersion": 1,
431
+ "requiredErrorCodes": [
432
+ "INVALID_INPUT"
433
+ ],
434
+ "description": "Human browser confirmation of the exact displayed ScheduledGoal envelope.",
435
+ "inputParams": [
436
+ {
437
+ "name": "goalId",
438
+ "type": "string",
439
+ "required": true,
440
+ "description": "Prepared goal id"
441
+ },
442
+ {
443
+ "name": "stateVersion",
444
+ "type": "number",
445
+ "required": true,
446
+ "description": "Displayed state version"
447
+ },
448
+ {
449
+ "name": "envelopeHash",
450
+ "type": "string",
451
+ "required": true,
452
+ "description": "Displayed envelope hash"
453
+ }
454
+ ],
455
+ "modelCallable": "never",
456
+ "humanConfirmation": "required"
457
+ },
458
+ {
459
+ "action": "cancelScheduledGoal",
460
+ "cli": "console scheduled goal service",
461
+ "kind": "mutation",
462
+ "inputSchemaVersion": 1,
463
+ "resultSchemaVersion": 1,
464
+ "envelopeSchemaVersion": 1,
465
+ "requiredErrorCodes": [
466
+ "INVALID_INPUT"
467
+ ],
468
+ "description": "Cancel future ScheduledGoal admission; in-flight/unknown ownership remains until reconciled.",
469
+ "inputParams": [
470
+ {
471
+ "name": "goalId",
472
+ "type": "string",
473
+ "required": true,
474
+ "description": "Goal id"
475
+ },
476
+ {
477
+ "name": "stateVersion",
478
+ "type": "number",
479
+ "required": true,
480
+ "description": "Current state version"
481
+ },
482
+ {
483
+ "name": "reason",
484
+ "type": "string",
485
+ "required": true,
486
+ "description": "Human cancellation reason"
487
+ }
488
+ ],
489
+ "modelCallable": "never",
490
+ "humanConfirmation": "required"
491
+ },
492
+ {
493
+ "action": "scheduledGoalGet",
494
+ "cli": "console scheduled goal service",
495
+ "kind": "read",
496
+ "inputSchemaVersion": 1,
497
+ "resultSchemaVersion": 1,
498
+ "envelopeSchemaVersion": 1,
499
+ "requiredErrorCodes": [
500
+ "INVALID_INPUT"
501
+ ],
502
+ "description": "Read a durable ScheduledGoal booking and separate execution, acceptance, delivery and reconciliation results. Never implies authorization.",
503
+ "inputParams": [
504
+ {
505
+ "name": "goalId",
506
+ "type": "string",
507
+ "required": true,
508
+ "description": "Goal id"
509
+ }
510
+ ],
511
+ "modelCallable": "always",
512
+ "humanConfirmation": "none"
513
+ },
514
+ {
515
+ "action": "scheduledGoalList",
516
+ "cli": "console scheduled goal service",
517
+ "kind": "read",
518
+ "inputSchemaVersion": 1,
519
+ "resultSchemaVersion": 1,
520
+ "envelopeSchemaVersion": 1,
521
+ "requiredErrorCodes": [
522
+ "INVALID_INPUT"
523
+ ],
524
+ "description": "List durable ScheduledGoals, including those whose original Chat was archived or deleted.",
525
+ "inputParams": [
526
+ {
527
+ "name": "chatSessionRef",
528
+ "type": "string",
529
+ "required": false,
530
+ "description": "Optional original Chat session id"
531
+ }
532
+ ],
533
+ "modelCallable": "always",
534
+ "humanConfirmation": "none"
535
+ },
395
536
  {
396
537
  action: "operatorCapabilities",
397
538
  cli: "loop-agent operator capabilities --json",
@@ -714,6 +855,24 @@ export function buildOperatorCapabilitiesDocument() {
714
855
  required: false,
715
856
  description: "optional verify commands (label:command or shell)",
716
857
  },
858
+ {
859
+ name: "requirementOwnership",
860
+ type: "array",
861
+ required: false,
862
+ description: "optional frozen requirement→file ownership for frontend-implementation DAGs: [{requirementIds, implementationFiles?, verificationFiles?}] — machine-enforced at plan finalize",
863
+ },
864
+ {
865
+ name: "capabilityBoundary",
866
+ type: "array",
867
+ required: false,
868
+ description: "optional frozen test capability boundary {allowed?, forbidden?} composed into dependencyPolicy by the runtime",
869
+ },
870
+ {
871
+ name: "interactionIds",
872
+ type: "array",
873
+ required: false,
874
+ description: "optional frozen interaction id vocabulary — contract interaction names are machine-checked against it at plan finalize",
875
+ },
717
876
  ],
718
877
  modelCallable: "always",
719
878
  humanConfirmation: "none",
@@ -1069,6 +1228,27 @@ export function buildOperatorCapabilitiesDocument() {
1069
1228
  required: false,
1070
1229
  description: "verification entries as label:command strings",
1071
1230
  },
1231
+ {
1232
+ name: "requirementOwnership",
1233
+ type: "array",
1234
+ itemsType: "string",
1235
+ required: false,
1236
+ description: "frozen requirement→file ownership: [{requirementIds, implementationFiles?, verificationFiles?}] — machine-enforced at plan finalize",
1237
+ },
1238
+ {
1239
+ name: "capabilityBoundary",
1240
+ type: "array",
1241
+ itemsType: "string",
1242
+ required: false,
1243
+ description: "frozen test capability boundary {allowed?, forbidden?} composed into dependencyPolicy by the runtime",
1244
+ },
1245
+ {
1246
+ name: "interactionIds",
1247
+ type: "array",
1248
+ itemsType: "string",
1249
+ required: false,
1250
+ description: "frozen interaction id vocabulary — contract interaction names are machine-checked against it at plan finalize",
1251
+ },
1072
1252
  {
1073
1253
  name: "approveGate",
1074
1254
  type: "string",
@@ -134,8 +134,10 @@ export function computePackageFingerprint(packageRoot) {
134
134
  const bBuf = Buffer.from(b.relativePath, "utf-8");
135
135
  const minLen = Math.min(aBuf.length, bBuf.length);
136
136
  for (let i = 0; i < minLen; i++) {
137
- if (aBuf[i] !== bBuf[i])
138
- return aBuf[i] - bBuf[i];
137
+ const aByte = aBuf[i];
138
+ const bByte = bBuf[i];
139
+ if (aByte !== bByte)
140
+ return (aByte ?? 0) - (bByte ?? 0);
139
141
  }
140
142
  return aBuf.length - bBuf.length;
141
143
  });
@@ -183,8 +185,8 @@ export function resolveBinPaths(requested, resolvedAt, inputs) {
183
185
  // Search PATH
184
186
  const pathEnv = env.PATH ?? env.Path ?? env.path ?? "";
185
187
  const candidates = resolveFromPath(requested, pathEnv, osPlatform, env.PATHEXT ?? env.Pathext ?? env.pathext, cwd);
186
- if (candidates.length > 0) {
187
- const entry = candidates[0];
188
+ const entry = candidates[0];
189
+ if (entry !== undefined) {
188
190
  assertRegularFile(entry, requested);
189
191
  return { requested, entry, realEntry: realpathSync(entry), resolvedAt };
190
192
  }
@@ -1,3 +1,4 @@
1
+ import { shouldRewriteAssistantTransientProviderError } from "../pi-provider-recovery.js";
1
2
  import { buildOverflowCheckpoint } from "./checkpoint.js";
2
3
  import { shouldRewriteAssistantOverflow } from "./overflow.js";
3
4
  import { clearRetrieveBypass, compressProviderPayload, createSiftRetrieveToolDefinition, SIFT_RETRIEVE_TOOL_NAME, } from "./sift-bridge.js";
@@ -11,35 +12,44 @@ export function createCompactionController() {
11
12
  export function createContextPressureExtension(options) {
12
13
  const l2 = options.policy.mode !== "off";
13
14
  const l1 = Boolean(options.sift);
14
- if (!l2 && !l1)
15
+ const transientRecovery = options.normalizeTransientProviderErrors === true;
16
+ if (!l2 && !l1 && !transientRecovery)
15
17
  return undefined;
16
18
  return {
17
19
  name: options.name ?? "operator-chat-context-pressure",
18
20
  hidden: true,
19
21
  factory: (api) => {
20
- if (l2) {
22
+ if (l2 || transientRecovery) {
21
23
  api.on("message_end", (event) => {
22
24
  const message = event.message;
23
25
  if (!message || typeof message !== "object")
24
26
  return undefined;
25
27
  const rec = message;
26
- if (typeof rec.errorMessage === "string") {
27
- options.controller.lastError = rec.errorMessage;
28
+ if (l2) {
29
+ if (typeof rec.errorMessage === "string") {
30
+ options.controller.lastError = rec.errorMessage;
31
+ }
32
+ if (rec.role === "assistant") {
33
+ clearRetrieveBypassIfPresent(options.sift);
34
+ }
35
+ const rewritten = shouldRewriteAssistantOverflow(message);
36
+ if (rewritten) {
37
+ incrementCounter(options.controller.counters, "overflow");
38
+ return {
39
+ message: {
40
+ ...rec,
41
+ errorMessage: rewritten,
42
+ },
43
+ };
44
+ }
28
45
  }
29
- if (rec.role === "assistant") {
30
- clearRetrieveBypassIfPresent(options.sift);
46
+ if (transientRecovery) {
47
+ return shouldRewriteAssistantTransientProviderError(message);
31
48
  }
32
- const rewritten = shouldRewriteAssistantOverflow(message);
33
- if (!rewritten)
34
- return undefined;
35
- incrementCounter(options.controller.counters, "overflow");
36
- return {
37
- message: {
38
- ...rec,
39
- errorMessage: rewritten,
40
- },
41
- };
49
+ return undefined;
42
50
  });
51
+ }
52
+ if (l2) {
43
53
  api.on("session_before_compact", (event) => {
44
54
  const reason = event.reason;
45
55
  if (reason === "overflow") {
@@ -268,7 +268,7 @@ export function sliceUtf8Range(text, offset, maxBytes) {
268
268
  }
269
269
  const buffer = Buffer.from(text, "utf8");
270
270
  let end = Math.min(totalBytes, start + limit);
271
- while (end > start && (buffer[end] & 0b1100_0000) === 0b1000_0000) {
271
+ while (end > start && ((buffer[end] ?? 0) & 0b1100_0000) === 0b1000_0000) {
272
272
  end -= 1;
273
273
  }
274
274
  const slice = buffer.subarray(start, end).toString("utf8");
@@ -0,0 +1,182 @@
1
+ import { buildGeneratedOverflowClassifierSource, isContextOverflow, } from "./pi-context-pressure/overflow.js";
2
+ export const NORMALIZED_TRANSIENT_PROVIDER_PREFIX = "provider returned error:";
3
+ const ERROR_TEXT_LIMIT = 1_500;
4
+ const PERMANENT_ERROR_PATTERNS = [
5
+ /\b(?:401|403|429)\b|unauthori[sz]ed|forbidden|authentication|invalid api[-_ ]?key|认证错误|鉴权失败/i,
6
+ /\b(?:quota|billing|insufficient.?credit|out of budget)\b|余额不足|配额(?:不足|耗尽)/i,
7
+ /rate.?limit|too many requests|请求.{0,8}(?:频繁|过多)|频率.{0,8}限制|限流/i,
8
+ /aborted by user|user cancel|cancelled|canceled|用户取消/i,
9
+ /business validation|invalid task|schema validation|业务校验/i,
10
+ ];
11
+ export const BUILT_IN_TRANSIENT_PROVIDER_RULES = Object.freeze([
12
+ Object.freeze({
13
+ id: "wrapped-transient-provider-error",
14
+ all: Object.freeze([
15
+ /\b(?:UnknownError|TypeValidationError)\b|Type validation failed/i,
16
+ ]),
17
+ any: Object.freeze([
18
+ /\b502\b|\bcode[:\s]*502\b/i,
19
+ /\bLLMRequestError\b/i,
20
+ /network fluctuation|timeout|model processing timeout/i,
21
+ /网络波动|模型处理超时|当前请求超时/i,
22
+ /transient provider failure|non-standard (?:payload|response)|upstream returned/i,
23
+ ]),
24
+ }),
25
+ Object.freeze({
26
+ id: "internal-llm-request-error",
27
+ all: Object.freeze([/\bLLMRequestError\b/i]),
28
+ any: Object.freeze([
29
+ /\b502\b|\bcode[:\s]*502\b/i,
30
+ /network fluctuation|timeout|model processing timeout/i,
31
+ /网络波动|模型处理超时|当前请求超时/i,
32
+ /non-standard (?:payload|response)|upstream returned/i,
33
+ ]),
34
+ }),
35
+ Object.freeze({
36
+ id: "internal-provider-fluctuation",
37
+ any: Object.freeze([/网络波动|模型处理超时|当前请求超时/i]),
38
+ }),
39
+ ]);
40
+ function stringifyErrorPart(value) {
41
+ if (typeof value === "string")
42
+ return value;
43
+ if (value == null)
44
+ return "";
45
+ try {
46
+ return JSON.stringify(value);
47
+ }
48
+ catch {
49
+ return String(value);
50
+ }
51
+ }
52
+ function errorText(error) {
53
+ if (typeof error === "string")
54
+ return error;
55
+ if (error == null)
56
+ return "";
57
+ if (typeof error !== "object")
58
+ return String(error);
59
+ const record = error;
60
+ return [
61
+ stringifyErrorPart(record.name),
62
+ stringifyErrorPart(record.message),
63
+ stringifyErrorPart(record.status),
64
+ stringifyErrorPart(record.code),
65
+ stringifyErrorPart(record.data),
66
+ stringifyErrorPart(error),
67
+ ]
68
+ .filter(Boolean)
69
+ .join(" ");
70
+ }
71
+ function patternMatches(pattern, text) {
72
+ pattern.lastIndex = 0;
73
+ const matched = pattern.test(text);
74
+ pattern.lastIndex = 0;
75
+ return matched;
76
+ }
77
+ function ruleMatches(rule, text) {
78
+ const all = rule.all ?? [];
79
+ const any = rule.any ?? [];
80
+ if (all.length === 0 && any.length === 0)
81
+ return false;
82
+ if (!all.every((pattern) => patternMatches(pattern, text)))
83
+ return false;
84
+ return any.length === 0 || any.some((pattern) => patternMatches(pattern, text));
85
+ }
86
+ function isPermanentProviderError(error, text) {
87
+ if (isContextOverflow(error))
88
+ return true;
89
+ return PERMANENT_ERROR_PATTERNS.some((pattern) => patternMatches(pattern, text));
90
+ }
91
+ export function classifyTransientProviderError(error, options = {}) {
92
+ const text = errorText(error);
93
+ if (!text || isPermanentProviderError(error, text)) {
94
+ return { retryable: false, reason: "permanent" };
95
+ }
96
+ const rules = [
97
+ ...BUILT_IN_TRANSIENT_PROVIDER_RULES,
98
+ ...(options.additionalRules ?? []),
99
+ ];
100
+ const matched = rules.find((rule) => ruleMatches(rule, text));
101
+ return matched
102
+ ? { retryable: true, ruleId: matched.id }
103
+ : { retryable: false, reason: "no-match" };
104
+ }
105
+ export function normalizeTransientProviderErrorMessage(current, options = {}) {
106
+ if (!current || current.startsWith(NORMALIZED_TRANSIENT_PROVIDER_PREFIX)) {
107
+ return undefined;
108
+ }
109
+ if (!classifyTransientProviderError(current, options).retryable)
110
+ return undefined;
111
+ const bounded = current.length <= ERROR_TEXT_LIMIT
112
+ ? current
113
+ : `${current.slice(0, ERROR_TEXT_LIMIT - 1)}…`;
114
+ return `${NORMALIZED_TRANSIENT_PROVIDER_PREFIX} ${bounded}`;
115
+ }
116
+ export function shouldRewriteAssistantTransientProviderError(message, options = {}) {
117
+ if (!message || typeof message !== "object")
118
+ return undefined;
119
+ const record = message;
120
+ if (record.role !== "assistant")
121
+ return undefined;
122
+ if (record.stopReason !== undefined && record.stopReason !== "error") {
123
+ return undefined;
124
+ }
125
+ const current = typeof record.errorMessage === "string" ? record.errorMessage : "";
126
+ const rewritten = normalizeTransientProviderErrorMessage(current, options);
127
+ return rewritten
128
+ ? { message: { ...record, errorMessage: rewritten } }
129
+ : undefined;
130
+ }
131
+ function serializePatterns(patterns) {
132
+ return JSON.stringify(patterns.map((pattern) => ({ source: pattern.source, flags: pattern.flags })));
133
+ }
134
+ /** Generate the pure predicate embedded in the project-level OpenCode plugin. */
135
+ export function buildGeneratedTransientProviderClassifierSource() {
136
+ const rules = BUILT_IN_TRANSIENT_PROVIDER_RULES.map((rule) => ({
137
+ id: rule.id,
138
+ all: (rule.all ?? []).map((pattern) => ({
139
+ source: pattern.source,
140
+ flags: pattern.flags,
141
+ })),
142
+ any: (rule.any ?? []).map((pattern) => ({
143
+ source: pattern.source,
144
+ flags: pattern.flags,
145
+ })),
146
+ }));
147
+ return `${buildGeneratedOverflowClassifierSource()}
148
+ const TRANSIENT_PROVIDER_PERMANENT_PATTERNS = ${serializePatterns(PERMANENT_ERROR_PATTERNS)};
149
+ const TRANSIENT_PROVIDER_RULES = ${JSON.stringify(rules)};
150
+ function transientProviderStringify(value) {
151
+ if (typeof value === "string") return value;
152
+ if (value == null) return "";
153
+ try { return JSON.stringify(value); } catch { return String(value); }
154
+ }
155
+ function transientProviderText(error) {
156
+ if (typeof error === "string") return error;
157
+ if (error == null) return "";
158
+ if (typeof error !== "object") return String(error);
159
+ return [
160
+ transientProviderStringify(error.name),
161
+ transientProviderStringify(error.message),
162
+ transientProviderStringify(error.status),
163
+ transientProviderStringify(error.code),
164
+ transientProviderStringify(error.data),
165
+ transientProviderStringify(error),
166
+ ].filter(Boolean).join(" ");
167
+ }
168
+ function transientProviderPatternMatches(pattern, text) {
169
+ return new RegExp(pattern.source, pattern.flags).test(text);
170
+ }
171
+ function transientProviderRuleMatches(rule, text) {
172
+ if (rule.all.length === 0 && rule.any.length === 0) return false;
173
+ if (!rule.all.every((pattern) => transientProviderPatternMatches(pattern, text))) return false;
174
+ return rule.any.length === 0 || rule.any.some((pattern) => transientProviderPatternMatches(pattern, text));
175
+ }
176
+ function isKnownTransientProviderError(error) {
177
+ const text = transientProviderText(error);
178
+ if (!text || isOverflowMessage(text)) return false;
179
+ if (TRANSIENT_PROVIDER_PERMANENT_PATTERNS.some((pattern) => transientProviderPatternMatches(pattern, text))) return false;
180
+ return TRANSIENT_PROVIDER_RULES.some((rule) => transientProviderRuleMatches(rule, text));
181
+ }`;
182
+ }
@@ -21,3 +21,43 @@ export const PI_RECOMMENDED_RETRY = {
21
21
  },
22
22
  };
23
23
  export const PI_RECOMMENDED_COMPACTION = { enabled: true };
24
+ function validBoolean(value) {
25
+ return typeof value === "boolean";
26
+ }
27
+ function validNonNegativeNumber(value) {
28
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
29
+ }
30
+ function preferredOptionalNonNegativeNumber(...values) {
31
+ return values.find(validNonNegativeNumber);
32
+ }
33
+ function preferredValue(projectValue, globalValue, fallback, isValid) {
34
+ if (isValid(projectValue))
35
+ return projectValue;
36
+ if (isValid(globalValue))
37
+ return globalValue;
38
+ return fallback;
39
+ }
40
+ /**
41
+ * Apply Console-owned retry defaults without writing settings files.
42
+ * Explicit project fields win over global fields, which win over defaults.
43
+ */
44
+ export function applyProcessRetryOverride(manager) {
45
+ if (!manager?.applyOverrides)
46
+ return { applied: false };
47
+ const project = manager.getProjectSettings?.()?.retry;
48
+ const global = manager.getGlobalSettings?.()?.retry;
49
+ const currentProvider = manager.getProviderRetrySettings?.();
50
+ const timeoutMs = preferredOptionalNonNegativeNumber(project?.provider?.timeoutMs, global?.provider?.timeoutMs, currentProvider?.timeoutMs);
51
+ const retry = {
52
+ enabled: preferredValue(project?.enabled, global?.enabled, PI_RECOMMENDED_RETRY.enabled, validBoolean),
53
+ maxRetries: preferredValue(project?.maxRetries, global?.maxRetries, PI_RECOMMENDED_RETRY.maxRetries, validNonNegativeNumber),
54
+ baseDelayMs: preferredValue(project?.baseDelayMs, global?.baseDelayMs, PI_RECOMMENDED_RETRY.baseDelayMs, validNonNegativeNumber),
55
+ provider: {
56
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
57
+ maxRetries: preferredValue(project?.provider?.maxRetries, global?.provider?.maxRetries, PI_RECOMMENDED_RETRY.provider.maxRetries, validNonNegativeNumber),
58
+ maxRetryDelayMs: preferredValue(project?.provider?.maxRetryDelayMs, global?.provider?.maxRetryDelayMs, PI_RECOMMENDED_RETRY.provider.maxRetryDelayMs, validNonNegativeNumber),
59
+ },
60
+ };
61
+ manager.applyOverrides({ retry });
62
+ return { applied: true, retry };
63
+ }
@@ -186,6 +186,8 @@ function globToRegExp(glob) {
186
186
  let regex = '^';
187
187
  for (let i = 0; i < glob.length; i += 1) {
188
188
  const char = glob[i];
189
+ if (char === undefined)
190
+ continue;
189
191
  if (char === '*') {
190
192
  const next = glob[i + 1];
191
193
  if (next === '*') {
@@ -286,6 +286,35 @@ const taskConfigObjectSchema = z.object({
286
286
  verifyPreset: verifyPresetSchema.optional().default("auto"),
287
287
  /** Task-contract commands that must be included in final DAG shell verification. */
288
288
  verifyCommands: z.array(taskVerifyCommandSchema).optional().default([]),
289
+ /** Generation-frozen requirement→file ownership for frontend-implementation
290
+ * DAGs. Machine-checked at plan finalize: a requirement's implementation
291
+ * targets (and its verification targets' files) must stay inside the
292
+ * declared sets, so ownership never depends on model compliance with prose.
293
+ */
294
+ requirementOwnership: z
295
+ .array(z
296
+ .object({
297
+ requirementIds: z.array(z.string().min(1)).min(1),
298
+ implementationFiles: z.array(z.string().min(1)).optional(),
299
+ verificationFiles: z.array(z.string().min(1)).optional(),
300
+ })
301
+ .strict()
302
+ .refine((entry) => (entry.implementationFiles?.length ?? 0) > 0 ||
303
+ (entry.verificationFiles?.length ?? 0) > 0, { message: "requirementOwnership entry needs implementationFiles or verificationFiles" }))
304
+ .optional(),
305
+ /** Generation-frozen test capability boundary composed into the canonical
306
+ * dependencyPolicy by the runtime (planner never maintains it). */
307
+ capabilityBoundary: z
308
+ .object({
309
+ allowed: z.array(z.string().min(1)).optional(),
310
+ forbidden: z.array(z.string().min(1)).optional(),
311
+ })
312
+ .strict()
313
+ .refine((entry) => (entry.allowed?.length ?? 0) > 0 || (entry.forbidden?.length ?? 0) > 0, { message: "capabilityBoundary needs allowed or forbidden entries" })
314
+ .optional(),
315
+ /** Generation-frozen interaction id vocabulary. Contract interaction names
316
+ * must come from this set (plan finalize deterministic check). */
317
+ interactionIds: z.array(z.string().min(1)).optional(),
289
318
  /** Verification selection policy. Intermediate loops may use quota; final gates still run full required verification. */
290
319
  verifyQuota: verifyQuotaSchema.optional().default("full"),
291
320
  /** DAG supervised verify strategy. Final quota is fixed to full; intermediate quota may reduce cost. */
@@ -187,6 +187,15 @@ export function mergeManagedTaskConfigFields(existing, draft) {
187
187
  ...(draft.frontendOpenspec !== undefined
188
188
  ? { frontendOpenspec: draft.frontendOpenspec }
189
189
  : {}),
190
+ ...(draft.requirementOwnership !== undefined
191
+ ? { requirementOwnership: draft.requirementOwnership }
192
+ : {}),
193
+ ...(draft.capabilityBoundary !== undefined
194
+ ? { capabilityBoundary: draft.capabilityBoundary }
195
+ : {}),
196
+ ...(draft.interactionIds !== undefined
197
+ ? { interactionIds: draft.interactionIds }
198
+ : {}),
190
199
  };
191
200
  if (draft.featureId !== undefined) {
192
201
  next.featureId = draft.featureId;
@@ -70,6 +70,12 @@ export async function recoverTaskContract(input) {
70
70
  };
71
71
  }
72
72
  const txId = input.txId ?? unfinished[0];
73
+ if (txId === undefined) {
74
+ return {
75
+ action: "manual-required",
76
+ message: "no unfinished transactions to recover",
77
+ };
78
+ }
73
79
  if (!unfinished.includes(txId)) {
74
80
  return {
75
81
  action: "manual-required",
@@ -75,6 +75,23 @@ export const taskContractDraftSchema = z
75
75
  assumptions: z.array(z.string()).optional(),
76
76
  hardConstraints: z.array(z.string()).optional(),
77
77
  frontendOpenspec: frontendOpenspecConfigSchema.optional(),
78
+ requirementOwnership: z
79
+ .array(z
80
+ .object({
81
+ requirementIds: z.array(z.string().min(1)).min(1),
82
+ implementationFiles: z.array(z.string().min(1)).optional(),
83
+ verificationFiles: z.array(z.string().min(1)).optional(),
84
+ })
85
+ .strict())
86
+ .optional(),
87
+ capabilityBoundary: z
88
+ .object({
89
+ allowed: z.array(z.string().min(1)).optional(),
90
+ forbidden: z.array(z.string().min(1)).optional(),
91
+ })
92
+ .strict()
93
+ .optional(),
94
+ interactionIds: z.array(z.string().min(1)).optional(),
78
95
  interviewAssessmentRef: z
79
96
  .object({
80
97
  draftSha256: z.string().min(1),
@@ -17,7 +17,10 @@ function parseSimpleFrontmatter(block) {
17
17
  const match = /^([A-Za-z0-9_-]+)\s*:\s*(.+?)\s*$/u.exec(line);
18
18
  if (!match)
19
19
  continue;
20
- out[match[1]] = parseYamlishScalar(match[2]);
20
+ const [, key, value] = match;
21
+ if (key === undefined || value === undefined)
22
+ continue;
23
+ out[key] = parseYamlishScalar(value);
21
24
  }
22
25
  return out;
23
26
  }
@@ -46,7 +49,11 @@ export function detectProductArtifactMeta(markdown) {
46
49
  if (!match) {
47
50
  return { artifactType: "unknown", recognized: false };
48
51
  }
49
- const fields = parseSimpleFrontmatter(match[1]);
52
+ const [, frontmatter] = match;
53
+ if (frontmatter === undefined) {
54
+ return { artifactType: "unknown", recognized: false };
55
+ }
56
+ const fields = parseSimpleFrontmatter(frontmatter);
50
57
  const artifactType = normalizeArtifactType(fields.artifact_type);
51
58
  const recognized = artifactType !== "unknown" || Boolean(fields.artifact_version);
52
59
  return {