@tea-agent/loop-agent 0.44.0-next.1 → 0.44.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +379 -416
- package/dist/application/evaluation/budget.js +21 -0
- package/dist/application/evaluation/corpus-hash.js +10 -15
- package/dist/application/evaluation/corpus.js +2 -1
- package/dist/application/evaluation/frontend-browser-acceptance.js +77 -0
- package/dist/application/evaluation/frontend-corpus-browser-acceptance.js +175 -0
- package/dist/application/evaluation/frontend-gateway-evidence.js +226 -0
- package/dist/application/evaluation/frontend-pair-registration.js +143 -0
- package/dist/application/evaluation/frontend-paired-summary.js +150 -0
- package/dist/application/evaluation/frontend-run-observation.js +144 -0
- package/dist/application/evaluation/frontend-shared-evidence.js +105 -0
- package/dist/application/evaluation/types.js +45 -12
- package/dist/application/task-lifecycle/observe.js +26 -1
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +11 -0
- package/dist/cli/program.js +4 -0
- package/dist/commands/task-advance.js +3 -5
- package/dist/commands/task-source-prepare.js +13 -1
- package/dist/executors/dag-pi/guards.js +4 -0
- package/dist/executors/dag-pi/model-config.js +30 -0
- package/dist/executors/dag-pi/plan/fact-adoption.js +55 -0
- package/dist/{workflows/dag/frontend-plan-completeness.js → executors/dag-pi/plan/facts.js} +22 -28
- package/dist/executors/dag-pi/plan/finalize-tools.js +259 -0
- package/dist/executors/dag-pi/plan/ledger-contract.js +55 -0
- package/dist/executors/dag-pi/plan/record-tools.js +861 -0
- package/dist/executors/dag-pi/plan/schema.js +129 -0
- package/dist/executors/dag-pi/plan/session.js +1 -0
- package/dist/executors/dag-pi/plan/tool-helpers.js +16 -0
- package/dist/executors/dag-pi/sessions/index.js +6 -0
- package/dist/executors/dag-pi/sessions/plan-batches.js +280 -0
- package/dist/executors/dag-pi/sessions/plan-prompts.js +367 -0
- package/dist/executors/dag-pi/sessions/scout-parallel.js +197 -0
- package/dist/executors/dag-pi/sessions/segmented-plan.js +1184 -0
- package/dist/executors/dag-pi/sessions/writer-evidence.js +60 -0
- package/dist/executors/dag-pi/tools/contract-tools.js +515 -0
- package/dist/executors/dag-pi/tools/design-terminal-tools.js +159 -0
- package/dist/executors/dag-pi/tools/plan-decision-tools.js +529 -0
- package/dist/executors/dag-pi/tools/review-terminal-tools.js +159 -0
- package/dist/executors/dag-pi/tools/scout-evidence-tools.js +270 -0
- package/dist/executors/dag-pi-executor.js +733 -5782
- package/dist/executors/pi-executor.js +6 -1
- package/dist/executors/pi-sdk-executor.js +112 -19
- package/dist/executors/shell-executor.js +88 -12
- package/dist/executors/shell-presets.js +1 -1
- package/dist/executors/shell-write-guard.js +26 -3
- package/dist/infrastructure/console/operation-store.js +48 -14
- package/dist/infrastructure/evaluation/corpus-store.js +37 -12
- package/dist/shared/file-identity.js +23 -0
- package/dist/shared/git-workspace-status.js +482 -0
- package/dist/shared/operator/capabilities.js +10 -5
- package/dist/shared/path-safety.js +2 -2
- package/dist/shared/wizard-local-telemetry.js +51 -0
- package/dist/task/config-types.js +22 -8
- package/dist/task/contract/project.js +13 -0
- package/dist/task/contract/schema.js +2 -7
- package/dist/task/frontend-preflight.js +1 -1
- package/dist/task/source-prepare/parse-intent.js +124 -5
- package/dist/task/source-prepare/prepare.js +6 -1
- package/dist/task/source-prepare/semantic-intake.js +18 -3
- package/dist/task/source-prepare/source-execution.js +65 -0
- package/dist/task/source-prepare/source-fidelity-pi.js +22 -9
- package/dist/task/source-prepare/source-provider-budget.js +290 -0
- package/dist/worker/console/chat/assistant-content.js +5 -34
- package/dist/worker/console/chat/chat-event-store.js +62 -10
- package/dist/worker/console/chat/context-insights.js +723 -0
- package/dist/worker/console/chat/conversation-nodes.js +383 -0
- package/dist/worker/console/chat/db-connections.js +854 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +1 -1
- package/dist/worker/console/chat/pi-runtime/custom-tools/sql-tools.js +655 -0
- package/dist/worker/console/chat/pi-runtime.js +445 -36
- package/dist/worker/console/chat/provider-error.js +0 -12
- package/dist/worker/console/chat/repo-browser.js +52 -4
- package/dist/worker/console/chat/routes.js +577 -72
- package/dist/worker/console/chat/sdd-data-alignment.js +8 -31
- package/dist/worker/console/chat/session-store.js +147 -19
- package/dist/worker/console/chat/shortcuts.js +7 -0
- package/dist/worker/console/chat/timeline-message-order.js +22 -0
- package/dist/worker/console/chat/tools.js +34 -0
- package/dist/worker/console/chat/turn-process.js +237 -66
- package/dist/worker/console/chat/user-turn-outline.js +19 -0
- package/dist/worker/console/console-update-runtime.js +2 -2
- package/dist/worker/console/dag-confirmation.js +3 -0
- package/dist/worker/console/dag-execution-receipt.js +3 -0
- package/dist/worker/console/operator-actions.js +32 -3
- package/dist/worker/console/operator-user-error.js +28 -1
- package/dist/worker/console/pi-readiness.js +4 -4
- package/dist/worker/console/prd-intake-bridge.js +5 -12
- package/dist/worker/console/recovery-cta.js +14 -14
- package/dist/worker/console/server.js +5 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-8-j6y-sd.js → abnfDiagram-N423BO3Z-r1NAPU_5.js} +1 -1
- package/dist/worker/console/static/assets/{arc-eoQiMvuk.js → arc-dT5T4sVL.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-C4A3uMcI.js → architectureDiagram-T3A2C74G-CP_cOq46.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D4zD2F-Q.js → blockDiagram-VBNYF7ZC-sToEZxEf.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-j1RkJziL.js → c4Diagram-5PPSVZJV-DSxwwi2m.js} +1 -1
- package/dist/worker/console/static/assets/channel-CyBY_yGk.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-YBHmhik1.js → chunk-2GRJ4B5K-B9fh0IkF.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-COfWyo9P.js → chunk-2Q5K7J3B-CAUNl-A6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-I99OUkHY.js → chunk-5RXB4S5H-BomeqbNX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-XKxoJNJ4.js → chunk-5VM5RSS4-BNAuTOLE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DLT_cYx1.js → chunk-6Q2QTUOP-DfzjRD5y.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CxcKZ9mV.js → chunk-GF5L2VYU-C3uE-yc2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-V1EqXdjY.js → chunk-JWPE2WC7-C3sQMMYr.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DebTtdFp.js → chunk-KBJHAD2P-D_AtEYQL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-B-ivNRDf.js → chunk-RYQCIY6F-DW4TwhKv.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DC_Ds11b.js → chunk-XXDRQBXY-CTQDmJcp.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-sWEqKwIb.js → cose-bilkent-JH36ORCC-iMqPuBsL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BXa_dcu4.js → cynefin-VYW2F7L2-DktIuDWs.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-C-Mle84F.js → cynefinDiagram-MW4NZA55-BgVnjyEs.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CXPDBITe.js → dagre-VZM6K2ZE-CR25E4bu.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-CC-WJQfa.js → diagram-7IWD3JNH-CPM2h5HY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CDAV5Vs4.js → diagram-B4RE2ZJO-DqF0x2g1.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CmFiAcNz.js → diagram-LBJQPF4R-G8BYp2eb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DPBZHuyn.js → diagram-Q27KOJAE-BbC4kT_D.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-jUlm_Ds3.js → diagram-UB23O5K3-CKZwZ-G5.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DWhQ3mfY.js → ebnfDiagram-BXEA7PRR-kJDmheia.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Tr2gMqet.js → erDiagram-JOGREHBK-DFTVHyxB.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DJjVQHPA.js → flowDiagram-UKHOOZJN-BqdN5_os.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-D74dQ4u0.js → ganttDiagram-PKOTCBZU-SYDjVakh.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js → gitGraphDiagram-DS77QQ5N-Bf8bNpGA.js} +1 -1
- package/dist/worker/console/static/assets/index-B28Onmfy.css +1 -0
- package/dist/worker/console/static/assets/index-CTMZsDmh.js +486 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-ILCbxJyb.js → infoDiagram-6WML65LV-DIeAmJ45.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DeuWBQ89.js → ishikawaDiagram-WSZJBQD7-oikqUAlo.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CF5ih8Fk.js → journeyDiagram-NVQOT4AX-mKEF_xYT.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C7yOSuRO.js → kanban-definition-27J2QSJJ-BdWJHPnN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BDZ9riWi.js → linear-DGRlieMH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-7pKqYtpZ.js → mermaid.core-4P9yPC9c.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-LeJDybSU.js → mindmap-definition-FAOFIHXS-5PTSkos6.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BJvT3pMD.js → pegDiagram-VL7TDLO6-DONIFpG5.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-_rGqpMan.js → pieDiagram-7S7Q4E2Y-D_Z4S70M.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DPcSv5aA.js → quadrantDiagram-CIZ2JOQS-CAsjh8iY.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Drxx4hkJ.js → railroadDiagram-AXF67PYL-Cx4Dd6ac.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BCTUdU4z.js → requirementDiagram-LRYGKXZP-cQb7mwyH.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B6wzbZmB.js → sankeyDiagram-W5VNT64P-Cd-DhUdf.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-BGt8d3QQ.js → sequenceDiagram-SI44F4Z6-AlKYRgIk.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-7nlhJKo7.js → sizeCapture-X5ZJPWSS-CUy_ET4e.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Cv2stqMA.js → stateDiagram-OKZ733FA-CTuVe6Sa.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BsWhs8O7.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-qDAo4Yc1.js → swimlanes-SLNWSIFB-ChFLJb-v.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CJcioYGH.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CKbDNKTr.js → timeline-definition-Z64GVDOM-DZZeiAPr.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DI-9EHic.js → vennDiagram-T6HMQDX7-t4O91cZU.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-BrzzRDpX.js → wardleyDiagram-T6FBY63Y-CV5qGHZu.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-BclH5hGh.js → xychartDiagram-ELKLHX3M-DyXbytUI.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +9 -1
- package/dist/worker/console/static-src/operator-chat/animation-frame-batcher.js +38 -0
- package/dist/worker/console/static-src/operator-chat/chat-link.js +20 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +186 -5
- package/dist/worker/console/static-src/operator-chat/chat-stream-continuity.js +101 -0
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +18 -3
- package/dist/worker/console/static-src/operator-chat/context-insights-store.js +64 -0
- package/dist/worker/console/static-src/operator-chat/details-rail-surfaces.js +98 -0
- package/dist/worker/console/static-src/operator-chat/file-palette-nav.js +81 -0
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +17 -3
- package/dist/worker/console/static-src/operator-chat/process-label.js +27 -5
- package/dist/worker/console/static-src/operator-chat/tools-catalog.js +16 -7
- package/dist/worker/console/static-src/operator-chat/transcript-mode.js +21 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +4 -1
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +13 -5
- package/dist/worker/console/static-src/operator-chat/turn-state-projection.js +166 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +56 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +211 -40
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +124 -27
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +88 -20
- package/dist/worker/console/static-src/operator-chat/useComposer.js +80 -6
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +13 -3
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +36 -17
- package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +18 -0
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/shell/console-update-reload.js +1 -1
- package/dist/worker/console/workspace-context.js +2 -0
- package/dist/worker/console/workspace-initialization.js +3 -3
- package/dist/worker/observability/read-model.js +23 -2
- package/dist/worker/observe/node-context-insights.js +479 -0
- package/dist/worker/observe/static/console-theme.css +174 -0
- package/dist/worker/observe/static/console-theme.js +36 -0
- package/dist/worker/observe/static/operator-chrome.css +85 -0
- package/dist/worker/observe/static/operator-chrome.js +51 -0
- package/dist/worker/scheduler/scheduled-goal-dispatch.js +3 -2
- package/dist/worker/scheduler/scheduled-goal-evidence.js +66 -3
- package/dist/worker/scheduler/scheduled-goal-store.js +10 -0
- package/dist/workflows/dag/budget-enforcement.js +31 -2
- package/dist/workflows/dag/checkpoint.js +686 -0
- package/dist/workflows/dag/frontend-closeout.js +3 -1
- package/dist/workflows/dag/frontend-contract-facts.js +11 -8
- package/dist/workflows/dag/frontend-design-policy.js +6 -6
- package/dist/workflows/dag/frontend-durable-tools.js +90 -70
- package/dist/workflows/dag/frontend-implementation-contract.js +146 -57
- package/dist/workflows/dag/frontend-plan-canary.js +66 -16
- package/dist/workflows/dag/frontend-plan-decision-contract.js +13 -21
- package/dist/workflows/dag/frontend-plan-progress.js +92 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +10 -5
- package/dist/workflows/dag/frontend-recovery-run.js +51 -46
- package/dist/workflows/dag/frontend-repair-assertions.js +36 -0
- package/dist/workflows/dag/frontend-review-context.js +29 -1
- package/dist/workflows/dag/frontend-review-scopes.js +92 -2
- package/dist/workflows/dag/frontend-risk.js +8 -3
- package/dist/workflows/dag/frontend-root-observation.js +261 -0
- package/dist/workflows/dag/frontend-session-budget.js +52 -39
- package/dist/workflows/dag/frontend-session-context.js +10 -0
- package/dist/workflows/dag/frontend-test-execution-evidence.js +206 -48
- package/dist/workflows/dag/frontend-typed-event-store.js +11 -1
- package/dist/workflows/dag/frontend-verification-trace.js +6 -0
- package/dist/workflows/dag/frontend-writer-admission.js +3 -1
- package/dist/workflows/dag/hybrid/sources.js +1812 -0
- package/dist/workflows/dag/hybrid/templates/backend-test.js +1807 -0
- package/dist/workflows/dag/hybrid/templates/frontend-test.js +702 -0
- package/dist/workflows/dag/hybrid/templates/frontend.js +1529 -0
- package/dist/workflows/dag/hybrid/templates/index.js +8 -0
- package/dist/workflows/dag/hybrid/templates/kg-bootstrap.js +449 -0
- package/dist/workflows/dag/hybrid/templates/knowledge-sync.js +495 -0
- package/dist/workflows/dag/hybrid/templates/shared.js +101 -0
- package/dist/workflows/dag/hybrid/templates/standard.js +265 -0
- package/dist/workflows/dag/hybrid/types.js +32 -0
- package/dist/workflows/dag/init-hybrid.js +57 -7106
- package/dist/workflows/dag/node-execution.js +11 -11
- package/dist/workflows/dag/output-protocol.js +1 -0
- package/dist/workflows/dag/rerun-feedback.js +35 -4
- package/dist/workflows/dag/rerun-task.js +62 -66
- package/dist/workflows/dag/runner.js +38 -1159
- package/dist/workflows/dag/terminal-status.js +502 -0
- package/dist/workflows/dag/types.js +15 -8
- package/dist/workflows/loop/benchmark.js +11 -8
- package/docs/README.md +1 -1
- package/docs/architecture/dag-execution.md +1 -1
- package/docs/architecture/runtime-boundaries.md +1 -1
- package/docs/governance/harness-methodology-verification.md +11 -0
- package/docs/templates/backend-test-dag.json +5 -4
- package/docs/templates/frontend-implementation-contract.schema.json +31 -11
- package/package.json +6 -4
- package/skills/frontend-design-review/SKILL.md +8 -11
- package/skills/frontend-design-review/references/review-checklist.md +3 -4
- package/skills/frontend-review/SKILL.md +5 -1
- package/skills/loop-agent/references/command-reference.md +8 -0
- package/skills/loop-agent/references/hybrid-dag.md +1 -1
- package/dist/worker/console/static/assets/channel-ChE7y-cx.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +0 -1
- package/dist/worker/console/static/assets/index-BWkIfcrK.css +0 -1
- package/dist/worker/console/static/assets/index-Cdkvw_H6.js +0 -469
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +0 -8
|
@@ -44,6 +44,8 @@ export const frontendCloseoutFactsSchema = z
|
|
|
44
44
|
status: frontendCoverageStatusSchema,
|
|
45
45
|
evidence: z.enum(["file-exists", "command-execution", "test-file-execution", "unavailable"]).optional(),
|
|
46
46
|
behaviorCoverage: z.enum(["unconfirmed"]).optional(),
|
|
47
|
+
plannedEvidenceLevel: z.enum(["unit", "mounted", "real-integration", "unknown"]).optional(),
|
|
48
|
+
boundary: z.string().min(1).optional(),
|
|
47
49
|
})
|
|
48
50
|
.strict()),
|
|
49
51
|
lintStatus: frontendLintStatusSchema,
|
|
@@ -145,7 +147,7 @@ function bulletList(items) {
|
|
|
145
147
|
return items.map((item) => `- ${item}`).join("\n");
|
|
146
148
|
}
|
|
147
149
|
function coverageLines(facts) {
|
|
148
|
-
const lines = facts.coverageMatrix.map((entry) => `- ${entry.verificationTargetId}: execution=${entry.status}; evidence=${entry.evidence ?? "unspecified"}; behavior-coverage=${entry.behaviorCoverage ?? "unconfirmed"}`);
|
|
150
|
+
const lines = facts.coverageMatrix.map((entry) => `- ${entry.verificationTargetId}: execution=${entry.status}; evidence=${entry.evidence ?? "unspecified"}; behavior-coverage=${entry.behaviorCoverage ?? "unconfirmed"}; planned-evidence=${entry.plannedEvidenceLevel ?? "unknown"}${entry.boundary ? `; boundary=${entry.boundary}` : ""}`);
|
|
149
151
|
return lines.length > 0 ? lines.join("\n") : "_(none)_";
|
|
150
152
|
}
|
|
151
153
|
function frontendStatus(facts) {
|
|
@@ -5,7 +5,8 @@ function object(value) {
|
|
|
5
5
|
? value
|
|
6
6
|
: undefined;
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
8
|
+
/** Project the latest requirement per id while retaining first-seen order.
|
|
9
|
+
* The append-only ledger also contains earlier execution metadata revisions.
|
|
9
10
|
* Later evidence declarations replace only the lanes they explicitly name. */
|
|
10
11
|
export function resolveFrontendContractRequirements(facts) {
|
|
11
12
|
const contractFacts = facts.map(object).filter((fact) => fact?.origin === "contract");
|
|
@@ -19,13 +20,15 @@ export function resolveFrontendContractRequirements(facts) {
|
|
|
19
20
|
...object(fact.evidence),
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const requirements = new Map();
|
|
24
|
+
for (const fact of contractFacts) {
|
|
25
|
+
if (fact.kind === "requirement" && typeof fact.id === "string")
|
|
26
|
+
requirements.set(fact.id, fact);
|
|
27
|
+
}
|
|
28
|
+
return [...requirements].map(([id, fact]) => ({
|
|
29
|
+
...fact, id,
|
|
30
|
+
evidence: { ...object(fact.evidence), ...evidenceById.get(id) },
|
|
31
|
+
}));
|
|
29
32
|
}
|
|
30
33
|
function names(value) {
|
|
31
34
|
return Array.isArray(value)
|
|
@@ -243,9 +243,9 @@ export function checkComponentChoice(contract, componentSpecCandidatePaths, opti
|
|
|
243
243
|
});
|
|
244
244
|
return findings;
|
|
245
245
|
}
|
|
246
|
-
/** 5.
|
|
247
|
-
*
|
|
248
|
-
export function checkTargetPaths(contract, writeSetPatterns) {
|
|
246
|
+
/** 5. Implementation targets require write permission. Existing, safely
|
|
247
|
+
* resolved verification files may remain read-only outside that writeSet. */
|
|
248
|
+
export function checkTargetPaths(contract, writeSetPatterns, existingVerificationPaths = []) {
|
|
249
249
|
const findings = [];
|
|
250
250
|
// No frozen writeSet patterns (legacy / unconfigured run) → nothing to
|
|
251
251
|
// check; an empty pattern set must not report every file as out of scope.
|
|
@@ -275,7 +275,7 @@ export function checkTargetPaths(contract, writeSetPatterns) {
|
|
|
275
275
|
for (const target of contract.verificationTargets) {
|
|
276
276
|
if (target.mode === "static")
|
|
277
277
|
continue;
|
|
278
|
-
if (!matches(target.file)) {
|
|
278
|
+
if (!matches(target.file) && !existingVerificationPaths.includes(target.file)) {
|
|
279
279
|
findings.push({
|
|
280
280
|
code: "target-path-outside-write-set",
|
|
281
281
|
message: `verification target "${target.id}" file is outside the writeSet patterns: ${target.file}`,
|
|
@@ -442,7 +442,7 @@ export function checkRequiredDeliverables(contract) {
|
|
|
442
442
|
return [];
|
|
443
443
|
const planned = new Set([
|
|
444
444
|
...contract.targets.files,
|
|
445
|
-
...contract.requirements.flatMap((requirement) => requirement.implementationTargets),
|
|
445
|
+
...contract.requirements.flatMap((requirement) => [...requirement.implementationTargets, ...(requirement.deliverableTargets ?? [])]),
|
|
446
446
|
...contract.verificationTargets.map((target) => target.file),
|
|
447
447
|
]);
|
|
448
448
|
return required
|
|
@@ -464,7 +464,7 @@ export function evaluateFrontendDesignPolicy(input) {
|
|
|
464
464
|
...checkComponentChoice(input.contract, input.componentSpecCandidatePaths, input.hasFreshPathEvidence
|
|
465
465
|
? { hasFreshPathEvidence: input.hasFreshPathEvidence }
|
|
466
466
|
: undefined),
|
|
467
|
-
...checkTargetPaths(input.contract, input.writeSetPatterns),
|
|
467
|
+
...checkTargetPaths(input.contract, input.writeSetPatterns, input.existingVerificationPaths),
|
|
468
468
|
...checkDependencies(input.contract, input.allowedDependencies),
|
|
469
469
|
...checkUiStateAttribution(input.contract),
|
|
470
470
|
...checkUxNameCollisions(input.contract),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { frontendPlanSemanticDigest } from "./frontend-plan-progress.js";
|
|
1
2
|
import { mkdir, open, rename, rm } from "node:fs/promises";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import path from "node:path";
|
|
@@ -12,7 +13,7 @@ export function readFrontendToolProgress(tools) {
|
|
|
12
13
|
const counters = [...new Set((tools ?? []).flatMap(tool => tool && typeof tool === "object" && progressByTool.has(tool) ? [progressByTool.get(tool)] : []))];
|
|
13
14
|
if (!counters.length)
|
|
14
15
|
return undefined;
|
|
15
|
-
return counters.reduce((sum, item) => ({ failedRecords: sum.failedRecords + item.failedRecords, duplicateRecords: sum.duplicateRecords + item.duplicateRecords, durableSubmissions: sum.durableSubmissions + item.durableSubmissions, durableReplacements: sum.durableReplacements + item.durableReplacements }), { failedRecords: 0, duplicateRecords: 0, durableSubmissions: 0, durableReplacements: 0 });
|
|
16
|
+
return counters.reduce((sum, item) => ({ finalizeRejections: sum.finalizeRejections + item.finalizeRejections, failedRecords: sum.failedRecords + item.failedRecords, duplicateRecords: sum.duplicateRecords + item.duplicateRecords, durableSubmissions: sum.durableSubmissions + item.durableSubmissions, durableReplacements: sum.durableReplacements + item.durableReplacements }), { finalizeRejections: 0, failedRecords: 0, duplicateRecords: 0, durableSubmissions: 0, durableReplacements: 0 });
|
|
16
17
|
}
|
|
17
18
|
async function exclusive(key, work) {
|
|
18
19
|
const previous = queues.get(key) ?? Promise.resolve();
|
|
@@ -61,7 +62,8 @@ export async function createDurableFrontendTools(input) {
|
|
|
61
62
|
return { ...tool, parameters: { ...schema, properties: { ...schema.properties, replace: { type: "boolean", description: "Explicitly revise the current fact with the same identity. Omit for new facts or identical replay." } } } };
|
|
62
63
|
});
|
|
63
64
|
const bindingSha256 = hash({ version: 1, attemptId: input.attemptId, binding: input.binding, schemas: tools.map(t => ({ name: t.name, parameters: t.parameters })) });
|
|
64
|
-
const publish = (store) => { input.store.records = store.records; input.store.revision = store.revision; input.setWorkingStore(input.store);
|
|
65
|
+
const publish = (store) => { input.store.records = store.records; input.store.revision = store.revision; input.setWorkingStore(input.store); if (hasCommittedTerminalEvent(store, input.attemptId))
|
|
66
|
+
input.planControl?.acceptTerminal(); };
|
|
65
67
|
const validate = async (records) => {
|
|
66
68
|
let revision = 0;
|
|
67
69
|
let terminal = false;
|
|
@@ -89,81 +91,99 @@ export async function createDurableFrontendTools(input) {
|
|
|
89
91
|
throw ledgerError("FRONTEND_LEDGER_MISSING", "frontend durable ledger disappeared or became empty; refusing an unproven acknowledgement");
|
|
90
92
|
};
|
|
91
93
|
await exclusive(file, restore);
|
|
92
|
-
const progress = { failedRecords: 0, duplicateRecords: 0, durableSubmissions: 0, durableReplacements: 0 };
|
|
94
|
+
const progress = { finalizeRejections: 0, failedRecords: 0, duplicateRecords: 0, durableSubmissions: 0, durableReplacements: 0 };
|
|
93
95
|
const replay = (receipt) => { progress.duplicateRecords++; return receipt; };
|
|
94
96
|
const wrapped = tools.map(tool => ({ ...tool, execute: (...args) => exclusive(file, async () => {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const identity = `${tool.name}:${typeof naturalId === "string" ? naturalId : "incremental"}`;
|
|
107
|
-
const submissions = input.store.records.flatMap(r => r.submission?.receipt ? [r.submission] : []);
|
|
108
|
-
const previousCall = submissions.find(s => s.callId === callId);
|
|
109
|
-
if (previousCall)
|
|
110
|
-
return previousCall.tool === tool.name && previousCall.paramsSha256 === paramsSha256 ? replay(previousCall.receipt) : failure("REQUEST_ID_REUSE_CONFLICT", `${tool.name}: call id already acknowledged with different parameters`);
|
|
111
|
-
const previousFact = submissions.filter(s => s.identity === identity).at(-1);
|
|
112
|
-
if (tool.name !== "record_plan_group_coverage" && previousFact?.paramsSha256 === paramsSha256)
|
|
113
|
-
return replay(previousFact.receipt);
|
|
114
|
-
// A committed finalize terminal carries no domain payload in its params
|
|
115
|
-
// (r15: the model acknowledged with {replace:false}, the executor's
|
|
116
|
-
// auto-finalize sends {}) — both are acknowledgements of the same durable
|
|
117
|
-
// terminal, so any later finalize call replays the receipt instead of
|
|
118
|
-
// demanding a params match no caller can reproduce. Other singletons
|
|
119
|
-
// (state registry, data flows, ...) carry domain payloads and keep the
|
|
120
|
-
// replace:true correction path.
|
|
121
|
-
if (FINALIZE_TERMINAL_TOOLS.has(tool.name) && previousFact?.receipt)
|
|
122
|
-
return replay(previousFact.receipt);
|
|
123
|
-
if (previousFact && naturalId !== undefined && params?.replace !== true && !["record_evidence_expectation", "record_required_deliverables", "record_data_flow"].includes(tool.name))
|
|
124
|
-
return failure("FACT_IDENTITY_CONFLICT", `${identity}: changing a saved fact requires explicit replacement (replace:true)`);
|
|
125
|
-
if (input.store.records.some(r => ["contract-finalized", "finalize_plan", "finalize_decision", "approve_review", "request_review_changes", "approve_design", "request_design_changes"].includes(String(r.fact.kind))))
|
|
126
|
-
return failure("TERMINAL_CONFLICT", "A successful terminal is already durable; only identical acknowledged submissions may be replayed");
|
|
127
|
-
const draft = structuredClone(input.store);
|
|
128
|
-
input.setWorkingStore(draft);
|
|
129
|
-
let result;
|
|
97
|
+
const beforeRevision = input.store.revision;
|
|
98
|
+
const execute = async () => {
|
|
99
|
+
const stopped = input.planControl?.readStop();
|
|
100
|
+
if (stopped)
|
|
101
|
+
return failure(stopped.code, stopped.error);
|
|
102
|
+
const [callId, params] = args;
|
|
103
|
+
const valid = Check(tool.parameters, params);
|
|
104
|
+
if (!valid) {
|
|
105
|
+
const errors = [...Errors(tool.parameters, params)];
|
|
106
|
+
return failure("TOOL_SCHEMA_INVALID", `${tool.name}: ${errors.slice(0, 8).map(e => `${e.instancePath || "/"}: ${e.message}`).join("; ")}${errors.length > 8 ? `; ${errors.length - 8} more fields` : ""}`);
|
|
107
|
+
}
|
|
130
108
|
try {
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
109
|
+
await restore();
|
|
110
|
+
const isReviewFinding = ["record_review_finding", "record_design_finding"].includes(tool.name);
|
|
111
|
+
const paramsSha256 = hash(isReviewFinding ? { ...params, replace: undefined } : params);
|
|
112
|
+
const singleton = new Set(["record_route_selection", "record_state_registry", "record_mock_api", "record_data_flow", "record_dependency", "record_design_deviation", "record_required_deliverables", "record_target_surface", "finalize_contract", "finalize_plan", "finalize_decision"]);
|
|
113
|
+
const naturalId = params?.id ?? params?.scopeId ?? params?.entry?.id ?? params?.requirementId ?? params?.choice?.purpose ?? params?.entry?.purpose ?? params?.entry?.state ?? params?.entry?.interaction ?? params?.entry?.boundary ?? (tool.name === "record_openspec_selection" ? params?.path : undefined) ?? (params?.endpoint ? `${params.endpoint.method}:${params.endpoint.path}` : undefined) ?? (singleton.has(tool.name) ? "singleton" : undefined);
|
|
114
|
+
const identity = `${tool.name}:${typeof naturalId === "string" ? naturalId : "incremental"}`;
|
|
115
|
+
const submissions = input.store.records.flatMap(r => r.submission?.receipt ? [r.submission] : []);
|
|
116
|
+
const previousCall = submissions.find(s => s.callId === callId);
|
|
117
|
+
if (previousCall)
|
|
118
|
+
return previousCall.tool === tool.name && previousCall.paramsSha256 === paramsSha256 ? replay(previousCall.receipt) : failure("REQUEST_ID_REUSE_CONFLICT", `${tool.name}: call id already acknowledged with different parameters`);
|
|
119
|
+
const previousFact = submissions.filter(s => s.identity === identity).at(-1);
|
|
120
|
+
if (isReviewFinding && !previousFact && params?.replace === true)
|
|
121
|
+
return failure("FACT_REPLACEMENT_NOT_FOUND", `${identity}: replacement requires an existing finding; omit replace to create it`);
|
|
122
|
+
if (tool.name !== "record_plan_group_coverage" && previousFact?.paramsSha256 === paramsSha256)
|
|
123
|
+
return replay(previousFact.receipt);
|
|
124
|
+
// A committed finalize terminal carries no domain payload in its params
|
|
125
|
+
// (r15: the model acknowledged with {replace:false}, the executor's
|
|
126
|
+
// auto-finalize sends {}) — both are acknowledgements of the same durable
|
|
127
|
+
// terminal, so any later finalize call replays the receipt instead of
|
|
128
|
+
// demanding a params match no caller can reproduce. Other singletons
|
|
129
|
+
// (state registry, data flows, ...) carry domain payloads and keep the
|
|
130
|
+
// replace:true correction path.
|
|
131
|
+
if (FINALIZE_TERMINAL_TOOLS.has(tool.name) && previousFact?.receipt)
|
|
132
|
+
return replay(previousFact.receipt);
|
|
133
|
+
if (previousFact && naturalId !== undefined && params?.replace !== true && !["record_evidence_expectation", "record_required_deliverables", "record_data_flow"].includes(tool.name))
|
|
134
|
+
return failure("FACT_IDENTITY_CONFLICT", `${identity}: changing a saved fact requires explicit replacement (replace:true)`);
|
|
135
|
+
if (input.store.records.some(r => ["contract-finalized", "finalize_plan", "finalize_decision", "approve_review", "request_review_changes", "approve_design", "request_design_changes"].includes(String(r.fact.kind))))
|
|
136
|
+
return failure("TERMINAL_CONFLICT", "A successful terminal is already durable; only identical acknowledged submissions may be replayed");
|
|
137
|
+
const draft = structuredClone(input.store);
|
|
138
|
+
input.setWorkingStore(draft);
|
|
139
|
+
let result;
|
|
140
|
+
try {
|
|
141
|
+
// Protocol controls must not be spread into domain facts by permissive callers.
|
|
142
|
+
const original = input.tools.find(t => t.name === tool.name);
|
|
143
|
+
const domainParams = { ...params };
|
|
144
|
+
if (!original.parameters.properties?.replace)
|
|
145
|
+
delete domainParams.replace;
|
|
146
|
+
result = await tool.execute(args[0], domainParams, ...args.slice(2));
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
input.setWorkingStore(input.store);
|
|
150
|
+
}
|
|
151
|
+
if (result.details?.ok !== true)
|
|
152
|
+
return result;
|
|
153
|
+
const newRecords = draft.records.filter(r => r.phase === "committed" && r.revision > input.store.revision);
|
|
154
|
+
if (!newRecords.length)
|
|
155
|
+
return replay(result);
|
|
156
|
+
for (const record of draft.records) {
|
|
157
|
+
record.submission ??= { version: 1, bindingSha256, tool: "bootstrap", callId: record.requestId, identity: record.eventId, paramsSha256: record.payloadSha256 };
|
|
158
|
+
}
|
|
159
|
+
for (const record of newRecords)
|
|
160
|
+
record.submission = { version: 1, bindingSha256, tool: tool.name, callId, identity, paramsSha256 };
|
|
161
|
+
newRecords.at(-1).submission.receipt = JSON.parse(JSON.stringify(result));
|
|
162
|
+
const committed = draft.records.filter(r => r.phase === "committed");
|
|
163
|
+
await validate(committed);
|
|
164
|
+
await persist(file, committed);
|
|
165
|
+
publish(draft);
|
|
166
|
+
progress.durableSubmissions++;
|
|
167
|
+
if (previousFact)
|
|
168
|
+
progress.durableReplacements++;
|
|
169
|
+
return result;
|
|
137
170
|
}
|
|
138
|
-
|
|
171
|
+
catch (error) {
|
|
139
172
|
input.setWorkingStore(input.store);
|
|
173
|
+
return failure(typeof error?.code === "string" ? error.code : "FRONTEND_COMMIT_FAILED", error instanceof Error ? error.message : String(error));
|
|
140
174
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
record.submission ??= { version: 1, bindingSha256, tool: "bootstrap", callId: record.requestId, identity: record.eventId, paramsSha256: record.payloadSha256 };
|
|
148
|
-
}
|
|
149
|
-
for (const record of newRecords)
|
|
150
|
-
record.submission = { version: 1, bindingSha256, tool: tool.name, callId, identity, paramsSha256 };
|
|
151
|
-
newRecords.at(-1).submission.receipt = JSON.parse(JSON.stringify(result));
|
|
152
|
-
const committed = draft.records.filter(r => r.phase === "committed");
|
|
153
|
-
await validate(committed);
|
|
154
|
-
await persist(file, committed);
|
|
155
|
-
publish(draft);
|
|
156
|
-
progress.durableSubmissions++;
|
|
157
|
-
if (previousFact)
|
|
158
|
-
progress.durableReplacements++;
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
input.setWorkingStore(input.store);
|
|
163
|
-
return failure(typeof error?.code === "string" ? error.code : "FRONTEND_COMMIT_FAILED", error instanceof Error ? error.message : String(error));
|
|
175
|
+
};
|
|
176
|
+
const result = await execute();
|
|
177
|
+
if (result.details?.ok !== true) {
|
|
178
|
+
progress.failedRecords++;
|
|
179
|
+
if (FINALIZE_TERMINAL_TOOLS.has(tool.name))
|
|
180
|
+
progress.finalizeRejections++;
|
|
164
181
|
}
|
|
165
|
-
|
|
166
|
-
|
|
182
|
+
const note = input.planControl?.observe(tool.name, args[1], result.details, input.store.revision > beforeRevision, input.planControl ? frontendPlanSemanticDigest(input.store.records) : undefined);
|
|
183
|
+
if (note)
|
|
184
|
+
return { ...result, content: [...(Array.isArray(result.content) ? result.content : []), { type: "text", text: JSON.stringify(note) }], details: { ...result.details, planProgress: note } };
|
|
185
|
+
return result;
|
|
186
|
+
}) }));
|
|
167
187
|
for (const tool of wrapped)
|
|
168
188
|
progressByTool.set(tool, progress);
|
|
169
189
|
return {
|