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

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 (209) hide show
  1. package/CHANGELOG.md +61 -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/pi-extension-resolver.js +14 -2
  16. package/dist/executors/shell-executor.js +217 -945
  17. package/dist/executors/shell-write-guard.js +0 -7
  18. package/dist/shared/dag-failure-category.js +0 -12
  19. package/dist/shared/openspec-spec.js +4 -70
  20. package/dist/shared/operator/capabilities.js +0 -7
  21. package/dist/task/config-types.js +7 -34
  22. package/dist/task/contract/adopt.js +0 -4
  23. package/dist/task/contract/import-revision.js +0 -4
  24. package/dist/task/contract/project.js +0 -3
  25. package/dist/task/contract/schema.js +1 -2
  26. package/dist/task/frontend-project-capability.js +20 -203
  27. package/dist/task/runtime.js +2 -5
  28. package/dist/task/source-prepare/build-draft.js +3 -3
  29. package/dist/task/source-prepare/fragment-inventory.js +9 -15
  30. package/dist/task/source-prepare/prepare.js +1 -89
  31. package/dist/task/source-prepare/semantic-intake.js +2 -6
  32. package/dist/task/source-references.js +1 -22
  33. package/dist/worker/console/chat/chat-ui-policy.js +4 -2
  34. package/dist/worker/console/chat/pi-runtime.js +235 -13
  35. package/dist/worker/console/chat/repo-browser.js +10 -3
  36. package/dist/worker/console/chat/routes.js +86 -44
  37. package/dist/worker/console/chat/semantic-activity.js +12 -11
  38. package/dist/worker/console/chat/session-stats.js +96 -0
  39. package/dist/worker/console/chat/session-store.js +133 -70
  40. package/dist/worker/console/chat/shortcuts.js +1 -1
  41. package/dist/worker/console/chat/turn-process.js +139 -60
  42. package/dist/worker/console/index.js +0 -3
  43. package/dist/worker/console/operation-store.js +6 -226
  44. package/dist/worker/console/operator-actions.js +7 -169
  45. package/dist/worker/console/pi-plugins.js +3 -1
  46. package/dist/worker/console/server.js +19 -4
  47. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bho4we4c.js → abnfDiagram-N423BO3Z-DQ5jlYVU.js} +1 -1
  48. package/dist/worker/console/static/assets/{arc-TBDkTeK0.js → arc-BeTVCzH9.js} +1 -1
  49. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BF_fZrn2.js → architectureDiagram-T3A2C74G-DassREBi.js} +1 -1
  50. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CCnPgUe2.js → blockDiagram-VBNYF7ZC-DyeNX8Ek.js} +1 -1
  51. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BCYZJLAT.js → c4Diagram-5PPSVZJV-BXb_zxGx.js} +1 -1
  52. package/dist/worker/console/static/assets/channel-B_lofstT.js +1 -0
  53. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D8K6adhU.js → chunk-2GRJ4B5K-B9F9gxGC.js} +1 -1
  54. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DkT1Q78b.js → chunk-2Q5K7J3B-Byd5zHEQ.js} +1 -1
  55. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DuhvpIr7.js → chunk-5RXB4S5H-BqoxMJk9.js} +1 -1
  56. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BnK6dC49.js → chunk-5VM5RSS4-CT7d6YZw.js} +1 -1
  57. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DPz__z7r.js → chunk-6Q2QTUOP-CdiNyN0N.js} +1 -1
  58. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-0kkppM2j.js → chunk-GF5L2VYU-BGw9bpVc.js} +1 -1
  59. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BB41iK5t.js → chunk-JWPE2WC7-DiDVlVB1.js} +1 -1
  60. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CiVrxKHU.js → chunk-KBJHAD2P-BhHf-4yK.js} +1 -1
  61. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-C2h9Xje1.js → chunk-RYQCIY6F-B79pEgwv.js} +1 -1
  62. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-3iOSHdbM.js → chunk-XXDRQBXY-Cb70EcUV.js} +1 -1
  63. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-ieUI0-eY.js +1 -0
  64. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-ieUI0-eY.js +1 -0
  65. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BN3A7tkk.js → cose-bilkent-JH36ORCC-DBHLnAf1.js} +1 -1
  66. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CTuBy0Or.js → cynefin-VYW2F7L2-BT_JRsOH.js} +1 -1
  67. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-wb6tUlMN.js → cynefinDiagram-MW4NZA55-Bss-msa3.js} +1 -1
  68. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-GP1Ivx8B.js → dagre-VZM6K2ZE-B8Gr24pt.js} +1 -1
  69. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-ejrcK6L0.js → diagram-7IWD3JNH-BrjU70Jw.js} +1 -1
  70. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-YFkCCvUU.js → diagram-B4RE2ZJO-Cp_JpPGd.js} +1 -1
  71. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-B4rrvIaL.js → diagram-LBJQPF4R-BWKICEP-.js} +1 -1
  72. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C-YIZcUf.js → diagram-Q27KOJAE-D3z_UNR_.js} +1 -1
  73. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPF5wcL1.js → diagram-UB23O5K3-_Ywm390x.js} +1 -1
  74. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CU5SzXjO.js → ebnfDiagram-BXEA7PRR-D9QYQQMB.js} +1 -1
  75. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CpL414DE.js → erDiagram-JOGREHBK-BNgXNKAr.js} +1 -1
  76. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-MrhLzNau.js → flowDiagram-UKHOOZJN-QRLnkPCg.js} +1 -1
  77. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Bg4qFuUo.js → ganttDiagram-PKOTCBZU-B9fOduNi.js} +1 -1
  78. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-ColxSXLR.js → gitGraphDiagram-DS77QQ5N-FSEdtPN2.js} +1 -1
  79. package/dist/worker/console/static/assets/index-Cs9JUSPs.css +1 -0
  80. package/dist/worker/console/static/assets/index-DtPrwu7M.js +451 -0
  81. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czvtm6gc.js → infoDiagram-6WML65LV-D5Bjg9dm.js} +1 -1
  82. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B7Xp8HyJ.js → ishikawaDiagram-WSZJBQD7-BlNRkWvf.js} +1 -1
  83. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DWYZcvph.js → journeyDiagram-NVQOT4AX-BdJiw3SL.js} +1 -1
  84. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-KTLZRUjx.js → kanban-definition-27J2QSJJ-CsDNlYht.js} +1 -1
  85. package/dist/worker/console/static/assets/{linear-_Exn7bfl.js → linear-8g9dbEmX.js} +1 -1
  86. package/dist/worker/console/static/assets/{mermaid.core-Cxg8kX8V.js → mermaid.core-ChyQH_ut.js} +5 -5
  87. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-oKrlo2Bt.js → mindmap-definition-FAOFIHXS-DwYoCTYt.js} +1 -1
  88. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-XAeteiNd.js → pegDiagram-VL7TDLO6-T_b2rS17.js} +1 -1
  89. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BTf1K-lp.js → pieDiagram-7S7Q4E2Y-1Cr7WMhH.js} +1 -1
  90. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-C0IlY0Jf.js → quadrantDiagram-CIZ2JOQS-Bq4qM59o.js} +1 -1
  91. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BVbKtZhW.js → railroadDiagram-AXF67PYL-ytFgR1RL.js} +1 -1
  92. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C5e4JFcr.js → requirementDiagram-LRYGKXZP-CnUdUVYX.js} +1 -1
  93. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cz30hc29.js → sankeyDiagram-W5VNT64P-_5rJqG6R.js} +1 -1
  94. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DS33n6d0.js → sequenceDiagram-SI44F4Z6-D5imyGbt.js} +1 -1
  95. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-46w7v-9T.js → sizeCapture-X5ZJPWSS-DvgDn3wL.js} +1 -1
  96. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-pbcD5SsZ.js → stateDiagram-OKZ733FA-BViu7duc.js} +1 -1
  97. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-kNxnG4_w.js +1 -0
  98. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DuivYBSj.js → swimlanes-SLNWSIFB-BcULKg2P.js} +2 -2
  99. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DyTzlcWH.js +8 -0
  100. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cb9VZVIl.js → timeline-definition-Z64GVDOM-DmPveIjt.js} +1 -1
  101. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D2-mfOgR.js → vennDiagram-T6HMQDX7-9r-iFy0R.js} +1 -1
  102. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DeS2aC76.js → wardleyDiagram-T6FBY63Y-D3fIXdvM.js} +1 -1
  103. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-WGsrFjxH.js → xychartDiagram-ELKLHX3M-BCSS9SBg.js} +1 -1
  104. package/dist/worker/console/static/index.html +2 -2
  105. package/dist/worker/console/static-src/app/useRunProgress.js +9 -2
  106. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +19 -8
  107. package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +22 -0
  108. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +15 -7
  109. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
  110. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -0
  111. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
  112. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +106 -0
  113. package/dist/worker/console/static-src/shell/workspace-route.js +4 -0
  114. package/dist/worker/console/workspace-context.js +1 -111
  115. package/dist/worker/observability/read-model.js +4 -0
  116. package/dist/worker/observe/routes.js +4 -0
  117. package/dist/worker/observe/static/dag-node-purpose.js +0 -5
  118. package/dist/worker/observe/static/views/dag-inspector.js +2 -7
  119. package/dist/worker/observe/static/views/session-timeline.js +46 -15
  120. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  121. package/dist/workflows/dag/contract-validator-registrations.js +2 -1
  122. package/dist/workflows/dag/frontend-implementation-contract.js +162 -932
  123. package/dist/workflows/dag/frontend-plan-render.js +1 -2
  124. package/dist/workflows/dag/frontend-prewrite-gate.js +349 -255
  125. package/dist/workflows/dag/frontend-recovery-plan.js +10 -17
  126. package/dist/workflows/dag/frontend-recovery-run.js +20 -33
  127. package/dist/workflows/dag/frontend-repair.js +432 -1
  128. package/dist/workflows/dag/frontend-review-context.js +15 -261
  129. package/dist/workflows/dag/frontend-verification-trace.js +24 -249
  130. package/dist/workflows/dag/frontend-worktree-diff.js +17 -250
  131. package/dist/workflows/dag/init-hybrid.js +494 -685
  132. package/dist/workflows/dag/interrupt-request.js +0 -7
  133. package/dist/workflows/dag/node-execution.js +4 -732
  134. package/dist/workflows/dag/prompt.js +1 -34
  135. package/dist/workflows/dag/report.js +1 -37
  136. package/dist/workflows/dag/rerun-feedback.js +1 -256
  137. package/dist/workflows/dag/rerun-plan.js +2 -10
  138. package/dist/workflows/dag/rerun-run.js +0 -23
  139. package/dist/workflows/dag/rerun-task.js +0 -29
  140. package/dist/workflows/dag/retry-policy.js +104 -214
  141. package/dist/workflows/dag/runner.js +122 -429
  142. package/dist/workflows/dag/scheduler.js +16 -114
  143. package/dist/workflows/dag/types.js +12 -239
  144. package/dist/workflows/dag/validate.js +12 -28
  145. package/docs/init-surface.manifest.json +12 -30
  146. package/docs/skills/vetted-skill-registry.md +2 -4
  147. package/docs/templates/README.md +0 -2
  148. package/docs/templates/agent-dag-report.schema.json +2 -8
  149. package/docs/templates/agent-dag.schema.json +1 -1
  150. package/docs/templates/frontend-implementation-contract.schema.json +1 -4
  151. package/harness.json +3 -3
  152. package/package.json +1 -1
  153. package/skills/frontend-bounded-implement/SKILL.md +14 -15
  154. package/skills/frontend-design-review/SKILL.md +41 -22
  155. package/skills/frontend-implementation/SKILL.md +52 -0
  156. package/skills/frontend-implementation/references/code-standards.md +33 -0
  157. package/skills/frontend-implementation/references/design-spec.md +56 -0
  158. package/skills/frontend-implementation/references/node-contracts.md +31 -0
  159. package/skills/frontend-review/SKILL.md +15 -20
  160. package/skills/frontend-review/references/review-findings.md +7 -6
  161. package/skills/frontend-verification/SKILL.md +1 -1
  162. package/skills/loop-agent/references/command-reference.md +0 -1
  163. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  164. package/dist/commands/dag-follow-up.js +0 -138
  165. package/dist/executors/pi-read-budget-policy.js +0 -239
  166. package/dist/worker/console/frontend-human-decision-adapter.js +0 -19
  167. package/dist/worker/console/frontend-split-operation-adapter.js +0 -20
  168. package/dist/worker/console/static/assets/channel-bnXW0U3C.js +0 -1
  169. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-rZpq_twR.js +0 -1
  170. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-rZpq_twR.js +0 -1
  171. package/dist/worker/console/static/assets/index-D3CC4eUz.css +0 -1
  172. package/dist/worker/console/static/assets/index-DLt4ZFvD.js +0 -437
  173. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-zBMYiUyi.js +0 -1
  174. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-d_rms-5i.js +0 -8
  175. package/dist/worker/console/static-src/active-run-badge.js +0 -17
  176. package/dist/worker/materialize/frontend-split-task-materializer.js +0 -72
  177. package/dist/workflows/dag/dag-retry-schema.js +0 -138
  178. package/dist/workflows/dag/frontend-closeout.js +0 -221
  179. package/dist/workflows/dag/frontend-design-policy.js +0 -400
  180. package/dist/workflows/dag/frontend-human-decision.js +0 -182
  181. package/dist/workflows/dag/frontend-provider-capability-matrix.js +0 -159
  182. package/dist/workflows/dag/frontend-read-budgets.js +0 -12
  183. package/dist/workflows/dag/frontend-recovery-capsule.js +0 -455
  184. package/dist/workflows/dag/frontend-recovery-controller.js +0 -202
  185. package/dist/workflows/dag/frontend-recovery-lineage.js +0 -178
  186. package/dist/workflows/dag/frontend-review-findings.js +0 -270
  187. package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -914
  188. package/dist/workflows/dag/frontend-shape-capsule-store.js +0 -191
  189. package/dist/workflows/dag/frontend-shape-facts.js +0 -409
  190. package/dist/workflows/dag/frontend-shape.js +0 -427
  191. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +0 -108
  192. package/dist/workflows/dag/frontend-split-application-service.js +0 -203
  193. package/dist/workflows/dag/frontend-split-orchestrator.js +0 -899
  194. package/dist/workflows/dag/frontend-typed-event-store.js +0 -452
  195. package/dist/workflows/dag/frontend-typed-event-transaction.js +0 -180
  196. package/dist/workflows/dag/frontend-writer-admission.js +0 -285
  197. package/dist/workflows/dag/frontend-writer-status.js +0 -256
  198. package/dist/workflows/dag/recovery-lease.js +0 -80
  199. package/docs/templates/frontend-implementation-dag.json +0 -89
  200. package/docs/templates/spec-registry.schema.json +0 -45
  201. package/skills/frontend-bounded-implement/references/code-standards.md +0 -19
  202. package/skills/frontend-contract/SKILL.md +0 -23
  203. package/skills/frontend-contract/references/contract-protocol.md +0 -34
  204. package/skills/frontend-plan/SKILL.md +0 -26
  205. package/skills/frontend-plan/references/decision-contract.md +0 -37
  206. package/skills/frontend-plan/references/design-decisions.md +0 -17
  207. package/skills/frontend-scout/SKILL.md +0 -25
  208. package/skills/frontend-scout/references/design-evidence.md +0 -16
  209. package/skills/frontend-scout/references/scout-evidence.md +0 -23
@@ -175,11 +175,8 @@ export function splitDocumentIntoFragments(doc) {
175
175
  const explicitSectionAc = matchExplicitAcHeading(lastHeadingSegment);
176
176
  const sectionKind = classifySectionHeading(section.headingPath);
177
177
  const effectiveKind = explicitSectionAc ? "acceptance" : sectionKind;
178
- // V4 显式 AC 标题行已在下方入口 emit(explicitSectionAc 分支);正文循环
179
- // 必须从标题行的下一行开始,否则同一标题行会被正文循环的 heading 分支
180
- // 再次 emit,产生结构性 duplicate(每个 AC 标题式片段出现两次)。
181
178
  const bodyStart = section.headingPath
182
- ? section.startLine + 1
179
+ ? section.startLine + (explicitSectionAc ? 0 : 1)
183
180
  : section.startLine;
184
181
  const bodyEnd = section.endLine;
185
182
  const bodyLines = lines.slice(Math.max(0, bodyStart - 1), Math.min(bodyEnd, lines.length));
@@ -441,17 +438,14 @@ export function buildFragmentInventory(input) {
441
438
  disposition = "non-goal";
442
439
  }
443
440
  else {
444
- // Non-goal/constraint/acceptance/objective sections are classified
445
- // above. An "other" section (背景 / 概述 / 说明 …) is contextual
446
- // description, not an executable requirement: even when it mentions
447
- // implementation verbs ("需要", "渲染", "组件"), it must not be
448
- // promoted to a high-risk unresolved executable fragment — that
449
- // blocks PRDs whose 背景 prose happens to use such words (merge
450
- // regression: "需要一个小组件" was flagged executable via 需要).
451
- // Explicit AC ids are already handled by the branches above, so
452
- // this branch is always contextual.
453
- disposition = "context-only";
454
- reason = "context-only fragment; excluded from canonical requirement coverage";
441
+ const executable = EXECUTABLE_HINT_RE.test(text);
442
+ disposition = executable ? "unresolved" : "context-only";
443
+ if (disposition === "unresolved") {
444
+ reason = "executable fragment outside recognized requirement/acceptance section";
445
+ }
446
+ else {
447
+ reason = "context-only fragment; excluded from canonical requirement coverage";
448
+ }
455
449
  }
456
450
  const priorId = seenText.get(text);
457
451
  if (priorId) {
@@ -5,9 +5,6 @@ import { ContractMutationError, applyTaskContract, logicalRevisionForState, obse
5
5
  import { TASK_CONTRACT_DRAFT_SCHEMA_VERSION } from "../contract/constants.js";
6
6
  import { getTaskContractPaths } from "../contract/paths.js";
7
7
  import { loadTaskConfig } from "../runtime.js";
8
- import { discoverFrontendProjectCapability, resolveFrontendSpecRootAliases, } from "../frontend-project-capability.js";
9
- import { classifyTaskDemand } from "../task-demand-routing.js";
10
- import { DEFAULT_FRONTEND_SPEC_ROOTS, extractDeclaredFrontendSpecRoots, } from "../../shared/openspec-spec.js";
11
8
  import { buildPrepareDraft } from "./build-draft.js";
12
9
  import { hasBlockingGaps, hasBlockingRisks, isFreshLegacyUnversioned, listPrepareGaps, appendLedgerGaps, } from "./completeness.js";
13
10
  import { detectProductArtifactMeta, isIntakeSoftGapCode, } from "./artifact-meta.js";
@@ -684,7 +681,7 @@ export async function prepareTaskSource(input) {
684
681
  facts = importedFacts ?? mergedSupplemental;
685
682
  }
686
683
  }
687
- let built = buildPrepareDraft({
684
+ const built = buildPrepareDraft({
688
685
  taskId,
689
686
  existingTaskConfig,
690
687
  baseDraft,
@@ -692,91 +689,6 @@ export async function prepareTaskSource(input) {
692
689
  flags: input.flags,
693
690
  references,
694
691
  });
695
- // Resolve an implicit frontend workflow before the first managed contract is
696
- // projected. Explicit taskKind (including explicit standard) remains a hard
697
- // contract; only a standard task with strong source/path/project evidence may
698
- // be promoted here. This keeps task.json, contract.json, and the first DAG
699
- // generation on the same workflow without a later hash-changing re-projection.
700
- if (built.draft.taskKind === "standard" &&
701
- !built.draft.taskKindExplicit) {
702
- const routingRequirement = [
703
- ...(sourceIntegrity?.documents ?? [])
704
- .map((document) => document.content)
705
- .filter((content) => Boolean(content?.trim())),
706
- ...(input.intent.kind === "facts" && input.intent.text
707
- ? [input.intent.text]
708
- : []),
709
- built.draft.requirement.objective,
710
- ...built.draft.requirement.scope,
711
- ...built.draft.requirement.acceptanceCriteria.map((item) => item.text),
712
- ].join("\n");
713
- let frontendProject;
714
- try {
715
- frontendProject = await discoverFrontendProjectCapability(repoRoot);
716
- }
717
- catch {
718
- // Capability discovery is advisory for routing. A failed probe must not
719
- // turn an otherwise valid standard contract preparation into an error.
720
- }
721
- const classification = classifyTaskDemand({
722
- title: built.draft.title,
723
- requirementMarkdown: routingRequirement,
724
- allowedPaths: built.draft.constraints.allowedPaths,
725
- frontendProject: frontendProject
726
- ? {
727
- framework: frontendProject.framework,
728
- evidencePaths: frontendProject.evidencePaths,
729
- }
730
- : undefined,
731
- });
732
- if (classification.kind === "frontend") {
733
- built = buildPrepareDraft({
734
- taskId,
735
- existingTaskConfig,
736
- baseDraft,
737
- facts,
738
- flags: {
739
- ...input.flags,
740
- taskKind: "frontend-implementation",
741
- },
742
- references,
743
- });
744
- }
745
- }
746
- // A user can explicitly name a non-default normative directory in the task
747
- // prompt (for example “规范目录 `design-system`”). Freeze that root into
748
- // the managed task config before the DAG exists; normal DAG selection consumes
749
- // the already-resolved task kind instead of mutating task.json later.
750
- if (built.draft.taskKind === "frontend-implementation") {
751
- // An imported PRD is materialized under sourceIntegrity rather than copied
752
- // into intent.text. Use both inputs so a `--prd` invocation can declare a
753
- // task-owned spec root just like supplemental free-form text can.
754
- const sourceText = [
755
- ...(sourceIntegrity?.documents ?? []).flatMap((document) => document.content ? [document.content] : []),
756
- ...(input.intent.kind === "facts" && input.intent.text
757
- ? [input.intent.text]
758
- : []),
759
- ].join("\n");
760
- const inferredRoots = extractDeclaredFrontendSpecRoots(sourceText);
761
- if (inferredRoots.length > 0) {
762
- const current = existingTaskConfig?.frontendOpenspec;
763
- const configuredRoots = current?.specRoots ?? [...DEFAULT_FRONTEND_SPEC_ROOTS];
764
- // Include roots declared by this source before resolving physical-target
765
- // aliases. A newly declared root may itself be a symlink (for example
766
- // `project-specs -> .../ai_doc`), so resolving aliases against only the
767
- // previous config cannot map `ai_doc/rules.md` back to project-specs.
768
- const provisionalRoots = [
769
- ...new Set([...configuredRoots, ...inferredRoots]),
770
- ].sort();
771
- const aliases = await resolveFrontendSpecRootAliases(repoRoot, provisionalRoots);
772
- const aliasMap = new Map(aliases.map(({ alias, logicalRoot }) => [alias, logicalRoot]));
773
- built.draft.frontendOpenspec = {
774
- policy: current?.policy ?? "cited",
775
- specRoots: [...new Set([...configuredRoots, ...inferredRoots.map((root) => aliasMap.get(root) ?? root)])].sort(),
776
- requiredReadPaths: current?.requiredReadPaths ?? [],
777
- };
778
- }
779
- }
780
692
  const { gaps, risks } = listPrepareGaps({
781
693
  draft: built.draft,
782
694
  state,
@@ -457,12 +457,8 @@ async function buildPrompt(input) {
457
457
  "Do NOT invent product behavior that is not supported by the documents.",
458
458
  "You MAY recommend an optional engineering block when the repo layout hint supports it:",
459
459
  "- allowedPaths / forbiddenPaths as minimal precise globs (e.g. source/packages/**/*.test.ts)",
460
- "- verifyCommands as real package scripts (e.g. pnpm -C source test); when acceptance criteria name a specific test file to run (e.g. 定向 vitest(test/.../xxx.test.ts)), emit the corresponding targeted command as its own entry (e.g. npx vitest run test/.../xxx.test.ts) instead of only the full-suite script — targeted commands are what a frontend implementation plan maps to behavior verification targets",
461
- "- taskKind when clearly implied, choosing from {standard / frontend-implementation / frontend-test / backend-test / knowledge-sync}:",
462
- " - frontend-implementation: the deliverable is a frontend component/page/UI feature (even when it ships with its own tests)",
463
- " - frontend-test: the deliverable is a browser/UI automation test suite for EXISTING functionality (no implementation work)",
464
- " - backend-test: pytest/backend test suite; standard: general repo implementation",
465
- " A task that IMPLEMENTS a component and adds tests for it is frontend-implementation, never frontend-test.",
460
+ "- verifyCommands as real package scripts (e.g. pnpm -C source test)",
461
+ "- taskKind when clearly implied (backend-test / frontend-test / standard / …)",
466
462
  "Prefer smallest correct write boundary; do not invent product paths that are not in the layout hint.",
467
463
  "Do NOT rewrite or suggest editing the original PRD files.",
468
464
  "Prefer explicit text; use provenance derived for rephrasing; use inferred only when clearly implied — if you must invent ACs, leave acceptanceCriteria empty so the system can stop for clarification.",
@@ -22,18 +22,6 @@ function slugifyName(value) {
22
22
  .replace(/-{2,}/g, "-");
23
23
  return slug || "requirement";
24
24
  }
25
- /** Stable identity of a manifest document for change detection. Timestamps and
26
- * byte sizes are excluded: identical content re-imported later must not appear
27
- * "changed" (the canonical hash includes manifest bytes). */
28
- function documentIdentity(doc) {
29
- return `${doc.role}|${doc.name}|${doc.materializedPath}|${doc.sha256}`;
30
- }
31
- function sameDocumentSet(left, right) {
32
- if (left.length !== right.length)
33
- return false;
34
- const rightIds = new Set(right.map(documentIdentity));
35
- return left.every((doc) => rightIds.has(documentIdentity(doc)));
36
- }
37
25
  function ensureUniqueReferenceName(existing, baseName, extension) {
38
26
  const used = new Set(existing);
39
27
  const candidate = `${baseName}${extension}`;
@@ -161,19 +149,10 @@ export async function importPrdDocument(input) {
161
149
  const documents = [...(existingManifest?.documents ?? [])].filter((entry) => entry.materializedPath !== materializedRelativePath);
162
150
  documents.push(document);
163
151
  documents.sort((left, right) => left.materializedPath.localeCompare(right.materializedPath));
164
- // Keep `updatedAt` stable across re-imports of the same content: the
165
- // canonical contract hash includes the manifest bytes, so a fresh
166
- // timestamp on every identical re-import would make the observed
167
- // canonical hash drift and fail task verification. Only bump it when the
168
- // document set actually changed (a new/changed materialized file).
169
- const documentSetChanged = !existingManifest ||
170
- !sameDocumentSet(existingManifest.documents, documents);
171
152
  const manifest = {
172
153
  schemaVersion: 1,
173
154
  taskId: input.taskId,
174
- updatedAt: documentSetChanged
175
- ? importedAt
176
- : (existingManifest?.updatedAt ?? importedAt),
155
+ updatedAt: importedAt,
177
156
  documents,
178
157
  };
179
158
  await writeSourceManifest(paths.sourceDir, manifest);
@@ -19,7 +19,9 @@ export function shouldPlayCompletionSound(input) {
19
19
  export function copyTextForMessage(input) {
20
20
  return input.code ?? input.text;
21
21
  }
22
- /** Empty sandbox means scripts, same-origin access, navigation and popups are denied. */
22
+ /** Project HTML may run its own UI scripts, but remains an opaque origin with
23
+ * forms, popups and top-level navigation denied by omission. */
24
+ export const HTML_PREVIEW_SANDBOX = "allow-scripts";
23
25
  export function previewSandbox() {
24
- return { sandbox: "" };
26
+ return { sandbox: HTML_PREVIEW_SANDBOX };
25
27
  }