@tea-agent/loop-agent 0.41.1 → 0.42.0-next.10

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 (302) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +397 -5
  3. package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
  4. package/dist/adapters/context-transfer/pi-session.js +61 -0
  5. package/dist/application/dag/generate-task-dag.js +75 -19
  6. package/dist/application/dag/run-dag.js +41 -0
  7. package/dist/application/task-lifecycle/advance.js +24 -5
  8. package/dist/application/task-lifecycle/observe.js +171 -17
  9. package/dist/application/task-lifecycle/plan-transitions.js +42 -7
  10. package/dist/application/task-lifecycle/recommendations.js +13 -2
  11. package/dist/build-stamp.json +3 -3
  12. package/dist/cli/command-definitions.js +19 -0
  13. package/dist/cli/program.js +29 -2
  14. package/dist/commands/client-recovery.js +3 -0
  15. package/dist/commands/dag-artifact.js +284 -0
  16. package/dist/commands/dag-context.js +184 -0
  17. package/dist/commands/dag-follow-up.js +138 -0
  18. package/dist/commands/dag-rerun-task.js +2 -0
  19. package/dist/commands/dag-rerun.js +206 -1
  20. package/dist/commands/init.js +27 -1
  21. package/dist/commands/task-advance.js +19 -0
  22. package/dist/executors/dag-pi-executor.js +4013 -86
  23. package/dist/executors/pi-executor.js +15 -4
  24. package/dist/executors/pi-read-budget-policy.js +239 -0
  25. package/dist/executors/pi-sdk-executor.js +3 -0
  26. package/dist/executors/shell-executor.js +978 -188
  27. package/dist/executors/shell-write-guard.js +7 -0
  28. package/dist/{worker → infrastructure}/console/app-data.js +4 -0
  29. package/dist/infrastructure/console/artifact-revision-store.js +430 -0
  30. package/dist/infrastructure/console/context-export-store.js +160 -0
  31. package/dist/infrastructure/console/dir-lock.js +132 -0
  32. package/dist/infrastructure/console/operation-store.js +417 -0
  33. package/dist/infrastructure/harness/artifact-store.js +10 -1
  34. package/dist/infrastructure/harness/atomic-write.js +12 -2
  35. package/dist/shared/context-transfer/artifact-revision.js +172 -0
  36. package/dist/shared/context-transfer.js +418 -0
  37. package/dist/shared/dag-failure-category.js +12 -0
  38. package/dist/shared/openspec-spec.js +70 -4
  39. package/dist/shared/operator/capabilities.js +21 -0
  40. package/dist/shared/operator/safe-run-summary.js +1 -0
  41. package/dist/shared/path-safety.js +93 -0
  42. package/dist/shared/preview.js +28 -4
  43. package/dist/task/config-types.js +107 -6
  44. package/dist/task/contract/adopt.js +4 -0
  45. package/dist/task/contract/import-revision.js +4 -0
  46. package/dist/task/contract/project.js +3 -0
  47. package/dist/task/contract/schema.js +2 -1
  48. package/dist/task/frontend-project-capability.js +203 -20
  49. package/dist/task/runtime.js +5 -2
  50. package/dist/task/source-prepare/build-draft.js +3 -3
  51. package/dist/task/source-prepare/fragment-inventory.js +64 -25
  52. package/dist/task/source-prepare/prepare.js +126 -21
  53. package/dist/task/source-prepare/semantic-intake.js +6 -2
  54. package/dist/task/source-references.js +22 -1
  55. package/dist/task/task-demand-routing.js +3 -0
  56. package/dist/worker/console/chat/chat-event-store.js +2 -2
  57. package/dist/worker/console/chat/model-resolver.js +7 -4
  58. package/dist/worker/console/chat/pi-runtime.js +86 -5
  59. package/dist/worker/console/chat/resource-preferences-store.js +1 -1
  60. package/dist/worker/console/chat/routes.js +136 -53
  61. package/dist/worker/console/chat/sdd-data-alignment.js +222 -0
  62. package/dist/worker/console/chat/session-catalog.js +2 -0
  63. package/dist/worker/console/chat/session-store.js +43 -1
  64. package/dist/worker/console/chat/shortcuts.js +18 -2
  65. package/dist/worker/console/chat/user-questions.js +1 -1
  66. package/dist/worker/console/console-update-runtime.js +1 -1
  67. package/dist/worker/console/context-transfer-diagnostics.js +198 -0
  68. package/dist/worker/console/dag-confirmation.js +1 -1
  69. package/dist/worker/console/dag-execution-receipt.js +1 -1
  70. package/dist/worker/console/doctor.js +1 -1
  71. package/dist/worker/console/draft-store.js +1 -1
  72. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  73. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  74. package/dist/worker/console/human-gate-token.js +1 -1
  75. package/dist/worker/console/index.js +6 -3
  76. package/dist/worker/console/interview/assessment.js +1 -1
  77. package/dist/worker/console/interview/session.js +1 -1
  78. package/dist/worker/console/operation-runner.js +45 -4
  79. package/dist/worker/console/operation-sse.js +1 -1
  80. package/dist/worker/console/operation-wait.js +1 -1
  81. package/dist/worker/console/operator-actions.js +273 -10
  82. package/dist/worker/console/operator-surface-health.js +1 -1
  83. package/dist/worker/console/operator-user-error.js +169 -0
  84. package/dist/worker/console/pi-plugins.js +57 -0
  85. package/dist/worker/console/pi-readiness.js +3 -2
  86. package/dist/worker/console/routes.js +637 -8
  87. package/dist/worker/console/security.js +35 -0
  88. package/dist/worker/console/server.js +29 -4
  89. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-D7oU983t.js → abnfDiagram-N423BO3Z-CcS17TBr.js} +1 -1
  90. package/dist/worker/console/static/assets/{arc-BrKSRdFS.js → arc-COptKq2S.js} +1 -1
  91. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CiXV7L56.js → architectureDiagram-T3A2C74G-h4LKMHjP.js} +1 -1
  92. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D_Hs_gIG.js → blockDiagram-VBNYF7ZC-COA1MOH0.js} +1 -1
  93. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DbM-Lqqh.js → c4Diagram-5PPSVZJV-DJUf0QPm.js} +1 -1
  94. package/dist/worker/console/static/assets/channel-DdBCaOJ6.js +1 -0
  95. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D1M8uqJw.js → chunk-2GRJ4B5K-mtWfKrUX.js} +1 -1
  96. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-4D3RFHT6.js → chunk-2Q5K7J3B-B8pXsxDQ.js} +1 -1
  97. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CdwpY_n9.js → chunk-5RXB4S5H-ipKzByl1.js} +1 -1
  98. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BLeLZ9PG.js → chunk-5VM5RSS4-DYi3Ald_.js} +1 -1
  99. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-CeRNEMvc.js → chunk-6Q2QTUOP-DQtGYoty.js} +1 -1
  100. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CjkHP8Vy.js → chunk-GF5L2VYU-BU0qS2YV.js} +1 -1
  101. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-B54ZUQY-.js → chunk-JWPE2WC7-DVH9dIGE.js} +1 -1
  102. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-4bKaMVmx.js → chunk-KBJHAD2P-Dt60SmgM.js} +1 -1
  103. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-Cyjfznu_.js → chunk-RYQCIY6F-BoaUGuEY.js} +1 -1
  104. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CDN-zGFV.js → chunk-XXDRQBXY-_WHFDTp2.js} +1 -1
  105. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DZFra1GO.js +1 -0
  106. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DZFra1GO.js +1 -0
  107. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-HxJmz411.js → cose-bilkent-JH36ORCC-BxkbTIRd.js} +1 -1
  108. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DtSt5K2w.js → cynefin-VYW2F7L2-Bf2UVnoG.js} +1 -1
  109. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-VtkSpRmG.js → cynefinDiagram-MW4NZA55-Bo23q1J_.js} +1 -1
  110. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-Bj4DT4du.js → dagre-VZM6K2ZE-Dd_UU49i.js} +1 -1
  111. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Bpuk6BmP.js → diagram-7IWD3JNH-ebUa1a9y.js} +1 -1
  112. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BHYGv_yO.js → diagram-B4RE2ZJO-BucthU8r.js} +1 -1
  113. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DEx3WwnT.js → diagram-LBJQPF4R-BgqNpAkm.js} +1 -1
  114. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Cj0dS5e8.js → diagram-Q27KOJAE-DC4q5NGa.js} +1 -1
  115. package/dist/worker/console/static/assets/{diagram-UB23O5K3-B97h8l21.js → diagram-UB23O5K3-CBqCaMeb.js} +1 -1
  116. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DMSFAhBd.js → ebnfDiagram-BXEA7PRR-CGtnbQ3-.js} +1 -1
  117. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DhVOCbt6.js → erDiagram-JOGREHBK-CG3LUao5.js} +1 -1
  118. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-GlakITWL.js → flowDiagram-UKHOOZJN-D2ZVgoFS.js} +1 -1
  119. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-VxPpu9eQ.js → ganttDiagram-PKOTCBZU-DoYFZiKt.js} +1 -1
  120. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bs_e5DRT.js → gitGraphDiagram-DS77QQ5N-CKoP1s6j.js} +1 -1
  121. package/dist/worker/console/static/assets/index-CAZ2fC_X.css +1 -0
  122. package/dist/worker/console/static/assets/index-vbTcFnFs.js +449 -0
  123. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BXYuU4Uw.js → infoDiagram-6WML65LV-Duofv8p2.js} +1 -1
  124. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-C34erCbU.js → ishikawaDiagram-WSZJBQD7-D2nlCkA1.js} +1 -1
  125. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DZCAiOU3.js → journeyDiagram-NVQOT4AX-Dd4IHdus.js} +1 -1
  126. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C9gaTdUm.js → kanban-definition-27J2QSJJ-Bi20AOdt.js} +1 -1
  127. package/dist/worker/console/static/assets/{linear-CvI0Z17U.js → linear-D59YJ9kB.js} +1 -1
  128. package/dist/worker/console/static/assets/{mermaid.core-DMMSIx7j.js → mermaid.core-Bl13LpNa.js} +5 -5
  129. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BKKP0EO6.js → mindmap-definition-FAOFIHXS-C6DLP5eY.js} +1 -1
  130. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-C3LiFbl5.js → pegDiagram-VL7TDLO6-BjO4cy64.js} +1 -1
  131. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-Bb3Om2Dz.js → pieDiagram-7S7Q4E2Y-D7i2qZTG.js} +1 -1
  132. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DNthMjzc.js → quadrantDiagram-CIZ2JOQS-Dx8o_h0y.js} +1 -1
  133. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-miFsr4Tv.js → railroadDiagram-AXF67PYL-B55orI_t.js} +1 -1
  134. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-yXUncmn6.js → requirementDiagram-LRYGKXZP-zWaehp6f.js} +1 -1
  135. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DLeWKLak.js → sankeyDiagram-W5VNT64P-CcA-pjvD.js} +1 -1
  136. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CI3he1R3.js → sequenceDiagram-SI44F4Z6-BOFbzNHI.js} +1 -1
  137. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B7jfDkS5.js → sizeCapture-X5ZJPWSS-BjAejah1.js} +1 -1
  138. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BmrZod7J.js → stateDiagram-OKZ733FA-DXYwxJwZ.js} +1 -1
  139. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Clg3V9t1.js +1 -0
  140. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CDOlHVSY.js → swimlanes-SLNWSIFB-OYiOch8n.js} +2 -2
  141. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DX1dxAAW.js +8 -0
  142. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cz-XX1gy.js → timeline-definition-Z64GVDOM-cZfH3nmU.js} +1 -1
  143. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-caV4cI8C.js → vennDiagram-T6HMQDX7-BDE7b3E1.js} +1 -1
  144. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-dImPlnIO.js → wardleyDiagram-T6FBY63Y-kyyGy9WJ.js} +1 -1
  145. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CtRYVJcn.js → xychartDiagram-ELKLHX3M-CJj6VTog.js} +1 -1
  146. package/dist/worker/console/static/index.html +7 -2
  147. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  148. package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
  149. package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -5
  150. package/dist/worker/console/static-src/operator-chat/input-history.js +8 -6
  151. package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
  152. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +258 -23
  153. package/dist/worker/console/static-src/operator-chat/useChatThread.js +112 -4
  154. package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -4
  155. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
  156. package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
  157. package/dist/worker/console/static-src/shell/console-update-reload.js +52 -0
  158. package/dist/worker/console/static-src/shell/workspace-route.js +11 -0
  159. package/dist/worker/console/workspace-context.js +142 -2
  160. package/dist/worker/console/workspace-registry.js +2 -2
  161. package/dist/worker/continuation/worker-continuation.js +278 -0
  162. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  163. package/dist/worker/observe/health.js +1 -1
  164. package/dist/worker/observe/node-transparency.js +572 -0
  165. package/dist/worker/observe/routes.js +55 -1
  166. package/dist/worker/observe/static/api.js +69 -5
  167. package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
  168. package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
  169. package/dist/worker/observe/static/dag-helpers.js +4 -2
  170. package/dist/worker/observe/static/dag-node-purpose.js +5 -0
  171. package/dist/worker/observe/static/inspect-workspace.js +23 -0
  172. package/dist/worker/observe/static/kpi.js +2 -2
  173. package/dist/worker/observe/static/operator-chrome.d.ts +10 -2
  174. package/dist/worker/observe/static/operator-chrome.js +37 -23
  175. package/dist/worker/observe/static/relations.js +2 -2
  176. package/dist/worker/observe/static/router.d.ts +12 -1
  177. package/dist/worker/observe/static/router.js +48 -6
  178. package/dist/worker/observe/static/run-processing.js +4 -2
  179. package/dist/worker/observe/static/shell-chrome.js +2 -2
  180. package/dist/worker/observe/static/state.js +8 -1
  181. package/dist/worker/observe/static/styles.css +1092 -86
  182. package/dist/worker/observe/static/views/dag-inspector.js +1228 -64
  183. package/dist/worker/observe/static/views/dag.js +10 -2
  184. package/dist/worker/observe/static/views/dags.js +3 -1
  185. package/dist/worker/observe/static/views/dashboard.js +14 -6
  186. package/dist/worker/observe/static/views/pool.js +7 -2
  187. package/dist/worker/observe/static/views/run.js +12 -3
  188. package/dist/worker/observe/static/views/session-timeline.js +142 -18
  189. package/dist/worker/observe/static/views/task.js +7 -2
  190. package/dist/worker/outcomes/adapters.js +19 -0
  191. package/dist/worker/outcomes/types.js +1 -0
  192. package/dist/worker/pool/attempt-lease.js +97 -66
  193. package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
  194. package/dist/worker/pool/reconcile.js +46 -1
  195. package/dist/worker/pool/run-store.js +2 -0
  196. package/dist/worker/pool/state-projection.js +2 -0
  197. package/dist/worker/task-spec/workflow-routing.js +8 -3
  198. package/dist/workflows/dag/artifact-bindings.js +149 -0
  199. package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
  200. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +215 -28
  201. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  202. package/dist/workflows/dag/backend-test-plan-protocol.js +106 -0
  203. package/dist/workflows/dag/backend-test-scenario-param.js +172 -25
  204. package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
  205. package/dist/workflows/dag/backend-test-writer-completeness.js +104 -12
  206. package/dist/workflows/dag/budget-enforcement.js +10 -0
  207. package/dist/workflows/dag/context-receipt.js +305 -0
  208. package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
  209. package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
  210. package/dist/workflows/dag/context-transfer/renderers.js +93 -0
  211. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  212. package/dist/workflows/dag/dag-retry-schema.js +138 -0
  213. package/dist/workflows/dag/frontend-closeout.js +221 -0
  214. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  215. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  216. package/dist/workflows/dag/frontend-implementation-contract.js +1237 -192
  217. package/dist/workflows/dag/frontend-plan-render.js +2 -1
  218. package/dist/workflows/dag/frontend-prewrite-gate.js +256 -350
  219. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  220. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  221. package/dist/workflows/dag/frontend-recovery-controller.js +226 -0
  222. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  223. package/dist/workflows/dag/frontend-recovery-plan.js +21 -10
  224. package/dist/workflows/dag/frontend-recovery-run.js +166 -34
  225. package/dist/workflows/dag/frontend-repair.js +1 -432
  226. package/dist/workflows/dag/frontend-review-context.js +261 -15
  227. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  228. package/dist/workflows/dag/frontend-shadow-dual-write.js +941 -0
  229. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  230. package/dist/workflows/dag/frontend-shape-facts.js +419 -0
  231. package/dist/workflows/dag/frontend-shape.js +435 -0
  232. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  233. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  234. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  235. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  236. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  237. package/dist/workflows/dag/frontend-verification-trace.js +252 -25
  238. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  239. package/dist/workflows/dag/frontend-writer-admission.js +319 -0
  240. package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
  241. package/dist/workflows/dag/frontend-writer-status.js +256 -0
  242. package/dist/workflows/dag/init-hybrid.js +1174 -562
  243. package/dist/workflows/dag/interrupt-request.js +7 -0
  244. package/dist/workflows/dag/node-execution.js +940 -31
  245. package/dist/workflows/dag/path-safety.js +1 -0
  246. package/dist/workflows/dag/prompt.js +99 -7
  247. package/dist/workflows/dag/recovery-lease.js +170 -0
  248. package/dist/workflows/dag/report.js +37 -1
  249. package/dist/workflows/dag/rerun-feedback.js +315 -1
  250. package/dist/workflows/dag/rerun-plan.js +568 -3
  251. package/dist/workflows/dag/rerun-run.js +642 -18
  252. package/dist/workflows/dag/rerun-task.js +251 -13
  253. package/dist/workflows/dag/retry-policy.js +219 -104
  254. package/dist/workflows/dag/runner.js +596 -121
  255. package/dist/workflows/dag/scheduler.js +133 -20
  256. package/dist/workflows/dag/skill-snapshot.js +17 -0
  257. package/dist/workflows/dag/types.js +426 -22
  258. package/dist/workflows/dag/validate.js +28 -12
  259. package/docs/architecture/runtime-boundaries.md +6 -6
  260. package/docs/architecture/worker-and-feature.md +1 -1
  261. package/docs/examples/README.md +5 -0
  262. package/docs/init-surface.manifest.json +30 -12
  263. package/docs/skills/vetted-skill-registry.md +4 -2
  264. package/docs/templates/README.md +2 -0
  265. package/docs/templates/agent-dag-report.schema.json +8 -2
  266. package/docs/templates/agent-dag.schema.json +33 -1
  267. package/docs/templates/backend-test-dag.json +23 -20
  268. package/docs/templates/frontend-implementation-contract.schema.json +4 -1
  269. package/docs/templates/frontend-implementation-dag.json +89 -0
  270. package/docs/templates/product-line/task.yaml +1 -1
  271. package/docs/templates/spec-registry.schema.json +45 -0
  272. package/harness.json +1 -1
  273. package/package.json +6 -3
  274. package/skills/frontend-bounded-implement/SKILL.md +15 -14
  275. package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
  276. package/skills/frontend-contract/SKILL.md +23 -0
  277. package/skills/frontend-contract/references/contract-protocol.md +34 -0
  278. package/skills/frontend-design-review/SKILL.md +22 -41
  279. package/skills/frontend-plan/SKILL.md +26 -0
  280. package/skills/frontend-plan/references/decision-contract.md +37 -0
  281. package/skills/frontend-plan/references/design-decisions.md +17 -0
  282. package/skills/frontend-review/SKILL.md +20 -15
  283. package/skills/frontend-review/references/review-findings.md +6 -7
  284. package/skills/frontend-scout/SKILL.md +25 -0
  285. package/skills/frontend-scout/references/design-evidence.md +16 -0
  286. package/skills/frontend-scout/references/scout-evidence.md +23 -0
  287. package/skills/frontend-verification/SKILL.md +1 -1
  288. package/skills/loop-agent/references/command-reference.md +7 -0
  289. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  290. package/dist/worker/console/operation-store.js +0 -169
  291. package/dist/worker/console/static/assets/channel-D1xajGpe.js +0 -1
  292. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BmuGTfRr.js +0 -1
  293. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BmuGTfRr.js +0 -1
  294. package/dist/worker/console/static/assets/index-BLzcAykx.js +0 -451
  295. package/dist/worker/console/static/assets/index-Cs9JUSPs.css +0 -1
  296. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-D9ykKEWP.js +0 -1
  297. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BvPOXALT.js +0 -8
  298. package/skills/frontend-implementation/SKILL.md +0 -52
  299. package/skills/frontend-implementation/references/code-standards.md +0 -33
  300. package/skills/frontend-implementation/references/design-spec.md +0 -56
  301. package/skills/frontend-implementation/references/node-contracts.md +0 -31
  302. /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
@@ -0,0 +1,172 @@
1
+ import { createHash } from "node:crypto";
2
+ import { artifactRevisionV1Schema } from "../context-transfer.js";
3
+ import { redactSecretsWithFindings } from "../preview.js";
4
+ export const ARTIFACT_REVISION_LIMITS = Object.freeze({
5
+ singleFileBytes: 10 * 1024 * 1024,
6
+ diffPreviewBytes: 64 * 1024,
7
+ });
8
+ function sha256(bytes) {
9
+ return createHash("sha256").update(bytes).digest("hex");
10
+ }
11
+ function isTextMedia(mediaType) {
12
+ return mediaType.startsWith("text/") || mediaType.includes("json") || mediaType.includes("xml");
13
+ }
14
+ function stableJson(bytes) {
15
+ try {
16
+ const value = JSON.parse(bytes.toString("utf8"));
17
+ const sort = (input) => {
18
+ if (Array.isArray(input))
19
+ return input.map(sort);
20
+ if (input && typeof input === "object") {
21
+ return Object.fromEntries(Object.entries(input)
22
+ .sort(([a], [b]) => a.localeCompare(b))
23
+ .map(([key, child]) => [key, sort(child)]));
24
+ }
25
+ return input;
26
+ };
27
+ return `${JSON.stringify(sort(value), null, 2)}\n`;
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ function boundedLineDiff(before, after) {
34
+ const beforeLines = before.split(/\r?\n/);
35
+ const afterLines = after.split(/\r?\n/);
36
+ const rows = [];
37
+ const limit = Math.max(beforeLines.length, afterLines.length);
38
+ for (let index = 0; index < limit; index += 1) {
39
+ if (beforeLines[index] === afterLines[index])
40
+ continue;
41
+ if (beforeLines[index] !== undefined)
42
+ rows.push(`- ${beforeLines[index]}`);
43
+ if (afterLines[index] !== undefined)
44
+ rows.push(`+ ${afterLines[index]}`);
45
+ }
46
+ const complete = rows.join("\n");
47
+ const preview = Buffer.from(complete, "utf8");
48
+ if (preview.byteLength <= ARTIFACT_REVISION_LIMITS.diffPreviewBytes) {
49
+ return { summary: complete, truncated: false };
50
+ }
51
+ return {
52
+ summary: preview.subarray(0, ARTIFACT_REVISION_LIMITS.diffPreviewBytes).toString("utf8") + "\n[diff truncated]",
53
+ truncated: true,
54
+ };
55
+ }
56
+ export function validateAndDescribeArtifactRevision(input) {
57
+ if (input.declaration.revisionPolicy !== "replace-file") {
58
+ throw new Error("ARTIFACT_NOT_REVISION_ELIGIBLE");
59
+ }
60
+ if (input.candidateBytes.byteLength > ARTIFACT_REVISION_LIMITS.singleFileBytes) {
61
+ throw new Error("ARTIFACT_REVISION_SCHEMA_INVALID: candidate exceeds size limit");
62
+ }
63
+ if (sha256(input.parentBytes) !== input.parentSha256) {
64
+ throw new Error("ARTIFACT_REVISION_DRIFT: parent artifact hash mismatch");
65
+ }
66
+ if (input.mediaType !== input.declaration.mediaType) {
67
+ throw new Error("ARTIFACT_REVISION_SCHEMA_INVALID: media type mismatch");
68
+ }
69
+ const textCandidate = isTextMedia(input.mediaType);
70
+ if (textCandidate &&
71
+ redactSecretsWithFindings(input.candidateBytes.toString("utf8"))
72
+ .findingCount > 0) {
73
+ throw new Error("SECRET_SCAN_CONFIRMATION_REQUIRED");
74
+ }
75
+ const candidateSha256 = sha256(input.candidateBytes);
76
+ if (candidateSha256 === input.parentSha256) {
77
+ throw new Error("ARTIFACT_REVISION_SCHEMA_INVALID: replacement is unchanged");
78
+ }
79
+ let kind = "binary";
80
+ let summary = `binary ${input.parentBytes.byteLength} -> ${input.candidateBytes.byteLength} bytes; ${input.parentSha256} -> ${candidateSha256}`;
81
+ let truncated = false;
82
+ let diffPreview;
83
+ const schemaChecks = [];
84
+ if (input.declaration.schemaId || input.mediaType.includes("json")) {
85
+ const before = stableJson(input.parentBytes);
86
+ const after = stableJson(input.candidateBytes);
87
+ if (!before || !after) {
88
+ throw new Error("ARTIFACT_REVISION_SCHEMA_INVALID: expected valid JSON");
89
+ }
90
+ kind = "json";
91
+ const declaredSchemaId = input.declaration.schemaId;
92
+ if (declaredSchemaId) {
93
+ const validator = input.artifactSchemaResolver?.(declaredSchemaId);
94
+ if (!validator) {
95
+ // Fail closed (W4.3): a declared schema without a registered
96
+ // validator must not pass as "JSON syntax only" — revision
97
+ // eligibility would silently outrun actual verification.
98
+ throw new Error(`ARTIFACT_REVISION_SCHEMA_INVALID: no registered revision validator for ${declaredSchemaId}; artifact cannot be staged until its schema is registered`);
99
+ }
100
+ const parsed = JSON.parse(after);
101
+ const result = validator.safeParse(parsed);
102
+ if (!result.success) {
103
+ const issue = result.error.issues[0];
104
+ const issuePath = issue
105
+ ? issue.path.map((part) => String(part)).join(".")
106
+ : "(root)";
107
+ throw new Error(`ARTIFACT_REVISION_SCHEMA_INVALID: candidate does not satisfy ${declaredSchemaId} at ${issuePath}: ${issue?.message ?? "schema violation"}`);
108
+ }
109
+ schemaChecks.push({
110
+ id: "artifact-schema",
111
+ status: "pass",
112
+ detail: declaredSchemaId,
113
+ });
114
+ }
115
+ const diff = boundedLineDiff(before, after);
116
+ summary = diff.summary;
117
+ truncated = diff.truncated;
118
+ diffPreview = Buffer.from(diff.summary, "utf8");
119
+ }
120
+ else if (isTextMedia(input.mediaType)) {
121
+ kind = "text";
122
+ const diff = boundedLineDiff(input.parentBytes.toString("utf8"), input.candidateBytes.toString("utf8"));
123
+ summary = diff.summary;
124
+ truncated = diff.truncated;
125
+ diffPreview = Buffer.from(diff.summary, "utf8");
126
+ }
127
+ const revision = artifactRevisionV1Schema.parse({
128
+ schemaVersion: 1,
129
+ revisionId: input.revisionId,
130
+ state: "validated",
131
+ parent: {
132
+ runId: input.parentRunId,
133
+ nodeId: input.producerNodeId,
134
+ artifactPath: input.declaration.path,
135
+ artifactSha256: input.parentSha256,
136
+ ...(input.declaration.schemaId ? { artifactSchemaId: input.declaration.schemaId } : {}),
137
+ },
138
+ candidate: {
139
+ stagingPath: input.stagingPath,
140
+ sha256: candidateSha256,
141
+ bytes: input.candidateBytes.byteLength,
142
+ mediaType: input.mediaType,
143
+ uploadedAt: input.uploadedAt,
144
+ uploadedBy: "operator",
145
+ },
146
+ validation: {
147
+ status: "pass",
148
+ checks: [
149
+ { id: "parent-hash", status: "pass" },
150
+ { id: "declared-path", status: "pass" },
151
+ { id: "media-type", status: "pass" },
152
+ textCandidate
153
+ ? { id: "secret-scan", status: "pass" }
154
+ : {
155
+ id: "secret-scan",
156
+ status: "warning",
157
+ detail: "binary candidate was not decoded for text secret scanning",
158
+ },
159
+ ...(kind === "json" ? [{ id: "json-syntax", status: "pass" }] : []),
160
+ ...schemaChecks,
161
+ ],
162
+ },
163
+ diff: {
164
+ kind,
165
+ summary,
166
+ ...(diffPreview ? { previewPath: `artifact-revisions/${input.revisionId}/diff.txt` } : {}),
167
+ truncated,
168
+ },
169
+ expiresAt: input.expiresAt,
170
+ });
171
+ return { revision, ...(diffPreview ? { diffPreview } : {}) };
172
+ }
@@ -0,0 +1,418 @@
1
+ import { createHash } from "node:crypto";
2
+ import { z } from "zod";
3
+ export const CONTEXT_TRANSFER_REASON_CODES = [
4
+ "CONTEXT_RECEIPT_MISSING",
5
+ "CONTEXT_COMPONENT_UNAVAILABLE",
6
+ "CONTEXT_BUNDLE_INEXACT",
7
+ "CONTEXT_BUNDLE_TOO_LARGE",
8
+ "RAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED",
9
+ "SECRET_SCAN_CONFIRMATION_REQUIRED",
10
+ "ARTIFACT_BINDING_UNAVAILABLE",
11
+ "ARTIFACT_NOT_REVISION_ELIGIBLE",
12
+ "ARTIFACT_IDENTITY_AMBIGUOUS",
13
+ "ARTIFACT_REVISION_SCHEMA_INVALID",
14
+ "ARTIFACT_REVISION_PATH_INVALID",
15
+ "ARTIFACT_REVISION_EXPIRED",
16
+ "ARTIFACT_REVISION_DRIFT",
17
+ "ARTIFACT_REVISION_QUOTA_EXCEEDED",
18
+ "ARTIFACT_CONSUMER_UNKNOWN",
19
+ "ARTIFACT_IMPACT_UNSAFE",
20
+ "RERUN_PLAN_DRIFT",
21
+ "WORKER_MANAGED_CONTINUATION_UNSUPPORTED",
22
+ "WORKER_CONTINUATION_AUTHORITY_MISMATCH",
23
+ "WORKER_CONTINUATION_NEEDS_RECONCILE",
24
+ ];
25
+ export const contextTransferReasonCodeSchema = z.enum(CONTEXT_TRANSFER_REASON_CODES);
26
+ export const CONTEXT_BUNDLE_LIMITS = Object.freeze({
27
+ previewBytes: 64 * 1024,
28
+ singleFileBytes: 16 * 1024 * 1024,
29
+ totalUncompressedBytes: 64 * 1024 * 1024,
30
+ fileCount: 2_048,
31
+ });
32
+ const sha256Schema = z.string().regex(/^[a-f0-9]{64}$/);
33
+ const safeRelativePosixPathSchema = z
34
+ .string()
35
+ .min(1)
36
+ .refine((value) => !value.includes("\0"), "path must not contain NUL")
37
+ .refine((value) => !value.includes("\\"), "path must use POSIX separators")
38
+ .refine((value) => !value.startsWith("/") &&
39
+ !value.startsWith("//") &&
40
+ !/^[A-Za-z]:/.test(value), "path must be relative")
41
+ .refine((value) => value.split("/").every((segment) => segment !== ".." && segment !== ""), "path must not escape or contain empty segments");
42
+ const contextComponentSchema = z
43
+ .object({
44
+ index: z.number().int().nonnegative(),
45
+ kind: z.enum([
46
+ "system-prompt",
47
+ "developer-prompt",
48
+ "user-prompt",
49
+ "task-contract",
50
+ "execution-constraint",
51
+ "context-file",
52
+ "upstream-artifact",
53
+ "tool-contract",
54
+ "runtime-fact",
55
+ ]),
56
+ logicalName: z.string().min(1),
57
+ source: z
58
+ .object({
59
+ type: z.string().min(1),
60
+ identity: z.string().min(1),
61
+ revision: z.string().min(1).optional(),
62
+ })
63
+ .strict(),
64
+ materializedPath: safeRelativePosixPathSchema.optional(),
65
+ sha256: sha256Schema,
66
+ bytes: z.number().int().nonnegative(),
67
+ mediaType: z.string().min(1),
68
+ inclusion: z.enum([
69
+ "full",
70
+ "excerpt",
71
+ "summary",
72
+ "reference-only",
73
+ "omitted",
74
+ ]),
75
+ authoritativeSource: z
76
+ .object({ identity: z.string().min(1), sha256: sha256Schema.optional() })
77
+ .strict()
78
+ .optional(),
79
+ omissionReason: z.string().min(1).optional(),
80
+ })
81
+ .strict();
82
+ export const effectiveNodeContextV1Schema = z
83
+ .object({
84
+ schemaVersion: z.literal(1),
85
+ identity: z
86
+ .object({
87
+ runId: z.string().min(1),
88
+ nodeId: z.string().min(1),
89
+ attempt: z.number().int().positive(),
90
+ capturedAt: z.string().min(1),
91
+ })
92
+ .strict(),
93
+ orderedComponents: z.array(contextComponentSchema),
94
+ promptAssembly: z
95
+ .object({
96
+ strategy: z.string().min(1),
97
+ finalPromptSha256: sha256Schema.optional(),
98
+ tokenEstimate: z.number().int().nonnegative().optional(),
99
+ truncations: z.array(z
100
+ .object({
101
+ componentIndex: z.number().int().nonnegative(),
102
+ reason: z.string().min(1),
103
+ retainedBytes: z.number().int().nonnegative().optional(),
104
+ })
105
+ .strict()),
106
+ })
107
+ .strict(),
108
+ boundaries: z
109
+ .object({
110
+ allowedPaths: z.array(z.string()),
111
+ forbiddenPaths: z.array(z.string()),
112
+ writeSet: z.array(z.string()),
113
+ })
114
+ .strict(),
115
+ runtime: z
116
+ .object({
117
+ executor: z.string().min(1),
118
+ modelHint: z.string().min(1).optional(),
119
+ resolvedModel: z.string().min(1).optional(),
120
+ skills: z.array(z.string()),
121
+ extensions: z.array(z.string()),
122
+ activeTools: z.array(z.string()),
123
+ })
124
+ .strict(),
125
+ contextDigest: sha256Schema,
126
+ })
127
+ .strict()
128
+ .superRefine((value, ctx) => {
129
+ value.orderedComponents.forEach((component, index) => {
130
+ if (component.index !== index) {
131
+ ctx.addIssue({
132
+ code: z.ZodIssueCode.custom,
133
+ path: ["orderedComponents", index, "index"],
134
+ message: "component indexes must be contiguous and ordered",
135
+ });
136
+ }
137
+ });
138
+ });
139
+ const bundleFileSchema = z
140
+ .object({
141
+ path: safeRelativePosixPathSchema,
142
+ sha256: sha256Schema,
143
+ bytes: z.number().int().nonnegative(),
144
+ mediaType: z.string().min(1),
145
+ origin: z.string().min(1),
146
+ redaction: z.enum(["none", "redacted", "omitted"]),
147
+ sourceSha256: sha256Schema.optional(),
148
+ })
149
+ .strict();
150
+ export const contextBundleManifestV1Schema = z
151
+ .object({
152
+ schemaVersion: z.literal(1),
153
+ bundleId: z.string().min(1),
154
+ createdAt: z.string().min(1),
155
+ source: z
156
+ .object({
157
+ repoIdentity: z.string().min(1),
158
+ taskId: z.string().min(1).optional(),
159
+ runId: z.string().min(1),
160
+ nodeId: z.string().min(1),
161
+ attempt: z.number().int().positive(),
162
+ pass: z.number().int().positive().optional(),
163
+ parentRunId: z.string().min(1).optional(),
164
+ })
165
+ .strict(),
166
+ profile: z.enum(["redacted", "raw"]),
167
+ target: z.enum(["generic", "pi-session", "pi-handoff", "readable"]),
168
+ reproducibility: z
169
+ .object({
170
+ level: z.enum([
171
+ "exact-pi-session",
172
+ "semantic-handoff",
173
+ "readable-transcript",
174
+ ]),
175
+ reasons: z.array(z.string()),
176
+ limitations: z.array(z.string()),
177
+ })
178
+ .strict(),
179
+ bindings: z
180
+ .object({
181
+ frozenRunSpecSha256: sha256Schema,
182
+ contextReceiptSha256: sha256Schema,
183
+ contextDigest: sha256Schema,
184
+ taskContractSha256: sha256Schema.optional(),
185
+ sourceBindingSha256: sha256Schema.optional(),
186
+ })
187
+ .strict(),
188
+ runtime: z
189
+ .object({
190
+ executor: z.string().min(1),
191
+ model: z.string().min(1).optional(),
192
+ provider: z.string().min(1).optional(),
193
+ piVersion: z.string().min(1).optional(),
194
+ skills: z.array(z
195
+ .object({
196
+ id: z.string().min(1),
197
+ version: z.string().min(1).optional(),
198
+ sha256: sha256Schema.optional(),
199
+ })
200
+ .strict()),
201
+ extensions: z.array(z
202
+ .object({
203
+ id: z.string().min(1),
204
+ packageName: z.string().min(1).optional(),
205
+ version: z.string().min(1).optional(),
206
+ status: z.string().min(1),
207
+ })
208
+ .strict()),
209
+ tools: z.array(z
210
+ .object({
211
+ name: z.string().min(1),
212
+ contractSha256: sha256Schema.optional(),
213
+ available: z.boolean(),
214
+ })
215
+ .strict()),
216
+ })
217
+ .strict(),
218
+ files: z.array(bundleFileSchema),
219
+ omissions: z.array(z
220
+ .object({
221
+ subject: z.string().min(1),
222
+ reasonCode: z.string().min(1),
223
+ detail: z.string().min(1).optional(),
224
+ })
225
+ .strict()),
226
+ security: z
227
+ .object({
228
+ secretScan: z.enum(["pass", "warning", "not-run"]),
229
+ findingCounts: z.record(z.string(), z.number().int().nonnegative()),
230
+ rawAcknowledgement: z
231
+ .object({
232
+ requestId: z.string().min(1),
233
+ acknowledgedAt: z.string().min(1),
234
+ })
235
+ .strict()
236
+ .optional(),
237
+ })
238
+ .strict(),
239
+ bundleSha256: sha256Schema,
240
+ })
241
+ .strict()
242
+ .superRefine((value, ctx) => {
243
+ const seen = new Set();
244
+ for (const [index, file] of value.files.entries()) {
245
+ const folded = file.path.normalize("NFC").toLocaleLowerCase("en-US");
246
+ if (seen.has(folded)) {
247
+ ctx.addIssue({
248
+ code: z.ZodIssueCode.custom,
249
+ path: ["files", index, "path"],
250
+ message: "bundle file paths must be unique under case folding",
251
+ });
252
+ }
253
+ seen.add(folded);
254
+ }
255
+ if (value.profile === "raw" && !value.security.rawAcknowledgement) {
256
+ ctx.addIssue({
257
+ code: z.ZodIssueCode.custom,
258
+ path: ["security", "rawAcknowledgement"],
259
+ message: "raw bundle requires explicit acknowledgement",
260
+ });
261
+ }
262
+ });
263
+ export const artifactRevisionV1Schema = z
264
+ .object({
265
+ schemaVersion: z.literal(1),
266
+ revisionId: z.string().min(1),
267
+ state: z.enum([
268
+ "staged",
269
+ "validated",
270
+ "rejected",
271
+ "expired",
272
+ "consumed",
273
+ "discarded",
274
+ ]),
275
+ parent: z
276
+ .object({
277
+ runId: z.string().min(1),
278
+ nodeId: z.string().min(1),
279
+ artifactPath: safeRelativePosixPathSchema,
280
+ artifactSha256: sha256Schema,
281
+ artifactSchemaId: z.string().min(1).optional(),
282
+ })
283
+ .strict(),
284
+ candidate: z
285
+ .object({
286
+ stagingPath: z.string().min(1),
287
+ sha256: sha256Schema,
288
+ bytes: z.number().int().nonnegative(),
289
+ mediaType: z.string().min(1),
290
+ uploadedAt: z.string().min(1),
291
+ uploadedBy: z.literal("operator"),
292
+ })
293
+ .strict(),
294
+ validation: z
295
+ .object({
296
+ status: z.enum(["pending", "pass", "fail"]),
297
+ checks: z.array(z
298
+ .object({
299
+ id: z.string().min(1),
300
+ status: z.enum(["pass", "warning", "fail"]),
301
+ detail: z.string().min(1).optional(),
302
+ })
303
+ .strict()),
304
+ })
305
+ .strict(),
306
+ diff: z
307
+ .object({
308
+ kind: z.enum(["text", "json", "binary"]),
309
+ summary: z.string(),
310
+ previewPath: safeRelativePosixPathSchema.optional(),
311
+ truncated: z.boolean(),
312
+ })
313
+ .strict(),
314
+ expiresAt: z.string().min(1),
315
+ /** Explicit staging lease (M4c): fresh lease blocks conflicting holders. */
316
+ lease: z
317
+ .object({
318
+ holder: z.string().min(1),
319
+ acquiredAt: z.string().min(1),
320
+ expiresAt: z.string().min(1),
321
+ })
322
+ .strict()
323
+ .optional(),
324
+ })
325
+ .strict();
326
+ export const artifactOverrideSetV1Schema = z
327
+ .object({
328
+ schemaVersion: z.literal(1),
329
+ overrides: z
330
+ .array(z
331
+ .object({
332
+ revisionId: z.string().min(1),
333
+ parentArtifact: z
334
+ .object({
335
+ runId: z.string().min(1),
336
+ nodeId: z.string().min(1),
337
+ path: safeRelativePosixPathSchema,
338
+ sha256: sha256Schema,
339
+ })
340
+ .strict(),
341
+ replacement: z
342
+ .object({
343
+ sha256: sha256Schema,
344
+ bytes: z.number().int().nonnegative(),
345
+ mediaType: z.string().min(1),
346
+ })
347
+ .strict(),
348
+ supersedes: z.string().min(1),
349
+ })
350
+ .strict())
351
+ .length(1),
352
+ overrideSetHash: sha256Schema,
353
+ })
354
+ .strict();
355
+ const workerContinuationIdSchema = z
356
+ .string()
357
+ .min(1)
358
+ .regex(/^[A-Za-z0-9._-]+$/);
359
+ /**
360
+ * Console-to-kernel authority for a Worker-owned artifact continuation.
361
+ * Every field is immutable and plan-hash-bound; the child identity is derived
362
+ * from the parent Worker run plus the single-use revision id.
363
+ */
364
+ export const workerContinuationAuthorityV1Schema = z
365
+ .object({
366
+ schemaVersion: z.literal(1),
367
+ parentWorkerRunId: workerContinuationIdSchema,
368
+ childWorkerRunId: workerContinuationIdSchema,
369
+ featureId: workerContinuationIdSchema,
370
+ taskId: workerContinuationIdSchema,
371
+ batchRunId: workerContinuationIdSchema,
372
+ revisionId: workerContinuationIdSchema,
373
+ })
374
+ .strict()
375
+ .superRefine((authority, ctx) => {
376
+ const expected = deriveWorkerContinuationRunId(authority.parentWorkerRunId, authority.revisionId);
377
+ if (authority.childWorkerRunId !== expected) {
378
+ ctx.addIssue({
379
+ code: z.ZodIssueCode.custom,
380
+ path: ["childWorkerRunId"],
381
+ message: `childWorkerRunId must equal ${expected}`,
382
+ });
383
+ }
384
+ });
385
+ export function deriveWorkerContinuationRunId(parentWorkerRunId, revisionId) {
386
+ const digest = createHash("sha256")
387
+ .update(`worker-continuation-v1\0${parentWorkerRunId}\0${revisionId}`)
388
+ .digest("hex")
389
+ .slice(0, 32);
390
+ return `wrc-${digest}`;
391
+ }
392
+ export function sortKeysDeep(value) {
393
+ if (Array.isArray(value))
394
+ return value.map(sortKeysDeep);
395
+ if (value && typeof value === "object") {
396
+ return Object.fromEntries(Object.entries(value)
397
+ .sort(([a], [b]) => a.localeCompare(b))
398
+ .map(([key, child]) => [key, sortKeysDeep(child)]));
399
+ }
400
+ return value;
401
+ }
402
+ export function canonicalSha256(value) {
403
+ return createHash("sha256")
404
+ .update(JSON.stringify(sortKeysDeep(value)))
405
+ .digest("hex");
406
+ }
407
+ export function computeContextDigest(context) {
408
+ return canonicalSha256(context);
409
+ }
410
+ export function computeBundleManifestSha256(manifest) {
411
+ return canonicalSha256(manifest);
412
+ }
413
+ export function computeOverrideSetHash(overrides) {
414
+ return canonicalSha256({ schemaVersion: 1, overrides });
415
+ }
416
+ export function isKnownContextTransferReasonCode(value) {
417
+ return contextTransferReasonCodeSchema.safeParse(value).success;
418
+ }
@@ -47,10 +47,22 @@ const RAW_TO_NORMALIZED = {
47
47
  "verify-failure": "validation",
48
48
  "test-failure": "validation",
49
49
  "verification-plan-stale": "validation",
50
+ "read-burst": "validation",
51
+ // Writer persisted real file changes but the final provider call hit a
52
+ // context overflow; verification never ran. Distinct from empty-output so
53
+ // the report shows partial success instead of a spec issue.
54
+ "partial-success-with-context-overflow": "validation",
55
+ // Writer burned an excessive token budget (unconverged read-edit-test loop)
56
+ // and still failed; distinct from empty-output for accurate reporting.
57
+ "writer-budget-exhausted": "validation",
50
58
  network: "executor",
51
59
  quota: "executor",
52
60
  "rate-limit": "executor",
53
61
  unavailable: "executor",
62
+ // Context window overflow (400 request-too-large): the session needs
63
+ // compaction / fresh context before retrying — an executor-side
64
+ // environment condition, not a plan-quality defect.
65
+ "context-overflow": "executor",
54
66
  // Deterministic capability/policy refusal: missing verified launcher JS
55
67
  // entry, capability allowlist rejection, or missing bounded write tool
56
68
  // profile. These are environment/config defects the operator repairs