@tea-agent/loop-agent 0.41.1-beta.0 → 0.41.1

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 (206) hide show
  1. package/CHANGELOG.md +47 -267
  2. package/dist/application/dag/generate-task-dag.js +19 -75
  3. package/dist/application/task-lifecycle/advance.js +5 -24
  4. package/dist/application/task-lifecycle/observe.js +17 -171
  5. package/dist/application/task-lifecycle/plan-transitions.js +7 -42
  6. package/dist/application/task-lifecycle/recommendations.js +2 -13
  7. package/dist/build-stamp.json +3 -3
  8. package/dist/cli/command-definitions.js +0 -7
  9. package/dist/cli/program.js +0 -5
  10. package/dist/commands/client-recovery.js +0 -3
  11. package/dist/commands/init.js +1 -27
  12. package/dist/commands/task-advance.js +0 -19
  13. package/dist/executors/dag-pi-executor.js +231 -3784
  14. package/dist/executors/pi-executor.js +4 -15
  15. package/dist/executors/shell-executor.js +217 -945
  16. package/dist/executors/shell-write-guard.js +0 -7
  17. package/dist/shared/dag-failure-category.js +0 -12
  18. package/dist/shared/openspec-spec.js +4 -70
  19. package/dist/shared/operator/capabilities.js +0 -7
  20. package/dist/task/config-types.js +7 -34
  21. package/dist/task/contract/adopt.js +0 -4
  22. package/dist/task/contract/import-revision.js +0 -4
  23. package/dist/task/contract/project.js +0 -3
  24. package/dist/task/contract/schema.js +1 -2
  25. package/dist/task/frontend-project-capability.js +20 -203
  26. package/dist/task/runtime.js +2 -5
  27. package/dist/task/source-prepare/build-draft.js +3 -3
  28. package/dist/task/source-prepare/fragment-inventory.js +9 -15
  29. package/dist/task/source-prepare/prepare.js +1 -89
  30. package/dist/task/source-prepare/semantic-intake.js +2 -6
  31. package/dist/task/source-references.js +1 -22
  32. package/dist/worker/console/chat/chat-ui-policy.js +4 -2
  33. package/dist/worker/console/chat/pi-runtime.js +176 -9
  34. package/dist/worker/console/chat/repo-browser.js +10 -3
  35. package/dist/worker/console/chat/routes.js +42 -22
  36. package/dist/worker/console/chat/semantic-activity.js +12 -11
  37. package/dist/worker/console/chat/session-stats.js +96 -0
  38. package/dist/worker/console/chat/session-store.js +117 -70
  39. package/dist/worker/console/chat/shortcuts.js +1 -1
  40. package/dist/worker/console/chat/turn-process.js +139 -60
  41. package/dist/worker/console/index.js +0 -3
  42. package/dist/worker/console/operation-store.js +6 -226
  43. package/dist/worker/console/operator-actions.js +7 -169
  44. package/dist/worker/console/pi-plugins.js +3 -1
  45. package/dist/worker/console/server.js +0 -3
  46. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bho4we4c.js → abnfDiagram-N423BO3Z-D7oU983t.js} +1 -1
  47. package/dist/worker/console/static/assets/{arc-TBDkTeK0.js → arc-BrKSRdFS.js} +1 -1
  48. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BF_fZrn2.js → architectureDiagram-T3A2C74G-CiXV7L56.js} +1 -1
  49. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CCnPgUe2.js → blockDiagram-VBNYF7ZC-D_Hs_gIG.js} +1 -1
  50. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BCYZJLAT.js → c4Diagram-5PPSVZJV-DbM-Lqqh.js} +1 -1
  51. package/dist/worker/console/static/assets/channel-D1xajGpe.js +1 -0
  52. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D8K6adhU.js → chunk-2GRJ4B5K-D1M8uqJw.js} +1 -1
  53. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DkT1Q78b.js → chunk-2Q5K7J3B-4D3RFHT6.js} +1 -1
  54. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DuhvpIr7.js → chunk-5RXB4S5H-CdwpY_n9.js} +1 -1
  55. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BnK6dC49.js → chunk-5VM5RSS4-BLeLZ9PG.js} +1 -1
  56. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DPz__z7r.js → chunk-6Q2QTUOP-CeRNEMvc.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-0kkppM2j.js → chunk-GF5L2VYU-CjkHP8Vy.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BB41iK5t.js → chunk-JWPE2WC7-B54ZUQY-.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CiVrxKHU.js → chunk-KBJHAD2P-4bKaMVmx.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-C2h9Xje1.js → chunk-RYQCIY6F-Cyjfznu_.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-3iOSHdbM.js → chunk-XXDRQBXY-CDN-zGFV.js} +1 -1
  62. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BmuGTfRr.js +1 -0
  63. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BmuGTfRr.js +1 -0
  64. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BN3A7tkk.js → cose-bilkent-JH36ORCC-HxJmz411.js} +1 -1
  65. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CTuBy0Or.js → cynefin-VYW2F7L2-DtSt5K2w.js} +1 -1
  66. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-wb6tUlMN.js → cynefinDiagram-MW4NZA55-VtkSpRmG.js} +1 -1
  67. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-GP1Ivx8B.js → dagre-VZM6K2ZE-Bj4DT4du.js} +1 -1
  68. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-ejrcK6L0.js → diagram-7IWD3JNH-Bpuk6BmP.js} +1 -1
  69. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-YFkCCvUU.js → diagram-B4RE2ZJO-BHYGv_yO.js} +1 -1
  70. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-B4rrvIaL.js → diagram-LBJQPF4R-DEx3WwnT.js} +1 -1
  71. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C-YIZcUf.js → diagram-Q27KOJAE-Cj0dS5e8.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPF5wcL1.js → diagram-UB23O5K3-B97h8l21.js} +1 -1
  73. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CU5SzXjO.js → ebnfDiagram-BXEA7PRR-DMSFAhBd.js} +1 -1
  74. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CpL414DE.js → erDiagram-JOGREHBK-DhVOCbt6.js} +1 -1
  75. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-MrhLzNau.js → flowDiagram-UKHOOZJN-GlakITWL.js} +1 -1
  76. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Bg4qFuUo.js → ganttDiagram-PKOTCBZU-VxPpu9eQ.js} +1 -1
  77. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-ColxSXLR.js → gitGraphDiagram-DS77QQ5N-Bs_e5DRT.js} +1 -1
  78. package/dist/worker/console/static/assets/index-BLzcAykx.js +451 -0
  79. package/dist/worker/console/static/assets/index-Cs9JUSPs.css +1 -0
  80. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czvtm6gc.js → infoDiagram-6WML65LV-BXYuU4Uw.js} +1 -1
  81. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B7Xp8HyJ.js → ishikawaDiagram-WSZJBQD7-C34erCbU.js} +1 -1
  82. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DWYZcvph.js → journeyDiagram-NVQOT4AX-DZCAiOU3.js} +1 -1
  83. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-KTLZRUjx.js → kanban-definition-27J2QSJJ-C9gaTdUm.js} +1 -1
  84. package/dist/worker/console/static/assets/{linear-_Exn7bfl.js → linear-CvI0Z17U.js} +1 -1
  85. package/dist/worker/console/static/assets/{mermaid.core-Cxg8kX8V.js → mermaid.core-DMMSIx7j.js} +5 -5
  86. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-oKrlo2Bt.js → mindmap-definition-FAOFIHXS-BKKP0EO6.js} +1 -1
  87. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-XAeteiNd.js → pegDiagram-VL7TDLO6-C3LiFbl5.js} +1 -1
  88. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BTf1K-lp.js → pieDiagram-7S7Q4E2Y-Bb3Om2Dz.js} +1 -1
  89. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-C0IlY0Jf.js → quadrantDiagram-CIZ2JOQS-DNthMjzc.js} +1 -1
  90. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BVbKtZhW.js → railroadDiagram-AXF67PYL-miFsr4Tv.js} +1 -1
  91. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C5e4JFcr.js → requirementDiagram-LRYGKXZP-yXUncmn6.js} +1 -1
  92. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cz30hc29.js → sankeyDiagram-W5VNT64P-DLeWKLak.js} +1 -1
  93. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DS33n6d0.js → sequenceDiagram-SI44F4Z6-CI3he1R3.js} +1 -1
  94. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-46w7v-9T.js → sizeCapture-X5ZJPWSS-B7jfDkS5.js} +1 -1
  95. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-pbcD5SsZ.js → stateDiagram-OKZ733FA-BmrZod7J.js} +1 -1
  96. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-D9ykKEWP.js +1 -0
  97. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DuivYBSj.js → swimlanes-SLNWSIFB-CDOlHVSY.js} +2 -2
  98. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BvPOXALT.js +8 -0
  99. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cb9VZVIl.js → timeline-definition-Z64GVDOM-Cz-XX1gy.js} +1 -1
  100. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D2-mfOgR.js → vennDiagram-T6HMQDX7-caV4cI8C.js} +1 -1
  101. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DeS2aC76.js → wardleyDiagram-T6FBY63Y-dImPlnIO.js} +1 -1
  102. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-WGsrFjxH.js → xychartDiagram-ELKLHX3M-CtRYVJcn.js} +1 -1
  103. package/dist/worker/console/static/index.html +2 -2
  104. package/dist/worker/console/static-src/app/useRunProgress.js +9 -2
  105. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +19 -8
  106. package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +22 -0
  107. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +15 -7
  108. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
  109. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -0
  110. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
  111. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +106 -0
  112. package/dist/worker/console/workspace-context.js +1 -111
  113. package/dist/worker/observability/read-model.js +4 -0
  114. package/dist/worker/observe/static/dag-node-purpose.js +0 -5
  115. package/dist/worker/observe/static/views/dag-inspector.js +2 -7
  116. package/dist/worker/observe/static/views/session-timeline.js +46 -15
  117. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  118. package/dist/workflows/dag/contract-validator-registrations.js +2 -1
  119. package/dist/workflows/dag/frontend-implementation-contract.js +162 -932
  120. package/dist/workflows/dag/frontend-plan-render.js +1 -2
  121. package/dist/workflows/dag/frontend-prewrite-gate.js +349 -255
  122. package/dist/workflows/dag/frontend-recovery-plan.js +10 -17
  123. package/dist/workflows/dag/frontend-recovery-run.js +20 -33
  124. package/dist/workflows/dag/frontend-repair.js +432 -1
  125. package/dist/workflows/dag/frontend-review-context.js +15 -261
  126. package/dist/workflows/dag/frontend-verification-trace.js +24 -249
  127. package/dist/workflows/dag/frontend-worktree-diff.js +17 -250
  128. package/dist/workflows/dag/init-hybrid.js +494 -685
  129. package/dist/workflows/dag/interrupt-request.js +0 -7
  130. package/dist/workflows/dag/node-execution.js +4 -732
  131. package/dist/workflows/dag/prompt.js +1 -34
  132. package/dist/workflows/dag/report.js +1 -37
  133. package/dist/workflows/dag/rerun-feedback.js +1 -256
  134. package/dist/workflows/dag/rerun-plan.js +2 -10
  135. package/dist/workflows/dag/rerun-run.js +0 -23
  136. package/dist/workflows/dag/rerun-task.js +0 -29
  137. package/dist/workflows/dag/retry-policy.js +104 -214
  138. package/dist/workflows/dag/runner.js +122 -429
  139. package/dist/workflows/dag/scheduler.js +16 -114
  140. package/dist/workflows/dag/types.js +12 -239
  141. package/dist/workflows/dag/validate.js +12 -28
  142. package/docs/init-surface.manifest.json +12 -30
  143. package/docs/skills/vetted-skill-registry.md +2 -4
  144. package/docs/templates/README.md +0 -2
  145. package/docs/templates/agent-dag-report.schema.json +2 -8
  146. package/docs/templates/agent-dag.schema.json +1 -1
  147. package/docs/templates/frontend-implementation-contract.schema.json +1 -4
  148. package/harness.json +3 -3
  149. package/package.json +1 -1
  150. package/skills/frontend-bounded-implement/SKILL.md +14 -15
  151. package/skills/frontend-design-review/SKILL.md +41 -22
  152. package/skills/frontend-implementation/SKILL.md +52 -0
  153. package/skills/frontend-implementation/references/code-standards.md +33 -0
  154. package/skills/frontend-implementation/references/design-spec.md +56 -0
  155. package/skills/frontend-implementation/references/node-contracts.md +31 -0
  156. package/skills/frontend-review/SKILL.md +15 -20
  157. package/skills/frontend-review/references/review-findings.md +7 -6
  158. package/skills/frontend-verification/SKILL.md +1 -1
  159. package/skills/loop-agent/references/command-reference.md +0 -1
  160. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  161. package/dist/commands/dag-follow-up.js +0 -138
  162. package/dist/executors/pi-read-budget-policy.js +0 -239
  163. package/dist/worker/console/frontend-human-decision-adapter.js +0 -19
  164. package/dist/worker/console/frontend-split-operation-adapter.js +0 -20
  165. package/dist/worker/console/static/assets/channel-bnXW0U3C.js +0 -1
  166. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-rZpq_twR.js +0 -1
  167. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-rZpq_twR.js +0 -1
  168. package/dist/worker/console/static/assets/index-D3CC4eUz.css +0 -1
  169. package/dist/worker/console/static/assets/index-DLt4ZFvD.js +0 -437
  170. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-zBMYiUyi.js +0 -1
  171. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-d_rms-5i.js +0 -8
  172. package/dist/worker/console/static-src/active-run-badge.js +0 -17
  173. package/dist/worker/materialize/frontend-split-task-materializer.js +0 -72
  174. package/dist/workflows/dag/dag-retry-schema.js +0 -138
  175. package/dist/workflows/dag/frontend-closeout.js +0 -221
  176. package/dist/workflows/dag/frontend-design-policy.js +0 -400
  177. package/dist/workflows/dag/frontend-human-decision.js +0 -182
  178. package/dist/workflows/dag/frontend-provider-capability-matrix.js +0 -159
  179. package/dist/workflows/dag/frontend-read-budgets.js +0 -12
  180. package/dist/workflows/dag/frontend-recovery-capsule.js +0 -455
  181. package/dist/workflows/dag/frontend-recovery-controller.js +0 -202
  182. package/dist/workflows/dag/frontend-recovery-lineage.js +0 -178
  183. package/dist/workflows/dag/frontend-review-findings.js +0 -270
  184. package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -914
  185. package/dist/workflows/dag/frontend-shape-capsule-store.js +0 -191
  186. package/dist/workflows/dag/frontend-shape-facts.js +0 -409
  187. package/dist/workflows/dag/frontend-shape.js +0 -427
  188. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +0 -108
  189. package/dist/workflows/dag/frontend-split-application-service.js +0 -203
  190. package/dist/workflows/dag/frontend-split-orchestrator.js +0 -899
  191. package/dist/workflows/dag/frontend-typed-event-store.js +0 -452
  192. package/dist/workflows/dag/frontend-typed-event-transaction.js +0 -180
  193. package/dist/workflows/dag/frontend-writer-admission.js +0 -285
  194. package/dist/workflows/dag/frontend-writer-status.js +0 -256
  195. package/dist/workflows/dag/recovery-lease.js +0 -80
  196. package/docs/templates/frontend-implementation-dag.json +0 -89
  197. package/docs/templates/spec-registry.schema.json +0 -45
  198. package/skills/frontend-bounded-implement/references/code-standards.md +0 -19
  199. package/skills/frontend-contract/SKILL.md +0 -23
  200. package/skills/frontend-contract/references/contract-protocol.md +0 -34
  201. package/skills/frontend-plan/SKILL.md +0 -26
  202. package/skills/frontend-plan/references/decision-contract.md +0 -37
  203. package/skills/frontend-plan/references/design-decisions.md +0 -17
  204. package/skills/frontend-scout/SKILL.md +0 -25
  205. package/skills/frontend-scout/references/design-evidence.md +0 -16
  206. package/skills/frontend-scout/references/scout-evidence.md +0 -23
@@ -45,42 +45,9 @@ function formatResolvedSkillInstructions(instructions) {
45
45
  if (!instructions || instructions.length === 0)
46
46
  return "(none)";
47
47
  return instructions
48
- .map((instruction) => formatSkillChecklist(instruction))
48
+ .map((instruction) => instruction.promptText)
49
49
  .join("\n\n---\n\n");
50
50
  }
51
- /** Keep skill provenance, but turn bounded inline manuals into a small action list. */
52
- function formatSkillChecklist(instruction) {
53
- const metadata = [
54
- `Skill: ${instruction.name}`,
55
- `Resolution: ${instruction.resolution}`,
56
- ...(instruction.path ? [`Path: ${instruction.path}`] : []),
57
- ...(instruction.sha256 ? [`Sha256: ${instruction.sha256}`] : []),
58
- "Injection mode: checklist",
59
- ];
60
- if (instruction.resolution !== "resolved")
61
- return [...metadata, instruction.promptText].join("\n");
62
- const source = instruction.promptText.split("Instructions:\n")[1] ?? "";
63
- const candidates = source
64
- .split(/\r?\n/)
65
- .map((line) => line.trim())
66
- .filter((line) => /^(?:#{1,3}\s+|[-*]\s+|\d+[.)]\s+)/.test(line) || line.length > 0)
67
- .map((line) => line.replace(/^#{1,3}\s+/, "").replace(/^[-*]\s+/, "").replace(/^\d+[.)]\s+/, ""))
68
- .filter((line) => line.length > 0);
69
- const checklist = [];
70
- let chars = 0;
71
- for (const item of candidates) {
72
- const bounded = item.slice(0, 240);
73
- if (checklist.length >= 10 || chars + bounded.length > 1_600)
74
- break;
75
- checklist.push(`- ${bounded}`);
76
- chars += bounded.length;
77
- }
78
- return [
79
- ...metadata,
80
- "Checklist (apply these actions; consult the immutable resolved file only when a listed action requires detail):",
81
- ...(checklist.length > 0 ? checklist : ["- Follow the resolved skill's declared workflow."]),
82
- ].join("\n");
83
- }
84
51
  export function formatOutputLanguageBlock(language = DEFAULT_DAG_OUTPUT_LANGUAGE) {
85
52
  if (language === "en") {
86
53
  return [
@@ -125,8 +125,6 @@ const dagNodeArtifactsReportSchema = z
125
125
  humanEscalationMd: dagArtifactRefSchema,
126
126
  humanApproval: dagArtifactRefSchema,
127
127
  humanRejection: dagArtifactRefSchema,
128
- changeManifest: dagArtifactRefSchema,
129
- changeManifestChangedFiles: z.array(z.string()).optional(),
130
128
  })
131
129
  .strict();
132
130
  const dagNodeReportRowSchema = z
@@ -261,20 +259,6 @@ export async function probeArtifact(filePath) {
261
259
  export async function buildNodeArtifactsReport(runDir, nodeId) {
262
260
  const nodeDir = path.join(runDir, nodeId);
263
261
  const artifact = (name) => probeArtifact(path.join(nodeDir, name));
264
- const changeManifestRef = await artifact("change-manifest.json");
265
- let changeManifestChangedFiles;
266
- if (changeManifestRef.exists) {
267
- try {
268
- const manifest = JSON.parse(await readFile(path.join(nodeDir, "change-manifest.json"), "utf-8"));
269
- changeManifestChangedFiles = Array.isArray(manifest.changedFiles)
270
- ? manifest.changedFiles
271
- .filter((item) => typeof item === "string")
272
- : undefined;
273
- }
274
- catch {
275
- // unreadable manifest → leave undefined
276
- }
277
- }
278
262
  return {
279
263
  resultSummary: await artifact("result.summary.md"),
280
264
  promptRedacted: await artifact("prompt.redacted.md"),
@@ -286,8 +270,6 @@ export async function buildNodeArtifactsReport(runDir, nodeId) {
286
270
  humanEscalationMd: await artifact("human-escalation.md"),
287
271
  humanApproval: await artifact("human-approval.json"),
288
272
  humanRejection: await artifact("human-rejection.json"),
289
- changeManifest: changeManifestRef,
290
- changeManifestChangedFiles,
291
273
  };
292
274
  }
293
275
  function taskById(spec) {
@@ -744,12 +726,6 @@ function formatArtifactFlags(artifacts) {
744
726
  flags.push("approval");
745
727
  if (artifacts.humanRejection.exists)
746
728
  flags.push("rejection");
747
- if (artifacts.changeManifest.exists) {
748
- const count = artifacts.changeManifestChangedFiles?.length;
749
- flags.push(count !== undefined
750
- ? `changed:${count}`
751
- : "change-manifest");
752
- }
753
729
  return flags.length > 0 ? flags.join(",") : "-";
754
730
  }
755
731
  function formatTimestamp(value) {
@@ -773,19 +749,7 @@ function summarizeNodeStatuses(nodes) {
773
749
  return `${total} total / ${finished} finished / ${failed} failed / ${skipped} skipped / ${pending} pending`;
774
750
  }
775
751
  function hasArtifact(artifacts) {
776
- return [
777
- artifacts.resultSummary,
778
- artifacts.promptRedacted,
779
- artifacts.skills,
780
- artifacts.nodeRecord,
781
- artifacts.decisionEnvelope,
782
- artifacts.decisionEnvelopeValidation,
783
- artifacts.humanEscalationJson,
784
- artifacts.humanEscalationMd,
785
- artifacts.humanApproval,
786
- artifacts.humanRejection,
787
- artifacts.changeManifest,
788
- ].some((artifact) => artifact.exists);
752
+ return Object.values(artifacts).some((artifact) => artifact.exists);
789
753
  }
790
754
  function failureRows(run) {
791
755
  return run.nodes.filter((node) => node.status === "ERROR" ||
@@ -2,8 +2,6 @@ import { createHash } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { parseJsonReviewVerdict } from "./output-protocol.js";
5
- import { FRONTEND_DESIGN_REVIEW_NODE_ID, FRONTEND_REVIEW_NODE_ID, readCommittedDesignRequestFact, readCommittedReviewRequestFact, } from "./frontend-review-findings.js";
6
- import { readTypedEventStoreFromJsonl } from "./frontend-typed-event-store.js";
7
5
  export const MAX_RERUN_FEEDBACK_CHARS = 12_000;
8
6
  const RERUN_FEEDBACK_TRUNCATION_MARKER = "\n\n...[上一轮反馈已按长度上限截断]...\n\n";
9
7
  const MAX_EVIDENCE_REFS = 8;
@@ -37,44 +35,6 @@ function requestRevision(text) {
37
35
  return (emphasized?.[1] ?? trimmed).trim() === "VERDICT: request-revision";
38
36
  });
39
37
  }
40
- /**
41
- * Deterministically render a typed `request_review_changes` fact into feedback
42
- * text. Unlike the legacy text channel (VERDICT: request-revision), the
43
- * frontend review terminal is a committed typed fact; the findings are the
44
- * actionable body the next round must consume.
45
- */
46
- export function formatTypedReviewRequestFeedback(fact) {
47
- const lines = [];
48
- lines.push(`frontend review committed request_review_changes (issueCategory=${typeof fact.issueCategory === "string" ? fact.issueCategory : "unknown"})`);
49
- if (Array.isArray(fact.findings) && fact.findings.length > 0) {
50
- lines.push("review findings:");
51
- for (const finding of fact.findings) {
52
- if (!finding || typeof finding !== "object")
53
- continue;
54
- const record = finding;
55
- const severity = typeof record.severity === "string" ? record.severity : "";
56
- const issue = typeof record.issue === "string" ? record.issue : "";
57
- const location = [
58
- typeof record.file === "string" ? record.file : "",
59
- typeof record.line === "number" ? String(record.line) : "",
60
- ]
61
- .filter(Boolean)
62
- .join(":");
63
- const prefix = location ? `[${location}] ` : "";
64
- const requiredChange = typeof record.requiredChange === "string" &&
65
- record.requiredChange.length > 0
66
- ? ` (requiredChange: ${record.requiredChange})`
67
- : "";
68
- lines.push(`- ${prefix}${severity}: ${issue}${requiredChange}`);
69
- }
70
- }
71
- if (Array.isArray(fact.evidenceRefs) && fact.evidenceRefs.length > 0) {
72
- lines.push(`evidenceRefs: ${fact.evidenceRefs
73
- .filter((ref) => typeof ref === "string")
74
- .join(", ")}`);
75
- }
76
- return lines.join("\n");
77
- }
78
38
  function pathInside(root, candidate) {
79
39
  const relative = path.relative(root, candidate);
80
40
  return (relative === "" ||
@@ -167,162 +127,6 @@ function evidenceRefs(repoRoot, runDir, pass, sourceNodeId) {
167
127
  }
168
128
  return result;
169
129
  }
170
- /**
171
- * Read the committed frontend review request fact (typed terminal channel).
172
- * Returns { nodeId, fact } when the review node committed `request_review_changes`.
173
- */
174
- async function readTypedReviewRequestFact(runDir) {
175
- const fact = await readCommittedReviewRequestFact({ runDir });
176
- if (!fact)
177
- return undefined;
178
- return {
179
- nodeId: FRONTEND_REVIEW_NODE_ID,
180
- fact: {
181
- issueCategory: fact.issueCategory,
182
- evidenceRefs: fact.evidenceRefs,
183
- findings: fact.findings,
184
- },
185
- };
186
- }
187
- /**
188
- * Read the committed frontend design request fact (typed terminal channel).
189
- * Returns { nodeId, fact } when the design review node committed
190
- * `request_design_changes` — the design analog of request_review_changes.
191
- */
192
- async function readTypedDesignRequestFact(runDir) {
193
- const fact = await readCommittedDesignRequestFact({ runDir });
194
- if (!fact)
195
- return undefined;
196
- return {
197
- nodeId: FRONTEND_DESIGN_REVIEW_NODE_ID,
198
- fact: {
199
- issueCategory: fact.issueCategory,
200
- evidenceRefs: fact.evidenceRefs,
201
- findings: fact.findings,
202
- },
203
- };
204
- }
205
- const RERUN_FEEDBACK_LINEAGE_MAX_DEPTH = 5;
206
- const RERUN_FEEDBACK_LINEAGE_LIFECYCLES = [
207
- "active",
208
- "paused",
209
- "completed",
210
- ];
211
- function safeLineageRunId(value) {
212
- if (typeof value !== "string" || !value || value !== value.trim())
213
- return undefined;
214
- if (value === "." ||
215
- value === ".." ||
216
- value.includes("/") ||
217
- value.includes("\\") ||
218
- value.includes("\0"))
219
- return undefined;
220
- return value;
221
- }
222
- async function readCommittedTerminalKind(input) {
223
- try {
224
- const records = await readTypedEventStoreFromJsonl(path.join(input.runDir, input.nodeId, input.factsFile));
225
- for (const record of records) {
226
- if (record.phase !== "committed")
227
- continue;
228
- const kind = record.fact.kind;
229
- if (typeof kind === "string" && input.kinds.includes(kind))
230
- return kind;
231
- }
232
- }
233
- catch {
234
- // A missing/unreadable terminal store means this run did not establish a
235
- // usable resolution barrier; lineage lookup may continue.
236
- }
237
- return undefined;
238
- }
239
- async function readReviewTerminalKind(runDir) {
240
- return readCommittedTerminalKind({
241
- runDir,
242
- nodeId: FRONTEND_REVIEW_NODE_ID,
243
- factsFile: "review-typed-facts.jsonl",
244
- kinds: ["request_review_changes", "approve_review"],
245
- });
246
- }
247
- async function readDesignTerminalKind(runDir) {
248
- return readCommittedTerminalKind({
249
- runDir,
250
- nodeId: FRONTEND_DESIGN_REVIEW_NODE_ID,
251
- factsFile: "design-typed-facts.jsonl",
252
- kinds: ["request_design_changes", "approve_design"],
253
- });
254
- }
255
- /**
256
- * Walk the rerun-task lineage chain (`<runDir>/.runtime/rerun-task-lineage.json`
257
- * → parentRunId) looking for the nearest ancestor run with a committed review
258
- * or design request fact. A nearer final-review approval resolves all older
259
- * findings; a nearer design approval resolves older design findings while
260
- * still allowing an older final-review request to survive. Bounded depth;
261
- * unsafe ids, mismatched state identities, cycles, and unreadable lineage
262
- * files terminate the walk with undefined.
263
- */
264
- async function readAncestorTypedRequestFact(runDir) {
265
- let currentRunDir = runDir;
266
- let currentRunId;
267
- let designResolved = false;
268
- const dagRunsRoot = path.resolve(runDir, "..", "..");
269
- const visitedRunDirs = new Set([path.resolve(runDir)]);
270
- for (let depth = 0; depth <= RERUN_FEEDBACK_LINEAGE_MAX_DEPTH; depth += 1) {
271
- const reviewTerminalKind = await readReviewTerminalKind(currentRunDir);
272
- if (currentRunId && reviewTerminalKind === "request_review_changes") {
273
- const fact = await readTypedReviewRequestFact(currentRunDir);
274
- if (fact)
275
- return { ...fact, parentRunId: currentRunId };
276
- }
277
- if (reviewTerminalKind === "approve_review")
278
- return undefined;
279
- const designTerminalKind = await readDesignTerminalKind(currentRunDir);
280
- if (currentRunId &&
281
- !designResolved &&
282
- designTerminalKind === "request_design_changes") {
283
- const fact = await readTypedDesignRequestFact(currentRunDir);
284
- if (fact)
285
- return { ...fact, parentRunId: currentRunId };
286
- }
287
- if (designTerminalKind === "approve_design")
288
- designResolved = true;
289
- if (depth === RERUN_FEEDBACK_LINEAGE_MAX_DEPTH)
290
- return undefined;
291
- let parentRunId;
292
- try {
293
- const lineage = JSON.parse(await readFile(path.join(currentRunDir, ".runtime", "rerun-task-lineage.json"), "utf8"));
294
- parentRunId = safeLineageRunId(lineage.parentRunId);
295
- }
296
- catch {
297
- return undefined;
298
- }
299
- if (!parentRunId)
300
- return undefined;
301
- let ancestorRunDir;
302
- for (const lifecycle of RERUN_FEEDBACK_LINEAGE_LIFECYCLES) {
303
- const candidate = path.join(dagRunsRoot, lifecycle, parentRunId);
304
- try {
305
- const ancestorState = JSON.parse(await readFile(path.join(candidate, "state.json"), "utf8"));
306
- if (ancestorState.runId === parentRunId) {
307
- ancestorRunDir = candidate;
308
- break;
309
- }
310
- }
311
- catch {
312
- // try next lifecycle
313
- }
314
- }
315
- if (!ancestorRunDir)
316
- return undefined;
317
- const resolvedAncestorRunDir = path.resolve(ancestorRunDir);
318
- if (visitedRunDirs.has(resolvedAncestorRunDir))
319
- return undefined;
320
- visitedRunDirs.add(resolvedAncestorRunDir);
321
- currentRunDir = ancestorRunDir;
322
- currentRunId = parentRunId;
323
- }
324
- return undefined;
325
- }
326
130
  /**
327
131
  * Derive only the latest unresolved verify/review feedback from canonical
328
132
  * parent-run facts. Provider-only failures intentionally return undefined.
@@ -340,67 +144,8 @@ export async function deriveDagRerunFeedback(input) {
340
144
  break;
341
145
  }
342
146
  }
343
- if (!sourceNodeId || !sourceNode) {
344
- // Typed terminal channel: the frontend review/design review commit their
345
- // verdicts as typed facts (request_review_changes / request_design_changes)
346
- // instead of VERDICT text, and the frontend DAG has no convergence
347
- // passHistory. Fall back to reading the typed event stores so findings
348
- // still flow into the next round as unresolved feedback. Prefer review;
349
- // if absent, fall through to the design review (a design rejection also
350
- // carries actionable findings the next plan round must consume). When
351
- // the direct parent has neither because it failed before review, walk the
352
- // rerun-task lineage chain — chained
353
- // reruns otherwise lose the grandparent's code-review findings and the
354
- // reviewer re-flags them as "unresolved previous-round feedback" (r18).
355
- // A committed approval is a resolution barrier and prevents older
356
- // findings from being resurrected.
357
- const typedFact = (await readTypedReviewRequestFact(input.runDir)) ??
358
- (await readTypedDesignRequestFact(input.runDir)) ??
359
- (await readAncestorTypedRequestFact(input.runDir));
360
- if (typedFact) {
361
- const parentSourceBindingHash = sourceBindingHash(input.spec);
362
- return withDigest({
363
- schemaVersion: 1,
364
- kind: "unresolved-terminal-feedback",
365
- parentRunId: "parentRunId" in typedFact &&
366
- typeof typedFact.parentRunId === "string"
367
- ? typedFact.parentRunId
368
- : input.parentRunId,
369
- taskId: input.taskId,
370
- sourceNodeId: typedFact.nodeId,
371
- verdict: "request-revision",
372
- failureCategory: typedFact.nodeId === FRONTEND_REVIEW_NODE_ID
373
- ? "review-request-changes"
374
- : "design-request-changes",
375
- feedbackText: scrubAndBoundFeedbackText(formatTypedReviewRequestFeedback(typedFact.fact), input.runDir, input.state.cwd),
376
- evidenceRefs: [
377
- {
378
- nodeId: typedFact.nodeId,
379
- preservedNodeRecordPath: `${typedFact.nodeId}.json`,
380
- },
381
- ],
382
- attemptSummary: {
383
- completedPasses: 1,
384
- maxPasses: 1,
385
- ...(input.state.terminalReason
386
- ? { terminalReason: input.state.terminalReason }
387
- : {}),
388
- },
389
- binding: {
390
- ...(parentSourceBindingHash
391
- ? { sourceCanonicalHash: parentSourceBindingHash }
392
- : {}),
393
- ...(input.spec.taskContractBinding?.canonicalHash
394
- ? {
395
- taskContractCanonicalHash: input.spec.taskContractBinding.canonicalHash,
396
- }
397
- : {}),
398
- status: "unknown",
399
- },
400
- });
401
- }
147
+ if (!sourceNodeId || !sourceNode)
402
148
  return undefined;
403
- }
404
149
  const completedPasses = pass?.pass ?? Math.max(1, input.state.convergence?.currentPass ?? 1);
405
150
  const maxPasses = Math.max(completedPasses, input.state.convergence?.maxPasses ?? 1);
406
151
  const parentSourceBindingHash = sourceBindingHash(input.spec);
@@ -160,16 +160,12 @@ function isCanonicalGeneratedVerifyShell(task) {
160
160
  return false;
161
161
  if (shell.projectGovernanceGate)
162
162
  return false;
163
- if (shell.frontendDesignPolicy)
164
- return false;
165
- if (shell.frontendWriterAdmission)
163
+ if (shell.frontendPrewriteGate)
166
164
  return false;
167
165
  if (shell.frontendVerificationBundle)
168
166
  return false;
169
167
  if (shell.frontendReviewContext)
170
168
  return false;
171
- if (shell.frontendCloseout)
172
- return false;
173
169
  if (shell.backendTestPipeline)
174
170
  return false;
175
171
  if (shell.nonZeroExitPolicy === "record")
@@ -195,16 +191,12 @@ function isSafeGateOnlyShell(task) {
195
191
  return false;
196
192
  if (shell.preset)
197
193
  return false;
198
- if (shell.frontendDesignPolicy)
199
- return false;
200
- if (shell.frontendWriterAdmission)
194
+ if (shell.frontendPrewriteGate)
201
195
  return false;
202
196
  if (shell.frontendVerificationBundle)
203
197
  return false;
204
198
  if (shell.frontendReviewContext)
205
199
  return false;
206
- if (shell.frontendCloseout)
207
- return false;
208
200
  if (shell.backendTestPipeline)
209
201
  return false;
210
202
  if (shell.verifyEvidence)
@@ -12,7 +12,6 @@ import { prepareActiveRunDir, writeNodeRecord, writeRunSpec, writeRunState, } fr
12
12
  import { cloneParentSkillSnapshotForContinuation, readSkillSnapshot, } from "./skill-snapshot.js";
13
13
  import { topoSortToRanks } from "./topo.js";
14
14
  import { captureWorkspaceCheckpoint, readWorkspaceCheckpoint, WORKSPACE_CHECKPOINT_START_REL, WORKSPACE_CHECKPOINT_TERMINAL_REL, writeWorkspaceCheckpoint, } from "./workspace-checkpoint.js";
15
- import { acquireDagRecoveryLease, bindDagRecoveryLeaseExecution, } from "./recovery-lease.js";
16
15
  export const RERUN_PLAN_REL_PATH = ".runtime/rerun-plan.json";
17
16
  export const IMPORT_MANIFEST_REL_PATH = ".runtime/import-manifest.json";
18
17
  export const WORKER_ASSOCIATION_REL_PATH = ".runtime/worker-association.json";
@@ -573,20 +572,6 @@ export async function executeDagRerun(input) {
573
572
  }
574
573
  const parentSpec = await readDagRunSpec(located.runDir);
575
574
  const parentState = await readDagRunState(located.runDir);
576
- const recoveryLease = await acquireDagRecoveryLease({
577
- cwd: input.cwd,
578
- parentRunId: input.parentRunId,
579
- requestId: input.requestId,
580
- kind: "rerun-from-node",
581
- });
582
- if (recoveryLease.kind === "held") {
583
- return {
584
- ok: false,
585
- plan,
586
- errorCode: "RECOVERY_LEASE_HELD",
587
- message: `parent run recovery is already claimed by ${recoveryLease.lease.kind} request ${recoveryLease.lease.requestId}`,
588
- };
589
- }
590
575
  const staged = await stageContinuationRun({
591
576
  cwd: input.cwd,
592
577
  parentRunDir: located.runDir,
@@ -598,14 +583,6 @@ export async function executeDagRerun(input) {
598
583
  requestId: input.requestId,
599
584
  promptOverrides: input.promptOverrides,
600
585
  });
601
- // Stage is non-executing; bind the child identity immediately before handing
602
- // it to the runner so no recovery DAG can start without durable parent
603
- // lineage ownership.
604
- await bindDagRecoveryLeaseExecution({
605
- leasePath: recoveryLease.leasePath,
606
- lease: recoveryLease.lease,
607
- executionRef: staged.state.runId,
608
- });
609
586
  const continuationOptions = {
610
587
  cwd: input.cwd,
611
588
  spec: staged.spec,
@@ -4,7 +4,6 @@ import { generateTaskDagUseCase } from "../../application/dag/generate-task-dag.
4
4
  import { writeJsonAtomic } from "../../infrastructure/harness/atomic-write.js";
5
5
  import { DAG_RUNS_DIR, isTerminalDagRunStatus, locateDagRun, readDagRunSpec, readDagRunState, } from "./lifecycle.js";
6
6
  import { deriveDagRerunFeedback } from "./rerun-feedback.js";
7
- import { acquireDagRecoveryLease, bindDagRecoveryLeaseExecution, } from "./recovery-lease.js";
8
7
  import { parseDagSpec, } from "./types.js";
9
8
  export const RERUN_TASK_LINEAGE_REL_PATH = ".runtime/rerun-task-lineage.json";
10
9
  export function parseDagRerunTaskArgs(args) {
@@ -370,34 +369,6 @@ export async function rerunStandaloneTask(input) {
370
369
  }
371
370
  }
372
371
  }
373
- const recoveryLease = execute
374
- ? await acquireDagRecoveryLease({
375
- cwd: input.cwd,
376
- parentRunId: input.parentRunId,
377
- requestId: input.requestId,
378
- kind: "standalone-task-rerun",
379
- })
380
- : undefined;
381
- if (recoveryLease?.kind === "held") {
382
- return blockedResult({
383
- parentRunId: input.parentRunId,
384
- reason: input.reason,
385
- requestId: input.requestId,
386
- blockedReason: "recovery-lease-held",
387
- note: `parent run recovery is already claimed by ${recoveryLease.lease.kind} request ${recoveryLease.lease.requestId}`,
388
- taskId: taskResolution.taskId,
389
- });
390
- }
391
- if (recoveryLease?.kind === "acquired") {
392
- // Persist a non-empty execution identity before generateTaskDagUseCase can
393
- // execute its new DAG. The generated run id is not available yet, so the
394
- // request id is the stable lineage handle for this entry point.
395
- await bindDagRecoveryLeaseExecution({
396
- leasePath: recoveryLease.leasePath,
397
- lease: recoveryLease.lease,
398
- executionRef: `standalone-task-rerun:${input.requestId}`,
399
- });
400
- }
401
372
  const generateResult = await generateTaskDagUseCase({
402
373
  repoRoot: input.cwd,
403
374
  taskId: taskResolution.taskId,