@tea-agent/loop-agent 0.43.0-next.1 → 0.43.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +144 -9
- package/dist/application/dag/run-dag.js +5 -0
- package/dist/application/evaluation/budget.js +19 -1
- package/dist/application/task-lifecycle/advance.js +17 -4
- package/dist/application/task-lifecycle/observe.js +43 -29
- package/dist/application/task-lifecycle/plan-transitions.js +5 -4
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +1237 -586
- package/dist/executors/pi-executor.js +22 -1
- package/dist/executors/pi-sdk-executor.js +140 -39
- package/dist/executors/shell-executor.js +8 -4
- package/dist/shared/frontend-execution-policy.js +23 -0
- package/dist/task/config-types.js +4 -0
- package/dist/task/source-prepare/ledger-reconciliation.js +2 -2
- package/dist/task/source-prepare/ledger-review.js +6 -9
- package/dist/task/source-prepare/semantic-intake.js +16 -26
- package/dist/task/source-prepare/source-fidelity-pi.js +28 -9
- package/dist/task/source-references.js +48 -23
- package/dist/worker/console/chat/assistant-content.js +23 -2
- package/dist/worker/console/chat/browser-policy.js +113 -0
- package/dist/worker/console/chat/browser-routes.js +140 -0
- package/dist/worker/console/chat/explore-tools.js +13 -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/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 +86 -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/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 +207 -1178
- package/dist/worker/console/chat/routes.js +208 -71
- package/dist/worker/console/chat/scm-routes.js +217 -0
- package/dist/worker/console/chat/scm-service.js +283 -0
- package/dist/worker/console/chat/scm-tools.js +111 -0
- package/dist/worker/console/chat/sdd-data-alignment.js +65 -9
- package/dist/worker/console/chat/session-catalog.js +32 -0
- package/dist/worker/console/chat/session-mode-view.js +49 -0
- package/dist/worker/console/chat/session-mode.js +219 -0
- package/dist/worker/console/chat/session-store.js +22 -6
- package/dist/worker/console/chat/shortcuts.js +6 -0
- package/dist/worker/console/chat/terminal-routes.js +216 -0
- package/dist/worker/console/chat/terminal-sessions.js +348 -0
- package/dist/worker/console/chat/terminal-tools.js +211 -0
- package/dist/worker/console/chat/tool-preview.js +11 -0
- package/dist/worker/console/chat/tools.js +2 -0
- package/dist/worker/console/server.js +2 -28
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-B0Q0nClf.js → abnfDiagram-N423BO3Z-CTSK0xbU.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DCPjC19G.js → arc-_2MfctFP.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CP5n9jmG.js → architectureDiagram-T3A2C74G-DsDe2wTg.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CmaWi_Wg.js → blockDiagram-VBNYF7ZC-Dtz_779U.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Ct5tcMfZ.js → c4Diagram-5PPSVZJV-LaULi-gw.js} +1 -1
- package/dist/worker/console/static/assets/channel-CqS4yBWT.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-C0osm1Zf.js → chunk-2GRJ4B5K-DuHBqqX8.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-CDWviED7.js → chunk-2Q5K7J3B-BZgZs1dn.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-mtSk1-j7.js → chunk-5RXB4S5H-tzwmlIO_.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-D5J9PHC7.js → chunk-5VM5RSS4-CeYrLkSn.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-Begg4WAa.js → chunk-6Q2QTUOP-C92cgilm.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-sF1AEy7T.js → chunk-GF5L2VYU-XOXpGC0F.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BqbsWXZb.js → chunk-JWPE2WC7-CGHbJyCH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BKJrPcJ6.js → chunk-KBJHAD2P-Bs2-LTzf.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CcwNMRho.js → chunk-RYQCIY6F-rN7up7E4.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-BEJi3iIs.js → chunk-XXDRQBXY-B_fWjKpR.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DVOxNOq0.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DVOxNOq0.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-DRLgTvVu.js → cose-bilkent-JH36ORCC-DE3SdJvB.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BoAVG3cs.js → cynefin-VYW2F7L2-B-4yuRAX.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Bzol06hR.js → cynefinDiagram-MW4NZA55-TiCPFuO8.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-UmliJM77.js → dagre-VZM6K2ZE-7crzLMzA.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BWLcJkFo.js → diagram-7IWD3JNH-Cvr-x6Fd.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-CgApOm-O.js → diagram-B4RE2ZJO-BzcRHUjH.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-Bh3RgTLs.js → diagram-LBJQPF4R-BjkAXilh.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Dsh-D5nE.js → diagram-Q27KOJAE-BkzyATK7.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-Dkbbpcpb.js → diagram-UB23O5K3-rZuTarYP.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-3EBaA3t3.js → ebnfDiagram-BXEA7PRR-CAYENaN1.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-Bq2Dc5ok.js → erDiagram-JOGREHBK-DCEam0Uq.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-De7y55ha.js → flowDiagram-UKHOOZJN-e_dH4wVO.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-fLiDbQRh.js → ganttDiagram-PKOTCBZU-CvZa2zOK.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Du617mp1.js → gitGraphDiagram-DS77QQ5N-CbT5TuKp.js} +1 -1
- package/dist/worker/console/static/assets/index-CUPeoE8W.js +468 -0
- package/dist/worker/console/static/assets/index-SAANIK8g.css +1 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BwmlF-XP.js → infoDiagram-6WML65LV-BWzHQa_Z.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-zsGtS59u.js → ishikawaDiagram-WSZJBQD7-BTjlovtU.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DTTPTe3f.js → journeyDiagram-NVQOT4AX-DkvQoCc1.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BkXg9aP-.js → kanban-definition-27J2QSJJ-CHSzGi3W.js} +1 -1
- package/dist/worker/console/static/assets/{linear-7U2ue5IE.js → linear-DZMkTCWH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-BUuGHmWO.js → mermaid.core-BIMhty7A.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-7q6fX0Sv.js → mindmap-definition-FAOFIHXS-Dx-tyMl3.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkQPJN55.js → pegDiagram-VL7TDLO6-C6G34rbY.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-CCal_tfX.js → pieDiagram-7S7Q4E2Y-CHK9XOfm.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B7bpxyAZ.js → quadrantDiagram-CIZ2JOQS-CDARkI0w.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-CJmww7D-.js → railroadDiagram-AXF67PYL-DiuUe0ZQ.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D6ldWJEv.js → requirementDiagram-LRYGKXZP-RE61UR56.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-VGh33I9e.js → sankeyDiagram-W5VNT64P-KDNLHMEG.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CCkDrIjU.js → sequenceDiagram-SI44F4Z6-CeVgXnD9.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-NC8f5Otb.js → sizeCapture-X5ZJPWSS-CXwGyjjG.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-_92ezZdF.js → stateDiagram-OKZ733FA-BjTfozab.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BXoYsyr2.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-BdUCGtbP.js → swimlanes-SLNWSIFB-BaXOB8GT.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DfKliS4e.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CdD1H8ia.js → timeline-definition-Z64GVDOM-C3r2hqUU.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-Dkdk3oFo.js → vennDiagram-T6HMQDX7-MWKgl1S9.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CKu2uPPY.js → wardleyDiagram-T6FBY63Y-C9iFcZPk.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-ClqAnuG8.js → xychartDiagram-ELKLHX3M-DqnM24Jp.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-link.js +94 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +122 -10
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +7 -0
- package/dist/worker/console/static-src/operator-chat/pending-user-message.js +27 -15
- package/dist/worker/console/static-src/operator-chat/process-label.js +41 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +13 -0
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +10 -0
- package/dist/worker/console/static-src/operator-chat/use-searchable-hidden.js +51 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +44 -24
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +18 -2
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +41 -8
- package/dist/worker/console/static-src/operator-chat/useComposer.js +26 -11
- package/dist/worker/console/static-src/operator-chat/user-turn-anchor-equality.js +21 -0
- package/dist/worker/console/workspace-context.js +15 -1
- package/dist/worker/observe/node-transparency.js +81 -72
- package/dist/worker/observe/routes.js +20 -1
- package/dist/worker/observe/static/dag-inspector-humanize.js +3 -0
- package/dist/worker/observe/static/dom.js +20 -1
- package/dist/worker/observe/static/format-pool.d.ts +2 -0
- package/dist/worker/observe/static/format-pool.js +6 -0
- package/dist/worker/observe/static/format.js +7 -0
- package/dist/worker/observe/static/inspect-workspace.js +34 -7
- package/dist/worker/observe/static/inspector-submission.js +32 -0
- package/dist/worker/observe/static/kpi.js +1 -0
- package/dist/worker/observe/static/relations.js +2 -0
- package/dist/worker/observe/static/router.js +13 -0
- package/dist/worker/observe/static/run-processing.js +2 -0
- package/dist/worker/observe/static/shell-chrome.js +36 -3
- package/dist/worker/observe/static/state.js +35 -2
- package/dist/worker/observe/static/styles.css +263 -39
- package/dist/worker/observe/static/task-failure-labels.d.ts +4 -0
- package/dist/worker/observe/static/task-failure-labels.js +67 -0
- package/dist/worker/observe/static/task-history.js +12 -0
- package/dist/worker/observe/static/views/batch.js +6 -13
- package/dist/worker/observe/static/views/dag-graph.js +50 -3
- package/dist/worker/observe/static/views/dag-inspector.js +742 -268
- package/dist/worker/observe/static/views/dag-trajectory.js +3 -0
- package/dist/worker/observe/static/views/dag.d.ts +6 -0
- package/dist/worker/observe/static/views/dag.js +49 -11
- package/dist/worker/observe/static/views/dags.js +2 -0
- package/dist/worker/observe/static/views/dashboard.js +21 -12
- package/dist/worker/observe/static/views/failures.js +21 -11
- package/dist/worker/observe/static/views/feature.js +11 -29
- package/dist/worker/observe/static/views/pool.js +37 -28
- package/dist/worker/observe/static/views/run.js +48 -5
- package/dist/worker/observe/static/views/session-timeline.js +189 -240
- package/dist/worker/observe/static/views/task.js +81 -62
- package/dist/workflows/dag/budget-enforcement.js +53 -3
- package/dist/workflows/dag/frontend-capacity.js +9 -0
- package/dist/workflows/dag/frontend-closeout.js +1 -1
- package/dist/workflows/dag/frontend-design-policy.js +2 -1
- package/dist/workflows/dag/frontend-durable-tools.js +193 -0
- package/dist/workflows/dag/frontend-execution-groups.js +24 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +13 -0
- package/dist/workflows/dag/frontend-input-projection.js +76 -0
- package/dist/workflows/dag/frontend-plan-completeness.js +186 -0
- package/dist/workflows/dag/frontend-plan-recovery-policy.js +18 -0
- package/dist/workflows/dag/frontend-plan-render.js +10 -3
- package/dist/workflows/dag/frontend-prewrite-gate.js +3 -3
- package/dist/workflows/dag/frontend-recovery-controller.js +7 -7
- package/dist/workflows/dag/frontend-recovery-lineage.js +13 -0
- package/dist/workflows/dag/frontend-recovery-run.js +4 -0
- package/dist/workflows/dag/frontend-review-context.js +2 -1
- package/dist/workflows/dag/frontend-review-scopes.js +139 -0
- package/dist/workflows/dag/frontend-session-budget.js +249 -0
- package/dist/workflows/dag/frontend-shadow-dual-write.js +20 -2
- package/dist/workflows/dag/frontend-shape-facts.js +12 -2
- package/dist/workflows/dag/frontend-shape.js +30 -1
- package/dist/workflows/dag/frontend-test-execution-evidence.js +3 -2
- package/dist/workflows/dag/frontend-typed-event-store.js +11 -0
- package/dist/workflows/dag/frontend-verification-trace.js +1 -1
- package/dist/workflows/dag/init-hybrid.js +65 -167
- package/dist/workflows/dag/node-execution.js +38 -155
- package/dist/workflows/dag/prompt.js +4 -0
- package/dist/workflows/dag/rerun-plan.js +7 -1
- package/dist/workflows/dag/runner.js +26 -1
- package/dist/workflows/dag/types.js +6 -0
- package/docs/operations/README.md +1 -0
- package/docs/templates/frontend-design-contract.md +4 -4
- package/docs/templates/frontend-implementation-contract.schema.json +34 -2
- package/docs/templates/frontend-implementation-dag.json +14 -13
- package/package.json +6 -3
- package/skills/frontend-bounded-implement/SKILL.md +3 -3
- package/skills/frontend-bounded-implement/references/code-standards.md +3 -3
- package/skills/frontend-contract/SKILL.md +2 -1
- package/skills/frontend-contract/references/contract-protocol.md +22 -4
- package/skills/frontend-design-review/SKILL.md +22 -16
- package/skills/frontend-design-review/references/review-checklist.md +7 -7
- package/skills/frontend-plan/SKILL.md +21 -2
- package/skills/frontend-plan/references/decision-contract.md +42 -23
- package/skills/frontend-review/SKILL.md +22 -29
- package/skills/frontend-review/references/review-findings.md +24 -43
- package/skills/frontend-scout/references/scout-evidence.md +4 -0
- package/dist/worker/console/static/assets/channel-DAS07MdS.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Cwk-5jiW.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Cwk-5jiW.js +0 -1
- package/dist/worker/console/static/assets/index-C0O48S_P.js +0 -449
- package/dist/worker/console/static/assets/index-CzKf4U8P.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DyJg5gzW.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-B1cw_0Uy.js +0 -8
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { frontendExecutionPolicySchema } from "../../shared/frontend-execution-policy.js";
|
|
2
3
|
import { access, readdir, readFile, realpath } from "node:fs/promises";
|
|
3
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
5
|
import { deflateRawSync } from "node:zlib";
|
|
@@ -698,7 +699,6 @@ export function frontendSourceMentionsMock(sources) {
|
|
|
698
699
|
*/
|
|
699
700
|
export function resolveFrontendMockMode(capability, taskConfig, hasApiDep) {
|
|
700
701
|
const policy = taskConfig.frontendMock?.policy ?? "auto";
|
|
701
|
-
const hasDeterministicMockVerification = capability.verifyCommands.length > 0;
|
|
702
702
|
if (capability.safetyViolation ||
|
|
703
703
|
!frontendMockServiceRootAllowed(taskConfig)) {
|
|
704
704
|
return "blocked";
|
|
@@ -714,7 +714,7 @@ export function resolveFrontendMockMode(capability, taskConfig, hasApiDep) {
|
|
|
714
714
|
}
|
|
715
715
|
// required policy
|
|
716
716
|
if (policy === "required") {
|
|
717
|
-
if (capability.status === "present"
|
|
717
|
+
if (capability.status === "present") {
|
|
718
718
|
return "required";
|
|
719
719
|
}
|
|
720
720
|
return "blocked";
|
|
@@ -723,13 +723,8 @@ export function resolveFrontendMockMode(capability, taskConfig, hasApiDep) {
|
|
|
723
723
|
if (!hasApiDep) {
|
|
724
724
|
return "not-required";
|
|
725
725
|
}
|
|
726
|
-
//
|
|
727
|
-
|
|
728
|
-
// deterministic Mock verification commands. Without executable verification
|
|
729
|
-
// commands a non-not-needed strategy could never be verified, so auto falls
|
|
730
|
-
// back to not-required; the prewrite gate then forces not-needed and the
|
|
731
|
-
// plan records the Real Integration Gap instead of inventing commands.
|
|
732
|
-
return capability.status === "present" && hasDeterministicMockVerification
|
|
726
|
+
// Confirmed Mock capability permits implementation; tests are deferred.
|
|
727
|
+
return capability.status === "present"
|
|
733
728
|
? "required"
|
|
734
729
|
: "not-required";
|
|
735
730
|
}
|
|
@@ -2543,7 +2538,7 @@ function resolveFrontendMockContextBlock(sources) {
|
|
|
2543
2538
|
parts.push(`Evidence Paths: ${capability.evidencePaths.join(", ")}`);
|
|
2544
2539
|
}
|
|
2545
2540
|
if (capability.verifyCommands.length > 0) {
|
|
2546
|
-
parts.push(`
|
|
2541
|
+
parts.push(`Deferred frontend-test Mock Commands: ${capability.verifyCommands
|
|
2547
2542
|
.map((command) => command.label)
|
|
2548
2543
|
.join(", ")}`);
|
|
2549
2544
|
}
|
|
@@ -2554,13 +2549,13 @@ function resolveFrontendMockContextBlock(sources) {
|
|
|
2554
2549
|
parts.push(`Reasons: ${capability.reasons.join("; ")}`);
|
|
2555
2550
|
}
|
|
2556
2551
|
if (mode === "required") {
|
|
2557
|
-
parts.push("
|
|
2552
|
+
parts.push("Implement the selected Mock strategy within authorized paths and keep production-default-off isolation. Mock behavior verification is deferred to frontend-test; it is not an implementation gate.");
|
|
2558
2553
|
}
|
|
2559
2554
|
if (mode === "not-required") {
|
|
2560
2555
|
parts.push("Generation-time evidence does not require Mock. The assessment must still use contract/scout evidence: select not-needed when Mock is intentionally skipped, or select a safe Mock strategy if project evidence supports one.");
|
|
2561
2556
|
if (frontendMockStrategyMustBeNotNeeded(sources)) {
|
|
2562
|
-
parts.push('Auto mode has no confirmed project Mock capability
|
|
2563
|
-
parts.push('HARD CONSTRAINT (frozen at generation time): this DAG allows only mockApi.strategy "not-needed"; the prewrite gate rejects any other strategy. If project governance (openspec / ai_workspace / decision records, e.g. a DEC rule requiring native) demands Mock-backed verification, that is a generation-time contract gap, not a plan-revision defect:
|
|
2557
|
+
parts.push('Auto mode has no confirmed project Mock capability. The structured contract must set mockApi.strategy to "not-needed". Keep the real request path as the default, record any unproved backend behavior as Real Integration Gap, and do not add Mock files or dependencies within this run.');
|
|
2558
|
+
parts.push('HARD CONSTRAINT (frozen at generation time): this DAG allows only mockApi.strategy "not-needed"; the prewrite gate rejects any other strategy. If project governance (openspec / ai_workspace / decision records, e.g. a DEC rule requiring native) demands Mock-backed verification, that is a generation-time contract gap, not a plan-revision defect: confirm the project Mock capability and policy: "required" in task.json and regenerate the DAG.');
|
|
2564
2559
|
}
|
|
2565
2560
|
}
|
|
2566
2561
|
if (mode === "blocked") {
|
|
@@ -2572,12 +2567,10 @@ function frontendMockStrategyMustBeNotNeeded(sources) {
|
|
|
2572
2567
|
const policy = sources.taskConfig.frontendMock?.policy ?? "auto";
|
|
2573
2568
|
const capability = sources.frontendMockCapability;
|
|
2574
2569
|
const capabilityStatus = capability?.status;
|
|
2575
|
-
const hasDeterministicMockVerification = (capability?.verifyCommands.length ?? 0) > 0;
|
|
2576
2570
|
return (policy === "auto" &&
|
|
2577
2571
|
(sources.frontendMockMode ?? "not-required") === "not-required" &&
|
|
2578
2572
|
(capabilityStatus === "absent" ||
|
|
2579
|
-
capabilityStatus === "ambiguous"
|
|
2580
|
-
!hasDeterministicMockVerification));
|
|
2573
|
+
capabilityStatus === "ambiguous"));
|
|
2581
2574
|
}
|
|
2582
2575
|
/**
|
|
2583
2576
|
* 候选规范懒加载:prompt 只内联与任务相关的候选,不全部塞给模型。
|
|
@@ -3061,7 +3054,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3061
3054
|
.filter(Boolean)
|
|
3062
3055
|
.join("\n\n"),
|
|
3063
3056
|
scout: [
|
|
3064
|
-
buildSourceContextBlock(sources, { includeReferenceDocuments: false }),
|
|
3057
|
+
buildSourceContextBlock(sources, { includeRequirementExcerpt: false, includeConstraintExcerpt: false, includeReferenceDocuments: false }),
|
|
3065
3058
|
capabilityContextBlock,
|
|
3066
3059
|
]
|
|
3067
3060
|
.filter(Boolean)
|
|
@@ -3072,12 +3065,8 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3072
3065
|
includeReferenceDocuments: false,
|
|
3073
3066
|
}),
|
|
3074
3067
|
};
|
|
3075
|
-
const hasMockVerifyCommands = (taskConfig.frontendMock?.verifyCommands.length ?? 0) > 0 ||
|
|
3076
|
-
mockCapability.verifyCommands.length > 0;
|
|
3077
3068
|
const requirementIds = frontendSourceBinding.requirementIds;
|
|
3078
|
-
const strategy = resolveDagVerifyStrategy(taskConfig);
|
|
3079
3069
|
const readOnlyPaths = taskConfig.allowedPaths.length > 0 ? taskConfig.allowedPaths : ["**"];
|
|
3080
|
-
const behaviorPaths = deriveFrontendBehaviorPaths(taskConfig);
|
|
3081
3070
|
const globalConstraints = [
|
|
3082
3071
|
...taskConfig.hardConstraints,
|
|
3083
3072
|
...(sources.constraintMarkdown
|
|
@@ -3091,7 +3080,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3091
3080
|
"Frontend planning must consume the read-only Mock assessment strategy produced after scouting; MOCK_STRATEGY: blocked must not pass the deterministic Mock contract gate.",
|
|
3092
3081
|
"Mock implementations must preserve the real request path as the default, require explicit test/dev activation, and never rely on commenting out the real request.",
|
|
3093
3082
|
"Mock-backed behavior evidence proves only the documented frontend contract, never real API integration.",
|
|
3094
|
-
"frontend-implementation
|
|
3083
|
+
"frontend-implementation completes requirement-to-code coverage and npm run build only. Behavior correctness and all testing are deferred to frontend-test; build success is never behavior-test success.",
|
|
3095
3084
|
"Frontend closeout renders only from committed facts; a weak status (failed / not-run / baseline-debt / mock-backed / pending) can never be rewritten into a stronger one (passed / real-integrated).",
|
|
3096
3085
|
`Frontend risk classification: ${frontendRisk.selectedRisk} — ${frontendRisk.reason}`,
|
|
3097
3086
|
frontendRisk.forceFullGates
|
|
@@ -3103,111 +3092,34 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3103
3092
|
const blockedReason = mockCapability.safetyViolation
|
|
3104
3093
|
? `Mock contract blocked: ${mockCapability.safetyViolation}`
|
|
3105
3094
|
: (taskConfig.frontendMock?.policy ?? "auto") === "required"
|
|
3106
|
-
? "Mock strategy is required, but no authorized Mock
|
|
3095
|
+
? "Mock strategy is required, but no authorized Mock capability was found."
|
|
3107
3096
|
: "Mock contract is blocked by deterministic generation-time Mock safety constraints.";
|
|
3108
3097
|
return buildBlockedFrontendMockDag(frontendSources, readOnlyPaths, forbiddenPaths, globalConstraints, blockedReason);
|
|
3109
3098
|
}
|
|
3110
|
-
|
|
3111
|
-
//
|
|
3112
|
-
// a real
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
: [FRONTEND_NO_STATIC_VERIFICATION_MARKER];
|
|
3119
|
-
const behaviorFallbackCommands = fallbackVerifyCommands.behaviorCommands;
|
|
3120
|
-
const parsedFrontendVerifyCommands = extractFrontendVerifyCommandsFromMarkdown({
|
|
3121
|
-
repoRoot: sources.repoRoot,
|
|
3122
|
-
requirementMarkdown: sources.requirementMarkdown,
|
|
3123
|
-
constraintMarkdown: sources.constraintMarkdown,
|
|
3124
|
-
});
|
|
3125
|
-
const explicitFrontendVerifyCommands = buildExplicitFrontendVerifyCommands(taskConfig, sources.repoRoot);
|
|
3126
|
-
const explicitCommandKeys = new Set([
|
|
3127
|
-
...explicitFrontendVerifyCommands.staticCommands,
|
|
3128
|
-
...explicitFrontendVerifyCommands.behaviorCommands,
|
|
3129
|
-
].map(verifyCommandKey));
|
|
3130
|
-
const adapterVerifyCommands = (sources.verifyCommands?.final ?? []).filter((command) => !explicitCommandKeys.has(verifyCommandKey(command)));
|
|
3131
|
-
const hasDeclaredFrontendVerification = explicitFrontendVerifyCommands.staticCommands.length > 0 ||
|
|
3132
|
-
explicitFrontendVerifyCommands.behaviorCommands.length > 0 ||
|
|
3133
|
-
parsedFrontendVerifyCommands.staticCommands.length > 0 ||
|
|
3134
|
-
parsedFrontendVerifyCommands.behaviorCommands.length > 0;
|
|
3135
|
-
const staticVerifyCommands = chooseFrontendVerifyCommands({
|
|
3136
|
-
explicitCommands: explicitFrontendVerifyCommands.staticCommands,
|
|
3137
|
-
parsedCommands: parsedFrontendVerifyCommands.staticCommands,
|
|
3138
|
-
adapterCommands: adapterVerifyCommands,
|
|
3139
|
-
});
|
|
3140
|
-
const partitionedStaticVerifyCommands = partitionFrontendStaticVerifyCommands({
|
|
3141
|
-
repoRoot: sources.repoRoot,
|
|
3142
|
-
commands: staticVerifyCommands.commands,
|
|
3143
|
-
commandSource: staticVerifyCommands.commandSource,
|
|
3144
|
-
});
|
|
3145
|
-
const behaviorVerifyCommands = chooseFrontendVerifyCommands({
|
|
3146
|
-
explicitCommands: explicitFrontendVerifyCommands.behaviorCommands,
|
|
3147
|
-
parsedCommands: parsedFrontendVerifyCommands.behaviorCommands,
|
|
3148
|
-
adapterCommands: adapterVerifyCommands,
|
|
3149
|
-
// A declared task verifier owns this task's verification boundary. A
|
|
3150
|
-
// static-only task must not inherit unrelated root-level test commands.
|
|
3151
|
-
allowAdapter: !hasDeclaredFrontendVerification,
|
|
3152
|
-
});
|
|
3099
|
+
// Implementation verifies buildability only. Tests (including task-declared
|
|
3100
|
+
// and Mock commands) belong to the independent frontend-test workflow.
|
|
3101
|
+
// Keep a real failing command when build is unavailable; never use a no-op.
|
|
3102
|
+
const buildCommands = [{
|
|
3103
|
+
label: "build",
|
|
3104
|
+
args: ["bash", "-lc", "npm run build"],
|
|
3105
|
+
cwd: sources.repoRoot ?? process.cwd(),
|
|
3106
|
+
}];
|
|
3153
3107
|
const staticShellCommands = buildVerifyShellCommands({
|
|
3154
|
-
repoRoot: sources.repoRoot,
|
|
3155
|
-
commands: partitionedStaticVerifyCommands.static.commands,
|
|
3156
|
-
fallbackCommands: staticFallbackCommands,
|
|
3157
|
-
});
|
|
3158
|
-
const lintShellCommands = buildVerifyShellCommands({
|
|
3159
|
-
repoRoot: sources.repoRoot,
|
|
3160
|
-
commands: partitionedStaticVerifyCommands.lint.commands,
|
|
3161
|
-
fallbackCommands: [],
|
|
3108
|
+
repoRoot: sources.repoRoot ?? process.cwd(), commands: buildCommands, fallbackCommands: [],
|
|
3162
3109
|
});
|
|
3163
|
-
const behaviorShellCommands = buildVerifyShellCommands({
|
|
3164
|
-
repoRoot: sources.repoRoot,
|
|
3165
|
-
commands: behaviorVerifyCommands.commands,
|
|
3166
|
-
fallbackCommands: hasDeclaredFrontendVerification
|
|
3167
|
-
? []
|
|
3168
|
-
: behaviorFallbackCommands,
|
|
3169
|
-
});
|
|
3170
|
-
const effectiveBehaviorFallbackCommands = hasDeclaredFrontendVerification
|
|
3171
|
-
? []
|
|
3172
|
-
: behaviorFallbackCommands;
|
|
3173
3110
|
const staticVerifyEvidence = buildVerifyEvidence({
|
|
3174
|
-
phase: "
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
commands: partitionedStaticVerifyCommands.static.commands,
|
|
3178
|
-
fallbackCommands: staticFallbackCommands,
|
|
3179
|
-
commandTexts: staticShellCommands,
|
|
3180
|
-
commandTimeoutMs: DEFAULT_VERIFY_TIMEOUT_MS,
|
|
3181
|
-
preflight: sources.verificationPreflight,
|
|
3111
|
+
phase: "final", quota: "full", commandSource: "inline",
|
|
3112
|
+
commands: buildCommands, fallbackCommands: [], commandTexts: staticShellCommands,
|
|
3113
|
+
finalFullRequired: true, commandTimeoutMs: DEFAULT_VERIFY_TIMEOUT_MS,
|
|
3182
3114
|
});
|
|
3183
|
-
const
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
quota: strategy.intermediateQuota ?? "full",
|
|
3187
|
-
commandSource: partitionedStaticVerifyCommands.lint.commandSource,
|
|
3188
|
-
commands: partitionedStaticVerifyCommands.lint.commands,
|
|
3189
|
-
fallbackCommands: [],
|
|
3190
|
-
commandTexts: lintShellCommands,
|
|
3191
|
-
commandTimeoutMs: DEFAULT_VERIFY_TIMEOUT_MS,
|
|
3192
|
-
preflight: sources.verificationPreflight,
|
|
3193
|
-
})
|
|
3194
|
-
: undefined;
|
|
3115
|
+
const behaviorShellCommands = [];
|
|
3116
|
+
const lintShellCommands = [];
|
|
3117
|
+
const mockShellCommands = [];
|
|
3195
3118
|
const behaviorVerifyEvidence = buildVerifyEvidence({
|
|
3196
|
-
phase: "final",
|
|
3197
|
-
|
|
3198
|
-
commandSource: behaviorVerifyCommands.commandSource,
|
|
3199
|
-
commands: behaviorVerifyCommands.commands,
|
|
3200
|
-
fallbackCommands: effectiveBehaviorFallbackCommands,
|
|
3201
|
-
commandTexts: behaviorShellCommands,
|
|
3202
|
-
finalFullRequired: true,
|
|
3119
|
+
phase: "final", quota: "full", commandSource: "inline",
|
|
3120
|
+
commands: [], fallbackCommands: [], commandTexts: [],
|
|
3203
3121
|
commandTimeoutMs: DEFAULT_VERIFY_TIMEOUT_MS,
|
|
3204
|
-
preflight: sources.verificationPreflight,
|
|
3205
3122
|
});
|
|
3206
|
-
const mockVerifyTemplate = mockMode === "required" && hasMockVerifyCommands
|
|
3207
|
-
? buildFrontendMockVerifyNode(frontendSources, implementId, readOnlyPaths, forbiddenPaths)
|
|
3208
|
-
: undefined;
|
|
3209
|
-
const mockShellCommands = mockVerifyTemplate?.shell?.commands ?? [];
|
|
3210
|
-
const mockVerifyEvidence = mockVerifyTemplate?.shell?.verifyEvidence;
|
|
3211
3123
|
// Contract v2: the frozen command directory is the only command reference
|
|
3212
3124
|
// the plan may use. Modes are assigned here once from the generation-time
|
|
3213
3125
|
// lane split; downstream materialization resolves the same directory from
|
|
@@ -3215,28 +3127,23 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3215
3127
|
const frontendVerifyDirectory = buildFrontendVerifyCommandDirectory({
|
|
3216
3128
|
staticLabels: staticVerifyEvidence.commandLabels,
|
|
3217
3129
|
behaviorLabels: behaviorVerifyEvidence.commandLabels,
|
|
3218
|
-
mockLabels:
|
|
3130
|
+
mockLabels: [],
|
|
3219
3131
|
staticCommandTexts: staticVerifyEvidence.commandTexts,
|
|
3220
3132
|
behaviorCommandTexts: behaviorVerifyEvidence.commandTexts,
|
|
3221
|
-
mockCommandTexts:
|
|
3133
|
+
mockCommandTexts: [],
|
|
3222
3134
|
});
|
|
3223
3135
|
const fixedVerificationContext = [
|
|
3224
3136
|
"## Fixed frontend verification entrypoints",
|
|
3225
|
-
"
|
|
3137
|
+
"Implementation verification is npm run build only. Map requirements to implementation files and the shared static build target. Test design, test execution, behavior correctness, edge cases, regression, accessibility and Mock-backed testing are deferred to the independent frontend-test workflow; missing test plans or test evidence never block this implementation workflow.",
|
|
3226
3138
|
"Reference frozen commands ONLY by commandId (record_plan_verification_target entry.commandId). The runtime resolves mode and label; never invent a mode or type.",
|
|
3227
3139
|
...frontendVerifyDirectory.map((entry) => ` - ${entry.commandId} [${entry.mode}]: ${JSON.stringify(entry.label)}`),
|
|
3228
3140
|
`- Static command source: ${staticVerifyEvidence.commandSource}`,
|
|
3229
3141
|
`- Behavior command source: ${behaviorVerifyEvidence.commandSource}`,
|
|
3230
3142
|
].join("\n");
|
|
3231
3143
|
const advisories = [];
|
|
3232
|
-
if (!hasDeclaredFrontendVerification &&
|
|
3233
|
-
fallbackVerifyCommands.staticCommands.length === 0 &&
|
|
3234
|
-
fallbackVerifyCommands.behaviorCommands.length === 0) {
|
|
3235
|
-
advisories.push("未发现可用的前端验证命令:目标项目没有可读取的 package.json scripts,也未探测到本地 TypeScript,verify 节点将没有静态/行为命令可执行。请在 task.json --verify 或执行约束.md 的验证约束中显式声明命令(例如 node --check src/app.js),然后重新生成 DAG。");
|
|
3236
|
-
}
|
|
3237
3144
|
if (frontendSourceMentionsMock(frontendSources) &&
|
|
3238
3145
|
frontendMockStrategyMustBeNotNeeded(frontendSources)) {
|
|
3239
|
-
advisories.push("auto 模式已将 Mock 策略收窄为 not-needed:任务源提到接口/API/Mock 需求,但仓库无确认 Mock
|
|
3146
|
+
advisories.push("auto 模式已将 Mock 策略收窄为 not-needed:任务源提到接口/API/Mock 需求,但仓库无确认 Mock 能力。若项目规范要求 Mock,请确认项目 Mock 能力与 policy:required 后重新生成 DAG。");
|
|
3240
3147
|
}
|
|
3241
3148
|
const openspecGate = await resolveFrontendOpenspecGateConfig(sources);
|
|
3242
3149
|
const requiresOpenspecClassification = openspecGate.openspecPolicy === "cited" &&
|
|
@@ -3342,13 +3249,13 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3342
3249
|
allowedPaths: readOnlyPaths,
|
|
3343
3250
|
forbiddenPaths,
|
|
3344
3251
|
skills: FRONTEND_CONTRACT_SKILLS,
|
|
3345
|
-
outputContract: "
|
|
3252
|
+
outputContract: "Incremental typed requirement facts; narrative is display-only. Submit through the incremental typed tools record_requirement / record_constraint / record_evidence_expectation / record_handoff_intent / record_open_question / record_split_proposal / record_ui_state / record_required_deliverables / record_openspec_selection, then complete each input scope with complete_contract_scope, then call finalize_contract; correct rejected calls until one successful terminal. record_requirement takes the canonical ledger requirement id and optional execution:{groupId,kind,summary} — the runtime owns the authoritative text, source spans, fragment bindings, and disposition. UI-visible or interactive requirements register a non-blocking frontend-test handoff intent, and any source-declared UI-state table is extracted verbatim through record_ui_state. End finalize_contract with a single contract disposition of ready | ready-with-assumptions | blocked. Cover scope, non-goals, acceptance criteria, UI states, target runtime environment, risks, and verification expectations; do not fix target files, components, or implementation methods as requirements. When OpenSpec candidates exist, classify only the ones you actually use: call record_openspec_selection once per required/relevant path; never enumerate irrelevant candidates (unmentioned defaults to irrelevant) and never emit a fenced selection JSON. No file writes.",
|
|
3346
3253
|
subtask_prompt: [
|
|
3347
|
-
"OUTPUT BUDGET DISCIPLINE
|
|
3348
|
-
"
|
|
3349
|
-
"Confirm each requirement by the SAME id as the ledger canonical requirement it covers (sourceBinding.requirementIds, e.g. AC-001) — do NOT invent new REQ/BR prefixed ids for canonical requirements: the compiled contract must match the ledger canonical requirement ids exactly or schema validation rejects it (unknown requirement id). record_requirement takes
|
|
3254
|
+
"OUTPUT BUDGET DISCIPLINE: provider capacity is discovered at runtime; use small records — NEVER attempt to emit the whole contract in one response; a single large JSON dump will be truncated and rejected. Incremental submission through the typed tools is the ONLY supported output mode. Start submitting with the FIRST tool call: after each read, call record_requirement for the requirements you have already confirmed, one or a few per call. Every tool-call round MUST make progress by submitting at least one record_* fact. Do not re-read the same source file that is already materialized in this session; read each file at most once.",
|
|
3255
|
+
"Consume the complete injected input scope and produce a concise frontend implementation contract as typed requirement facts from complete injected scopes.",
|
|
3256
|
+
"Confirm each requirement by the SAME id as the ledger canonical requirement it covers (sourceBinding.requirementIds, e.g. AC-001) — do NOT invent new REQ/BR prefixed ids for canonical requirements: the compiled contract must match the ledger canonical requirement ids exactly or schema validation rejects it (unknown requirement id). record_requirement takes the canonical id and optional execution:{groupId,kind,summary}; the runtime commits the authoritative text and sourceFragmentIds from the frozen ledger. Never pass text/statement/sourceFragmentIds yourself — model rewrites and JSON-stringified fragment arrays are rejected.",
|
|
3350
3257
|
"Requirement semantics, source spans, dispositions, and fragment bindings are ledger/runtime-owned. If a canonical requirement is genuinely blocked, say so in the Markdown contract narrative and finalize with the matching disposition instead of trying to encode it in the requirement fact.",
|
|
3351
|
-
"Register evidence expectations
|
|
3258
|
+
"Register source evidence expectations without treating them as this implementation run's test gates. Always register a non-blocking frontend-test handoff intent for behavior, regression, Mock, and integration testing. This run checks requirement implementation coverage and npm run build only; test methods and results belong to the separate testing workflow.",
|
|
3352
3259
|
'Use record_evidence_expectation with {requirementId,evidence:{static,behavior,mock,"real-integration"}}; every lane is required | optional | not-applicable. Requirement text and provenance remain runtime-owned.',
|
|
3353
3260
|
'Before finalize_contract ready, call record_required_deliverables once with the complete {items:[{path,requirementId,sourceFragmentId}]} inventory, or {items:[]} when no file delivery is mandatory. Interpret the original source, including lists and tables: allowedPaths/only-allowed-to-modify is permission, not an obligation; do not promote prohibited files, examples or references into deliverables. Paths must occur exactly in a frozen source fragment bound to that canonical requirement. Correct the whole inventory before finalizing if needed.',
|
|
3354
3261
|
"Authoritative UI states: when the task source declares a UI-state table (state id / trigger / observable outcome), extract it VERBATIM through record_ui_state, one call per state, using the source's own state ids. The planner must bind these ids later — do not rename, merge, or invent states.",
|
|
@@ -3406,17 +3313,17 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3406
3313
|
retryOnInvalid: true,
|
|
3407
3314
|
skeleton: frontendContractSkeleton,
|
|
3408
3315
|
},
|
|
3409
|
-
outputContract: "Typed decision patch only: map frozen requirements to implementation/verification targets and select the needed component, state, data/Mock, styling, and dependency decisions. Use only the record_* tools needed to express those decisions, then call finalize_plan
|
|
3316
|
+
outputContract: "Typed decision patch only: map frozen requirements to implementation/verification targets and select the needed component, state, data/Mock, styling, and dependency decisions. Use only the record_* tools needed to express those decisions, then call finalize_plan; correct rejected facts until one successful terminal. Contract owns requirement semantics; Scout owns repository discovery; deterministic runtime owns schema, protected fields, path containment, and command validation. No Markdown narrative or file writes.",
|
|
3410
3317
|
subtask_prompt: [
|
|
3411
|
-
"
|
|
3318
|
+
"List the implementation plan from frozen Contract requirements and Scout paths: what to change, where, and the needed component/state/data decisions. Submit those concrete actions in finalize_plan implementationSteps: [{requirementIds, action}]; cover every frozen requirement, sharing steps across related IDs when appropriate. Do not design tests, prescribe DOM harnesses, or require test evidence.",
|
|
3412
3319
|
"Record only: requirement-to-file/verification coverage; component/styling choices; applicable UI state and interaction behavior; data/Mock strategy; and a dependency policy or genuine evidence gap. Reuse Scout paths. If scope is missing, record a blocking gap instead of inventing a path.",
|
|
3413
3320
|
"Use the typed tool schemas as the field contract. Runtime owns schemaVersion, sourceBinding, riskLevel, targets.files, mockApi.productionDefaultOff, aliases, command allowlisting, path containment, and final validation; do not restate those rules or emit a full JSON contract.",
|
|
3414
|
-
`Cover each frozen requirement ID exactly once: ${requirementIds.join(", ") || "(none)"}. Bind every verification target to a frozen commandId from the directory above plus a Scout-confirmed file.
|
|
3415
|
-
"UX vocabulary protocol: record_state_registry FIRST with the full global vocabulary — one stable kebab-case behavior-domain name per UI state/interaction (e.g. planner-task-edit, focus-queue-move), never one name per AC number and never a rename of an already-recorded concept.
|
|
3321
|
+
`Cover each frozen requirement ID exactly once: ${requirementIds.join(", ") || "(none)"}. Bind every verification target to a frozen commandId from the directory above plus a Scout-confirmed file. Use the shared static build target for implementation files; do not create behavior test targets or test plans. Static commands are project-wide checks traced by file and command only.`,
|
|
3322
|
+
"UX vocabulary protocol: record_state_registry FIRST with the full global vocabulary — one stable kebab-case behavior-domain name per UI state/interaction (e.g. planner-task-edit, focus-queue-move), never one name per AC number and never a rename of an already-recorded concept. Details consume complete execution-group scopes and reuse the same global names across scopes. Constraints/exclusions must not manufacture UI. Then record_state_flow entries whose names all come from that registry; uiState names must use the contract's declared authoritative ids (declaredUiStates in the plan input) when present. Retry attempts see committedUx in this input — reuse those exact names. Components: one choice may cover many state/interaction ids via covers; reuse-existing requires evidencePath naming an existing repo file (greenfield must be decision=new).",
|
|
3416
3323
|
...(requiresOpenspecClassification ? ["When a component choice uses an OpenSpec selection, cite that selection; otherwise do not classify unrelated candidates."] : []),
|
|
3417
|
-
"Call finalize_plan
|
|
3418
|
-
"TOOL-ONLY PLAN: Do not read Contract/Scout stdout, task sources, or Scout-confirmed target files. Contract and Scout already own evidence discovery; use the injected upstream facts, record a genuine evidence gap when those facts are insufficient, and start committing record_* facts immediately. For decision=new, pass sourceRequirementIds to record_component_choice; runtime derives the exact PRD citation from the frozen ledger.",
|
|
3419
|
-
"
|
|
3324
|
+
"Call finalize_plan; correct rejected facts until one successful terminal after the necessary typed facts. Return no Markdown narrative.",
|
|
3325
|
+
"Group members retain full source text and independent ACs. Use record_plan_group_coverage only for actually shared references; do not create components for exclusions. TOOL-ONLY PLAN: Do not read Contract/Scout stdout, task sources, or Scout-confirmed target files. Contract and Scout already own evidence discovery; use the injected upstream facts, record a genuine evidence gap when those facts are insufficient, and start committing record_* facts immediately. For decision=new, pass sourceRequirementIds to record_component_choice; runtime derives the exact PRD citation from the frozen ledger.",
|
|
3326
|
+
"Incremental output protocol: process the current complete scope, committing small records immediately. Runtime packs full input and estimated work without assuming a model capacity from its name. Use record_plan_group_coverage for shared references, record_mock_endpoint per endpoint, and finalize only when all coverage is complete. On exhaustion, durable progress survives and remaining work is reduced; never omit source conditions or repeatedly retry the same exhausted scope.",
|
|
3420
3327
|
fixedVerificationContext,
|
|
3421
3328
|
scopedOpenspecContext,
|
|
3422
3329
|
mockContextBlock,
|
|
@@ -3456,7 +3363,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3456
3363
|
"request-adapter",
|
|
3457
3364
|
"not-needed",
|
|
3458
3365
|
],
|
|
3459
|
-
mockCommandLabels:
|
|
3366
|
+
mockCommandLabels: [],
|
|
3460
3367
|
artifactName: "frontend-implementation-contract.json",
|
|
3461
3368
|
outputDir: "contracts",
|
|
3462
3369
|
requireSourceFreshness: true,
|
|
@@ -3500,14 +3407,15 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3500
3407
|
skills: FRONTEND_DESIGN_REVIEW_SKILLS,
|
|
3501
3408
|
outputContract: "Authoritative typed design terminal via approve_design / request_design_changes tools. No JSON verdict; the committed typed design fact is the only authority. No file writes.",
|
|
3502
3409
|
subtask_prompt: [
|
|
3410
|
+
"Submit findings individually with record_design_finding and stable IDs; terminal tools aggregate saved findings. Correct rejected calls, stop after a successful terminal. Check execution groups against every member source outcome, including permission, threshold and failure-path differences; each independent AC needs corresponding planned implementation; shared build evidence checks buildability only.",
|
|
3503
3411
|
"Audit the frontend plan before implementation. frontend-plan-pi is emitted to you as canonical full-contract JSON after the runtime applied and validated the planner's editable patch against its protected skeleton; there is no separate plan prose.",
|
|
3504
3412
|
"Your authoritative terminal verdict is exactly one committed typed tool call: approve_design or request_design_changes. Call exactly one of them; after calling one, do not call the other.",
|
|
3505
3413
|
"request_design_changes must carry a typed issueCategory, at least one evidenceRef, and non-empty findings.",
|
|
3506
3414
|
"Your verdict is consumed as deterministic data input by frontend-writer-admission-shell. approve_design permits admission; request_design_changes blocks writer admission until a recovery plan incorporates every Critical/Important finding.",
|
|
3507
|
-
"Request design changes
|
|
3508
|
-
"
|
|
3415
|
+
"Request design changes only for missing requirement implementation coverage or unauthorized scope/dependencies. Preserve declared production-default-off Mock boundaries. Missing test methods, test cases, DOM/state-transition verification, Mock-backed evidence or behavior correctness evidence are not design blockers; defer them to frontend-test.",
|
|
3416
|
+
"Check whether every required feature/state has an implementation plan and whether paths and dependencies are authorized. Do not turn behavior correctness or regression concerns into implementation blockers; record them for frontend-test.",
|
|
3509
3417
|
"Component selection conformance is a hard blocking condition: request_design_changes when the frontend spec (component/theme/rule.components bucket) already defines a component for a purpose but the plan selects another or self-invents one without a declared deviation; when uiComponentChoices is missing/empty for UI-visible work while the frozen component/theme bucket is non-empty; when a decision=specified specReference.path is missing a ledger OpenSpec reference or successful read event; or when a decision=new component lacks a traceable task-source/PRD specReference. A PRD reference for decision=new is not an OpenSpec citation and must not be rejected merely for lacking an OpenSpec read event. For uiComponentChoices, purpose is the stable coverage key and must match interaction.name or uiState.name; responsibility is expressed by the matched expectedBehavior plus rationale, and you must not reject it merely for matching an interaction or component identifier.",
|
|
3510
|
-
"
|
|
3418
|
+
"The only executable verification in this workflow is npm run build. A missing test plan, missing behavior evidence, or prediction that tests will fail is non-blocking and belongs to frontend-test. Only requirement omissions, scope violations and a failed build block implementation completion.",
|
|
3511
3419
|
"Read-only: do not modify repository files.",
|
|
3512
3420
|
"LARGE-FILE AUDIT (avoid full reads): style/theme audit files can be large (e.g. styles.css is often hundreds of KB). Prefer grep to locate the exact rules/variables you must verify (e.g. grep the oc- class, is-* modifier, or --oc- theme variables with their line numbers), then read only the narrow line range when surrounding context is needed. Do not read a large style/test file in full — a single full read can exhaust the read budget and fail the attempt.",
|
|
3513
3421
|
"Canonical contract reading: frontend-design-policy-shell prints absolute paths for Contract, Contract index, and the non-blocking Capacity diagnostic. Read the capacity diagnostic first. When it recommends full-contract, read the exact Contract path. When it recommends indexed-sections, read the Contract index and its hash-bound section files instead of opening the full contract. Never resolve a bare contracts/... path against the repository root or hunt for substitutes. Implementation target files inside the writeSet are created later by the implement node: do not read them and do not treat their absence as a design defect.",
|
|
@@ -3533,11 +3441,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3533
3441
|
frontendWriterAdmission: {
|
|
3534
3442
|
schemaVersion: 1,
|
|
3535
3443
|
designReviewFromNodeId: "frontend-design-review-pi",
|
|
3536
|
-
frozenCommandLabels:
|
|
3537
|
-
...staticVerifyEvidence.commandLabels,
|
|
3538
|
-
...behaviorVerifyEvidence.commandLabels,
|
|
3539
|
-
...(mockVerifyEvidence?.commandLabels ?? []),
|
|
3540
|
-
],
|
|
3444
|
+
frozenCommandLabels: staticVerifyEvidence.commandLabels,
|
|
3541
3445
|
allowedMockStrategies: taskConfig.frontendMock?.policy === "disabled" ||
|
|
3542
3446
|
frontendMockStrategyMustBeNotNeeded(frontendSources)
|
|
3543
3447
|
? ["not-needed"]
|
|
@@ -3553,12 +3457,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3553
3457
|
"request-adapter",
|
|
3554
3458
|
"not-needed",
|
|
3555
3459
|
],
|
|
3556
|
-
...(lintShellCommands.length > 0 && lintVerifyEvidence
|
|
3557
|
-
? {
|
|
3558
|
-
lintCommands: lintShellCommands,
|
|
3559
|
-
lintEvidence: lintVerifyEvidence,
|
|
3560
|
-
}
|
|
3561
|
-
: {}),
|
|
3562
3460
|
},
|
|
3563
3461
|
cwd: ".",
|
|
3564
3462
|
timeoutMs: 60000,
|
|
@@ -3574,18 +3472,16 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3574
3472
|
forbiddenPaths,
|
|
3575
3473
|
writerOutcomePolicyType: "frontend-facts-v1",
|
|
3576
3474
|
}),
|
|
3577
|
-
outputContract: "The implementation status
|
|
3475
|
+
outputContract: "The executor derives implementation status from write events, diff, write guard and build checks. Report changed files, requirement-to-code coverage, build result and pending frontend-test handoff; do not claim tested behavior correctness.",
|
|
3578
3476
|
subtask_prompt: [
|
|
3579
3477
|
"Implement against the validated run-owned Frontend Implementation Contract materialized by frontend-design-policy-shell (path/schema/hash) and authorized by frontend-writer-admission-shell. Do not rebuild the contract from Markdown alone.",
|
|
3580
3478
|
"WRITER TOOL PROTOCOL (hard): the response text is not delivery. Never paste source code, test code, or full file contents into chat. After reading the canonical contract, make the first implementation change with the structured write/edit tool (one file per call); continue writing through those tools until the writeSet is complete. If a write/edit tool is unavailable, stop and report the blocked capability instead of drafting code in the response.",
|
|
3581
3479
|
"The canonical contract already contains the approved requirement, target-file, UI-state, verification, design, and Mock/API decisions. Do not re-open task sources, OpenSpec, AI workspace, plan/revision, or design-review prose, and do not repeat broad repository research. Inspect only contract target files and directly related local code needed to implement them.",
|
|
3582
|
-
"
|
|
3583
|
-
"Map every requirement id, expectedOutcome, interaction
|
|
3584
|
-
"For every behavior verification target, treat target.id as a stable trace token and include that exact token in a real describe/it/test literal title (for example, it('[VT-DASHBOARD-SHELL] renders the dashboard', ...)). One test title may carry multiple target ids when it proves multiple grouped behaviors; comments and ordinary strings do not count as trace evidence.",
|
|
3585
|
-
"Before reporting Tests Changed as done, self-audit with the executor's rule: collect ONLY the string literals passed directly to describe(/it(/test( calls in each test file and confirm every behavior target id for that file appears inside one of those literals. A token in a comment, a variable, or a non-title string does not satisfy the trace check; if any id is missing from the literal titles, edit the title strings before finishing.",
|
|
3480
|
+
"Implement the planned requirements and report where each is realized. Do not add a test-first stage or require tests for completion. The independent frontend-test workflow owns tests; the only frozen command here is npm run build.",
|
|
3481
|
+
"Map every requirement id, expectedOutcome, interaction and applicable UI state to concrete implementation files. The shared static build target is a buildability check, not proof of behavior correctness.",
|
|
3586
3482
|
"Begin implementation after the contract and its target files are confirmed. Do not spend the turn collecting optional context. If the canonical contract lacks behavior needed to edit safely, stop and state the blocking reason in the summary instead of reopening broad discovery.",
|
|
3587
3483
|
"Your implementation status is derived by the executor from mechanical facts (persisted write-tool events, run delta, write guard, requirement coverage, focused-check failures), never from any IMPLEMENTATION_OUTCOME first line. Do not emit an IMPLEMENTATION_OUTCOME first line.",
|
|
3588
|
-
"The node
|
|
3484
|
+
"The node uses bounded build checks and diff checkpoints. Repair local syntax/type/import/build errors within the writeSet; do not expand into behavior testing, regression testing or test repair.",
|
|
3589
3485
|
"Implement only the approved Mock strategy carried by the validated contract. Preserve the real request path as the default, require explicit test/dev activation, and never comment out or replace the real request with inline data.",
|
|
3590
3486
|
"frontend-design-policy-shell materialized and validated the canonical contract; frontend-writer-admission-shell authorized the writeSet. Stay within writeSet and preserve unrelated files.",
|
|
3591
3487
|
"For native, browser-intercept, or request-adapter, implement contract-aligned fixtures/states and a dev/test-only activation boundary in this same writer. For not-needed, do not add Mock files or a framework and state the positive reason.",
|
|
@@ -3593,7 +3489,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3593
3489
|
"Edit existing files with the structured edit/write tools. NEVER rewrite Markdown (or any file with quoting/backticks/indentation-sensitive content) via bash sed/awk/echo redirection: escaping mistakes silently corrupt the file and self-repair loops burn the run.",
|
|
3594
3490
|
...(implementPaths.docIndexCompanions.length > 0
|
|
3595
3491
|
? [
|
|
3596
|
-
`Doc index sync is MANDATORY: ${implementPaths.docIndexCompanions.join(", ")} are catalog index files for this writeSet. When you add, rename, or remove any indexed file, you MUST also update ${implementPaths.docIndexCompanions.join(" and ")} in the same run (append or fix the matching index entry following the existing line style).
|
|
3492
|
+
`Doc index sync is MANDATORY: ${implementPaths.docIndexCompanions.join(", ")} are catalog index files for this writeSet. When you add, rename, or remove any indexed file, you MUST also update ${implementPaths.docIndexCompanions.join(" and ")} in the same run (append or fix the matching index entry following the existing line style). Keep these index updates within the authorized writeSet.`,
|
|
3597
3493
|
]
|
|
3598
3494
|
: []),
|
|
3599
3495
|
writerDeliveryContract(taskConfig),
|
|
@@ -3610,7 +3506,7 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3610
3506
|
writePolicy: "read-only",
|
|
3611
3507
|
allowedPaths: readOnlyPaths,
|
|
3612
3508
|
forbiddenPaths,
|
|
3613
|
-
outputContract: "Run
|
|
3509
|
+
outputContract: "Run npm run build and preserve its exit status. No test, lint or separate typecheck commands; any build failure remains terminal and eligible for existing bounded recovery.",
|
|
3614
3510
|
subtask_prompt: "Execute the frontend verification bundle. Preserve per-command evidence; a failure fails this node (terminal) and routes to recovery.",
|
|
3615
3511
|
shell: {
|
|
3616
3512
|
commands: [],
|
|
@@ -3620,8 +3516,6 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3620
3516
|
lintCommands: lintShellCommands,
|
|
3621
3517
|
staticCommands: staticShellCommands,
|
|
3622
3518
|
behaviorCommands: behaviorShellCommands,
|
|
3623
|
-
mockEvidence: mockVerifyEvidence,
|
|
3624
|
-
lintEvidence: lintVerifyEvidence,
|
|
3625
3519
|
staticEvidence: staticVerifyEvidence,
|
|
3626
3520
|
behaviorEvidence: behaviorVerifyEvidence,
|
|
3627
3521
|
lintBaselineNodeId: lintShellCommands.length > 0
|
|
@@ -3665,19 +3559,20 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3665
3559
|
skills: FRONTEND_REVIEW_SKILLS,
|
|
3666
3560
|
outputContract: 'Authoritative typed review terminal via approve_review / request_review_changes tools. No JSON verdict is required in the response text; the typed terminal fact is the only authority. No file writes.',
|
|
3667
3561
|
subtask_prompt: [
|
|
3668
|
-
"
|
|
3562
|
+
"Submit findings individually with record_review_finding and stable IDs; terminal tools aggregate saved findings. Correct rejected calls, stop after a successful terminal. Check execution groups against every member source outcome, including permission, threshold and failure-path differences; each independent AC needs corresponding planned implementation; shared build evidence checks buildability only.",
|
|
3563
|
+
"Check requirement-to-code coverage, authorized files/dependencies and the npm run build result. Behavior correctness, edge cases, regressions and test design/execution belong to frontend-test; their missing evidence is not a blocker here.",
|
|
3669
3564
|
"Your authoritative terminal verdict is exactly one committed typed tool call: approve_review or request_review_changes. Call it once and do not call the other afterwards.",
|
|
3670
3565
|
"approve_review means the implementation passes; it must not carry Critical or Important findings. request_review_changes must carry a typed issueCategory, at least one evidenceRef, and non-empty findings.",
|
|
3671
3566
|
"Do NOT emit an equivalent JSON verdict in the response text: the committed typed terminal fact is the only authority and no branch or gate reads response-text JSON verdicts.",
|
|
3672
3567
|
"Read contracts/frontend-review-context.json from frontend-review-context-shell. It binds a hash-verified canonical contract reference, a field-to-section index, frontend lint assessment when configured, the effective verification trace, and the run-owned actual diff. Read contractRef.capacityDiagnosticPath first: use contractRef.path only when full-contract is recommended; otherwise read only the hash-bound contractRef.sections needed for the changed surface and verification claims. Then read diff.reviewSummaryPath. The full artifacts/diff_patch.patch is retained only as audit evidence: do NOT read it in full. For semantic review, read only the named per-file diff fragment in the summary/index (in part order when needed) and then the current source file when necessary. Do not claim actual diff is missing when those artifacts exist; do not invent a diff from the implementation summary alone. Trace proves command/file/stable-target-id binding only—not semantic correctness.",
|
|
3673
|
-
"
|
|
3568
|
+
"This run requires only a successful npm run build exit. Other test/lint/typecheck evidence is not required. Do not claim absent evidence passed; report independent testing as not-run.",
|
|
3674
3569
|
"Flag .skip/.only, deleted or weakened tests, unauthorized config changes, Mock-only evidence claimed as real integration, and Browser/visual claims (always not-run in this workflow).",
|
|
3675
3570
|
"The contract referenced and hash-bound by frontend-review-context.json is the effective plan materialized by frontend-design-policy-shell. Do not re-open task sources, OpenSpec, AI workspace, design-review, writer summary, or verification node prose. Inspect only the canonical review context, its indexed contract sections, its bound diff, and diff-referenced files when semantic review requires source code.",
|
|
3676
3571
|
"For uiComponentChoices, purpose is the stable coverage key and must match interaction.name or uiState.name. Responsibility is expressed by the matched expectedBehavior plus rationale; you must not reject it merely for matching an interaction or component identifier.",
|
|
3677
|
-
"
|
|
3572
|
+
"Check implementation of source requirements and declared production Mock isolation in the diff. Missing Mock-backed or real API test evidence is a non-blocking frontend-test handoff, not an implementation rejection.",
|
|
3678
3573
|
"Inspect the frontend-verify-shell evidence in the review context directly, including the production/default-real-path static check, and require Mock activation to be off for that check.",
|
|
3679
3574
|
"Distinguish Mock-backed evidence from real API integration evidence and preserve the Real Integration Gap when the backend was not exercised.",
|
|
3680
|
-
"Review implementation
|
|
3575
|
+
"Review requirement implementation coverage and write authorization. Runtime behavior correctness and quality testing are deferred to frontend-test. Read-only: do not modify files.",
|
|
3681
3576
|
].join("\n\n"),
|
|
3682
3577
|
},
|
|
3683
3578
|
{
|
|
@@ -3751,6 +3646,9 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
3751
3646
|
// runner can bound M6 auto-recovery without re-reading the task config.
|
|
3752
3647
|
const frontendMaxContinuations = sources.taskConfig.frontendRecovery?.maxContinuations ?? 1;
|
|
3753
3648
|
spec.frontendRecovery = { maxContinuations: frontendMaxContinuations };
|
|
3649
|
+
// Configurable execution safety quota, independent of model context/output capacity.
|
|
3650
|
+
spec.budget = { schemaVersion: 1, mode: "hard", limits: { maxProviderRequests: sources.taskConfig.frontendRecovery?.maxProviderRequests ?? 1024 } };
|
|
3651
|
+
spec.frontendExecutionPolicy = frontendExecutionPolicySchema.parse(sources.taskConfig.frontendExecutionPolicy ?? {});
|
|
3754
3652
|
applyDefaultReadOnlyRetryPolicy(spec);
|
|
3755
3653
|
stampGeneratedArtifactBindings(spec);
|
|
3756
3654
|
parseDagSpec(spec);
|