@tea-agent/loop-agent 0.39.0-beta.0 → 0.39.0-beta.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 (331) hide show
  1. package/AGENTS.md +4 -1
  2. package/CHANGELOG.md +248 -95
  3. package/README.md +9 -5
  4. package/bin/loop-agent.js +7 -3
  5. package/dist/application/task-lifecycle/advance.js +12 -0
  6. package/dist/application/task-lifecycle/recommendations.js +13 -2
  7. package/dist/build-stamp.json +3 -3
  8. package/dist/cli/command-definitions.js +23 -5
  9. package/dist/cli/program.js +21 -2
  10. package/dist/cli/update/notifier.js +2 -2
  11. package/dist/cli/update/runtime-activity.js +1 -29
  12. package/dist/cli.js +2 -1
  13. package/dist/commands/client-recovery.js +3 -0
  14. package/dist/commands/dag-follow-up.js +138 -0
  15. package/dist/commands/dag-rerun.js +55 -1
  16. package/dist/commands/init-model-catalog.js +464 -0
  17. package/dist/commands/init-upgrade.js +265 -97
  18. package/dist/commands/init.js +455 -28
  19. package/dist/commands/inspect-next.js +8 -0
  20. package/dist/commands/task-advance.js +19 -0
  21. package/dist/executors/dag-pi-executor.js +2306 -61
  22. package/dist/executors/pi-executor.js +7 -0
  23. package/dist/executors/pi-extension-resolver.js +233 -0
  24. package/dist/executors/pi-playwright-cli-tool.js +74 -28
  25. package/dist/executors/pi-read-budget-policy.js +239 -0
  26. package/dist/executors/pi-sdk-executor.js +180 -33
  27. package/dist/executors/shell-executor.js +1249 -224
  28. package/dist/executors/shell-write-guard.js +14 -0
  29. package/dist/executors/workspace-write-snapshot.js +68 -0
  30. package/dist/infrastructure/harness/atomic-write.js +23 -0
  31. package/dist/shared/dag-failure-category.js +150 -0
  32. package/dist/shared/dag-prompt-override.js +27 -0
  33. package/dist/shared/openspec-spec.js +70 -4
  34. package/dist/shared/operator/capabilities.js +39 -0
  35. package/dist/shared/playwright-cli-command-policy.js +15 -0
  36. package/dist/shared/update/console-notifier.js +100 -0
  37. package/dist/{cli → shared}/update/npm-client.js +70 -15
  38. package/dist/{cli → shared}/update/state.js +41 -13
  39. package/dist/task/config-types.js +50 -5
  40. package/dist/task/contract/apply.js +11 -1
  41. package/dist/task/contract/constants.js +2 -0
  42. package/dist/task/contract/hash.js +3 -0
  43. package/dist/task/contract/observe.js +25 -4
  44. package/dist/task/contract/paths.js +2 -1
  45. package/dist/task/contract/project.js +18 -1
  46. package/dist/task/contract/schema.js +4 -1
  47. package/dist/task/contract/transaction.js +12 -0
  48. package/dist/task/frontend-project-capability.js +199 -18
  49. package/dist/task/source-prepare/completeness.js +188 -0
  50. package/dist/task/source-prepare/fragment-inventory.js +477 -0
  51. package/dist/task/source-prepare/index.js +3 -0
  52. package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
  53. package/dist/task/source-prepare/ledger-review.js +214 -0
  54. package/dist/task/source-prepare/ledger.js +545 -0
  55. package/dist/task/source-prepare/parse-intent.js +24 -4
  56. package/dist/task/source-prepare/prepare.js +298 -1
  57. package/dist/task/source-prepare/semantic-intake.js +25 -5
  58. package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
  59. package/dist/task/source-prepare/types.js +22 -0
  60. package/dist/task/source-references.js +22 -1
  61. package/dist/worker/cli.js +18 -2
  62. package/dist/worker/console/chat/chat-event-store.js +62 -4
  63. package/dist/worker/console/chat/context-panel.js +7 -0
  64. package/dist/worker/console/chat/deferred-turn.js +12 -0
  65. package/dist/worker/console/chat/operation-card.js +8 -1
  66. package/dist/worker/console/chat/pi-console-config.js +81 -10
  67. package/dist/worker/console/chat/pi-runtime.js +264 -16
  68. package/dist/worker/console/chat/provider-error.js +98 -0
  69. package/dist/worker/console/chat/routes.js +298 -32
  70. package/dist/worker/console/chat/session-stats.js +179 -0
  71. package/dist/worker/console/chat/session-store.js +93 -63
  72. package/dist/worker/console/chat/todos.js +115 -0
  73. package/dist/worker/console/chat/tool-preview.js +42 -0
  74. package/dist/worker/console/chat/turn-process.js +20 -55
  75. package/dist/worker/console/chat/user-questions.js +266 -0
  76. package/dist/worker/console/chat/workspace-landing.js +14 -0
  77. package/dist/worker/console/console-handoff.js +82 -0
  78. package/dist/worker/console/console-update-and-init.js +115 -0
  79. package/dist/worker/console/console-update-runtime.js +84 -0
  80. package/dist/worker/console/dag-execution-receipt.js +33 -0
  81. package/dist/worker/console/draft-store.js +49 -0
  82. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  83. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  84. package/dist/worker/console/index.js +3 -0
  85. package/dist/worker/console/inspect-split.js +18 -0
  86. package/dist/worker/console/native-directory-picker.js +13 -0
  87. package/dist/worker/console/operation-run-facts.js +19 -3
  88. package/dist/worker/console/operation-store.js +227 -7
  89. package/dist/worker/console/operator-actions.js +388 -0
  90. package/dist/worker/console/operator-surface-health.js +1 -0
  91. package/dist/worker/console/operator-user-error.js +2 -2
  92. package/dist/worker/console/prd-intake-bridge.js +13 -0
  93. package/dist/worker/console/routes.js +355 -3
  94. package/dist/worker/console/security.js +67 -13
  95. package/dist/worker/console/server.js +609 -164
  96. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4kVYweA.js → abnfDiagram-N423BO3Z-BAsjg7ew.js} +1 -1
  97. package/dist/worker/console/static/assets/{arc-Bj2M8iO5.js → arc-CyIlrwZw.js} +1 -1
  98. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CLlXe4-6.js → architectureDiagram-T3A2C74G-Bo4tobhH.js} +1 -1
  99. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-psEp5xH0.js → blockDiagram-VBNYF7ZC-Dfpow9gu.js} +1 -1
  100. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DeKcOCGJ.js → c4Diagram-5PPSVZJV-DPmzG_B4.js} +1 -1
  101. package/dist/worker/console/static/assets/channel-DSrJAn0-.js +1 -0
  102. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-K0C744p1.js → chunk-2GRJ4B5K-pKQpB1UW.js} +1 -1
  103. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-xbNw4J9-.js → chunk-2Q5K7J3B-5n9YYquZ.js} +1 -1
  104. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLaSDUO.js → chunk-5RXB4S5H-DP3CtA2a.js} +1 -1
  105. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CtiPlKel.js → chunk-5VM5RSS4-DYxMJPUy.js} +1 -1
  106. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DZtolir7.js → chunk-6Q2QTUOP-CS3D50Io.js} +1 -1
  107. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CPcdNeew.js → chunk-GF5L2VYU-gSdDfo5_.js} +1 -1
  108. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-NgHc6V37.js → chunk-JWPE2WC7-A48q0ZNt.js} +1 -1
  109. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DQ_T-hg8.js → chunk-KBJHAD2P-ow8Mm3DY.js} +1 -1
  110. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DgLsxcVP.js → chunk-RYQCIY6F-CMKfLWYE.js} +1 -1
  111. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-UrVoM9z1.js → chunk-XXDRQBXY-BiTBdQPX.js} +1 -1
  112. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DeMmPl0_.js +1 -0
  113. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DeMmPl0_.js +1 -0
  114. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CLkYvTb3.js → cose-bilkent-JH36ORCC-Cm7exRz_.js} +1 -1
  115. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BwT_xKrE.js → cynefin-VYW2F7L2-D9O5qGOu.js} +1 -1
  116. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bi9tuzif.js → cynefinDiagram-MW4NZA55-CkvQnako.js} +1 -1
  117. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BCIqkWBV.js → dagre-VZM6K2ZE-B1rzp7CB.js} +1 -1
  118. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dip6l9_Z.js → diagram-7IWD3JNH-BP07Ipcc.js} +1 -1
  119. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B-xkh_wK.js → diagram-B4RE2ZJO-BlPzweQb.js} +1 -1
  120. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DZO0kTt_.js → diagram-LBJQPF4R-CxPa7n0S.js} +1 -1
  121. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D6ZplNbZ.js → diagram-Q27KOJAE-CMTZs53A.js} +1 -1
  122. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPekbhoS.js → diagram-UB23O5K3-CxG_X52r.js} +1 -1
  123. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BtmaJpK5.js → ebnfDiagram-BXEA7PRR-D8axtJM0.js} +1 -1
  124. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-6DS0Xc44.js → erDiagram-JOGREHBK-DIsGzn7b.js} +1 -1
  125. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CihnROSm.js → flowDiagram-UKHOOZJN-CU9zkDG0.js} +1 -1
  126. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CZC4zOE2.js → ganttDiagram-PKOTCBZU-DCjTmz5P.js} +1 -1
  127. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js → gitGraphDiagram-DS77QQ5N-BksdmFzg.js} +1 -1
  128. package/dist/worker/console/static/assets/index-B-O5ChYq.css +1 -0
  129. package/dist/worker/console/static/assets/index-CfnY8AQx.js +407 -0
  130. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DlSl4BGx.js → infoDiagram-6WML65LV-CGzzzJtL.js} +1 -1
  131. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-snnzFl_U.js → ishikawaDiagram-WSZJBQD7-BdseB80N.js} +1 -1
  132. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BDE7qpMx.js → journeyDiagram-NVQOT4AX-DM9gsgha.js} +1 -1
  133. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CD2Ci04G.js → kanban-definition-27J2QSJJ-3q-_9R2b.js} +1 -1
  134. package/dist/worker/console/static/assets/{linear-DdnapKIH.js → linear-B8N-Mxsd.js} +1 -1
  135. package/dist/worker/console/static/assets/{mermaid.core-BVjAT9b8.js → mermaid.core-EPIHUUsu.js} +5 -5
  136. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-D0yJk-zA.js → mindmap-definition-FAOFIHXS-CxwO12aa.js} +1 -1
  137. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVo9tFP-.js → pegDiagram-VL7TDLO6-bPqbVX6Y.js} +1 -1
  138. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnOV-mZ_.js → pieDiagram-7S7Q4E2Y-KzqIvzeX.js} +1 -1
  139. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CzUJo58i.js → quadrantDiagram-CIZ2JOQS-CyofpWiV.js} +1 -1
  140. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Bvikrolh.js → railroadDiagram-AXF67PYL-cTWJvLTP.js} +1 -1
  141. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DtaSVCap.js → requirementDiagram-LRYGKXZP-BK--q27B.js} +1 -1
  142. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-C2c9A0wW.js → sankeyDiagram-W5VNT64P-C0SDOHXK.js} +1 -1
  143. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DmXJcU7r.js → sequenceDiagram-SI44F4Z6-Cong6YIo.js} +1 -1
  144. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4GUFW92.js → sizeCapture-X5ZJPWSS-DUVkgZx8.js} +1 -1
  145. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Dsad2MXf.js → stateDiagram-OKZ733FA-C7XgxuZg.js} +1 -1
  146. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Dzbnd5oX.js +1 -0
  147. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DGq48Fbi.js → swimlanes-SLNWSIFB-D9Ayvwcy.js} +2 -2
  148. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BY0hHk6G.js +8 -0
  149. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CSSi6OFf.js → timeline-definition-Z64GVDOM-Byb000cH.js} +1 -1
  150. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BqyzPrWv.js → vennDiagram-T6HMQDX7-DMLegPt4.js} +1 -1
  151. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DlznVb6S.js → wardleyDiagram-T6FBY63Y-ChMMeOsP.js} +1 -1
  152. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CfBcgJ_K.js → xychartDiagram-ELKLHX3M-bEMEPisW.js} +1 -1
  153. package/dist/worker/console/static/index.html +2 -2
  154. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  155. package/dist/worker/console/static-src/app/console-types.js +68 -4
  156. package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
  157. package/dist/worker/console/static-src/app/useOperatorActions.js +41 -6
  158. package/dist/worker/console/static-src/app/useRecoveryConsole.js +45 -10
  159. package/dist/worker/console/static-src/app/useRunProgress.js +47 -0
  160. package/dist/worker/console/static-src/app/useTaskWizard.js +74 -2
  161. package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
  162. package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
  163. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +140 -8
  164. package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
  165. package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
  166. package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
  167. package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
  168. package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
  169. package/dist/worker/console/static-src/operator-chat/turn-submission.js +16 -3
  170. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +168 -72
  171. package/dist/worker/console/static-src/operator-chat/useChatStream.js +102 -21
  172. package/dist/worker/console/static-src/operator-chat/useChatThread.js +184 -4
  173. package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
  174. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
  175. package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
  176. package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
  177. package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
  178. package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
  179. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
  180. package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
  181. package/dist/worker/console/static-src/shell/workspace-route.js +337 -0
  182. package/dist/worker/console/workspace-context.js +344 -0
  183. package/dist/worker/console/workspace-registry.js +214 -0
  184. package/dist/worker/loop-agent/loop-agent-client.js +7 -3
  185. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  186. package/dist/worker/materialize/harness-task-lineage.js +5 -2
  187. package/dist/worker/observability/init-runtime-activity.js +26 -0
  188. package/dist/worker/observability/read-model.js +22 -0
  189. package/dist/worker/observe/node-input.js +160 -3
  190. package/dist/worker/observe/node-process.js +377 -0
  191. package/dist/worker/observe/routes.js +224 -3
  192. package/dist/worker/observe/server.js +4 -0
  193. package/dist/worker/observe/shell-handler-keys.js +34 -0
  194. package/dist/worker/observe/static/api.js +90 -4
  195. package/dist/worker/observe/static/app.js +18 -70
  196. package/dist/worker/observe/static/constants.js +8 -1
  197. package/dist/worker/observe/static/dag-history-labels.js +4 -0
  198. package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
  199. package/dist/worker/observe/static/dag-node-purpose.js +208 -0
  200. package/dist/worker/observe/static/format.js +60 -0
  201. package/dist/worker/observe/static/index.html +6 -1
  202. package/dist/worker/observe/static/inspect-workspace.js +307 -0
  203. package/dist/worker/observe/static/markdown-render.js +20 -1
  204. package/dist/worker/observe/static/operator-chrome.css +145 -20
  205. package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
  206. package/dist/worker/observe/static/operator-chrome.js +330 -96
  207. package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
  208. package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
  209. package/dist/worker/observe/static/router.d.ts +46 -0
  210. package/dist/worker/observe/static/router.js +25 -1
  211. package/dist/worker/observe/static/state.d.ts +50 -0
  212. package/dist/worker/observe/static/state.js +184 -1
  213. package/dist/worker/observe/static/styles.css +395 -0
  214. package/dist/worker/observe/static/views/dag-graph.js +4 -2
  215. package/dist/worker/observe/static/views/dag-inspector.js +1067 -9
  216. package/dist/worker/observe/static/views/dag.d.ts +13 -0
  217. package/dist/worker/observe/static/views/dag.js +14 -5
  218. package/dist/worker/observe/static/views/dashboard.js +6 -4
  219. package/dist/worker/observe/static/views/failures.js +5 -2
  220. package/dist/worker/observe/static/views/night.js +2 -2
  221. package/dist/worker/observe/static/views/pool.js +1 -0
  222. package/dist/worker/observe/static/views/run.js +3 -1
  223. package/dist/worker/observe/static/views/session-timeline.js +78 -9
  224. package/dist/worker/observe/static/views/task.js +56 -1
  225. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +49 -3
  226. package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
  227. package/dist/workflows/dag/backend-test-pytest-collection.js +98 -14
  228. package/dist/workflows/dag/backend-test-writer-completeness.js +10 -5
  229. package/dist/workflows/dag/contract-output-registry.js +15 -0
  230. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  231. package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
  232. package/dist/workflows/dag/dynamic-runtime/map.js +1 -1
  233. package/dist/workflows/dag/failure-category.js +7 -116
  234. package/dist/workflows/dag/frontend-closeout.js +221 -0
  235. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  236. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  237. package/dist/workflows/dag/frontend-implementation-contract.js +534 -178
  238. package/dist/workflows/dag/frontend-plan-render.js +24 -0
  239. package/dist/workflows/dag/frontend-prewrite-gate.js +371 -393
  240. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  241. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  242. package/dist/workflows/dag/frontend-recovery-controller.js +202 -0
  243. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  244. package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
  245. package/dist/workflows/dag/frontend-recovery-run.js +33 -20
  246. package/dist/workflows/dag/frontend-repair.js +7 -424
  247. package/dist/workflows/dag/frontend-review-context.js +288 -14
  248. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  249. package/dist/workflows/dag/frontend-risk.js +15 -2
  250. package/dist/workflows/dag/frontend-shadow-dual-write.js +814 -0
  251. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  252. package/dist/workflows/dag/frontend-shape-facts.js +409 -0
  253. package/dist/workflows/dag/frontend-shape.js +427 -0
  254. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  255. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  256. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  257. package/dist/workflows/dag/frontend-test-case-checklist.js +30 -4
  258. package/dist/workflows/dag/frontend-test-case-manifest.js +11 -4
  259. package/dist/workflows/dag/frontend-test-case-quality.js +11 -16
  260. package/dist/workflows/dag/frontend-test-environment-probe.js +230 -0
  261. package/dist/workflows/dag/frontend-test-html-report.js +3 -1
  262. package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
  263. package/dist/workflows/dag/frontend-test-layout.js +159 -0
  264. package/dist/workflows/dag/frontend-test-markdown.js +61 -0
  265. package/dist/workflows/dag/frontend-test-result-contract.js +188 -42
  266. package/dist/workflows/dag/frontend-test-standard-scenarios.js +70 -0
  267. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  268. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  269. package/dist/workflows/dag/frontend-verification-trace.js +52 -17
  270. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  271. package/dist/workflows/dag/frontend-writer-admission.js +272 -0
  272. package/dist/workflows/dag/frontend-writer-status.js +244 -0
  273. package/dist/workflows/dag/init-hybrid.js +984 -618
  274. package/dist/workflows/dag/interrupt-request.js +10 -3
  275. package/dist/workflows/dag/lifecycle.js +3 -3
  276. package/dist/workflows/dag/node-execution.js +468 -34
  277. package/dist/workflows/dag/prompt.js +44 -19
  278. package/dist/workflows/dag/recovery-lease.js +80 -0
  279. package/dist/workflows/dag/report.js +37 -1
  280. package/dist/workflows/dag/rerun-feedback.js +124 -1
  281. package/dist/workflows/dag/rerun-plan.js +144 -5
  282. package/dist/workflows/dag/rerun-run.js +81 -6
  283. package/dist/workflows/dag/rerun-task.js +29 -0
  284. package/dist/workflows/dag/retry-policy.js +318 -8
  285. package/dist/workflows/dag/runner.js +429 -122
  286. package/dist/workflows/dag/scheduler.js +114 -16
  287. package/dist/workflows/dag/structured-output-repair.js +712 -0
  288. package/dist/workflows/dag/types.js +321 -31
  289. package/dist/workflows/dag/upstream-artifacts.js +0 -4
  290. package/dist/workflows/dag/validate.js +92 -32
  291. package/docs/README.md +2 -0
  292. package/docs/architecture/evolution.md +45 -0
  293. package/docs/init-surface.manifest.json +9 -0
  294. package/docs/operations/README.md +1 -1
  295. package/docs/operations/local-development-environment.md +21 -0
  296. package/docs/templates/README.md +2 -1
  297. package/docs/templates/agent-dag-report.schema.json +8 -2
  298. package/docs/templates/agent-dag.schema.json +45 -1
  299. package/docs/templates/frontend-implementation-contract.schema.json +684 -24
  300. package/docs/templates/frontend-test-case-checklist.md +2 -2
  301. package/docs/templates/frontend-test-dag.json +8 -10
  302. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
  303. package/docs/templates/init-managed-agents.md +13 -3
  304. package/docs/templates/spec-registry.schema.json +45 -0
  305. package/harness.json +3 -3
  306. package/package.json +7 -1
  307. package/scripts/next-info.mjs +356 -0
  308. package/scripts/next-publish-gate.mjs +238 -0
  309. package/scripts/release-source-binding.mjs +251 -0
  310. package/skills/codebase-scout/SKILL.md +1 -1
  311. package/skills/fe-test-ui-scout/SKILL.md +65 -0
  312. package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
  313. package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
  314. package/skills/frontend-bounded-implement/SKILL.md +8 -14
  315. package/skills/frontend-design-review/SKILL.md +20 -41
  316. package/skills/frontend-implementation/SKILL.md +3 -4
  317. package/skills/frontend-implementation/references/design-spec.md +15 -10
  318. package/skills/frontend-implementation/references/node-contracts.md +23 -13
  319. package/skills/frontend-review/SKILL.md +22 -14
  320. package/skills/frontend-review/references/review-findings.md +6 -7
  321. package/skills/loop-agent/references/command-reference.md +12 -4
  322. package/skills/loop-agent/references/hybrid-dag.md +8 -1
  323. package/skills/playwright-cli/SKILL.md +23 -1
  324. package/skills/playwright-cli-case-generator/SKILL.md +29 -8
  325. package/dist/worker/console/static/assets/channel-CPF4N7pf.js +0 -1
  326. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +0 -1
  327. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +0 -1
  328. package/dist/worker/console/static/assets/index-DTZOKgAn.js +0 -404
  329. package/dist/worker/console/static/assets/index-Ya5FE7cD.css +0 -1
  330. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +0 -1
  331. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +0 -8
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Pure projection from a DAG run detail payload (GET /api/dag-runs/:id) into
3
+ * the structured run progress shown on the wizard RunPanel: node counts,
4
+ * current node + elapsed time, failure pointer, and stall signal. The panel
5
+ * used to show only a raw SSE log tail — node/phase information drowned in
6
+ * log noise during 20-40 minute runs.
7
+ */
8
+ export function classifyRunProgressNodeStatus(raw) {
9
+ const status = (raw ?? "").trim().toLowerCase();
10
+ if (!status)
11
+ return "pending";
12
+ if (status.includes("running") || status === "in_progress" || status === "active") {
13
+ return "running";
14
+ }
15
+ if (status.includes("fail") || status.includes("error") || status === "blocked") {
16
+ return "failed";
17
+ }
18
+ if (status.includes("finish") ||
19
+ status.includes("success") ||
20
+ status === "done" ||
21
+ status === "ok") {
22
+ return "finished";
23
+ }
24
+ if (status.includes("skip"))
25
+ return "skipped";
26
+ return "pending";
27
+ }
28
+ function toProgressNode(node) {
29
+ const nodeId = String(node.nodeId ?? node.id ?? "").trim();
30
+ return {
31
+ nodeId,
32
+ label: String((node.label ?? node.name ?? nodeId) || "未命名节点"),
33
+ status: String(node.status ?? ""),
34
+ rank: typeof node.rank === "string" ? node.rank : undefined,
35
+ startedAt: typeof node.startedAt === "string" ? node.startedAt : undefined,
36
+ durationMs: typeof node.durationMs === "number" ? node.durationMs : undefined,
37
+ errorPreview: typeof node.errorPreview === "string" ? node.errorPreview : undefined,
38
+ };
39
+ }
40
+ function elapsedSince(iso, now) {
41
+ if (!iso)
42
+ return null;
43
+ const started = Date.parse(iso);
44
+ if (Number.isNaN(started))
45
+ return null;
46
+ const elapsed = now - started;
47
+ return elapsed >= 0 ? elapsed : null;
48
+ }
49
+ export function summarizeRunProgress(dag, now = Date.now()) {
50
+ if (!dag) {
51
+ return {
52
+ total: 0,
53
+ finished: 0,
54
+ running: null,
55
+ failed: null,
56
+ terminal: false,
57
+ effectiveStatus: null,
58
+ stalled: false,
59
+ currentNodeElapsedMs: null,
60
+ runElapsedMs: null,
61
+ };
62
+ }
63
+ const rawNodes = Array.isArray(dag.nodes) ? dag.nodes : [];
64
+ const nodes = rawNodes.map(toProgressNode);
65
+ const classes = nodes.map((node) => classifyRunProgressNodeStatus(node.status));
66
+ const finished = classes.filter((cls) => cls === "finished" || cls === "skipped").length;
67
+ const runningIndex = classes.indexOf("running");
68
+ const running = runningIndex >= 0 ? nodes[runningIndex] : null;
69
+ const failedIndex = classes.indexOf("failed");
70
+ const failed = failedIndex >= 0 ? nodes[failedIndex] : null;
71
+ const effectiveStatus = String(dag.effectiveStatus ??
72
+ dag.status ??
73
+ "").toLowerCase();
74
+ const terminal = TERMINAL_RUN_PROGRESS_STATUSES.has(effectiveStatus);
75
+ const runStartedAt = typeof dag.startedAt === "string" ? dag.startedAt : undefined;
76
+ const runDurationMs = typeof dag.durationMs === "number" ? dag.durationMs : undefined;
77
+ return {
78
+ total: nodes.length,
79
+ finished,
80
+ running,
81
+ failed,
82
+ terminal,
83
+ effectiveStatus: effectiveStatus || null,
84
+ stalled: effectiveStatus === "running-suspected-stall",
85
+ currentNodeElapsedMs: running?.durationMs ?? elapsedSince(running?.startedAt, now),
86
+ runElapsedMs: terminal
87
+ ? (runDurationMs ?? elapsedSince(runStartedAt, now))
88
+ : elapsedSince(runStartedAt, now),
89
+ };
90
+ }
91
+ const TERMINAL_RUN_PROGRESS_STATUSES = new Set([
92
+ "finished",
93
+ "failed",
94
+ "partial_failed",
95
+ "superseded",
96
+ "abandoned",
97
+ ]);
98
+ export function formatDurationMs(ms) {
99
+ if (ms == null || !Number.isFinite(ms) || ms < 0)
100
+ return "—";
101
+ const totalSeconds = Math.floor(ms / 1000);
102
+ const hours = Math.floor(totalSeconds / 3600);
103
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
104
+ const seconds = totalSeconds % 60;
105
+ if (hours > 0)
106
+ return `${hours} 时 ${minutes} 分`;
107
+ if (minutes > 0)
108
+ return `${minutes} 分 ${seconds} 秒`;
109
+ return `${seconds} 秒`;
110
+ }
@@ -0,0 +1,299 @@
1
+ import { useEffect, useMemo, useRef, useState } from "react";
2
+ import { confirmationToken } from "../operator-chat/format.js";
3
+ import { describeMutationGateFailure, isMutationGateFailureCode, } from "../operator-chat/mutation-gate.js";
4
+ /**
5
+ * Multi-workspace registry state (2026-08-23, AC-001/AC-003).
6
+ *
7
+ * Consumes the process-level GET/POST/DELETE /api/operator/v1/workspaces
8
+ * surface. POST/DELETE pass the Console mutation-gate confirmation token.
9
+ * The selected workspaceId is remembered in localStorage and validated
10
+ * against the visible list. A stale local preference falls back to the first
11
+ * visible workspace; an explicit unknown URL id remains fail-closed in the
12
+ * route layer.
13
+ *
14
+ * The network/state machine lives in createWorkspacesController (headless,
15
+ * node-testable); useWorkspaces is a thin React subscription wrapper.
16
+ */
17
+ export const ACTIVE_WORKSPACE_STORAGE_KEY = "loop-console.operator-shell.active-workspace.v1";
18
+ export function readStoredWorkspaceId(storage) {
19
+ try {
20
+ const raw = storage?.getItem(ACTIVE_WORKSPACE_STORAGE_KEY)?.trim();
21
+ return raw || null;
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ export function rememberWorkspaceId(workspaceId, storage) {
28
+ try {
29
+ if (workspaceId)
30
+ storage?.setItem(ACTIVE_WORKSPACE_STORAGE_KEY, workspaceId);
31
+ else
32
+ storage?.removeItem(ACTIVE_WORKSPACE_STORAGE_KEY);
33
+ }
34
+ catch {
35
+ /* localStorage unavailable: in-memory selection still works. */
36
+ }
37
+ }
38
+ export function pickDefaultWorkspaceId(workspaces, storedId) {
39
+ if (storedId) {
40
+ if (workspaces.some((w) => w.workspaceId === storedId))
41
+ return { status: "ok", workspaceId: storedId };
42
+ return { status: "ok", workspaceId: workspaces[0]?.workspaceId ?? null };
43
+ }
44
+ return { status: "ok", workspaceId: workspaces[0]?.workspaceId ?? null };
45
+ }
46
+ export function describeWorkspaceAddError(status, code, message) {
47
+ if (status === 409 || code === "DUPLICATE") {
48
+ return (message ||
49
+ "该目录(或等价路径)已存在为 Workspace:请直接选择既有条目,或更换其他真实目录。");
50
+ }
51
+ if (status === 400 || code === "INVALID_PATH") {
52
+ return message || "目录不可用:请确认输入的是存在的真实目录绝对路径。";
53
+ }
54
+ if (isMutationGateFailureCode(code)) {
55
+ return describeMutationGateFailure(code);
56
+ }
57
+ return message || `添加 Workspace 失败(HTTP ${status})`;
58
+ }
59
+ // The headless object also exposes subscribe(); declared via intersection below.
60
+ /** Headless multi-workspace state machine (real request path, no React). */
61
+ export function createWorkspacesController(params = {}) {
62
+ const origin = params.origin ?? "";
63
+ const fetchImpl = params.fetchFn ?? fetch;
64
+ const storage = params.storage;
65
+ const token = params.confirmationTokenFn ?? confirmationToken;
66
+ const listeners = new Set();
67
+ let state = {
68
+ workspaces: [],
69
+ loading: true,
70
+ error: null,
71
+ workspaceId: readStoredWorkspaceId(storage),
72
+ unknownWorkspaceId: null,
73
+ };
74
+ const emit = () => {
75
+ for (const listener of listeners)
76
+ listener();
77
+ };
78
+ const setState = (patch) => {
79
+ state = { ...state, ...patch };
80
+ emit();
81
+ };
82
+ const refresh = async () => {
83
+ try {
84
+ const res = await fetchImpl(`${origin}/api/operator/v1/workspaces`, {
85
+ credentials: "include",
86
+ });
87
+ if (!res.ok)
88
+ return;
89
+ const body = (await res.json());
90
+ const list = body.workspaces ?? [];
91
+ // A stale local preference falls back to the first server-visible
92
+ // Workspace. Explicit route ids are validated separately and remain
93
+ // fail-closed.
94
+ const pick = pickDefaultWorkspaceId(list, state.workspaceId);
95
+ if (pick.status === "unknown-workspace") {
96
+ setState({
97
+ workspaces: list,
98
+ unknownWorkspaceId: pick.workspaceId,
99
+ });
100
+ return;
101
+ }
102
+ const nextId = pick.workspaceId;
103
+ const previousId = state.workspaceId;
104
+ setState({
105
+ workspaces: list,
106
+ unknownWorkspaceId: null,
107
+ ...(nextId !== previousId ? { workspaceId: nextId } : {}),
108
+ });
109
+ if (nextId !== previousId)
110
+ rememberWorkspaceId(nextId, storage);
111
+ }
112
+ catch {
113
+ /* Registry unreachable: keep last known list. */
114
+ }
115
+ finally {
116
+ if (state.loading)
117
+ setState({ loading: false });
118
+ }
119
+ };
120
+ const addWorkspace = async (directoryPath, name) => {
121
+ setState({ error: null });
122
+ try {
123
+ const res = await fetchImpl(`${origin}/api/operator/v1/workspaces`, {
124
+ method: "POST",
125
+ credentials: "include",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ "x-loop-console-confirmation": token(),
129
+ },
130
+ body: JSON.stringify({ directoryPath, ...(name ? { name } : {}) }),
131
+ });
132
+ const body = (await res.json().catch(() => ({})));
133
+ if (!res.ok || !body.workspace) {
134
+ const message = describeWorkspaceAddError(res.status, body.error?.code, body.error?.message);
135
+ setState({ error: message });
136
+ return { ok: false, error: message };
137
+ }
138
+ await refresh();
139
+ setState({ workspaceId: body.workspace.workspaceId });
140
+ rememberWorkspaceId(body.workspace.workspaceId, storage);
141
+ return { ok: true, workspaceId: body.workspace.workspaceId };
142
+ }
143
+ catch (err) {
144
+ const message = err instanceof Error ? err.message : String(err);
145
+ const display = `添加 Workspace 失败:${message}`;
146
+ setState({ error: display });
147
+ return { ok: false, error: display };
148
+ }
149
+ };
150
+ const pickWorkspaceDirectory = async () => {
151
+ setState({ error: null });
152
+ try {
153
+ const res = await fetchImpl(`${origin}/api/operator/v1/workspaces/pick`, {
154
+ method: "POST",
155
+ credentials: "include",
156
+ headers: {
157
+ "x-loop-console-confirmation": token(),
158
+ },
159
+ });
160
+ const body = (await res.json().catch(() => ({})));
161
+ if (!res.ok) {
162
+ const message = isMutationGateFailureCode(body.error?.code)
163
+ ? describeMutationGateFailure(body.error?.code ?? "")
164
+ : (body.error?.message ?? `打开目录选择窗口失败(HTTP ${res.status})`);
165
+ setState({ error: message });
166
+ return null;
167
+ }
168
+ return typeof body.directoryPath === "string" && body.directoryPath.trim()
169
+ ? body.directoryPath
170
+ : null;
171
+ }
172
+ catch (error) {
173
+ const message = error instanceof Error ? error.message : String(error);
174
+ setState({ error: `打开目录选择窗口失败:${message}` });
175
+ return null;
176
+ }
177
+ };
178
+ const removeWorkspace = async (targetId) => {
179
+ setState({ error: null });
180
+ try {
181
+ const res = await fetchImpl(`${origin}/api/operator/v1/workspaces/${encodeURIComponent(targetId)}`, {
182
+ method: "DELETE",
183
+ credentials: "include",
184
+ headers: {
185
+ "x-loop-console-confirmation": token(),
186
+ },
187
+ });
188
+ const body = (await res.json().catch(() => ({})));
189
+ if (!res.ok) {
190
+ const message = res.status === 404
191
+ ? "Workspace 已不存在(可能已被移除),列表将刷新。"
192
+ : isMutationGateFailureCode(body.error?.code)
193
+ ? describeMutationGateFailure(body.error?.code ?? "")
194
+ : (body.error?.message ?? `移除 Workspace 失败(HTTP ${res.status})`);
195
+ setState({ error: message });
196
+ await refresh();
197
+ return { ok: false, error: message };
198
+ }
199
+ await refresh();
200
+ // Soft remove keeps historical sessions; if the removed workspace was
201
+ // selected, switch to a remaining one (never a startup-workspace id —
202
+ // only visible registry entries are ever selected).
203
+ if (state.workspaceId === targetId) {
204
+ const nextId = state.workspaces[0]?.workspaceId ?? null;
205
+ setState({ workspaceId: nextId });
206
+ rememberWorkspaceId(nextId, storage);
207
+ }
208
+ return { ok: true };
209
+ }
210
+ catch (err) {
211
+ const message = err instanceof Error ? err.message : String(err);
212
+ const display = `移除 Workspace 失败:${message}`;
213
+ setState({ error: display });
214
+ return { ok: false, error: display };
215
+ }
216
+ };
217
+ const selectWorkspace = (next) => {
218
+ if (next === state.workspaceId && !state.unknownWorkspaceId)
219
+ return;
220
+ setState({ workspaceId: next, unknownWorkspaceId: null });
221
+ rememberWorkspaceId(next, storage);
222
+ };
223
+ void refresh();
224
+ return {
225
+ get workspaces() {
226
+ return state.workspaces;
227
+ },
228
+ get loading() {
229
+ return state.loading;
230
+ },
231
+ get error() {
232
+ return state.error;
233
+ },
234
+ get workspaceId() {
235
+ return state.workspaceId;
236
+ },
237
+ get unknownWorkspaceId() {
238
+ return state.unknownWorkspaceId;
239
+ },
240
+ refresh,
241
+ pickWorkspaceDirectory,
242
+ addWorkspace,
243
+ removeWorkspace,
244
+ selectWorkspace,
245
+ subscribe(listener) {
246
+ listeners.add(listener);
247
+ return () => listeners.delete(listener);
248
+ },
249
+ };
250
+ }
251
+ /** React binding: one controller per mount, state mirrored into useState. */
252
+ export function useWorkspaces(params) {
253
+ const controllerRef = useRef(null);
254
+ if (!controllerRef.current) {
255
+ controllerRef.current = createWorkspacesController(params);
256
+ }
257
+ const controller = controllerRef.current;
258
+ const [state, setState] = useState(() => ({
259
+ workspaces: controller.workspaces,
260
+ loading: controller.loading,
261
+ error: controller.error,
262
+ workspaceId: controller.workspaceId,
263
+ unknownWorkspaceId: controller.unknownWorkspaceId,
264
+ }));
265
+ useEffect(() => {
266
+ const unsubscribe = controller.subscribe(() => {
267
+ setState({
268
+ workspaces: controller.workspaces,
269
+ loading: controller.loading,
270
+ error: controller.error,
271
+ workspaceId: controller.workspaceId,
272
+ unknownWorkspaceId: controller.unknownWorkspaceId,
273
+ });
274
+ });
275
+ return unsubscribe;
276
+ }, [controller]);
277
+ return useMemo(() => ({
278
+ get workspaces() {
279
+ return state.workspaces;
280
+ },
281
+ get loading() {
282
+ return state.loading;
283
+ },
284
+ get error() {
285
+ return state.error;
286
+ },
287
+ get workspaceId() {
288
+ return state.workspaceId;
289
+ },
290
+ get unknownWorkspaceId() {
291
+ return state.unknownWorkspaceId;
292
+ },
293
+ refresh: controller.refresh,
294
+ pickWorkspaceDirectory: controller.pickWorkspaceDirectory,
295
+ addWorkspace: controller.addWorkspace,
296
+ removeWorkspace: controller.removeWorkspace,
297
+ selectWorkspace: controller.selectWorkspace,
298
+ }), [state, controller]);
299
+ }