@tea-agent/loop-agent 0.38.1 → 0.38.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +126 -12
- package/README.md +2 -0
- package/bin/loop-agent.js +7 -3
- package/dist/application/dag/generate-task-dag.js +9 -0
- package/dist/application/task-lifecycle/advance.js +4 -0
- package/dist/build-stamp.json +3 -3
- package/dist/commands/init.js +2 -14
- package/dist/commands/task-advance.js +31 -0
- package/dist/executors/dag-pi-executor.js +99 -5
- package/dist/executors/pi-event-serializer.js +42 -1
- package/dist/executors/pi-executor.js +51 -0
- package/dist/executors/pi-extension-resolver.js +233 -0
- package/dist/executors/pi-sdk-executor.js +187 -59
- package/dist/executors/shell-executor.js +324 -16
- package/dist/executors/shell-write-guard.js +7 -0
- package/dist/governance/manifest-types.js +0 -2
- package/dist/shared/operator/capabilities.js +87 -22
- package/dist/task/config-types.js +22 -0
- package/dist/task/contract/constants.js +1 -0
- package/dist/task/contract/diff.js +26 -0
- package/dist/task/contract/project.js +5 -0
- package/dist/task/contract/schema.js +6 -1
- package/dist/task/source-prepare/build-draft.js +15 -0
- package/dist/worker/console/chat/deferred-turn.js +91 -0
- package/dist/worker/console/chat/pi-runtime.js +10 -5
- package/dist/worker/console/chat/routes.js +458 -47
- package/dist/worker/console/chat/semantic-activity.js +13 -13
- package/dist/worker/console/chat/session-store.js +146 -2
- package/dist/worker/console/harness-pi-model-matrix.js +2 -11
- package/dist/worker/console/operator-actions.js +5 -4
- package/dist/worker/console/pi-readiness.js +5 -4
- package/dist/worker/console/recovery-cta.js +4 -4
- package/dist/worker/console/recovery-error-copy.js +4 -4
- package/dist/worker/console/server.js +6 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Hfsot6rP.js → abnfDiagram-N423BO3Z-C4kVYweA.js} +1 -1
- package/dist/worker/console/static/assets/{arc-YGwEASin.js → arc-Bj2M8iO5.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CmOM0F92.js → architectureDiagram-T3A2C74G-CLlXe4-6.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-DDLuaHC5.js → blockDiagram-VBNYF7ZC-psEp5xH0.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B0Um43W4.js → c4Diagram-5PPSVZJV-DeKcOCGJ.js} +1 -1
- package/dist/worker/console/static/assets/channel-CPF4N7pf.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DvBN4JZc.js → chunk-2GRJ4B5K-K0C744p1.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B1UVgW4E.js → chunk-2Q5K7J3B-xbNw4J9-.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-Cf0GgXzX.js → chunk-5RXB4S5H-DjLaSDUO.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-DbNA24sj.js → chunk-5VM5RSS4-CtiPlKel.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-Bi_0Be06.js → chunk-6Q2QTUOP-DZtolir7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-C8pPGvRd.js → chunk-GF5L2VYU-CPcdNeew.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BitQY8Z-.js → chunk-JWPE2WC7-NgHc6V37.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-U67GCiEo.js → chunk-KBJHAD2P-DQ_T-hg8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-IoJwXPBA.js → chunk-RYQCIY6F-DgLsxcVP.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-YDZ_UHgE.js → chunk-XXDRQBXY-UrVoM9z1.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C2DwA_Y1.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C2DwA_Y1.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CUZgsiRC.js → cose-bilkent-JH36ORCC-CLkYvTb3.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-COmCh4pT.js → cynefin-VYW2F7L2-BwT_xKrE.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Ta6FSm68.js → cynefinDiagram-MW4NZA55-Bi9tuzif.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-UdcR-VW9.js → dagre-VZM6K2ZE-BCIqkWBV.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-DybcO3Et.js → diagram-7IWD3JNH-Dip6l9_Z.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-wErDFWLw.js → diagram-B4RE2ZJO-B-xkh_wK.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DkVHZWqz.js → diagram-LBJQPF4R-DZO0kTt_.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DdqWs7QN.js → diagram-Q27KOJAE-D6ZplNbZ.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-C9dMVmDo.js → diagram-UB23O5K3-BPekbhoS.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-B2T2WcBK.js → ebnfDiagram-BXEA7PRR-BtmaJpK5.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Bt9rjDFq.js → erDiagram-JOGREHBK-6DS0Xc44.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-U8ic_tvi.js → flowDiagram-UKHOOZJN-CihnROSm.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-BfQJdQoO.js → ganttDiagram-PKOTCBZU-CZC4zOE2.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CpMftH4O.js → gitGraphDiagram-DS77QQ5N-Dq1fhzGN.js} +1 -1
- package/dist/worker/console/static/assets/index-DTZOKgAn.js +404 -0
- package/dist/worker/console/static/assets/index-Ya5FE7cD.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DzqWXNO_.js → infoDiagram-6WML65LV-DlSl4BGx.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-CJmGQ5Yp.js → ishikawaDiagram-WSZJBQD7-snnzFl_U.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-ChPtKFLz.js → journeyDiagram-NVQOT4AX-BDE7qpMx.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-PRe7wB5u.js → kanban-definition-27J2QSJJ-CD2Ci04G.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DpKX6QNp.js → linear-DdnapKIH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Dnl76b7Y.js → mermaid.core-BVjAT9b8.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-S9PCXc3J.js → mindmap-definition-FAOFIHXS-D0yJk-zA.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-Du8e-FSX.js → pegDiagram-VL7TDLO6-BVo9tFP-.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CY6OmHTc.js → pieDiagram-7S7Q4E2Y-DnOV-mZ_.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-C65GPhpj.js → quadrantDiagram-CIZ2JOQS-CzUJo58i.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-U6IUiTCL.js → railroadDiagram-AXF67PYL-Bvikrolh.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D-I_9Qhi.js → requirementDiagram-LRYGKXZP-DtaSVCap.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-B57Fhed0.js → sankeyDiagram-W5VNT64P-C2c9A0wW.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CJOtiw21.js → sequenceDiagram-SI44F4Z6-DmXJcU7r.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-FyX8zxSh.js → sizeCapture-X5ZJPWSS-B4GUFW92.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-eF-pbs9t.js → stateDiagram-OKZ733FA-Dsad2MXf.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B8FB_cNk.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CcfkA-Dq.js → swimlanes-SLNWSIFB-DGq48Fbi.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CrZYaWfx.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DH8FjnOK.js → timeline-definition-Z64GVDOM-CSSi6OFf.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-beoTagJg.js → vennDiagram-T6HMQDX7-BqyzPrWv.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CQSfw4cK.js → wardleyDiagram-T6FBY63Y-DlznVb6S.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CQgzQ6jn.js → xychartDiagram-ELKLHX3M-CfBcgJ_K.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +0 -12
- package/dist/worker/console/static-src/app/useOperatorActions.js +1 -1
- package/dist/worker/console/static-src/app/useRecoveryActions.js +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +38 -1
- package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +328 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +8 -1
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +42 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +3 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +204 -11
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +23 -1
- package/dist/worker/observe/node-input.js +72 -3
- package/dist/worker/observe/static/dag-history-labels.js +4 -0
- package/dist/worker/observe/static/state.js +2 -2
- package/dist/worker/observe/static/views/dag-inspector.js +51 -0
- package/dist/worker/observe/static/views/session-timeline.js +18 -5
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +809 -53
- package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
- package/dist/workflows/dag/backend-test-execution-contract.js +18 -9
- package/dist/workflows/dag/backend-test-gap-fill.js +205 -0
- package/dist/workflows/dag/backend-test-intake-context.js +32 -0
- package/dist/workflows/dag/backend-test-layout.js +133 -0
- package/dist/workflows/dag/backend-test-markdown-workflow.js +167 -32
- package/dist/workflows/dag/backend-test-module-stem.js +5 -0
- package/dist/workflows/dag/backend-test-pytest-collection.js +368 -33
- package/dist/workflows/dag/backend-test-result-contract.js +1 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +884 -140
- package/dist/workflows/dag/backend-test-scenario-partitions.js +321 -0
- package/dist/workflows/dag/backend-test-writer-completeness.js +100 -56
- package/dist/workflows/dag/contract-output-registry.js +15 -0
- package/dist/workflows/dag/contract-validator-registrations.js +2 -1
- package/dist/workflows/dag/convergence/controller.js +141 -0
- package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
- package/dist/workflows/dag/dynamic-runtime/shared.js +1 -1
- package/dist/workflows/dag/failure-category.js +4 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +355 -26
- package/dist/workflows/dag/frontend-prewrite-gate.js +96 -84
- package/dist/workflows/dag/frontend-test-case-quality.js +5 -13
- package/dist/workflows/dag/frontend-test-environment-probe.js +227 -0
- package/dist/workflows/dag/frontend-test-markdown.js +61 -0
- package/dist/workflows/dag/frontend-test-result-contract.js +10 -18
- package/dist/workflows/dag/frontend-test-standard-scenarios.js +68 -0
- package/dist/workflows/dag/init-hybrid.js +720 -177
- package/dist/workflows/dag/node-execution.js +164 -26
- package/dist/workflows/dag/prompt.js +60 -1
- package/dist/workflows/dag/rerun-feedback.js +212 -0
- package/dist/workflows/dag/rerun-plan.js +112 -27
- package/dist/workflows/dag/rerun-run.js +3 -0
- package/dist/workflows/dag/rerun-task.js +61 -2
- package/dist/workflows/dag/retry-policy.js +18 -0
- package/dist/workflows/dag/structured-output-repair.js +712 -0
- package/dist/workflows/dag/types.js +121 -0
- package/dist/workflows/dag/validate.js +41 -1
- package/docs/operations/local-development-environment.md +1 -5
- package/docs/skills/vetted-skill-registry.md +14 -0
- package/docs/templates/README.md +1 -1
- package/docs/templates/agent-dag.schema.json +44 -0
- package/docs/templates/backend-test-dag.json +60 -35
- package/docs/templates/frontend-test-dag.json +8 -10
- package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
- package/docs/templates/harness.schema.json +0 -8
- package/harness.json +1 -8
- package/package.json +8 -4
- package/skills/analyze-product-requirements/SKILL.md +8 -5
- package/skills/analyze-product-requirements/references/acceptance-criteria.md +1 -1
- package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +10 -6
- package/skills/analyze-product-requirements/references/example.md +50 -0
- package/skills/analyze-product-requirements/references/forward-test-cases.md +11 -7
- package/skills/analyze-product-requirements/references/kb-integration.md +5 -5
- package/skills/analyze-product-requirements/references/product-analysis-schema.md +8 -4
- package/skills/analyze-product-requirements/references/product-requirement-schema.md +2 -2
- package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +1 -1
- package/skills/analyze-product-requirements/scripts/test-validators.mjs +11 -1
- package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +20 -1
- package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +9 -0
- package/skills/codebase-scout/SKILL.md +1 -1
- package/skills/frontend-implementation/references/node-contracts.md +2 -2
- package/skills/improve-codebase-architecture/SKILL.md +81 -0
- package/skills/improve-codebase-architecture/deepening.md +37 -0
- package/skills/improve-codebase-architecture/html-report.md +123 -0
- package/skills/improve-codebase-architecture/interface-design.md +44 -0
- package/skills/improve-codebase-architecture/language.md +53 -0
- package/dist/worker/console/static/assets/channel-Dp_2Aqf1.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL--CODy37j.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE--CODy37j.js +0 -1
- package/dist/worker/console/static/assets/index-BA5-N5ER.css +0 -1
- package/dist/worker/console/static/assets/index-DKPXBrdc.js +0 -325
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-B-mvnLEc.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-JtpBmIv4.js +0 -8
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* its schemaId in the contract output registry. Imported once by the node
|
|
4
4
|
* executor; keeps per-contract imports out of the executor.
|
|
5
5
|
*/
|
|
6
|
-
import { validateFrontendContractNodeOutput, validateFrontendRevisionPatchNodeOutput, } from "./frontend-implementation-contract.js";
|
|
6
|
+
import { validateFrontendContractNodeOutput, validateFrontendPlanPatchNodeOutput, validateFrontendRevisionPatchNodeOutput, } from "./frontend-implementation-contract.js";
|
|
7
7
|
import { registerStructuredContractValidator } from "./contract-output-registry.js";
|
|
8
8
|
registerStructuredContractValidator("frontend-implementation-contract-v1", validateFrontendContractNodeOutput);
|
|
9
|
+
registerStructuredContractValidator("frontend-implementation-contract-plan-patch-v1", validateFrontendPlanPatchNodeOutput);
|
|
9
10
|
registerStructuredContractValidator("frontend-implementation-contract-revision-patch-v1", validateFrontendRevisionPatchNodeOutput);
|
|
@@ -21,6 +21,17 @@ const REVIEW_VERDICT_NODE_ID = "review-verdict-recovery-pi";
|
|
|
21
21
|
const INITIAL_REVIEW_NODE_ID = "initial-review-pi";
|
|
22
22
|
const INITIAL_REVIEW_GATE_NODE_ID = "initial-review-gate-shell";
|
|
23
23
|
const INITIAL_REVIEW_PASS_NODE_ID = "initial-review-pass-shell";
|
|
24
|
+
/**
|
|
25
|
+
* Standard-dag governance verify chain ids. When the convergence chain
|
|
26
|
+
* observes the governance standard gate, a legitimate verify-pi
|
|
27
|
+
* `request-revision` re-enters a bounded implement-repair loop instead of
|
|
28
|
+
* terminating the run at the gate, mirroring the review-chain re-entry
|
|
29
|
+
* semantics (AC3/AC4). Protocol/provider/safety failures on verify-pi keep
|
|
30
|
+
* failing closed; only a safe `request-revision` drives code repair here.
|
|
31
|
+
*/
|
|
32
|
+
const GOVERNANCE_VERIFY_GATE_NODE_ID = "governance-standard-gate-shell";
|
|
33
|
+
const GOVERNANCE_VERIFY_NODE_ID = "verify-pi";
|
|
34
|
+
const GOVERNANCE_VERIFY_WRITER_NODE_ID = "implement-pi";
|
|
24
35
|
// Automatic code repair is authorized only for an ordinary command/test
|
|
25
36
|
// failure. Unknown, protocol, validation, provider, safety, governance, and
|
|
26
37
|
// human-decision categories all fail closed instead of reaching a writer.
|
|
@@ -57,6 +68,15 @@ export async function runConvergencePassController(input) {
|
|
|
57
68
|
}
|
|
58
69
|
const chain = getConvergenceChain(input.spec);
|
|
59
70
|
const observesReview = chain.includes(REVIEW_GATE_NODE_ID);
|
|
71
|
+
const observesGovernanceVerify = chain.includes(GOVERNANCE_VERIFY_GATE_NODE_ID);
|
|
72
|
+
// Standard-dag governance verify convergence: verify-pi drives a bounded
|
|
73
|
+
// implement-repair loop on `request-revision`. This shape has no
|
|
74
|
+
// hard-verify/review nodes; dispatch before the legacy hard-verify logic so
|
|
75
|
+
// the standard governance DAG never falls into `unsupported-dag-shape`/
|
|
76
|
+
// `non-retry-failure` dead ends.
|
|
77
|
+
if (observesGovernanceVerify && !observesReview) {
|
|
78
|
+
return handleGovernanceVerifyConvergence(input);
|
|
79
|
+
}
|
|
60
80
|
if (input.tasksById.has(INITIAL_REVIEW_NODE_ID)) {
|
|
61
81
|
const initialReview = input.state.nodes[INITIAL_REVIEW_NODE_ID];
|
|
62
82
|
const initialGate = input.state.nodes[INITIAL_REVIEW_GATE_NODE_ID];
|
|
@@ -397,6 +417,127 @@ async function handleReviewRequestRevision(input, reviewGate) {
|
|
|
397
417
|
function getConvergenceChain(spec) {
|
|
398
418
|
return spec.convergence?.chainNodeIds ?? DEFAULT_CONVERGENCE_CHAIN_NODE_IDS;
|
|
399
419
|
}
|
|
420
|
+
/**
|
|
421
|
+
* Legitimate governance verify revision: verify-pi finished and emitted
|
|
422
|
+
* `request-revision`. No secondary verdict-recovery node exists on the
|
|
423
|
+
* standard dag, so the single verify-pi verdict plus a non-transport failure
|
|
424
|
+
* category is the legitimacy bar (protocol-invalid/invalid-output/timeout on
|
|
425
|
+
* verify-pi fail closed instead of driving repair).
|
|
426
|
+
*/
|
|
427
|
+
function isLegitimateGovernanceVerifyRevision(state) {
|
|
428
|
+
const verifyNode = state.nodes[GOVERNANCE_VERIFY_NODE_ID];
|
|
429
|
+
return (verifyNode?.status === "FINISHED" &&
|
|
430
|
+
parseProcessVerdict(verifyNode) === "request-revision");
|
|
431
|
+
}
|
|
432
|
+
function isLegitimateGovernanceVerifyPass(state) {
|
|
433
|
+
const verifyNode = state.nodes[GOVERNANCE_VERIFY_NODE_ID];
|
|
434
|
+
return (verifyNode?.status === "FINISHED" &&
|
|
435
|
+
parseProcessVerdict(verifyNode) === "pass");
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Standard-dag governance verify convergence loop. Terminal pass when
|
|
439
|
+
* verify-pi passes; bounded re-entry (reset implement-pi + verify chain) when
|
|
440
|
+
* verify-pi legitimately requests revision. The reset lets the next
|
|
441
|
+
* implement-pi pass consume the prior verify findings through the structured
|
|
442
|
+
* convergence feedback block (node-execution injects it for implementer
|
|
443
|
+
* roles), so `already-satisfied` no-ops are explicitly contradicted by the
|
|
444
|
+
* preserved verify-pi evidence refs.
|
|
445
|
+
*/
|
|
446
|
+
async function handleGovernanceVerifyConvergence(input) {
|
|
447
|
+
const convergence = input.state.convergence;
|
|
448
|
+
const currentPass = convergence.currentPass || 1;
|
|
449
|
+
const verifyNode = input.state.nodes[GOVERNANCE_VERIFY_NODE_ID];
|
|
450
|
+
const verifyShell = input.state.nodes["verify-shell"];
|
|
451
|
+
// Hard verify commands failed: not a governance verdict issue. Without a
|
|
452
|
+
// supervised repair chain, this stays terminal so the failure-aware
|
|
453
|
+
// closeout reports it truthfully.
|
|
454
|
+
if (verifyShell?.status === "ERROR") {
|
|
455
|
+
const passRecord = await buildConvergencePassRecord({
|
|
456
|
+
pass: currentPass,
|
|
457
|
+
status: "terminal",
|
|
458
|
+
reason: "hard-verify-failed",
|
|
459
|
+
state: input.state,
|
|
460
|
+
runDir: input.runDir,
|
|
461
|
+
spec: input.spec,
|
|
462
|
+
});
|
|
463
|
+
convergence.passHistory.push(passRecord);
|
|
464
|
+
convergence.terminalReason = "hard-verify-failed";
|
|
465
|
+
await input.persistState();
|
|
466
|
+
return { retry: false };
|
|
467
|
+
}
|
|
468
|
+
if (isLegitimateGovernanceVerifyPass(input.state)) {
|
|
469
|
+
convergence.terminalReason = "hard-verify-pass";
|
|
470
|
+
await appendConvergenceKnowledgePattern({
|
|
471
|
+
cwd: input.cwd,
|
|
472
|
+
state: input.state,
|
|
473
|
+
});
|
|
474
|
+
return { retry: false };
|
|
475
|
+
}
|
|
476
|
+
const verifyFailureCategory = verifyNode?.failureCategory;
|
|
477
|
+
const legitimateRevision = isLegitimateGovernanceVerifyRevision(input.state);
|
|
478
|
+
if (!legitimateRevision ||
|
|
479
|
+
(verifyFailureCategory &&
|
|
480
|
+
REVIEW_SOURCE_NON_RETRY_FAILURES.has(verifyFailureCategory))) {
|
|
481
|
+
const passRecord = await buildConvergencePassRecord({
|
|
482
|
+
pass: currentPass,
|
|
483
|
+
status: "terminal",
|
|
484
|
+
reason: "non-retry-failure",
|
|
485
|
+
state: input.state,
|
|
486
|
+
runDir: input.runDir,
|
|
487
|
+
spec: input.spec,
|
|
488
|
+
});
|
|
489
|
+
convergence.passHistory.push(passRecord);
|
|
490
|
+
convergence.terminalReason = "non-retry-failure";
|
|
491
|
+
await input.persistState();
|
|
492
|
+
return { retry: false };
|
|
493
|
+
}
|
|
494
|
+
const passRecord = await buildConvergencePassRecord({
|
|
495
|
+
pass: currentPass,
|
|
496
|
+
status: "retrying",
|
|
497
|
+
reason: "verify-request-revision",
|
|
498
|
+
state: input.state,
|
|
499
|
+
runDir: input.runDir,
|
|
500
|
+
spec: input.spec,
|
|
501
|
+
});
|
|
502
|
+
if (currentPass >= convergence.maxPasses) {
|
|
503
|
+
passRecord.status = "terminal";
|
|
504
|
+
passRecord.reason = "max-passes";
|
|
505
|
+
convergence.passHistory.push(passRecord);
|
|
506
|
+
convergence.terminalReason = "max-passes";
|
|
507
|
+
await input.persistState();
|
|
508
|
+
return { retry: false };
|
|
509
|
+
}
|
|
510
|
+
convergence.passHistory.push(passRecord);
|
|
511
|
+
convergence.currentPass = currentPass + 1;
|
|
512
|
+
// Reset the writer plus the governance verify chain: the next implement-pi
|
|
513
|
+
// pass must consume the preserved verify-pi findings (injected as
|
|
514
|
+
// convergence feedback) instead of returning already-satisfied.
|
|
515
|
+
for (const id of collectGovernanceVerifyResetIds(input.spec)) {
|
|
516
|
+
const task = input.tasksById.get(id);
|
|
517
|
+
if (!task)
|
|
518
|
+
continue;
|
|
519
|
+
input.state.nodes[id] = freshNodeRecord(task);
|
|
520
|
+
}
|
|
521
|
+
await input.persistState();
|
|
522
|
+
return { retry: true };
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Reset set for the governance verify loop: the exclusive writer and the
|
|
526
|
+
* verify chain closure (verify-shell, verify-pi, governance gate, and every
|
|
527
|
+
* transitive descendant so closeout re-adjudicates from fresh evidence).
|
|
528
|
+
*/
|
|
529
|
+
function collectGovernanceVerifyResetIds(spec) {
|
|
530
|
+
const resetIds = new Set([
|
|
531
|
+
GOVERNANCE_VERIFY_WRITER_NODE_ID,
|
|
532
|
+
"verify-shell",
|
|
533
|
+
GOVERNANCE_VERIFY_NODE_ID,
|
|
534
|
+
GOVERNANCE_VERIFY_GATE_NODE_ID,
|
|
535
|
+
]);
|
|
536
|
+
for (const id of collectTransitiveDescendantTaskIds(spec, GOVERNANCE_VERIFY_GATE_NODE_ID)) {
|
|
537
|
+
resetIds.add(id);
|
|
538
|
+
}
|
|
539
|
+
return resetIds;
|
|
540
|
+
}
|
|
400
541
|
function hasConvergenceChain(tasksById, spec) {
|
|
401
542
|
const chain = getConvergenceChain(spec);
|
|
402
543
|
return chain.every((id) => tasksById.has(id));
|
|
@@ -367,19 +367,26 @@ export async function executeDynamicMapExpansion(input) {
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
const budgetBlockedIds = new Set(blockedChildren.map((entry) => entry.nodeId));
|
|
370
|
+
const failOnTokenBudgetExhaustion = input.expansion.failOnTokenBudgetExhaustion === true;
|
|
370
371
|
const failedChildren = tolerateChildFailures
|
|
371
372
|
? []
|
|
372
373
|
: childNodeIds.filter((nodeId) => {
|
|
373
374
|
const record = input.state.nodes[nodeId];
|
|
374
375
|
if (!record || record.status === "FINISHED")
|
|
375
376
|
return false;
|
|
376
|
-
if (budgetBlockedIds.has(nodeId) || isBudgetBlockedRecord(record))
|
|
377
|
-
return
|
|
377
|
+
if (budgetBlockedIds.has(nodeId) || isBudgetBlockedRecord(record)) {
|
|
378
|
+
return failOnTokenBudgetExhaustion;
|
|
379
|
+
}
|
|
378
380
|
return true;
|
|
379
381
|
});
|
|
382
|
+
const finishedItemCount = childNodeIds.filter((nodeId) => input.state.nodes[nodeId]?.status === "FINISHED").length;
|
|
383
|
+
const blockedItemCount = budgetBlockedIds.size;
|
|
380
384
|
const aggregate = {
|
|
381
385
|
workflowNodeId: input.expansion.workflowNodeId,
|
|
382
386
|
itemCount: items.length,
|
|
387
|
+
expectedItemCount: items.length,
|
|
388
|
+
finishedItemCount,
|
|
389
|
+
blockedItemCount,
|
|
383
390
|
children: childNodeIds.map((nodeId, index) => ({
|
|
384
391
|
nodeId,
|
|
385
392
|
item: items[index],
|
|
@@ -399,21 +406,30 @@ export async function executeDynamicMapExpansion(input) {
|
|
|
399
406
|
?.reason,
|
|
400
407
|
})),
|
|
401
408
|
tokensUsed: totalTokensUsed,
|
|
409
|
+
maxTotalTokens: tokenBudget?.maxTotalTokens,
|
|
402
410
|
caseOutcomeNotes: caseOutcomeNotes.length > 0 ? caseOutcomeNotes : undefined,
|
|
403
411
|
};
|
|
412
|
+
const tokenBudgetFailure = failOnTokenBudgetExhaustion && blockedItemCount > 0;
|
|
404
413
|
return {
|
|
405
|
-
// With tolerateChildFailures: barrier
|
|
406
|
-
// case evidence
|
|
407
|
-
|
|
414
|
+
// With tolerateChildFailures: barrier succeeds and product outcomes live in
|
|
415
|
+
// case evidence. Backend-test opts into token-budget fail-closed because a
|
|
416
|
+
// partial generated module set is never a valid downstream input.
|
|
417
|
+
ok: failedChildren.length === 0 && !tokenBudgetFailure,
|
|
408
418
|
stdout: JSON.stringify(aggregate),
|
|
409
419
|
stderr: caseOutcomeNotes.length > 0
|
|
410
420
|
? `map children recorded as case outcomes: ${caseOutcomeNotes
|
|
411
421
|
.map((entry) => `${entry.nodeId}=${entry.status}:${entry.reason}`)
|
|
412
422
|
.join(", ")}`
|
|
423
|
+
: tokenBudgetFailure
|
|
424
|
+
? `dynamic map token budget exhausted: expected=${items.length} finished=${finishedItemCount} blocked=${blockedItemCount} tokensUsed=${totalTokensUsed} maxTotalTokens=${tokenBudget?.maxTotalTokens ?? "unbounded"}`
|
|
425
|
+
: failedChildren.length > 0
|
|
426
|
+
? `dynamic map children failed: ${failedChildren.join(", ")}`
|
|
427
|
+
: "",
|
|
428
|
+
failureCategory: tokenBudgetFailure
|
|
429
|
+
? "dynamic-expansion-token-budget-exhausted"
|
|
413
430
|
: failedChildren.length > 0
|
|
414
|
-
?
|
|
415
|
-
: "",
|
|
416
|
-
failureCategory: failedChildren.length > 0 ? "dynamic-expansion-child-failed" : "success",
|
|
431
|
+
? "dynamic-expansion-child-failed"
|
|
432
|
+
: "success",
|
|
417
433
|
durationMs: Date.now() - started,
|
|
418
434
|
};
|
|
419
435
|
}
|
|
@@ -30,7 +30,7 @@ export function getNodeOutputAsJson(state, nodeId) {
|
|
|
30
30
|
/** Normalize a line the same way verdict gates do (strip whole-line Markdown emphasis). */
|
|
31
31
|
export function normalizeVerdictCandidateLine(value) {
|
|
32
32
|
const trimmed = String(value).trim();
|
|
33
|
-
const emphasized = trimmed.match(
|
|
33
|
+
const emphasized = trimmed.match(/^(?:`{1,3}|\*{1,3})\s*(VERDICT:[^`*]+?)\s*(?:`{1,3}|\*{1,3})$/);
|
|
34
34
|
const line = (emphasized ? emphasized[1] : trimmed).trim();
|
|
35
35
|
// Canonicalize the colon separator and trailing sentence punctuation so
|
|
36
36
|
// "VERDICT:pass", "VERDICT: pass", or "VERDICT: pass." match the declared
|
|
@@ -31,6 +31,10 @@ const RAW_TO_NORMALIZED = {
|
|
|
31
31
|
"spawn-error": "shell-command",
|
|
32
32
|
"static-error": "static-error",
|
|
33
33
|
"invalid-output": "validation",
|
|
34
|
+
"structured-output-truncated": "validation",
|
|
35
|
+
"output-too-large": "validation",
|
|
36
|
+
"structured-repair-exhausted": "validation",
|
|
37
|
+
"governance-blocked": "validation",
|
|
34
38
|
"path-violation": "validation",
|
|
35
39
|
"empty-output": "validation",
|
|
36
40
|
"verify-failure": "validation",
|