@tea-agent/loop-agent 0.39.0-next.17 → 0.39.0-next.19

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/build-stamp.json +2 -2
  3. package/dist/commands/init.js +2 -14
  4. package/dist/governance/manifest-types.js +0 -2
  5. package/dist/worker/console/harness-pi-model-matrix.js +2 -11
  6. package/dist/worker/console/pi-readiness.js +1 -0
  7. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-B_oUmMOh.js → abnfDiagram-N423BO3Z-DwiNHTdC.js} +1 -1
  8. package/dist/worker/console/static/assets/{arc-ftlOud1c.js → arc-CqaEjHku.js} +1 -1
  9. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-DjW1pNpm.js → architectureDiagram-T3A2C74G-BoztYl-Q.js} +1 -1
  10. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BIKIhuQ2.js → blockDiagram-VBNYF7ZC-BR6kEDU-.js} +1 -1
  11. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-gQPyScnQ.js → c4Diagram-5PPSVZJV-x8RjYRwv.js} +1 -1
  12. package/dist/worker/console/static/assets/channel-1N7RyL5T.js +1 -0
  13. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-DbYJpklA.js → chunk-2GRJ4B5K-_HKgW9Gv.js} +1 -1
  14. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-B2EimXhx.js → chunk-2Q5K7J3B-BF0MICQ6.js} +1 -1
  15. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CRl4qEu8.js → chunk-5RXB4S5H-CwMHVJ8a.js} +1 -1
  16. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-aCdt3uIm.js → chunk-5VM5RSS4-BsAqLAeh.js} +1 -1
  17. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-upQU37XN.js → chunk-6Q2QTUOP-IdBfnQF8.js} +1 -1
  18. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CTNubrNg.js → chunk-GF5L2VYU-CmnTA6PM.js} +1 -1
  19. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-CzhqBe80.js → chunk-JWPE2WC7-DDC1y-tm.js} +1 -1
  20. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-51xTGTO2.js → chunk-KBJHAD2P-Df-jjFHX.js} +1 -1
  21. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-CCYvtwPn.js → chunk-RYQCIY6F-DXHlHej7.js} +1 -1
  22. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-Ct6GraPo.js → chunk-XXDRQBXY-BJUMTtaD.js} +1 -1
  23. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BEne8l1a.js +1 -0
  24. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BEne8l1a.js +1 -0
  25. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-DB-ntLzq.js → cose-bilkent-JH36ORCC-DvfSBnQA.js} +1 -1
  26. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-BHujm5FN.js → cynefin-VYW2F7L2-BXe-YrAg.js} +1 -1
  27. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Cx5wZ3Lb.js → cynefinDiagram-MW4NZA55-C25KAXmE.js} +1 -1
  28. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CZspWvZB.js → dagre-VZM6K2ZE-DvTVWxGT.js} +1 -1
  29. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-B8eB7kJZ.js → diagram-7IWD3JNH-e_4e-pmQ.js} +1 -1
  30. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-IPXv9g8R.js → diagram-B4RE2ZJO-vG09145o.js} +1 -1
  31. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BGnjGtYW.js → diagram-LBJQPF4R-DlqSYoTs.js} +1 -1
  32. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-hEQoyS1K.js → diagram-Q27KOJAE-BI-4PyfE.js} +1 -1
  33. package/dist/worker/console/static/assets/{diagram-UB23O5K3-C5mG8Xwz.js → diagram-UB23O5K3-C9dLNlyM.js} +1 -1
  34. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-D3xfcbnF.js → ebnfDiagram-BXEA7PRR-CuqayYwb.js} +1 -1
  35. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CcLL1SM0.js → erDiagram-JOGREHBK-Cjt_WoXR.js} +1 -1
  36. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CSuAfPiR.js → flowDiagram-UKHOOZJN-DI5LAkdd.js} +1 -1
  37. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DLqDAAke.js → ganttDiagram-PKOTCBZU-BNulKWJe.js} +1 -1
  38. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-DAZsLAah.js → gitGraphDiagram-DS77QQ5N-BjWpiSad.js} +1 -1
  39. package/dist/worker/console/static/assets/{index-BTNvk20w.js → index-DAAlqKAz.js} +57 -57
  40. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-DXSlZAx8.js → infoDiagram-6WML65LV-C2z-HyGf.js} +1 -1
  41. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-DhBkRCya.js → ishikawaDiagram-WSZJBQD7-BqiVeYz0.js} +1 -1
  42. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-C-RZUWu7.js → journeyDiagram-NVQOT4AX-jEOZ2ROo.js} +1 -1
  43. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-B2kKlMxE.js → kanban-definition-27J2QSJJ-CArokfSN.js} +1 -1
  44. package/dist/worker/console/static/assets/{linear-DMke1BBn.js → linear-Bq9c9mgI.js} +1 -1
  45. package/dist/worker/console/static/assets/{mermaid.core-DeA6yB6l.js → mermaid.core-CD1Q-FZj.js} +5 -5
  46. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BZ6xfhel.js → mindmap-definition-FAOFIHXS-C3_TRMVq.js} +1 -1
  47. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DTAzpGRC.js → pegDiagram-VL7TDLO6-d6-3C5eP.js} +1 -1
  48. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BX_T9L06.js → pieDiagram-7S7Q4E2Y-rBMZEugn.js} +1 -1
  49. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Cj4UGUTS.js → quadrantDiagram-CIZ2JOQS-B1oYGuOW.js} +1 -1
  50. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-Hcvjh9D4.js → railroadDiagram-AXF67PYL-CduEVeL8.js} +1 -1
  51. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-PEuuqrN2.js → requirementDiagram-LRYGKXZP-BX1CnUrJ.js} +1 -1
  52. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Mb_IOENk.js → sankeyDiagram-W5VNT64P-Cf5q1crB.js} +1 -1
  53. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DGbthBV4.js → sequenceDiagram-SI44F4Z6-D84Udu8j.js} +1 -1
  54. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-Ctp2tKYQ.js → sizeCapture-X5ZJPWSS-BGbReoBj.js} +1 -1
  55. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-CHTwWXQq.js → stateDiagram-OKZ733FA-CW1DYgTf.js} +1 -1
  56. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BPT5G0Dj.js +1 -0
  57. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-MfdGy8FB.js → swimlanes-SLNWSIFB-B0Ps2tSZ.js} +2 -2
  58. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BGMpptSy.js +8 -0
  59. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-oVHobrn4.js → timeline-definition-Z64GVDOM-CAvdUBWu.js} +1 -1
  60. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CJ-FRNVZ.js → vennDiagram-T6HMQDX7-Cc5Qi527.js} +1 -1
  61. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-HTiTkCdT.js → wardleyDiagram-T6FBY63Y-m_CGFXYN.js} +1 -1
  62. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DiuS-VLK.js → xychartDiagram-ELKLHX3M-DNfoFR4W.js} +1 -1
  63. package/dist/worker/console/static/index.html +1 -1
  64. package/dist/worker/console/static-src/app/console-types.js +0 -12
  65. package/dist/workflows/dag/contract-validator-registrations.js +2 -1
  66. package/dist/workflows/dag/dynamic-runtime/shared.js +1 -1
  67. package/dist/workflows/dag/frontend-implementation-contract.js +236 -8
  68. package/dist/workflows/dag/frontend-prewrite-gate.js +89 -32
  69. package/dist/workflows/dag/init-hybrid.js +20 -30
  70. package/dist/workflows/dag/node-execution.js +45 -18
  71. package/dist/workflows/dag/types.js +18 -0
  72. package/docs/templates/harness.schema.json +0 -8
  73. package/harness.json +1 -8
  74. package/package.json +1 -1
  75. package/skills/frontend-implementation/references/node-contracts.md +2 -2
  76. package/dist/worker/console/static/assets/channel-Kf0dWmvg.js +0 -1
  77. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DvMFMDx0.js +0 -1
  78. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DvMFMDx0.js +0 -1
  79. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-GwsFii7W.js +0 -1
  80. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-D603UkUt.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;
@@ -144,27 +164,14 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
144
164
  if (previousFailureCategory === "invalid-output" &&
145
165
  task.structuredContractOutput &&
146
166
  previousProtocolReason) {
147
- // Revision nodes emit an RFC 7386 merge-patch delta (no schemaVersion /
148
- // targets), so the retry instruction must not push them toward a full
149
- // contract rewrite; plan nodes keep the strict v1 guidance.
150
- const guidance = task.structuredContractOutput.schemaId ===
151
- "frontend-implementation-contract-revision-patch-v1"
152
- ? [
153
- "Return exactly one fenced json object containing the RFC 7386 merge-patch delta against the original contract (null deletes a key; arrays and scalars replace; plain objects merge recursively) + exactly one openspec-citations block.",
154
- "The delta contains only the fields you change; do not emit a full contract or a schemaVersion/targets section.",
155
- ]
156
- : [
157
- "Return exactly one fenced json block conforming to the frontend-implementation-contract-v1 schema.",
158
- "Fix every reported field violation: do not emit null for optional fields, do not misspell field names, and match the required types exactly.",
159
- "The Markdown explanation may be omitted; prioritize a complete contract.",
160
- ];
161
167
  return [
162
168
  basePrompt,
163
169
  "",
164
170
  "<retry_instruction>",
165
171
  "Previous attempt produced an invalid frontend implementation contract:",
166
172
  previousProtocolReason,
167
- ...guidance,
173
+ ...frontendStructuredArtifactRetryGuidance(task.structuredContractOutput.schemaId),
174
+ "Fix every reported field violation: do not emit null for optional fields, do not misspell field names, and match the required types exactly.",
168
175
  "</retry_instruction>",
169
176
  ].join("\n");
170
177
  }
@@ -175,9 +182,8 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
175
182
  "",
176
183
  "<retry_instruction>",
177
184
  "Previous attempt was truncated by the provider (stopReason=length) before the JSON contract was completed.",
178
- "This attempt: output ONLY the single fenced json contract block, immediately followed by exactly one openspec-citations block.",
179
- "Do not emit any Markdown explanation, evidence excerpts, or duplicated upstream context.",
180
- "The contract JSON must be complete; the trailing Markdown explanation may be omitted entirely.",
185
+ ...frontendStructuredArtifactRetryGuidance(task.structuredContractOutput.schemaId),
186
+ "The JSON artifact must be complete; omit evidence excerpts and duplicated upstream context.",
181
187
  "</retry_instruction>",
182
188
  ].join("\n");
183
189
  }
@@ -246,6 +252,17 @@ function buildAttemptPrompt(task, basePrompt, attemptNumber, previousFailureCate
246
252
  return basePrompt;
247
253
  }
248
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
+ }
249
266
  return [
250
267
  basePrompt,
251
268
  "",
@@ -792,6 +809,9 @@ export async function executeDagNode(input) {
792
809
  runDir,
793
810
  text: contractText,
794
811
  sourceBinding: spec.sourceBinding,
812
+ nodeId,
813
+ attempt: attemptNumber,
814
+ structuredContractOutput: task.structuredContractOutput,
795
815
  });
796
816
  if (!contractCheck.ok) {
797
817
  // A provider stopReason=length means the response was cut before the
@@ -811,6 +831,13 @@ export async function executeDagNode(input) {
811
831
  previousProtocolReason = contractCheck.reason;
812
832
  }
813
833
  else {
834
+ if (contractCheck.normalizedText) {
835
+ result = {
836
+ ...result,
837
+ assistantText: contractCheck.normalizedText,
838
+ stdout: contractCheck.normalizedText,
839
+ };
840
+ }
814
841
  previousProtocolReason = undefined;
815
842
  }
816
843
  }
@@ -713,6 +713,7 @@ export const dagConvergenceSpecSchema = z
713
713
  */
714
714
  export const structuredContractOutputSchemaIds = [
715
715
  "frontend-implementation-contract-v1",
716
+ "frontend-implementation-contract-plan-patch-v1",
716
717
  "frontend-implementation-contract-revision-patch-v1",
717
718
  ];
718
719
  export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/, "task id must be kebab-case"),
@@ -775,8 +776,25 @@ export const dagTaskSchema = z.object({ id: z.string().regex(/^[a-z][a-z0-9-]*$/
775
776
  .object({
776
777
  schemaId: z.enum(structuredContractOutputSchemaIds),
777
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(),
778
785
  })
779
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
+ })
780
798
  .optional(),
781
799
  /**
782
800
  * Fail-closed outcome/diff consistency contract for bounded Pi writers.
@@ -344,14 +344,6 @@
344
344
  "HIGH": {
345
345
  "$ref": "#/$defs/executorTierModel",
346
346
  "description": "HIGH 复杂度 DAG task 的模型覆盖值,优先级高于 defaultModel。可为模型字符串,或 { model, thinking? } 对象。"
347
- },
348
- "modelOptions": {
349
- "type": "array",
350
- "items": {
351
- "type": "string",
352
- "minLength": 1
353
- },
354
- "description": "Console「模型与认证」页模型矩阵下拉的可选模型列表(provider/model 或裸 model id)。仅供下拉数据使用,不参与 DAG 模型路由。"
355
347
  }
356
348
  }
357
349
  }
package/harness.json CHANGED
@@ -84,14 +84,7 @@
84
84
  "description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
85
85
  "LOW": "wizard-local/minimax-m3",
86
86
  "MED": "wizard-local/grok-4.6",
87
- "HIGH": "wizard-local/gpt-5.6-sol",
88
- "modelOptions": [
89
- "wizard-local/minimax-m3",
90
- "wizard-local/grok-4.6",
91
- "wizard-local/gpt-5.6-sol",
92
- "deepseek/deepseek-v4-pro",
93
- "deepseek/deepseek-v4-flash"
94
- ]
87
+ "HIGH": "wizard-local/gpt-5.6-sol"
95
88
  }
96
89
  }
97
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.39.0-next.17",
3
+ "version": "0.39.0-next.19",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -6,14 +6,14 @@ Pre-write nodes are read-only. Preserve IDs, labels, commands, language, require
6
6
 
7
7
  - **`frontend-contract-pi`**: `Scope`, `Non-goals`, `Acceptance Criteria`, `UI States`, `Target Runtime Environment`, `Risks`, `Verification Expectations`; no guessed requirements.
8
8
  - **`frontend-scout-pi`**: routes, components, tokens, data/API/Mock, scripts, tests, assets; fact vs inference vs gap. Search+read `openspec/schemas/`, `openspec/project-specs/`, `ai_workspace/` first. Output stack, styling, conventions, state/data, test entry points, reuse, risks.
9
- - **`frontend-plan-pi` + conditional design loop**: AC → observable `expectedOutcome`; interactions → `trigger`+`expectedBehavior`; steps, in-bound files, UI states, reuse, deps, Mock/API strategy, activation/rollback, frozen verify entrypoints, real-integration gap. **JSON-only**: one-line lead-in + **exactly one** fenced `json` block (`frontend-implementation-contract-v1`) + one `openspec-citations` block. No plan prose; plan.md is rendered by the gate. `frontend-contract-json-pi`/`frontend-contract-json-validate-shell` don't exist; IDs+paths ≠ behavior semantics. Use `uiStates: []` for logic-only changes; don't invent UI states. Applicable states need behavior/implementation/verification; non-applicable need reasons. Non-`not-needed` needs frozen Mock verify commands (`frontendMock.verifyCommands`/`package.json` mock script/capability seed); `auto` with absent/ambiguous capability or no command → `not-needed`; `required` without a command → generation-time blocked. Initial pass = original plan; only `request-revision` runs revision+final review; small-risk = one review.
9
+ - **`frontend-plan-pi` + conditional design loop**: AC → observable `expectedOutcome`; interactions → `trigger`+`expectedBehavior`; include steps, in-bound files, UI states, reuse, deps, Mock/API, frozen verify entrypoints and integration gaps. DAG freezes a protected skeleton (`schemaVersion`, `sourceBinding`, `riskLevel`, `targets.files`, `mockApi.productionDefaultOff`). Model returns a **JSON-only** editable RFC 7386 patch (`frontend-implementation-contract-plan-patch-v1`) plus one `openspec-citations` block. Runtime compiles canonical `frontend-implementation-contract-v1` and archives raw/extracted/normalized/validation candidates; unresolved optional symbols are dropped and audited. No plan prose; gate renders plan.md. IDs+paths ≠ behavior semantics. Applicable UI states need behavior/implementation/verification; non-applicable states need reasons. Active Mock needs frozen commands; `auto` without confirmed capability/command → `not-needed`; `required` without command → generation-time blocked. Only `request-revision` runs revision+final review; small-risk gets one review.
10
10
  - `uiComponentChoices[]` (optional): `{purpose, component, decision, specReference, rationale}`; `specified` needs `specReference{path,section,line}`; `new` needs null ref+rationale.
11
11
  - **`frontend-prewrite-gate-shell`**: sole write authorization. Resolve effective plan (revised if revision ran, else original) + review; require exact pass; retain every REQ/BR/AC id; enforce Mock policy; validate schema/source binding+writeSet containment; materialize `contracts/frontend-implementation-contract.json` from the **single** fenced contract block (multiple candidates fail closed `invalid-output`). Fallback only when conditional primary absent; malformed primary fails closed. Generation-time blocked Mock yields one blocking shell node, no writer.
12
12
  - `verificationTarget.commandLabel` must be a **frozen command label** from `verifyEvidence.commandLabels`; others fail closed (`invalid-output`). Empty frozen set (no `run.json`) skips check.
13
13
  - `mockApi.strategy !== "not-needed"` fails closed when `mockCommandLabels` empty (`no authorized Mock verification commands`).
14
14
  - OpenSpec policy: `task.json.frontendOpenspec.policy` (default `cited`); candidates = `requiredReadPaths` ∪ task-source citations; effective plan must append one fenced `openspec-citations` block (one JSON `{"path","section","line"}` per line). Candidates non-empty but block missing/unparseable → `openspec-citation-block-unparseable`; candidate not cited → `openspec-not-cited`; cited path without read event → `openspec-citation-not-read` (anti-fabrication). Empty candidates skip enforcement. `scan-strict` keeps full-read semantics (`openspec-not-read`); both modes keep `candidate-missing-drift`.
15
15
  - Component conformance: missing `uiComponentChoices` (frozen bucket non-empty + UI-visible work) → `component-choices-missing`; bad/uncited `specReference.path` → `component-spec-reference-invalid` / `component-spec-not-cited`.
16
- - revisionPatch mode: revision output is an RFC 7386 merge-patch delta applied on the original contract node (`planFallbackFromNodeIds[0]`); legacy DAGs keep full-contract semantics. Size guard: canonical serialization >64KB → `retryable-invalid` + `contract-too-large`.
16
+ - revisionPatch mode: revision output is an RFC 7386 merge-patch delta applied on the original canonical contract node (`planFallbackFromNodeIds[0]`); protected skeleton paths remain immutable. Legacy DAGs keep full-contract semantics. Size guard: canonical serialization >64KB → `retryable-invalid` + `contract-too-large`.
17
17
  - **`frontend-implement-pi`**: sole regular exclusive writer; uses `frontend-bounded-implement` (not this skill). Stay in `writeSet`; real requests default-on. Atomic handler/intercept/adapter with tests. Stop on forbidden paths/guesses. First line `IMPLEMENTATION_OUTCOME: changed|already-satisfied|blocked`; runtime checks against attributed diff. Optional mock-verify when frozen; static+behavior always; behavior must prove page consumption. `not-needed` keeps real integration pending unless real backend has fresh evidence.
18
18
 
19
19
  ## Contract / trace / stages (M1–M2)
@@ -1 +0,0 @@
1
- import{ag as o,ah as n}from"./mermaid.core-DeA6yB6l.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-CTNubrNg.js";import{_ as i}from"./mermaid.core-DeA6yB6l.js";import"./chunk-5VM5RSS4-aCdt3uIm.js";import"./chunk-XXDRQBXY-Ct6GraPo.js";import"./chunk-KBJHAD2P-51xTGTO2.js";import"./chunk-2GRJ4B5K-DbYJpklA.js";import"./index-BTNvk20w.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-CTNubrNg.js";import{_ as i}from"./mermaid.core-DeA6yB6l.js";import"./chunk-5VM5RSS4-aCdt3uIm.js";import"./chunk-XXDRQBXY-Ct6GraPo.js";import"./chunk-KBJHAD2P-51xTGTO2.js";import"./chunk-2GRJ4B5K-DbYJpklA.js";import"./index-BTNvk20w.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as r,b as e,a,S as s}from"./chunk-5RXB4S5H-CRl4qEu8.js";import{_ as i}from"./mermaid.core-DeA6yB6l.js";import"./chunk-XXDRQBXY-Ct6GraPo.js";import"./chunk-KBJHAD2P-51xTGTO2.js";import"./chunk-2GRJ4B5K-DbYJpklA.js";import"./index-BTNvk20w.js";var u={parser:a,get db(){return new s(2)},renderer:e,styles:r,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1,8 +0,0 @@
1
- import{c as r,s as e}from"./flowDiagram-UKHOOZJN-CSuAfPiR.js";import{_ as a}from"./mermaid.core-DeA6yB6l.js";import"./chunk-5VM5RSS4-aCdt3uIm.js";import"./chunk-XXDRQBXY-Ct6GraPo.js";import"./chunk-KBJHAD2P-51xTGTO2.js";import"./chunk-2GRJ4B5K-DbYJpklA.js";import"./channel-Kf0dWmvg.js";import"./index-BTNvk20w.js";var o=a(t=>`${e(t)}
2
- .swimlane.cluster rect {
3
- stroke: ${t.clusterBorder} !important;
4
- }
5
- [data-look="neo"].cluster rect {
6
- filter: none;
7
- }
8
- `,"getStyles"),s=o,n=r({defaultLayout:"swimlane",styles:s});export{n as diagram};