@tea-agent/loop-agent 0.39.0-beta.0 → 0.39.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -1
- package/CHANGELOG.md +248 -95
- package/README.md +9 -5
- package/bin/loop-agent.js +7 -3
- package/dist/application/task-lifecycle/advance.js +12 -0
- package/dist/application/task-lifecycle/recommendations.js +13 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +23 -5
- package/dist/cli/program.js +21 -2
- package/dist/cli/update/notifier.js +2 -2
- package/dist/cli/update/runtime-activity.js +1 -29
- package/dist/cli.js +2 -1
- package/dist/commands/client-recovery.js +3 -0
- package/dist/commands/dag-follow-up.js +138 -0
- package/dist/commands/dag-rerun.js +55 -1
- package/dist/commands/init-model-catalog.js +464 -0
- package/dist/commands/init-upgrade.js +265 -97
- package/dist/commands/init.js +455 -28
- package/dist/commands/inspect-next.js +8 -0
- package/dist/commands/task-advance.js +19 -0
- package/dist/executors/dag-pi-executor.js +2306 -61
- package/dist/executors/pi-executor.js +7 -0
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-playwright-cli-tool.js +74 -28
- package/dist/executors/pi-read-budget-policy.js +239 -0
- package/dist/executors/pi-sdk-executor.js +180 -33
- package/dist/executors/shell-executor.js +1249 -224
- package/dist/executors/shell-write-guard.js +14 -0
- package/dist/executors/workspace-write-snapshot.js +68 -0
- package/dist/infrastructure/harness/atomic-write.js +23 -0
- package/dist/shared/dag-failure-category.js +150 -0
- package/dist/shared/dag-prompt-override.js +27 -0
- package/dist/shared/openspec-spec.js +70 -4
- package/dist/shared/operator/capabilities.js +39 -0
- package/dist/shared/playwright-cli-command-policy.js +15 -0
- package/dist/shared/update/console-notifier.js +100 -0
- package/dist/{cli → shared}/update/npm-client.js +70 -15
- package/dist/{cli → shared}/update/state.js +41 -13
- package/dist/task/config-types.js +50 -5
- package/dist/task/contract/apply.js +11 -1
- package/dist/task/contract/constants.js +2 -0
- package/dist/task/contract/hash.js +3 -0
- package/dist/task/contract/observe.js +25 -4
- package/dist/task/contract/paths.js +2 -1
- package/dist/task/contract/project.js +18 -1
- package/dist/task/contract/schema.js +4 -1
- package/dist/task/contract/transaction.js +12 -0
- package/dist/task/frontend-project-capability.js +199 -18
- package/dist/task/source-prepare/completeness.js +188 -0
- package/dist/task/source-prepare/fragment-inventory.js +477 -0
- package/dist/task/source-prepare/index.js +3 -0
- package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
- package/dist/task/source-prepare/ledger-review.js +214 -0
- package/dist/task/source-prepare/ledger.js +545 -0
- package/dist/task/source-prepare/parse-intent.js +24 -4
- package/dist/task/source-prepare/prepare.js +298 -1
- package/dist/task/source-prepare/semantic-intake.js +25 -5
- package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
- package/dist/task/source-prepare/types.js +22 -0
- package/dist/task/source-references.js +22 -1
- package/dist/worker/cli.js +18 -2
- package/dist/worker/console/chat/chat-event-store.js +62 -4
- package/dist/worker/console/chat/context-panel.js +7 -0
- package/dist/worker/console/chat/deferred-turn.js +12 -0
- package/dist/worker/console/chat/operation-card.js +8 -1
- package/dist/worker/console/chat/pi-console-config.js +81 -10
- package/dist/worker/console/chat/pi-runtime.js +264 -16
- package/dist/worker/console/chat/provider-error.js +98 -0
- package/dist/worker/console/chat/routes.js +298 -32
- package/dist/worker/console/chat/session-stats.js +179 -0
- package/dist/worker/console/chat/session-store.js +93 -63
- package/dist/worker/console/chat/todos.js +115 -0
- package/dist/worker/console/chat/tool-preview.js +42 -0
- package/dist/worker/console/chat/turn-process.js +20 -55
- package/dist/worker/console/chat/user-questions.js +266 -0
- package/dist/worker/console/chat/workspace-landing.js +14 -0
- package/dist/worker/console/console-handoff.js +82 -0
- package/dist/worker/console/console-update-and-init.js +115 -0
- package/dist/worker/console/console-update-runtime.js +84 -0
- package/dist/worker/console/dag-execution-receipt.js +33 -0
- package/dist/worker/console/draft-store.js +49 -0
- 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/index.js +3 -0
- package/dist/worker/console/inspect-split.js +18 -0
- package/dist/worker/console/native-directory-picker.js +13 -0
- package/dist/worker/console/operation-run-facts.js +19 -3
- package/dist/worker/console/operation-store.js +227 -7
- package/dist/worker/console/operator-actions.js +388 -0
- package/dist/worker/console/operator-surface-health.js +1 -0
- package/dist/worker/console/operator-user-error.js +2 -2
- package/dist/worker/console/prd-intake-bridge.js +13 -0
- package/dist/worker/console/routes.js +355 -3
- package/dist/worker/console/security.js +67 -13
- package/dist/worker/console/server.js +609 -164
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4kVYweA.js → abnfDiagram-N423BO3Z-BAsjg7ew.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Bj2M8iO5.js → arc-CyIlrwZw.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CLlXe4-6.js → architectureDiagram-T3A2C74G-Bo4tobhH.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-psEp5xH0.js → blockDiagram-VBNYF7ZC-Dfpow9gu.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DeKcOCGJ.js → c4Diagram-5PPSVZJV-DPmzG_B4.js} +1 -1
- package/dist/worker/console/static/assets/channel-DSrJAn0-.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-K0C744p1.js → chunk-2GRJ4B5K-pKQpB1UW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-xbNw4J9-.js → chunk-2Q5K7J3B-5n9YYquZ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLaSDUO.js → chunk-5RXB4S5H-DP3CtA2a.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CtiPlKel.js → chunk-5VM5RSS4-DYxMJPUy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DZtolir7.js → chunk-6Q2QTUOP-CS3D50Io.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CPcdNeew.js → chunk-GF5L2VYU-gSdDfo5_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-NgHc6V37.js → chunk-JWPE2WC7-A48q0ZNt.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DQ_T-hg8.js → chunk-KBJHAD2P-ow8Mm3DY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DgLsxcVP.js → chunk-RYQCIY6F-CMKfLWYE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-UrVoM9z1.js → chunk-XXDRQBXY-BiTBdQPX.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DeMmPl0_.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DeMmPl0_.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CLkYvTb3.js → cose-bilkent-JH36ORCC-Cm7exRz_.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BwT_xKrE.js → cynefin-VYW2F7L2-D9O5qGOu.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bi9tuzif.js → cynefinDiagram-MW4NZA55-CkvQnako.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BCIqkWBV.js → dagre-VZM6K2ZE-B1rzp7CB.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dip6l9_Z.js → diagram-7IWD3JNH-BP07Ipcc.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B-xkh_wK.js → diagram-B4RE2ZJO-BlPzweQb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DZO0kTt_.js → diagram-LBJQPF4R-CxPa7n0S.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D6ZplNbZ.js → diagram-Q27KOJAE-CMTZs53A.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPekbhoS.js → diagram-UB23O5K3-CxG_X52r.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BtmaJpK5.js → ebnfDiagram-BXEA7PRR-D8axtJM0.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-6DS0Xc44.js → erDiagram-JOGREHBK-DIsGzn7b.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CihnROSm.js → flowDiagram-UKHOOZJN-CU9zkDG0.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CZC4zOE2.js → ganttDiagram-PKOTCBZU-DCjTmz5P.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js → gitGraphDiagram-DS77QQ5N-BksdmFzg.js} +1 -1
- package/dist/worker/console/static/assets/index-B-O5ChYq.css +1 -0
- package/dist/worker/console/static/assets/index-CfnY8AQx.js +407 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DlSl4BGx.js → infoDiagram-6WML65LV-CGzzzJtL.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-snnzFl_U.js → ishikawaDiagram-WSZJBQD7-BdseB80N.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BDE7qpMx.js → journeyDiagram-NVQOT4AX-DM9gsgha.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CD2Ci04G.js → kanban-definition-27J2QSJJ-3q-_9R2b.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DdnapKIH.js → linear-B8N-Mxsd.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BVjAT9b8.js → mermaid.core-EPIHUUsu.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-D0yJk-zA.js → mindmap-definition-FAOFIHXS-CxwO12aa.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVo9tFP-.js → pegDiagram-VL7TDLO6-bPqbVX6Y.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnOV-mZ_.js → pieDiagram-7S7Q4E2Y-KzqIvzeX.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CzUJo58i.js → quadrantDiagram-CIZ2JOQS-CyofpWiV.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Bvikrolh.js → railroadDiagram-AXF67PYL-cTWJvLTP.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DtaSVCap.js → requirementDiagram-LRYGKXZP-BK--q27B.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-C2c9A0wW.js → sankeyDiagram-W5VNT64P-C0SDOHXK.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DmXJcU7r.js → sequenceDiagram-SI44F4Z6-Cong6YIo.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4GUFW92.js → sizeCapture-X5ZJPWSS-DUVkgZx8.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Dsad2MXf.js → stateDiagram-OKZ733FA-C7XgxuZg.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Dzbnd5oX.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DGq48Fbi.js → swimlanes-SLNWSIFB-D9Ayvwcy.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BY0hHk6G.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CSSi6OFf.js → timeline-definition-Z64GVDOM-Byb000cH.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BqyzPrWv.js → vennDiagram-T6HMQDX7-DMLegPt4.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DlznVb6S.js → wardleyDiagram-T6FBY63Y-ChMMeOsP.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CfBcgJ_K.js → xychartDiagram-ELKLHX3M-bEMEPisW.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/active-run-badge.js +17 -0
- package/dist/worker/console/static-src/app/console-types.js +68 -4
- package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
- package/dist/worker/console/static-src/app/useOperatorActions.js +41 -6
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +45 -10
- package/dist/worker/console/static-src/app/useRunProgress.js +47 -0
- package/dist/worker/console/static-src/app/useTaskWizard.js +74 -2
- package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
- package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +140 -8
- package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
- package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
- package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
- package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
- package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +16 -3
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +168 -72
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +102 -21
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +184 -4
- package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
- package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
- package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
- package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +337 -0
- package/dist/worker/console/workspace-context.js +344 -0
- package/dist/worker/console/workspace-registry.js +214 -0
- package/dist/worker/loop-agent/loop-agent-client.js +7 -3
- package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
- package/dist/worker/materialize/harness-task-lineage.js +5 -2
- package/dist/worker/observability/init-runtime-activity.js +26 -0
- package/dist/worker/observability/read-model.js +22 -0
- package/dist/worker/observe/node-input.js +160 -3
- package/dist/worker/observe/node-process.js +377 -0
- package/dist/worker/observe/routes.js +224 -3
- package/dist/worker/observe/server.js +4 -0
- package/dist/worker/observe/shell-handler-keys.js +34 -0
- package/dist/worker/observe/static/api.js +90 -4
- package/dist/worker/observe/static/app.js +18 -70
- package/dist/worker/observe/static/constants.js +8 -1
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
- package/dist/worker/observe/static/dag-node-purpose.js +208 -0
- package/dist/worker/observe/static/format.js +60 -0
- package/dist/worker/observe/static/index.html +6 -1
- package/dist/worker/observe/static/inspect-workspace.js +307 -0
- package/dist/worker/observe/static/markdown-render.js +20 -1
- package/dist/worker/observe/static/operator-chrome.css +145 -20
- package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
- package/dist/worker/observe/static/operator-chrome.js +330 -96
- package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
- package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
- package/dist/worker/observe/static/router.d.ts +46 -0
- package/dist/worker/observe/static/router.js +25 -1
- package/dist/worker/observe/static/state.d.ts +50 -0
- package/dist/worker/observe/static/state.js +184 -1
- package/dist/worker/observe/static/styles.css +395 -0
- package/dist/worker/observe/static/views/dag-graph.js +4 -2
- package/dist/worker/observe/static/views/dag-inspector.js +1067 -9
- package/dist/worker/observe/static/views/dag.d.ts +13 -0
- package/dist/worker/observe/static/views/dag.js +14 -5
- package/dist/worker/observe/static/views/dashboard.js +6 -4
- package/dist/worker/observe/static/views/failures.js +5 -2
- package/dist/worker/observe/static/views/night.js +2 -2
- package/dist/worker/observe/static/views/pool.js +1 -0
- package/dist/worker/observe/static/views/run.js +3 -1
- package/dist/worker/observe/static/views/session-timeline.js +78 -9
- package/dist/worker/observe/static/views/task.js +56 -1
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +49 -3
- package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
- package/dist/workflows/dag/backend-test-pytest-collection.js +98 -14
- package/dist/workflows/dag/backend-test-writer-completeness.js +10 -5
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/contract-validator-registrations.js +1 -2
- package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
- package/dist/workflows/dag/dynamic-runtime/map.js +1 -1
- package/dist/workflows/dag/failure-category.js +7 -116
- 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 +534 -178
- package/dist/workflows/dag/frontend-plan-render.js +24 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +371 -393
- 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 +202 -0
- package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
- package/dist/workflows/dag/frontend-recovery-run.js +33 -20
- package/dist/workflows/dag/frontend-repair.js +7 -424
- package/dist/workflows/dag/frontend-review-context.js +288 -14
- package/dist/workflows/dag/frontend-review-findings.js +270 -0
- package/dist/workflows/dag/frontend-risk.js +15 -2
- package/dist/workflows/dag/frontend-shadow-dual-write.js +814 -0
- package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
- package/dist/workflows/dag/frontend-shape-facts.js +409 -0
- package/dist/workflows/dag/frontend-shape.js +427 -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-test-case-checklist.js +30 -4
- package/dist/workflows/dag/frontend-test-case-manifest.js +11 -4
- package/dist/workflows/dag/frontend-test-case-quality.js +11 -16
- package/dist/workflows/dag/frontend-test-environment-probe.js +230 -0
- package/dist/workflows/dag/frontend-test-html-report.js +3 -1
- package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
- package/dist/workflows/dag/frontend-test-layout.js +159 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +188 -42
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +70 -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 +52 -17
- package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
- package/dist/workflows/dag/frontend-writer-admission.js +272 -0
- package/dist/workflows/dag/frontend-writer-status.js +244 -0
- package/dist/workflows/dag/init-hybrid.js +984 -618
- package/dist/workflows/dag/interrupt-request.js +10 -3
- package/dist/workflows/dag/lifecycle.js +3 -3
- package/dist/workflows/dag/node-execution.js +468 -34
- package/dist/workflows/dag/prompt.js +44 -19
- package/dist/workflows/dag/recovery-lease.js +80 -0
- package/dist/workflows/dag/report.js +37 -1
- package/dist/workflows/dag/rerun-feedback.js +124 -1
- package/dist/workflows/dag/rerun-plan.js +144 -5
- package/dist/workflows/dag/rerun-run.js +81 -6
- package/dist/workflows/dag/rerun-task.js +29 -0
- package/dist/workflows/dag/retry-policy.js +318 -8
- package/dist/workflows/dag/runner.js +429 -122
- package/dist/workflows/dag/scheduler.js +114 -16
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +321 -31
- package/dist/workflows/dag/upstream-artifacts.js +0 -4
- package/dist/workflows/dag/validate.js +92 -32
- package/docs/README.md +2 -0
- package/docs/architecture/evolution.md +45 -0
- package/docs/init-surface.manifest.json +9 -0
- package/docs/operations/README.md +1 -1
- package/docs/operations/local-development-environment.md +21 -0
- package/docs/templates/README.md +2 -1
- package/docs/templates/agent-dag-report.schema.json +8 -2
- package/docs/templates/agent-dag.schema.json +45 -1
- package/docs/templates/frontend-implementation-contract.schema.json +684 -24
- package/docs/templates/frontend-test-case-checklist.md +2 -2
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/docs/templates/init-managed-agents.md +13 -3
- package/docs/templates/spec-registry.schema.json +45 -0
- package/harness.json +3 -3
- package/package.json +7 -1
- package/scripts/next-info.mjs +356 -0
- package/scripts/next-publish-gate.mjs +238 -0
- package/scripts/release-source-binding.mjs +251 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/fe-test-ui-scout/SKILL.md +65 -0
- package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
- package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
- package/skills/frontend-bounded-implement/SKILL.md +8 -14
- package/skills/frontend-design-review/SKILL.md +20 -41
- package/skills/frontend-implementation/SKILL.md +3 -4
- package/skills/frontend-implementation/references/design-spec.md +15 -10
- package/skills/frontend-implementation/references/node-contracts.md +23 -13
- package/skills/frontend-review/SKILL.md +22 -14
- package/skills/frontend-review/references/review-findings.md +6 -7
- package/skills/loop-agent/references/command-reference.md +12 -4
- package/skills/loop-agent/references/hybrid-dag.md +8 -1
- package/skills/playwright-cli/SKILL.md +23 -1
- package/skills/playwright-cli-case-generator/SKILL.md +29 -8
- package/dist/worker/console/static/assets/channel-CPF4N7pf.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/index-DTZOKgAn.js +0 -404
- package/dist/worker/console/static/assets/index-Ya5FE7cD.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +0 -8
|
@@ -17,21 +17,33 @@ const ACTION_PROGRESS_COPY = {
|
|
|
17
17
|
spineCheck: "正在运行 Spine 审计…",
|
|
18
18
|
dagGenerate: "正在生成 DAG…",
|
|
19
19
|
standaloneTaskRerun: "正在带反馈重新执行任务:服务端校验资格后生成并启动新 DAG…",
|
|
20
|
+
consoleUpdateAndInit: "正在检查活动运行、所选 npm 渠道与安全初始化;完成后 Console 将自动刷新…",
|
|
20
21
|
workerTaskRetry: "正在重新排队 Worker Task…",
|
|
21
22
|
};
|
|
22
23
|
/** Central operator-action dispatcher: POST /api/operator/v1/operations with
|
|
23
24
|
* polling, long-running background waits, interview payload handoff and the
|
|
24
25
|
* per-operation SSE follow log. */
|
|
25
26
|
export function useOperatorActions(params) {
|
|
26
|
-
const { shell, applyInterviewPayload } = params;
|
|
27
|
+
const { shell, applyInterviewPayload, workspaceId } = params;
|
|
27
28
|
const { setBusy, setOpError, setOpErrorCode, setOpMessage, setReadiness, setStep, setNav, setLastOpState, setLayers, step, nav, } = shell;
|
|
28
29
|
const [operationId, setOperationId] = useState(null);
|
|
30
|
+
const [operationWorkspaceId, setOperationWorkspaceId] = useState(null);
|
|
29
31
|
const [sseLog, setSseLog] = useState([]);
|
|
30
32
|
const [followSse, setFollowSse] = useState(true);
|
|
31
33
|
const sseAbort = useRef(null);
|
|
32
34
|
const [confirmationId, setConfirmationId] = useState(null);
|
|
33
35
|
const [confirmationDetails, setConfirmationDetails] = useState(null);
|
|
34
36
|
const runAction = useCallback(async (action, actionParams = {}, opts) => {
|
|
37
|
+
const requestWorkspaceId = workspaceId?.trim() || null;
|
|
38
|
+
if (!requestWorkspaceId) {
|
|
39
|
+
const message = "当前 Workspace 不可用;请先选择有效 Workspace 后再执行操作";
|
|
40
|
+
setOpError(message);
|
|
41
|
+
setOpErrorCode("WORKSPACE_REQUIRED");
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
error: { code: "WORKSPACE_REQUIRED", message },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
35
47
|
setBusy(true);
|
|
36
48
|
setOpError(null);
|
|
37
49
|
setOpErrorCode(null);
|
|
@@ -40,7 +52,7 @@ export function useOperatorActions(params) {
|
|
|
40
52
|
// other UI feedback, which reads as a frozen page.
|
|
41
53
|
setOpMessage(ACTION_PROGRESS_COPY[action] ?? null);
|
|
42
54
|
try {
|
|
43
|
-
const { status, body } = await postOperator(action, actionParams, opts?.clientRequestId);
|
|
55
|
+
const { status, body } = await postOperator(action, actionParams, opts?.clientRequestId, requestWorkspaceId);
|
|
44
56
|
if (status === 412 || body.error?.code === "PI_SETUP_REQUIRED") {
|
|
45
57
|
setOpError(formatOperatorUserError(body.error?.message ?? "Pi 未就绪或已降级:该操作暂不可用"));
|
|
46
58
|
setOpErrorCode(body.error?.code ?? "PI_SETUP_REQUIRED");
|
|
@@ -62,6 +74,7 @@ export function useOperatorActions(params) {
|
|
|
62
74
|
return body;
|
|
63
75
|
}
|
|
64
76
|
if (body.operationId) {
|
|
77
|
+
setOperationWorkspaceId(requestWorkspaceId ?? null);
|
|
65
78
|
const activeChatSessionId = window.localStorage
|
|
66
79
|
.getItem(ACTIVE_CHAT_SESSION_STORAGE_KEY)
|
|
67
80
|
?.trim();
|
|
@@ -94,7 +107,7 @@ export function useOperatorActions(params) {
|
|
|
94
107
|
setOpMessage(`操作已接受,后台运行中:${body.operationId}(请看事件流;可同时打开 Observe)`);
|
|
95
108
|
// Recovery / long actions still need terminal feedback on this page.
|
|
96
109
|
const acceptedOpId = body.operationId;
|
|
97
|
-
void waitForOperation(acceptedOpId, 30 * 60_000).then((finalOp) => {
|
|
110
|
+
void waitForOperation(acceptedOpId, 30 * 60_000, requestWorkspaceId).then((finalOp) => {
|
|
98
111
|
if (!finalOp)
|
|
99
112
|
return;
|
|
100
113
|
setLastOpState(finalOp.state ?? null);
|
|
@@ -118,11 +131,15 @@ export function useOperatorActions(params) {
|
|
|
118
131
|
command: "succeeded",
|
|
119
132
|
}));
|
|
120
133
|
}
|
|
134
|
+
if (action === "consoleUpdateAndInit" && finalOp.state === "restarting") {
|
|
135
|
+
setOpMessage("新 Console 正在接棒,页面即将刷新…");
|
|
136
|
+
setTimeout(() => window.location.reload(), 800);
|
|
137
|
+
}
|
|
121
138
|
});
|
|
122
139
|
}
|
|
123
140
|
else {
|
|
124
141
|
setOpMessage(`操作已接受:${body.operationId}`);
|
|
125
|
-
const finalOp = await waitForOperation(body.operationId);
|
|
142
|
+
const finalOp = await waitForOperation(body.operationId, 300_000, requestWorkspaceId);
|
|
126
143
|
if (finalOp) {
|
|
127
144
|
setLastOpState(finalOp.state ?? null);
|
|
128
145
|
if (finalOp.state === "failed" ||
|
|
@@ -222,6 +239,7 @@ export function useOperatorActions(params) {
|
|
|
222
239
|
setNav,
|
|
223
240
|
setLastOpState,
|
|
224
241
|
setLayers,
|
|
242
|
+
workspaceId,
|
|
225
243
|
]);
|
|
226
244
|
const summarizeEnvelope = useCallback((body) => {
|
|
227
245
|
if (!body)
|
|
@@ -260,7 +278,10 @@ export function useOperatorActions(params) {
|
|
|
260
278
|
sseAbort.current = ac;
|
|
261
279
|
setSseLog((prev) => [...prev, `开始跟随事件流 ${opId}`]);
|
|
262
280
|
try {
|
|
263
|
-
const
|
|
281
|
+
const query = operationWorkspaceId
|
|
282
|
+
? `?workspaceId=${encodeURIComponent(operationWorkspaceId)}`
|
|
283
|
+
: "";
|
|
284
|
+
const res = await fetch(`/api/operator/v1/operations/${encodeURIComponent(opId)}/events${query}`, { credentials: "same-origin", signal: ac.signal });
|
|
264
285
|
if (!res.ok || !res.body) {
|
|
265
286
|
setSseLog((prev) => [...prev, `事件流 HTTP ${res.status}`]);
|
|
266
287
|
return;
|
|
@@ -294,7 +315,7 @@ export function useOperatorActions(params) {
|
|
|
294
315
|
]);
|
|
295
316
|
}
|
|
296
317
|
}
|
|
297
|
-
}, [followSse]);
|
|
318
|
+
}, [followSse, operationWorkspaceId]);
|
|
298
319
|
useEffect(() => {
|
|
299
320
|
if (operationId && followSse && (step === "run" || nav === "recovery")) {
|
|
300
321
|
void followOperationEvents(operationId);
|
|
@@ -306,6 +327,19 @@ export function useOperatorActions(params) {
|
|
|
306
327
|
sseAbort.current?.abort();
|
|
307
328
|
setOpMessage("已停止跟随日志(未取消子进程)");
|
|
308
329
|
}, [setOpMessage]);
|
|
330
|
+
/** AC-004 (2026-08-26): Operate workspace-switch reset. Aborts the old
|
|
331
|
+
* workspace's operation SSE follow and clears operationId + human-gate
|
|
332
|
+
* confirmation state. The wizard/recovery ids are cleared by App; this
|
|
333
|
+
* hook owns only its own operation/confirmation projection. */
|
|
334
|
+
const resetForWorkspaceScope = useCallback(() => {
|
|
335
|
+
sseAbort.current?.abort();
|
|
336
|
+
setOperationId(null);
|
|
337
|
+
setOperationWorkspaceId(null);
|
|
338
|
+
setSseLog([]);
|
|
339
|
+
setFollowSse(true);
|
|
340
|
+
setConfirmationId(null);
|
|
341
|
+
setConfirmationDetails(null);
|
|
342
|
+
}, []);
|
|
309
343
|
return {
|
|
310
344
|
runAction,
|
|
311
345
|
summarizeEnvelope,
|
|
@@ -316,6 +350,7 @@ export function useOperatorActions(params) {
|
|
|
316
350
|
followSse,
|
|
317
351
|
setFollowSse,
|
|
318
352
|
stopFollowSse,
|
|
353
|
+
resetForWorkspaceScope,
|
|
319
354
|
confirmationId,
|
|
320
355
|
setConfirmationId,
|
|
321
356
|
confirmationDetails,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { classifyRecoveryFact, consoleRecoveryCtas, partitionRecoveryCtas, recommendedRecoveryCtaId, } from "../../recovery-cta.js";
|
|
3
3
|
import { buildRecoveryReason, isAutoRecoveryReason, pickDefaultRecoveryNodeId, pickDefaultRecoveryRunId, sortRecoveryNodeCandidates, } from "../../recovery-selection.js";
|
|
4
|
-
import { postOperator, RECOVERY_FACT_LABEL, } from "./console-types.js";
|
|
4
|
+
import { postOperator, scopedReadUrl, RECOVERY_FACT_LABEL, } from "./console-types.js";
|
|
5
5
|
import { useRecoveryActions } from "./useRecoveryActions.js";
|
|
6
|
+
import { applyCanonicalHref, buildInspectHref, } from "../shell/workspace-route.js";
|
|
6
7
|
/** Recovery workspace: DAG-run / node candidate selection, fact-classified
|
|
7
8
|
* CTA lanes, structured reason prefill, plan preflight and gated reruns. */
|
|
8
9
|
export function useRecoveryConsole(params) {
|
|
@@ -36,12 +37,12 @@ export function useRecoveryConsole(params) {
|
|
|
36
37
|
const inspectPath = useCallback(() => {
|
|
37
38
|
if (dagRunId.trim()) {
|
|
38
39
|
// from=recovery 激活统一壳的对象上下文 chip 与显式返回路径
|
|
39
|
-
return `/
|
|
40
|
+
return buildInspectHref(`/dag/${encodeURIComponent(dagRunId.trim())}`, "from=recovery");
|
|
40
41
|
}
|
|
41
|
-
return "
|
|
42
|
+
return "/#/inspect";
|
|
42
43
|
}, [dagRunId]);
|
|
43
44
|
const openFullInspect = useCallback(() => {
|
|
44
|
-
|
|
45
|
+
applyCanonicalHref(inspectPath());
|
|
45
46
|
}, [inspectPath]);
|
|
46
47
|
/** Resolve DAG run id for inspect (side panel or full page). */
|
|
47
48
|
const resolveDagRunForInspect = useCallback(async () => {
|
|
@@ -70,7 +71,7 @@ export function useRecoveryConsole(params) {
|
|
|
70
71
|
setDagRunId(resolvedDag);
|
|
71
72
|
setObserveLinkStatus("match");
|
|
72
73
|
setObserveLinkMessage(null);
|
|
73
|
-
setObserveUrl(`/
|
|
74
|
+
setObserveUrl(buildInspectHref(`/dag/${encodeURIComponent(resolvedDag)}`));
|
|
74
75
|
return resolvedDag;
|
|
75
76
|
}
|
|
76
77
|
setOpError("尚未找到该任务的 DAG 运行,请稍后再打开检视");
|
|
@@ -97,7 +98,7 @@ export function useRecoveryConsole(params) {
|
|
|
97
98
|
const resolved = await resolveDagRunForInspect();
|
|
98
99
|
if (!resolved)
|
|
99
100
|
return;
|
|
100
|
-
|
|
101
|
+
applyCanonicalHref(buildInspectHref(`/dag/${encodeURIComponent(resolved)}`, "from=recovery"));
|
|
101
102
|
}, [resolveDagRunForInspect]);
|
|
102
103
|
const loadRecoveryRuns = useCallback(async () => {
|
|
103
104
|
setRecoveryRunsLoading(true);
|
|
@@ -107,7 +108,7 @@ export function useRecoveryConsole(params) {
|
|
|
107
108
|
if (id)
|
|
108
109
|
qs.set("taskId", id);
|
|
109
110
|
qs.set("limit", "40");
|
|
110
|
-
const res = await fetch(`/api/operator/v1/recovery/candidates?${qs.toString()}
|
|
111
|
+
const res = await fetch(scopedReadUrl(`/api/operator/v1/recovery/candidates?${qs.toString()}`), { credentials: "same-origin" });
|
|
111
112
|
if (!res.ok) {
|
|
112
113
|
setRecoveryRuns([]);
|
|
113
114
|
return;
|
|
@@ -133,7 +134,7 @@ export function useRecoveryConsole(params) {
|
|
|
133
134
|
}
|
|
134
135
|
setRecoveryNodesLoading(true);
|
|
135
136
|
try {
|
|
136
|
-
const res = await fetch(`/api/dag-runs/${encodeURIComponent(id)}
|
|
137
|
+
const res = await fetch(scopedReadUrl(`/api/dag-runs/${encodeURIComponent(id)}`), {
|
|
137
138
|
credentials: "same-origin",
|
|
138
139
|
});
|
|
139
140
|
if (!res.ok) {
|
|
@@ -219,6 +220,22 @@ export function useRecoveryConsole(params) {
|
|
|
219
220
|
setInterruptEligibility(null);
|
|
220
221
|
return;
|
|
221
222
|
}
|
|
223
|
+
// Interrupt eligibility only changes while a run is live. Polling a
|
|
224
|
+
// terminal run every 4s is pure noise — back off to a slow keepalive
|
|
225
|
+
// (the status itself can still flip if reconciliation rewrites it).
|
|
226
|
+
const idleStatuses = new Set([
|
|
227
|
+
"finished",
|
|
228
|
+
"failed",
|
|
229
|
+
"partial_failed",
|
|
230
|
+
"superseded",
|
|
231
|
+
"abandoned",
|
|
232
|
+
"interrupted",
|
|
233
|
+
]);
|
|
234
|
+
const intervalMs = recoveryRunStatus && idleStatuses.has(recoveryRunStatus) ? 30_000 : 4_000;
|
|
235
|
+
// While live (4s cadence) also refresh the run status itself: the
|
|
236
|
+
// status is only read once per selection, so a run that settles while
|
|
237
|
+
// selected used to keep the fast eligibility poll forever (2026-08-23).
|
|
238
|
+
const refreshRunStatus = intervalMs === 4_000;
|
|
222
239
|
let cancelled = false;
|
|
223
240
|
const load = async () => {
|
|
224
241
|
const { body } = await postOperator("dagInterruptEligibility", { runId });
|
|
@@ -234,14 +251,32 @@ export function useRecoveryConsole(params) {
|
|
|
234
251
|
targetOperationId: result.targetOperationId,
|
|
235
252
|
targetOperationState: result.targetOperationState,
|
|
236
253
|
});
|
|
254
|
+
if (!refreshRunStatus)
|
|
255
|
+
return;
|
|
256
|
+
try {
|
|
257
|
+
const res = await fetch(scopedReadUrl(`/api/dag-runs/${encodeURIComponent(runId)}`), { credentials: "same-origin" });
|
|
258
|
+
if (!res.ok || cancelled)
|
|
259
|
+
return;
|
|
260
|
+
const runBody = (await res.json());
|
|
261
|
+
if (cancelled)
|
|
262
|
+
return;
|
|
263
|
+
const next = (typeof runBody.effectiveStatus === "string" &&
|
|
264
|
+
runBody.effectiveStatus) ||
|
|
265
|
+
(typeof runBody.status === "string" && runBody.status) ||
|
|
266
|
+
null;
|
|
267
|
+
setRecoveryRunStatus(next);
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// Keep the last known status; the next round retries.
|
|
271
|
+
}
|
|
237
272
|
};
|
|
238
273
|
void load();
|
|
239
|
-
const timer = window.setInterval(() => void load(),
|
|
274
|
+
const timer = window.setInterval(() => void load(), intervalMs);
|
|
240
275
|
return () => {
|
|
241
276
|
cancelled = true;
|
|
242
277
|
window.clearInterval(timer);
|
|
243
278
|
};
|
|
244
|
-
}, [nav, dagRunId]);
|
|
279
|
+
}, [nav, dagRunId, recoveryRunStatus]);
|
|
245
280
|
useEffect(() => {
|
|
246
281
|
if (nav !== "recovery")
|
|
247
282
|
return;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { isTerminalDagRun } from "../../inspect-split.js";
|
|
3
|
+
import { scopedReadUrl } from "./console-types.js";
|
|
4
|
+
import { summarizeRunProgress, } from "../pages/tasks/run-panel-progress.js";
|
|
5
|
+
const RUN_PROGRESS_POLL_INTERVAL_MS = 5000;
|
|
6
|
+
/**
|
|
7
|
+
* Live run progress for the wizard RunPanel. Polls the DAG run detail
|
|
8
|
+
* endpoint every 5s while the run is live and stops once terminal; returns
|
|
9
|
+
* null until the first payload arrives. Errors keep the last known state.
|
|
10
|
+
*/
|
|
11
|
+
export function useRunProgress(dagRunId) {
|
|
12
|
+
const [dag, setDag] = useState(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const runId = dagRunId.trim();
|
|
15
|
+
setDag(null);
|
|
16
|
+
if (!runId)
|
|
17
|
+
return;
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
let timer;
|
|
20
|
+
const load = async () => {
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetch(scopedReadUrl(`/api/dag-runs/${encodeURIComponent(runId)}`), { credentials: "same-origin", signal: controller.signal });
|
|
23
|
+
if (!response.ok)
|
|
24
|
+
return;
|
|
25
|
+
const body = (await response.json());
|
|
26
|
+
if (controller.signal.aborted)
|
|
27
|
+
return;
|
|
28
|
+
setDag(body);
|
|
29
|
+
if (isTerminalDagRun(body) && timer !== undefined) {
|
|
30
|
+
window.clearInterval(timer);
|
|
31
|
+
timer = undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Keep the last known state; transient failures surface via staleness.
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
void load();
|
|
39
|
+
timer = window.setInterval(() => void load(), RUN_PROGRESS_POLL_INTERVAL_MS);
|
|
40
|
+
return () => {
|
|
41
|
+
controller.abort();
|
|
42
|
+
if (timer !== undefined)
|
|
43
|
+
window.clearInterval(timer);
|
|
44
|
+
};
|
|
45
|
+
}, [dagRunId]);
|
|
46
|
+
return useMemo(() => summarizeRunProgress(dag), [dag]);
|
|
47
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { ensureUniqueDocumentNames, operatorRequestFits, operatorRequestTooLargeMessage, } from "../prd-file-import.js";
|
|
3
|
-
import { requestId, WORKFLOW_OPTIONS, } from "./console-types.js";
|
|
3
|
+
import { requestId, scopedReadUrl, WORKFLOW_OPTIONS, } from "./console-types.js";
|
|
4
|
+
export async function fetchLedgerSummary(taskId, fetchImpl) {
|
|
5
|
+
const impl = fetchImpl ?? fetch;
|
|
6
|
+
const response = await impl(scopedReadUrl(`/api/tasks/${encodeURIComponent(taskId)}/ledger`), { credentials: "same-origin" });
|
|
7
|
+
if (!response.ok)
|
|
8
|
+
return { ok: false };
|
|
9
|
+
const summary = (await response.json());
|
|
10
|
+
return { ok: true, summary };
|
|
11
|
+
}
|
|
4
12
|
/** Happy Path task wizard: import-prd → interview → contract → dag-confirm →
|
|
5
13
|
* run. Owns task identity, interview projection and contract preflight/apply. */
|
|
6
14
|
export function useTaskWizard(params) {
|
|
@@ -24,16 +32,27 @@ export function useTaskWizard(params) {
|
|
|
24
32
|
const [contractDiffSummary, setContractDiffSummary] = useState(null);
|
|
25
33
|
const [contractApplied, setContractApplied] = useState(false);
|
|
26
34
|
const [spineOk, setSpineOk] = useState(null);
|
|
35
|
+
const [ledgerLoading, setLedgerLoading] = useState(false);
|
|
36
|
+
const [ledgerError, setLedgerError] = useState(null);
|
|
37
|
+
const [ledgerSummary, setLedgerSummary] = useState(null);
|
|
27
38
|
const [contractPreflightKey, setContractPreflightKey] = useState(null);
|
|
28
39
|
const contractPreflightRunning = useRef(false);
|
|
40
|
+
/** Epoch guard for ledger fetches: only the newest request may write wizard
|
|
41
|
+
* state, so a concurrent in-flight preflight response can never overwrite
|
|
42
|
+
* a fresh post-apply result (AC-001). */
|
|
43
|
+
const ledgerFetchEpoch = useRef(0);
|
|
29
44
|
const resetContractLanding = useCallback(() => {
|
|
30
45
|
setContractValidateOk(null);
|
|
31
46
|
setContractValidateSummary(null);
|
|
32
47
|
setContractDiffSummary(null);
|
|
33
48
|
setContractApplied(false);
|
|
34
49
|
setSpineOk(null);
|
|
50
|
+
setLedgerLoading(false);
|
|
51
|
+
setLedgerError(null);
|
|
52
|
+
setLedgerSummary(null);
|
|
35
53
|
setContractPreflightKey(null);
|
|
36
54
|
contractPreflightRunning.current = false;
|
|
55
|
+
ledgerFetchEpoch.current = 0;
|
|
37
56
|
}, []);
|
|
38
57
|
const enterContractStep = useCallback(() => {
|
|
39
58
|
resetContractLanding();
|
|
@@ -56,6 +75,39 @@ export function useTaskWizard(params) {
|
|
|
56
75
|
: "访谈已完成:草稿已绑定完整评估结果");
|
|
57
76
|
}
|
|
58
77
|
}, [enterContractStep, setOpMessage]);
|
|
78
|
+
/** Epoch-guarded shared ledger refresh used by both the contract-step
|
|
79
|
+
* preflight and the post-apply re-GET. `failureSemantics` keeps the
|
|
80
|
+
* preflight five-state behavior (non-ok → empty state, no error) while the
|
|
81
|
+
* post-apply refresh treats a non-ok/network failure as a safe-degrade
|
|
82
|
+
* error per AC-001. */
|
|
83
|
+
const refreshLedgerState = useCallback(async (id, failureSemantics) => {
|
|
84
|
+
const epoch = ++ledgerFetchEpoch.current;
|
|
85
|
+
setLedgerLoading(true);
|
|
86
|
+
setLedgerError(null);
|
|
87
|
+
try {
|
|
88
|
+
const outcome = await fetchLedgerSummary(id);
|
|
89
|
+
if (ledgerFetchEpoch.current !== epoch)
|
|
90
|
+
return;
|
|
91
|
+
if (!outcome.ok) {
|
|
92
|
+
setLedgerSummary(null);
|
|
93
|
+
if (failureSemantics) {
|
|
94
|
+
setLedgerError("ledger 接口不可达(安全降级)");
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
setLedgerSummary(outcome.summary);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
if (ledgerFetchEpoch.current !== epoch)
|
|
102
|
+
return;
|
|
103
|
+
setLedgerError("ledger 接口不可达(安全降级)");
|
|
104
|
+
setLedgerSummary(null);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
if (ledgerFetchEpoch.current === epoch)
|
|
108
|
+
setLedgerLoading(false);
|
|
109
|
+
}
|
|
110
|
+
}, []);
|
|
59
111
|
const runContractPreflight = useCallback(async (force = false) => {
|
|
60
112
|
const id = taskId.trim();
|
|
61
113
|
if (!id)
|
|
@@ -74,6 +126,9 @@ export function useTaskWizard(params) {
|
|
|
74
126
|
setContractDiffSummary(null);
|
|
75
127
|
setSpineOk(null);
|
|
76
128
|
setContractApplied(false);
|
|
129
|
+
// Shared epoch-guarded refresh preserves the five-state semantics:
|
|
130
|
+
// non-ok → empty state, network failure → safe-degrade error.
|
|
131
|
+
await refreshLedgerState(id, false);
|
|
77
132
|
try {
|
|
78
133
|
const validateBody = await runAction("contractValidate", {
|
|
79
134
|
taskId: id,
|
|
@@ -101,6 +156,7 @@ export function useTaskWizard(params) {
|
|
|
101
156
|
contractPreflightKey,
|
|
102
157
|
contractValidateOk,
|
|
103
158
|
isActionSuccess,
|
|
159
|
+
refreshLedgerState,
|
|
104
160
|
runAction,
|
|
105
161
|
setOpMessage,
|
|
106
162
|
summarizeEnvelope,
|
|
@@ -116,6 +172,11 @@ export function useTaskWizard(params) {
|
|
|
116
172
|
return;
|
|
117
173
|
}
|
|
118
174
|
setContractApplied(true);
|
|
175
|
+
// AC-001: re-GET the read-only ledger right after apply succeeds and
|
|
176
|
+
// write the latest summary BEFORE spineCheck/setStep, so the first
|
|
177
|
+
// dag-confirm frame shows post-apply statistics (never a loading/empty
|
|
178
|
+
// flash); refresh failure safe-degrades via ledgerError.
|
|
179
|
+
await refreshLedgerState(id, true);
|
|
119
180
|
const spineBody = await runAction("spineCheck", { taskId: id });
|
|
120
181
|
if (isActionSuccess(spineBody)) {
|
|
121
182
|
setSpineOk(true);
|
|
@@ -125,7 +186,15 @@ export function useTaskWizard(params) {
|
|
|
125
186
|
}
|
|
126
187
|
setSpineOk(false);
|
|
127
188
|
setOpMessage("契约已应用,但 Spine 审计未通过:可重试 Spine");
|
|
128
|
-
}, [
|
|
189
|
+
}, [
|
|
190
|
+
assessmentId,
|
|
191
|
+
isActionSuccess,
|
|
192
|
+
refreshLedgerState,
|
|
193
|
+
runAction,
|
|
194
|
+
setOpMessage,
|
|
195
|
+
setStep,
|
|
196
|
+
taskId,
|
|
197
|
+
]);
|
|
129
198
|
const retrySpineOnly = useCallback(async () => {
|
|
130
199
|
const id = taskId.trim();
|
|
131
200
|
if (!id)
|
|
@@ -282,6 +351,9 @@ export function useTaskWizard(params) {
|
|
|
282
351
|
contractValidateOk,
|
|
283
352
|
contractValidateSummary,
|
|
284
353
|
contractDiffSummary,
|
|
354
|
+
ledgerLoading,
|
|
355
|
+
ledgerError,
|
|
356
|
+
ledgerSummary,
|
|
285
357
|
contractApplied,
|
|
286
358
|
spineOk,
|
|
287
359
|
applyInterviewPayload,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { scopedReadUrl } from "../app/console-types.js";
|
|
2
3
|
/** Night board data plane: schedules list + doctor report + task pool +
|
|
3
4
|
* foreground aux-ticker projection, loaded together on mount/refresh. */
|
|
4
5
|
export function useNightBoard(params) {
|
|
@@ -16,10 +17,12 @@ export function useNightBoard(params) {
|
|
|
16
17
|
setLoadError(null);
|
|
17
18
|
try {
|
|
18
19
|
const [jobsRes, doctorRes, tasksRes, tickerRes] = await Promise.all([
|
|
19
|
-
fetch("/api/night-jobs", { credentials: "same-origin" }),
|
|
20
|
-
fetch("/api/night-jobs/doctor", {
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
fetch(scopedReadUrl("/api/night-jobs"), { credentials: "same-origin" }),
|
|
21
|
+
fetch(scopedReadUrl("/api/night-jobs/doctor"), {
|
|
22
|
+
credentials: "same-origin",
|
|
23
|
+
}),
|
|
24
|
+
fetch(scopedReadUrl("/api/tasks"), { credentials: "same-origin" }),
|
|
25
|
+
fetch(scopedReadUrl("/api/operator/v1/night-aux-ticker"), {
|
|
23
26
|
credentials: "same-origin",
|
|
24
27
|
}),
|
|
25
28
|
]);
|
|
@@ -59,7 +62,7 @@ export function useNightBoard(params) {
|
|
|
59
62
|
}, [refreshBoard]);
|
|
60
63
|
const onMorningReport = useCallback(async () => {
|
|
61
64
|
try {
|
|
62
|
-
const res = await fetch("/api/night-jobs/morning", {
|
|
65
|
+
const res = await fetch(scopedReadUrl("/api/night-jobs/morning"), {
|
|
63
66
|
credentials: "same-origin",
|
|
64
67
|
});
|
|
65
68
|
if (!res.ok) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operator-facing recovery advice per normalized DAG failure category
|
|
3
|
+
* (mirrors DAG_NORMALIZED_FAILURE_CATEGORIES). The task journey card used to
|
|
4
|
+
* stop at "原因分类为 X" without telling the operator what to do next; this
|
|
5
|
+
* maps each class to the concrete next move, aligned with the Recovery
|
|
6
|
+
* workspace CTAs (node rerun / reconcile / models page).
|
|
7
|
+
*/
|
|
8
|
+
const FAILURE_CATEGORY_ADVICE = {
|
|
9
|
+
validation: "节点输出未通过契约或门禁校验。可在恢复页从失败节点重跑;若错误指向任务契约(如验证命令、Mock 策略),先修正任务配置并重新生成 DAG。",
|
|
10
|
+
executor: "执行器或模型提供方调用失败(网络、配额或运行时错误)。稍后可在恢复页从失败节点重跑;反复出现请到「模型与认证」页检查配置与凭据。",
|
|
11
|
+
"write-guard": "写入越过了授权边界(writeSet / allowedPaths)。检查计划中的写入路径是否越界,修正后从失败节点重跑。",
|
|
12
|
+
timeout: "节点执行超时。可在恢复页从失败节点重跑;反复超时建议缩小任务范围或排查卡住的命令。",
|
|
13
|
+
auth: "模型或服务认证失败。请先到「模型与认证」页检查 API Key 与模型配置,再从失败节点重跑。",
|
|
14
|
+
"human-required": "节点正在等待人工审批。完成审批后该节点可继续执行;也可在恢复页查看对账状态。",
|
|
15
|
+
"human-rejected": "人工审批被拒绝。请调整任务描述或契约后重新发起任务。",
|
|
16
|
+
"shell-command": "验证/构建命令以非零退出。进入 DAG 查看命令输出定位具体失败,修复后从失败节点重跑。",
|
|
17
|
+
"static-error": "静态检查(typecheck / lint 等)失败。修复对应代码错误后从失败节点重跑。",
|
|
18
|
+
"decision-envelope": "决策与证据不匹配(决策包络校验失败)。进入 DAG 查看节点决策依据,修正后重跑。",
|
|
19
|
+
unknown: "失败原因未归类。进入 DAG 查看节点详情,或在恢复页使用对账 / 诊断入口。",
|
|
20
|
+
};
|
|
21
|
+
export function failureCategoryAdvice(category) {
|
|
22
|
+
if (!category)
|
|
23
|
+
return undefined;
|
|
24
|
+
return FAILURE_CATEGORY_ADVICE[category];
|
|
25
|
+
}
|