@tea-agent/loop-agent 0.41.1 → 0.42.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +397 -5
- package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
- package/dist/adapters/context-transfer/pi-session.js +61 -0
- package/dist/application/dag/generate-task-dag.js +75 -19
- package/dist/application/dag/run-dag.js +41 -0
- package/dist/application/task-lifecycle/advance.js +24 -5
- package/dist/application/task-lifecycle/observe.js +171 -17
- package/dist/application/task-lifecycle/plan-transitions.js +42 -7
- package/dist/application/task-lifecycle/recommendations.js +13 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +19 -0
- package/dist/cli/program.js +29 -2
- package/dist/commands/client-recovery.js +3 -0
- package/dist/commands/dag-artifact.js +284 -0
- package/dist/commands/dag-context.js +184 -0
- package/dist/commands/dag-follow-up.js +138 -0
- package/dist/commands/dag-rerun-task.js +2 -0
- package/dist/commands/dag-rerun.js +206 -1
- package/dist/commands/init.js +27 -1
- package/dist/commands/task-advance.js +19 -0
- package/dist/executors/dag-pi-executor.js +4013 -86
- package/dist/executors/pi-executor.js +15 -4
- package/dist/executors/pi-read-budget-policy.js +239 -0
- package/dist/executors/pi-sdk-executor.js +3 -0
- package/dist/executors/shell-executor.js +978 -188
- package/dist/executors/shell-write-guard.js +7 -0
- package/dist/{worker → infrastructure}/console/app-data.js +4 -0
- package/dist/infrastructure/console/artifact-revision-store.js +430 -0
- package/dist/infrastructure/console/context-export-store.js +160 -0
- package/dist/infrastructure/console/dir-lock.js +132 -0
- package/dist/infrastructure/console/operation-store.js +417 -0
- package/dist/infrastructure/harness/artifact-store.js +10 -1
- package/dist/infrastructure/harness/atomic-write.js +12 -2
- package/dist/shared/context-transfer/artifact-revision.js +172 -0
- package/dist/shared/context-transfer.js +418 -0
- package/dist/shared/dag-failure-category.js +12 -0
- package/dist/shared/openspec-spec.js +70 -4
- package/dist/shared/operator/capabilities.js +21 -0
- package/dist/shared/operator/safe-run-summary.js +1 -0
- package/dist/shared/path-safety.js +93 -0
- package/dist/shared/preview.js +28 -4
- package/dist/task/config-types.js +107 -6
- package/dist/task/contract/adopt.js +4 -0
- package/dist/task/contract/import-revision.js +4 -0
- package/dist/task/contract/project.js +3 -0
- package/dist/task/contract/schema.js +2 -1
- package/dist/task/frontend-project-capability.js +203 -20
- package/dist/task/runtime.js +5 -2
- package/dist/task/source-prepare/build-draft.js +3 -3
- package/dist/task/source-prepare/fragment-inventory.js +64 -25
- package/dist/task/source-prepare/prepare.js +126 -21
- package/dist/task/source-prepare/semantic-intake.js +6 -2
- package/dist/task/source-references.js +22 -1
- package/dist/task/task-demand-routing.js +3 -0
- package/dist/worker/console/chat/chat-event-store.js +2 -2
- package/dist/worker/console/chat/model-resolver.js +7 -4
- package/dist/worker/console/chat/pi-runtime.js +86 -5
- package/dist/worker/console/chat/resource-preferences-store.js +1 -1
- package/dist/worker/console/chat/routes.js +136 -53
- package/dist/worker/console/chat/sdd-data-alignment.js +222 -0
- package/dist/worker/console/chat/session-catalog.js +2 -0
- package/dist/worker/console/chat/session-store.js +43 -1
- package/dist/worker/console/chat/shortcuts.js +18 -2
- package/dist/worker/console/chat/user-questions.js +1 -1
- package/dist/worker/console/console-update-runtime.js +1 -1
- package/dist/worker/console/context-transfer-diagnostics.js +198 -0
- package/dist/worker/console/dag-confirmation.js +1 -1
- package/dist/worker/console/dag-execution-receipt.js +1 -1
- package/dist/worker/console/doctor.js +1 -1
- package/dist/worker/console/draft-store.js +1 -1
- package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
- package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
- package/dist/worker/console/human-gate-token.js +1 -1
- package/dist/worker/console/index.js +6 -3
- package/dist/worker/console/interview/assessment.js +1 -1
- package/dist/worker/console/interview/session.js +1 -1
- package/dist/worker/console/operation-runner.js +45 -4
- package/dist/worker/console/operation-sse.js +1 -1
- package/dist/worker/console/operation-wait.js +1 -1
- package/dist/worker/console/operator-actions.js +273 -10
- package/dist/worker/console/operator-surface-health.js +1 -1
- package/dist/worker/console/operator-user-error.js +169 -0
- package/dist/worker/console/pi-plugins.js +57 -0
- package/dist/worker/console/pi-readiness.js +3 -2
- package/dist/worker/console/routes.js +637 -8
- package/dist/worker/console/security.js +35 -0
- package/dist/worker/console/server.js +29 -4
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-D7oU983t.js → abnfDiagram-N423BO3Z-CcS17TBr.js} +1 -1
- package/dist/worker/console/static/assets/{arc-BrKSRdFS.js → arc-COptKq2S.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CiXV7L56.js → architectureDiagram-T3A2C74G-h4LKMHjP.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D_Hs_gIG.js → blockDiagram-VBNYF7ZC-COA1MOH0.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DbM-Lqqh.js → c4Diagram-5PPSVZJV-DJUf0QPm.js} +1 -1
- package/dist/worker/console/static/assets/channel-DdBCaOJ6.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D1M8uqJw.js → chunk-2GRJ4B5K-mtWfKrUX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-4D3RFHT6.js → chunk-2Q5K7J3B-B8pXsxDQ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CdwpY_n9.js → chunk-5RXB4S5H-ipKzByl1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BLeLZ9PG.js → chunk-5VM5RSS4-DYi3Ald_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-CeRNEMvc.js → chunk-6Q2QTUOP-DQtGYoty.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CjkHP8Vy.js → chunk-GF5L2VYU-BU0qS2YV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-B54ZUQY-.js → chunk-JWPE2WC7-DVH9dIGE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-4bKaMVmx.js → chunk-KBJHAD2P-Dt60SmgM.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-Cyjfznu_.js → chunk-RYQCIY6F-BoaUGuEY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CDN-zGFV.js → chunk-XXDRQBXY-_WHFDTp2.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DZFra1GO.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DZFra1GO.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-HxJmz411.js → cose-bilkent-JH36ORCC-BxkbTIRd.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DtSt5K2w.js → cynefin-VYW2F7L2-Bf2UVnoG.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-VtkSpRmG.js → cynefinDiagram-MW4NZA55-Bo23q1J_.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-Bj4DT4du.js → dagre-VZM6K2ZE-Dd_UU49i.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Bpuk6BmP.js → diagram-7IWD3JNH-ebUa1a9y.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BHYGv_yO.js → diagram-B4RE2ZJO-BucthU8r.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DEx3WwnT.js → diagram-LBJQPF4R-BgqNpAkm.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Cj0dS5e8.js → diagram-Q27KOJAE-DC4q5NGa.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-B97h8l21.js → diagram-UB23O5K3-CBqCaMeb.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DMSFAhBd.js → ebnfDiagram-BXEA7PRR-CGtnbQ3-.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DhVOCbt6.js → erDiagram-JOGREHBK-CG3LUao5.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-GlakITWL.js → flowDiagram-UKHOOZJN-D2ZVgoFS.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-VxPpu9eQ.js → ganttDiagram-PKOTCBZU-DoYFZiKt.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bs_e5DRT.js → gitGraphDiagram-DS77QQ5N-CKoP1s6j.js} +1 -1
- package/dist/worker/console/static/assets/index-CAZ2fC_X.css +1 -0
- package/dist/worker/console/static/assets/index-vbTcFnFs.js +449 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BXYuU4Uw.js → infoDiagram-6WML65LV-Duofv8p2.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-C34erCbU.js → ishikawaDiagram-WSZJBQD7-D2nlCkA1.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DZCAiOU3.js → journeyDiagram-NVQOT4AX-Dd4IHdus.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C9gaTdUm.js → kanban-definition-27J2QSJJ-Bi20AOdt.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CvI0Z17U.js → linear-D59YJ9kB.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DMMSIx7j.js → mermaid.core-Bl13LpNa.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BKKP0EO6.js → mindmap-definition-FAOFIHXS-C6DLP5eY.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-C3LiFbl5.js → pegDiagram-VL7TDLO6-BjO4cy64.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-Bb3Om2Dz.js → pieDiagram-7S7Q4E2Y-D7i2qZTG.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DNthMjzc.js → quadrantDiagram-CIZ2JOQS-Dx8o_h0y.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-miFsr4Tv.js → railroadDiagram-AXF67PYL-B55orI_t.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-yXUncmn6.js → requirementDiagram-LRYGKXZP-zWaehp6f.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DLeWKLak.js → sankeyDiagram-W5VNT64P-CcA-pjvD.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CI3he1R3.js → sequenceDiagram-SI44F4Z6-BOFbzNHI.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B7jfDkS5.js → sizeCapture-X5ZJPWSS-BjAejah1.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BmrZod7J.js → stateDiagram-OKZ733FA-DXYwxJwZ.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Clg3V9t1.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CDOlHVSY.js → swimlanes-SLNWSIFB-OYiOch8n.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DX1dxAAW.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cz-XX1gy.js → timeline-definition-Z64GVDOM-cZfH3nmU.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-caV4cI8C.js → vennDiagram-T6HMQDX7-BDE7b3E1.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-dImPlnIO.js → wardleyDiagram-T6FBY63Y-kyyGy9WJ.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CtRYVJcn.js → xychartDiagram-ELKLHX3M-CJj6VTog.js} +1 -1
- package/dist/worker/console/static/index.html +7 -2
- package/dist/worker/console/static-src/active-run-badge.js +17 -0
- package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -5
- package/dist/worker/console/static-src/operator-chat/input-history.js +8 -6
- package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +258 -23
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +112 -4
- package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -4
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
- package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
- package/dist/worker/console/static-src/shell/console-update-reload.js +52 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +11 -0
- package/dist/worker/console/workspace-context.js +142 -2
- package/dist/worker/console/workspace-registry.js +2 -2
- package/dist/worker/continuation/worker-continuation.js +278 -0
- package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
- package/dist/worker/observe/health.js +1 -1
- package/dist/worker/observe/node-transparency.js +572 -0
- package/dist/worker/observe/routes.js +55 -1
- package/dist/worker/observe/static/api.js +69 -5
- package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
- package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
- package/dist/worker/observe/static/dag-helpers.js +4 -2
- package/dist/worker/observe/static/dag-node-purpose.js +5 -0
- package/dist/worker/observe/static/inspect-workspace.js +23 -0
- package/dist/worker/observe/static/kpi.js +2 -2
- package/dist/worker/observe/static/operator-chrome.d.ts +10 -2
- package/dist/worker/observe/static/operator-chrome.js +37 -23
- package/dist/worker/observe/static/relations.js +2 -2
- package/dist/worker/observe/static/router.d.ts +12 -1
- package/dist/worker/observe/static/router.js +48 -6
- package/dist/worker/observe/static/run-processing.js +4 -2
- package/dist/worker/observe/static/shell-chrome.js +2 -2
- package/dist/worker/observe/static/state.js +8 -1
- package/dist/worker/observe/static/styles.css +1092 -86
- package/dist/worker/observe/static/views/dag-inspector.js +1228 -64
- package/dist/worker/observe/static/views/dag.js +10 -2
- package/dist/worker/observe/static/views/dags.js +3 -1
- package/dist/worker/observe/static/views/dashboard.js +14 -6
- package/dist/worker/observe/static/views/pool.js +7 -2
- package/dist/worker/observe/static/views/run.js +12 -3
- package/dist/worker/observe/static/views/session-timeline.js +142 -18
- package/dist/worker/observe/static/views/task.js +7 -2
- package/dist/worker/outcomes/adapters.js +19 -0
- package/dist/worker/outcomes/types.js +1 -0
- package/dist/worker/pool/attempt-lease.js +97 -66
- package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
- package/dist/worker/pool/reconcile.js +46 -1
- package/dist/worker/pool/run-store.js +2 -0
- package/dist/worker/pool/state-projection.js +2 -0
- package/dist/worker/task-spec/workflow-routing.js +8 -3
- package/dist/workflows/dag/artifact-bindings.js +149 -0
- package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +215 -28
- package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
- package/dist/workflows/dag/backend-test-plan-protocol.js +106 -0
- package/dist/workflows/dag/backend-test-scenario-param.js +172 -25
- package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
- package/dist/workflows/dag/backend-test-writer-completeness.js +104 -12
- package/dist/workflows/dag/budget-enforcement.js +10 -0
- package/dist/workflows/dag/context-receipt.js +305 -0
- package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
- package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
- package/dist/workflows/dag/context-transfer/renderers.js +93 -0
- package/dist/workflows/dag/contract-validator-registrations.js +1 -2
- package/dist/workflows/dag/dag-retry-schema.js +138 -0
- package/dist/workflows/dag/frontend-closeout.js +221 -0
- package/dist/workflows/dag/frontend-design-policy.js +400 -0
- package/dist/workflows/dag/frontend-human-decision.js +182 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +1237 -192
- package/dist/workflows/dag/frontend-plan-render.js +2 -1
- package/dist/workflows/dag/frontend-prewrite-gate.js +256 -350
- package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
- package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
- package/dist/workflows/dag/frontend-recovery-controller.js +226 -0
- package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +21 -10
- package/dist/workflows/dag/frontend-recovery-run.js +166 -34
- package/dist/workflows/dag/frontend-repair.js +1 -432
- package/dist/workflows/dag/frontend-review-context.js +261 -15
- package/dist/workflows/dag/frontend-review-findings.js +270 -0
- package/dist/workflows/dag/frontend-shadow-dual-write.js +941 -0
- package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
- package/dist/workflows/dag/frontend-shape-facts.js +419 -0
- package/dist/workflows/dag/frontend-shape.js +435 -0
- package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
- package/dist/workflows/dag/frontend-split-application-service.js +203 -0
- package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
- package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
- package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
- package/dist/workflows/dag/frontend-verification-trace.js +252 -25
- package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
- package/dist/workflows/dag/frontend-writer-admission.js +319 -0
- package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
- package/dist/workflows/dag/frontend-writer-status.js +256 -0
- package/dist/workflows/dag/init-hybrid.js +1174 -562
- package/dist/workflows/dag/interrupt-request.js +7 -0
- package/dist/workflows/dag/node-execution.js +940 -31
- package/dist/workflows/dag/path-safety.js +1 -0
- package/dist/workflows/dag/prompt.js +99 -7
- package/dist/workflows/dag/recovery-lease.js +170 -0
- package/dist/workflows/dag/report.js +37 -1
- package/dist/workflows/dag/rerun-feedback.js +315 -1
- package/dist/workflows/dag/rerun-plan.js +568 -3
- package/dist/workflows/dag/rerun-run.js +642 -18
- package/dist/workflows/dag/rerun-task.js +251 -13
- package/dist/workflows/dag/retry-policy.js +219 -104
- package/dist/workflows/dag/runner.js +596 -121
- package/dist/workflows/dag/scheduler.js +133 -20
- package/dist/workflows/dag/skill-snapshot.js +17 -0
- package/dist/workflows/dag/types.js +426 -22
- package/dist/workflows/dag/validate.js +28 -12
- package/docs/architecture/runtime-boundaries.md +6 -6
- package/docs/architecture/worker-and-feature.md +1 -1
- package/docs/examples/README.md +5 -0
- package/docs/init-surface.manifest.json +30 -12
- package/docs/skills/vetted-skill-registry.md +4 -2
- package/docs/templates/README.md +2 -0
- package/docs/templates/agent-dag-report.schema.json +8 -2
- package/docs/templates/agent-dag.schema.json +33 -1
- package/docs/templates/backend-test-dag.json +23 -20
- package/docs/templates/frontend-implementation-contract.schema.json +4 -1
- package/docs/templates/frontend-implementation-dag.json +89 -0
- package/docs/templates/product-line/task.yaml +1 -1
- package/docs/templates/spec-registry.schema.json +45 -0
- package/harness.json +1 -1
- package/package.json +6 -3
- package/skills/frontend-bounded-implement/SKILL.md +15 -14
- package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
- package/skills/frontend-contract/SKILL.md +23 -0
- package/skills/frontend-contract/references/contract-protocol.md +34 -0
- package/skills/frontend-design-review/SKILL.md +22 -41
- package/skills/frontend-plan/SKILL.md +26 -0
- package/skills/frontend-plan/references/decision-contract.md +37 -0
- package/skills/frontend-plan/references/design-decisions.md +17 -0
- package/skills/frontend-review/SKILL.md +20 -15
- package/skills/frontend-review/references/review-findings.md +6 -7
- package/skills/frontend-scout/SKILL.md +25 -0
- package/skills/frontend-scout/references/design-evidence.md +16 -0
- package/skills/frontend-scout/references/scout-evidence.md +23 -0
- package/skills/frontend-verification/SKILL.md +1 -1
- package/skills/loop-agent/references/command-reference.md +7 -0
- package/skills/loop-agent/references/hybrid-dag.md +2 -2
- package/dist/worker/console/operation-store.js +0 -169
- package/dist/worker/console/static/assets/channel-D1xajGpe.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BmuGTfRr.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BmuGTfRr.js +0 -1
- package/dist/worker/console/static/assets/index-BLzcAykx.js +0 -451
- package/dist/worker/console/static/assets/index-Cs9JUSPs.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-D9ykKEWP.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BvPOXALT.js +0 -8
- package/skills/frontend-implementation/SKILL.md +0 -52
- package/skills/frontend-implementation/references/code-standards.md +0 -33
- package/skills/frontend-implementation/references/design-spec.md +0 -56
- package/skills/frontend-implementation/references/node-contracts.md +0 -31
- /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
|
@@ -84,6 +84,29 @@ export async function fetchDagNodeInput(runId, nodeId) {
|
|
|
84
84
|
return fetchJsonResult(url);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
export async function fetchDagNodeContext(runId, nodeId, attempt) {
|
|
88
|
+
const params = new URLSearchParams();
|
|
89
|
+
if (attempt != null) params.set("attempt", String(attempt));
|
|
90
|
+
const query = params.toString();
|
|
91
|
+
const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/context${query ? `?${query}` : ""}`;
|
|
92
|
+
return fetchJsonResult(url);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function fetchDagNodeArtifacts(runId, nodeId) {
|
|
96
|
+
const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/artifacts`;
|
|
97
|
+
return fetchJsonResult(url);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function fetchDagNodeArtifactPreview(runId, nodeId, artifactId) {
|
|
101
|
+
const params = new URLSearchParams({ artifactId: String(artifactId ?? "") });
|
|
102
|
+
const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/artifacts/preview?${params.toString()}`;
|
|
103
|
+
return fetchJsonResult(url);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function fetchDagRunLineage(runId) {
|
|
107
|
+
return fetchJsonResult(`/api/dag-runs/${encodeURIComponent(runId)}/lineage`);
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
export async function fetchDagNodeProcess(runId, nodeId, key) {
|
|
88
111
|
const params = new URLSearchParams();
|
|
89
112
|
if (key) params.set("key", String(key));
|
|
@@ -123,18 +146,28 @@ export function artifactUrl(artifactPath) {
|
|
|
123
146
|
* Experimental (prompt-override rerun only): POST one allowlisted operator
|
|
124
147
|
* action through the Console mutation gate using the SCOPED inspect token
|
|
125
148
|
* (window.__INSPECT_MUTATION_TOKEN__). The server injects it into /inspect
|
|
126
|
-
* HTML
|
|
127
|
-
*
|
|
149
|
+
* HTML and into the Console SPA (which hosts the /inspect workspace) by
|
|
150
|
+
* default; HARNESS_DAG_RERUN_PROMPT_OVERRIDE=0|false|off disables injection.
|
|
151
|
+
* The token only authorizes dagRerunPlan / dagRerun — never general
|
|
128
152
|
* Console mutations.
|
|
129
153
|
* Absent token → the call is not attempted.
|
|
130
154
|
*/
|
|
131
|
-
export async function postOperatorAction(
|
|
155
|
+
export async function postOperatorAction(
|
|
156
|
+
action,
|
|
157
|
+
actionParams = {},
|
|
158
|
+
clientRequestId,
|
|
159
|
+
) {
|
|
132
160
|
const token = globalThis.__INSPECT_MUTATION_TOKEN__;
|
|
133
161
|
if (!token) {
|
|
134
162
|
return {
|
|
135
163
|
ok: false,
|
|
136
164
|
status: 0,
|
|
137
|
-
body: {
|
|
165
|
+
body: {
|
|
166
|
+
error: {
|
|
167
|
+
code: "PROMPT_OVERRIDE_DISABLED",
|
|
168
|
+
message: "提示词重启未启用(服务端未注入确认 token)",
|
|
169
|
+
},
|
|
170
|
+
},
|
|
138
171
|
};
|
|
139
172
|
}
|
|
140
173
|
const workspaceId = workspaceScope();
|
|
@@ -158,7 +191,12 @@ export async function postOperatorAction(action, actionParams = {}) {
|
|
|
158
191
|
"Content-Type": "application/json",
|
|
159
192
|
"x-loop-console-confirmation": token,
|
|
160
193
|
},
|
|
161
|
-
body: JSON.stringify({
|
|
194
|
+
body: JSON.stringify({
|
|
195
|
+
workspaceId,
|
|
196
|
+
action,
|
|
197
|
+
actionParams,
|
|
198
|
+
clientRequestId,
|
|
199
|
+
}),
|
|
162
200
|
});
|
|
163
201
|
let body = null;
|
|
164
202
|
try {
|
|
@@ -172,6 +210,32 @@ export async function postOperatorAction(action, actionParams = {}) {
|
|
|
172
210
|
}
|
|
173
211
|
}
|
|
174
212
|
|
|
213
|
+
export async function downloadContextExport(downloadUrl) {
|
|
214
|
+
const token = globalThis.__INSPECT_MUTATION_TOKEN__;
|
|
215
|
+
if (!token) throw new Error("导出下载能力未启用");
|
|
216
|
+
const res = await fetchWithWorkspaceScope(downloadUrl, {
|
|
217
|
+
method: "GET",
|
|
218
|
+
credentials: "same-origin",
|
|
219
|
+
headers: { "x-loop-console-confirmation": token },
|
|
220
|
+
});
|
|
221
|
+
if (!res.ok) {
|
|
222
|
+
let message = `下载失败:HTTP ${res.status}`;
|
|
223
|
+
try {
|
|
224
|
+
const body = await res.json();
|
|
225
|
+
message = body?.error?.message ?? message;
|
|
226
|
+
} catch {
|
|
227
|
+
// Preserve bounded local fallback copy.
|
|
228
|
+
}
|
|
229
|
+
throw new Error(message);
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
blob: await res.blob(),
|
|
233
|
+
filename:
|
|
234
|
+
/filename="([^"]+)"/.exec(res.headers.get("content-disposition") ?? "")?.[1] ??
|
|
235
|
+
"context-bundle.zip",
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
175
239
|
/** Poll a Console operation snapshot (read-only GET). */
|
|
176
240
|
export async function fetchOperatorOperation(operationId) {
|
|
177
241
|
try {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function contextTransferReasonLabel(
|
|
2
|
+
reasonCode: string | null | undefined,
|
|
3
|
+
): string | null;
|
|
4
|
+
export function formatContextTransferReasonList(
|
|
5
|
+
reasonCodes: readonly (string | null | undefined)[] | null | undefined,
|
|
6
|
+
): string | null;
|
|
7
|
+
export function describeTransferError(
|
|
8
|
+
message: string | null | undefined,
|
|
9
|
+
): string | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context transfer / artifact revision 稳定 reason code 的操作者文案映射
|
|
3
|
+
* (Observe UI,exec-plan 2026-08-25-console-node-context-artifact-rerun W1.5)。
|
|
4
|
+
*
|
|
5
|
+
* 表驱动纯函数:已知 code 映射为中文业务术语,未知 code fail-closed 返回
|
|
6
|
+
* null(调用方保留原始 token 展示,不猜测、不解释为成功)。
|
|
7
|
+
* 冻结 code 清单见 src/shared/context-transfer.ts CONTEXT_TRANSFER_REASON_CODES;
|
|
8
|
+
* 附加条目为 Console operation / rerun 执行面会透传到 Inspector 的错误码。
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const CONTEXT_TRANSFER_REASON_LABELS = {
|
|
12
|
+
CONTEXT_RECEIPT_MISSING: "该节点没有执行时上下文回执",
|
|
13
|
+
CONTEXT_COMPONENT_UNAVAILABLE: "部分上下文组件当前不可用",
|
|
14
|
+
CONTEXT_BUNDLE_INEXACT: "导出等级为近似恢复,不是精确重放",
|
|
15
|
+
CONTEXT_BUNDLE_TOO_LARGE: "导出内容超出体积上限",
|
|
16
|
+
RAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED: "原文导出需要显式确认敏感数据风险",
|
|
17
|
+
SECRET_SCAN_CONFIRMATION_REQUIRED: "候选文件疑似包含凭据,需确认后才能继续",
|
|
18
|
+
ARTIFACT_BINDING_UNAVAILABLE: "缺少结构化产物关系",
|
|
19
|
+
ARTIFACT_NOT_REVISION_ELIGIBLE: "该产物不允许修订替换",
|
|
20
|
+
ARTIFACT_IDENTITY_AMBIGUOUS: "产物身份不唯一,无法安全定位",
|
|
21
|
+
ARTIFACT_REVISION_SCHEMA_INVALID: "候选文件不符合声明的数据结构",
|
|
22
|
+
ARTIFACT_REVISION_PATH_INVALID: "候选目标路径无效",
|
|
23
|
+
ARTIFACT_REVISION_EXPIRED: "修订候选已过期,需要重新上传",
|
|
24
|
+
ARTIFACT_REVISION_DRIFT: "候选文件与登记内容不一致",
|
|
25
|
+
ARTIFACT_REVISION_QUOTA_EXCEEDED: "修订暂存区配额已满,请先清理或等待过期回收",
|
|
26
|
+
ARTIFACT_CONSUMER_UNKNOWN: "无法确定受影响的下游节点",
|
|
27
|
+
ARTIFACT_IMPACT_UNSAFE: "影响范围包含不能自动重跑的节点",
|
|
28
|
+
RERUN_PLAN_DRIFT: "继续运行计划与当前事实发生漂移",
|
|
29
|
+
WORKER_MANAGED_CONTINUATION_UNSUPPORTED: "由 Worker 托管的运行暂不支持派生继续",
|
|
30
|
+
WORKER_CONTINUATION_AUTHORITY_MISMATCH: "Worker 派生运行的归属事实不一致",
|
|
31
|
+
WORKER_CONTINUATION_NEEDS_RECONCILE: "Worker 派生运行已存在,需要先恢复核对",
|
|
32
|
+
WORKER_CONTINUATION_LEASE_CONFLICT: "该 Worker Task 已有运行占用",
|
|
33
|
+
INELIGIBLE: "当前不满足继续运行的条件",
|
|
34
|
+
PARENT_IMMUTABILITY_VIOLATION: "父运行事实发生变化,已阻止派生",
|
|
35
|
+
PARENT_LIFECYCLE: "父运行状态不允许派生继续",
|
|
36
|
+
PLAN_DRIFT: "计划与执行前校验不一致",
|
|
37
|
+
REQUEST_ID_REUSE_CONFLICT: "相同请求 ID 已被其他操作占用",
|
|
38
|
+
OPERATION_NEEDS_RECONCILE: "操作记录需要先恢复核对",
|
|
39
|
+
CONTEXT_EXPORT_FAILED: "上下文导出失败",
|
|
40
|
+
CONTEXT_EXPORT_UNAVAILABLE: "导出内容不存在或已过期",
|
|
41
|
+
LEASE_HELD: "资源正被其他操作占用",
|
|
42
|
+
NOT_FOUND: "目标不存在或已过期",
|
|
43
|
+
// Console operation 面会透传的通用错误码。
|
|
44
|
+
INVALID_INPUT: "请求参数不完整或不合法",
|
|
45
|
+
INTERNAL_ERROR: "内部错误,请重试;若持续失败请查看操作诊断",
|
|
46
|
+
OPERATION_NOT_FOUND: "操作不存在或已被清理",
|
|
47
|
+
OPERATION_NOT_TERMINAL: "操作尚未结束,请稍后查询",
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// 非 reason-code 形态、但会透传到检查器状态行的运行时错误 → 中文语义。
|
|
51
|
+
const RUNTIME_ERROR_PATTERNS = [
|
|
52
|
+
{
|
|
53
|
+
pattern: /controller identity changed|package fingerprint changed/i,
|
|
54
|
+
copy:
|
|
55
|
+
"控制器版本已变更:Console 启动后代码被重新构建。请重启 Console 进程加载当前构建后重试本操作。",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern:
|
|
59
|
+
/invalid (?:confirmation header |boot capability )?token|mutation requires (?:boot capability cookie|confirmation header token)/i,
|
|
60
|
+
copy:
|
|
61
|
+
"页面凭证已失效(Console 可能已重启,或页面是重启前的旧缓存)。请强制刷新页面(Cmd/Ctrl+Shift+R)后重试。",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
pattern: /context receipt missing/i,
|
|
65
|
+
copy: "该节点没有执行时上下文回执,无法生成交接包。",
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 已知 reason code → 中文业务术语;未知或缺失返回 null(调用方应原样展示
|
|
71
|
+
* 原始 token,保持诚实降级)。
|
|
72
|
+
*/
|
|
73
|
+
export function contextTransferReasonLabel(reasonCode) {
|
|
74
|
+
const key = String(reasonCode ?? "");
|
|
75
|
+
if (!key) return null;
|
|
76
|
+
return CONTEXT_TRANSFER_REASON_LABELS[key] ?? null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* reason code 列表 → 面向操作者的展示串:已知项输出「中文(CODE)」,
|
|
81
|
+
* 未知项原样保留;空输入返回 null 供调用方守卫。
|
|
82
|
+
*/
|
|
83
|
+
export function formatContextTransferReasonList(reasonCodes) {
|
|
84
|
+
const codes = (Array.isArray(reasonCodes) ? reasonCodes : [])
|
|
85
|
+
.map((code) => String(code ?? ""))
|
|
86
|
+
.filter((code) => code.length > 0);
|
|
87
|
+
if (codes.length === 0) return null;
|
|
88
|
+
return codes
|
|
89
|
+
.map((code) => {
|
|
90
|
+
const label = contextTransferReasonLabel(code);
|
|
91
|
+
return label ? `${label}(${code})` : code;
|
|
92
|
+
})
|
|
93
|
+
.join(";");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const REASON_CODE_SCAN_PATTERN = new RegExp(
|
|
97
|
+
`\\b(?:${Object.keys(CONTEXT_TRANSFER_REASON_LABELS).join("|")})\\b`,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 任意错误信息 → 面向操作者的语义化文案。扫描消息中嵌入的已知 reason
|
|
102
|
+
* code,命中时以中文业务术语开头并保留原码与原始信息;未命中已知 code
|
|
103
|
+
* 返回 null(调用方原样展示,不猜测成功、不编造解释)。
|
|
104
|
+
*/
|
|
105
|
+
export function describeTransferError(message) {
|
|
106
|
+
const raw = String(message ?? "").trim();
|
|
107
|
+
if (!raw) return null;
|
|
108
|
+
for (const entry of RUNTIME_ERROR_PATTERNS) {
|
|
109
|
+
if (entry.pattern.test(raw)) return entry.copy;
|
|
110
|
+
}
|
|
111
|
+
const match = REASON_CODE_SCAN_PATTERN.exec(raw);
|
|
112
|
+
if (!match) return null;
|
|
113
|
+
const label = contextTransferReasonLabel(match[0]);
|
|
114
|
+
if (!label) return null;
|
|
115
|
+
if (raw === match[0]) return `${label}(${match[0]})`;
|
|
116
|
+
const rest = raw.replace(match[0], "").replace(/^[\s::-]+/, "").trim();
|
|
117
|
+
return rest
|
|
118
|
+
? `${label}(${match[0]});原始信息:${rest}`
|
|
119
|
+
: `${label}(${match[0]})`;
|
|
120
|
+
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
formatDuration,
|
|
7
7
|
formatAgo,
|
|
8
8
|
} from "./format.js";
|
|
9
|
-
import { navigate } from "./router.js";
|
|
9
|
+
import { inspectPathToCanonicalHref, navigate } from "./router.js";
|
|
10
10
|
|
|
11
11
|
export function isNodeActive(status) {
|
|
12
12
|
if (!status) return false;
|
|
@@ -151,7 +151,9 @@ export function frontendLintSummary(frontendLint) {
|
|
|
151
151
|
card.appendChild(meta);
|
|
152
152
|
|
|
153
153
|
const link = el("a", "active-dag-link", UI_TEXT.enterDetail);
|
|
154
|
-
link.href =
|
|
154
|
+
link.href = inspectPathToCanonicalHref(
|
|
155
|
+
`/dag/${encodeURIComponent(dag.dagRunId)}`,
|
|
156
|
+
);
|
|
155
157
|
link.addEventListener("click", (e) => {
|
|
156
158
|
e.preventDefault();
|
|
157
159
|
navigate(`/dag/${encodeURIComponent(dag.dagRunId)}`);
|
|
@@ -39,20 +39,25 @@ const NODE_PURPOSE_BY_ID = {
|
|
|
39
39
|
"closeout-summary-pi": "把验证与交付事实写成简短交接摘要。",
|
|
40
40
|
|
|
41
41
|
"frontend-contract-pi": "把前端需求整理成可追踪契约:页面、状态、验收与边界。",
|
|
42
|
+
"frontend-contract-import-shell": "导入并固化前端实现契约,供后续设计、写入与验证节点使用。",
|
|
42
43
|
"frontend-scout-pi": "只读侦察前端结构、组件与接口用法,不改文件。",
|
|
43
44
|
"frontend-plan-pi": "选定实现与 Mock/API 策略,输出可执行的前端实现契约补丁。",
|
|
45
|
+
"frontend-design-policy-shell": "确定前端设计与 Mock/API 策略,冻结后续实现必须遵守的规则。",
|
|
44
46
|
"frontend-design-review-pi": "审查前端计划是否可写:通过则沿用原计划,否则要求修订。",
|
|
45
47
|
"frontend-plan-revision-pi": "按设计审查意见修订前端契约,不扩大范围。",
|
|
46
48
|
"frontend-final-design-review-pi": "复核修订后的前端计划,只有通过才能授权写入。",
|
|
47
49
|
"frontend-prewrite-gate-shell": "写入前门禁:核对契约、覆盖与 Mock 策略,通过才允许改前端。",
|
|
50
|
+
"frontend-writer-admission-shell": "核对契约、设计策略与 writeSet,满足准入条件后才允许 writer 写入。",
|
|
48
51
|
"frontend-lint-baseline-shell": "记录写入前的 lint 基线,供实现后对比,不阻断写入。",
|
|
49
52
|
"frontend-implement-pi": "按已批准契约改前端代码、状态与交互,留在 writeSet 内。",
|
|
50
53
|
"frontend-verify-assess-shell": "跑静态/行为/Mock 验证并评估能否有界修复。",
|
|
54
|
+
"frontend-verify-shell": "执行冻结的前端验证命令,产出可复查的通过或失败证据。",
|
|
51
55
|
"frontend-repair-pi": "只修评估为可修复的前端失败,不重开需求。",
|
|
52
56
|
"frontend-reverify-shell": "修复后用同一套冻结命令复验。",
|
|
53
57
|
"frontend-review-context-shell": "打包真实 diff 与有效验证证据,供审查节点使用。",
|
|
54
58
|
"frontend-review-pi": "对照契约审查前端实现与证据,给出通过或需修订。",
|
|
55
59
|
"frontend-review-gate-shell": "前端审查门禁:结论为通过才进入收口。",
|
|
60
|
+
"frontend-closeout-shell": "汇总实现、验证与遗留事项,形成确定性的前端收口事实。",
|
|
56
61
|
"frontend-closeout-pi": "汇总前端交付状态(含真实联调是否仍待完成)。",
|
|
57
62
|
"frontend-mock-assess-pi": "评估项目是否具备授权的 Mock 验证能力。",
|
|
58
63
|
"frontend-mock-contract-gate-shell": "Mock 契约门禁:策略与验证命令不一致则阻断。",
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
parseRoute,
|
|
11
11
|
setNavigateHandler,
|
|
12
12
|
inspectPathToCanonicalHref,
|
|
13
|
+
workspaceIdFromLocation,
|
|
13
14
|
} from "./router.js";
|
|
14
15
|
import {
|
|
15
16
|
isPageVisible,
|
|
@@ -93,6 +94,25 @@ function onInspectRootClick(event) {
|
|
|
93
94
|
navigateInspectPath(href);
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
/** Static Inspect markup still contains a few compatibility anchors. Normalize
|
|
98
|
+
* them on mount/route change so opening a link in a new tab preserves the
|
|
99
|
+
* workspace as reliably as an ordinary in-app click. Chat remains deliberately
|
|
100
|
+
* bare: its selected workspace is client state, not a hash contract. */
|
|
101
|
+
function scopeInspectShellLinks(root, workspaceId) {
|
|
102
|
+
if (!root?.querySelectorAll) return;
|
|
103
|
+
for (const anchor of root.querySelectorAll("a[href]")) {
|
|
104
|
+
const href = anchor.getAttribute("href");
|
|
105
|
+
if (!href || href.startsWith("/#/chat") || href.startsWith("#/chat")) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (!isInspectShellHref(href)) continue;
|
|
109
|
+
anchor.setAttribute(
|
|
110
|
+
"href",
|
|
111
|
+
inspectPathToCanonicalHref(href, workspaceId),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
96
116
|
function resumeInspectPolling() {
|
|
97
117
|
if (!isPageVisible() || !isWorkspaceActive()) return;
|
|
98
118
|
const r = lastInspectHash
|
|
@@ -187,6 +207,7 @@ export function startStandaloneInspect() {
|
|
|
187
207
|
if (typeof window === "undefined") return;
|
|
188
208
|
// Multi-workspace (AC-003): sync scope from the URL query before any fetch.
|
|
189
209
|
syncWorkspaceScopeFromLocation();
|
|
210
|
+
scopeInspectShellLinks(document, workspaceIdFromLocation());
|
|
190
211
|
window.addEventListener("hashchange", syncWorkspaceScopeFromLocation);
|
|
191
212
|
const chromeHost = document.getElementById("operator-chrome");
|
|
192
213
|
if (chromeHost) {
|
|
@@ -242,6 +263,7 @@ export function mountInspectWorkspace(root, options = {}) {
|
|
|
242
263
|
|
|
243
264
|
setNavigateHandler(onNavigate);
|
|
244
265
|
lastInspectHash = options.hash || (typeof location !== "undefined" ? location.hash : "");
|
|
266
|
+
scopeInspectShellLinks(root, workspaceIdFromHash(lastInspectHash));
|
|
245
267
|
setWorkspaceActive(options.active !== false);
|
|
246
268
|
|
|
247
269
|
const listenerAbort =
|
|
@@ -266,6 +288,7 @@ export function mountInspectWorkspace(root, options = {}) {
|
|
|
266
288
|
updateRoute(hashValue) {
|
|
267
289
|
if (host.destroyed) return;
|
|
268
290
|
lastInspectHash = hashValue || lastInspectHash;
|
|
291
|
+
scopeInspectShellLinks(root, workspaceIdFromHash(lastInspectHash));
|
|
269
292
|
if (!uiState.workspaceActive) return;
|
|
270
293
|
// AC-006: a hosted route update that carries a DIFFERENT workspaceId
|
|
271
294
|
// must not route under the old scope. Swap atomically:
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/** KPI cards, projection fault, artifact/inbox links. */
|
|
2
2
|
import { UI_TEXT } from "./constants.js";
|
|
3
3
|
import { el } from "./dom.js";
|
|
4
|
-
import { navigate } from "./router.js";
|
|
4
|
+
import { inspectPathToCanonicalHref, navigate } from "./router.js";
|
|
5
5
|
|
|
6
6
|
export function failuresInboxLink(count) {
|
|
7
7
|
const wrap = el("span", "kpi-value-with-link");
|
|
8
8
|
wrap.appendChild(el("span", "kpi-value-num", String(count)));
|
|
9
9
|
const a = el("a", "inbox-link", `${UI_TEXT.failureInbox} →`);
|
|
10
|
-
a.href = "
|
|
10
|
+
a.href = inspectPathToCanonicalHref("/failures");
|
|
11
11
|
a.addEventListener("click", (e) => {
|
|
12
12
|
e.preventDefault();
|
|
13
13
|
navigate("/failures");
|
|
@@ -62,10 +62,18 @@ export function parseInspectObjectView(
|
|
|
62
62
|
export function activeInspectTabHref(hashValue: string): string | null;
|
|
63
63
|
export function parseInspectContext(hashValue: string): InspectContext | null;
|
|
64
64
|
export function resolveOperateHrefFromInspectHash(hashValue: string): string;
|
|
65
|
-
export function buildOperateInterruptHref(
|
|
65
|
+
export function buildOperateInterruptHref(
|
|
66
|
+
dagRunId: string,
|
|
67
|
+
options?: { workspaceId?: string | null },
|
|
68
|
+
): string;
|
|
66
69
|
export function buildInspectDagHref(
|
|
67
70
|
dagRunId: string,
|
|
68
|
-
options?: { from?: string },
|
|
71
|
+
options?: { from?: string; workspaceId?: string | null },
|
|
72
|
+
): string;
|
|
73
|
+
export function parseInspectWorkspaceId(hashValue: string): string | null;
|
|
74
|
+
export function withWorkspaceQuery(
|
|
75
|
+
href: string,
|
|
76
|
+
workspaceId?: string | null,
|
|
69
77
|
): string;
|
|
70
78
|
export function clearInspectContextSource(hashValue: string): string;
|
|
71
79
|
export function repoBaseName(repoRoot: string): string;
|
|
@@ -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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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,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 =
|
|
51
|
+
a.href = inspectPathToCanonicalHref(path);
|
|
52
52
|
a.addEventListener("click", (e) => {
|
|
53
53
|
e.preventDefault();
|
|
54
54
|
e.stopPropagation();
|
|
@@ -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
|
|
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
|
-
|
|
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 === "/")
|
|
80
|
-
|
|
81
|
-
|
|
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 =
|
|
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();
|