@tea-agent/loop-agent 0.39.0-beta.1 → 0.39.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -1
- package/CHANGELOG.md +248 -95
- package/README.md +9 -5
- package/bin/loop-agent.js +7 -3
- package/dist/application/task-lifecycle/advance.js +12 -0
- package/dist/application/task-lifecycle/recommendations.js +13 -2
- package/dist/build-stamp.json +3 -3
- package/dist/cli/command-definitions.js +23 -5
- package/dist/cli/program.js +21 -2
- package/dist/cli/update/notifier.js +2 -2
- package/dist/cli/update/runtime-activity.js +1 -29
- package/dist/cli.js +2 -1
- package/dist/commands/client-recovery.js +3 -0
- package/dist/commands/dag-follow-up.js +138 -0
- package/dist/commands/dag-rerun.js +55 -1
- package/dist/commands/init-model-catalog.js +464 -0
- package/dist/commands/init-upgrade.js +265 -97
- package/dist/commands/init.js +455 -28
- package/dist/commands/inspect-next.js +8 -0
- package/dist/commands/task-advance.js +19 -0
- package/dist/executors/dag-pi-executor.js +2306 -61
- package/dist/executors/pi-executor.js +7 -0
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-playwright-cli-tool.js +74 -28
- package/dist/executors/pi-read-budget-policy.js +239 -0
- package/dist/executors/pi-sdk-executor.js +180 -33
- package/dist/executors/shell-executor.js +1249 -224
- package/dist/executors/shell-write-guard.js +14 -0
- package/dist/executors/workspace-write-snapshot.js +68 -0
- package/dist/infrastructure/harness/atomic-write.js +23 -0
- package/dist/shared/dag-failure-category.js +150 -0
- package/dist/shared/dag-prompt-override.js +27 -0
- package/dist/shared/openspec-spec.js +70 -4
- package/dist/shared/operator/capabilities.js +39 -0
- package/dist/shared/playwright-cli-command-policy.js +15 -0
- package/dist/shared/update/console-notifier.js +100 -0
- package/dist/{cli → shared}/update/npm-client.js +70 -15
- package/dist/{cli → shared}/update/state.js +41 -13
- package/dist/task/config-types.js +50 -5
- package/dist/task/contract/apply.js +11 -1
- package/dist/task/contract/constants.js +2 -0
- package/dist/task/contract/hash.js +3 -0
- package/dist/task/contract/observe.js +25 -4
- package/dist/task/contract/paths.js +2 -1
- package/dist/task/contract/project.js +18 -1
- package/dist/task/contract/schema.js +4 -1
- package/dist/task/contract/transaction.js +12 -0
- package/dist/task/frontend-project-capability.js +199 -18
- package/dist/task/source-prepare/completeness.js +188 -0
- package/dist/task/source-prepare/fragment-inventory.js +477 -0
- package/dist/task/source-prepare/index.js +3 -0
- package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
- package/dist/task/source-prepare/ledger-review.js +214 -0
- package/dist/task/source-prepare/ledger.js +545 -0
- package/dist/task/source-prepare/parse-intent.js +24 -4
- package/dist/task/source-prepare/prepare.js +298 -1
- package/dist/task/source-prepare/semantic-intake.js +25 -5
- package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
- package/dist/task/source-prepare/types.js +22 -0
- package/dist/task/source-references.js +22 -1
- package/dist/worker/cli.js +18 -2
- package/dist/worker/console/chat/chat-event-store.js +62 -4
- package/dist/worker/console/chat/context-panel.js +7 -0
- package/dist/worker/console/chat/deferred-turn.js +12 -0
- package/dist/worker/console/chat/operation-card.js +8 -1
- package/dist/worker/console/chat/pi-console-config.js +81 -10
- package/dist/worker/console/chat/pi-runtime.js +264 -16
- package/dist/worker/console/chat/provider-error.js +98 -0
- package/dist/worker/console/chat/routes.js +298 -32
- package/dist/worker/console/chat/session-stats.js +179 -0
- package/dist/worker/console/chat/session-store.js +93 -63
- package/dist/worker/console/chat/todos.js +115 -0
- package/dist/worker/console/chat/tool-preview.js +42 -0
- package/dist/worker/console/chat/turn-process.js +20 -55
- package/dist/worker/console/chat/user-questions.js +266 -0
- package/dist/worker/console/chat/workspace-landing.js +14 -0
- package/dist/worker/console/console-handoff.js +82 -0
- package/dist/worker/console/console-update-and-init.js +115 -0
- package/dist/worker/console/console-update-runtime.js +84 -0
- package/dist/worker/console/dag-execution-receipt.js +33 -0
- package/dist/worker/console/draft-store.js +49 -0
- package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
- package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
- package/dist/worker/console/index.js +3 -0
- package/dist/worker/console/inspect-split.js +18 -0
- package/dist/worker/console/native-directory-picker.js +13 -0
- package/dist/worker/console/operation-run-facts.js +19 -3
- package/dist/worker/console/operation-store.js +227 -7
- package/dist/worker/console/operator-actions.js +388 -0
- package/dist/worker/console/operator-surface-health.js +1 -0
- package/dist/worker/console/operator-user-error.js +2 -2
- package/dist/worker/console/prd-intake-bridge.js +13 -0
- package/dist/worker/console/routes.js +355 -3
- package/dist/worker/console/security.js +67 -13
- package/dist/worker/console/server.js +609 -164
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-C4kVYweA.js → abnfDiagram-N423BO3Z-BAsjg7ew.js} +1 -1
- package/dist/worker/console/static/assets/{arc-Bj2M8iO5.js → arc-CyIlrwZw.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CLlXe4-6.js → architectureDiagram-T3A2C74G-Bo4tobhH.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-psEp5xH0.js → blockDiagram-VBNYF7ZC-Dfpow9gu.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DeKcOCGJ.js → c4Diagram-5PPSVZJV-DPmzG_B4.js} +1 -1
- package/dist/worker/console/static/assets/channel-DSrJAn0-.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-K0C744p1.js → chunk-2GRJ4B5K-pKQpB1UW.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-xbNw4J9-.js → chunk-2Q5K7J3B-5n9YYquZ.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLaSDUO.js → chunk-5RXB4S5H-DP3CtA2a.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-CtiPlKel.js → chunk-5VM5RSS4-DYxMJPUy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DZtolir7.js → chunk-6Q2QTUOP-CS3D50Io.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CPcdNeew.js → chunk-GF5L2VYU-gSdDfo5_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-NgHc6V37.js → chunk-JWPE2WC7-A48q0ZNt.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-DQ_T-hg8.js → chunk-KBJHAD2P-ow8Mm3DY.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DgLsxcVP.js → chunk-RYQCIY6F-CMKfLWYE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-UrVoM9z1.js → chunk-XXDRQBXY-BiTBdQPX.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DeMmPl0_.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DeMmPl0_.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CLkYvTb3.js → cose-bilkent-JH36ORCC-Cm7exRz_.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BwT_xKrE.js → cynefin-VYW2F7L2-D9O5qGOu.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bi9tuzif.js → cynefinDiagram-MW4NZA55-CkvQnako.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BCIqkWBV.js → dagre-VZM6K2ZE-B1rzp7CB.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dip6l9_Z.js → diagram-7IWD3JNH-BP07Ipcc.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-B-xkh_wK.js → diagram-B4RE2ZJO-BlPzweQb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DZO0kTt_.js → diagram-LBJQPF4R-CxPa7n0S.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-D6ZplNbZ.js → diagram-Q27KOJAE-CMTZs53A.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPekbhoS.js → diagram-UB23O5K3-CxG_X52r.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-BtmaJpK5.js → ebnfDiagram-BXEA7PRR-D8axtJM0.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-6DS0Xc44.js → erDiagram-JOGREHBK-DIsGzn7b.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CihnROSm.js → flowDiagram-UKHOOZJN-CU9zkDG0.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CZC4zOE2.js → ganttDiagram-PKOTCBZU-DCjTmz5P.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js → gitGraphDiagram-DS77QQ5N-BksdmFzg.js} +1 -1
- package/dist/worker/console/static/assets/index-B-O5ChYq.css +1 -0
- package/dist/worker/console/static/assets/index-CfnY8AQx.js +407 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DlSl4BGx.js → infoDiagram-6WML65LV-CGzzzJtL.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-snnzFl_U.js → ishikawaDiagram-WSZJBQD7-BdseB80N.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-BDE7qpMx.js → journeyDiagram-NVQOT4AX-DM9gsgha.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-CD2Ci04G.js → kanban-definition-27J2QSJJ-3q-_9R2b.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DdnapKIH.js → linear-B8N-Mxsd.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BVjAT9b8.js → mermaid.core-EPIHUUsu.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-D0yJk-zA.js → mindmap-definition-FAOFIHXS-CxwO12aa.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVo9tFP-.js → pegDiagram-VL7TDLO6-bPqbVX6Y.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DnOV-mZ_.js → pieDiagram-7S7Q4E2Y-KzqIvzeX.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-CzUJo58i.js → quadrantDiagram-CIZ2JOQS-CyofpWiV.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Bvikrolh.js → railroadDiagram-AXF67PYL-cTWJvLTP.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-DtaSVCap.js → requirementDiagram-LRYGKXZP-BK--q27B.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-C2c9A0wW.js → sankeyDiagram-W5VNT64P-C0SDOHXK.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DmXJcU7r.js → sequenceDiagram-SI44F4Z6-Cong6YIo.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B4GUFW92.js → sizeCapture-X5ZJPWSS-DUVkgZx8.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Dsad2MXf.js → stateDiagram-OKZ733FA-C7XgxuZg.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Dzbnd5oX.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DGq48Fbi.js → swimlanes-SLNWSIFB-D9Ayvwcy.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BY0hHk6G.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CSSi6OFf.js → timeline-definition-Z64GVDOM-Byb000cH.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BqyzPrWv.js → vennDiagram-T6HMQDX7-DMLegPt4.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DlznVb6S.js → wardleyDiagram-T6FBY63Y-ChMMeOsP.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CfBcgJ_K.js → xychartDiagram-ELKLHX3M-bEMEPisW.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/active-run-badge.js +17 -0
- package/dist/worker/console/static-src/app/console-types.js +68 -4
- package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
- package/dist/worker/console/static-src/app/useOperatorActions.js +41 -6
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +45 -10
- package/dist/worker/console/static-src/app/useRunProgress.js +47 -0
- package/dist/worker/console/static-src/app/useTaskWizard.js +74 -2
- package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
- package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +140 -8
- package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
- package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
- package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
- package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
- package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +16 -3
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +168 -72
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +102 -21
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +184 -4
- package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
- package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
- package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
- package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
- package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +337 -0
- package/dist/worker/console/workspace-context.js +344 -0
- package/dist/worker/console/workspace-registry.js +214 -0
- package/dist/worker/loop-agent/loop-agent-client.js +7 -3
- package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
- package/dist/worker/materialize/harness-task-lineage.js +5 -2
- package/dist/worker/observability/init-runtime-activity.js +26 -0
- package/dist/worker/observability/read-model.js +22 -0
- package/dist/worker/observe/node-input.js +160 -3
- package/dist/worker/observe/node-process.js +377 -0
- package/dist/worker/observe/routes.js +224 -3
- package/dist/worker/observe/server.js +4 -0
- package/dist/worker/observe/shell-handler-keys.js +34 -0
- package/dist/worker/observe/static/api.js +90 -4
- package/dist/worker/observe/static/app.js +18 -70
- package/dist/worker/observe/static/constants.js +8 -1
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
- package/dist/worker/observe/static/dag-node-purpose.js +208 -0
- package/dist/worker/observe/static/format.js +60 -0
- package/dist/worker/observe/static/index.html +6 -1
- package/dist/worker/observe/static/inspect-workspace.js +307 -0
- package/dist/worker/observe/static/markdown-render.js +20 -1
- package/dist/worker/observe/static/operator-chrome.css +145 -20
- package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
- package/dist/worker/observe/static/operator-chrome.js +330 -96
- package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
- package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
- package/dist/worker/observe/static/router.d.ts +46 -0
- package/dist/worker/observe/static/router.js +25 -1
- package/dist/worker/observe/static/state.d.ts +50 -0
- package/dist/worker/observe/static/state.js +184 -1
- package/dist/worker/observe/static/styles.css +395 -0
- package/dist/worker/observe/static/views/dag-graph.js +4 -2
- package/dist/worker/observe/static/views/dag-inspector.js +1067 -9
- package/dist/worker/observe/static/views/dag.d.ts +13 -0
- package/dist/worker/observe/static/views/dag.js +14 -5
- package/dist/worker/observe/static/views/dashboard.js +6 -4
- package/dist/worker/observe/static/views/failures.js +5 -2
- package/dist/worker/observe/static/views/night.js +2 -2
- package/dist/worker/observe/static/views/pool.js +1 -0
- package/dist/worker/observe/static/views/run.js +3 -1
- package/dist/worker/observe/static/views/session-timeline.js +78 -9
- package/dist/worker/observe/static/views/task.js +56 -1
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +49 -3
- package/dist/workflows/dag/backend-test-markdown-workflow.js +176 -1
- package/dist/workflows/dag/backend-test-pytest-collection.js +98 -14
- package/dist/workflows/dag/backend-test-writer-completeness.js +10 -5
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/contract-validator-registrations.js +1 -2
- package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
- package/dist/workflows/dag/dynamic-runtime/map.js +1 -1
- package/dist/workflows/dag/failure-category.js +7 -116
- package/dist/workflows/dag/frontend-closeout.js +221 -0
- package/dist/workflows/dag/frontend-design-policy.js +400 -0
- package/dist/workflows/dag/frontend-human-decision.js +182 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +538 -166
- package/dist/workflows/dag/frontend-plan-render.js +24 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +388 -392
- package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
- package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
- package/dist/workflows/dag/frontend-recovery-controller.js +202 -0
- package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
- package/dist/workflows/dag/frontend-recovery-plan.js +17 -10
- package/dist/workflows/dag/frontend-recovery-run.js +33 -20
- package/dist/workflows/dag/frontend-repair.js +7 -424
- package/dist/workflows/dag/frontend-review-context.js +288 -14
- package/dist/workflows/dag/frontend-review-findings.js +270 -0
- package/dist/workflows/dag/frontend-risk.js +15 -2
- package/dist/workflows/dag/frontend-shadow-dual-write.js +814 -0
- package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
- package/dist/workflows/dag/frontend-shape-facts.js +409 -0
- package/dist/workflows/dag/frontend-shape.js +427 -0
- package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
- package/dist/workflows/dag/frontend-split-application-service.js +203 -0
- package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
- package/dist/workflows/dag/frontend-test-case-checklist.js +30 -4
- package/dist/workflows/dag/frontend-test-case-manifest.js +11 -4
- package/dist/workflows/dag/frontend-test-case-quality.js +11 -16
- package/dist/workflows/dag/frontend-test-environment-probe.js +230 -0
- package/dist/workflows/dag/frontend-test-html-report.js +3 -1
- package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
- package/dist/workflows/dag/frontend-test-layout.js +159 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +188 -42
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +70 -0
- package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
- package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
- package/dist/workflows/dag/frontend-verification-trace.js +52 -17
- package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
- package/dist/workflows/dag/frontend-writer-admission.js +272 -0
- package/dist/workflows/dag/frontend-writer-status.js +244 -0
- package/dist/workflows/dag/init-hybrid.js +984 -613
- package/dist/workflows/dag/interrupt-request.js +10 -3
- package/dist/workflows/dag/lifecycle.js +3 -3
- package/dist/workflows/dag/node-execution.js +468 -58
- package/dist/workflows/dag/prompt.js +44 -19
- package/dist/workflows/dag/recovery-lease.js +80 -0
- package/dist/workflows/dag/report.js +37 -1
- package/dist/workflows/dag/rerun-feedback.js +124 -1
- package/dist/workflows/dag/rerun-plan.js +144 -5
- package/dist/workflows/dag/rerun-run.js +81 -6
- package/dist/workflows/dag/rerun-task.js +29 -0
- package/dist/workflows/dag/retry-policy.js +318 -8
- package/dist/workflows/dag/runner.js +429 -122
- package/dist/workflows/dag/scheduler.js +114 -16
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +321 -31
- package/dist/workflows/dag/upstream-artifacts.js +0 -4
- package/dist/workflows/dag/validate.js +92 -32
- package/docs/README.md +2 -0
- package/docs/architecture/evolution.md +45 -0
- package/docs/init-surface.manifest.json +9 -0
- package/docs/operations/README.md +1 -1
- package/docs/operations/local-development-environment.md +21 -0
- package/docs/templates/README.md +2 -1
- package/docs/templates/agent-dag-report.schema.json +8 -2
- package/docs/templates/agent-dag.schema.json +45 -1
- package/docs/templates/frontend-implementation-contract.schema.json +684 -24
- package/docs/templates/frontend-test-case-checklist.md +2 -2
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/docs/templates/init-managed-agents.md +13 -3
- package/docs/templates/spec-registry.schema.json +45 -0
- package/harness.json +3 -3
- package/package.json +7 -1
- package/scripts/next-info.mjs +356 -0
- package/scripts/next-publish-gate.mjs +238 -0
- package/scripts/release-source-binding.mjs +251 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/fe-test-ui-scout/SKILL.md +65 -0
- package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
- package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
- package/skills/frontend-bounded-implement/SKILL.md +8 -14
- package/skills/frontend-design-review/SKILL.md +20 -41
- package/skills/frontend-implementation/SKILL.md +3 -4
- package/skills/frontend-implementation/references/design-spec.md +15 -10
- package/skills/frontend-implementation/references/node-contracts.md +23 -13
- package/skills/frontend-review/SKILL.md +22 -14
- package/skills/frontend-review/references/review-findings.md +6 -7
- package/skills/loop-agent/references/command-reference.md +12 -4
- package/skills/loop-agent/references/hybrid-dag.md +8 -1
- package/skills/playwright-cli/SKILL.md +23 -1
- package/skills/playwright-cli-case-generator/SKILL.md +29 -8
- package/dist/worker/console/static/assets/channel-CPF4N7pf.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +0 -1
- package/dist/worker/console/static/assets/index-DTZOKgAn.js +0 -404
- package/dist/worker/console/static/assets/index-Ya5FE7cD.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +0 -8
package/README.md
CHANGED
|
@@ -47,12 +47,14 @@ npm install -g @tea-agent/loop-agent@0.37.5 # 精确、可复现
|
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
49
|
loop-agent init instructions --repo-root .
|
|
50
|
-
loop-agent init --repo-root . --
|
|
50
|
+
loop-agent init model-catalog --repo-root . --json
|
|
51
|
+
loop-agent init --repo-root . --profile full --merge \
|
|
52
|
+
--low-model <provider/model> --med-model <provider/model> --high-model <provider/model>
|
|
51
53
|
loop-agent init doctor --repo-root .
|
|
52
54
|
loop-agent inspect --repo-root .
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
`init model-catalog` 会通过 Pi runtime 与 OpenCode 的非 verbose 列表发现本机可用模型,只输出白名单模型元数据、Pi setup 状态和 provider 凭据就绪状态,不输出原始配置或凭据。已有 LOW/MED/HIGH 只要仍存在于 Pi 就保持不变;只有已移除或缺失的档位才由模型结合项目、能力、成本和上下文窗口重选。如果 Pi 没有模型定义,初始化模型会先向用户补齐 provider/model、API/base URL、上下文窗口、最大输出等无法推断的信息并协助配置;如果只是凭据缺失,则保留 harness 选择并修复认证。初始化会保留已有用户内容,并补充 `AGENTS.md`、`harness.json`、`ai_workspace/loop-agent/`、`.agents/skills/`、`.harness/` 和验证脚本等治理入口。
|
|
56
58
|
|
|
57
59
|
控制器升级后,旧项目可能仍使用过期的 repo-local skills、模板、managed blocks 和治理说明。普通安全仓库命令结束时会自动检测目标项目是否需要对齐:非 TTY 只向 stderr 输出提示且不写入目标;TTY 且无 human decisions、无活跃 DAG/Worker 时,可经明确 `y/yes` 同意后应用 deterministic safe actions;也可手动运行统一入口:
|
|
58
60
|
|
|
@@ -66,11 +68,11 @@ loop-agent init reconcile --repo-root .
|
|
|
66
68
|
|
|
67
69
|
```bash
|
|
68
70
|
loop-agent init upgrade --repo-root . --json
|
|
69
|
-
# controller
|
|
71
|
+
# controller 返回当前单文件 merge task 后(其余任务已在同一次计划中排队):
|
|
70
72
|
loop-agent init upgrade --repo-root . --run-id <run-id> --continue --json
|
|
71
73
|
```
|
|
72
74
|
|
|
73
|
-
它在 `.harness/init-upgrades/<run-id>/`
|
|
75
|
+
它在 `.harness/init-upgrades/<run-id>/` 保存身份、一次性模型目录与 surface 计划、动作收据、合并队列、验证与报告。固定投影文件按 recorded ownership 确定性新增、更新或安全删除;用户改过的文件和项目自适应内容才进入模型合并。多个合并仍逐文件限制 `allowedPaths`,但接受后直接激活下一项,不重复版本发现和全量规划;全部处理完只执行一次最终验证。`harness.json` 按属性结构新增/删除字段并保留项目值,同时同步 schema。已完成的 `--status` / `--report` 只读取控制器哈希锚定的证据,不重新执行项目脚本。默认管理项目 `.opencode/plugins/`、`.pi/extensions/` 和 `.pi/settings.json`,不会默认写 `~/.pi/agent/settings.json`。旧项目首次执行后需 reload 宿主会话。明确「检查初始化更新」「只检查,不要修改」仍只运行 `init check-update`。
|
|
74
76
|
|
|
75
77
|
完整说明见[初始化目标项目](website/docs/quick-start/init-target-project.md)。
|
|
76
78
|
|
|
@@ -114,7 +116,7 @@ loop-agent dag report --run-id <run-id>
|
|
|
114
116
|
| --- | --- | --- |
|
|
115
117
|
| 受治理 CLI | `loop-agent …` / `agent-worker …` | 权威写入与诊断 |
|
|
116
118
|
| Loop Operator Console | `agent-worker console` | Official 本地控制面(默认 repo=当前目录、`127.0.0.1:8790`,含 Operate 与 Inspect) |
|
|
117
|
-
| Inspect(只读) | `agent-worker console` → `/inspect/`;`observe snapshot` | 统一 Console 内只读检视;`observe serve` 已下线(REMOVED / exit 2
|
|
119
|
+
| Inspect(只读) | `agent-worker console` → `/inspect/`;`observe snapshot` | 统一 Console 内只读检视;`observe serve` 已下线(REMOVED / exit 2)。实验例外:节点 inspector 默认显示失败节点「提示词重启」tab;紧急回退可设置 `HARNESS_DAG_RERUN_PROMPT_OVERRIDE=0`(也接受 `false` / `off`),关闭后不注入任何 mutation token |
|
|
118
120
|
|
|
119
121
|
```bash
|
|
120
122
|
# 终端 A:Console(任务/运行操作面;canonical mutation 只经 sibling loop-agent)
|
|
@@ -124,6 +126,8 @@ agent-worker console doctor --repo .
|
|
|
124
126
|
|
|
125
127
|
```
|
|
126
128
|
|
|
129
|
+
裸 `agent-worker console` 不在终端询问升级。Operate 右上角提供非阻塞的更新入口,默认选择 npm `latest` 稳定版,也可由操作者显式选择 `next` 预发布版;更新前会先检查活跃运行和全局安装来源。`console doctor`、帮助和版本命令均不触发更新检查。
|
|
130
|
+
|
|
127
131
|
访问 Console <http://127.0.0.1:8790/>;**Operator Chat Official** 是 Console 内的主引导交互,默认打开「对话」工作区。构建时设置 `VITE_OPERATOR_CHAT_DEFAULT_LANDING=tasks` 可改回 Tasks;URL hash(`#/tasks`)与 localStorage 仍优先于默认值。顶部「检视」以及 `/inspect/` 提供只读 Dashboard、DAG、时间线与 artifacts;`loop-agent …` / `agent-worker …` CLI direct path 仍是受治理 fallback。当前状态为 **code ready, dogfood pending/unmet**,不宣称已替代 openCode 或其他外部主会话。
|
|
128
132
|
|
|
129
133
|
## 核心边界
|
package/bin/loop-agent.js
CHANGED
|
@@ -18,11 +18,15 @@ if (!existsSync(cliEntry)) {
|
|
|
18
18
|
* to silently execute a dist/ that predates the latest source edit. The
|
|
19
19
|
* classic failure mode is editing src/** and running the bin without
|
|
20
20
|
* `npm run build`, which executes the previous build. Suppress with
|
|
21
|
-
* --ignore-stale-dist
|
|
21
|
+
* --ignore-stale-dist (or LOOP_AGENT_IGNORE_STALE_DIST=1, which sibling
|
|
22
|
+
* processes such as a Console-spawned CLI inherit automatically) when
|
|
23
|
+
* intentionally running a stale build.
|
|
22
24
|
*/
|
|
23
25
|
const srcDir = join(packageRoot, "src");
|
|
24
|
-
const ignoreStale =
|
|
25
|
-
|
|
26
|
+
const ignoreStale =
|
|
27
|
+
process.argv.includes("--ignore-stale-dist") ||
|
|
28
|
+
process.env.LOOP_AGENT_IGNORE_STALE_DIST === "1";
|
|
29
|
+
if (process.argv.includes("--ignore-stale-dist")) {
|
|
26
30
|
process.argv = process.argv.filter((arg) => arg !== "--ignore-stale-dist");
|
|
27
31
|
}
|
|
28
32
|
if (!ignoreStale && existsSync(srcDir)) {
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { createTask, getTaskPaths, loadTaskConfig, } from "../../task/runtime.js";
|
|
4
4
|
import { importPrdDocument } from "../../task/source-references.js";
|
|
5
5
|
import { prepareTaskSource } from "../../task/source-prepare/index.js";
|
|
6
|
+
import { resolveProductionSourceFidelityPi } from "../../task/source-prepare/source-fidelity-pi.js";
|
|
6
7
|
import { isIntakeSoftGapCode, resolvePrdImportRole, } from "../../task/source-prepare/artifact-meta.js";
|
|
7
8
|
import { sanitizeDraftPlaceholders } from "../../task/source-prepare/placeholder-paths.js";
|
|
8
9
|
import { evaluateSemanticIntakeEligibility, isSemanticIntakeDisabled, readSemanticIntakeAttempted, runSemanticIntake, } from "../../task/source-prepare/semantic-intake.js";
|
|
@@ -585,6 +586,15 @@ export async function advanceTaskLifecycle(input) {
|
|
|
585
586
|
continue;
|
|
586
587
|
}
|
|
587
588
|
if (action.type === "prepare-contract") {
|
|
589
|
+
// 生产 source fidelity Pi 接线(AC-PROD-001/005):仅 frontend-implementation
|
|
590
|
+
// 任务注入 reconcile executor + 独立 reviewer;ineligible 返回 undefined 不接线。
|
|
591
|
+
// 主路径与 semantic-intake retry 路径共用同一接线,保证任意一条生产路径都实际
|
|
592
|
+
// 触发 reconciliation executor(修复前两处均缺省导致生产路径从不调用 Pi)。
|
|
593
|
+
const sourceFidelity = await resolveProductionSourceFidelityPi({
|
|
594
|
+
repoRoot: input.repoRoot,
|
|
595
|
+
taskId: input.taskId,
|
|
596
|
+
taskKind: input.taskKind,
|
|
597
|
+
});
|
|
588
598
|
let draftIntent = null;
|
|
589
599
|
if (input.fromDraftPath) {
|
|
590
600
|
try {
|
|
@@ -635,6 +645,7 @@ export async function advanceTaskLifecycle(input) {
|
|
|
635
645
|
verifyCommands: effectiveInput.verifyCommands,
|
|
636
646
|
backendTest: input.backendTest,
|
|
637
647
|
},
|
|
648
|
+
...(sourceFidelity ? { sourceFidelity } : {}),
|
|
638
649
|
});
|
|
639
650
|
if (!prepareResult.ok) {
|
|
640
651
|
const gapCodes = (prepareResult.gaps ?? [])
|
|
@@ -712,6 +723,7 @@ export async function advanceTaskLifecycle(input) {
|
|
|
712
723
|
verifyCommands: effectiveInput.verifyCommands,
|
|
713
724
|
backendTest: input.backendTest,
|
|
714
725
|
},
|
|
726
|
+
...(sourceFidelity ? { sourceFidelity } : {}),
|
|
715
727
|
});
|
|
716
728
|
if (retry.ok) {
|
|
717
729
|
warnings.push({
|
|
@@ -42,6 +42,7 @@ export async function buildTaskLifecycleRecommendations(input) {
|
|
|
42
42
|
const allowedPaths = [];
|
|
43
43
|
const verifyCommands = [];
|
|
44
44
|
// 1) managed task config
|
|
45
|
+
let hasDeclaredManagedVerify = false;
|
|
45
46
|
try {
|
|
46
47
|
const config = await loadTaskConfig(input.repoRoot, input.taskId);
|
|
47
48
|
for (const glob of config.allowedPaths ?? []) {
|
|
@@ -53,7 +54,9 @@ export async function buildTaskLifecycleRecommendations(input) {
|
|
|
53
54
|
source: "managed-task-config",
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
const managedVerify = (config.verifyCommands ?? []).filter((cmd) => Boolean(cmd.command?.trim()));
|
|
58
|
+
hasDeclaredManagedVerify = managedVerify.length > 0;
|
|
59
|
+
for (const cmd of managedVerify) {
|
|
57
60
|
const label = cmd.label?.trim() || "verify";
|
|
58
61
|
const command = cmd.command?.trim();
|
|
59
62
|
if (!command)
|
|
@@ -70,14 +73,22 @@ export async function buildTaskLifecycleRecommendations(input) {
|
|
|
70
73
|
// task may not exist yet
|
|
71
74
|
}
|
|
72
75
|
// 2) package.json scripts (only if not already covered by managed config)
|
|
76
|
+
// The full-suite `test` script is recommended only when the task declares
|
|
77
|
+
// NO managed verifyCommands at all. Once a task configures a targeted
|
|
78
|
+
// verify set (e.g. per-change typecheck + a scoped vitest run), the full
|
|
79
|
+
// `npm run test` must never be auto-added: it validates the whole repo,
|
|
80
|
+
// costs far more than the change under review, and can fail on unrelated
|
|
81
|
+
// pre-existing breakage, turning a targeted verify green into a hard fail.
|
|
73
82
|
const scripts = await readPackageScripts(input.repoRoot);
|
|
74
83
|
const hasVerifyLabel = (label) => verifyCommands.some((entry) => entry.label === label);
|
|
75
84
|
const scriptCandidates = [
|
|
76
85
|
{ label: "typecheck", script: "typecheck" },
|
|
77
|
-
{ label: "test", script: "test" },
|
|
78
86
|
{ label: "check-repo", script: "check:repo" },
|
|
79
87
|
{ label: "check-repo", script: "check-repo" },
|
|
80
88
|
];
|
|
89
|
+
if (!hasDeclaredManagedVerify) {
|
|
90
|
+
scriptCandidates.push({ label: "test", script: "test" });
|
|
91
|
+
}
|
|
81
92
|
for (const candidate of scriptCandidates) {
|
|
82
93
|
const scriptBody = scripts[candidate.script];
|
|
83
94
|
if (!scriptBody)
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.39.0-beta.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-08-
|
|
3
|
+
"version": "0.39.0-beta.10",
|
|
4
|
+
"gitSha": "f6ea22730a28e6556983394e41560c0d8d18a852",
|
|
5
|
+
"builtAt": "2026-08-27T07:03:53.753Z"
|
|
6
6
|
}
|
|
@@ -7,6 +7,7 @@ import { runCoverageReport } from "../commands/coverage-report.js";
|
|
|
7
7
|
import { runExamples } from "../commands/examples.js";
|
|
8
8
|
import { runHandoffCheck } from "../commands/handoff-check.js";
|
|
9
9
|
import { runInspect } from "../commands/inspect.js";
|
|
10
|
+
import { runInspectNext } from "../commands/inspect-next.js";
|
|
10
11
|
import { runInstructions } from "../commands/instructions.js";
|
|
11
12
|
import { runTaskAdvance } from "../commands/task-advance.js";
|
|
12
13
|
import { runTaskStatus } from "../commands/task-status.js";
|
|
@@ -34,6 +35,7 @@ import { runDagReconcileTasks } from "../commands/dag-reconcile-tasks.js";
|
|
|
34
35
|
import { runDagReconcileRun } from "../commands/dag-reconcile-run.js";
|
|
35
36
|
import { runDagRequestInterrupt } from "../commands/dag-request-interrupt.js";
|
|
36
37
|
import { runDagRerunTask } from "../commands/dag-rerun-task.js";
|
|
38
|
+
import { runDagFollowUp } from "../commands/dag-follow-up.js";
|
|
37
39
|
import { runDagRerun } from "../commands/dag-rerun.js";
|
|
38
40
|
import { runDagResume } from "../commands/dag-resume.js";
|
|
39
41
|
import { runDagDecisionInspect, runDagDecisionValidate, } from "../workflows/dag/decision-envelope.js";
|
|
@@ -74,6 +76,7 @@ export function parseSummaryFlag(tokens) {
|
|
|
74
76
|
const DOCS_SUBCOMMANDS = ["audit", "archive"];
|
|
75
77
|
const INIT_SUBCOMMANDS = [
|
|
76
78
|
"instructions",
|
|
79
|
+
"model-catalog",
|
|
77
80
|
"doctor",
|
|
78
81
|
"check-update",
|
|
79
82
|
"update",
|
|
@@ -133,6 +136,7 @@ const DAG_SUBCOMMANDS = [
|
|
|
133
136
|
"request-interrupt",
|
|
134
137
|
"rerun",
|
|
135
138
|
"rerun-task",
|
|
139
|
+
"follow-up",
|
|
136
140
|
"reconcile-tasks",
|
|
137
141
|
"final-verification",
|
|
138
142
|
"decision",
|
|
@@ -162,10 +166,19 @@ export const COMMAND_DEFINITIONS = [
|
|
|
162
166
|
name: "inspect",
|
|
163
167
|
adapter: "required",
|
|
164
168
|
tier: "operator",
|
|
165
|
-
intent: "Inspect the target repo harness manifest.",
|
|
166
|
-
usage: "inspect",
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
intent: "Inspect the target repo harness manifest, or report the current npm next binding.",
|
|
170
|
+
usage: "inspect | inspect next [--json]",
|
|
171
|
+
subcommands: ["next"],
|
|
172
|
+
handler: async ({ adapter, repoRoot, subcommand, rest }) => {
|
|
173
|
+
if (subcommand === "next") {
|
|
174
|
+
await runInspectNext(repoRoot, rest.filter((arg) => Boolean(arg)));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (subcommand === undefined || subcommand.startsWith("-")) {
|
|
178
|
+
await runInspect(adapter, repoRoot);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
throw new Error("usage: inspect | inspect next [--json]");
|
|
169
182
|
},
|
|
170
183
|
},
|
|
171
184
|
{
|
|
@@ -205,7 +218,7 @@ export const COMMAND_DEFINITIONS = [
|
|
|
205
218
|
adapter: "none",
|
|
206
219
|
tier: "primary",
|
|
207
220
|
intent: "Initialize a target repository with loop-agent harness capabilities.",
|
|
208
|
-
usage: "init [instructions|doctor|check-update|update|reconcile|upgrade] [--profile full|minimal] [--merge] [--json|--markdown] [--bootstrap-surface|--apply-safe] [--client-recovery=auto|project|user|off] [--run-id <id> --status|--continue|--report]",
|
|
221
|
+
usage: "init [instructions|model-catalog|doctor|check-update|update|reconcile|upgrade] [--profile full|minimal] [--merge] [--model provider/model | --low-model provider/model --med-model provider/model --high-model provider/model] [--json|--markdown] [--bootstrap-surface|--apply-safe] [--client-recovery=auto|project|user|off] [--run-id <id> --status|--continue|--report]",
|
|
209
222
|
subcommands: [...INIT_SUBCOMMANDS],
|
|
210
223
|
handler: async ({ repoRoot, subcommand, rest }) => {
|
|
211
224
|
await runInit(repoRoot, [subcommand, ...rest].filter(Boolean), { readRuntimeActivity: readInitRuntimeActivity });
|
|
@@ -566,6 +579,11 @@ export const COMMAND_DEFINITIONS = [
|
|
|
566
579
|
await runDagRerunTask(repoRoot, rerunTaskArgs);
|
|
567
580
|
return;
|
|
568
581
|
}
|
|
582
|
+
if (subcommand === "follow-up") {
|
|
583
|
+
const followUpArgs = rest.filter((arg) => Boolean(arg));
|
|
584
|
+
await runDagFollowUp(repoRoot, followUpArgs);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
569
587
|
if (subcommand === "reconcile-tasks") {
|
|
570
588
|
const reconcileArgs = rest.filter((arg) => Boolean(arg));
|
|
571
589
|
await runDagReconcileTasks(repoRoot, reconcileArgs);
|
package/dist/cli/program.js
CHANGED
|
@@ -13,6 +13,7 @@ import { runDagReconcileTasks } from "../commands/dag-reconcile-tasks.js";
|
|
|
13
13
|
import { runDagReconcileRun } from "../commands/dag-reconcile-run.js";
|
|
14
14
|
import { runDagRequestInterrupt } from "../commands/dag-request-interrupt.js";
|
|
15
15
|
import { runDagRerunTask } from "../commands/dag-rerun-task.js";
|
|
16
|
+
import { runDagFollowUp } from "../commands/dag-follow-up.js";
|
|
16
17
|
import { runDagRerun } from "../commands/dag-rerun.js";
|
|
17
18
|
import { runDagReject } from "../commands/dag-reject.js";
|
|
18
19
|
import { runDagCloseoutDraft, runDagReport } from "../commands/dag-report.js";
|
|
@@ -33,6 +34,7 @@ import { runHarvest } from "../commands/harvest.js";
|
|
|
33
34
|
import { runInit } from "../commands/init.js";
|
|
34
35
|
import { readInitRuntimeActivity } from "./update/runtime-activity.js";
|
|
35
36
|
import { runInspect } from "../commands/inspect.js";
|
|
37
|
+
import { runInspectNext } from "../commands/inspect-next.js";
|
|
36
38
|
import { runInstructions } from "../commands/instructions.js";
|
|
37
39
|
import { runKnowledge } from "../commands/knowledge.js";
|
|
38
40
|
import { runLoop } from "../commands/loop.js";
|
|
@@ -97,6 +99,9 @@ async function dispatchRegisteredCommand(commandObject, defaultRepoRoot, rawArgs
|
|
|
97
99
|
[...rest, ...rawArgs].some((token) => token === "--json")) ||
|
|
98
100
|
(command === "stats" &&
|
|
99
101
|
subcommand === "context" &&
|
|
102
|
+
[...rest, ...rawArgs].some((token) => token === "--json")) ||
|
|
103
|
+
(command === "inspect" &&
|
|
104
|
+
subcommand === "next" &&
|
|
100
105
|
[...rest, ...rawArgs].some((token) => token === "--json"));
|
|
101
106
|
const repoRoot = resolveRepoRootOnly(commandObject, defaultRepoRoot, {
|
|
102
107
|
quiet,
|
|
@@ -125,8 +130,15 @@ async function runTaskCommand(repoRoot, subcommand, rest) {
|
|
|
125
130
|
async function runCommanderAction(ctx, command, subcommand, rest) {
|
|
126
131
|
switch (command) {
|
|
127
132
|
case "inspect":
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
if (subcommand === "next") {
|
|
134
|
+
await runInspectNext(ctx.repoRoot, rest);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (subcommand === undefined || subcommand.startsWith("-")) {
|
|
138
|
+
await runInspect(ctx.adapter, ctx.repoRoot);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
throw new Error("usage: inspect | inspect next [--json]");
|
|
130
142
|
case "doctor":
|
|
131
143
|
await runDoctor(ctx.adapter, ctx.repoRoot, compactArgs([subcommand, ...rest]));
|
|
132
144
|
return;
|
|
@@ -341,6 +353,9 @@ async function runDagAction(repoRoot, subcommand, rest) {
|
|
|
341
353
|
case "rerun-task":
|
|
342
354
|
await runDagRerunTask(repoRoot, args);
|
|
343
355
|
return;
|
|
356
|
+
case "follow-up":
|
|
357
|
+
await runDagFollowUp(repoRoot, args);
|
|
358
|
+
return;
|
|
344
359
|
case "reconcile-tasks":
|
|
345
360
|
await runDagReconcileTasks(repoRoot, args);
|
|
346
361
|
return;
|
|
@@ -500,6 +515,7 @@ function addDagCommand(program, defaultRepoRoot) {
|
|
|
500
515
|
"request-interrupt",
|
|
501
516
|
"rerun",
|
|
502
517
|
"rerun-task",
|
|
518
|
+
"follow-up",
|
|
503
519
|
"reconcile-tasks",
|
|
504
520
|
"final-verification",
|
|
505
521
|
], defaultRepoRoot);
|
|
@@ -595,6 +611,9 @@ export function buildLoopAgentProgram(options) {
|
|
|
595
611
|
.option("--no-merge", "skip existing files")
|
|
596
612
|
.option("--provider <provider>", "provider paired with a bare --model (otherwise use provider/model)")
|
|
597
613
|
.option("--model <model>", "qualified provider/model, or a bare model paired with --provider")
|
|
614
|
+
.option("--low-model <provider/model>", "credential-ready Pi model for LOW")
|
|
615
|
+
.option("--med-model <provider/model>", "credential-ready Pi model for MED")
|
|
616
|
+
.option("--high-model <provider/model>", "credential-ready Pi model for HIGH")
|
|
598
617
|
.option("--json", "print JSON")
|
|
599
618
|
.option("--markdown", "print Markdown")
|
|
600
619
|
.option("--bootstrap-surface", "write an inferred .harness/init-surface.json baseline")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
2
|
import { evaluateLatestVersion, shouldCheckForUpdates } from "./policy.js";
|
|
3
|
-
import { acquireUpdateLock, readUpdateState, updateLockPath, updateStatePath, writeUpdateState, } from "
|
|
3
|
+
import { acquireUpdateLock, readUpdateState, updateLockPath, updateStatePath, writeUpdateState, } from "../../shared/update/state.js";
|
|
4
4
|
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
5
5
|
const FAILURE_COOLDOWN_MS = 10 * 60 * 1000;
|
|
6
6
|
export async function runSelfUpdateNotifier(options) {
|
|
@@ -69,7 +69,7 @@ export async function runSelfUpdateNotifier(options) {
|
|
|
69
69
|
}
|
|
70
70
|
writeStderr(`loop-agent 已更新到 ${decision.targetVersion};新版本将在下一次调用时生效。\n`);
|
|
71
71
|
await safeWriteState(statePath, {
|
|
72
|
-
|
|
72
|
+
...state,
|
|
73
73
|
lastCheckedAt: now().toISOString(),
|
|
74
74
|
latestVersion: decision.targetVersion,
|
|
75
75
|
});
|
|
@@ -1,29 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { buildGlobalSnapshot } from "../../worker/observability/read-model.js";
|
|
4
|
-
/**
|
|
5
|
-
* Read-only runtime guard for init-surface writes.
|
|
6
|
-
*
|
|
7
|
-
* DAG activeness is anchored to real directories in the canonical active
|
|
8
|
-
* lifecycle root. Worker activeness reuses the Observe read model so Task Pool
|
|
9
|
-
* status precedence and composite identity stay owned by the Worker adapter.
|
|
10
|
-
* Projection failures block writes because liveness cannot be proven safely.
|
|
11
|
-
*/
|
|
12
|
-
export async function readInitRuntimeActivity(repoRoot) {
|
|
13
|
-
const resolvedRoot = path.resolve(repoRoot);
|
|
14
|
-
const activeDagRoot = path.join(resolvedRoot, ".harness", "dag-runs", "active");
|
|
15
|
-
const entries = await readdir(activeDagRoot, { withFileTypes: true }).catch(() => []);
|
|
16
|
-
const activeDagRunIds = entries
|
|
17
|
-
.filter((entry) => entry.isDirectory() && entry.name !== ".gitkeep")
|
|
18
|
-
.map((entry) => entry.name)
|
|
19
|
-
.sort();
|
|
20
|
-
const snapshot = await buildGlobalSnapshot({ repoRoot: resolvedRoot });
|
|
21
|
-
return {
|
|
22
|
-
activeDagRunIds,
|
|
23
|
-
activeWorkerBatches: snapshot.health.worker.activeBatches,
|
|
24
|
-
activeWorkerTasks: snapshot.health.worker.activeTasks,
|
|
25
|
-
...(snapshot.projectionError
|
|
26
|
-
? { workerProjectionError: snapshot.projectionError.message }
|
|
27
|
-
: {}),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
1
|
+
export { readInitRuntimeActivity } from "../../worker/observability/init-runtime-activity.js";
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import os from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { buildLoopAgentProgram } from "./cli/program.js";
|
|
7
|
-
import { createNpmUpdateClient } from "./
|
|
7
|
+
import { createNpmUpdateClient } from "./shared/update/npm-client.js";
|
|
8
8
|
import { runSelfUpdateNotifier } from "./cli/update/notifier.js";
|
|
9
9
|
import { resolveInitSurfaceRepoRoot, runInitSurfaceNotifier, } from "./cli/update/init-surface-notifier.js";
|
|
10
10
|
async function main() {
|
|
@@ -29,6 +29,7 @@ async function main() {
|
|
|
29
29
|
client: createNpmUpdateClient({
|
|
30
30
|
currentVersion,
|
|
31
31
|
packageRoot,
|
|
32
|
+
cwd: defaultRepoRoot,
|
|
32
33
|
env: process.env,
|
|
33
34
|
}),
|
|
34
35
|
});
|
|
@@ -1356,12 +1356,15 @@ export async function runClientRecovery(input) {
|
|
|
1356
1356
|
}
|
|
1357
1357
|
const plugin = await installProjectOpenCodePlugin({
|
|
1358
1358
|
repoRoot: input.repoRoot,
|
|
1359
|
+
onlyIfMissing: true,
|
|
1359
1360
|
});
|
|
1360
1361
|
const overflowPlugin = await installProjectOpenCodeOverflowCompactPlugin({
|
|
1361
1362
|
repoRoot: input.repoRoot,
|
|
1363
|
+
onlyIfMissing: true,
|
|
1362
1364
|
});
|
|
1363
1365
|
const piExtension = await installProjectPiContextOverflowExtension({
|
|
1364
1366
|
repoRoot: input.repoRoot,
|
|
1367
|
+
onlyIfMissing: true,
|
|
1365
1368
|
});
|
|
1366
1369
|
const pi = await applyProjectPiSettingsMerge({ repoRoot: input.repoRoot });
|
|
1367
1370
|
if (mode !== "user") {
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { FRONTEND_REVIEW_FINDINGS_PRD_REL, readFrontendReviewFindingsPrd, } from "../workflows/dag/frontend-review-findings.js";
|
|
4
|
+
import { locateDagRun } from "../workflows/dag/lifecycle.js";
|
|
5
|
+
import { createTask, getTaskPaths } from "../task/runtime.js";
|
|
6
|
+
import { importPrdDocument } from "../task/source-references.js";
|
|
7
|
+
function parseFlagValue(rawArgs, flag) {
|
|
8
|
+
const index = rawArgs.indexOf(flag);
|
|
9
|
+
if (index < 0 || index + 1 >= rawArgs.length)
|
|
10
|
+
return undefined;
|
|
11
|
+
return rawArgs[index + 1];
|
|
12
|
+
}
|
|
13
|
+
export function parseDagFollowUpArgs(rawArgs) {
|
|
14
|
+
const positional = rawArgs.filter((arg) => !arg.startsWith("-"));
|
|
15
|
+
const parentRunId = positional[0];
|
|
16
|
+
if (!parentRunId) {
|
|
17
|
+
throw new Error("usage: dag follow-up <parent-run-id> [--task-id <id>] [--execute] [--profile <profile>]");
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
parentRunId,
|
|
21
|
+
taskId: parseFlagValue(rawArgs, "--task-id"),
|
|
22
|
+
execute: rawArgs.includes("--execute"),
|
|
23
|
+
profile: parseFlagValue(rawArgs, "--profile"),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function deriveFollowUpTaskId(parentRunId) {
|
|
27
|
+
// Deterministic, valid task id derived from the parent run id.
|
|
28
|
+
return `${parentRunId}-followup`;
|
|
29
|
+
}
|
|
30
|
+
/** CLI entry: parse raw args and run the follow-up flow. */
|
|
31
|
+
export async function runDagFollowUp(repoRoot, rawArgs) {
|
|
32
|
+
const parsed = parseDagFollowUpArgs(rawArgs);
|
|
33
|
+
const result = await runDagFollowUpInternal(repoRoot, parsed.parentRunId, {
|
|
34
|
+
taskId: parsed.taskId,
|
|
35
|
+
execute: parsed.execute,
|
|
36
|
+
profile: parsed.profile,
|
|
37
|
+
});
|
|
38
|
+
console.log(JSON.stringify(result, null, 2));
|
|
39
|
+
if (!result.ok) {
|
|
40
|
+
process.exitCode = result.mode === "blocked" ? 2 : 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function runDagFollowUpInternal(repoRoot, parentRunId, options = {}) {
|
|
44
|
+
const located = await locateDagRun(repoRoot, parentRunId);
|
|
45
|
+
if (!located) {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
mode: "invalid",
|
|
49
|
+
reason: `dag run not found: ${parentRunId}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const prd = await readFrontendReviewFindingsPrd(located.runDir);
|
|
53
|
+
if (!prd) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
mode: "invalid",
|
|
57
|
+
reason: `no frontend review findings PRD found in run ${parentRunId} (${FRONTEND_REVIEW_FINDINGS_PRD_REL}); the review must have committed request_review_changes`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const taskId = options.taskId ?? deriveFollowUpTaskId(parentRunId);
|
|
61
|
+
try {
|
|
62
|
+
await createTask(repoRoot, taskId, `修复 review 发现(parent ${parentRunId})`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
mode: "blocked",
|
|
68
|
+
reason: `failed to create task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Materialize the PRD draft into the task's source directory so the task
|
|
72
|
+
// lifecycle can import it as its requirement.
|
|
73
|
+
const prdMaterialized = path.join(getTaskPaths(repoRoot, taskId).sourceDir, "review-findings-prd.md");
|
|
74
|
+
try {
|
|
75
|
+
await mkdir(path.dirname(prdMaterialized), { recursive: true });
|
|
76
|
+
await importPrdDocument({
|
|
77
|
+
repoRoot,
|
|
78
|
+
taskId,
|
|
79
|
+
filePath: path.join(located.runDir, FRONTEND_REVIEW_FINDINGS_PRD_REL),
|
|
80
|
+
name: "review-findings-prd",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
mode: "blocked",
|
|
87
|
+
reason: `failed to import PRD into task ${taskId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (!options.execute) {
|
|
91
|
+
return {
|
|
92
|
+
ok: true,
|
|
93
|
+
mode: "created",
|
|
94
|
+
taskId,
|
|
95
|
+
prdPath: prdMaterialized,
|
|
96
|
+
next: {
|
|
97
|
+
kind: "advance",
|
|
98
|
+
command: `loop-agent task advance ${taskId} --task-kind frontend-implementation --json`,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// Execute: advance through the frontend DAG.
|
|
103
|
+
const { advanceTaskLifecycle } = await import("../application/task-lifecycle/advance.js");
|
|
104
|
+
const profile = options.profile === "auto" ||
|
|
105
|
+
options.profile === "minimal" ||
|
|
106
|
+
options.profile === "standard" ||
|
|
107
|
+
options.profile === "reviewed" ||
|
|
108
|
+
options.profile === "supervised"
|
|
109
|
+
? options.profile
|
|
110
|
+
: undefined;
|
|
111
|
+
const result = await advanceTaskLifecycle({
|
|
112
|
+
repoRoot,
|
|
113
|
+
taskId,
|
|
114
|
+
taskKind: "frontend-implementation",
|
|
115
|
+
taskKindExplicit: true,
|
|
116
|
+
...(profile ? { profile, profileExplicit: true } : {}),
|
|
117
|
+
observer: undefined,
|
|
118
|
+
});
|
|
119
|
+
const ok = result.lifecycleState === "run-succeeded" ||
|
|
120
|
+
result.lifecycleState === "awaiting-write-set-approval";
|
|
121
|
+
return {
|
|
122
|
+
ok,
|
|
123
|
+
mode: ok ? "created" : "blocked",
|
|
124
|
+
taskId,
|
|
125
|
+
prdPath: prdMaterialized,
|
|
126
|
+
reason: ok
|
|
127
|
+
? undefined
|
|
128
|
+
: `advance lifecycleState: ${result.lifecycleState}${result.blockers.length > 0
|
|
129
|
+
? `; blockers: ${result.blockers.map((b) => b.code).join(", ")}`
|
|
130
|
+
: ""}`,
|
|
131
|
+
next: ok
|
|
132
|
+
? undefined
|
|
133
|
+
: {
|
|
134
|
+
kind: "advance",
|
|
135
|
+
command: `loop-agent task advance ${taskId} --task-kind frontend-implementation --json`,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { isDagRerunPromptOverrideEnabled } from "../shared/dag-prompt-override.js";
|
|
1
3
|
import { executeDagRerun, planDagRerun, } from "../workflows/dag/rerun-run.js";
|
|
2
4
|
export function parseDagRerunArgs(args) {
|
|
3
5
|
if (args.length === 0) {
|
|
@@ -9,6 +11,8 @@ export function parseDagRerunArgs(args) {
|
|
|
9
11
|
let planHash;
|
|
10
12
|
let requestId;
|
|
11
13
|
let reason;
|
|
14
|
+
const promptOverrideSpecs = [];
|
|
15
|
+
const promptOverrideAppendSpecs = [];
|
|
12
16
|
for (let index = 0; index < args.length; index += 1) {
|
|
13
17
|
const arg = args[index];
|
|
14
18
|
if (arg === "--run-id")
|
|
@@ -33,6 +37,14 @@ export function parseDagRerunArgs(args) {
|
|
|
33
37
|
reason = args[++index];
|
|
34
38
|
else if (arg.startsWith("--reason="))
|
|
35
39
|
reason = arg.slice("--reason=".length);
|
|
40
|
+
else if (arg === "--prompt-override")
|
|
41
|
+
promptOverrideSpecs.push(args[++index] ?? "");
|
|
42
|
+
else if (arg.startsWith("--prompt-override="))
|
|
43
|
+
promptOverrideSpecs.push(arg.slice("--prompt-override=".length));
|
|
44
|
+
else if (arg === "--prompt-override-append")
|
|
45
|
+
promptOverrideAppendSpecs.push(args[++index] ?? "");
|
|
46
|
+
else if (arg.startsWith("--prompt-override-append="))
|
|
47
|
+
promptOverrideAppendSpecs.push(arg.slice("--prompt-override-append=".length));
|
|
36
48
|
else if (arg === "--json")
|
|
37
49
|
continue;
|
|
38
50
|
else if (arg.startsWith("-"))
|
|
@@ -50,7 +62,13 @@ export function parseDagRerunArgs(args) {
|
|
|
50
62
|
if (planHash || requestId || reason) {
|
|
51
63
|
throw new Error("dag rerun --plan cannot be combined with execute flags");
|
|
52
64
|
}
|
|
53
|
-
return {
|
|
65
|
+
return {
|
|
66
|
+
parentRunId,
|
|
67
|
+
selectedNodeId,
|
|
68
|
+
planOnly: true,
|
|
69
|
+
promptOverrideSpecs,
|
|
70
|
+
promptOverrideAppendSpecs,
|
|
71
|
+
};
|
|
54
72
|
}
|
|
55
73
|
if (!planHash?.trim()) {
|
|
56
74
|
throw new Error("dag rerun execute requires --plan-hash <hash>");
|
|
@@ -68,15 +86,50 @@ export function parseDagRerunArgs(args) {
|
|
|
68
86
|
planHash: planHash.trim(),
|
|
69
87
|
requestId: requestId.trim(),
|
|
70
88
|
reason: reason.trim(),
|
|
89
|
+
promptOverrideSpecs,
|
|
90
|
+
promptOverrideAppendSpecs,
|
|
71
91
|
};
|
|
72
92
|
}
|
|
93
|
+
async function loadPromptOverrides(specs, mode) {
|
|
94
|
+
const overrides = [];
|
|
95
|
+
for (const spec of specs) {
|
|
96
|
+
const separator = spec.indexOf("@");
|
|
97
|
+
if (separator <= 0 || separator >= spec.length - 1) {
|
|
98
|
+
throw new Error(`dag rerun --prompt-override${mode === "append" ? "-append" : ""} expects <nodeId>@<filePath>, got: ${spec}`);
|
|
99
|
+
}
|
|
100
|
+
const nodeId = spec.slice(0, separator);
|
|
101
|
+
const filePath = spec.slice(separator + 1);
|
|
102
|
+
let prompt;
|
|
103
|
+
try {
|
|
104
|
+
prompt = await readFile(filePath, "utf-8");
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`cannot read prompt override file for node ${nodeId} (${filePath}): ${error instanceof Error ? error.message : String(error)}`);
|
|
108
|
+
}
|
|
109
|
+
overrides.push(mode === "append" ? { nodeId, prompt, mode } : { nodeId, prompt });
|
|
110
|
+
}
|
|
111
|
+
return overrides;
|
|
112
|
+
}
|
|
73
113
|
export async function runDagRerun(repoRoot, rawArgs) {
|
|
74
114
|
const parsed = parseDagRerunArgs(rawArgs);
|
|
115
|
+
let promptOverrides;
|
|
116
|
+
const hasOverrides = parsed.promptOverrideSpecs.length > 0 ||
|
|
117
|
+
parsed.promptOverrideAppendSpecs.length > 0;
|
|
118
|
+
if (hasOverrides) {
|
|
119
|
+
if (!isDagRerunPromptOverrideEnabled()) {
|
|
120
|
+
throw new Error("prompt override rerun is disabled by HARNESS_DAG_RERUN_PROMPT_OVERRIDE; unset it or use a value other than 0, false, or off to enable this experimental capability");
|
|
121
|
+
}
|
|
122
|
+
promptOverrides = [
|
|
123
|
+
...(await loadPromptOverrides(parsed.promptOverrideSpecs, "replace")),
|
|
124
|
+
...(await loadPromptOverrides(parsed.promptOverrideAppendSpecs, "append")),
|
|
125
|
+
];
|
|
126
|
+
}
|
|
75
127
|
if (parsed.planOnly) {
|
|
76
128
|
const plan = await planDagRerun({
|
|
77
129
|
cwd: repoRoot,
|
|
78
130
|
parentRunId: parsed.parentRunId,
|
|
79
131
|
selectedNodeId: parsed.selectedNodeId,
|
|
132
|
+
promptOverrides,
|
|
80
133
|
});
|
|
81
134
|
const result = {
|
|
82
135
|
ok: plan.eligible,
|
|
@@ -95,6 +148,7 @@ export async function runDagRerun(repoRoot, rawArgs) {
|
|
|
95
148
|
planHash: parsed.planHash,
|
|
96
149
|
requestId: parsed.requestId,
|
|
97
150
|
reason: parsed.reason,
|
|
151
|
+
promptOverrides,
|
|
98
152
|
});
|
|
99
153
|
console.log(JSON.stringify(result, null, 2));
|
|
100
154
|
if (!result.ok) {
|