@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
@@ -11,6 +11,8 @@
11
11
  * mountOperatorChrome 仅在浏览器环境调用。
12
12
  */
13
13
 
14
+ import { withWorkspaceQuery } from "./router.js";
15
+
14
16
  export const OPERATE_TABS = Object.freeze([
15
17
  { id: "tasks", label: "任务", href: "/#/operate/tasks" },
16
18
  { id: "recovery", label: "恢复", href: "/#/operate/recovery" },
@@ -52,16 +54,7 @@ export function parseInspectWorkspaceId(hashValue) {
52
54
  return id || null;
53
55
  }
54
56
 
55
- export function withWorkspaceQuery(href, workspaceId) {
56
- const raw = String(href ?? "");
57
- if (!workspaceId) return raw;
58
- const qIndex = raw.indexOf("?");
59
- if (qIndex < 0) return `${raw}?workspaceId=${encodeURIComponent(workspaceId)}`;
60
- const params = new URLSearchParams(raw.slice(qIndex + 1));
61
- if (params.get("workspaceId") === workspaceId) return raw;
62
- params.set("workspaceId", workspaceId);
63
- return `${raw.slice(0, qIndex)}?${params.toString()}`;
64
- }
57
+ export { withWorkspaceQuery };
65
58
 
66
59
  function splitHash(hashValue) {
67
60
  const raw = String(hashValue ?? "").replace(/^#/, "");
@@ -129,13 +122,17 @@ export function parseInspectContext(hashValue) {
129
122
  if (from !== "recovery") return null;
130
123
  const returnParams = new URLSearchParams();
131
124
  if (objectView.view === "dag") returnParams.set("dagRunId", objectView.id);
125
+ const workspaceId = parseInspectWorkspaceId(hashValue);
132
126
  const suffix = returnParams.toString();
133
127
  return {
134
128
  view: objectView.view,
135
129
  id: objectView.id,
136
130
  from,
137
131
  kindLabel: CONTEXT_KIND_LABELS[objectView.view] ?? objectView.view,
138
- returnHref: `/#/operate/recovery${suffix ? `?${suffix}` : ""}`,
132
+ returnHref: withWorkspaceQuery(
133
+ `/#/operate/recovery${suffix ? `?${suffix}` : ""}`,
134
+ workspaceId,
135
+ ),
139
136
  returnLabel: "返回 恢复",
140
137
  };
141
138
  }
@@ -143,21 +140,31 @@ export function parseInspectContext(hashValue) {
143
140
  /** 从 Inspect 切回操作侧:持有 DAG 选中时不丢对象(换动作不换对象)。 */
144
141
  export function resolveOperateHrefFromInspectHash(hashValue) {
145
142
  const objectView = parseInspectObjectView(hashValue);
143
+ const workspaceId = parseInspectWorkspaceId(hashValue);
146
144
  if (objectView?.view === "dag") {
147
- return `/#/operate/recovery?dagRunId=${encodeURIComponent(objectView.id)}`;
145
+ return withWorkspaceQuery(
146
+ `/#/operate/recovery?dagRunId=${encodeURIComponent(objectView.id)}`,
147
+ workspaceId,
148
+ );
148
149
  }
149
- return "/#/operate/tasks";
150
+ return withWorkspaceQuery("/#/operate/tasks", workspaceId);
150
151
  }
151
152
 
152
153
  /** Inspect DAG 详情 → Operate Recovery 协作中止深链(只改导航,不发 mutation)。 */
153
- export function buildOperateInterruptHref(dagRunId) {
154
- return `/#/operate/recovery?dagRunId=${encodeURIComponent(dagRunId)}&intent=interrupt`;
154
+ export function buildOperateInterruptHref(dagRunId, options = {}) {
155
+ return withWorkspaceQuery(
156
+ `/#/operate/recovery?dagRunId=${encodeURIComponent(dagRunId)}&intent=interrupt`,
157
+ options.workspaceId,
158
+ );
155
159
  }
156
160
 
157
161
  /** 操作侧 → Inspect 的 canonical 深链(可携带 from 以激活上下文 chip)。 */
158
162
  export function buildInspectDagHref(dagRunId, options = {}) {
159
163
  const base = `/#/inspect/dag/${encodeURIComponent(dagRunId)}`;
160
- return options.from === "recovery" ? `${base}?from=recovery` : base;
164
+ return withWorkspaceQuery(
165
+ options.from === "recovery" ? `${base}?from=recovery` : base,
166
+ options.workspaceId,
167
+ );
161
168
  }
162
169
 
163
170
  /** 清除跨模式来源标记,但保留对象页上的其它查询参数与当前历史位置。 */
@@ -218,14 +225,19 @@ export function buildOperatorChromeModel(config) {
218
225
  : []
219
226
  ).map((tab) => ({
220
227
  ...tab,
228
+ href: withWorkspaceQuery(
229
+ tab.href,
230
+ config.workspaceSwitcher?.activeId ?? config.workspaceId,
231
+ ),
221
232
  active:
222
- tab.href ===
233
+ tab.href.split("?")[0] ===
223
234
  (String(config.activeTabHref ?? "").split("?")[0] || null),
224
235
  }));
225
236
  const state = config.readinessState ?? "unknown";
226
237
  const operateHref = config.operateHref ?? "/#/operate/tasks";
227
238
  const inspectHref = config.inspectHref ?? "/#/inspect";
228
- const activeWorkspaceId = config.workspaceSwitcher?.activeId ?? null;
239
+ const activeWorkspaceId =
240
+ config.workspaceSwitcher?.activeId ?? config.workspaceId ?? null;
229
241
  return {
230
242
  mode,
231
243
  homeHref: withWorkspaceQuery(
@@ -245,13 +257,13 @@ export function buildOperatorChromeModel(config) {
245
257
  {
246
258
  id: "operate",
247
259
  label: "操作",
248
- href: operateHref,
260
+ href: withWorkspaceQuery(operateHref, activeWorkspaceId),
249
261
  active: mode === "operate",
250
262
  },
251
263
  {
252
264
  id: "inspect",
253
265
  label: "观测",
254
- href: inspectHref,
266
+ href: withWorkspaceQuery(inspectHref, activeWorkspaceId),
255
267
  active: mode === "inspect",
256
268
  },
257
269
  ],
@@ -261,9 +273,10 @@ export function buildOperatorChromeModel(config) {
261
273
  pi: {
262
274
  state,
263
275
  label: READINESS_LABELS[state] ?? state,
264
- href:
265
- config.readinessHref ??
266
- (mode === "inspect" ? "/#/operate/models" : "/#/operate/models"),
276
+ href: withWorkspaceQuery(
277
+ config.readinessHref ?? "/#/operate/models",
278
+ activeWorkspaceId,
279
+ ),
267
280
  title: config.readinessTitle ?? "",
268
281
  },
269
282
  workspaceTabsVisible: tabs.length > 0,
@@ -424,6 +437,7 @@ export function mountOperatorChrome(root, config = {}) {
424
437
  const base = { ...currentConfig };
425
438
  if (base.liveLocation) {
426
439
  const hash = window.location.hash;
440
+ base.workspaceId = parseInspectWorkspaceId(hash);
427
441
  base.activeTabHref = activeInspectTabHref(hash);
428
442
  base.operateHref = resolveOperateHrefFromInspectHash(hash);
429
443
  base.context = parseInspectContext(hash);
@@ -1,3 +1,5 @@
1
+ import { attemptFailureLabel } from "./dag-history-labels.js";
2
+
1
3
  export function buildPromptRestartCandidateOptions(
2
4
  frozenPrompt,
3
5
  failedCandidates,
@@ -5,7 +7,7 @@ export function buildPromptRestartCandidateOptions(
5
7
  const options = [
6
8
  {
7
9
  key: "frozen",
8
- label: "冻结原始提示词",
10
+ label: "运行开始时的提示词",
9
11
  prompt: String(frozenPrompt ?? ""),
10
12
  truncated: false,
11
13
  },
@@ -27,7 +29,7 @@ export function buildPromptRestartCandidateOptions(
27
29
  : "unknown";
28
30
  options.push({
29
31
  key: `attempt-${attempt}`,
30
- label: `第 ${attempt} 次失败 · ${failureCategory}`,
32
+ label: `第 ${attempt} 次失败 · ${attemptFailureLabel(failureCategory)}`,
31
33
  prompt: candidate.prompt,
32
34
  truncated: candidate.truncated === true,
33
35
  });
@@ -1,6 +1,6 @@
1
1
  /** Object relation navigation (Observe UI R5). */
2
2
  import { el } from "./dom.js";
3
- import { navigate } from "./router.js";
3
+ import { inspectPathToCanonicalHref, navigate } from "./router.js";
4
4
 
5
5
  export function objectExistsInSnapshot(kind, id, snapshot, featureId) {
6
6
  if (!id) return false;
@@ -48,7 +48,7 @@ export function objectRouteLink(kind, id, snapshot, featureId) {
48
48
  if (!exists) return el("span", "muted", id);
49
49
  const path = objectRoutePath(kind, id, featureId);
50
50
  const a = el("a", "object-link", id);
51
- a.href = `#${path}`;
51
+ a.href = inspectPathToCanonicalHref(path);
52
52
  a.addEventListener("click", (e) => {
53
53
  e.preventDefault();
54
54
  e.stopPropagation();
@@ -70,11 +70,11 @@ export function featureLookupState(snapshot, featureId) {
70
70
 
71
71
  export const RELATION_KIND_ORDER = ["feature", "task", "batch", "run", "dag"];
72
72
  export const RELATION_LABELS = {
73
- feature: "Feature",
74
- task: "Task",
75
- batch: "Batch",
76
- run: "Run",
77
- dag: "DAG",
73
+ feature: "需求",
74
+ task: "任务",
75
+ batch: "任务批次",
76
+ run: "执行实例",
77
+ dag: "运行流程",
78
78
  };
79
79
 
80
80
  /**
@@ -18,7 +18,18 @@ export function parseRoute(): InspectHashRoute;
18
18
  export function setNavigateHandler(
19
19
  handler: ((href: string) => void) | null,
20
20
  ): void;
21
- export function inspectPathToCanonicalHref(path: string): string;
21
+ export function workspaceIdFromLocation(locationLike?: {
22
+ hash?: string;
23
+ search?: string;
24
+ } | null): string | null;
25
+ export function withWorkspaceQuery(
26
+ href: string,
27
+ workspaceId?: string | null,
28
+ ): string;
29
+ export function inspectPathToCanonicalHref(
30
+ path: string,
31
+ workspaceId?: string | null,
32
+ ): string;
22
33
  export function navigate(path: string): void;
23
34
 
24
35
  export const DAG_HISTORY_DEFAULT_PAGE: number;
@@ -70,15 +70,57 @@ export function setNavigateHandler(handler) {
70
70
  navigateHandler = typeof handler === "function" ? handler : null;
71
71
  }
72
72
 
73
- export function inspectPathToCanonicalHref(path) {
73
+ /** Read the selected workspace from either Console's canonical hash or the
74
+ * standalone Inspect document query. The latter remains a compatibility
75
+ * entrypoint, so it must not manufacture a scope when none was supplied. */
76
+ export function workspaceIdFromLocation(locationLike = typeof location !== "undefined" ? location : null) {
77
+ if (!locationLike) return null;
78
+ const hash = String(locationLike.hash ?? "").replace(/^#/, "");
79
+ const hashQuery = hash.includes("?") ? hash.slice(hash.indexOf("?") + 1) : "";
80
+ const fromHash = new URLSearchParams(hashQuery).get("workspaceId")?.trim();
81
+ if (fromHash) return fromHash;
82
+ return new URLSearchParams(String(locationLike.search ?? ""))
83
+ .get("workspaceId")
84
+ ?.trim() || null;
85
+ }
86
+
87
+ /** Add the current workspace to a Console hash href without changing the
88
+ * destination's own query. This is deliberately usable for Inspect, Operate,
89
+ * and Chat; Console canonicalization still strips scope from Chat itself. */
90
+ export function withWorkspaceQuery(href, workspaceId = workspaceIdFromLocation()) {
91
+ const raw = String(href ?? "").trim();
92
+ const id = workspaceId?.trim();
93
+ if (!raw || !id) return raw;
94
+ const normalized = raw.startsWith("#") ? `/${raw}` : raw;
95
+ const qIndex = normalized.indexOf("?");
96
+ const base = qIndex >= 0 ? normalized.slice(0, qIndex) : normalized;
97
+ const query = new URLSearchParams(qIndex >= 0 ? normalized.slice(qIndex + 1) : "");
98
+ query.set("workspaceId", id);
99
+ return `${base}?${query.toString()}`;
100
+ }
101
+
102
+ export function inspectPathToCanonicalHref(path, workspaceId = workspaceIdFromLocation()) {
74
103
  const raw = String(path ?? "");
75
- if (raw.startsWith("/#/inspect")) return raw;
76
- if (raw.startsWith("#/inspect")) return `/${raw}`;
104
+ if (raw.startsWith("/#/inspect")) return withWorkspaceQuery(raw, workspaceId);
105
+ if (raw.startsWith("#/inspect")) return withWorkspaceQuery(`/${raw}`, workspaceId);
106
+ // Inspect owns only its own paths. Passing an Operate/Chat deep link through
107
+ // the old converter produced /#/inspect/#/operate/... and was the direct
108
+ // cause of the live-DAG interrupt link landing on the wrong page.
109
+ if (raw.startsWith("/#/operate") || raw.startsWith("/#/chat")) {
110
+ return withWorkspaceQuery(raw, workspaceId);
111
+ }
112
+ if (raw.startsWith("#/operate") || raw.startsWith("#/chat")) {
113
+ return withWorkspaceQuery(`/${raw}`, workspaceId);
114
+ }
77
115
  const stripped = raw.replace(/^#/, "");
78
116
  const withSlash = stripped.startsWith("/") ? stripped : `/${stripped}`;
79
- if (withSlash === "/inspect" || withSlash === "/") return "/#/inspect";
80
- if (withSlash.startsWith("/inspect/")) return `/#${withSlash}`;
81
- return `/#/inspect${withSlash}`;
117
+ if (withSlash === "/inspect" || withSlash === "/") {
118
+ return withWorkspaceQuery("/#/inspect", workspaceId);
119
+ }
120
+ if (withSlash.startsWith("/inspect/")) {
121
+ return withWorkspaceQuery(`/#${withSlash}`, workspaceId);
122
+ }
123
+ return withWorkspaceQuery(`/#/inspect${withSlash}`, workspaceId);
82
124
  }
83
125
 
84
126
  export function navigate(path) {
@@ -6,7 +6,7 @@ import {
6
6
  ARTIFACT_KEYS,
7
7
  } from "./constants.js";
8
8
  import { badge } from "./format.js";
9
- import { navigate } from "./router.js";
9
+ import { inspectPathToCanonicalHref, navigate } from "./router.js";
10
10
 
11
11
  export function stepDisplayLabel(label) {
12
12
  return STEP_LABELS[label] ?? label;
@@ -127,7 +127,9 @@ export function taskRunHistoryRow(run) {
127
127
  let runLink = run.workerRunId;
128
128
  if (run.workerRunId) {
129
129
  const a = document.createElement("a");
130
- a.href = `#/run/${encodeURIComponent(run.workerRunId)}`;
130
+ a.href = inspectPathToCanonicalHref(
131
+ `/run/${encodeURIComponent(run.workerRunId)}`,
132
+ );
131
133
  a.textContent = run.workerRunId;
132
134
  a.addEventListener("click", (e) => {
133
135
  e.preventDefault();
@@ -2,7 +2,7 @@
2
2
  import { UI_TEXT } from "./constants.js";
3
3
  import { clearNode, el } from "./dom.js";
4
4
  import { formatAgo } from "./format.js";
5
- import { navigate } from "./router.js";
5
+ import { inspectPathToCanonicalHref, navigate } from "./router.js";
6
6
  import { buildObjectRelations, renderObjectRelationBar } from "./relations.js";
7
7
  import { closeDagInspector } from "./views/dag-inspector.js";
8
8
 
@@ -23,7 +23,7 @@ export function setBreadcrumb(parts) {
23
23
  if (i > 0) nav.appendChild(document.createTextNode(" / "));
24
24
  if (part.href) {
25
25
  const a = document.createElement("a");
26
- a.href = part.href;
26
+ a.href = inspectPathToCanonicalHref(part.href);
27
27
  a.textContent = part.label;
28
28
  a.addEventListener("click", (e) => {
29
29
  e.preventDefault();
@@ -105,6 +105,11 @@ export const uiState = {
105
105
  dagGraphViewportState: null,
106
106
  dagTrajectoryViewportState: null,
107
107
  dagTimelineViewportState: null,
108
+ /**
109
+ * Explicit「执行记录」auto-scroll preference for the selected node.
110
+ * Defaults on for every newly selected node and survives polling/tab switches.
111
+ */
112
+ dagTimelineAutoScrollEnabled: true,
108
113
  dagNodeOutputViewportState: null,
109
114
  dagNodeInputViewportState: null,
110
115
  /** Spec-evidence inspector content scroll (single active region snapshot). */
@@ -1354,6 +1354,57 @@ body.is-resizing-dag-graph {
1354
1354
  padding: var(--space-4);
1355
1355
  overflow: auto;
1356
1356
  overscroll-behavior: contain;
1357
+ container-type: inline-size;
1358
+ }
1359
+ .dag-inspector-content.is-readable-page {
1360
+ display: flex;
1361
+ flex-direction: column;
1362
+ gap: 14px;
1363
+ background: color-mix(in srgb, var(--canvas-soft) 72%, var(--surface));
1364
+ }
1365
+ .inspector-page-lead {
1366
+ position: relative;
1367
+ flex: 0 0 auto;
1368
+ min-width: 0;
1369
+ padding: 13px 15px 14px 20px;
1370
+ border: 1px solid var(--hairline);
1371
+ border-radius: 12px;
1372
+ background: var(--surface);
1373
+ box-shadow: 0 4px 14px rgb(38 37 30 / 4%);
1374
+ overflow: hidden;
1375
+ }
1376
+ .inspector-page-lead::before {
1377
+ position: absolute;
1378
+ top: 0;
1379
+ bottom: 0;
1380
+ left: 0;
1381
+ width: 4px;
1382
+ background: var(--orange);
1383
+ content: "";
1384
+ }
1385
+ .inspector-page-lead h4,
1386
+ .inspector-page-lead p {
1387
+ margin: 0;
1388
+ }
1389
+ .inspector-page-lead h4 {
1390
+ margin-top: 3px;
1391
+ color: var(--ink);
1392
+ font-size: 16px;
1393
+ line-height: 1.35;
1394
+ }
1395
+ .inspector-page-lead p {
1396
+ margin-top: 5px;
1397
+ max-width: 68ch;
1398
+ color: var(--body);
1399
+ font-size: 12px;
1400
+ line-height: 1.55;
1401
+ }
1402
+ .inspector-page-eyebrow {
1403
+ display: block;
1404
+ color: var(--orange-active);
1405
+ font-size: 9px;
1406
+ font-weight: 800;
1407
+ letter-spacing: 0.12em;
1357
1408
  }
1358
1409
  .dag-inspector-attempt-bar {
1359
1410
  position: sticky;
@@ -1968,6 +2019,101 @@ body.is-resizing-dag-graph {
1968
2019
  gap: 8px;
1969
2020
  margin-bottom: var(--space-2);
1970
2021
  }
2022
+ .process-timeline-autoscroll-dock {
2023
+ position: sticky;
2024
+ top: calc(100% - 42px);
2025
+ z-index: 4;
2026
+ display: flex;
2027
+ justify-content: flex-end;
2028
+ height: 0;
2029
+ margin: 0 2px;
2030
+ pointer-events: none;
2031
+ }
2032
+ .process-timeline-autoscroll {
2033
+ position: relative;
2034
+ pointer-events: auto;
2035
+ display: inline-flex;
2036
+ align-items: center;
2037
+ justify-content: center;
2038
+ gap: 7px;
2039
+ width: 36px;
2040
+ height: 36px;
2041
+ padding: 0;
2042
+ border: 1px solid var(--hairline-strong);
2043
+ border-radius: 50%;
2044
+ background: color-mix(in srgb, var(--surface) 94%, var(--canvas));
2045
+ color: var(--body);
2046
+ box-shadow: 0 8px 24px rgb(38 37 30 / 14%);
2047
+ font-size: 14px;
2048
+ cursor: pointer;
2049
+ backdrop-filter: blur(10px);
2050
+ }
2051
+ .process-timeline-autoscroll::after {
2052
+ position: absolute;
2053
+ right: 0;
2054
+ bottom: calc(100% + 8px);
2055
+ padding: 6px 8px;
2056
+ border: 1px solid var(--hairline-strong);
2057
+ border-radius: var(--radius-sm);
2058
+ background: var(--ink);
2059
+ color: #fff;
2060
+ box-shadow: 0 6px 16px rgb(38 37 30 / 14%);
2061
+ content: attr(data-tooltip);
2062
+ font-size: 11px;
2063
+ font-weight: 650;
2064
+ line-height: 1;
2065
+ white-space: nowrap;
2066
+ opacity: 0;
2067
+ transform: translateY(3px);
2068
+ pointer-events: none;
2069
+ transition: opacity 120ms ease, transform 120ms ease;
2070
+ }
2071
+ .process-timeline-autoscroll:hover::after,
2072
+ .process-timeline-autoscroll:focus-visible::after {
2073
+ opacity: 1;
2074
+ transform: translateY(0);
2075
+ }
2076
+ .process-timeline-autoscroll:hover,
2077
+ .process-timeline-autoscroll:focus-visible {
2078
+ border-color: var(--orange);
2079
+ color: var(--orange-active);
2080
+ outline: none;
2081
+ box-shadow: 0 8px 24px rgb(38 37 30 / 16%), 0 0 0 3px var(--orange-soft);
2082
+ }
2083
+ .process-timeline-autoscroll.is-active {
2084
+ border-color: var(--ink);
2085
+ background: var(--ink);
2086
+ color: #fff;
2087
+ }
2088
+ .process-timeline-autoscroll.is-active:hover,
2089
+ .process-timeline-autoscroll.is-active:focus-visible {
2090
+ border-color: var(--orange);
2091
+ background: var(--ink);
2092
+ color: #fff;
2093
+ }
2094
+ .process-timeline-autoscroll-signal {
2095
+ width: 5px;
2096
+ height: 5px;
2097
+ border-radius: 50%;
2098
+ background: var(--muted-soft);
2099
+ }
2100
+ .process-timeline-autoscroll.is-active .process-timeline-autoscroll-signal {
2101
+ background: var(--orange);
2102
+ box-shadow: 0 0 0 4px rgb(245 78 0 / 16%);
2103
+ animation: process-timeline-live-pulse 1.8s ease-out infinite;
2104
+ }
2105
+ @keyframes process-timeline-live-pulse {
2106
+ 0%, 55%, 100% { box-shadow: 0 0 0 4px rgb(245 78 0 / 16%); }
2107
+ 75% { box-shadow: 0 0 0 7px rgb(245 78 0 / 0%); }
2108
+ }
2109
+ @media (prefers-reduced-motion: reduce) {
2110
+ .process-timeline-autoscroll.is-active .process-timeline-autoscroll-signal {
2111
+ animation: none;
2112
+ }
2113
+ .process-timeline-autoscroll::after {
2114
+ transition: none;
2115
+ }
2116
+ }
1971
2117
  .process-timeline-filter-group {
1972
2118
  display: inline-flex;
1973
2119
  flex-wrap: wrap;
@@ -2248,6 +2394,10 @@ body.is-resizing-dag-graph {
2248
2394
  }
2249
2395
  .node-input-semantics {
2250
2396
  margin: 0;
2397
+ padding: 9px 11px;
2398
+ border: 1px dashed var(--hairline-strong);
2399
+ border-radius: 9px;
2400
+ background: color-mix(in srgb, var(--canvas-soft) 74%, var(--surface));
2251
2401
  font-size: 12px;
2252
2402
  font-weight: 600;
2253
2403
  color: var(--muted);
@@ -2267,6 +2417,31 @@ body.is-resizing-dag-graph {
2267
2417
  font-size: 12px;
2268
2418
  font-weight: 600;
2269
2419
  }
2420
+ .dag-inspector-content.is-readable-page .node-input-section,
2421
+ .dag-inspector-content.is-readable-page .spec-evidence-section,
2422
+ .dag-inspector-content.is-readable-page
2423
+ .node-transparency-root
2424
+ > .node-input-summary {
2425
+ padding: 14px 15px;
2426
+ border: 1px solid var(--hairline);
2427
+ border-radius: 12px;
2428
+ background: var(--surface);
2429
+ box-shadow: 0 3px 12px rgb(38 37 30 / 3%);
2430
+ }
2431
+ .dag-inspector-content.is-readable-page .node-input-section,
2432
+ .dag-inspector-content.is-readable-page .spec-evidence-section {
2433
+ padding-bottom: 14px;
2434
+ }
2435
+ .dag-inspector-content.is-readable-page
2436
+ .spec-evidence-section
2437
+ + .spec-evidence-section {
2438
+ margin-top: 0;
2439
+ }
2440
+ .dag-inspector-content.is-readable-page .node-input-section h4,
2441
+ .dag-inspector-content.is-readable-page .spec-evidence-section h4 {
2442
+ margin-bottom: 10px;
2443
+ font-size: 13px;
2444
+ }
2270
2445
  .node-input-summary {
2271
2446
  display: grid;
2272
2447
  grid-template-columns: max-content 1fr;
@@ -2279,6 +2454,35 @@ body.is-resizing-dag-graph {
2279
2454
  color: var(--muted);
2280
2455
  font-weight: 600;
2281
2456
  }
2457
+ .dag-inspector-content.is-readable-page .node-input-summary dt[title] {
2458
+ cursor: help;
2459
+ text-decoration: underline dotted color-mix(in srgb, var(--muted) 48%, transparent);
2460
+ text-underline-offset: 3px;
2461
+ }
2462
+ .dag-inspector-content.is-readable-page .node-input-summary dt[title]::after {
2463
+ display: inline-grid;
2464
+ place-items: center;
2465
+ width: 13px;
2466
+ height: 13px;
2467
+ margin-left: 4px;
2468
+ border: 1px solid var(--hairline-strong);
2469
+ border-radius: 50%;
2470
+ color: var(--muted);
2471
+ font-size: 9px;
2472
+ font-weight: 800;
2473
+ line-height: 1;
2474
+ content: "?";
2475
+ }
2476
+ .dag-inspector-content.is-readable-page .node-input-summary > dt,
2477
+ .dag-inspector-content.is-readable-page .node-input-summary > dd {
2478
+ padding: 7px 0;
2479
+ border-bottom: 1px solid color-mix(in srgb, var(--hairline) 72%, transparent);
2480
+ }
2481
+ .dag-inspector-content.is-readable-page
2482
+ .node-input-summary
2483
+ > :nth-last-child(-n + 2) {
2484
+ border-bottom: 0;
2485
+ }
2282
2486
  .node-input-summary dd {
2283
2487
  margin: 0;
2284
2488
  color: var(--ink);
@@ -2347,6 +2551,33 @@ body.is-resizing-dag-graph {
2347
2551
  border-radius: var(--radius-md);
2348
2552
  background: var(--surface-2, #f3f1ec);
2349
2553
  }
2554
+
2555
+ @container (max-width: 520px) {
2556
+ .inspector-page-lead {
2557
+ padding: 12px 13px 13px 18px;
2558
+ }
2559
+ .inspector-page-lead h4 {
2560
+ font-size: 15px;
2561
+ }
2562
+ .dag-inspector-content.is-readable-page .node-input-section,
2563
+ .dag-inspector-content.is-readable-page .spec-evidence-section,
2564
+ .dag-inspector-content.is-readable-page
2565
+ .node-transparency-root
2566
+ > .node-input-summary {
2567
+ padding: 12px;
2568
+ }
2569
+ .dag-inspector-content.is-readable-page .node-input-summary {
2570
+ grid-template-columns: minmax(0, 1fr);
2571
+ gap: 0;
2572
+ }
2573
+ .dag-inspector-content.is-readable-page .node-input-summary > dt {
2574
+ padding: 8px 0 2px;
2575
+ border-bottom: 0;
2576
+ }
2577
+ .dag-inspector-content.is-readable-page .node-input-summary > dd {
2578
+ padding: 0 0 8px;
2579
+ }
2580
+ }
2350
2581
  .node-artifact-card.is-consumed {
2351
2582
  border-left: 3px solid var(--blue, #2563eb);
2352
2583
  }
@@ -202,7 +202,7 @@ export function renderDagGraph(dag, dagRunId, existingWrap = null) {
202
202
  width: layout.width,
203
203
  height: layout.height,
204
204
  role: "img",
205
- "aria-label": `DAG 依赖图,共 ${nodes.length} 个节点`,
205
+ "aria-label": `执行步骤关系,共 ${nodes.length} 个步骤`,
206
206
  });
207
207
  const defs = svgEl("defs");
208
208
  const marker = svgEl("marker", {