@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
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* Opt-in palettes. Repeat tokens at the Inspect boundary: it owns local defaults
|
|
2
|
+
* and is loaded after the Console stylesheet. Specificity keeps load order safe. */
|
|
3
|
+
:root[data-console-theme="midnight"],
|
|
4
|
+
:root[data-console-theme="midnight"] body[data-shell="observe-console"],
|
|
5
|
+
:root[data-console-theme="midnight"] .inspect-workspace-root {
|
|
6
|
+
color-scheme: dark;
|
|
7
|
+
--canvas: #1c222a;
|
|
8
|
+
--canvas-soft: #202730;
|
|
9
|
+
--surface: #252d37;
|
|
10
|
+
--surface-muted: #2d3641;
|
|
11
|
+
--ink: #dce2e9;
|
|
12
|
+
--surface-ink: #dce2e9;
|
|
13
|
+
--body: #bcc5d0;
|
|
14
|
+
--muted: #a1acba;
|
|
15
|
+
--muted-soft: #909eaf;
|
|
16
|
+
--muted-ink: #a1acba;
|
|
17
|
+
--hairline: #353f4b;
|
|
18
|
+
--hairline-strong: #526171;
|
|
19
|
+
--orange: #a0bcd3;
|
|
20
|
+
--orange-active: #b8cfe0;
|
|
21
|
+
--blue: #a0bcd3;
|
|
22
|
+
--brand: #b2aacb;
|
|
23
|
+
--theme-action: #4d6b86;
|
|
24
|
+
--theme-action-hover: #557590;
|
|
25
|
+
--theme-on-action: #ffffff;
|
|
26
|
+
--green: #99c5b0;
|
|
27
|
+
--amber: #d3b783;
|
|
28
|
+
--warn: #d3b783;
|
|
29
|
+
--red: #dea4ac;
|
|
30
|
+
--peach: #303e4d;
|
|
31
|
+
--mint: #2d403b;
|
|
32
|
+
--lavender: #393746;
|
|
33
|
+
--gold: #c3ac80;
|
|
34
|
+
--shadow-sm: 0 1px 2px rgb(0 0 0 / 12%);
|
|
35
|
+
--shadow-panel: 0 1px 2px rgb(0 0 0 / 12%), 0 6px 18px rgb(0 0 0 / 10%);
|
|
36
|
+
--shadow-soft: 0 8px 24px rgb(0 0 0 / 18%);
|
|
37
|
+
--shadow-lg: 0 16px 40px rgb(0 0 0 / 24%);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:root[data-console-theme="daylight"],
|
|
41
|
+
:root[data-console-theme="daylight"] body[data-shell="observe-console"],
|
|
42
|
+
:root[data-console-theme="daylight"] .inspect-workspace-root {
|
|
43
|
+
color-scheme: light;
|
|
44
|
+
--canvas: #eef0f2;
|
|
45
|
+
--canvas-soft: #f3f4f5;
|
|
46
|
+
--surface: #f9fafb;
|
|
47
|
+
--surface-muted: #e5e9ed;
|
|
48
|
+
--ink: #303b47;
|
|
49
|
+
--surface-ink: #303b47;
|
|
50
|
+
--body: #4b5867;
|
|
51
|
+
--muted: #5e6a78;
|
|
52
|
+
--muted-soft: #697583;
|
|
53
|
+
--muted-ink: #5e6a78;
|
|
54
|
+
--hairline: #dce1e6;
|
|
55
|
+
--hairline-strong: #b5bfc9;
|
|
56
|
+
--orange: #466581;
|
|
57
|
+
--orange-active: #365570;
|
|
58
|
+
--blue: #466581;
|
|
59
|
+
--brand: #706387;
|
|
60
|
+
--theme-action: #536f88;
|
|
61
|
+
--theme-action-hover: #466079;
|
|
62
|
+
--theme-on-action: #ffffff;
|
|
63
|
+
--green: #3e735d;
|
|
64
|
+
--amber: #85632d;
|
|
65
|
+
--warn: #85632d;
|
|
66
|
+
--red: #a04f5c;
|
|
67
|
+
--peach: #dfe7ee;
|
|
68
|
+
--mint: #e0eae4;
|
|
69
|
+
--lavender: #e7e3ed;
|
|
70
|
+
--gold: #927644;
|
|
71
|
+
--shadow-sm: 0 1px 2px rgb(35 45 58 / 4%);
|
|
72
|
+
--shadow-panel: 0 1px 2px rgb(35 45 58 / 3%), 0 6px 18px rgb(35 45 58 / 3%);
|
|
73
|
+
--shadow-soft: 0 8px 24px rgb(35 45 58 / 6%);
|
|
74
|
+
--shadow-lg: 0 16px 40px rgb(35 45 58 / 9%);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Only the two added themes override component literals; original warm paper
|
|
78
|
+
* remains byte-for-byte defined by its existing stylesheets. */
|
|
79
|
+
:root:is([data-console-theme="midnight"], [data-console-theme="daylight"]) {
|
|
80
|
+
--orange-soft: color-mix(in srgb, var(--orange) 10%, var(--surface));
|
|
81
|
+
background: var(--canvas);
|
|
82
|
+
|
|
83
|
+
body[data-shell="observe-console"], .inspect-workspace-root {
|
|
84
|
+
--orange-soft: color-mix(in srgb, var(--orange) 10%, var(--surface));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
::selection { background: color-mix(in srgb, var(--blue) 32%, var(--surface)); }
|
|
88
|
+
|
|
89
|
+
.oc-composer-shell, .console-update-channel, .console-update-button,
|
|
90
|
+
.panel-output { background: var(--surface); color: var(--ink); }
|
|
91
|
+
.console-update-channel, .console-update-button { border-color: var(--hairline-strong); }
|
|
92
|
+
.console-update-channel-label { color: var(--body); }
|
|
93
|
+
.console-update-error, .console-update-result-error { color: var(--red); }
|
|
94
|
+
.console-update-badge { background: var(--surface-muted); color: var(--amber); }
|
|
95
|
+
|
|
96
|
+
.oc-bubble-user { background: color-mix(in srgb, var(--blue) 9%, var(--surface)); }
|
|
97
|
+
.oc-composer-shell { box-shadow: var(--shadow-panel); }
|
|
98
|
+
.oc-bubble-assistant .oc-codeblock { background: var(--canvas-soft); }
|
|
99
|
+
.oc-session-scroll, .oc-tree-scroll { background: var(--canvas-soft); }
|
|
100
|
+
.oc-sidebar-new-session:is(:hover, :focus-visible),
|
|
101
|
+
.oc-hero-chip:is(:hover, :focus-visible, [aria-expanded="true"]) { background: var(--surface-muted); }
|
|
102
|
+
|
|
103
|
+
.night-health-pill, .models-status-pill[data-state="ready"],
|
|
104
|
+
.models-probe-item.is-ok .models-probe-badge {
|
|
105
|
+
background: color-mix(in srgb, var(--green) 14%, var(--surface));
|
|
106
|
+
}
|
|
107
|
+
.night-health-pill.is-bad, .models-status-pill[data-state="setup-required"],
|
|
108
|
+
.models-probe-item.is-bad .models-probe-badge, .dag-error-node {
|
|
109
|
+
background: color-mix(in srgb, var(--red) 12%, var(--surface));
|
|
110
|
+
}
|
|
111
|
+
.models-status-pill[data-state="degraded"], .models-degraded-note,
|
|
112
|
+
.dag-active-node { background: var(--orange-soft); }
|
|
113
|
+
.liveness-timeout-risk { background: color-mix(in srgb, var(--amber) 12%, var(--surface)); }
|
|
114
|
+
.night-strip-icon { color: var(--brand); }
|
|
115
|
+
|
|
116
|
+
/* Quiet selected surfaces keep navigation secondary to the content. */
|
|
117
|
+
.och-mode-thumb { background: var(--surface); box-shadow: var(--shadow-sm); }
|
|
118
|
+
.och-mode-btn.och-on { color: var(--ink); }
|
|
119
|
+
.dag-inspector-tab[aria-selected="true"],
|
|
120
|
+
.dag-graph-mode-tab[aria-selected="true"],
|
|
121
|
+
#dag-inspector-panel-prompt-restart button.prompt-restart-mode-option.is-selected {
|
|
122
|
+
background: var(--surface-muted);
|
|
123
|
+
color: var(--ink);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Accent text needs a different luminance from a white-labelled action. */
|
|
127
|
+
.btn-primary, button.btn-primary, .oc-send, .oc-question-button.is-primary,
|
|
128
|
+
.oc-scm-commitbtn, .skip-link, .dags-page-num.is-current,
|
|
129
|
+
.dag-action-primary, .context-export-submit,
|
|
130
|
+
#dag-inspector-panel-prompt-restart button.prompt-restart-submit:not(.is-secondary) {
|
|
131
|
+
background: var(--theme-action);
|
|
132
|
+
border-color: var(--theme-action);
|
|
133
|
+
color: var(--theme-on-action);
|
|
134
|
+
box-shadow: var(--shadow-sm);
|
|
135
|
+
}
|
|
136
|
+
.btn-primary:hover:not(:disabled), button.btn-primary:hover:not(:disabled),
|
|
137
|
+
.oc-send:hover:not(:disabled), .oc-question-button.is-primary:hover:not(:disabled),
|
|
138
|
+
.oc-scm-commitbtn:hover:not(:disabled), .dag-action-primary:hover:not(:disabled),
|
|
139
|
+
.context-export-submit:hover:not(:disabled),
|
|
140
|
+
#dag-inspector-panel-prompt-restart button.prompt-restart-submit:not(.is-secondary):hover {
|
|
141
|
+
background: var(--theme-action-hover);
|
|
142
|
+
border-color: var(--theme-action-hover);
|
|
143
|
+
}
|
|
144
|
+
.och-context-return, .process-timeline-autoscroll::after {
|
|
145
|
+
background: var(--surface-muted);
|
|
146
|
+
color: var(--ink);
|
|
147
|
+
}
|
|
148
|
+
.markdown-output pre, .output-block { background: var(--canvas-soft); color: var(--ink); }
|
|
149
|
+
.context-export-ticket { background: var(--surface-muted); color: var(--ink); }
|
|
150
|
+
.context-export-ticket-safety { color: var(--green); }
|
|
151
|
+
.context-export-ticket-safety.is-risk { color: var(--red); }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Syntax highlighting is independently hardcoded to a light palette. */
|
|
155
|
+
:root[data-console-theme="midnight"] {
|
|
156
|
+
/* The SVG brand uses dark strokes; provide a subtle light backing, not a filter. */
|
|
157
|
+
.och-brand-mark, .oc-hero img { background: #aebac7; border-radius: 6px; }
|
|
158
|
+
.hljs { color: var(--ink); background: var(--canvas-soft); }
|
|
159
|
+
.hljs-doctag, .hljs-keyword, .hljs-meta .hljs-keyword,
|
|
160
|
+
.hljs-template-tag, .hljs-template-variable, .hljs-type,
|
|
161
|
+
.hljs-variable.language_ { color: #c7afcf; }
|
|
162
|
+
.hljs-title, .hljs-title.class_, .hljs-title.class_.inherited__,
|
|
163
|
+
.hljs-title.function_ { color: #b9b3d1; }
|
|
164
|
+
.hljs-attr, .hljs-attribute, .hljs-literal, .hljs-meta, .hljs-number,
|
|
165
|
+
.hljs-operator, .hljs-selector-attr, .hljs-selector-class,
|
|
166
|
+
.hljs-selector-id, .hljs-variable, .hljs-section { color: var(--blue); }
|
|
167
|
+
.hljs-meta .hljs-string, .hljs-regexp, .hljs-string,
|
|
168
|
+
.hljs-name, .hljs-quote, .hljs-selector-pseudo, .hljs-selector-tag { color: var(--green); }
|
|
169
|
+
.hljs-built_in, .hljs-symbol, .hljs-bullet { color: var(--amber); }
|
|
170
|
+
.hljs-code, .hljs-comment, .hljs-formula { color: var(--muted); }
|
|
171
|
+
.hljs-subst, .hljs-emphasis, .hljs-strong { color: var(--ink); }
|
|
172
|
+
.hljs-addition { color: var(--green); background: var(--mint); }
|
|
173
|
+
.hljs-deletion { color: var(--red); background: color-mix(in srgb, var(--red) 12%, var(--surface)); }
|
|
174
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Shared Console theme identities; the default leaves the original palette intact. */
|
|
2
|
+
export const CONSOLE_THEMES = Object.freeze([
|
|
3
|
+
{ id: "default", label: "默认" },
|
|
4
|
+
{ id: "midnight", label: "深色" },
|
|
5
|
+
{ id: "daylight", label: "浅色" },
|
|
6
|
+
]);
|
|
7
|
+
|
|
8
|
+
const STORAGE_KEY = "loop-console.theme.v1";
|
|
9
|
+
|
|
10
|
+
function normalizeTheme(value) {
|
|
11
|
+
return CONSOLE_THEMES.some((theme) => theme.id === value) ? value : "default";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function applyStoredConsoleTheme() {
|
|
15
|
+
let value;
|
|
16
|
+
try {
|
|
17
|
+
value = window.localStorage.getItem(STORAGE_KEY);
|
|
18
|
+
} catch {
|
|
19
|
+
// Storage can be disabled, including the localStorage getter itself.
|
|
20
|
+
}
|
|
21
|
+
const theme = normalizeTheme(value);
|
|
22
|
+
document.documentElement.dataset.consoleTheme = theme;
|
|
23
|
+
return theme;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function setConsoleTheme(value) {
|
|
27
|
+
const theme = normalizeTheme(value);
|
|
28
|
+
// Apply before persistence: a storage failure must not disable the picker.
|
|
29
|
+
document.documentElement.dataset.consoleTheme = theme;
|
|
30
|
+
try {
|
|
31
|
+
window.localStorage.setItem(STORAGE_KEY, theme);
|
|
32
|
+
} catch {
|
|
33
|
+
// The document attribute remains the in-memory preference.
|
|
34
|
+
}
|
|
35
|
+
return theme;
|
|
36
|
+
}
|
|
@@ -8,6 +8,84 @@
|
|
|
8
8
|
* 的暖白 token 保持一致;宿主样式表已定义同名变量时以宿主为准。
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
@import "./console-theme.css";
|
|
12
|
+
|
|
13
|
+
.och-theme {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 6px;
|
|
17
|
+
flex: none;
|
|
18
|
+
color: var(--och-muted);
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.och-theme-trigger {
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
width: 26px;
|
|
27
|
+
min-height: 26px;
|
|
28
|
+
padding: 0;
|
|
29
|
+
border: 1px solid transparent;
|
|
30
|
+
border-radius: 6px;
|
|
31
|
+
background: transparent;
|
|
32
|
+
color: var(--och-body);
|
|
33
|
+
font: inherit;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.och-theme-trigger:hover,
|
|
38
|
+
.och-theme-trigger[aria-expanded="true"] {
|
|
39
|
+
background: var(--och-surface-muted);
|
|
40
|
+
color: var(--och-ink);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.och-theme-trigger:focus-visible,
|
|
44
|
+
.och-theme-option:focus-visible {
|
|
45
|
+
outline: 2px solid var(--och-orange);
|
|
46
|
+
outline-offset: 2px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Native popover renders in the top layer, outside the narrow header's clip. */
|
|
50
|
+
.och-theme-menu {
|
|
51
|
+
position: fixed;
|
|
52
|
+
inset: auto;
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
width: 112px;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 4px;
|
|
57
|
+
border: 1px solid var(--och-hairline);
|
|
58
|
+
border-radius: 8px;
|
|
59
|
+
background: var(--och-surface);
|
|
60
|
+
color: var(--och-ink);
|
|
61
|
+
box-shadow: var(--shadow-soft);
|
|
62
|
+
font: inherit;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.och-theme-option {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
justify-content: space-between;
|
|
69
|
+
width: 100%;
|
|
70
|
+
min-height: 28px;
|
|
71
|
+
padding: 4px 8px;
|
|
72
|
+
border: 0;
|
|
73
|
+
border-radius: 4px;
|
|
74
|
+
background: transparent;
|
|
75
|
+
color: inherit;
|
|
76
|
+
font: inherit;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.och-theme-option:hover,
|
|
81
|
+
.och-theme-option[aria-pressed="true"] {
|
|
82
|
+
background: var(--och-surface-muted);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.och-theme-option[aria-pressed="true"]::after {
|
|
86
|
+
content: "✓";
|
|
87
|
+
}
|
|
88
|
+
|
|
11
89
|
.och {
|
|
12
90
|
--och-canvas: var(--canvas, #f3f4f6);
|
|
13
91
|
--och-surface: var(--surface, #fbfcfd);
|
|
@@ -622,7 +700,14 @@
|
|
|
622
700
|
.och-inner {
|
|
623
701
|
padding-inline: 12px;
|
|
624
702
|
}
|
|
703
|
+
.och-theme {
|
|
704
|
+
position: absolute;
|
|
705
|
+
top: 46px;
|
|
706
|
+
right: 0;
|
|
707
|
+
}
|
|
625
708
|
.och-global {
|
|
709
|
+
height: 84px;
|
|
710
|
+
padding-bottom: 40px;
|
|
626
711
|
gap: 6px;
|
|
627
712
|
overflow-x: auto;
|
|
628
713
|
scrollbar-width: none;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { withWorkspaceQuery } from "./router.js";
|
|
15
|
+
import { CONSOLE_THEMES, applyStoredConsoleTheme, setConsoleTheme } from "./console-theme.js";
|
|
16
|
+
export { CONSOLE_THEMES } from "./console-theme.js";
|
|
15
17
|
|
|
16
18
|
export const OPERATE_TABS = Object.freeze([
|
|
17
19
|
{ id: "tasks", label: "任务", href: "/#/operate/tasks" },
|
|
@@ -296,6 +298,13 @@ export function buildOperatorChromeModel(config) {
|
|
|
296
298
|
|
|
297
299
|
const SVG_NS = "http:" + "//www.w3.org/2000/svg";
|
|
298
300
|
const ICONS = Object.freeze({
|
|
301
|
+
theme: {
|
|
302
|
+
size: 16,
|
|
303
|
+
parts: [
|
|
304
|
+
["circle", { cx: 12, cy: 12, r: 9 }],
|
|
305
|
+
["path", { d: "M12 3a9 9 0 0 1 0 18Z", fill: "currentColor", stroke: "none" }],
|
|
306
|
+
],
|
|
307
|
+
},
|
|
299
308
|
radar: {
|
|
300
309
|
size: 17,
|
|
301
310
|
parts: [
|
|
@@ -426,6 +435,7 @@ function readWorkspaceCollapsedPref() {
|
|
|
426
435
|
export function mountOperatorChrome(root, config = {}) {
|
|
427
436
|
if (!root) throw new Error("mountOperatorChrome: root element is required");
|
|
428
437
|
root.classList.add("och-host");
|
|
438
|
+
if (!document.documentElement.dataset.consoleTheme) applyStoredConsoleTheme();
|
|
429
439
|
|
|
430
440
|
let currentConfig = { ...config };
|
|
431
441
|
let popoverOpen = false;
|
|
@@ -701,6 +711,47 @@ export function mountOperatorChrome(root, config = {}) {
|
|
|
701
711
|
|
|
702
712
|
global.appendChild(el("span", "och-spacer"));
|
|
703
713
|
|
|
714
|
+
const themePicker = el("div", "och-theme");
|
|
715
|
+
const trigger = el("button", "och-theme-trigger");
|
|
716
|
+
trigger.type = "button";
|
|
717
|
+
trigger.title = "主题";
|
|
718
|
+
trigger.setAttribute("aria-label", "主题");
|
|
719
|
+
trigger.appendChild(makeIcon("theme"));
|
|
720
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
721
|
+
const menu = el("div", "och-theme-menu");
|
|
722
|
+
menu.id = `${popoverId}-theme`;
|
|
723
|
+
menu.popover = "auto";
|
|
724
|
+
menu.setAttribute("role", "group");
|
|
725
|
+
menu.setAttribute("aria-label", "选择主题");
|
|
726
|
+
trigger.setAttribute("aria-controls", menu.id);
|
|
727
|
+
trigger.popoverTargetElement = menu;
|
|
728
|
+
menu.addEventListener("beforetoggle", (event) => {
|
|
729
|
+
if (event.newState !== "open") return;
|
|
730
|
+
const rect = trigger.getBoundingClientRect();
|
|
731
|
+
menu.style.top = `${rect.bottom + 6}px`;
|
|
732
|
+
menu.style.left = `${Math.max(8, Math.min(rect.right - 112, window.innerWidth - 120))}px`;
|
|
733
|
+
});
|
|
734
|
+
menu.addEventListener("toggle", (event) => {
|
|
735
|
+
trigger.setAttribute("aria-expanded", String(event.newState === "open"));
|
|
736
|
+
});
|
|
737
|
+
for (const theme of CONSOLE_THEMES) {
|
|
738
|
+
const option = el("button", "och-theme-option", theme.label);
|
|
739
|
+
option.type = "button";
|
|
740
|
+
option.dataset.theme = theme.id;
|
|
741
|
+
option.setAttribute("aria-pressed", String(theme.id === (document.documentElement.dataset.consoleTheme ?? "default")));
|
|
742
|
+
option.addEventListener("click", () => {
|
|
743
|
+
setConsoleTheme(theme.id);
|
|
744
|
+
for (const item of menu.children) {
|
|
745
|
+
item.setAttribute("aria-pressed", String(item.dataset.theme === theme.id));
|
|
746
|
+
}
|
|
747
|
+
menu.hidePopover();
|
|
748
|
+
trigger.focus();
|
|
749
|
+
});
|
|
750
|
+
menu.appendChild(option);
|
|
751
|
+
}
|
|
752
|
+
themePicker.append(trigger, menu);
|
|
753
|
+
global.appendChild(themePicker);
|
|
754
|
+
|
|
704
755
|
if (model.statusVisible && model.freshness) {
|
|
705
756
|
const fresh = el("span", "och-fresh");
|
|
706
757
|
fresh.setAttribute("aria-label", "数据新鲜度");
|
|
@@ -69,10 +69,11 @@ export async function prepareScheduledGoalDraft(input, client) {
|
|
|
69
69
|
if (!assessment.ok)
|
|
70
70
|
throw new Error(`scheduled goal ineligible: ${assessment.reason}`);
|
|
71
71
|
const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
72
|
+
const repositoryPath = (file) => path.relative(root, file).split(path.sep).join("/");
|
|
72
73
|
return scheduledGoalDraftSchema.parse({ ...parsed, controllerRef: identity.packageFingerprint.value,
|
|
73
74
|
prepared: { gateToken: `${snapshot.gate.id}:${snapshot.gate.digest}`,
|
|
74
|
-
dagPath:
|
|
75
|
-
contractPath:
|
|
75
|
+
dagPath: repositoryPath(paths.dagDraftPath), dagHash: digest(dagBytes),
|
|
76
|
+
contractPath: repositoryPath(paths.taskConfigPath), contractHash: digest(configBytes) }, });
|
|
76
77
|
}
|
|
77
78
|
/** Materialize only contract/runtime inputs; execution remains owned by the operation host. */
|
|
78
79
|
export async function prepareDerivedScheduledGoalTask(goalId, ownerToken, goals, client) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { execFile } from "node:child_process";
|
|
2
|
+
import { execFile, spawn } from "node:child_process";
|
|
3
3
|
import { promisify } from "node:util";
|
|
4
4
|
import { lstat, readFile, readlink, realpath } from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
@@ -7,6 +7,59 @@ import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
|
7
7
|
import { scheduledGoalDraftSchema } from "./scheduled-goal-types.js";
|
|
8
8
|
const execFileAsync = promisify(execFile);
|
|
9
9
|
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
10
|
+
/** Working-copy paths that are plain files, so Git can read them back. */
|
|
11
|
+
async function plainFileNames(root, names) {
|
|
12
|
+
const plain = [];
|
|
13
|
+
for (const name of names) {
|
|
14
|
+
const info = await lstat(path.resolve(root, name)).catch(() => undefined);
|
|
15
|
+
if (info?.isFile())
|
|
16
|
+
plain.push(name);
|
|
17
|
+
}
|
|
18
|
+
return plain;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Repository-form blob IDs for working-copy files, computed by Git itself so
|
|
22
|
+
* that `core.autocrlf` and `eol` attributes normalize exactly as a commit
|
|
23
|
+
* would. Hashing never consults the index, so staged-only and
|
|
24
|
+
* `assume-unchanged` paths keep their raw-byte meaning. A failure degrades to
|
|
25
|
+
* the caller's raw-byte blob, which can only over-report change, never hide it;
|
|
26
|
+
* `--stdin-paths` cannot carry names containing a newline.
|
|
27
|
+
*/
|
|
28
|
+
async function gitNormalizedBlobIds(root, names) {
|
|
29
|
+
const ids = new Map();
|
|
30
|
+
const candidates = names.filter((name) => !name.includes("\n"));
|
|
31
|
+
if (candidates.length === 0)
|
|
32
|
+
return ids;
|
|
33
|
+
let stdout;
|
|
34
|
+
try {
|
|
35
|
+
stdout = await new Promise((resolve, reject) => {
|
|
36
|
+
const child = spawn("git", ["-C", root, "hash-object", "--stdin-paths"], { stdio: ["pipe", "pipe", "pipe"] });
|
|
37
|
+
let output = "";
|
|
38
|
+
let failure = "";
|
|
39
|
+
child.stdout.setEncoding("utf8");
|
|
40
|
+
child.stdout.on("data", (chunk) => { output += chunk; });
|
|
41
|
+
child.stderr.setEncoding("utf8");
|
|
42
|
+
child.stderr.on("data", (chunk) => { failure += chunk; });
|
|
43
|
+
child.on("error", reject);
|
|
44
|
+
child.on("close", (code) => {
|
|
45
|
+
if (code === 0)
|
|
46
|
+
resolve(output);
|
|
47
|
+
else
|
|
48
|
+
reject(new Error(`git hash-object failed: ${failure.trim()}`));
|
|
49
|
+
});
|
|
50
|
+
child.stdin.end(`${candidates.join("\n")}\n`);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return ids;
|
|
55
|
+
}
|
|
56
|
+
const hashes = stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
57
|
+
if (hashes.length !== candidates.length)
|
|
58
|
+
return ids;
|
|
59
|
+
for (let index = 0; index < candidates.length; index += 1)
|
|
60
|
+
ids.set(candidates[index], hashes[index]);
|
|
61
|
+
return ids;
|
|
62
|
+
}
|
|
10
63
|
/** Run only frozen AC commands. A timeout is uncertain execution, never a passing or repairable failure. */
|
|
11
64
|
export async function evaluateScheduledGoalCriteria(frozen, options = {}) {
|
|
12
65
|
frozen = scheduledGoalDraftSchema.pick({ worktreeRef: true, frozenBase: true, allowedPaths: true, forbiddenPaths: true, acceptance: true, time: true }).strip().parse(frozen);
|
|
@@ -115,6 +168,11 @@ export async function captureScheduledGoalTree(worktree, base, allowedPaths, for
|
|
|
115
168
|
const blobId = (bytes) => createHash(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
|
|
116
169
|
const names = [...new Set([...entries(tracked), ...entries(untracked), ...baseEntries.keys()])].sort();
|
|
117
170
|
const deliveryNames = new Set(names);
|
|
171
|
+
// Compare content identity through Git's own normalization: a working copy
|
|
172
|
+
// materialized with `core.autocrlf` (or an `eol` attribute) is stored as LF
|
|
173
|
+
// while the checkout is CRLF, and raw bytes would report that as drift on
|
|
174
|
+
// every text file.
|
|
175
|
+
const normalizedIds = await gitNormalizedBlobIds(root, await plainFileNames(root, names));
|
|
118
176
|
const files = [];
|
|
119
177
|
const changedPaths = [];
|
|
120
178
|
for (const name of names) {
|
|
@@ -143,8 +201,13 @@ export async function captureScheduledGoalTree(worktree, base, allowedPaths, for
|
|
|
143
201
|
}
|
|
144
202
|
else if (stat.isFile()) {
|
|
145
203
|
const bytes = await readFile(target);
|
|
146
|
-
|
|
147
|
-
|
|
204
|
+
actualId = normalizedIds.get(name) ?? blobId(bytes);
|
|
205
|
+
files.push({
|
|
206
|
+
name,
|
|
207
|
+
kind: "file",
|
|
208
|
+
hash: sha256(`${objectFormat}:${actualId}`),
|
|
209
|
+
executable: Boolean(stat.mode & 0o111),
|
|
210
|
+
});
|
|
148
211
|
actualMode = stat.mode & 0o111 ? "100755" : "100644";
|
|
149
212
|
}
|
|
150
213
|
else
|
|
@@ -16,6 +16,16 @@ async function syncDirectory(directoryPath) {
|
|
|
16
16
|
try {
|
|
17
17
|
await directory.sync();
|
|
18
18
|
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
// The file body is already durable from the file-level fsync above.
|
|
21
|
+
// Windows refuses to flush a directory handle (EPERM) and some
|
|
22
|
+
// filesystems reject the call outright, so a directory-only failure must
|
|
23
|
+
// not abort a transaction whose data is already on disk.
|
|
24
|
+
const code = error.code;
|
|
25
|
+
if (code !== "EPERM" && code !== "EACCES" && code !== "EINVAL"
|
|
26
|
+
&& code !== "ENOTSUP" && code !== "EOPNOTSUPP" && code !== "ENOSYS")
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
19
29
|
finally {
|
|
20
30
|
await directory.close();
|
|
21
31
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { checkBudgetPreNode, createBudgetLedger, formatBudgetReportMarkdown, isHardBudgetBreached, recordNodeBudgetSample, reserveProviderBudget, skipPendingNodesForBudgetBreach, } from "../../application/evaluation/budget.js";
|
|
3
|
+
import { campaignBudgetSchema, checkBudgetPreNode, createBudgetLedger, formatBudgetReportMarkdown, isHardBudgetBreached, recordNodeBudgetSample, reserveProviderBudget, skipPendingNodesForBudgetBreach, } from "../../application/evaluation/budget.js";
|
|
4
4
|
import { sha256OfCanonicalJson } from "../../task/contract/hash.js";
|
|
5
5
|
/** A continuation already contains its ancestors' consumption. Never sum both. */
|
|
6
6
|
export function validateCumulativeBudgetSuccessor(parent, child) {
|
|
@@ -9,9 +9,33 @@ export function validateCumulativeBudgetSuccessor(parent, child) {
|
|
|
9
9
|
const next = child.budgetLedger;
|
|
10
10
|
if (!previous || !next || !lineage || (child.continuation?.parentRunId ?? child.frontendRecoveryState?.parentRunId) !== parent.runId || lineage.parentLedgerSha256 !== sha256OfCanonicalJson(previous) || sha256OfCanonicalJson(lineage.inheritedConsumed) !== sha256OfCanonicalJson(previous.consumed) || sha256OfCanonicalJson(parent.budget ?? null) !== sha256OfCanonicalJson(child.budget ?? null))
|
|
11
11
|
throw Error("FRONTEND_PROVIDER_BUDGET_LINEAGE_INVALID: unbound cumulative continuation");
|
|
12
|
+
const invalid = (reason) => { throw Error(`FRONTEND_PROVIDER_BUDGET_LINEAGE_INVALID: ${reason}`); };
|
|
13
|
+
for (const [state, ledger] of [[parent, previous], [child, next]]) {
|
|
14
|
+
const parsed = campaignBudgetSchema.safeParse(state.budget);
|
|
15
|
+
if (!parsed.success || ledger.schemaVersion !== 1 || ledger.mode !== parsed.data.mode || sha256OfCanonicalJson(ledger.limits) !== sha256OfCanonicalJson(parsed.data.limits))
|
|
16
|
+
invalid("ledger differs from frozen budget");
|
|
17
|
+
const count = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
18
|
+
for (const key of ["executorCalls", "wallTimeMs", "repairPasses", "peakContextChars"])
|
|
19
|
+
if (!count(ledger.consumed[key]))
|
|
20
|
+
invalid("invalid consumption");
|
|
21
|
+
if (ledger.consumed.tokens !== null && !count(ledger.consumed.tokens))
|
|
22
|
+
invalid("invalid token consumption");
|
|
23
|
+
if ((ledger.mode === "hard" && ledger.limits.maxProviderRequests !== undefined || ledger.consumed.providerRequests !== undefined) && !count(ledger.consumed.providerRequests))
|
|
24
|
+
invalid("invalid request consumption");
|
|
25
|
+
if (!Array.isArray(ledger.consumed.missingTokenNodeIds) || ledger.consumed.missingTokenNodeIds.some(id => typeof id !== "string" || !id))
|
|
26
|
+
invalid("invalid missing token records");
|
|
27
|
+
if (!Array.isArray(ledger.breaches) || (ledger.mode === "record-only" ? ledger.status !== "record-only" : !["ok", "breached"].includes(ledger.status)))
|
|
28
|
+
invalid("invalid ledger status");
|
|
29
|
+
}
|
|
12
30
|
for (const key of ["executorCalls", "providerRequests", "wallTimeMs", "repairPasses", "peakContextChars"])
|
|
13
31
|
if ((next.consumed[key] ?? 0) < (previous.consumed[key] ?? 0))
|
|
14
|
-
|
|
32
|
+
invalid("consumption decreased");
|
|
33
|
+
if (previous.consumed.tokens !== null && (next.consumed.tokens === null || next.consumed.tokens < previous.consumed.tokens))
|
|
34
|
+
invalid("token consumption decreased");
|
|
35
|
+
if (previous.consumed.missingTokenNodeIds.some(id => !next.consumed.missingTokenNodeIds.includes(id)))
|
|
36
|
+
invalid("missing token records lost");
|
|
37
|
+
if (previous.status === "breached" && next.status !== "breached" || previous.breaches.some(breach => !next.breaches.some(value => sha256OfCanonicalJson(value) === sha256OfCanonicalJson(breach))))
|
|
38
|
+
invalid("budget breach lost");
|
|
15
39
|
return next;
|
|
16
40
|
}
|
|
17
41
|
const requestQueues = new WeakMap();
|
|
@@ -27,6 +51,11 @@ export async function reserveDagProviderRequest(input) {
|
|
|
27
51
|
throw Error("FRONTEND_PROVIDER_BUDGET_STALE: request belongs to an inactive attempt");
|
|
28
52
|
if (isHardBudgetBreached(ledger))
|
|
29
53
|
throw Error("FRONTEND_PROVIDER_BUDGET_EXHAUSTED: run budget already breached");
|
|
54
|
+
if ((ledger.consumed.providerRequests ?? 0) < ledger.limits.maxProviderRequests && input.reserveTaskRequest) {
|
|
55
|
+
await input.reserveTaskRequest();
|
|
56
|
+
if (!active())
|
|
57
|
+
throw Error("FRONTEND_PROVIDER_BUDGET_STALE: attempt stopped during task reservation");
|
|
58
|
+
}
|
|
30
59
|
const breach = reserveProviderBudget(ledger, input.nodeId);
|
|
31
60
|
if (breach)
|
|
32
61
|
applyHardBudgetBreach(input.state, breach);
|