@tea-agent/loop-agent 0.40.0-next.1 → 0.40.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 +106 -109
- package/README.md +2 -2
- package/dist/application/task-lifecycle/advance.js +12 -0
- package/dist/build-stamp.json +3 -3
- package/dist/cli/update/runtime-activity.js +1 -29
- package/dist/commands/dag-rerun.js +1 -1
- package/dist/executors/dag-pi-executor.js +69 -7
- package/dist/executors/pi-executor.js +4 -2
- package/dist/executors/pi-sdk-executor.js +46 -1
- package/dist/executors/pi-writer-tool-policy.js +57 -1
- package/dist/executors/shell-executor.js +43 -3
- package/dist/executors/workspace-write-snapshot.js +68 -0
- package/dist/infrastructure/harness/atomic-write.js +23 -0
- package/dist/shared/dag-prompt-override.js +4 -5
- package/dist/shared/update/npm-client.js +33 -11
- package/dist/task/config-types.js +10 -0
- 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 +15 -1
- package/dist/task/contract/schema.js +2 -0
- package/dist/task/contract/transaction.js +12 -0
- package/dist/task/source-prepare/completeness.js +188 -0
- package/dist/task/source-prepare/fragment-inventory.js +474 -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/prepare.js +262 -1
- package/dist/task/source-prepare/semantic-intake.js +19 -3
- package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
- package/dist/task/source-prepare/types.js +22 -0
- package/dist/worker/cli.js +12 -26
- package/dist/worker/console/chat/chat-event-store.js +75 -5
- 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/pi-runtime.js +331 -18
- package/dist/worker/console/chat/provider-error.js +98 -0
- package/dist/worker/console/chat/routes.js +389 -56
- 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 +79 -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/draft-store.js +49 -0
- package/dist/worker/console/native-directory-picker.js +13 -0
- package/dist/worker/console/operation-store.js +1 -1
- package/dist/worker/console/operator-actions.js +129 -4
- package/dist/worker/console/operator-surface-health.js +1 -0
- package/dist/worker/console/prd-intake-bridge.js +13 -0
- package/dist/worker/console/routes.js +312 -1
- package/dist/worker/console/security.js +4 -4
- package/dist/worker/console/server.js +583 -172
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Br92EGb7.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
- package/dist/worker/console/static/assets/{arc-oulImtQq.js → arc-CAkA3We3.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-tyHc6aqO.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CY86BSpT.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BKKsDmNs.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-CXZdjl3B.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B-aIFDQ5.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BDgAW_B2.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DABa4UPR.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-aGbysVOx.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-B8MSZDVs.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CpelV73g.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BE04ty3z.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BUxTkaaR.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CYYBVKfX.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CEQF_xmQ.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CqpxN5IT.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-B3PzanVi.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BSUGCNx1.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CdLevU5T.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BjpF_Kok.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C4I6NJny.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C8hecCr5.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-Daod6tOS.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BvvmazGv.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DeN_vfV4.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-D6dq1t9z.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DziIdNY4.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dy4s5CXr.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czv5eYx2.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Bsk3nFRT.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DxGmNj5K.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CYCFqkO_.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
- package/dist/worker/console/static/assets/{linear-B0YzRwrd.js → linear-ByuxcHvp.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-t3EZtIGh.js → mermaid.core-DwPGvpCv.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BTXpTv0T.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DU8UkKqA.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DP4y8ohp.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B07vNaYR.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-xDWktb2i.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BLNMKqeS.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-n0adalxH.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BbnS-2DL.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4uPpCLu.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA--MMbB0fX.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BXUgp2QY.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CsaMxki7.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-C2IuG9iH.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CmEWOXCW.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-D_9LE0MG.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- 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 +10 -11
- package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
- 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/chat-sse-events.js +141 -8
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
- package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
- 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/spatial-overlay.js +1 -2
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +181 -87
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +159 -44
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +177 -8
- 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/shell/useWorkspaces.js +299 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +339 -0
- package/dist/worker/console/workspace-context.js +234 -0
- package/dist/worker/console/workspace-registry.js +214 -0
- package/dist/worker/observability/init-runtime-activity.js +26 -0
- package/dist/worker/observe/node-input.js +88 -2
- package/dist/worker/observe/routes.js +188 -0
- package/dist/worker/observe/server.js +4 -0
- package/dist/worker/observe/static/api.js +29 -9
- package/dist/worker/observe/static/app.js +18 -70
- package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
- package/dist/worker/observe/static/dag-node-purpose.js +203 -0
- package/dist/worker/observe/static/format.js +37 -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/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 -100
- 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 +174 -2
- package/dist/worker/observe/static/styles.css +357 -35
- package/dist/worker/observe/static/views/dag-graph.js +4 -2
- package/dist/worker/observe/static/views/dag-inspector.js +533 -79
- package/dist/worker/observe/static/views/dag.d.ts +13 -0
- package/dist/worker/observe/static/views/dag.js +6 -4
- package/dist/worker/observe/static/views/dashboard.js +6 -4
- 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/task.js +56 -1
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +29 -1
- 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 +17 -17
- package/dist/workflows/dag/dynamic-runtime/map.js +1 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +88 -2
- package/dist/workflows/dag/frontend-plan-render.js +24 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +197 -0
- package/dist/workflows/dag/frontend-review-context.js +92 -10
- package/dist/workflows/dag/init-hybrid.js +238 -51
- package/dist/workflows/dag/interrupt-request.js +3 -3
- package/dist/workflows/dag/lifecycle.js +3 -3
- package/dist/workflows/dag/node-execution.js +45 -0
- package/dist/workflows/dag/types.js +62 -12
- package/docs/README.md +2 -0
- package/docs/architecture/evolution.md +45 -0
- package/docs/init-surface.manifest.json +1 -0
- package/docs/operations/local-development-environment.md +21 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +18 -0
- package/docs/templates/backend-test-dag.json +265 -237
- package/docs/templates/frontend-implementation-contract.schema.json +681 -24
- package/harness.json +3 -3
- package/package.json +3 -1
- package/skills/loop-agent/references/hybrid-dag.md +7 -0
- package/dist/worker/console/static/assets/channel-TY36zt-i.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Dk7QCChM.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Dk7QCChM.js +0 -1
- package/dist/worker/console/static/assets/index-C3GgHg-g.css +0 -1
- package/dist/worker/console/static/assets/index-Ci8ksvBm.js +0 -406
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BqOigMQ4.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Caxz9UA2.js +0 -8
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
|
@@ -11,7 +11,11 @@ import { buildGlobalSnapshot, clampDagRunHistoryPageSize, clampTaskRunHistoryLim
|
|
|
11
11
|
import { loadDagRunExecutionTrajectory } from "../observability/dag-execution-trajectory.js";
|
|
12
12
|
import { resolveDagTaskSourcePath } from "../../task/dag-source-paths.js";
|
|
13
13
|
import { dagSourceBindingSchema } from "../../workflows/dag/types.js";
|
|
14
|
+
import { getTaskPaths } from "../../task/runtime.js";
|
|
15
|
+
import { classifyLedgerGate, computeLedgerInputDigest, LedgerParseError, parseLedgerJson, recoverLedgerInputContract, summarizeLedger, } from "../../task/source-prepare/ledger.js";
|
|
14
16
|
import { getTaskPoolRoot } from "../pool/run-store.js";
|
|
17
|
+
import { resolveDagRunArtifact, } from "./dag-run-artifacts.js";
|
|
18
|
+
import { frontendPrewriteResultV1Schema } from "../../workflows/dag/frontend-prewrite-gate.js";
|
|
15
19
|
import { isAllowedArtifactTextPath, resolveArtifactPath, resolveRepoFilePreview, toRepoRelativeArtifactPath, } from "./paths.js";
|
|
16
20
|
import { extractSpecEvidence, extractSpecReadContent, } from "./spec-evidence.js";
|
|
17
21
|
import { buildDagNodeInput } from "./node-input.js";
|
|
@@ -70,6 +74,15 @@ export const ROUTES = [
|
|
|
70
74
|
pattern: /^\/api\/tasks\/([^/]+)\/runs$/,
|
|
71
75
|
handler: handleTaskRuns,
|
|
72
76
|
},
|
|
77
|
+
/**
|
|
78
|
+
* Read-only source fidelity ledger safe summary (AC-009 / AC-FIDELITY-009):
|
|
79
|
+
* 只返回计数/状态/failure code,不泄漏敏感原文。
|
|
80
|
+
*/
|
|
81
|
+
{
|
|
82
|
+
method: "GET",
|
|
83
|
+
pattern: /^\/api\/tasks\/([^/]+)\/ledger$/,
|
|
84
|
+
handler: handleTaskLedger,
|
|
85
|
+
},
|
|
73
86
|
{
|
|
74
87
|
method: "GET",
|
|
75
88
|
pattern: /^\/api\/tasks\/([^/]+)$/,
|
|
@@ -116,6 +129,16 @@ export const ROUTES = [
|
|
|
116
129
|
pattern: /^\/api\/dag-runs\/([^/]+)\/nodes\/([^/]+)\/spec-evidence\/file$/,
|
|
117
130
|
handler: handleDagNodeSpecEvidenceFile,
|
|
118
131
|
},
|
|
132
|
+
// DAG run 专属只读 prewrite 结果(AC-006 / AC-BLOCK-006):唯一读路径为
|
|
133
|
+
// run-owned contracts/frontend-prewrite-result.json(resolveDagRunArtifact 四类
|
|
134
|
+
// fail-closed),不扩大 isAllowedArtifactTextPath 通用 allowlist;响应以
|
|
135
|
+
// frontendPrewriteResultV1Schema(.strict())解析,Inspector 不再做
|
|
136
|
+
// /api/artifacts 预览 → JSON.stringify → JSON.parse 双编码。
|
|
137
|
+
{
|
|
138
|
+
method: "GET",
|
|
139
|
+
pattern: /^\/api\/dag-runs\/([^/]+)\/prewrite-result$/,
|
|
140
|
+
handler: handleDagRunPrewriteResult,
|
|
141
|
+
},
|
|
119
142
|
{
|
|
120
143
|
method: "GET",
|
|
121
144
|
pattern: /^\/api\/dag-runs\/([^/]+)$/,
|
|
@@ -448,6 +471,117 @@ async function handleTaskRuns(_req, res, match, ctx) {
|
|
|
448
471
|
});
|
|
449
472
|
sendJson(res, 200, page);
|
|
450
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* GET /api/tasks/:id/ledger — 只读 ledger 安全摘要。任务存在但无 ledger 时返回
|
|
476
|
+
* `{ present: false }`(空态,不伪造计数);任务不存在返回 404;ledger 解析失败
|
|
477
|
+
* 返回带稳定 SOURCE_FIDELITY_* 错误码的 `{ present: false }`(AC-HARD-003:与
|
|
478
|
+
* parseLedgerJson 同一稳定码,不泄漏原文)。binding v2 标记 + ledgerSha256 +
|
|
479
|
+
* inputDigest 仅在真实 v2 绑定(非空 canonical requirement 集)时展示(AC-HARD-004:
|
|
480
|
+
* v1+optional 冒充 v2 不标记);inputDigest 与当前权威源输入不一致时置 stale。
|
|
481
|
+
*/
|
|
482
|
+
async function handleTaskLedger(_req, res, match, ctx) {
|
|
483
|
+
const taskId = match.params.id;
|
|
484
|
+
if (!isSafeObservabilityIdentifier(taskId)) {
|
|
485
|
+
sendJson(res, 400, { error: "Invalid task identifier" });
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const taskPaths = getTaskPaths(ctx.repoRoot, taskId);
|
|
489
|
+
try {
|
|
490
|
+
await stat(taskPaths.taskDir);
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
sendJson(res, 404, { error: "Task not found" });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const ledgerPath = path.join(taskPaths.sourceDir, "requirement-ledger.json");
|
|
497
|
+
let raw;
|
|
498
|
+
try {
|
|
499
|
+
raw = await readFile(ledgerPath, "utf8");
|
|
500
|
+
}
|
|
501
|
+
catch (error) {
|
|
502
|
+
if (error.code === "ENOENT") {
|
|
503
|
+
sendJson(res, 200, { present: false, taskId });
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
sendJson(res, 200, {
|
|
507
|
+
present: false,
|
|
508
|
+
taskId,
|
|
509
|
+
error: "ledger-unreadable",
|
|
510
|
+
});
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
let ledger;
|
|
514
|
+
try {
|
|
515
|
+
ledger = parseLedgerJson(raw);
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
// AC-HARD-003:解析失败分支使用与 parseLedgerJson 相同的稳定 SOURCE_FIDELITY_*
|
|
519
|
+
// 错误码(结构化可消费),而非裸字符串/裸 Error。
|
|
520
|
+
const code = error instanceof LedgerParseError
|
|
521
|
+
? error.code
|
|
522
|
+
: "SOURCE_FIDELITY_LEDGER_STALE";
|
|
523
|
+
sendJson(res, 200, {
|
|
524
|
+
present: false,
|
|
525
|
+
taskId,
|
|
526
|
+
error: code,
|
|
527
|
+
});
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const classification = classifyLedgerGate(ledger);
|
|
531
|
+
const summary = summarizeLedger(ledger, {
|
|
532
|
+
gateStatus: classification.ok ? "pass" : "fail",
|
|
533
|
+
failureCode: classification.ok ? null : classification.code,
|
|
534
|
+
});
|
|
535
|
+
// v2 binding 语义(AC-HARD-004):仅在真实 v2 绑定(canonical requirement 非空,
|
|
536
|
+
// 具备 requirement→fragment 映射证据)时标记 bindingSchemaVersion=2 并透传
|
|
537
|
+
// ledgerSha256/inputDigest;空 canonical 的 ledger 是退化/伪造 v2,不标记。
|
|
538
|
+
const contract = recoverLedgerInputContract(ledger);
|
|
539
|
+
const realV2Binding = contract.canonicalRequirements.length > 0;
|
|
540
|
+
let stale = false;
|
|
541
|
+
if (realV2Binding) {
|
|
542
|
+
// 当前权威源输入:ledger.sourcePaths(repo-root relative POSIX)→ 当前字节;
|
|
543
|
+
// 缺失/清空的权威源视为 stale(fail-closed,与 init-hybrid 语义一致)。
|
|
544
|
+
const currentByPath = new Map();
|
|
545
|
+
for (const sourcePath of contract.sourcePaths) {
|
|
546
|
+
try {
|
|
547
|
+
currentByPath.set(sourcePath, await readFile(path.resolve(ctx.repoRoot, sourcePath), "utf8"));
|
|
548
|
+
}
|
|
549
|
+
catch {
|
|
550
|
+
// 权威源缺失:保持缺失,expectedInputDigest 不一致 → stale。
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
const expectedDigest = computeLedgerInputDigest({
|
|
554
|
+
sourceDocuments: contract.sourcePaths.map((sourcePath) => ({
|
|
555
|
+
path: sourcePath,
|
|
556
|
+
content: currentByPath.get(sourcePath) ?? "",
|
|
557
|
+
})),
|
|
558
|
+
canonicalRequirements: contract.canonicalRequirements,
|
|
559
|
+
});
|
|
560
|
+
stale = ledger.inputDigest !== expectedDigest;
|
|
561
|
+
}
|
|
562
|
+
const ledgerSha256 = createHash("sha256").update(raw).digest("hex");
|
|
563
|
+
sendJson(res, 200, {
|
|
564
|
+
present: true,
|
|
565
|
+
taskId,
|
|
566
|
+
...(realV2Binding
|
|
567
|
+
? {
|
|
568
|
+
bindingSchemaVersion: 2,
|
|
569
|
+
ledgerSha256,
|
|
570
|
+
inputDigest: ledger.inputDigest,
|
|
571
|
+
stale,
|
|
572
|
+
}
|
|
573
|
+
: {}),
|
|
574
|
+
fragmentCount: summary.fragmentCount,
|
|
575
|
+
canonicalRequirementCount: summary.canonicalRequirementCount,
|
|
576
|
+
contextOnlyCount: summary.contextOnlyCount,
|
|
577
|
+
duplicateCount: summary.duplicateCount,
|
|
578
|
+
unresolvedCount: summary.unresolvedCount,
|
|
579
|
+
conflictCount: summary.conflictCount,
|
|
580
|
+
gateStatus: summary.gateStatus,
|
|
581
|
+
failureCode: summary.failureCode,
|
|
582
|
+
exclusions: summary.exclusions,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
451
585
|
function ambiguousTaskBody(taskId, candidates) {
|
|
452
586
|
return {
|
|
453
587
|
error: "Task identity ambiguous",
|
|
@@ -535,6 +669,60 @@ async function handleDagRuns(_req, res, match, ctx) {
|
|
|
535
669
|
const body = listDagRunHistoryFromSnapshot(snapshot, { page, pageSize });
|
|
536
670
|
sendJson(res, 200, body);
|
|
537
671
|
}
|
|
672
|
+
/**
|
|
673
|
+
* GET /api/dag-runs/:dagRunId/prewrite-result(AC-006 / AC-BLOCK-006)
|
|
674
|
+
* 只读 run-owned contracts/frontend-prewrite-result.json:resolveDagRunArtifact 是
|
|
675
|
+
* 唯一读路径(active/paused/completed 生命周期;invalid-id / unsafe-path /
|
|
676
|
+
* not-found / ambiguous 四类 fail-closed)。响应以 frontendPrewriteResultV1Schema
|
|
677
|
+
* (.strict())解析,拒绝 envelope 之外的字段;不扩大通用 artifact allowlist。
|
|
678
|
+
*/
|
|
679
|
+
async function handleDagRunPrewriteResult(_req, res, match, ctx) {
|
|
680
|
+
const dagRunId = match.params.id;
|
|
681
|
+
const resolved = resolveDagRunArtifact(ctx.repoRoot, dagRunId, [
|
|
682
|
+
"contracts",
|
|
683
|
+
"frontend-prewrite-result.json",
|
|
684
|
+
]);
|
|
685
|
+
if (!resolved.ok) {
|
|
686
|
+
if (resolved.reason === "invalid-id") {
|
|
687
|
+
sendJson(res, 400, { error: "Invalid dag run identifier" });
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
if (resolved.reason === "ambiguous") {
|
|
691
|
+
sendJson(res, 409, { error: "DAG run identity ambiguous" });
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
sendJson(res, 404, { error: "Prewrite result not found" });
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
let raw;
|
|
698
|
+
try {
|
|
699
|
+
raw = await readFile(resolved.result.absolutePath, "utf8");
|
|
700
|
+
}
|
|
701
|
+
catch {
|
|
702
|
+
sendJson(res, 404, { error: "Prewrite result not found" });
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
let parsed;
|
|
706
|
+
try {
|
|
707
|
+
parsed = JSON.parse(raw);
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
sendJson(res, 500, {
|
|
711
|
+
error: "Prewrite result is not valid JSON",
|
|
712
|
+
reason: "prewrite-result-unparseable",
|
|
713
|
+
});
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
const envelope = frontendPrewriteResultV1Schema.safeParse(parsed);
|
|
717
|
+
if (!envelope.success) {
|
|
718
|
+
sendJson(res, 500, {
|
|
719
|
+
error: "Prewrite result is not a valid frontend-prewrite-result-v1 envelope",
|
|
720
|
+
reason: "prewrite-result-schema-invalid",
|
|
721
|
+
});
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
sendJson(res, 200, envelope.data);
|
|
725
|
+
}
|
|
538
726
|
export async function handleDagRunById(_req, res, match, ctx) {
|
|
539
727
|
const snapshot = await getSnapshot(ctx);
|
|
540
728
|
const dagRun = snapshot.dagRuns.find((d) => d.dagRunId === match.params.id);
|
|
@@ -83,6 +83,10 @@ export function createObserveServer(options) {
|
|
|
83
83
|
url: `http://${host}:${addr.port}`,
|
|
84
84
|
close: () => new Promise((closeResolve, closeReject) => {
|
|
85
85
|
server.close((err) => (err ? closeReject(err) : closeResolve()));
|
|
86
|
+
// Explicit shutdown must not wait for the 65s keep-alive window.
|
|
87
|
+
// This also closes active SSE clients so process/test teardown is
|
|
88
|
+
// deterministic instead of timing out behind pooled connections.
|
|
89
|
+
server.closeAllConnections();
|
|
86
90
|
}),
|
|
87
91
|
});
|
|
88
92
|
});
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/** Fetch and artifact helpers (Observe UI R5). */
|
|
2
|
+
import {
|
|
3
|
+
fetchWithWorkspaceScope,
|
|
4
|
+
workspaceScope,
|
|
5
|
+
} from "./state.js";
|
|
2
6
|
|
|
3
7
|
export async function fetchJson(url) {
|
|
4
8
|
try {
|
|
5
|
-
const res = await
|
|
9
|
+
const res = await fetchWithWorkspaceScope(url);
|
|
6
10
|
if (!res.ok) return null;
|
|
7
11
|
return await res.json();
|
|
8
12
|
} catch {
|
|
@@ -18,7 +22,10 @@ export async function fetchJson(url) {
|
|
|
18
22
|
export async function fetchJsonResult(url, options = {}) {
|
|
19
23
|
const signal = options?.signal;
|
|
20
24
|
try {
|
|
21
|
-
const res = await
|
|
25
|
+
const res = await fetchWithWorkspaceScope(
|
|
26
|
+
url,
|
|
27
|
+
signal ? { signal } : undefined,
|
|
28
|
+
);
|
|
22
29
|
let body = null;
|
|
23
30
|
try {
|
|
24
31
|
body = await res.json();
|
|
@@ -92,7 +99,7 @@ export async function fetchDagNodeProcess(runId, nodeId, key) {
|
|
|
92
99
|
*/
|
|
93
100
|
export async function fetchSpecEvidenceFile(runId, nodeId, source, relPath) {
|
|
94
101
|
const url = `/api/dag-runs/${encodeURIComponent(runId)}/nodes/${encodeURIComponent(nodeId)}/spec-evidence/file?source=${encodeURIComponent(source)}&path=${encodeURIComponent(relPath)}`;
|
|
95
|
-
const res = await
|
|
102
|
+
const res = await fetchWithWorkspaceScope(url);
|
|
96
103
|
let body = null;
|
|
97
104
|
try {
|
|
98
105
|
body = await res.json();
|
|
@@ -116,8 +123,9 @@ export function artifactUrl(artifactPath) {
|
|
|
116
123
|
* Experimental (prompt-override rerun only): POST one allowlisted operator
|
|
117
124
|
* action through the Console mutation gate using the SCOPED inspect token
|
|
118
125
|
* (window.__INSPECT_MUTATION_TOKEN__). The server injects it into /inspect
|
|
119
|
-
* HTML
|
|
120
|
-
* authorizes dagRerunPlan / dagRerun — never general
|
|
126
|
+
* HTML by default; HARNESS_DAG_RERUN_PROMPT_OVERRIDE=0|false|off disables
|
|
127
|
+
* injection. The token only authorizes dagRerunPlan / dagRerun — never general
|
|
128
|
+
* Console mutations.
|
|
121
129
|
* Absent token → the call is not attempted.
|
|
122
130
|
*/
|
|
123
131
|
export async function postOperatorAction(action, actionParams = {}) {
|
|
@@ -129,15 +137,28 @@ export async function postOperatorAction(action, actionParams = {}) {
|
|
|
129
137
|
body: { error: { code: "PROMPT_OVERRIDE_DISABLED", message: "提示词重启未启用(服务端未注入确认 token)" } },
|
|
130
138
|
};
|
|
131
139
|
}
|
|
140
|
+
const workspaceId = workspaceScope();
|
|
141
|
+
if (!workspaceId) {
|
|
142
|
+
return {
|
|
143
|
+
ok: false,
|
|
144
|
+
status: 400,
|
|
145
|
+
body: {
|
|
146
|
+
error: {
|
|
147
|
+
code: "WORKSPACE_REQUIRED",
|
|
148
|
+
message: "workspaceId is required",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
132
153
|
try {
|
|
133
|
-
const res = await
|
|
154
|
+
const res = await fetchWithWorkspaceScope("/api/operator/v1/operations", {
|
|
134
155
|
method: "POST",
|
|
135
156
|
credentials: "same-origin",
|
|
136
157
|
headers: {
|
|
137
158
|
"Content-Type": "application/json",
|
|
138
159
|
"x-loop-console-confirmation": token,
|
|
139
160
|
},
|
|
140
|
-
body: JSON.stringify({ action, actionParams }),
|
|
161
|
+
body: JSON.stringify({ workspaceId, action, actionParams }),
|
|
141
162
|
});
|
|
142
163
|
let body = null;
|
|
143
164
|
try {
|
|
@@ -154,7 +175,7 @@ export async function postOperatorAction(action, actionParams = {}) {
|
|
|
154
175
|
/** Poll a Console operation snapshot (read-only GET). */
|
|
155
176
|
export async function fetchOperatorOperation(operationId) {
|
|
156
177
|
try {
|
|
157
|
-
const res = await
|
|
178
|
+
const res = await fetchWithWorkspaceScope(
|
|
158
179
|
`/api/operator/v1/operations/${encodeURIComponent(operationId)}`,
|
|
159
180
|
{ credentials: "same-origin" },
|
|
160
181
|
);
|
|
@@ -180,4 +201,3 @@ export function parseArtifactPreviewResponse(text) {
|
|
|
180
201
|
truncated: parsed.truncated === true,
|
|
181
202
|
};
|
|
182
203
|
}
|
|
183
|
-
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/** Observe UI bootstrap:
|
|
1
|
+
/** Observe UI bootstrap: standalone compatibility entry + re-exports. */
|
|
2
2
|
import {
|
|
3
3
|
parseHashRoute,
|
|
4
4
|
parseHashRouteWithFilters,
|
|
5
5
|
buildHashPath,
|
|
6
|
-
parseRoute,
|
|
7
6
|
} from "./router.js";
|
|
8
7
|
import { parseArtifactPreviewResponse } from "./api.js";
|
|
9
8
|
import {
|
|
@@ -15,7 +14,6 @@ import {
|
|
|
15
14
|
} from "./relations.js";
|
|
16
15
|
import { copyText, renderRecommendedCommand } from "./copy.js";
|
|
17
16
|
import {
|
|
18
|
-
isPageVisible,
|
|
19
17
|
detailPollDelay,
|
|
20
18
|
updateDagGraphViewportState,
|
|
21
19
|
captureDagGraphViewportState,
|
|
@@ -25,11 +23,9 @@ import {
|
|
|
25
23
|
shouldReuseDagDetailShell,
|
|
26
24
|
shouldPreserveDiagnosticsOpen,
|
|
27
25
|
isInteractiveGestureActive,
|
|
28
|
-
stopTimers,
|
|
29
26
|
renderViewState,
|
|
30
27
|
mountViewState,
|
|
31
28
|
viewStateDescriptor,
|
|
32
|
-
uiState,
|
|
33
29
|
} from "./state.js";
|
|
34
30
|
import { sortPoolTasks, poolStatusCounts } from "./format-pool.js";
|
|
35
31
|
import {
|
|
@@ -45,34 +41,22 @@ import {
|
|
|
45
41
|
dashboardVisibleFeatures,
|
|
46
42
|
findDagForRun,
|
|
47
43
|
} from "./dag-model.js";
|
|
48
|
-
|
|
49
|
-
import { renderFailures } from "./views/failures.js";
|
|
50
|
-
import { startPoolView } from "./views/pool.js";
|
|
51
|
-
import { startDashboardPolling } from "./views/dashboard.js";
|
|
52
|
-
import { startDagsView } from "./views/dags.js";
|
|
53
|
-
import { renderFeatureDetail } from "./views/feature.js";
|
|
54
|
-
import { renderBatch } from "./views/batch.js";
|
|
55
|
-
import { startTaskPolling } from "./views/task.js";
|
|
56
|
-
import { startRunPolling } from "./views/run.js";
|
|
57
|
-
import { startDagPolling } from "./views/dag.js";
|
|
58
44
|
import { renderDagGraph } from "./views/dag-graph.js";
|
|
59
|
-
import { renderNightJobs } from "./views/night.js";
|
|
60
45
|
import {
|
|
61
46
|
selectDagNode,
|
|
62
47
|
closeDagInspector,
|
|
63
|
-
closeDagInspectorOnOutsideClick,
|
|
64
48
|
renderDagInspector,
|
|
65
49
|
} from "./views/dag-inspector.js";
|
|
66
50
|
import {
|
|
67
51
|
mergeSessionEvents,
|
|
68
52
|
renderSessionTimeline,
|
|
69
53
|
} from "./views/session-timeline.js";
|
|
70
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
route,
|
|
56
|
+
startStandaloneInspect,
|
|
57
|
+
tryCanonicalizeStandaloneInspect,
|
|
58
|
+
} from "./inspect-workspace.js";
|
|
71
59
|
|
|
72
|
-
// Compatibility re-exports for poll-stable UI helpers (owned by state.js / views):
|
|
73
|
-
// reuse-dag-detail-shell, reuse-dag-graph-wrap, existingGraphWrap?.parentNode === ranksEl,
|
|
74
|
-
// existingDetails?.parentNode === metaEl, let pre = existingPre, computeFollowLatest,
|
|
75
|
-
// updateDagOutputViewportState, isInteractiveGestureActive.
|
|
76
60
|
export {
|
|
77
61
|
detailPollDelay,
|
|
78
62
|
parseMarkdownBlocks,
|
|
@@ -114,56 +98,20 @@ export {
|
|
|
114
98
|
renderDagInspector,
|
|
115
99
|
renderSessionTimeline,
|
|
116
100
|
mergeSessionEvents,
|
|
101
|
+
route,
|
|
102
|
+
tryCanonicalizeStandaloneInspect,
|
|
117
103
|
};
|
|
118
104
|
|
|
119
|
-
function route() {
|
|
120
|
-
stopTimers();
|
|
121
|
-
const r = parseRoute();
|
|
122
|
-
if (r.view === "dashboard") {
|
|
123
|
-
startDashboardPolling(r.scrollTo);
|
|
124
|
-
} else if (r.view === "dags") {
|
|
125
|
-
void startDagsView();
|
|
126
|
-
} else if (r.view === "batch") {
|
|
127
|
-
void renderBatch(r.batchRunId);
|
|
128
|
-
} else if (r.view === "run") {
|
|
129
|
-
startRunPolling(r.workerRunId);
|
|
130
|
-
} else if (r.view === "dag") {
|
|
131
|
-
startDagPolling(r.dagRunId);
|
|
132
|
-
} else if (r.view === "failures") {
|
|
133
|
-
void renderFailures();
|
|
134
|
-
} else if (r.view === "pool") {
|
|
135
|
-
startPoolView();
|
|
136
|
-
} else if (r.view === "night") {
|
|
137
|
-
void renderNightJobs(r.scheduleId);
|
|
138
|
-
} else if (r.view === "task") {
|
|
139
|
-
startTaskPolling(r.featureId, r.taskId);
|
|
140
|
-
} else if (r.view === "feature") {
|
|
141
|
-
void renderFeatureDetail(r.featureId);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
105
|
if (typeof window !== "undefined") {
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
106
|
+
// Compatibility listeners remain owned by inspect-workspace.js:
|
|
107
|
+
// window.addEventListener("hashchange", route)
|
|
108
|
+
// window.addEventListener("load", route)
|
|
109
|
+
// document.addEventListener("pointerdown", closeDagInspectorOnOutsideClick)
|
|
110
|
+
// document.addEventListener("visibilitychange", ...)
|
|
111
|
+
// reuse-dag-detail-shell, reuse-dag-graph-wrap, existingGraphWrap?.parentNode === ranksEl,
|
|
112
|
+
// existingDetails?.parentNode === metaEl, let pre = existingPre, computeFollowLatest,
|
|
113
|
+
// updateDagOutputViewportState, isInteractiveGestureActive.
|
|
114
|
+
if (!tryCanonicalizeStandaloneInspect(window.location)) {
|
|
115
|
+
startStandaloneInspect();
|
|
155
116
|
}
|
|
156
|
-
window.addEventListener("hashchange", route);
|
|
157
|
-
window.addEventListener("load", route);
|
|
158
|
-
document.addEventListener("pointerdown", closeDagInspectorOnOutsideClick);
|
|
159
|
-
document.addEventListener("visibilitychange", () => {
|
|
160
|
-
if (!isPageVisible()) return;
|
|
161
|
-
const r = parseRoute();
|
|
162
|
-
if (r.view === "dashboard") startDashboardPolling();
|
|
163
|
-
// History page is manual-refresh only (no 5s dashboard polling).
|
|
164
|
-
if (r.view === "run") startRunPolling(r.workerRunId, false);
|
|
165
|
-
if (r.view === "dag") startDagPolling(r.dagRunId, false);
|
|
166
|
-
if (r.view === "pool" && uiState.poolAutoRefresh) startPoolView();
|
|
167
|
-
if (r.view === "task") startTaskPolling(r.featureId, r.taskId);
|
|
168
|
-
});
|
|
169
117
|
}
|