@tea-agent/loop-agent 0.42.0-next.9 → 0.42.1

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 (236) hide show
  1. package/CHANGELOG.md +111 -45
  2. package/dist/application/dag/run-dag.js +8 -2
  3. package/dist/application/evaluation/budget.js +19 -1
  4. package/dist/application/task-lifecycle/advance.js +26 -8
  5. package/dist/application/task-lifecycle/observe.js +43 -29
  6. package/dist/application/task-lifecycle/plan-transitions.js +5 -4
  7. package/dist/build-stamp.json +3 -3
  8. package/dist/cli/program.js +1 -1
  9. package/dist/commands/dag-rerun-task.js +2 -0
  10. package/dist/commands/task-source-prepare.js +3 -1
  11. package/dist/executors/dag-pi-executor.js +2584 -600
  12. package/dist/executors/pi-executor.js +22 -1
  13. package/dist/executors/pi-extension-resolver.js +14 -2
  14. package/dist/executors/pi-sdk-executor.js +140 -39
  15. package/dist/executors/shell-executor.js +135 -55
  16. package/dist/shared/dag-failure-category.js +6 -0
  17. package/dist/shared/frontend-execution-policy.js +23 -0
  18. package/dist/task/config-types.js +4 -0
  19. package/dist/task/contract/apply.js +36 -2
  20. package/dist/task/source-prepare/ledger-reconciliation.js +2 -2
  21. package/dist/task/source-prepare/ledger-review.js +6 -9
  22. package/dist/task/source-prepare/parse-intent.js +7 -0
  23. package/dist/task/source-prepare/semantic-intake.js +16 -26
  24. package/dist/task/source-prepare/source-fidelity-pi.js +28 -9
  25. package/dist/task/source-references.js +48 -23
  26. package/dist/worker/console/chat/assistant-content.js +23 -2
  27. package/dist/worker/console/chat/browser-policy.js +143 -0
  28. package/dist/worker/console/chat/browser-routes.js +148 -0
  29. package/dist/worker/console/chat/chat-event-store.js +4 -2
  30. package/dist/worker/console/chat/explore-tools.js +13 -0
  31. package/dist/worker/console/chat/pi-runtime.js +173 -94
  32. package/dist/worker/console/chat/resource-loader.js +4 -1
  33. package/dist/worker/console/chat/routes.js +208 -66
  34. package/dist/worker/console/chat/scm-routes.js +217 -0
  35. package/dist/worker/console/chat/scm-service.js +283 -0
  36. package/dist/worker/console/chat/scm-tools.js +111 -0
  37. package/dist/worker/console/chat/sdd-data-alignment.js +78 -11
  38. package/dist/worker/console/chat/session-catalog.js +32 -0
  39. package/dist/worker/console/chat/session-mode-view.js +48 -0
  40. package/dist/worker/console/chat/session-mode.js +218 -0
  41. package/dist/worker/console/chat/session-store.js +27 -7
  42. package/dist/worker/console/chat/shortcuts.js +6 -0
  43. package/dist/worker/console/chat/subagents/agent-tool.js +62 -0
  44. package/dist/worker/console/chat/subagents/explore-agent.js +169 -0
  45. package/dist/worker/console/chat/subagents/index.js +5 -0
  46. package/dist/worker/console/chat/subagents/orchestrator.js +273 -0
  47. package/dist/worker/console/chat/subagents/tool-policy.js +53 -0
  48. package/dist/worker/console/chat/subagents/types.js +13 -0
  49. package/dist/worker/console/chat/terminal-routes.js +216 -0
  50. package/dist/worker/console/chat/terminal-sessions.js +284 -0
  51. package/dist/worker/console/chat/terminal-tools.js +199 -0
  52. package/dist/worker/console/chat/tool-preview.js +21 -0
  53. package/dist/worker/console/chat/tools.js +13 -1
  54. package/dist/worker/console/chat/turn-process.js +1 -0
  55. package/dist/worker/console/interview/tools.js +1 -0
  56. package/dist/worker/console/server.js +2 -28
  57. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C6n9_m0P.js → abnfDiagram-N423BO3Z-C9eI7nEo.js} +1 -1
  58. package/dist/worker/console/static/assets/{arc-DQh-IfZ1.js → arc-VJWsxWhB.js} +1 -1
  59. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-54NnrwUC.js → architectureDiagram-T3A2C74G-BGcyiMSo.js} +1 -1
  60. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-pivRALGK.js → blockDiagram-VBNYF7ZC-BScnFwyi.js} +1 -1
  61. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BR7OV2NJ.js → c4Diagram-5PPSVZJV-Bl9_BsLi.js} +1 -1
  62. package/dist/worker/console/static/assets/channel-B6sQYuOE.js +1 -0
  63. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-B1Aq6BcK.js → chunk-2GRJ4B5K-F1uKxiUt.js} +1 -1
  64. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CbdU0rjo.js → chunk-2Q5K7J3B-rSRMynVu.js} +1 -1
  65. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-Dqi2GJeD.js → chunk-5RXB4S5H-DAsJm1WD.js} +1 -1
  66. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BYn1Hu4R.js → chunk-5VM5RSS4-DQIdVI0a.js} +1 -1
  67. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DRLjDL0k.js → chunk-6Q2QTUOP-4A_8rJ-Q.js} +1 -1
  68. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CY9Xx2jV.js → chunk-GF5L2VYU-BHnT-vjh.js} +1 -1
  69. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BNCZs7_z.js → chunk-JWPE2WC7-Rq7QKBkn.js} +1 -1
  70. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DZ8AStLL.js → chunk-KBJHAD2P-BXh-AI2u.js} +1 -1
  71. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DsxjYrzz.js → chunk-RYQCIY6F-BblcLy8m.js} +1 -1
  72. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Ddx1KC1l.js → chunk-XXDRQBXY-zHZmVnB6.js} +1 -1
  73. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Z6s5QoeI.js +1 -0
  74. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Z6s5QoeI.js +1 -0
  75. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-W9TveCnK.js → cose-bilkent-JH36ORCC-Cmwz0Wi4.js} +1 -1
  76. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-l9j_ztZH.js → cynefin-VYW2F7L2-Dq76MHQU.js} +1 -1
  77. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BMJMKi4G.js → cynefinDiagram-MW4NZA55-zPahV1fM.js} +1 -1
  78. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-Bb4mG9pH.js → dagre-VZM6K2ZE-DQJ3xPc_.js} +1 -1
  79. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BMgL_Qv0.js → diagram-7IWD3JNH-BwX7u6fv.js} +1 -1
  80. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-Bvo2T4OQ.js → diagram-B4RE2ZJO-CodnDCco.js} +1 -1
  81. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-_5kWRN9c.js → diagram-LBJQPF4R-gAjtWkxG.js} +1 -1
  82. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DqdMrltM.js → diagram-Q27KOJAE-CGCqz0cS.js} +1 -1
  83. package/dist/worker/console/static/assets/{diagram-UB23O5K3-CDDYsNkp.js → diagram-UB23O5K3-RHwYEywd.js} +1 -1
  84. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-c4nfnZUV.js → ebnfDiagram-BXEA7PRR-B6seb_p_.js} +1 -1
  85. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DnkUcNMs.js → erDiagram-JOGREHBK-CmwCKYe8.js} +1 -1
  86. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-Dz0KGLZE.js → flowDiagram-UKHOOZJN-BfNsaZ0V.js} +1 -1
  87. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Cj1t1uka.js → ganttDiagram-PKOTCBZU-zmYgi_Z3.js} +1 -1
  88. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-tp2FrBHd.js → gitGraphDiagram-DS77QQ5N-BDEzzSKF.js} +1 -1
  89. package/dist/worker/console/static/assets/index-DgenUAfc.js +468 -0
  90. package/dist/worker/console/static/assets/index-aF4u-Y__.css +1 -0
  91. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DQwJS8DH.js → infoDiagram-6WML65LV-DeSz8l42.js} +1 -1
  92. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-eimCQWD4.js → ishikawaDiagram-WSZJBQD7-B1LV29aH.js} +1 -1
  93. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Dd9Gbwgv.js → journeyDiagram-NVQOT4AX-CCw4W2oU.js} +1 -1
  94. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Qve3cyft.js → kanban-definition-27J2QSJJ-BozaMoRJ.js} +1 -1
  95. package/dist/worker/console/static/assets/{linear-UXKSe36Z.js → linear-G1JR40SX.js} +1 -1
  96. package/dist/worker/console/static/assets/{mermaid.core-CWhj4JXN.js → mermaid.core-CCgPF0oA.js} +5 -5
  97. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-yTcwf4SJ.js → mindmap-definition-FAOFIHXS-CEqnCHnD.js} +1 -1
  98. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-_7qToaZP.js → pegDiagram-VL7TDLO6-DpmQPKuI.js} +1 -1
  99. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CXmrKmDm.js → pieDiagram-7S7Q4E2Y-BP501AxR.js} +1 -1
  100. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-hMmrJyaS.js → quadrantDiagram-CIZ2JOQS-D1dBhl_A.js} +1 -1
  101. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BXw8tCBe.js → railroadDiagram-AXF67PYL-DgZDS5pY.js} +1 -1
  102. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BmjgnLZl.js → requirementDiagram-LRYGKXZP-BzB3pyIq.js} +1 -1
  103. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Bj77SPpN.js → sankeyDiagram-W5VNT64P-B9ZprFFP.js} +1 -1
  104. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-B2FDVysL.js → sequenceDiagram-SI44F4Z6-CC2-_XrA.js} +1 -1
  105. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-UChNY9ZZ.js → sizeCapture-X5ZJPWSS-UVtAUqgB.js} +1 -1
  106. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-wbAEkbd7.js → stateDiagram-OKZ733FA-CWcS5JYG.js} +1 -1
  107. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BooX8u1Q.js +1 -0
  108. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DCEkU8HR.js → swimlanes-SLNWSIFB-C4p-dn06.js} +2 -2
  109. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D64_eqqE.js +8 -0
  110. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-BGp7H06U.js → timeline-definition-Z64GVDOM-Dnz52OHX.js} +1 -1
  111. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DsCIQuWR.js → vennDiagram-T6HMQDX7-CzTE0Nfu.js} +1 -1
  112. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-cRZLP4Xe.js → wardleyDiagram-T6FBY63Y-NAR9cjQQ.js} +1 -1
  113. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CP0xLR9Y.js → xychartDiagram-ELKLHX3M-DVMk8413.js} +1 -1
  114. package/dist/worker/console/static/index.html +2 -2
  115. package/dist/worker/console/static-src/chat-view-types.js +1 -1
  116. package/dist/worker/console/static-src/operator-chat/chat-link.js +94 -0
  117. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +142 -7
  118. package/dist/worker/console/static-src/operator-chat/pending-user-message.js +44 -0
  119. package/dist/worker/console/static-src/operator-chat/process-label.js +41 -0
  120. package/dist/worker/console/static-src/operator-chat/tools-catalog.js +21 -2
  121. package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +13 -0
  122. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +2 -0
  123. package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +51 -0
  124. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +33 -18
  125. package/dist/worker/console/static-src/operator-chat/useChatStream.js +48 -16
  126. package/dist/worker/console/static-src/operator-chat/useChatThread.js +170 -7
  127. package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -7
  128. package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +21 -0
  129. package/dist/worker/console/static-src/shell/workspace-route.js +4 -0
  130. package/dist/worker/console/workspace-context.js +15 -1
  131. package/dist/worker/observe/node-transparency.js +81 -72
  132. package/dist/worker/observe/routes.js +20 -1
  133. package/dist/worker/observe/static/constants.js +22 -22
  134. package/dist/worker/observe/static/dag-context-reason-labels.js +19 -0
  135. package/dist/worker/observe/static/dag-history-labels.js +1 -0
  136. package/dist/worker/observe/static/dag-inspector-humanize.d.ts +16 -0
  137. package/dist/worker/observe/static/dag-inspector-humanize.js +342 -0
  138. package/dist/worker/observe/static/dag-node-purpose.js +10 -10
  139. package/dist/worker/observe/static/dom.js +20 -1
  140. package/dist/worker/observe/static/format-pool.d.ts +2 -0
  141. package/dist/worker/observe/static/format-pool.js +6 -0
  142. package/dist/worker/observe/static/format.js +7 -0
  143. package/dist/worker/observe/static/index.html +4 -4
  144. package/dist/worker/observe/static/inspect-workspace.js +34 -7
  145. package/dist/worker/observe/static/inspector-submission.js +32 -0
  146. package/dist/worker/observe/static/kpi.js +1 -0
  147. package/dist/worker/observe/static/prompt-restart-candidates.js +4 -2
  148. package/dist/worker/observe/static/relations.js +7 -5
  149. package/dist/worker/observe/static/router.js +13 -0
  150. package/dist/worker/observe/static/run-processing.js +2 -0
  151. package/dist/worker/observe/static/shell-chrome.js +36 -3
  152. package/dist/worker/observe/static/state.js +35 -2
  153. package/dist/worker/observe/static/styles.css +431 -39
  154. package/dist/worker/observe/static/task-failure-labels.d.ts +4 -0
  155. package/dist/worker/observe/static/task-failure-labels.js +67 -0
  156. package/dist/worker/observe/static/task-history.js +12 -0
  157. package/dist/worker/observe/static/views/batch.js +6 -13
  158. package/dist/worker/observe/static/views/dag-graph.js +51 -4
  159. package/dist/worker/observe/static/views/dag-inspector.js +1069 -426
  160. package/dist/worker/observe/static/views/dag-trajectory.js +3 -0
  161. package/dist/worker/observe/static/views/dag.d.ts +6 -0
  162. package/dist/worker/observe/static/views/dag.js +64 -22
  163. package/dist/worker/observe/static/views/dags.js +2 -0
  164. package/dist/worker/observe/static/views/dashboard.js +21 -12
  165. package/dist/worker/observe/static/views/failures.js +21 -11
  166. package/dist/worker/observe/static/views/feature.js +11 -29
  167. package/dist/worker/observe/static/views/pool.js +37 -28
  168. package/dist/worker/observe/static/views/run.js +48 -5
  169. package/dist/worker/observe/static/views/session-timeline.js +194 -243
  170. package/dist/worker/observe/static/views/task.js +81 -62
  171. package/dist/workflows/dag/backend-test-plan-protocol.js +104 -0
  172. package/dist/workflows/dag/budget-enforcement.js +53 -3
  173. package/dist/workflows/dag/dag-retry-schema.js +3 -0
  174. package/dist/workflows/dag/frontend-capacity.js +9 -0
  175. package/dist/workflows/dag/frontend-contract-facts.js +130 -0
  176. package/dist/workflows/dag/frontend-design-policy.js +103 -17
  177. package/dist/workflows/dag/frontend-durable-tools.js +193 -0
  178. package/dist/workflows/dag/frontend-execution-groups.js +24 -0
  179. package/dist/workflows/dag/frontend-implementation-contract.js +423 -41
  180. package/dist/workflows/dag/frontend-input-projection.js +76 -0
  181. package/dist/workflows/dag/frontend-plan-completeness.js +186 -0
  182. package/dist/workflows/dag/frontend-plan-recovery-policy.js +18 -0
  183. package/dist/workflows/dag/frontend-plan-render.js +21 -3
  184. package/dist/workflows/dag/frontend-prewrite-gate.js +1 -1
  185. package/dist/workflows/dag/frontend-recovery-controller.js +32 -8
  186. package/dist/workflows/dag/frontend-recovery-lineage.js +13 -0
  187. package/dist/workflows/dag/frontend-recovery-plan.js +4 -1
  188. package/dist/workflows/dag/frontend-recovery-run.js +146 -16
  189. package/dist/workflows/dag/frontend-review-scopes.js +139 -0
  190. package/dist/workflows/dag/frontend-risk.js +2 -0
  191. package/dist/workflows/dag/frontend-session-budget.js +249 -0
  192. package/dist/workflows/dag/frontend-shadow-dual-write.js +37 -3
  193. package/dist/workflows/dag/frontend-shape-facts.js +12 -2
  194. package/dist/workflows/dag/frontend-shape.js +46 -7
  195. package/dist/workflows/dag/frontend-test-execution-evidence.js +49 -0
  196. package/dist/workflows/dag/frontend-typed-event-store.js +14 -0
  197. package/dist/workflows/dag/frontend-verification-trace.js +38 -4
  198. package/dist/workflows/dag/frontend-writer-admission.js +2 -2
  199. package/dist/workflows/dag/init-hybrid.js +70 -35
  200. package/dist/workflows/dag/node-execution.js +225 -226
  201. package/dist/workflows/dag/prompt.js +4 -0
  202. package/dist/workflows/dag/recovery-lease.js +106 -16
  203. package/dist/workflows/dag/rerun-feedback.js +1 -0
  204. package/dist/workflows/dag/rerun-plan.js +96 -4
  205. package/dist/workflows/dag/rerun-run.js +28 -6
  206. package/dist/workflows/dag/rerun-task.js +221 -18
  207. package/dist/workflows/dag/retry-policy.js +27 -10
  208. package/dist/workflows/dag/runner-exit-diagnostics.js +125 -0
  209. package/dist/workflows/dag/runner.js +246 -19
  210. package/dist/workflows/dag/structured-output-repair.js +4 -1
  211. package/dist/workflows/dag/types.js +10 -3
  212. package/dist/workflows/dag/validate.js +10 -8
  213. package/dist/workflows/dag/workspace-checkpoint.js +66 -0
  214. package/docs/operations/README.md +2 -0
  215. package/docs/templates/agent-dag.schema.json +2 -2
  216. package/docs/templates/backend-test-dag.json +6 -4
  217. package/docs/templates/frontend-design-contract.md +4 -4
  218. package/docs/templates/frontend-implementation-contract.schema.json +68 -4
  219. package/docs/templates/frontend-implementation-dag.json +5 -5
  220. package/harness.json +1 -1
  221. package/package.json +8 -6
  222. package/skills/frontend-contract/SKILL.md +2 -1
  223. package/skills/frontend-contract/references/contract-protocol.md +19 -3
  224. package/skills/frontend-design-review/SKILL.md +12 -11
  225. package/skills/frontend-plan/SKILL.md +22 -2
  226. package/skills/frontend-plan/references/decision-contract.md +114 -5
  227. package/skills/frontend-plan/references/design-decisions.md +32 -0
  228. package/skills/frontend-review/SKILL.md +10 -11
  229. package/skills/frontend-scout/references/scout-evidence.md +4 -0
  230. package/dist/worker/console/static/assets/channel-DsZxrgqe.js +0 -1
  231. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-CuToPeGV.js +0 -1
  232. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-CuToPeGV.js +0 -1
  233. package/dist/worker/console/static/assets/index-D9Sc0f0y.js +0 -449
  234. package/dist/worker/console/static/assets/index-DDQc5a50.css +0 -1
  235. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-yPoT19ft.js +0 -1
  236. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-VWdarchG.js +0 -8
@@ -1,3 +1,4 @@
1
+ import { bindManualViewRefresh, mountTaskRelationPicker } from "../shell-chrome.js";
1
2
  /** Observe UI view module (R5). */
2
3
  import {
3
4
  UI_TEXT,
@@ -19,6 +20,7 @@ import {
19
20
  import { clearNode, el, metaGrid, buildTable } from "../dom.js";
20
21
  import {
21
22
  badge,
23
+ batchStatusBadge,
22
24
  badgeClass,
23
25
  statusLabel,
24
26
  formatTs,
@@ -71,6 +73,7 @@ import { mountBoundedEventTimeline } from "./timeline.js";
71
73
 
72
74
  export async function renderBatch(batchRunId) {
73
75
  showView("batch");
76
+ bindManualViewRefresh("batch", () => renderBatch(batchRunId));
74
77
  setBreadcrumb([
75
78
  { label: UI_TEXT.dashboard, href: "#/" },
76
79
  { label: batchRunId },
@@ -88,7 +91,7 @@ export async function renderBatch(batchRunId) {
88
91
  ]);
89
92
  if (snapshot) {
90
93
  uiState.lastSnapshot = snapshot;
91
- updateHeaderRefresh(snapshot.generatedAt);
94
+ updateHeaderRefresh(snapshot.generatedAt, { mode: "manual" });
92
95
  }
93
96
  if (!batch) {
94
97
  clearNode(metaEl);
@@ -100,17 +103,7 @@ export async function renderBatch(batchRunId) {
100
103
  return;
101
104
  }
102
105
 
103
- mountRelationBar(
104
- "batch-relations",
105
- {
106
- featureId: batch.featureId,
107
- batchRunId: batch.batchRunId,
108
- taskId: batch.tasks?.[0]?.taskId,
109
- workerRunId: batch.tasks?.[0]?.workerRunId,
110
- dagRunId: batch.tasks?.[0]?.dagRunId,
111
- },
112
- snapshot,
113
- );
106
+ mountTaskRelationPicker("batch-relations", { featureId: batch.featureId, batchRunId: batch.batchRunId }, (batch.tasks ?? []).map((task) => ({ ...task, featureId: task.featureId ?? batch.featureId })), snapshot);
114
107
 
115
108
  const totalDerived = derivedDurationMs(batch.startedAt, batch.finishedAt);
116
109
  clearNode(metaEl);
@@ -123,7 +116,7 @@ export async function renderBatch(batchRunId) {
123
116
  ? objectRouteLink("feature", batch.featureId, snapshot)
124
117
  : el("span", "muted", "—"),
125
118
  ],
126
- ["状态", badge(batch.status)],
119
+ ["状态", batchStatusBadge(batch)],
127
120
  ["开始时间", formatTs(batch.startedAt)],
128
121
  ["结束时间", formatTs(batch.finishedAt)],
129
122
  ["总耗时", formatDuration(totalDerived)],
@@ -6,7 +6,7 @@ import {
6
6
  edgeCollidesNonEndpointNodes,
7
7
  routeControlEdge,
8
8
  } from "../dag-edge-routing.js";
9
- import { el } from "../dom.js";
9
+ import { el, iconButton } from "../dom.js";
10
10
  import {
11
11
  statusLabel,
12
12
  statusSymbol,
@@ -23,7 +23,7 @@ import {
23
23
  currentDagGraphViewMode,
24
24
  } from "../state.js";
25
25
  import { describeDagNodePurpose } from "../dag-node-purpose.js";
26
- import { selectDagNode } from "./dag-inspector.js";
26
+ import { selectDagNode, selectDagExecution } from "./dag-inspector.js";
27
27
  import { renderTrajectoryStoryboard } from "./dag-trajectory.js";
28
28
 
29
29
  export function svgEl(tag, attrs = {}) {
@@ -138,6 +138,10 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
138
138
  controlLaneCount,
139
139
  });
140
140
  const wrap = existingWrap ?? el("div", "dag-graph-wrap");
141
+ const active = document.activeElement;
142
+ const focusedNodeId = existingWrap?.contains?.(active) ? active?.getAttribute?.("data-node-id") : null;
143
+ const focusedAction = existingWrap?.contains?.(active) ? active?.dataset?.graphAction : null;
144
+ const previousSearch = existingWrap?.querySelector(".dag-graph-search")?.value ?? "";
141
145
  // Preserve .dag-graph-viewport DOM identity across poll refreshes so the
142
146
  // user's active scroll/pointer target is not destroyed mid-gesture.
143
147
  let viewport =
@@ -169,7 +173,7 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
169
173
  }
170
174
  toolbarLeft.appendChild(el("span", "dag-graph-summary", summaryText));
171
175
  toolbar.appendChild(toolbarLeft);
172
- const reset = el("button", "dag-graph-reset", "重置视图");
176
+ const reset = iconButton("重置视图", "ri-restart-line", "dag-graph-reset");
173
177
  toolbar.appendChild(reset);
174
178
  const appendBeforeViewport = (child) => {
175
179
  if (viewport?.parentNode === wrap) wrap.insertBefore(child, viewport);
@@ -202,7 +206,7 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
202
206
  width: layout.width,
203
207
  height: layout.height,
204
208
  role: "img",
205
- "aria-label": `DAG 依赖图,共 ${nodes.length} 个节点`,
209
+ "aria-label": `执行步骤关系,共 ${nodes.length} 个步骤`,
206
210
  });
207
211
  const defs = svgEl("defs");
208
212
  const marker = svgEl("marker", {
@@ -339,6 +343,7 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
339
343
  const purpose = describeDagNodePurpose(node.nodeId, node);
340
344
  const group = svgEl("g", {
341
345
  transform: `translate(${position.x} ${position.y})`,
346
+ "data-node-id": node.nodeId,
342
347
  class: `dag-graph-node status-${status}${node.nodeId === uiState.selectedDagNodeId ? " selected" : ""}${uiState.selectedDagNodeId && !related.has(node.nodeId) ? " dag-dimmed" : ""}`,
343
348
  tabindex: 0,
344
349
  role: "button",
@@ -402,6 +407,9 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
402
407
  });
403
408
  svg.appendChild(group);
404
409
  }
410
+ const scale = Number(viewport.dataset.scale) || 1;
411
+ svg.style.width = `${Number(svg.getAttribute("width")) * scale}px`;
412
+ svg.style.height = `${Number(svg.getAttribute("height")) * scale}px`;
405
413
  viewport.appendChild(svg);
406
414
  }
407
415
  if (viewport.parentNode !== wrap) wrap.appendChild(viewport);
@@ -476,9 +484,48 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
476
484
  }
477
485
  }
478
486
  }
487
+ const findNode = (id) => {
488
+ const matches = [...viewport.querySelectorAll("[data-node-id]")].filter((element) => element.getAttribute("data-node-id") === id);
489
+ const key = uiState.dagInspectorAttempt?.nodeId === id ? uiState.dagInspectorAttempt.key : null;
490
+ return matches.find((element) => key && element.getAttribute("data-execution-key") === key) ?? matches.at(-1);
491
+ };
492
+ const center = (id, executionId = null) => {
493
+ const target = executionId ? [...viewport.querySelectorAll("[data-execution-id]")].find((item) => item.getAttribute("data-execution-id") === executionId) : findNode(id);
494
+ if (!target) return;
495
+ const rect = target.getBoundingClientRect(), container = viewport.getBoundingClientRect();
496
+ viewport.scrollTo({ left: viewport.scrollLeft + rect.left - container.left - (container.width - rect.width) / 2, top: viewport.scrollTop + rect.top - container.top - (container.height - rect.height) / 2, behavior: "smooth" });
497
+ };
498
+ const addAction = (id, label, action) => { const icons = { selected: "ri-focus-3-line", running: "ri-play-circle-line", failed: "ri-error-warning-line", fit: "ri-fullscreen-line" }; const button = iconButton(label, icons[id], "dag-graph-reset"); button.type = "button"; button.dataset.graphAction = id; button.addEventListener("click", action); toolbar.appendChild(button); return button; };
499
+ addAction("selected", "定位选中", () => center(uiState.selectedDagNodeId)).disabled = !findNode(uiState.selectedDagNodeId);
500
+ addAction("running", "定位运行中", () => { const node = nodes.find((item) => String(item.status).toLowerCase() === "running"); if (node) center(node.nodeId); }).disabled = !nodes.some((item) => String(item.status).toLowerCase() === "running");
501
+ const failedNodes = (mode === "trajectory" ? dag.executionTrajectory?.occurrences ?? [] : nodes).filter((item) => ["error", "failed"].includes(String(item.status).toLowerCase()));
502
+ const failed = addAction("failed", `下个失败 (${failedNodes.length})`, () => {
503
+ if (!failedNodes.length) return;
504
+ const index = failedNodes.findIndex((item) => item.nodeId === uiState.selectedDagNodeId && (mode !== "trajectory" || (item.pass ? `pass-${item.pass}` : null) === (uiState.dagInspectorAttempt?.key ?? null)));
505
+ const node = failedNodes[(index + 1) % failedNodes.length];
506
+ if (mode === "trajectory") selectDagExecution(dagRunId, node.nodeId, node.pass ? `pass-${node.pass}` : null);
507
+ else selectDagNode(dagRunId, node.nodeId);
508
+ requestAnimationFrame(() => center(node.nodeId, node.executionId));
509
+ });
510
+ failed.disabled = !failedNodes.some((node) => findNode(node.nodeId));
511
+ const fit = addAction("fit", "适应画布", () => {
512
+ const svg = viewport.querySelector("svg.dag-graph"); if (!svg) return;
513
+ const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
514
+ const scale = Math.min(1, (viewport.clientWidth - 24) / width, (viewport.clientHeight - 24) / height);
515
+ if (!(scale > 0)) return;
516
+ viewport.dataset.scale = String(scale); svg.style.width = `${width * scale}px`; svg.style.height = `${height * scale}px`; viewport.scrollTo({ left: 0, top: 0 });
517
+ });
518
+ fit.disabled = mode !== "topology";
519
+ const search = el("input", "dag-graph-search"); search.type = "search"; search.placeholder = "查找节点…"; search.value = previousSearch; search.setAttribute("aria-label", "查找流程节点"); search.dataset.graphAction = "search";
520
+ search.addEventListener("keydown", (event) => { if (event.key !== "Enter" || event.isComposing) return; event.preventDefault(); const matches = nodes.filter((item) => `${item.nodeId} ${describeDagNodePurpose(item.nodeId, item)}`.toLocaleLowerCase().includes(search.value.trim().toLocaleLowerCase())); if (!matches.length) return; const index = matches.findIndex((item) => item.nodeId === uiState.selectedDagNodeId); const node = matches[(index + 1) % matches.length]; center(node.nodeId); selectDagNode(dagRunId, node.nodeId); }); toolbar.appendChild(search);
521
+ if (focusedNodeId) findNode(focusedNodeId)?.focus?.({ preventScroll: true });
522
+ else if (focusedAction) [...toolbar.querySelectorAll("[data-graph-action]")].find((item) => item.dataset.graphAction === focusedAction)?.focus?.({ preventScroll: true });
479
523
  // Toolbar is rebuilt each paint; bind reset to the current viewport/dagRunId.
480
524
  // 重置视图只重置当前模式的 viewport:不切换模式、不重置另一模式、不关闭 Inspector。
481
525
  reset.addEventListener("click", () => {
526
+ viewport.dataset.scale = "1";
527
+ const svg = viewport.querySelector("svg.dag-graph");
528
+ if (svg) { svg.style.width = `${svg.getAttribute("width")}px`; svg.style.height = `${svg.getAttribute("height")}px`; }
482
529
  if (mode === "trajectory") {
483
530
  uiState.dagTrajectoryViewportState = updateDagTrajectoryViewportState(
484
531
  uiState.dagTrajectoryViewportState,