@tea-agent/loop-agent 0.43.0-next.8 → 0.43.0
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 +41 -2312
- package/README.md +7 -0
- package/dist/application/dag/args.js +8 -0
- package/dist/application/task-lifecycle/advance.js +38 -7
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +2 -0
- package/dist/cli/program.js +3 -1
- package/dist/cli/update/init-surface-notifier.js +2 -0
- package/dist/cli/update/policy.js +2 -0
- package/dist/commands/client-recovery.js +20 -55
- package/dist/commands/cursor-prompt.js +2 -0
- package/dist/commands/dag-approve.js +2 -0
- package/dist/commands/dag-final-verification.js +2 -0
- package/dist/commands/dag-init-hybrid.js +2 -0
- package/dist/commands/dag-reconcile-tasks.js +2 -0
- package/dist/commands/dag-reject.js +2 -0
- package/dist/commands/dag-report.js +2 -0
- package/dist/commands/dag-rerun.js +2 -0
- package/dist/commands/dag-resume.js +2 -0
- package/dist/commands/dag-workflow-compile.js +2 -0
- package/dist/commands/dag-workflow-plan.js +2 -0
- package/dist/commands/dag-workflow-validate.js +2 -0
- package/dist/commands/delegate.js +2 -0
- package/dist/commands/examples.js +2 -0
- package/dist/commands/import-prd.js +2 -0
- package/dist/commands/init-model-catalog.js +2 -0
- package/dist/commands/init.js +19 -13
- package/dist/commands/instructions.js +2 -0
- package/dist/commands/knowledge.js +2 -0
- package/dist/commands/loop-benchmark.js +2 -0
- package/dist/commands/pi-prompt.js +2 -0
- package/dist/commands/pi-reuse-benchmark.js +2 -0
- package/dist/commands/promote-run.js +2 -0
- package/dist/commands/stats.js +1 -1
- package/dist/commands/study-init.js +2 -0
- package/dist/commands/task-advance.js +34 -0
- package/dist/commands/task-source-prepare.js +2 -0
- package/dist/commands/worktree-create.js +2 -0
- package/dist/commands/worktree-remove.js +2 -0
- package/dist/executors/dag-pi-executor.js +1650 -198
- package/dist/executors/pi-executor.js +85 -3
- package/dist/executors/pi-sdk-executor.js +18 -0
- package/dist/executors/shell-executor.js +93 -7
- package/dist/executors/shell-verification.js +3 -0
- package/dist/executors/shell-write-guard.js +27 -32
- package/dist/governance/exec-plans.js +6 -3
- package/dist/infrastructure/console/app-data.js +6 -0
- package/dist/shared/artifacts-core.js +2 -0
- package/dist/shared/backend-dogfood-preflight.js +47 -0
- package/dist/shared/dag-failure-category.js +3 -0
- package/dist/shared/git-progress.js +2 -0
- package/dist/shared/one-shot-prompt-args.js +2 -0
- package/dist/shared/operator/capabilities.js +180 -0
- package/dist/shared/package-metadata.js +6 -4
- package/dist/shared/pi-context-pressure/extension.js +26 -16
- package/dist/shared/pi-context-pressure/sift-bridge.js +1 -1
- package/dist/shared/pi-provider-recovery.js +182 -0
- package/dist/shared/pi-retry-settings.js +40 -0
- package/dist/shared/reference-context.js +2 -0
- package/dist/task/config-types.js +29 -0
- package/dist/task/contract/project.js +9 -0
- package/dist/task/contract/recover.js +6 -0
- package/dist/task/contract/schema.js +17 -0
- package/dist/task/source-prepare/artifact-meta.js +9 -2
- package/dist/task/source-prepare/build-draft.js +60 -0
- package/dist/task/source-prepare/fragment-inventory.js +4 -1
- package/dist/task/source-prepare/parse-intent.js +36 -11
- package/dist/task/task-demand-routing.js +5 -2
- package/dist/worker/console/chat/browser-automation.js +523 -0
- package/dist/worker/console/chat/browser-policy.js +6 -36
- package/dist/worker/console/chat/browser-routes.js +188 -56
- package/dist/worker/console/chat/explore-tools.js +5 -2
- package/dist/worker/console/chat/pi-mode-loop-isolation.js +155 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/ask-user-question.js +44 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/browser-tools.js +184 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/explore-tools.js +202 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/goal-tools.js +79 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/operator-tools.js +94 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/scheduled-goal-tools.js +22 -0
- package/dist/worker/console/chat/pi-runtime/custom-tools/todo-write.js +38 -0
- package/dist/worker/console/chat/pi-runtime/inspection-types.js +28 -0
- package/dist/worker/console/chat/pi-runtime/inspection.js +439 -0
- package/dist/worker/console/chat/pi-runtime/progressive-tools.js +195 -0
- package/dist/worker/console/chat/pi-runtime/sdk-bindings.js +153 -0
- package/dist/worker/console/chat/pi-runtime/sdk-session.js +5 -0
- package/dist/worker/console/chat/pi-runtime.js +208 -1138
- package/dist/worker/console/chat/routes.js +59 -24
- package/dist/worker/console/chat/scheduled-goal-booking.js +59 -0
- package/dist/worker/console/chat/scheduled-goal-delivery.js +27 -0
- package/dist/worker/console/chat/scheduled-goal-request.js +190 -0
- package/dist/worker/console/chat/sdd-data-alignment.js +1 -1
- package/dist/worker/console/chat/session-mode-view.js +5 -4
- package/dist/worker/console/chat/session-mode.js +18 -12
- package/dist/worker/console/chat/session-store.js +42 -9
- package/dist/worker/console/chat/terminal-sessions.js +65 -1
- package/dist/worker/console/chat/terminal-tools.js +17 -5
- package/dist/worker/console/chat/tool-preview.js +115 -0
- package/dist/worker/console/chat/tools.js +10 -0
- package/dist/worker/console/chat/turn-order.js +13 -0
- package/dist/worker/console/chat/turn-process.js +32 -30
- package/dist/worker/console/console-update-and-init.js +1 -19
- package/dist/worker/console/console-update-runtime.js +5 -20
- package/dist/worker/console/operator-actions.js +63 -1
- package/dist/worker/console/prd-intake-bridge.js +54 -1
- package/dist/worker/console/routes.js +8 -0
- package/dist/worker/console/scheduled-goal-host.js +98 -0
- package/dist/worker/console/scheduled-goal-operation-adapter.js +127 -0
- package/dist/worker/console/server.js +24 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CwAxHSAM.js → abnfDiagram-N423BO3Z-8-j6y-sd.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Bozf-oeF.js → arc-eoQiMvuk.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DEypbEQv.js → architectureDiagram-T3A2C74G-C4A3uMcI.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-B1BQWCbE.js → blockDiagram-VBNYF7ZC-D4zD2F-Q.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B3u5-yZz.js → c4Diagram-5PPSVZJV-j1RkJziL.js} +1 -1
- package/dist/worker/console/static/assets/channel-ChE7y-cx.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DSUc2NTh.js → chunk-2GRJ4B5K-YBHmhik1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DZouMIvT.js → chunk-2Q5K7J3B-COfWyo9P.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-B3bhB5hh.js → chunk-5RXB4S5H-I99OUkHY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CZFP_BOz.js → chunk-5VM5RSS4-XKxoJNJ4.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DnE_wb-X.js → chunk-6Q2QTUOP-DLT_cYx1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C2OfoiWm.js → chunk-GF5L2VYU-CxcKZ9mV.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BKUTL8mm.js → chunk-JWPE2WC7-V1EqXdjY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BT5oz0tg.js → chunk-KBJHAD2P-DebTtdFp.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-D8vk-GJi.js → chunk-RYQCIY6F-B-ivNRDf.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CkUIm3zu.js → chunk-XXDRQBXY-DC_Ds11b.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C01TCf2X.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C01TCf2X.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CO9QNHmR.js → cose-bilkent-JH36ORCC-sWEqKwIb.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-s52EPl2Z.js → cynefin-VYW2F7L2-BXa_dcu4.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BHaseJfW.js → cynefinDiagram-MW4NZA55-C-Mle84F.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CTVhRG_R.js → dagre-VZM6K2ZE-CXPDBITe.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B6pYeOMR.js → diagram-7IWD3JNH-CC-WJQfa.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CXXRzw5j.js → diagram-B4RE2ZJO-CDAV5Vs4.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BOeJHiLA.js → diagram-LBJQPF4R-CmFiAcNz.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DbEg6h_l.js → diagram-Q27KOJAE-DPBZHuyn.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-CjlEcbX6.js → diagram-UB23O5K3-jUlm_Ds3.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BcqMPbD_.js → ebnfDiagram-BXEA7PRR-DWhQ3mfY.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DWfRyHe5.js → erDiagram-JOGREHBK-Tr2gMqet.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-Bz7TeIc8.js → flowDiagram-UKHOOZJN-DJjVQHPA.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BD-JxYjU.js → ganttDiagram-PKOTCBZU-D74dQ4u0.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Cv16vMHK.js → gitGraphDiagram-DS77QQ5N-DwW0tZ0X.js} +1 -1
- package/dist/worker/console/static/assets/index-BWkIfcrK.css +1 -0
- package/dist/worker/console/static/assets/index-Cdkvw_H6.js +469 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BlWO0HQQ.js → infoDiagram-6WML65LV-ILCbxJyb.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-C4mbsn97.js → ishikawaDiagram-WSZJBQD7-DeuWBQ89.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-CBPvVKjw.js → journeyDiagram-NVQOT4AX-CF5ih8Fk.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DPHLp54K.js → kanban-definition-27J2QSJJ-C7yOSuRO.js} +1 -1
- package/dist/worker/console/static/assets/{linear-CXx_9o6k.js → linear-BDZ9riWi.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DU3IxMq9.js → mermaid.core-7pKqYtpZ.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-COm4a2ud.js → mindmap-definition-FAOFIHXS-LeJDybSU.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Cbt7OA5d.js → pegDiagram-VL7TDLO6-BJvT3pMD.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BiYV_4Wl.js → pieDiagram-7S7Q4E2Y-_rGqpMan.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-lg2zhvbp.js → quadrantDiagram-CIZ2JOQS-DPcSv5aA.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-cBLvtf0p.js → railroadDiagram-AXF67PYL-Drxx4hkJ.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-BoekU3Bg.js → requirementDiagram-LRYGKXZP-BCTUdU4z.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-D_DMZYga.js → sankeyDiagram-W5VNT64P-B6wzbZmB.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-Lzmzn8lz.js → sequenceDiagram-SI44F4Z6-BGt8d3QQ.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-Cos3HpIe.js → sizeCapture-X5ZJPWSS-7nlhJKo7.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-D-hFBGsx.js → stateDiagram-OKZ733FA-Cv2stqMA.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DC7V5vcq.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BY95sCVI.js → swimlanes-SLNWSIFB-qDAo4Yc1.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Bwy4QUTO.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-D1iCgWHS.js → timeline-definition-Z64GVDOM-CKbDNKTr.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D9IYy4WK.js → vennDiagram-T6HMQDX7-DI-9EHic.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-C9yJwO-R.js → wardleyDiagram-T6FBY63Y-BrzzRDpX.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CC2llyou.js → xychartDiagram-ELKLHX3M-BclH5hGh.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/active-turn-tail.js +10 -0
- package/dist/worker/console/static-src/operator-chat/chat-scroll-position.js +24 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +41 -11
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +10 -17
- package/dist/worker/console/static-src/operator-chat/composer-session-ledger.js +192 -0
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +9 -1
- package/dist/worker/console/static-src/operator-chat/slash-palette-nav.js +15 -5
- package/dist/worker/console/static-src/operator-chat/timeline-merge.js +29 -0
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +10 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +105 -44
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +145 -70
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +38 -57
- package/dist/worker/console/static-src/operator-chat/useComposer.js +195 -73
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +2 -0
- package/dist/worker/console/static-src/prd-file-import.js +3 -1
- package/dist/worker/console/workspace-context.js +22 -0
- package/dist/worker/console/workspace-initialization.js +209 -0
- package/dist/worker/delivery/git-transaction.js +2 -0
- package/dist/worker/feature/fullstack-validate.js +2 -0
- package/dist/worker/loop-agent/loop-agent-client.js +8 -2
- package/dist/worker/materialize/harness-task-materializer.js +4 -1
- package/dist/worker/metrics/projector.js +1 -1
- package/dist/worker/observability/event-store.js +4 -1
- package/dist/worker/observability/read-model.js +4 -1
- package/dist/worker/observe/node-transparency.js +23 -1
- package/dist/worker/observe/routes.js +4 -0
- package/dist/worker/observe/static/operator-chrome.js +3 -1
- package/dist/worker/observe/static/styles.css +7 -4
- package/dist/worker/observe/static/views/dag-inspector.js +5 -19
- package/dist/worker/outcomes/declared-artifacts.js +2 -0
- package/dist/worker/preflight.js +3 -0
- package/dist/worker/scheduler/scheduled-goal-dispatch.js +117 -0
- package/dist/worker/scheduler/scheduled-goal-evidence.js +167 -0
- package/dist/worker/scheduler/scheduled-goal-recovery.js +62 -0
- package/dist/worker/scheduler/scheduled-goal-store.js +699 -0
- package/dist/worker/scheduler/scheduled-goal-supervisor.js +132 -0
- package/dist/worker/scheduler/scheduled-goal-time.js +102 -0
- package/dist/worker/scheduler/scheduled-goal-types.js +95 -0
- package/dist/worker/task-spec/validate.js +4 -1
- package/dist/workflows/dag/backend-test-markdown-workflow.js +6 -24
- package/dist/workflows/dag/backend-test-plan-protocol.js +82 -5
- package/dist/workflows/dag/dag-retry-schema.js +11 -0
- package/dist/workflows/dag/decision-envelope.js +2 -0
- package/dist/workflows/dag/dynamic-runtime/shared.js +2 -2
- package/dist/workflows/dag/frontend-closeout.js +3 -1
- package/dist/workflows/dag/frontend-committed-facts.js +461 -0
- package/dist/workflows/dag/frontend-durable-tools.js +15 -3
- package/dist/workflows/dag/frontend-implementation-contract.js +369 -12
- package/dist/workflows/dag/frontend-plan-canary.js +53 -0
- package/dist/workflows/dag/frontend-plan-decision-contract.js +803 -0
- package/dist/workflows/dag/frontend-plan-render.js +0 -2
- package/dist/workflows/dag/frontend-provider-capability-matrix.js +8 -61
- package/dist/workflows/dag/frontend-recovery-run.js +57 -0
- package/dist/workflows/dag/frontend-repair.js +55 -76
- package/dist/workflows/dag/frontend-review-context.js +42 -68
- package/dist/workflows/dag/frontend-review-scopes.js +2 -2
- package/dist/workflows/dag/frontend-risk.js +92 -10
- package/dist/workflows/dag/frontend-session-budget.js +117 -3
- package/dist/workflows/dag/frontend-shape.js +11 -55
- package/dist/workflows/dag/frontend-test-execution-evidence.js +35 -10
- package/dist/workflows/dag/frontend-typed-event-store.js +32 -25
- package/dist/workflows/dag/frontend-verification-trace.js +33 -54
- package/dist/workflows/dag/frontend-writer-admission.js +3 -47
- package/dist/workflows/dag/frontend-writer-status.js +0 -23
- package/dist/workflows/dag/init-hybrid.js +47 -19
- package/dist/workflows/dag/interrupt-request.js +2 -0
- package/dist/workflows/dag/lifecycle.js +11 -2
- package/dist/workflows/dag/node-execution.js +50 -13
- package/dist/workflows/dag/reconcile-run.js +2 -0
- package/dist/workflows/dag/repair-artifact.js +3 -1
- package/dist/workflows/dag/report.js +2 -0
- package/dist/workflows/dag/rerun-plan.js +10 -0
- package/dist/workflows/dag/rerun-task.js +79 -1
- package/dist/workflows/dag/retry-policy.js +18 -0
- package/dist/workflows/dag/scheduler.js +2 -4
- package/dist/workflows/dag/types.js +44 -6
- package/dist/workflows/dag/validate.js +4 -0
- package/docs/README.md +1 -0
- package/docs/architecture/runtime-boundaries.md +3 -3
- package/docs/governance/README.md +1 -0
- package/docs/init-surface.manifest.json +1 -0
- package/docs/operations/README.md +2 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +2 -2
- package/docs/templates/backend-test-dag.json +14 -10
- package/docs/templates/frontend-implementation-contract.schema.json +0 -7
- package/package.json +9 -3
- package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
- package/skills/frontend-contract/references/contract-protocol.md +3 -1
- package/skills/frontend-plan/SKILL.md +8 -6
- package/skills/frontend-plan/references/decision-contract.md +3 -3
- package/skills/frontend-review/SKILL.md +18 -28
- package/skills/frontend-review/references/review-findings.md +8 -3
- package/dist/commands/new-task.js +0 -5
- package/dist/commands/status.js +0 -57
- package/dist/commands/task-contract.js +0 -269
- package/dist/shared/prompts.js +0 -26
- package/dist/task/config.js +0 -2
- package/dist/task/contract/validate-draft.js +0 -106
- package/dist/task/goal.js +0 -3
- package/dist/task/index.js +0 -12
- package/dist/task/lifecycle.js +0 -1
- package/dist/task/operator/capabilities.js +0 -6
- package/dist/task/operator/envelope.js +0 -2
- package/dist/task/operator/index.js +0 -5
- package/dist/task/operator/registry.js +0 -2
- package/dist/task/operator/types.js +0 -1
- package/dist/task/paths.js +0 -1
- package/dist/task/source-state.js +0 -1
- package/dist/task/subagent-guidance.js +0 -1
- package/dist/worker/console/chat/sift-bridge.js +0 -1
- package/dist/worker/console/index.js +0 -20
- package/dist/worker/console/static/assets/channel-JM-I_b0s.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DuQQAYEg.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DuQQAYEg.js +0 -1
- package/dist/worker/console/static/assets/index-B5H-giS2.js +0 -468
- package/dist/worker/console/static/assets/index-Bf7dxfm-.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-img0hVJ4.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B4acZJvk.js +0 -8
- package/dist/worker/scheduler/index.js +0 -25
- package/dist/workflows/dag/facts.js +0 -4
- package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -975
- package/dist/workflows/dag/index.js +0 -6
- package/dist/workflows/dynamic/index.js +0 -7
|
@@ -1023,7 +1023,74 @@ export function shouldRetryWithFallback(stderr, stdout) {
|
|
|
1023
1023
|
stdout,
|
|
1024
1024
|
timedOut: false,
|
|
1025
1025
|
});
|
|
1026
|
-
return [
|
|
1026
|
+
return [
|
|
1027
|
+
"quota",
|
|
1028
|
+
"rate-limit",
|
|
1029
|
+
"unavailable",
|
|
1030
|
+
"upstream-unavailable",
|
|
1031
|
+
"network",
|
|
1032
|
+
].includes(category);
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Provider/transport failure text, with model-authored content excluded.
|
|
1036
|
+
*
|
|
1037
|
+
* The captured stdout is a JSONL session transcript: it carries assistant text,
|
|
1038
|
+
* tool arguments and saved findings verbatim. Matching provider vocabulary
|
|
1039
|
+
* against that whole stream let model content drive the verdict (smoke r28: the
|
|
1040
|
+
* reviewer's own finding id `FDR-R28-UNAUTHORIZED-APP-CSS` was read as an auth
|
|
1041
|
+
* failure, which is not retryable, so a completed review was reported as a node
|
|
1042
|
+
* error). Only error-shaped channels may classify a transport failure:
|
|
1043
|
+
* stderr, error events, and the error fields of a message record.
|
|
1044
|
+
*/
|
|
1045
|
+
export function extractProviderFailureText(stdout) {
|
|
1046
|
+
const parts = [];
|
|
1047
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
1048
|
+
const line = rawLine.trim();
|
|
1049
|
+
if (!line)
|
|
1050
|
+
continue;
|
|
1051
|
+
if (!line.startsWith("{")) {
|
|
1052
|
+
// Non-JSON child output (warnings, CLI errors) is not model-authored.
|
|
1053
|
+
parts.push(line);
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
let record;
|
|
1057
|
+
try {
|
|
1058
|
+
const parsed = JSON.parse(line);
|
|
1059
|
+
if (!isRecord(parsed))
|
|
1060
|
+
continue;
|
|
1061
|
+
record = parsed;
|
|
1062
|
+
}
|
|
1063
|
+
catch {
|
|
1064
|
+
// An unparseable line may be truncated model content: skip it.
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
const type = typeof record.type === "string" ? record.type : "";
|
|
1068
|
+
const isErrorEvent = type === "error" || type === "agent_error" || type.endsWith("_error");
|
|
1069
|
+
const errorMessage = typeof record.errorMessage === "string" ? record.errorMessage : "";
|
|
1070
|
+
const errorField = record.error;
|
|
1071
|
+
const message = isRecord(record.message) ? record.message : undefined;
|
|
1072
|
+
const messageErrorMessage = typeof message?.errorMessage === "string" ? message.errorMessage : "";
|
|
1073
|
+
const messageErrored = message?.stopReason === "error";
|
|
1074
|
+
if (!isErrorEvent &&
|
|
1075
|
+
!errorMessage &&
|
|
1076
|
+
errorField === undefined &&
|
|
1077
|
+
!messageErrorMessage) {
|
|
1078
|
+
continue;
|
|
1079
|
+
}
|
|
1080
|
+
parts.push([type, errorMessage, messageErrorMessage, messageErrored ? "stopReason error" : ""]
|
|
1081
|
+
.filter(Boolean)
|
|
1082
|
+
.join(" "));
|
|
1083
|
+
if (typeof errorField === "string") {
|
|
1084
|
+
parts.push(errorField);
|
|
1085
|
+
}
|
|
1086
|
+
else if (isRecord(errorField)) {
|
|
1087
|
+
parts.push(["message", "errorMessage", "reason", "code", "status", "type"]
|
|
1088
|
+
.map((key) => (errorField[key] === undefined ? "" : String(errorField[key])))
|
|
1089
|
+
.filter(Boolean)
|
|
1090
|
+
.join(" "));
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
return parts.join("\n");
|
|
1027
1094
|
}
|
|
1028
1095
|
export function classifyPiFailure(input) {
|
|
1029
1096
|
if (input.exitCode === 0 && input.assistantText.trim())
|
|
@@ -1034,7 +1101,9 @@ export function classifyPiFailure(input) {
|
|
|
1034
1101
|
return "timeout";
|
|
1035
1102
|
if (input.outputTooLarge)
|
|
1036
1103
|
return "output-too-large";
|
|
1037
|
-
|
|
1104
|
+
// Provider/transport verdicts read error-shaped channels only; the raw stdout
|
|
1105
|
+
// stream embeds assistant text, tool arguments and findings verbatim.
|
|
1106
|
+
const combined = `${input.stderr}\n${extractProviderFailureText(input.stdout)}`.toLowerCase();
|
|
1038
1107
|
// Context overflow (400 request-too-large / context window exceeded).
|
|
1039
1108
|
// Must be detected BEFORE the generic rate-limit/quota phrases: an overflow
|
|
1040
1109
|
// error often contains "too many tokens" / "maximum context" which would
|
|
@@ -1052,8 +1121,21 @@ export function classifyPiFailure(input) {
|
|
|
1052
1121
|
return "rate-limit";
|
|
1053
1122
|
if (/quota|usage limit|reached[^\n.]{0,60}limit|5\s*小时|5小时|insufficient_quota|billing/.test(combined))
|
|
1054
1123
|
return "quota";
|
|
1055
|
-
|
|
1124
|
+
// Error words must stand alone: the captured stream also contains
|
|
1125
|
+
// model-authored identifiers, and smoke r28 lost a whole run because the
|
|
1126
|
+
// reviewer's own finding id `FDR-R28-UNAUTHORIZED-APP-CSS` matched a bare
|
|
1127
|
+
// `\bunauthorized\b`, turning a retryable empty-output into a terminal
|
|
1128
|
+
// `auth`. Identifier delimiters (`-`/`_`/alphanumerics) disqualify a match.
|
|
1129
|
+
if (/(?<![\w-])unauthorized(?![\w-])|\bhttp\s*40[13]\b|invalid api key|(?<![\w-])authentication (?:failed|required|error)(?![\w-])|(?<![\w-])auth(?:entication)? failed(?![\w-])/.test(combined))
|
|
1056
1130
|
return "auth";
|
|
1131
|
+
// Gateway reachability first: a 502/503 body means the provider was
|
|
1132
|
+
// unreachable, not that the request lacked a capability. Reporting the
|
|
1133
|
+
// generic category here previously let an upstream outage surface as the
|
|
1134
|
+
// plan ladder's `unsupported-provider-capability`, which reads as a model
|
|
1135
|
+
// capability mismatch and sent the incident diagnosis in the wrong
|
|
1136
|
+
// direction (2026-09-11).
|
|
1137
|
+
if (/\bhttp\s*50[23]\b|(?:^|\D)50[23](?:\D|$)|service temporarily unavailable|bad gateway|upstream (?:is )?(?:unavailable|down|unreachable)|网关(?:暂时)?不可用/.test(combined))
|
|
1138
|
+
return "upstream-unavailable";
|
|
1057
1139
|
if (/unknown provider|unknown model|(?:provider|model|service|gateway)\s+(?:is\s+)?unavailable|overloaded|at capacity|temporarily unavailable/.test(combined))
|
|
1058
1140
|
return "unavailable";
|
|
1059
1141
|
if (/network\s*(?:error|failure|issue|timeout|unreachable|reset|abort)|networkerror|connection (?:reset|error|refused|closed|timed\s*out)|request timed out|socket hang up|econn\w*|etimedout|fetch failed|dns (?:error|failure|lookup failed)/.test(combined))
|
|
@@ -322,6 +322,21 @@ async function createSdkSession(sdk, input, shared) {
|
|
|
322
322
|
extensionToolExtras.push(...computeExtensionToolAllowlistExtras([{ name: SIFT_RETRIEVE_TOOL_NAME }], input.toolNames));
|
|
323
323
|
}
|
|
324
324
|
const sessionToolNames = [...input.toolNames, ...extensionToolExtras];
|
|
325
|
+
// Pre-session protocol self-check: createAgentSession silently drops a
|
|
326
|
+
// custom tool whose name is absent from this allowlist (the post-create
|
|
327
|
+
// mismatch check cannot see the omission either — expected and actual are
|
|
328
|
+
// both false). The model would then be prompted to call tools that do not
|
|
329
|
+
// exist and burn attempts discovering it (smoke r10/r14 class of failure),
|
|
330
|
+
// so fail before any model call, naming the dropped tools.
|
|
331
|
+
if (input.requireAllowlistedCustomTools && Array.isArray(input.customTools) && input.customTools.length > 0) {
|
|
332
|
+
const allowlist = new Set(sessionToolNames);
|
|
333
|
+
const dropped = input.customTools
|
|
334
|
+
.map((tool) => (isRecord(tool) && typeof tool.name === "string" ? tool.name : undefined))
|
|
335
|
+
.filter((name) => typeof name === "string" && !allowlist.has(name));
|
|
336
|
+
if (dropped.length > 0) {
|
|
337
|
+
throw new Error(`pi session custom tools would be silently dropped (absent from the activation allowlist): ${dropped.join(", ")}; allowlist: [${sessionToolNames.join(", ")}]`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
325
340
|
if (input.requireWriterCustomTools) {
|
|
326
341
|
if (!Array.isArray(input.customTools) || input.customTools.length === 0) {
|
|
327
342
|
throw new Error("pi writer tool policy missing customTools; refusing to create uncontrolled writer session");
|
|
@@ -707,6 +722,9 @@ async function executeSingleSdkAttemptInternal(options) {
|
|
|
707
722
|
? { customTools: writerCustomTools }
|
|
708
723
|
: {}),
|
|
709
724
|
...(requireWriterCustomTools ? { requireWriterCustomTools: true } : {}),
|
|
725
|
+
...(options.writerToolPolicy?.requireAllowlistedCustomTools
|
|
726
|
+
? { requireAllowlistedCustomTools: true }
|
|
727
|
+
: {}),
|
|
710
728
|
...(options.piExtensionPaths && options.piExtensionPaths.length > 0
|
|
711
729
|
? { additionalExtensionPaths: options.piExtensionPaths }
|
|
712
730
|
: {}),
|
|
@@ -470,6 +470,54 @@ function parseCheckRepoSubcheckDurations(result) {
|
|
|
470
470
|
}
|
|
471
471
|
return durations;
|
|
472
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Frozen-command evidence for the review node: which commandId/label/lane each
|
|
475
|
+
* executed command belongs to, its exit status, and the lint lane's status
|
|
476
|
+
* (explicitly `not-configured` when the task declares no lint commands).
|
|
477
|
+
*
|
|
478
|
+
* The review protocol requires exit evidence ("typecheck, build, and test are
|
|
479
|
+
* required successful final exits") while the verification trace only proves
|
|
480
|
+
* command/file/target binding, so this artifact is what makes that requirement
|
|
481
|
+
* satisfiable at all (smoke r31: the reviewer had to request changes for a
|
|
482
|
+
* check no context could support).
|
|
483
|
+
*/
|
|
484
|
+
export function buildFrontendVerificationEvidence(input) {
|
|
485
|
+
const directory = buildFrontendVerifyCommandDirectory({
|
|
486
|
+
staticLabels: input.bundle.staticEvidence?.commandLabels ?? [],
|
|
487
|
+
staticCommandTexts: input.bundle.staticEvidence?.commandTexts ?? [],
|
|
488
|
+
behaviorLabels: input.bundle.behaviorEvidence?.commandLabels ?? [],
|
|
489
|
+
behaviorCommandTexts: input.bundle.behaviorEvidence?.commandTexts ?? [],
|
|
490
|
+
mockLabels: input.bundle.mockEvidence?.commandLabels ?? [],
|
|
491
|
+
mockCommandTexts: input.bundle.mockEvidence?.commandTexts ?? [],
|
|
492
|
+
lintLabels: input.bundle.lintEvidence?.commandLabels ?? [],
|
|
493
|
+
lintCommandTexts: input.bundle.lintEvidence?.commandTexts ?? [],
|
|
494
|
+
});
|
|
495
|
+
const entryByCommand = new Map(directory.map((entry) => [entry.command.trim(), entry]));
|
|
496
|
+
return {
|
|
497
|
+
schemaVersion: 1,
|
|
498
|
+
schemaId: "frontend-verification-evidence-v1",
|
|
499
|
+
nodeId: input.nodeId,
|
|
500
|
+
runId: input.runId,
|
|
501
|
+
capturedAt: new Date().toISOString(),
|
|
502
|
+
allPassed: input.results.every((result) => result.ok),
|
|
503
|
+
lintStatus: input.lintStatus,
|
|
504
|
+
lintConfigured: input.lintConfigured,
|
|
505
|
+
commands: input.results.map((result, index) => {
|
|
506
|
+
const entry = entryByCommand.get(result.command.trim());
|
|
507
|
+
return {
|
|
508
|
+
index: index + 1,
|
|
509
|
+
commandId: entry?.commandId ?? null,
|
|
510
|
+
label: entry?.label ?? null,
|
|
511
|
+
lane: entry?.lane ?? null,
|
|
512
|
+
command: result.command,
|
|
513
|
+
ok: result.ok,
|
|
514
|
+
exitCode: result.exitCode,
|
|
515
|
+
failureCategory: result.failureCategory,
|
|
516
|
+
reused: result.reused === true,
|
|
517
|
+
};
|
|
518
|
+
}),
|
|
519
|
+
};
|
|
520
|
+
}
|
|
473
521
|
export function buildShellResultSummaryMarkdown(input) {
|
|
474
522
|
const lines = [
|
|
475
523
|
"# Shell execution summary",
|
|
@@ -1915,7 +1963,7 @@ async function executePipelineCommands(input, meta, overrideCommands) {
|
|
|
1915
1963
|
* of inventing refs. */
|
|
1916
1964
|
async function deriveUnresolvedVerificationEntrypointRefs(runDir, frozenCommandIds) {
|
|
1917
1965
|
try {
|
|
1918
|
-
const { restorePlanPatchFromCommittedFacts } = await import("../workflows/dag/frontend-
|
|
1966
|
+
const { restorePlanPatchFromCommittedFacts } = await import("../workflows/dag/frontend-implementation-contract.js");
|
|
1919
1967
|
const records = await readTypedEventStoreFromJsonl(path.join(runDir, "frontend-plan-pi", "plan-typed-facts.jsonl"));
|
|
1920
1968
|
const patch = restorePlanPatchFromCommittedFacts(records);
|
|
1921
1969
|
const targets = patch
|
|
@@ -2127,6 +2175,27 @@ async function executeFrontendVerificationBundle(input, meta) {
|
|
|
2127
2175
|
command: result.command,
|
|
2128
2176
|
reused: result.reused === true,
|
|
2129
2177
|
}));
|
|
2178
|
+
// Auditable per-command evidence for the review node (smoke r31): the review
|
|
2179
|
+
// protocol treats shell exit status as authoritative, but the review context
|
|
2180
|
+
// only carried the verification trace's command/file/target *binding*
|
|
2181
|
+
// status, so a reviewer could not confirm the frozen commands actually
|
|
2182
|
+
// exited 0 and had to request changes for missing evidence. Written before
|
|
2183
|
+
// either the failure or the success path returns.
|
|
2184
|
+
const lintConfigured = (bundle.lintCommands?.length ?? 0) > 0;
|
|
2185
|
+
await writeDagRunJsonArtifact(meta.runDir, "contracts/frontend-verification-evidence.json", buildFrontendVerificationEvidence({
|
|
2186
|
+
nodeId: input.task.id,
|
|
2187
|
+
runId: meta.runId,
|
|
2188
|
+
bundle,
|
|
2189
|
+
results,
|
|
2190
|
+
// The review protocol's lint vocabulary is
|
|
2191
|
+
// passed | baseline-debt | failed | unavailable; a task that declares
|
|
2192
|
+
// no lint commands reports `unavailable` plus lintConfigured:false
|
|
2193
|
+
// rather than inventing a value outside that catalog (smoke r33).
|
|
2194
|
+
lintStatus: lintConfigured
|
|
2195
|
+
? (lintAssessment?.status ?? "unavailable")
|
|
2196
|
+
: "unavailable",
|
|
2197
|
+
lintConfigured,
|
|
2198
|
+
}));
|
|
2130
2199
|
// Lint baseline-debt is tolerated, so a lint-only failure must not become the
|
|
2131
2200
|
// verification failure. A shared lint/static or lint/behavior command is
|
|
2132
2201
|
// different: once reused by a non-lint lane, its failure belongs to that lane
|
|
@@ -2320,16 +2389,22 @@ async function readRunDirJson(runDir, relativePath) {
|
|
|
2320
2389
|
}
|
|
2321
2390
|
/** Committed typed review terminal kinds from the review node's typed event
|
|
2322
2391
|
* store (AC-003: typed terminal tools are the only authoritative verdict). */
|
|
2323
|
-
async function collectReviewTerminalKinds(runDir, reviewNodeId) {
|
|
2392
|
+
export async function collectReviewTerminalKinds(runDir, reviewNodeId) {
|
|
2324
2393
|
try {
|
|
2325
2394
|
const records = await readTypedEventStoreFromJsonl(path.join(runDir, reviewNodeId, "review-typed-facts.jsonl"));
|
|
2395
|
+
// The store also holds findings and scope checkpoints; only the verdict
|
|
2396
|
+
// kinds decide "missing or ambiguous" (fail closed on 0 or 2+).
|
|
2397
|
+
const terminalKinds = new Set([
|
|
2398
|
+
"approve_review",
|
|
2399
|
+
"request_review_changes",
|
|
2400
|
+
]);
|
|
2326
2401
|
return records
|
|
2327
2402
|
.filter((record) => record.phase === "committed")
|
|
2328
2403
|
.map((record) => {
|
|
2329
2404
|
const kind = record.fact.kind;
|
|
2330
2405
|
return typeof kind === "string" ? kind : "";
|
|
2331
2406
|
})
|
|
2332
|
-
.filter(
|
|
2407
|
+
.filter((kind) => terminalKinds.has(kind));
|
|
2333
2408
|
}
|
|
2334
2409
|
catch {
|
|
2335
2410
|
return [];
|
|
@@ -2339,16 +2414,24 @@ async function collectReviewTerminalKinds(runDir, reviewNodeId) {
|
|
|
2339
2414
|
* event store (M8: the committed approve_design / request_design_changes fact
|
|
2340
2415
|
* is the only authoritative verdict; the legacy first-line VERDICT text is
|
|
2341
2416
|
* never read for writer admission). Fail-closed on a missing/unreadable store. */
|
|
2342
|
-
async function collectDesignTerminalKinds(runDir, designNodeId) {
|
|
2417
|
+
export async function collectDesignTerminalKinds(runDir, designNodeId) {
|
|
2343
2418
|
try {
|
|
2344
2419
|
const records = await readTypedEventStoreFromJsonl(path.join(runDir, designNodeId, "design-typed-facts.jsonl"));
|
|
2420
|
+
// The store also holds findings and scope checkpoints; only the verdict
|
|
2421
|
+
// kinds decide "missing or ambiguous" (fail closed on 0 or 2+). Without
|
|
2422
|
+
// this filter any recorded finding makes admission read the committed
|
|
2423
|
+
// verdict as ambiguous and blocks the writer (r11 decision-path smoke).
|
|
2424
|
+
const terminalKinds = new Set([
|
|
2425
|
+
"approve_design",
|
|
2426
|
+
"request_design_changes",
|
|
2427
|
+
]);
|
|
2345
2428
|
return records
|
|
2346
2429
|
.filter((record) => record.phase === "committed")
|
|
2347
2430
|
.map((record) => {
|
|
2348
2431
|
const kind = record.fact.kind;
|
|
2349
2432
|
return typeof kind === "string" ? kind : "";
|
|
2350
2433
|
})
|
|
2351
|
-
.filter(
|
|
2434
|
+
.filter((kind) => terminalKinds.has(kind));
|
|
2352
2435
|
}
|
|
2353
2436
|
catch {
|
|
2354
2437
|
return [];
|
|
@@ -2511,7 +2594,7 @@ async function executeFrontendDesignPolicy(input, meta) {
|
|
|
2511
2594
|
// M9a the plan node's assistantText is a pure Markdown narrative; the
|
|
2512
2595
|
// compile authority is the committed plan ledger ⊕ runtime skeleton.
|
|
2513
2596
|
// Fail closed on missing committed facts — never fall back to text.
|
|
2514
|
-
const { readCommittedOriginFacts, checkCommittedOriginFacts } = await import("../workflows/dag/frontend-
|
|
2597
|
+
const { readCommittedOriginFacts, checkCommittedOriginFacts } = await import("../workflows/dag/frontend-committed-facts.js");
|
|
2515
2598
|
// A+B (AC-001/003): fail-closed committed contract/scout typed facts.
|
|
2516
2599
|
// Missing/uncommitted facts block here; never fall back to text parsing.
|
|
2517
2600
|
const committedContractFacts = await readCommittedOriginFacts(meta.runDir, "frontend-contract-pi", "contract-typed-facts.jsonl");
|
|
@@ -2630,7 +2713,7 @@ async function executeFrontendDesignPolicy(input, meta) {
|
|
|
2630
2713
|
});
|
|
2631
2714
|
}
|
|
2632
2715
|
// Byte freshness is necessary but not sufficient: require the same ledger
|
|
2633
|
-
// semantic checks as the
|
|
2716
|
+
// semantic checks as the canonical admission policy before production writer
|
|
2634
2717
|
// admission can be materialized.
|
|
2635
2718
|
if (meta.spec.sourceBinding) {
|
|
2636
2719
|
const ledgerCheck = await checkFrontendSourceFidelityLedger({
|
|
@@ -2974,6 +3057,7 @@ async function executeFrontendCloseout(input, meta) {
|
|
|
2974
3057
|
const contract = frontendImplementationContractSchema.parse(JSON.parse(contractRaw));
|
|
2975
3058
|
const trace = context.verificationTrace;
|
|
2976
3059
|
const verificationTargets = (trace?.targets ?? []).map((target) => ({
|
|
3060
|
+
mode: contract.verificationTargets.find((entry) => entry.id === target.id)?.mode ?? "static",
|
|
2977
3061
|
status: target.status === "ok" ? "ok" : "failed",
|
|
2978
3062
|
}));
|
|
2979
3063
|
const mockEvidenceBound = contract.mockApi.strategy !== "not-needed" &&
|
|
@@ -3015,6 +3099,8 @@ async function executeFrontendCloseout(input, meta) {
|
|
|
3015
3099
|
coverageMatrix: verificationTargets.map((target, index) => ({
|
|
3016
3100
|
verificationTargetId: trace?.targets?.[index]?.id ?? `vt-${index}`,
|
|
3017
3101
|
status: target.status === "ok" ? "passed" : "failed",
|
|
3102
|
+
evidence: trace?.targets?.[index]?.evidence ?? "unavailable",
|
|
3103
|
+
behaviorCoverage: "unconfirmed",
|
|
3018
3104
|
})),
|
|
3019
3105
|
lintStatus: "unavailable",
|
|
3020
3106
|
integrationFacts,
|
|
@@ -138,6 +138,9 @@ export function renderVerifyReport(results) {
|
|
|
138
138
|
export async function executeCommand(command, defaultTimeoutMs = DEFAULT_VERIFY_TIMEOUT_MS) {
|
|
139
139
|
return new Promise((resolve, reject) => {
|
|
140
140
|
const [binary, ...args] = command.args;
|
|
141
|
+
if (binary === undefined) {
|
|
142
|
+
throw new Error("verify command requires a non-empty args array");
|
|
143
|
+
}
|
|
141
144
|
const timeoutMs = command.timeoutMs ?? defaultTimeoutMs;
|
|
142
145
|
const startedAt = Date.now();
|
|
143
146
|
const child = spawn(binary, args, {
|
|
@@ -94,48 +94,43 @@ const DAG_RUNS_PREFIX = ".harness/dag-runs/";
|
|
|
94
94
|
* They are not product evidence and must not fail exclusive write guards.
|
|
95
95
|
* Intentional report/product writes remain governed by writePolicy/writeSet.
|
|
96
96
|
*/
|
|
97
|
-
|
|
98
|
-
const normalized = normalizePath(filePath);
|
|
99
|
-
if (!normalized)
|
|
100
|
-
return false;
|
|
97
|
+
const EPHEMERAL_CACHE_DIRS = [
|
|
101
98
|
// CodeGraph extension sync side effect (plan 2026-08-21 D7): a loaded
|
|
102
99
|
// pi-codegraph extension keeps an existing .codegraph/ index fresh at
|
|
103
100
|
// session start; those index files are extension-owned run state, not
|
|
104
101
|
// writer output, so they never count as write-guard violations.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
normalized.startsWith(".pytest_cache/")) {
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
if (normalized === ".mypy_cache" || normalized.startsWith(".mypy_cache/")) {
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
if (normalized === ".ruff_cache" || normalized.startsWith(".ruff_cache/")) {
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
102
|
+
".codegraph",
|
|
103
|
+
".pytest_cache",
|
|
104
|
+
".mypy_cache",
|
|
105
|
+
".ruff_cache",
|
|
118
106
|
// playwright-cli default session dumps (console/page/network) under repo cwd.
|
|
119
107
|
// Real browser case evidence must still be written under testcase/** explicitly.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
if (normalized === ".coverage" || normalized.startsWith(".coverage.")) {
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
108
|
+
".playwright-cli",
|
|
109
|
+
];
|
|
110
|
+
const EPHEMERAL_CACHE_DIR_PREFIXES = [
|
|
127
111
|
// vite/vitest runtime caches live under node_modules/.vite (e.g.
|
|
128
112
|
// node_modules/.vite/vitest/results.json). node_modules is the gitignored
|
|
129
113
|
// dependency tree — tool cache writes there are never a writer's product
|
|
130
114
|
// change and must not trip the write guard.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
115
|
+
"node_modules/.vite",
|
|
116
|
+
];
|
|
117
|
+
const EPHEMERAL_CACHE_FILES = new Set([".coverage"]);
|
|
118
|
+
const EPHEMERAL_CACHE_PATH_PATTERNS = [
|
|
119
|
+
/(?:^|\/)__pycache__(?:\/|$)/,
|
|
120
|
+
/\.(?:pyc|pyo)$/,
|
|
121
|
+
];
|
|
122
|
+
function isExactOrChildPath(value, names) {
|
|
123
|
+
return names.some((name) => value === name || value.startsWith(`${name}/`));
|
|
124
|
+
}
|
|
125
|
+
export function isEphemeralToolCachePath(filePath) {
|
|
126
|
+
const normalized = normalizePath(filePath);
|
|
127
|
+
if (!normalized)
|
|
128
|
+
return false;
|
|
129
|
+
return (isExactOrChildPath(normalized, EPHEMERAL_CACHE_DIRS) ||
|
|
130
|
+
EPHEMERAL_CACHE_DIR_PREFIXES.some((prefix) => normalized.startsWith(`${prefix}/`)) ||
|
|
131
|
+
EPHEMERAL_CACHE_FILES.has(normalized) ||
|
|
132
|
+
normalized.startsWith(".coverage.") ||
|
|
133
|
+
EPHEMERAL_CACHE_PATH_PATTERNS.some((pattern) => pattern.test(normalized)));
|
|
139
134
|
}
|
|
140
135
|
/** MVP post-run guard: only paths that changed during the shell node are checked. */
|
|
141
136
|
export function validateShellWriteGuard(input) {
|
|
@@ -174,7 +174,7 @@ function localIndexReference(rawReference) {
|
|
|
174
174
|
.trim()
|
|
175
175
|
.replace(/^<|>$/g, "")
|
|
176
176
|
.split(/[?#]/, 1)[0]
|
|
177
|
-
|
|
177
|
+
?.replaceAll("\\", "/") ?? "";
|
|
178
178
|
if (!normalized.endsWith(".md") || normalized.includes("/"))
|
|
179
179
|
return null;
|
|
180
180
|
// Naming-convention placeholders (e.g. `YYYY-MM-DD-<topic>.md`) and other
|
|
@@ -332,6 +332,8 @@ function findInsertionPointForActiveEntry(lines) {
|
|
|
332
332
|
// trailing section (blank-line separated context), or at the end.
|
|
333
333
|
for (let i = 0; i < lines.length; i += 1) {
|
|
334
334
|
const line = lines[i];
|
|
335
|
+
if (line === undefined)
|
|
336
|
+
break;
|
|
335
337
|
if (/^[-*]\s+已归档/.test(line))
|
|
336
338
|
return i;
|
|
337
339
|
if (/^[-*]\s+`[^`]+\.md`/.test(line)) {
|
|
@@ -357,7 +359,8 @@ function removeIndexEntries(indexContent, file) {
|
|
|
357
359
|
const lines = indexContent.split(/\r?\n/);
|
|
358
360
|
const filtered = lines.filter((line) => {
|
|
359
361
|
const linkMatch = line.match(/\[[^\]]*\]\(([^)]+)\)/);
|
|
360
|
-
|
|
362
|
+
const linkTarget = linkMatch?.[1];
|
|
363
|
+
if (linkTarget !== undefined && path.basename(linkTarget) === file)
|
|
361
364
|
return false;
|
|
362
365
|
if (line.includes(`\`${file}\``))
|
|
363
366
|
return false;
|
|
@@ -375,7 +378,7 @@ function collapseBlankRuns(lines) {
|
|
|
375
378
|
result.push(line);
|
|
376
379
|
prevBlank = isBlank;
|
|
377
380
|
}
|
|
378
|
-
while (result.length > 0 && result[result.length - 1]
|
|
381
|
+
while (result.length > 0 && result[result.length - 1]?.trim() === "") {
|
|
379
382
|
result.pop();
|
|
380
383
|
}
|
|
381
384
|
return result;
|
|
@@ -45,6 +45,9 @@ export function openConsoleAppData(options) {
|
|
|
45
45
|
chats: path.join(repoNamespace, "chats"),
|
|
46
46
|
chatSessions: path.join(repoNamespace, "chat-sessions"),
|
|
47
47
|
chatEvents: path.join(repoNamespace, "chat-events"),
|
|
48
|
+
browserProfile: path.join(repoNamespace, "browser-profile"),
|
|
49
|
+
browserDownloads: path.join(repoNamespace, "browser-downloads"),
|
|
50
|
+
browserScreenshots: path.join(repoNamespace, "browser-screenshots"),
|
|
48
51
|
resourcePreferences: path.join(repoNamespace, "resource-preferences.json"),
|
|
49
52
|
};
|
|
50
53
|
for (const dir of [
|
|
@@ -60,6 +63,9 @@ export function openConsoleAppData(options) {
|
|
|
60
63
|
paths.chats,
|
|
61
64
|
paths.chatSessions,
|
|
62
65
|
paths.chatEvents,
|
|
66
|
+
paths.browserProfile,
|
|
67
|
+
paths.browserDownloads,
|
|
68
|
+
paths.browserScreenshots,
|
|
63
69
|
path.dirname(paths.resourcePreferences),
|
|
64
70
|
]) {
|
|
65
71
|
ensureSecureDir(dir);
|
|
@@ -81,6 +81,8 @@ function isUnchangedNewTaskTemplate(step, content) {
|
|
|
81
81
|
}
|
|
82
82
|
function firstRequiredSectionIsEmpty(step, content) {
|
|
83
83
|
const [, firstSectionHeading] = REQUIRED_HEADINGS[step];
|
|
84
|
+
if (!firstSectionHeading)
|
|
85
|
+
return false;
|
|
84
86
|
const headingIndex = content.indexOf(firstSectionHeading);
|
|
85
87
|
if (headingIndex < 0) {
|
|
86
88
|
return false;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { buildControllerIdentityFromEntry, readBuildStamp } from "./package-metadata.js";
|
|
5
|
+
export function sha256File(file) {
|
|
6
|
+
return `sha256:${createHash("sha256").update(readFileSync(file)).digest("hex")}`;
|
|
7
|
+
}
|
|
8
|
+
export function classifyBackendDogfoodProvenance(input) {
|
|
9
|
+
if (input.tarballPath)
|
|
10
|
+
return { kind: "local-tarball", version: input.identity.packageVersion, tarballSha256: sha256File(input.tarballPath) };
|
|
11
|
+
if (input.distTag)
|
|
12
|
+
return { kind: "published-npm", version: input.identity.packageVersion, distTag: input.distTag };
|
|
13
|
+
return { kind: "local-candidate", version: input.identity.packageVersion };
|
|
14
|
+
}
|
|
15
|
+
export function buildBackendDogfoodIdentityEvidence(input) {
|
|
16
|
+
const controller = buildControllerIdentityFromEntry({ requested: input.controllerEntry, entry: path.resolve(input.controllerEntry) });
|
|
17
|
+
if (!controller)
|
|
18
|
+
throw new Error("BACKEND_DOGFOOD_IDENTITY_UNRESOLVED");
|
|
19
|
+
const fingerprint = controller.packageFingerprint.value;
|
|
20
|
+
if (fingerprint !== input.expectedFingerprint)
|
|
21
|
+
throw new Error(`BACKEND_DOGFOOD_CONTROLLER_MISMATCH: expected ${input.expectedFingerprint}, got ${fingerprint}`);
|
|
22
|
+
const consoleIdentity = input.consoleHost
|
|
23
|
+
? undefined
|
|
24
|
+
: buildControllerIdentityFromEntry({
|
|
25
|
+
requested: input.consoleControllerEntry ?? path.join(controller.packageRoot, "bin", "agent-worker.js"),
|
|
26
|
+
entry: input.consoleControllerEntry ?? path.join(controller.packageRoot, "bin", "agent-worker.js"),
|
|
27
|
+
});
|
|
28
|
+
if (!input.consoleHost && !consoleIdentity)
|
|
29
|
+
throw new Error("BACKEND_DOGFOOD_CONSOLE_IDENTITY_UNRESOLVED");
|
|
30
|
+
const consoleHost = {
|
|
31
|
+
packageName: String(input.consoleHost?.packageName ?? consoleIdentity?.packageName),
|
|
32
|
+
packageVersion: String(input.consoleHost?.packageVersion ?? consoleIdentity?.packageVersion),
|
|
33
|
+
packageFingerprint: String(input.consoleHost?.packageFingerprint ?? consoleIdentity?.packageFingerprint.value),
|
|
34
|
+
};
|
|
35
|
+
const expected = `${controller.packageName}@${controller.packageVersion}@${fingerprint}`;
|
|
36
|
+
const actual = `${consoleHost.packageName}@${consoleHost.packageVersion}@${consoleHost.packageFingerprint}`;
|
|
37
|
+
if (actual !== expected)
|
|
38
|
+
throw new Error(`BACKEND_DOGFOOD_CONSOLE_IDENTITY_MISMATCH: expected ${expected}, got ${actual}`);
|
|
39
|
+
return {
|
|
40
|
+
schemaVersion: 1,
|
|
41
|
+
controller,
|
|
42
|
+
provenance: classifyBackendDogfoodProvenance({ identity: controller, distTag: input.distTag, tarballPath: input.tarballPath }),
|
|
43
|
+
buildCommitSha: readBuildStamp(controller.packageRoot)?.gitSha ?? null,
|
|
44
|
+
consoleHost,
|
|
45
|
+
dagController: { packageName: controller.packageName, packageVersion: controller.packageVersion, packageFingerprint: fingerprint },
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -59,6 +59,9 @@ const RAW_TO_NORMALIZED = {
|
|
|
59
59
|
quota: "executor",
|
|
60
60
|
"rate-limit": "executor",
|
|
61
61
|
unavailable: "executor",
|
|
62
|
+
// Gateway reachability outage: still an executor-class failure, but named so
|
|
63
|
+
// reports do not read as a capability mismatch.
|
|
64
|
+
"upstream-unavailable": "executor",
|
|
62
65
|
// Context window overflow (400 request-too-large): the session needs
|
|
63
66
|
// compaction / fresh context before retrying — an executor-side
|
|
64
67
|
// environment condition, not a plan-quality defect.
|
|
@@ -112,6 +112,8 @@ function globToRegExp(pattern) {
|
|
|
112
112
|
let regex = '^';
|
|
113
113
|
for (let i = 0; i < normalized.length; i += 1) {
|
|
114
114
|
const char = normalized[i];
|
|
115
|
+
if (char === undefined)
|
|
116
|
+
continue;
|
|
115
117
|
const next = normalized[i + 1];
|
|
116
118
|
if (char === '*' && next === '*') {
|
|
117
119
|
const afterGlobstar = normalized[i + 2];
|
|
@@ -8,6 +8,8 @@ export function createOneShotPromptParseAccum() {
|
|
|
8
8
|
}
|
|
9
9
|
export function parseOneShotCommonFlag(args, index, accum) {
|
|
10
10
|
const arg = args[index];
|
|
11
|
+
if (arg === undefined)
|
|
12
|
+
return { kind: "not-common" };
|
|
11
13
|
if (arg === "--stdin") {
|
|
12
14
|
accum.fromStdin = true;
|
|
13
15
|
return { kind: "consumed", nextIndex: index };
|