@tea-agent/loop-agent 0.42.0-next.1 → 0.42.0-next.11

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 (247) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +321 -1
  3. package/dist/application/dag/generate-task-dag.js +75 -19
  4. package/dist/application/dag/run-dag.js +41 -0
  5. package/dist/application/task-lifecycle/advance.js +24 -5
  6. package/dist/application/task-lifecycle/observe.js +171 -17
  7. package/dist/application/task-lifecycle/plan-transitions.js +42 -7
  8. package/dist/application/task-lifecycle/recommendations.js +13 -2
  9. package/dist/build-stamp.json +3 -3
  10. package/dist/cli/command-definitions.js +7 -0
  11. package/dist/cli/program.js +6 -1
  12. package/dist/commands/client-recovery.js +3 -0
  13. package/dist/commands/dag-follow-up.js +138 -0
  14. package/dist/commands/dag-rerun-task.js +2 -0
  15. package/dist/commands/init.js +27 -1
  16. package/dist/commands/task-advance.js +19 -0
  17. package/dist/executors/dag-pi-executor.js +4010 -78
  18. package/dist/executors/pi-executor.js +15 -4
  19. package/dist/executors/pi-extension-resolver.js +14 -2
  20. package/dist/executors/pi-read-budget-policy.js +239 -0
  21. package/dist/executors/shell-executor.js +978 -188
  22. package/dist/executors/shell-write-guard.js +7 -0
  23. package/dist/infrastructure/console/operation-store.js +226 -6
  24. package/dist/shared/dag-failure-category.js +12 -0
  25. package/dist/shared/openspec-spec.js +70 -4
  26. package/dist/shared/operator/capabilities.js +7 -0
  27. package/dist/task/config-types.js +105 -5
  28. package/dist/task/contract/adopt.js +4 -0
  29. package/dist/task/contract/import-revision.js +4 -0
  30. package/dist/task/contract/project.js +3 -0
  31. package/dist/task/contract/schema.js +2 -1
  32. package/dist/task/frontend-project-capability.js +203 -20
  33. package/dist/task/runtime.js +5 -2
  34. package/dist/task/source-prepare/build-draft.js +3 -3
  35. package/dist/task/source-prepare/fragment-inventory.js +64 -25
  36. package/dist/task/source-prepare/prepare.js +126 -21
  37. package/dist/task/source-prepare/semantic-intake.js +6 -2
  38. package/dist/task/source-references.js +22 -1
  39. package/dist/worker/console/chat/chat-ui-policy.js +4 -2
  40. package/dist/worker/console/chat/model-resolver.js +7 -4
  41. package/dist/worker/console/chat/pi-runtime.js +258 -11
  42. package/dist/worker/console/chat/repo-browser.js +10 -3
  43. package/dist/worker/console/chat/routes.js +165 -71
  44. package/dist/worker/console/chat/sdd-data-alignment.js +222 -0
  45. package/dist/worker/console/chat/session-catalog.js +2 -0
  46. package/dist/worker/console/chat/session-store.js +159 -70
  47. package/dist/worker/console/chat/shortcuts.js +19 -3
  48. package/dist/worker/console/chat/turn-process.js +111 -56
  49. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  50. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  51. package/dist/worker/console/index.js +3 -0
  52. package/dist/worker/console/operator-actions.js +169 -7
  53. package/dist/worker/console/pi-readiness.js +3 -2
  54. package/dist/worker/console/server.js +23 -1
  55. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DZZ8m3PO.js → abnfDiagram-N423BO3Z-CcS17TBr.js} +1 -1
  56. package/dist/worker/console/static/assets/{arc-D6PvaVd-.js → arc-COptKq2S.js} +1 -1
  57. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-B_OTOiI8.js → architectureDiagram-T3A2C74G-h4LKMHjP.js} +1 -1
  58. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Bv6rqHBg.js → blockDiagram-VBNYF7ZC-COA1MOH0.js} +1 -1
  59. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B8eHr0oz.js → c4Diagram-5PPSVZJV-DJUf0QPm.js} +1 -1
  60. package/dist/worker/console/static/assets/channel-DdBCaOJ6.js +1 -0
  61. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DYwR0im2.js → chunk-2GRJ4B5K-mtWfKrUX.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-D2WPGqXt.js → chunk-2Q5K7J3B-B8pXsxDQ.js} +1 -1
  63. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CQISJ_I7.js → chunk-5RXB4S5H-ipKzByl1.js} +1 -1
  64. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-C0o2Du1e.js → chunk-5VM5RSS4-DYi3Ald_.js} +1 -1
  65. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-4f8kr-U7.js → chunk-6Q2QTUOP-DQtGYoty.js} +1 -1
  66. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D_OWvXzX.js → chunk-GF5L2VYU-BU0qS2YV.js} +1 -1
  67. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CasdPz5X.js → chunk-JWPE2WC7-DVH9dIGE.js} +1 -1
  68. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Cj8lRrla.js → chunk-KBJHAD2P-Dt60SmgM.js} +1 -1
  69. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CUvD1FSd.js → chunk-RYQCIY6F-BoaUGuEY.js} +1 -1
  70. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CqLw_eqB.js → chunk-XXDRQBXY-_WHFDTp2.js} +1 -1
  71. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DZFra1GO.js +1 -0
  72. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DZFra1GO.js +1 -0
  73. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-ku-WqJPx.js → cose-bilkent-JH36ORCC-BxkbTIRd.js} +1 -1
  74. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-Bq_PYDhl.js → cynefin-VYW2F7L2-Bf2UVnoG.js} +1 -1
  75. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BiGZV641.js → cynefinDiagram-MW4NZA55-Bo23q1J_.js} +1 -1
  76. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-C4JRlglF.js → dagre-VZM6K2ZE-Dd_UU49i.js} +1 -1
  77. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B0dNeWYG.js → diagram-7IWD3JNH-ebUa1a9y.js} +1 -1
  78. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-Cj35YvYM.js → diagram-B4RE2ZJO-BucthU8r.js} +1 -1
  79. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-uzQoJ2-8.js → diagram-LBJQPF4R-BgqNpAkm.js} +1 -1
  80. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D1a-Buoz.js → diagram-Q27KOJAE-DC4q5NGa.js} +1 -1
  81. package/dist/worker/console/static/assets/{diagram-UB23O5K3-XjRrLRSs.js → diagram-UB23O5K3-CBqCaMeb.js} +1 -1
  82. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Da_O24cW.js → ebnfDiagram-BXEA7PRR-CGtnbQ3-.js} +1 -1
  83. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BLJ8jrYU.js → erDiagram-JOGREHBK-CG3LUao5.js} +1 -1
  84. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-B9GrLjM0.js → flowDiagram-UKHOOZJN-D2ZVgoFS.js} +1 -1
  85. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CeJ0TqiK.js → ganttDiagram-PKOTCBZU-DoYFZiKt.js} +1 -1
  86. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bm2eNNFX.js → gitGraphDiagram-DS77QQ5N-CKoP1s6j.js} +1 -1
  87. package/dist/worker/console/static/assets/index-CAZ2fC_X.css +1 -0
  88. package/dist/worker/console/static/assets/index-vbTcFnFs.js +449 -0
  89. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DB26i3d8.js → infoDiagram-6WML65LV-Duofv8p2.js} +1 -1
  90. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BOGRyeZT.js → ishikawaDiagram-WSZJBQD7-D2nlCkA1.js} +1 -1
  91. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CZRoBO_6.js → journeyDiagram-NVQOT4AX-Dd4IHdus.js} +1 -1
  92. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-qlWhJyoB.js → kanban-definition-27J2QSJJ-Bi20AOdt.js} +1 -1
  93. package/dist/worker/console/static/assets/{linear-CfUiDDB3.js → linear-D59YJ9kB.js} +1 -1
  94. package/dist/worker/console/static/assets/{mermaid.core-BQe6fpqj.js → mermaid.core-Bl13LpNa.js} +5 -5
  95. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-zFzWHw64.js → mindmap-definition-FAOFIHXS-C6DLP5eY.js} +1 -1
  96. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DFGUqjZO.js → pegDiagram-VL7TDLO6-BjO4cy64.js} +1 -1
  97. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BB5i0l8Z.js → pieDiagram-7S7Q4E2Y-D7i2qZTG.js} +1 -1
  98. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-obbVZ_X5.js → quadrantDiagram-CIZ2JOQS-Dx8o_h0y.js} +1 -1
  99. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BwdaNzc1.js → railroadDiagram-AXF67PYL-B55orI_t.js} +1 -1
  100. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CkTJaugh.js → requirementDiagram-LRYGKXZP-zWaehp6f.js} +1 -1
  101. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-BwJ-hIgq.js → sankeyDiagram-W5VNT64P-CcA-pjvD.js} +1 -1
  102. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BzSgmm7w.js → sequenceDiagram-SI44F4Z6-BOFbzNHI.js} +1 -1
  103. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-Bn3oj5Q1.js → sizeCapture-X5ZJPWSS-BjAejah1.js} +1 -1
  104. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-dxhGtL8K.js → stateDiagram-OKZ733FA-DXYwxJwZ.js} +1 -1
  105. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Clg3V9t1.js +1 -0
  106. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BLpEInya.js → swimlanes-SLNWSIFB-OYiOch8n.js} +2 -2
  107. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DX1dxAAW.js +8 -0
  108. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-ChJGYcXy.js → timeline-definition-Z64GVDOM-cZfH3nmU.js} +1 -1
  109. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DK-qjRer.js → vennDiagram-T6HMQDX7-BDE7b3E1.js} +1 -1
  110. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-3qeaWAg-.js → wardleyDiagram-T6FBY63Y-kyyGy9WJ.js} +1 -1
  111. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CootlyP9.js → xychartDiagram-ELKLHX3M-CJj6VTog.js} +1 -1
  112. package/dist/worker/console/static/index.html +2 -2
  113. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  114. package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -5
  115. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +19 -8
  116. package/dist/worker/console/static-src/operator-chat/input-history.js +8 -6
  117. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +15 -7
  118. package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
  119. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +258 -23
  120. package/dist/worker/console/static-src/operator-chat/useChatThread.js +112 -4
  121. package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -4
  122. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
  123. package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
  124. package/dist/worker/console/static-src/shell/console-update-reload.js +36 -9
  125. package/dist/worker/console/static-src/shell/workspace-route.js +11 -0
  126. package/dist/worker/console/workspace-context.js +115 -1
  127. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  128. package/dist/worker/observe/routes.js +4 -0
  129. package/dist/worker/observe/static/constants.js +22 -22
  130. package/dist/worker/observe/static/dag-context-reason-labels.js +19 -0
  131. package/dist/worker/observe/static/dag-helpers.js +4 -2
  132. package/dist/worker/observe/static/dag-history-labels.js +1 -0
  133. package/dist/worker/observe/static/dag-inspector-humanize.d.ts +16 -0
  134. package/dist/worker/observe/static/dag-inspector-humanize.js +339 -0
  135. package/dist/worker/observe/static/dag-node-purpose.js +13 -8
  136. package/dist/worker/observe/static/index.html +4 -4
  137. package/dist/worker/observe/static/inspect-workspace.js +23 -0
  138. package/dist/worker/observe/static/kpi.js +2 -2
  139. package/dist/worker/observe/static/operator-chrome.d.ts +10 -2
  140. package/dist/worker/observe/static/operator-chrome.js +37 -23
  141. package/dist/worker/observe/static/prompt-restart-candidates.js +4 -2
  142. package/dist/worker/observe/static/relations.js +7 -7
  143. package/dist/worker/observe/static/router.d.ts +12 -1
  144. package/dist/worker/observe/static/router.js +48 -6
  145. package/dist/worker/observe/static/run-processing.js +4 -2
  146. package/dist/worker/observe/static/shell-chrome.js +2 -2
  147. package/dist/worker/observe/static/state.js +5 -0
  148. package/dist/worker/observe/static/styles.css +231 -0
  149. package/dist/worker/observe/static/views/dag-graph.js +1 -1
  150. package/dist/worker/observe/static/views/dag-inspector.js +336 -181
  151. package/dist/worker/observe/static/views/dag.js +26 -14
  152. package/dist/worker/observe/static/views/dags.js +3 -1
  153. package/dist/worker/observe/static/views/dashboard.js +14 -6
  154. package/dist/worker/observe/static/views/pool.js +7 -2
  155. package/dist/worker/observe/static/views/run.js +12 -3
  156. package/dist/worker/observe/static/views/session-timeline.js +74 -13
  157. package/dist/worker/observe/static/views/task.js +7 -2
  158. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +215 -28
  159. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  160. package/dist/workflows/dag/backend-test-plan-protocol.js +210 -0
  161. package/dist/workflows/dag/backend-test-scenario-param.js +172 -25
  162. package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
  163. package/dist/workflows/dag/backend-test-writer-completeness.js +104 -12
  164. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  165. package/dist/workflows/dag/dag-retry-schema.js +138 -0
  166. package/dist/workflows/dag/frontend-closeout.js +221 -0
  167. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  168. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  169. package/dist/workflows/dag/frontend-implementation-contract.js +1237 -192
  170. package/dist/workflows/dag/frontend-plan-render.js +2 -1
  171. package/dist/workflows/dag/frontend-prewrite-gate.js +256 -350
  172. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  173. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  174. package/dist/workflows/dag/frontend-recovery-controller.js +226 -0
  175. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  176. package/dist/workflows/dag/frontend-recovery-plan.js +21 -10
  177. package/dist/workflows/dag/frontend-recovery-run.js +166 -34
  178. package/dist/workflows/dag/frontend-repair.js +1 -432
  179. package/dist/workflows/dag/frontend-review-context.js +261 -15
  180. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  181. package/dist/workflows/dag/frontend-shadow-dual-write.js +941 -0
  182. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  183. package/dist/workflows/dag/frontend-shape-facts.js +419 -0
  184. package/dist/workflows/dag/frontend-shape.js +435 -0
  185. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  186. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  187. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  188. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  189. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  190. package/dist/workflows/dag/frontend-verification-trace.js +252 -25
  191. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  192. package/dist/workflows/dag/frontend-writer-admission.js +319 -0
  193. package/dist/workflows/dag/frontend-writer-status.js +256 -0
  194. package/dist/workflows/dag/init-hybrid.js +1031 -564
  195. package/dist/workflows/dag/interrupt-request.js +7 -0
  196. package/dist/workflows/dag/node-execution.js +854 -4
  197. package/dist/workflows/dag/prompt.js +70 -3
  198. package/dist/workflows/dag/recovery-lease.js +170 -0
  199. package/dist/workflows/dag/report.js +37 -1
  200. package/dist/workflows/dag/rerun-feedback.js +315 -1
  201. package/dist/workflows/dag/rerun-plan.js +17 -6
  202. package/dist/workflows/dag/rerun-run.js +44 -6
  203. package/dist/workflows/dag/rerun-task.js +251 -13
  204. package/dist/workflows/dag/retry-policy.js +230 -104
  205. package/dist/workflows/dag/runner.js +580 -124
  206. package/dist/workflows/dag/scheduler.js +133 -20
  207. package/dist/workflows/dag/types.js +244 -16
  208. package/dist/workflows/dag/validate.js +28 -12
  209. package/docs/examples/README.md +5 -0
  210. package/docs/init-surface.manifest.json +30 -12
  211. package/docs/skills/vetted-skill-registry.md +4 -2
  212. package/docs/templates/README.md +2 -0
  213. package/docs/templates/agent-dag-report.schema.json +8 -2
  214. package/docs/templates/agent-dag.schema.json +1 -1
  215. package/docs/templates/backend-test-dag.json +25 -20
  216. package/docs/templates/frontend-implementation-contract.schema.json +4 -1
  217. package/docs/templates/frontend-implementation-dag.json +89 -0
  218. package/docs/templates/spec-registry.schema.json +45 -0
  219. package/harness.json +1 -1
  220. package/package.json +4 -3
  221. package/skills/frontend-bounded-implement/SKILL.md +15 -14
  222. package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
  223. package/skills/frontend-contract/SKILL.md +23 -0
  224. package/skills/frontend-contract/references/contract-protocol.md +34 -0
  225. package/skills/frontend-design-review/SKILL.md +22 -41
  226. package/skills/frontend-plan/SKILL.md +26 -0
  227. package/skills/frontend-plan/references/decision-contract.md +37 -0
  228. package/skills/frontend-plan/references/design-decisions.md +17 -0
  229. package/skills/frontend-review/SKILL.md +20 -15
  230. package/skills/frontend-review/references/review-findings.md +6 -7
  231. package/skills/frontend-scout/SKILL.md +25 -0
  232. package/skills/frontend-scout/references/design-evidence.md +16 -0
  233. package/skills/frontend-scout/references/scout-evidence.md +23 -0
  234. package/skills/frontend-verification/SKILL.md +1 -1
  235. package/skills/loop-agent/references/command-reference.md +1 -0
  236. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  237. package/dist/worker/console/static/assets/channel-BU5gOilw.js +0 -1
  238. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DIzKJGHr.js +0 -1
  239. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DIzKJGHr.js +0 -1
  240. package/dist/worker/console/static/assets/index-H9rFJiGL.css +0 -1
  241. package/dist/worker/console/static/assets/index-xwu9GxEc.js +0 -451
  242. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cld2qK9v.js +0 -1
  243. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-TIHpiT7w.js +0 -8
  244. package/skills/frontend-implementation/SKILL.md +0 -52
  245. package/skills/frontend-implementation/references/code-standards.md +0 -33
  246. package/skills/frontend-implementation/references/design-spec.md +0 -56
  247. package/skills/frontend-implementation/references/node-contracts.md +0 -31
@@ -35,7 +35,12 @@ import {
35
35
  parseMarkdownBlocks,
36
36
  markdownLinkHref,
37
37
  } from "../format.js";
38
- import { parseRoute, navigate, buildHashPath } from "../router.js";
38
+ import {
39
+ parseRoute,
40
+ navigate,
41
+ buildHashPath,
42
+ withWorkspaceQuery,
43
+ } from "../router.js";
39
44
  import {
40
45
  fetchJson,
41
46
  artifactUrl,
@@ -71,6 +76,7 @@ import {
71
76
  findDagForRun,
72
77
  } from "../dag-model.js";
73
78
  import { describeDagNodePurpose } from "../dag-node-purpose.js";
79
+ import { inspectorValueLabel } from "../dag-inspector-humanize.js";
74
80
  import { layoutDag } from "../dag-layout.js";
75
81
  import {
76
82
  showView,
@@ -192,7 +198,9 @@ export function buildDagNodeTable(dagRunId, nodes) {
192
198
  index + 1,
193
199
  node.nodeId,
194
200
  node.rank ?? "—",
195
- node.executor ?? "—",
201
+ node.executor
202
+ ? inspectorValueLabel("executor", node.executor)
203
+ : "—",
196
204
  node.model ?? "—",
197
205
  node.status ? badge(node.status) : "—",
198
206
  formatMs(node.durationMs),
@@ -206,10 +214,10 @@ export function buildDagNodeTable(dagRunId, nodes) {
206
214
  const nodeTable = buildTable(
207
215
  [
208
216
  "序号",
209
- "节点 ID",
210
- "依赖层",
217
+ "步骤编号",
218
+ "执行层级",
211
219
  "执行方式",
212
- "模型",
220
+ "实际模型",
213
221
  "状态",
214
222
  "耗时",
215
223
  "执行历史",
@@ -248,6 +256,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
248
256
  uiState.dagInspectorAttempt = null;
249
257
  uiState.dagGraphViewportState = null;
250
258
  uiState.dagTimelineViewportState = null;
259
+ uiState.dagTimelineAutoScrollEnabled = true;
251
260
  }
252
261
  // AC-001:同会话内重新进入同一 dagRunId 保持当前图视图模式(不切回逻辑拓扑)。
253
262
  uiState.dagGraphViewMode = dagGraphViewModes.get(dagRunId) ?? "topology";
@@ -255,7 +264,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
255
264
  const metaEl = document.getElementById("dag-meta");
256
265
  const ranksEl = document.getElementById("dag-ranks");
257
266
  const nodesEl = document.getElementById("dag-nodes");
258
- if (initial && metaEl) mountViewState(metaEl, "loading", "加载 DAG…");
267
+ if (initial && metaEl) mountViewState(metaEl, "loading", "正在加载运行流程…");
259
268
  uiState.dagGraphViewportState = captureDagGraphViewportState(
260
269
  uiState.dagGraphViewportState,
261
270
  dagRunId,
@@ -275,7 +284,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
275
284
  }
276
285
  if (!dag) {
277
286
  clearNode(metaEl);
278
- mountViewState(metaEl, "error", "找不到该 DAG 运行。");
287
+ mountViewState(metaEl, "error", "找不到这次运行。运行记录可能已被清理。");
279
288
  mountRelationBar("dag-relations", {}, snapshot);
280
289
  closeDagInspector();
281
290
  return false;
@@ -348,7 +357,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
348
357
  LIVENESS_LABELS[dag.liveness] ?? dag.liveness ?? LIVENESS_LABELS.unknown;
349
358
  const primaryEntries = [
350
359
  ["标题", dag.title || dag.dagRunId],
351
- ["DAG 运行 ID", dag.dagRunId],
360
+ ["运行编号", dag.dagRunId],
352
361
  ["状态", dagStatusBadge(dag.effectiveStatus ?? dag.status)],
353
362
  ];
354
363
  if (visibility.showExecutorStatus)
@@ -364,7 +373,9 @@ export async function renderDagDetail(dagRunId, initial = true) {
364
373
  "page-action-btn",
365
374
  "在操作台中止此运行 →",
366
375
  );
367
- interruptLink.href = `/#/operate/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`;
376
+ interruptLink.href = withWorkspaceQuery(
377
+ `/#/operate/recovery?dagRunId=${encodeURIComponent(dag.dagRunId)}&intent=interrupt`,
378
+ );
368
379
  interruptLink.setAttribute("data-testid", "inspect-dag-interrupt-link");
369
380
  interruptLink.title = "只跳转到操作台 Recovery,不会在观测页执行中止";
370
381
  primaryEntries.push(["协作中止", interruptLink]);
@@ -375,7 +386,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
375
386
  ["总耗时", formatDuration(dag.durationMs)],
376
387
  ["进度", `${progress.finished}/${progress.total}`],
377
388
  ["成功/失败/跳过", `${succeededCount}/${failedCount}/${skippedCount}`],
378
- ["DAG 路径", dag.dagPath ?? "—"],
389
+ ["记录保存位置", dag.dagPath ?? "—"],
379
390
  );
380
391
  const lintSummary = frontendLintSummary(dag.frontendLint);
381
392
  if (lintSummary) {
@@ -421,7 +432,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
421
432
  );
422
433
  if (nodes.length === 0) {
423
434
  clearNode(ranksEl);
424
- ranksEl.appendChild(el("h3", null, "DAG 依赖图"));
435
+ ranksEl.appendChild(el("h3", null, "执行步骤关系"));
425
436
  ranksEl.appendChild(el("p", "empty", UI_TEXT.noNodes));
426
437
  } else if (reuseShell && existingGraphWrap?.parentNode === ranksEl) {
427
438
  // reuse-dag-graph-wrap + viewport identity: keep wrap/viewport alive.
@@ -432,16 +443,16 @@ export async function renderDagDetail(dagRunId, initial = true) {
432
443
  }
433
444
  } else {
434
445
  clearNode(ranksEl);
435
- ranksEl.appendChild(el("h3", null, "DAG 依赖图"));
446
+ ranksEl.appendChild(el("h3", null, "执行步骤关系"));
436
447
  ranksEl.appendChild(renderDagGraph(dag, dagRunId, null));
437
448
  }
438
449
 
439
450
  const nodesScrollLeft = nodesEl.scrollLeft;
440
451
  clearNode(nodesEl);
441
452
  const nodeHeading = el("div", "dag-section-heading");
442
- nodeHeading.appendChild(el("h3", null, "节点"));
453
+ nodeHeading.appendChild(el("h3", null, "执行步骤"));
443
454
  nodeHeading.appendChild(
444
- el("span", "dag-section-meta", `共 ${nodes.length} 个节点`),
455
+ el("span", "dag-section-meta", `共 ${nodes.length} 个步骤`),
445
456
  );
446
457
  nodesEl.appendChild(nodeHeading);
447
458
 
@@ -471,6 +482,7 @@ export async function renderDagDetail(dagRunId, initial = true) {
471
482
  dagRunId,
472
483
  nodes.find((node) => node.nodeId === uiState.selectedDagNodeId),
473
484
  initial,
485
+ dag,
474
486
  );
475
487
  return isDagRunActive(dag);
476
488
  }
@@ -327,7 +327,9 @@ function buildRow(run) {
327
327
 
328
328
  const nameTd = document.createElement("td");
329
329
  const nameLink = el("a", "dags-name-link", run.title || run.dagRunId);
330
- nameLink.href = `#/dag/${encodeURIComponent(run.dagRunId)}`;
330
+ nameLink.href = inspectPathToCanonicalHref(
331
+ `/dag/${encodeURIComponent(run.dagRunId)}`,
332
+ );
331
333
  nameLink.addEventListener("click", (event) => {
332
334
  event.preventDefault();
333
335
  event.stopPropagation();
@@ -35,7 +35,13 @@ import {
35
35
  parseMarkdownBlocks,
36
36
  markdownLinkHref,
37
37
  } from "../format.js";
38
- import { parseRoute, navigate, buildHashPath } from "../router.js";
38
+ import {
39
+ parseRoute,
40
+ navigate,
41
+ buildHashPath,
42
+ inspectPathToCanonicalHref,
43
+ withWorkspaceQuery,
44
+ } from "../router.js";
39
45
  import { fetchJson, artifactUrl, parseArtifactPreviewResponse } from "../api.js";
40
46
  import {
41
47
  objectRouteLink,
@@ -118,14 +124,14 @@ async function renderNightStrip() {
118
124
 
119
125
  const actions = el("div", "night-strip-actions");
120
126
  const detail = el("a", "page-action-btn", "夜间详情");
121
- detail.href = "/#/inspect/night";
127
+ detail.href = inspectPathToCanonicalHref("/night");
122
128
  detail.addEventListener("click", (e) => {
123
129
  e.preventDefault();
124
130
  navigate("/night");
125
131
  });
126
132
  actions.appendChild(detail);
127
133
  const manage = el("a", "page-action-btn night-strip-manage", "晨审处置 →");
128
- manage.href = "/#/operate/night";
134
+ manage.href = withWorkspaceQuery("/#/operate/night");
129
135
  manage.title = "夜间计划的管理与晨审处置在操作台完成(Inspect 保持只读)";
130
136
  actions.appendChild(manage);
131
137
  strip.appendChild(actions);
@@ -528,7 +534,7 @@ export async function renderDashboard(scrollTo) {
528
534
  workerBlock.appendChild(el("div", "risk-total", String(block.total)));
529
535
  workerBlock.appendChild(el("p", "risk-summary", block.summary));
530
536
  const link = el("a", "risk-link", "查看异常 Task →");
531
- link.href = "#/failures";
537
+ link.href = inspectPathToCanonicalHref("/failures");
532
538
  link.addEventListener("click", (event) => {
533
539
  event.preventDefault();
534
540
  navigate("/failures");
@@ -556,7 +562,7 @@ export async function renderDashboard(scrollTo) {
556
562
  const head = el("div", "section-heading-row");
557
563
  head.appendChild(el("h3", "section-heading", UI_TEXT.recentDags));
558
564
  const allLink = el("a", "section-heading-action", UI_TEXT.viewAllDags);
559
- allLink.href = "#/dags?page=1&pageSize=20";
565
+ allLink.href = inspectPathToCanonicalHref("/dags?page=1&pageSize=20");
560
566
  allLink.setAttribute("aria-label", "查看全部 DAG 运行历史");
561
567
  allLink.addEventListener("click", (event) => {
562
568
  event.preventDefault();
@@ -686,7 +692,9 @@ function syncTableRow(row, cells) {
686
692
  function buildDagTimelineItem(dag) {
687
693
  const progress = dagProgress(dag);
688
694
  const item = el("a", "dag-run-timeline-item");
689
- item.href = `#/dag/${encodeURIComponent(dag.dagRunId)}`;
695
+ item.href = inspectPathToCanonicalHref(
696
+ `/dag/${encodeURIComponent(dag.dagRunId)}`,
697
+ );
690
698
  item.title = dag.title || dag.dagRunId;
691
699
  item.addEventListener("click", (event) => {
692
700
  event.preventDefault();
@@ -8,7 +8,12 @@ import {
8
8
  livenessBadge,
9
9
  truncateText,
10
10
  } from "../format.js";
11
- import { parseRoute, navigate, buildHashPath } from "../router.js";
11
+ import {
12
+ parseRoute,
13
+ navigate,
14
+ buildHashPath,
15
+ inspectPathToCanonicalHref,
16
+ } from "../router.js";
12
17
  import { fetchJson } from "../api.js";
13
18
  import { objectRouteLink } from "../relations.js";
14
19
  import {
@@ -118,7 +123,7 @@ function taskPath(task) {
118
123
 
119
124
  function linkTo(path, label, className) {
120
125
  const a = el("a", className || "object-link", label);
121
- a.href = `#${path}`;
126
+ a.href = inspectPathToCanonicalHref(path);
122
127
  a.addEventListener("click", (e) => {
123
128
  e.preventDefault();
124
129
  e.stopPropagation();
@@ -35,7 +35,12 @@ import {
35
35
  parseMarkdownBlocks,
36
36
  markdownLinkHref,
37
37
  } from "../format.js";
38
- import { parseRoute, navigate, buildHashPath } from "../router.js";
38
+ import {
39
+ parseRoute,
40
+ navigate,
41
+ buildHashPath,
42
+ inspectPathToCanonicalHref,
43
+ } from "../router.js";
39
44
  import {
40
45
  fetchJson,
41
46
  artifactUrl,
@@ -176,7 +181,9 @@ export function renderRunDagProgress(task, snapshot) {
176
181
  "详情",
177
182
  (() => {
178
183
  const a = el("a", "link", "查看 DAG 详情 →");
179
- a.href = `#/dag/${encodeURIComponent(dag.dagRunId)}`;
184
+ a.href = inspectPathToCanonicalHref(
185
+ `/dag/${encodeURIComponent(dag.dagRunId)}`,
186
+ );
180
187
  a.addEventListener("click", (e) => {
181
188
  e.preventDefault();
182
189
  navigate(`/dag/${encodeURIComponent(dag.dagRunId)}`);
@@ -295,7 +302,9 @@ export function renderRunPanels(task, events, snapshot) {
295
302
  li.appendChild(marker);
296
303
  if (step.label === "run-dag" && dag?.dagRunId) {
297
304
  const link = document.createElement("a");
298
- link.href = `#/dag/${encodeURIComponent(dag.dagRunId)}`;
305
+ link.href = inspectPathToCanonicalHref(
306
+ `/dag/${encodeURIComponent(dag.dagRunId)}`,
307
+ );
299
308
  link.className = "step-link";
300
309
  link.textContent = "DAG →";
301
310
  link.addEventListener("click", (e) => {
@@ -7,12 +7,72 @@ import { fetchJson } from "../api.js";
7
7
  import {
8
8
  uiState,
9
9
  updateDagTimelineViewportState,
10
- computeFollowLatest,
11
10
  } from "../state.js";
12
11
 
13
12
  /** Default visible lines for tool result preview before expand. */
14
13
  export const TOOL_RESULT_PREVIEW_LINES = 20;
15
14
 
15
+ function isTimelineAutoScrollEnabled() {
16
+ return uiState.dagTimelineAutoScrollEnabled !== false;
17
+ }
18
+
19
+ function scrollTimelineToLatest(content) {
20
+ content.scrollLeft = 0;
21
+ content.scrollTop = content.scrollHeight;
22
+ uiState.dagTimelineViewportState = updateDagTimelineViewportState(
23
+ uiState.dagTimelineViewportState,
24
+ uiState.currentDagRunId,
25
+ content.dataset.nodeId,
26
+ content.scrollLeft,
27
+ content.scrollTop,
28
+ true,
29
+ );
30
+ }
31
+
32
+ /** Floating, explicit live-follow control for the execution-record viewport. */
33
+ export function createTimelineAutoScrollControl(content) {
34
+ const dock = el("div", "process-timeline-autoscroll-dock");
35
+ const button = document.createElement("button");
36
+ button.type = "button";
37
+ const signal = el("span", "process-timeline-autoscroll-signal");
38
+ signal.setAttribute("aria-hidden", "true");
39
+ const icon = el("i", "ri-arrow-down-line");
40
+ icon.setAttribute("aria-hidden", "true");
41
+ button.appendChild(signal);
42
+ button.appendChild(icon);
43
+
44
+ const sync = () => {
45
+ const enabled = isTimelineAutoScrollEnabled();
46
+ const actionLabel = enabled ? "关闭自动滚动" : "自动滚动";
47
+ button.className = `process-timeline-autoscroll${enabled ? " is-active" : ""}`;
48
+ button.setAttribute("aria-pressed", String(enabled));
49
+ button.setAttribute("aria-label", actionLabel);
50
+ button.setAttribute("data-tooltip", actionLabel);
51
+ icon.className = enabled ? "ri-arrow-down-line" : "ri-pause-mini-fill";
52
+ };
53
+
54
+ button.addEventListener("click", () => {
55
+ const enabled = !isTimelineAutoScrollEnabled();
56
+ uiState.dagTimelineAutoScrollEnabled = enabled;
57
+ if (enabled) scrollTimelineToLatest(content);
58
+ else {
59
+ uiState.dagTimelineViewportState = updateDagTimelineViewportState(
60
+ uiState.dagTimelineViewportState,
61
+ uiState.currentDagRunId,
62
+ content.dataset.nodeId,
63
+ content.scrollLeft,
64
+ content.scrollTop,
65
+ false,
66
+ );
67
+ }
68
+ sync();
69
+ });
70
+
71
+ sync();
72
+ dock.appendChild(button);
73
+ return dock;
74
+ }
75
+
16
76
  export function normalizeSessionEventFields(event) {
17
77
  if (!event || typeof event !== "object") return {};
18
78
  const args = event.args ?? event.input ?? event.toolInput;
@@ -951,6 +1011,7 @@ export function renderSessionTimeline(content, nodeId, options = {}) {
951
1011
  });
952
1012
  toolbar.appendChild(exportBtn);
953
1013
  content.appendChild(toolbar);
1014
+ content.appendChild(createTimelineAutoScrollControl(content));
954
1015
 
955
1016
  const timelineItems = filterExecutionRecordItems(
956
1017
  buildRichTimelineItems(visible.events, { showProtocol }),
@@ -1030,23 +1091,18 @@ export function renderSessionTimeline(content, nodeId, options = {}) {
1030
1091
  content.addEventListener(
1031
1092
  "scroll",
1032
1093
  () => {
1033
- const followLatest = computeFollowLatest(
1034
- content.scrollTop,
1035
- content.scrollHeight,
1036
- content.clientHeight,
1037
- );
1038
1094
  uiState.dagTimelineViewportState = updateDagTimelineViewportState(
1039
1095
  uiState.dagTimelineViewportState,
1040
1096
  uiState.currentDagRunId,
1041
1097
  nodeId,
1042
1098
  content.scrollLeft,
1043
1099
  content.scrollTop,
1044
- followLatest,
1100
+ isTimelineAutoScrollEnabled(),
1045
1101
  );
1046
1102
  },
1047
1103
  { passive: true },
1048
1104
  );
1049
- if (timelineState?.followLatest ?? true) {
1105
+ if (isTimelineAutoScrollEnabled()) {
1050
1106
  content.scrollLeft = timelineState?.scrollLeft ?? 0;
1051
1107
  content.scrollTop = content.scrollHeight;
1052
1108
  } else {
@@ -1058,14 +1114,19 @@ export function renderSessionTimeline(content, nodeId, options = {}) {
1058
1114
  function rerenderSessionTimeline(content, nodeId, options) {
1059
1115
  const scrollTop = content.scrollTop;
1060
1116
  const scrollLeft = content.scrollLeft;
1117
+ const autoScrollEnabled = isTimelineAutoScrollEnabled();
1061
1118
  const preserved = [...content.children].filter((child) =>
1062
- String(child.className ?? "")
1063
- .split(/\s+/)
1064
- .includes("dag-inspector-attempt-bar"),
1119
+ ["dag-inspector-attempt-bar", "inspector-page-lead"].some((className) =>
1120
+ String(child.className ?? "")
1121
+ .split(/\s+/)
1122
+ .includes(className),
1123
+ ),
1065
1124
  );
1066
1125
  while (content.firstChild) content.removeChild(content.firstChild);
1067
1126
  for (const child of preserved) content.appendChild(child);
1068
1127
  renderSessionTimeline(content, nodeId, options);
1069
- content.scrollTop = scrollTop;
1070
- content.scrollLeft = scrollLeft;
1128
+ if (!autoScrollEnabled) {
1129
+ content.scrollTop = scrollTop;
1130
+ content.scrollLeft = scrollLeft;
1131
+ }
1071
1132
  }
@@ -36,7 +36,12 @@ import {
36
36
  markdownLinkHref,
37
37
  formatLedgerSummary,
38
38
  } from "../format.js";
39
- import { parseRoute, navigate, buildHashPath } from "../router.js";
39
+ import {
40
+ parseRoute,
41
+ navigate,
42
+ buildHashPath,
43
+ inspectPathToCanonicalHref,
44
+ } from "../router.js";
40
45
  import {
41
46
  fetchJson,
42
47
  fetchJsonResult,
@@ -133,7 +138,7 @@ export async function renderTaskDetail(featureId, taskId) {
133
138
  if (!c?.featureId || !c?.taskId) continue;
134
139
  const path = `/feature/${encodeURIComponent(c.featureId)}/task/${encodeURIComponent(c.taskId)}`;
135
140
  const a = el("a", "object-link", `${c.featureId}::${c.taskId}`);
136
- a.href = `#${path}`;
141
+ a.href = inspectPathToCanonicalHref(path);
137
142
  a.addEventListener("click", (e) => {
138
143
  e.preventDefault();
139
144
  navigate(path);