@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
@@ -2,6 +2,8 @@ import { createHash } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { parseJsonReviewVerdict } from "./output-protocol.js";
5
+ import { FRONTEND_DESIGN_REVIEW_NODE_ID, FRONTEND_REVIEW_NODE_ID, readCommittedDesignRequestFact, readCommittedReviewRequestFact, } from "./frontend-review-findings.js";
6
+ import { readTypedEventStoreFromJsonl } from "./frontend-typed-event-store.js";
5
7
  export const MAX_RERUN_FEEDBACK_CHARS = 12_000;
6
8
  const RERUN_FEEDBACK_TRUNCATION_MARKER = "\n\n...[上一轮反馈已按长度上限截断]...\n\n";
7
9
  const MAX_EVIDENCE_REFS = 8;
@@ -35,6 +37,44 @@ function requestRevision(text) {
35
37
  return (emphasized?.[1] ?? trimmed).trim() === "VERDICT: request-revision";
36
38
  });
37
39
  }
40
+ /**
41
+ * Deterministically render a typed `request_review_changes` fact into feedback
42
+ * text. Unlike the legacy text channel (VERDICT: request-revision), the
43
+ * frontend review terminal is a committed typed fact; the findings are the
44
+ * actionable body the next round must consume.
45
+ */
46
+ export function formatTypedReviewRequestFeedback(fact) {
47
+ const lines = [];
48
+ lines.push(`frontend review committed request_review_changes (issueCategory=${typeof fact.issueCategory === "string" ? fact.issueCategory : "unknown"})`);
49
+ if (Array.isArray(fact.findings) && fact.findings.length > 0) {
50
+ lines.push("review findings:");
51
+ for (const finding of fact.findings) {
52
+ if (!finding || typeof finding !== "object")
53
+ continue;
54
+ const record = finding;
55
+ const severity = typeof record.severity === "string" ? record.severity : "";
56
+ const issue = typeof record.issue === "string" ? record.issue : "";
57
+ const location = [
58
+ typeof record.file === "string" ? record.file : "",
59
+ typeof record.line === "number" ? String(record.line) : "",
60
+ ]
61
+ .filter(Boolean)
62
+ .join(":");
63
+ const prefix = location ? `[${location}] ` : "";
64
+ const requiredChange = typeof record.requiredChange === "string" &&
65
+ record.requiredChange.length > 0
66
+ ? ` (requiredChange: ${record.requiredChange})`
67
+ : "";
68
+ lines.push(`- ${prefix}${severity}: ${issue}${requiredChange}`);
69
+ }
70
+ }
71
+ if (Array.isArray(fact.evidenceRefs) && fact.evidenceRefs.length > 0) {
72
+ lines.push(`evidenceRefs: ${fact.evidenceRefs
73
+ .filter((ref) => typeof ref === "string")
74
+ .join(", ")}`);
75
+ }
76
+ return lines.join("\n");
77
+ }
38
78
  function pathInside(root, candidate) {
39
79
  const relative = path.relative(root, candidate);
40
80
  return (relative === "" ||
@@ -127,6 +167,162 @@ function evidenceRefs(repoRoot, runDir, pass, sourceNodeId) {
127
167
  }
128
168
  return result;
129
169
  }
170
+ /**
171
+ * Read the committed frontend review request fact (typed terminal channel).
172
+ * Returns { nodeId, fact } when the review node committed `request_review_changes`.
173
+ */
174
+ async function readTypedReviewRequestFact(runDir) {
175
+ const fact = await readCommittedReviewRequestFact({ runDir });
176
+ if (!fact)
177
+ return undefined;
178
+ return {
179
+ nodeId: FRONTEND_REVIEW_NODE_ID,
180
+ fact: {
181
+ issueCategory: fact.issueCategory,
182
+ evidenceRefs: fact.evidenceRefs,
183
+ findings: fact.findings,
184
+ },
185
+ };
186
+ }
187
+ /**
188
+ * Read the committed frontend design request fact (typed terminal channel).
189
+ * Returns { nodeId, fact } when the design review node committed
190
+ * `request_design_changes` — the design analog of request_review_changes.
191
+ */
192
+ async function readTypedDesignRequestFact(runDir) {
193
+ const fact = await readCommittedDesignRequestFact({ runDir });
194
+ if (!fact)
195
+ return undefined;
196
+ return {
197
+ nodeId: FRONTEND_DESIGN_REVIEW_NODE_ID,
198
+ fact: {
199
+ issueCategory: fact.issueCategory,
200
+ evidenceRefs: fact.evidenceRefs,
201
+ findings: fact.findings,
202
+ },
203
+ };
204
+ }
205
+ const RERUN_FEEDBACK_LINEAGE_MAX_DEPTH = 5;
206
+ const RERUN_FEEDBACK_LINEAGE_LIFECYCLES = [
207
+ "active",
208
+ "paused",
209
+ "completed",
210
+ ];
211
+ function safeLineageRunId(value) {
212
+ if (typeof value !== "string" || !value || value !== value.trim())
213
+ return undefined;
214
+ if (value === "." ||
215
+ value === ".." ||
216
+ value.includes("/") ||
217
+ value.includes("\\") ||
218
+ value.includes("\0"))
219
+ return undefined;
220
+ return value;
221
+ }
222
+ async function readCommittedTerminalKind(input) {
223
+ try {
224
+ const records = await readTypedEventStoreFromJsonl(path.join(input.runDir, input.nodeId, input.factsFile));
225
+ for (const record of records) {
226
+ if (record.phase !== "committed")
227
+ continue;
228
+ const kind = record.fact.kind;
229
+ if (typeof kind === "string" && input.kinds.includes(kind))
230
+ return kind;
231
+ }
232
+ }
233
+ catch {
234
+ // A missing/unreadable terminal store means this run did not establish a
235
+ // usable resolution barrier; lineage lookup may continue.
236
+ }
237
+ return undefined;
238
+ }
239
+ async function readReviewTerminalKind(runDir) {
240
+ return readCommittedTerminalKind({
241
+ runDir,
242
+ nodeId: FRONTEND_REVIEW_NODE_ID,
243
+ factsFile: "review-typed-facts.jsonl",
244
+ kinds: ["request_review_changes", "approve_review"],
245
+ });
246
+ }
247
+ async function readDesignTerminalKind(runDir) {
248
+ return readCommittedTerminalKind({
249
+ runDir,
250
+ nodeId: FRONTEND_DESIGN_REVIEW_NODE_ID,
251
+ factsFile: "design-typed-facts.jsonl",
252
+ kinds: ["request_design_changes", "approve_design"],
253
+ });
254
+ }
255
+ /**
256
+ * Walk the rerun-task lineage chain (`<runDir>/.runtime/rerun-task-lineage.json`
257
+ * → parentRunId) looking for the nearest ancestor run with a committed review
258
+ * or design request fact. A nearer final-review approval resolves all older
259
+ * findings; a nearer design approval resolves older design findings while
260
+ * still allowing an older final-review request to survive. Bounded depth;
261
+ * unsafe ids, mismatched state identities, cycles, and unreadable lineage
262
+ * files terminate the walk with undefined.
263
+ */
264
+ async function readAncestorTypedRequestFact(runDir) {
265
+ let currentRunDir = runDir;
266
+ let currentRunId;
267
+ let designResolved = false;
268
+ const dagRunsRoot = path.resolve(runDir, "..", "..");
269
+ const visitedRunDirs = new Set([path.resolve(runDir)]);
270
+ for (let depth = 0; depth <= RERUN_FEEDBACK_LINEAGE_MAX_DEPTH; depth += 1) {
271
+ const reviewTerminalKind = await readReviewTerminalKind(currentRunDir);
272
+ if (currentRunId && reviewTerminalKind === "request_review_changes") {
273
+ const fact = await readTypedReviewRequestFact(currentRunDir);
274
+ if (fact)
275
+ return { ...fact, parentRunId: currentRunId };
276
+ }
277
+ if (reviewTerminalKind === "approve_review")
278
+ return undefined;
279
+ const designTerminalKind = await readDesignTerminalKind(currentRunDir);
280
+ if (currentRunId &&
281
+ !designResolved &&
282
+ designTerminalKind === "request_design_changes") {
283
+ const fact = await readTypedDesignRequestFact(currentRunDir);
284
+ if (fact)
285
+ return { ...fact, parentRunId: currentRunId };
286
+ }
287
+ if (designTerminalKind === "approve_design")
288
+ designResolved = true;
289
+ if (depth === RERUN_FEEDBACK_LINEAGE_MAX_DEPTH)
290
+ return undefined;
291
+ let parentRunId;
292
+ try {
293
+ const lineage = JSON.parse(await readFile(path.join(currentRunDir, ".runtime", "rerun-task-lineage.json"), "utf8"));
294
+ parentRunId = safeLineageRunId(lineage.parentRunId);
295
+ }
296
+ catch {
297
+ return undefined;
298
+ }
299
+ if (!parentRunId)
300
+ return undefined;
301
+ let ancestorRunDir;
302
+ for (const lifecycle of RERUN_FEEDBACK_LINEAGE_LIFECYCLES) {
303
+ const candidate = path.join(dagRunsRoot, lifecycle, parentRunId);
304
+ try {
305
+ const ancestorState = JSON.parse(await readFile(path.join(candidate, "state.json"), "utf8"));
306
+ if (ancestorState.runId === parentRunId) {
307
+ ancestorRunDir = candidate;
308
+ break;
309
+ }
310
+ }
311
+ catch {
312
+ // try next lifecycle
313
+ }
314
+ }
315
+ if (!ancestorRunDir)
316
+ return undefined;
317
+ const resolvedAncestorRunDir = path.resolve(ancestorRunDir);
318
+ if (visitedRunDirs.has(resolvedAncestorRunDir))
319
+ return undefined;
320
+ visitedRunDirs.add(resolvedAncestorRunDir);
321
+ currentRunDir = ancestorRunDir;
322
+ currentRunId = parentRunId;
323
+ }
324
+ return undefined;
325
+ }
130
326
  /**
131
327
  * Derive only the latest unresolved verify/review feedback from canonical
132
328
  * parent-run facts. Provider-only failures intentionally return undefined.
@@ -144,8 +340,126 @@ export async function deriveDagRerunFeedback(input) {
144
340
  break;
145
341
  }
146
342
  }
147
- if (!sourceNodeId || !sourceNode)
343
+ if (!sourceNodeId || !sourceNode) {
344
+ // Typed terminal channel: the frontend review/design review commit their
345
+ // verdicts as typed facts (request_review_changes / request_design_changes)
346
+ // instead of VERDICT text, and the frontend DAG has no convergence
347
+ // passHistory. Fall back to reading the typed event stores so findings
348
+ // still flow into the next round as unresolved feedback. Prefer review;
349
+ // if absent, fall through to the design review (a design rejection also
350
+ // carries actionable findings the next plan round must consume). When
351
+ // the direct parent has neither because it failed before review, walk the
352
+ // rerun-task lineage chain — chained
353
+ // reruns otherwise lose the grandparent's code-review findings and the
354
+ // reviewer re-flags them as "unresolved previous-round feedback" (r18).
355
+ // A committed approval is a resolution barrier and prevents older
356
+ // findings from being resurrected.
357
+ const typedFact = (await readTypedReviewRequestFact(input.runDir)) ??
358
+ (await readTypedDesignRequestFact(input.runDir)) ??
359
+ (await readAncestorTypedRequestFact(input.runDir));
360
+ if (typedFact) {
361
+ const parentSourceBindingHash = sourceBindingHash(input.spec);
362
+ return withDigest({
363
+ schemaVersion: 1,
364
+ kind: "unresolved-terminal-feedback",
365
+ parentRunId: "parentRunId" in typedFact &&
366
+ typeof typedFact.parentRunId === "string"
367
+ ? typedFact.parentRunId
368
+ : input.parentRunId,
369
+ taskId: input.taskId,
370
+ sourceNodeId: typedFact.nodeId,
371
+ verdict: "request-revision",
372
+ failureCategory: typedFact.nodeId === FRONTEND_REVIEW_NODE_ID
373
+ ? "review-request-changes"
374
+ : "design-request-changes",
375
+ feedbackText: scrubAndBoundFeedbackText(formatTypedReviewRequestFeedback(typedFact.fact), input.runDir, input.state.cwd),
376
+ evidenceRefs: [
377
+ {
378
+ nodeId: typedFact.nodeId,
379
+ preservedNodeRecordPath: `${typedFact.nodeId}.json`,
380
+ },
381
+ ],
382
+ attemptSummary: {
383
+ completedPasses: 1,
384
+ maxPasses: 1,
385
+ ...(input.state.terminalReason
386
+ ? { terminalReason: input.state.terminalReason }
387
+ : {}),
388
+ },
389
+ binding: {
390
+ ...(parentSourceBindingHash
391
+ ? { sourceCanonicalHash: parentSourceBindingHash }
392
+ : {}),
393
+ ...(input.spec.taskContractBinding?.canonicalHash
394
+ ? {
395
+ taskContractCanonicalHash: input.spec.taskContractBinding.canonicalHash,
396
+ }
397
+ : {}),
398
+ status: "unknown",
399
+ },
400
+ });
401
+ }
402
+ // Preserve actionable writer failures even when the run stopped before a
403
+ // final review node could commit typed findings. This is especially
404
+ // important for provider length exhaustion: the next run must see the
405
+ // stop reason/tool statistics instead of repeating the same prompt.
406
+ const writerNodeId = ["frontend-implement-pi", "implement-pi"].find((nodeId) => {
407
+ const node = input.state.nodes[nodeId];
408
+ return (node?.status === "ERROR" &&
409
+ [
410
+ "empty-output",
411
+ "invalid-output",
412
+ "writer-thinking-exhausted",
413
+ "writer-budget-exhausted",
414
+ "incomplete-write-set",
415
+ "partial-success-with-context-overflow",
416
+ ].includes(node.failureCategory ?? ""));
417
+ });
418
+ if (writerNodeId) {
419
+ const writerNode = await readNodeRecord(input.runDir, pass, undefined, writerNodeId, input.state.nodes[writerNodeId]);
420
+ if (writerNode) {
421
+ const writerFeedback = [
422
+ `writer failure category: ${writerNode.failureCategory ?? "unknown"}`,
423
+ writerNode.stopReason ? `provider stopReason: ${writerNode.stopReason}` : "",
424
+ typeof writerNode.writeToolCallCount === "number"
425
+ ? `write tool calls: ${writerNode.writeToolCallCount}`
426
+ : "",
427
+ writerNode.stderr?.trim() ?? "",
428
+ canonicalNodeOutput(writerNode),
429
+ ]
430
+ .filter(Boolean)
431
+ .join("\n\n");
432
+ const parentSourceBindingHash = sourceBindingHash(input.spec);
433
+ return withDigest({
434
+ schemaVersion: 1,
435
+ kind: "unresolved-terminal-feedback",
436
+ parentRunId: input.parentRunId,
437
+ taskId: input.taskId,
438
+ sourceNodeId: writerNodeId,
439
+ verdict: "request-revision",
440
+ failureCategory: writerNode.failureCategory,
441
+ feedbackText: scrubAndBoundFeedbackText(writerFeedback, input.runDir, input.state.cwd),
442
+ evidenceRefs: [
443
+ {
444
+ nodeId: writerNodeId,
445
+ preservedNodeRecordPath: `${writerNodeId}.json`,
446
+ },
447
+ ],
448
+ attemptSummary: { completedPasses: 1, maxPasses: 1 },
449
+ binding: {
450
+ ...(parentSourceBindingHash
451
+ ? { sourceCanonicalHash: parentSourceBindingHash }
452
+ : {}),
453
+ ...(input.spec.taskContractBinding?.canonicalHash
454
+ ? { taskContractCanonicalHash: input.spec.taskContractBinding.canonicalHash }
455
+ : {}),
456
+ status: "unknown",
457
+ },
458
+ });
459
+ }
460
+ }
148
461
  return undefined;
462
+ }
149
463
  const completedPasses = pass?.pass ?? Math.max(1, input.state.convergence?.currentPass ?? 1);
150
464
  const maxPasses = Math.max(completedPasses, input.state.convergence?.maxPasses ?? 1);
151
465
  const parentSourceBindingHash = sourceBindingHash(input.spec);