@tea-agent/loop-agent 0.39.0-next.2 → 0.39.0-next.20
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 -0
- package/dist/build-stamp.json +2 -2
- package/dist/commands/init-upgrade.js +97 -19
- package/dist/executors/dag-pi-executor.js +42 -4
- package/dist/executors/shell-executor.js +269 -15
- package/dist/shared/operator/capabilities.js +149 -27
- package/dist/task/config-types.js +22 -0
- package/dist/worker/console/chat/mcp-inventory.js +221 -0
- package/dist/worker/console/chat/pi-runtime.js +165 -83
- package/dist/worker/console/chat/repo-walk.js +10 -1
- package/dist/worker/console/chat/routes.js +19 -8
- package/dist/worker/console/chat/semantic-activity.js +17 -5
- package/dist/worker/console/chat/turn-process.js +17 -30
- package/dist/worker/console/harness-pi-model-matrix.js +137 -0
- package/dist/worker/console/operator-actions.js +128 -4
- package/dist/worker/console/operator-user-error.js +19 -0
- package/dist/worker/console/pi-readiness.js +8 -1
- package/dist/worker/console/security.js +20 -1
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-DSvF6RXQ.js → abnfDiagram-N423BO3Z-BmOEx0gA.js} +1 -1
- package/dist/worker/console/static/assets/{arc-DuI4ogtJ.js → arc-BGiVVe8b.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DdBbgD4y.js → architectureDiagram-T3A2C74G-nDdu4rgJ.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-xQC2HELm.js → blockDiagram-VBNYF7ZC-Bb5u0BWf.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DPMSgwIZ.js → c4Diagram-5PPSVZJV-BlhC0j94.js} +1 -1
- package/dist/worker/console/static/assets/channel-Tl-FkUqr.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-WTEKTxin.js → chunk-2GRJ4B5K-Ai8_qQXI.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B6vZ0Pv_.js → chunk-2Q5K7J3B-B9gyCjqX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BrerNAix.js → chunk-5RXB4S5H-Bzbj3zGH.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-D_ch2aaI.js → chunk-5VM5RSS4-BT415PvT.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-VvfacNrq.js → chunk-6Q2QTUOP-D_A5_5QL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-B-uGFIg2.js → chunk-GF5L2VYU-srJkaP3f.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BlysCtod.js → chunk-JWPE2WC7-UYGvEP4l.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-BjAUAfcT.js → chunk-KBJHAD2P-B8luBrrz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BeZnBmb-.js → chunk-RYQCIY6F-DN7wXZSq.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Bbfe3UJG.js → chunk-XXDRQBXY-DXKyMuKS.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BaehtRk4.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BaehtRk4.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BKJQnYVM.js → cose-bilkent-JH36ORCC-dqvoynXj.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-B1wtI3hU.js → cynefin-VYW2F7L2--PcyL34A.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DCF6DBSu.js → cynefinDiagram-MW4NZA55-DvWs_hTY.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BJyNGRlP.js → dagre-VZM6K2ZE-DxeIxbyO.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B7j1-VsZ.js → diagram-7IWD3JNH-DPCG61Of.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BREJ140a.js → diagram-B4RE2ZJO-CmuU50-U.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-CDPHmHGH.js → diagram-LBJQPF4R-B61XLD_v.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BtZLrez1.js → diagram-Q27KOJAE-BB7HTRRY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-mzybu8oU.js → diagram-UB23O5K3-DvkboAIp.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Dk3I2uO6.js → ebnfDiagram-BXEA7PRR-BdJ_y1fL.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-BT97u_tQ.js → erDiagram-JOGREHBK-9bUBZTRi.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CMOtYzui.js → flowDiagram-UKHOOZJN-Dw4L4RBa.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DiNydkuY.js → ganttDiagram-PKOTCBZU-Jr82N_QP.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Cwt6fLkl.js → gitGraphDiagram-DS77QQ5N-DAz9wFLr.js} +1 -1
- package/dist/worker/console/static/assets/index-B7Y-0g3J.css +1 -0
- package/dist/worker/console/static/assets/index-DkCrqaYg.js +325 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-AsGIGKKB.js → infoDiagram-6WML65LV-CBB5Np7y.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BL8ITZh3.js → ishikawaDiagram-WSZJBQD7-D8IOp94y.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-VPKAUX8M.js → journeyDiagram-NVQOT4AX-Dgd3AHGG.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-BL56hfGp.js → kanban-definition-27J2QSJJ-BmYOxLE9.js} +1 -1
- package/dist/worker/console/static/assets/{linear-BmSG3nIZ.js → linear-DfYTEF6J.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-DWGK9kwP.js → mermaid.core-BjuFPRqa.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS--vvKLjo0.js → mindmap-definition-FAOFIHXS-CLyUViGd.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-B41mxb2-.js → pegDiagram-VL7TDLO6-BvX2Di4-.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DTlu77sw.js → pieDiagram-7S7Q4E2Y-BFj0_OLv.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Bk5A7alv.js → quadrantDiagram-CIZ2JOQS-BIUrD_hx.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Csf9jzQy.js → railroadDiagram-AXF67PYL-CHBB48fj.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-CeptoSNx.js → requirementDiagram-LRYGKXZP-sJrYw2Sf.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-A-DLCLer.js → sankeyDiagram-W5VNT64P-BzHH6fPR.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-22VbPdOI.js → sequenceDiagram-SI44F4Z6-7QCnelCt.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DWvAyBC9.js → sizeCapture-X5ZJPWSS-sDYSxn72.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-qICZ75yT.js → stateDiagram-OKZ733FA-XpiUdwzm.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-eEhq2A8Y.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-xi7lcMyp.js → swimlanes-SLNWSIFB-DvqgNPzD.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-la8AC7fo.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Bu6Nl6O2.js → timeline-definition-Z64GVDOM-2TyOYNx0.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BzMz4Bn9.js → vennDiagram-T6HMQDX7-B-nM6wM2.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-CxaJnzc5.js → wardleyDiagram-T6FBY63Y-B86wPdbr.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-5JK-omQK.js → xychartDiagram-ELKLHX3M-Dr1C4AQz.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +39 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +44 -21
- package/dist/worker/console/static-src/operator-chat/mutation-gate.js +45 -0
- package/dist/worker/console/static-src/operator-chat/resource-diagnostics.js +204 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +15 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +17 -4
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +28 -22
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +26 -1
- package/dist/workflows/dag/backend-test-case-coverage-analysis.js +755 -51
- 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 +249 -0
- package/dist/workflows/dag/backend-test-writer-completeness.js +100 -56
- package/dist/workflows/dag/contract-validator-registrations.js +3 -1
- package/dist/workflows/dag/dynamic-runtime/map.js +24 -8
- package/dist/workflows/dag/dynamic-runtime/shared.js +1 -1
- package/dist/workflows/dag/frontend-implementation-contract.js +386 -0
- package/dist/workflows/dag/frontend-plan-render.js +90 -0
- package/dist/workflows/dag/frontend-prewrite-gate.js +243 -8
- package/dist/workflows/dag/init-hybrid.js +753 -104
- package/dist/workflows/dag/node-execution.js +61 -2
- package/dist/workflows/dag/retry-policy.js +4 -0
- package/dist/workflows/dag/types.js +74 -0
- package/docs/templates/backend-test-dag.json +60 -35
- package/docs/templates/frontend-implementation-contract.schema.json +9 -2
- package/harness.json +3 -1
- package/package.json +1 -1
- package/skills/frontend-design-review/references/review-checklist.md +2 -0
- package/skills/frontend-implementation/references/design-spec.md +16 -19
- package/skills/frontend-implementation/references/node-contracts.md +9 -6
- package/dist/worker/console/static/assets/channel-DLVz9TYW.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BeAuGcO9.js +0 -1
- package/dist/worker/console/static/assets/index-DQxiso1w.js +0 -325
- package/dist/worker/console/static/assets/index-_j0Hzo69.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DzKvfHTX.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Cxqr_qM1.js +0 -8
|
@@ -129,6 +129,26 @@ export function buildNodePrompt(spec, task, upstream, options) {
|
|
|
129
129
|
convergenceFeedback: options?.convergenceFeedback,
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
|
+
function frontendStructuredArtifactRetryGuidance(schemaId) {
|
|
133
|
+
if (schemaId === "frontend-implementation-contract-plan-patch-v1") {
|
|
134
|
+
return [
|
|
135
|
+
"Return exactly this artifact and nothing else: one short lead-in line, then exactly one fenced json block containing only the editable RFC 7386 plan patch, immediately followed by exactly one fenced openspec-citations block.",
|
|
136
|
+
"The runtime applies your patch to its protected contract skeleton. Do not emit schemaVersion, sourceBinding, riskLevel, targets.files, or mockApi.productionDefaultOff; do not emit the full contract.",
|
|
137
|
+
"Do not emit Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
if (schemaId === "frontend-implementation-contract-revision-patch-v1") {
|
|
141
|
+
return [
|
|
142
|
+
"Return exactly this artifact and nothing else: one short lead-in line, then exactly one fenced json block containing the RFC 7386 merge-patch delta, immediately followed by exactly one fenced openspec-citations block.",
|
|
143
|
+
"The delta contains only the fields you change; null deletes a key, arrays and scalars replace, and plain objects merge recursively. Do not emit a full contract or a schemaVersion/targets section.",
|
|
144
|
+
"Do not emit Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
|
|
145
|
+
];
|
|
146
|
+
}
|
|
147
|
+
return [
|
|
148
|
+
"Return exactly this artifact and nothing else: one short lead-in line, then exactly one fenced json block conforming to frontend-implementation-contract-v1, immediately followed by exactly one fenced openspec-citations block.",
|
|
149
|
+
"The contract JSON fields are the complete implementation plan. Do not emit a separate plan document, Markdown headings, bullets, plan prose, explanations, raw JSON, or any other fenced block.",
|
|
150
|
+
];
|
|
151
|
+
}
|
|
132
152
|
function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCategory, previousProtocolReason, recoveryTargetPaths, recoveryDiagnostics) {
|
|
133
153
|
if (attemptNumber <= 1)
|
|
134
154
|
return basePrompt;
|
|
@@ -150,11 +170,23 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
|
|
|
150
170
|
"<retry_instruction>",
|
|
151
171
|
"Previous attempt produced an invalid frontend implementation contract:",
|
|
152
172
|
previousProtocolReason,
|
|
153
|
-
|
|
173
|
+
...frontendStructuredArtifactRetryGuidance(task.structuredContractOutput.schemaId),
|
|
154
174
|
"Fix every reported field violation: do not emit null for optional fields, do not misspell field names, and match the required types exactly.",
|
|
155
175
|
"</retry_instruction>",
|
|
156
176
|
].join("\n");
|
|
157
177
|
}
|
|
178
|
+
if (previousFailureCategory === "structured-output-truncated" &&
|
|
179
|
+
task.structuredContractOutput) {
|
|
180
|
+
return [
|
|
181
|
+
basePrompt,
|
|
182
|
+
"",
|
|
183
|
+
"<retry_instruction>",
|
|
184
|
+
"Previous attempt was truncated by the provider (stopReason=length) before the JSON contract was completed.",
|
|
185
|
+
...frontendStructuredArtifactRetryGuidance(task.structuredContractOutput.schemaId),
|
|
186
|
+
"The JSON artifact must be complete; omit evidence excerpts and duplicated upstream context.",
|
|
187
|
+
"</retry_instruction>",
|
|
188
|
+
].join("\n");
|
|
189
|
+
}
|
|
158
190
|
if (previousFailureCategory === "writer-empty-diff") {
|
|
159
191
|
const maxAttempts = task.retryPolicy?.maxAttempts ?? 3;
|
|
160
192
|
// When a completeness progress exists for this writer, fold the concrete
|
|
@@ -220,6 +252,17 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
|
|
|
220
252
|
return basePrompt;
|
|
221
253
|
}
|
|
222
254
|
if (task.outputMode === "structured-required") {
|
|
255
|
+
if (task.structuredContractOutput) {
|
|
256
|
+
return [
|
|
257
|
+
basePrompt,
|
|
258
|
+
"",
|
|
259
|
+
"<retry_instruction>",
|
|
260
|
+
"Previous attempt exceeded the structured output size limit.",
|
|
261
|
+
...frontendStructuredArtifactRetryGuidance(task.structuredContractOutput.schemaId),
|
|
262
|
+
"Keep every required field but make values concise; omit evidence excerpts and duplicated upstream context.",
|
|
263
|
+
"</retry_instruction>",
|
|
264
|
+
].join("\n");
|
|
265
|
+
}
|
|
223
266
|
return [
|
|
224
267
|
basePrompt,
|
|
225
268
|
"",
|
|
@@ -766,12 +809,21 @@ export async function executeDagNode(input) {
|
|
|
766
809
|
runDir,
|
|
767
810
|
text: contractText,
|
|
768
811
|
sourceBinding: spec.sourceBinding,
|
|
812
|
+
nodeId,
|
|
813
|
+
attempt: attemptNumber,
|
|
814
|
+
structuredContractOutput: task.structuredContractOutput,
|
|
769
815
|
});
|
|
770
816
|
if (!contractCheck.ok) {
|
|
817
|
+
// A provider stopReason=length means the response was cut before the
|
|
818
|
+
// JSON contract could complete; separate it from an ordinary bad
|
|
819
|
+
// contract so the retry switches to a JSON-only output strategy.
|
|
820
|
+
const attemptStopReason = result.stopReason;
|
|
771
821
|
result = {
|
|
772
822
|
...result,
|
|
773
823
|
ok: false,
|
|
774
|
-
failureCategory: "
|
|
824
|
+
failureCategory: attemptStopReason === "length"
|
|
825
|
+
? "structured-output-truncated"
|
|
826
|
+
: "invalid-output",
|
|
775
827
|
stderr: [result.stderr, contractCheck.reason]
|
|
776
828
|
.filter(Boolean)
|
|
777
829
|
.join("\n"),
|
|
@@ -779,6 +831,13 @@ export async function executeDagNode(input) {
|
|
|
779
831
|
previousProtocolReason = contractCheck.reason;
|
|
780
832
|
}
|
|
781
833
|
else {
|
|
834
|
+
if (contractCheck.normalizedText) {
|
|
835
|
+
result = {
|
|
836
|
+
...result,
|
|
837
|
+
assistantText: contractCheck.normalizedText,
|
|
838
|
+
stdout: contractCheck.normalizedText,
|
|
839
|
+
};
|
|
840
|
+
}
|
|
782
841
|
previousProtocolReason = undefined;
|
|
783
842
|
}
|
|
784
843
|
}
|
|
@@ -21,6 +21,8 @@ export const STRUCTURED_OUTPUT_RETRY_CATEGORY = "output-too-large";
|
|
|
21
21
|
export const PROTOCOL_INVALID_RETRY_CATEGORY = "protocol-invalid";
|
|
22
22
|
/** Recoverable model artifact/schema formatting failure on read-only structured nodes. */
|
|
23
23
|
export const STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY = "invalid-output";
|
|
24
|
+
/** Provider stopReason=length truncated the response before the JSON contract completed. */
|
|
25
|
+
export const STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY = "structured-output-truncated";
|
|
24
26
|
/** Retry only a proven no-op from an explicitly opt-in bounded Pi writer. */
|
|
25
27
|
export const WRITER_EMPTY_DIFF_RETRY_CATEGORY = "writer-empty-diff";
|
|
26
28
|
/** Retry when a backend-test writer finished but Completeness Gate found missing/broken targets. */
|
|
@@ -36,6 +38,7 @@ export const STRUCTURED_REQUIRED_DAG_RETRY_CATEGORIES = [
|
|
|
36
38
|
...DEFAULT_DAG_RETRY_CATEGORIES,
|
|
37
39
|
STRUCTURED_OUTPUT_RETRY_CATEGORY,
|
|
38
40
|
STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
|
|
41
|
+
STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY,
|
|
39
42
|
];
|
|
40
43
|
/** Categories allowed on nodes that declare a machine-readable outputProtocol. */
|
|
41
44
|
export const PROTOCOL_AWARE_DAG_RETRY_CATEGORIES = [
|
|
@@ -48,6 +51,7 @@ export const ALL_DAG_RETRY_CATEGORIES = [
|
|
|
48
51
|
STRUCTURED_OUTPUT_RETRY_CATEGORY,
|
|
49
52
|
PROTOCOL_INVALID_RETRY_CATEGORY,
|
|
50
53
|
STRUCTURED_ARTIFACT_INVALID_RETRY_CATEGORY,
|
|
54
|
+
STRUCTURED_OUTPUT_TRUNCATED_RETRY_CATEGORY,
|
|
51
55
|
WRITER_EMPTY_DIFF_RETRY_CATEGORY,
|
|
52
56
|
INCOMPLETE_WRITE_SET_RETRY_CATEGORY,
|
|
53
57
|
WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY,
|
|
@@ -193,12 +193,38 @@ export const dagFrontendPrewriteGateSchema = z.object({
|
|
|
193
193
|
requireSourceFreshness: z.literal(true),
|
|
194
194
|
implementationWriteSet: z.array(z.string().min(1)).min(1).optional(),
|
|
195
195
|
openspecCandidatePaths: z.array(openspecCandidatePathSchema).default([]),
|
|
196
|
+
/**
|
|
197
|
+
* Generation-frozen component/theme specification bucket. Derived from
|
|
198
|
+
* `designEvidence.classified.component ∪ theme ∪ rule.components` at DAG
|
|
199
|
+
* generation. When non-empty and the canonical contract has UI-visible
|
|
200
|
+
* work, the prewrite gate requires a non-empty `uiComponentChoices` and
|
|
201
|
+
* cross-checks each `specReference.path` against this set + the effective
|
|
202
|
+
* plan openspec-citations block. Legacy DAGs without this field keep the
|
|
203
|
+
* field-absent semantics (component-choices-missing is not enforced).
|
|
204
|
+
*/
|
|
205
|
+
componentSpecCandidatePaths: z.array(openspecCandidatePathSchema).optional(),
|
|
196
206
|
/**
|
|
197
207
|
* OpenSpec gate policy. Omitted on legacy DAGs: the runtime treats
|
|
198
208
|
* undefined as scan-strict so pre-existing full-read semantics are
|
|
199
209
|
* preserved. Generation always writes it explicitly for new DAGs.
|
|
200
210
|
*/
|
|
201
211
|
openspecPolicy: z.enum(["cited", "scan-strict"]).optional(),
|
|
212
|
+
/**
|
|
213
|
+
* When true, the effective plan node (planFromNodeId when it is selected
|
|
214
|
+
* over the fallback) emits an RFC 7386 merge-patch delta instead of a full
|
|
215
|
+
* contract. The gate applies it on the original contract node
|
|
216
|
+
* (planFallbackFromNodeIds[0]) before analysis/materialization. Legacy DAGs
|
|
217
|
+
* without this field keep full-contract semantics.
|
|
218
|
+
*/
|
|
219
|
+
revisionPatch: z.boolean().optional(),
|
|
220
|
+
/**
|
|
221
|
+
* Deterministically rendered plan.md artifact name (same outputDir as the
|
|
222
|
+
* contract). Defaults to frontend-plan.md at runtime.
|
|
223
|
+
*/
|
|
224
|
+
planMdArtifactName: z
|
|
225
|
+
.string()
|
|
226
|
+
.regex(/^[a-z0-9][a-z0-9._-]*\.md$/)
|
|
227
|
+
.optional(),
|
|
202
228
|
/**
|
|
203
229
|
* Generation-frozen candidate source metadata (diagnostic). cited mode
|
|
204
230
|
* candidates are declared ∪ taskSourceCited; scan-strict candidates are
|
|
@@ -397,6 +423,8 @@ export const dagBackendTestPipelineSchema = z.enum([
|
|
|
397
423
|
"markdown-scenario-param",
|
|
398
424
|
"markdown-execute-html",
|
|
399
425
|
"markdown-manifest",
|
|
426
|
+
"markdown-report",
|
|
427
|
+
"ingest-backend-test-gap",
|
|
400
428
|
]);
|
|
401
429
|
export const dagFrontendBrowserToolPreflightSchema = z.object({}).strict();
|
|
402
430
|
export const dagFrontendTestEvidenceValidationSchema = z.object({}).strict();
|
|
@@ -574,6 +602,13 @@ export const dagDynamicExpansionSchema = z.object({
|
|
|
574
602
|
maxTotalTokens: z.number().int().positive().optional(),
|
|
575
603
|
})
|
|
576
604
|
.optional(),
|
|
605
|
+
/**
|
|
606
|
+
* When true, any child blocked by the aggregate token budget fails the map
|
|
607
|
+
* barrier instead of being retained as a case-level blocked outcome.
|
|
608
|
+
* Backend-test enables this because partial Markdown/pytest module sets are
|
|
609
|
+
* invalid generation assets; frontend-test keeps the default false.
|
|
610
|
+
*/
|
|
611
|
+
failOnTokenBudgetExhaustion: z.boolean().optional(),
|
|
577
612
|
/**
|
|
578
613
|
* When true, map child ERROR/auth/timeout is recorded as case-level
|
|
579
614
|
* failed/blocked evidence and the map barrier still succeeds (frontend-test).
|
|
@@ -678,6 +713,8 @@ export const dagConvergenceSpecSchema = z
|
|
|
678
713
|
*/
|
|
679
714
|
export const structuredContractOutputSchemaIds = [
|
|
680
715
|
"frontend-implementation-contract-v1",
|
|
716
|
+
"frontend-implementation-contract-plan-patch-v1",
|
|
717
|
+
"frontend-implementation-contract-revision-patch-v1",
|
|
681
718
|
];
|
|
682
719
|
export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/, "task id must be kebab-case"),
|
|
683
720
|
depends_on: z.array(z.string()).default([]),
|
|
@@ -739,8 +776,25 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
|
|
|
739
776
|
.object({
|
|
740
777
|
schemaId: z.enum(structuredContractOutputSchemaIds),
|
|
741
778
|
retryOnInvalid: z.boolean().default(true),
|
|
779
|
+
/**
|
|
780
|
+
* Optional deterministic base object for patch-producing structured
|
|
781
|
+
* nodes. The frontend plan patch validator applies the model delta to
|
|
782
|
+
* this run-owned skeleton before strict contract validation.
|
|
783
|
+
*/
|
|
784
|
+
skeleton: z.record(z.string(), z.unknown()).optional(),
|
|
742
785
|
})
|
|
743
786
|
.strict()
|
|
787
|
+
.superRefine((value, ctx) => {
|
|
788
|
+
if (value.schemaId ===
|
|
789
|
+
"frontend-implementation-contract-plan-patch-v1" &&
|
|
790
|
+
!value.skeleton) {
|
|
791
|
+
ctx.addIssue({
|
|
792
|
+
code: "custom",
|
|
793
|
+
message: "frontend plan patch output requires a runtime skeleton",
|
|
794
|
+
path: ["skeleton"],
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
})
|
|
744
798
|
.optional(),
|
|
745
799
|
/**
|
|
746
800
|
* Fail-closed outcome/diff consistency contract for bounded Pi writers.
|
|
@@ -830,6 +884,26 @@ export const dagSpecSchema = z
|
|
|
830
884
|
sourceBinding: dagSourceBindingSchema.optional(),
|
|
831
885
|
/** v4 managed Task Contract binding; only valid on version 4. */
|
|
832
886
|
taskContractBinding: dagTaskContractBindingSchema.optional(),
|
|
887
|
+
/** Frozen backend-test artifact layout (plan A); absent = historical default testcase/ layout. */
|
|
888
|
+
backendTestLayout: z
|
|
889
|
+
.object({
|
|
890
|
+
testRoot: z.string(),
|
|
891
|
+
markdownRel: z.string(),
|
|
892
|
+
scriptRel: z.string(),
|
|
893
|
+
markdownDir: z.string(),
|
|
894
|
+
scriptDir: z.string(),
|
|
895
|
+
readmePath: z.string(),
|
|
896
|
+
isDefault: z.boolean(),
|
|
897
|
+
})
|
|
898
|
+
.optional(),
|
|
899
|
+
/** Bound user shared-setup document (plan B); absent = no shared setup references expected. */
|
|
900
|
+
backendTestSharedSetup: z
|
|
901
|
+
.object({
|
|
902
|
+
path: z.string(),
|
|
903
|
+
readPath: z.string(),
|
|
904
|
+
sha256: z.string(),
|
|
905
|
+
})
|
|
906
|
+
.optional(),
|
|
833
907
|
outputLanguage: dagOutputLanguageSchema.optional(),
|
|
834
908
|
objective: z.string().optional(),
|
|
835
909
|
successCriteria: z.array(z.string()).optional(),
|