@tea-agent/loop-agent 0.39.0-next.9 → 0.39.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 (288) hide show
  1. package/AGENTS.md +4 -1
  2. package/CHANGELOG.md +269 -69
  3. package/README.md +11 -5
  4. package/bin/loop-agent.js +7 -3
  5. package/dist/application/dag/generate-task-dag.js +9 -0
  6. package/dist/application/task-lifecycle/advance.js +16 -0
  7. package/dist/build-stamp.json +3 -3
  8. package/dist/cli/command-definitions.js +16 -5
  9. package/dist/cli/program.js +16 -2
  10. package/dist/cli/update/notifier.js +2 -2
  11. package/dist/cli/update/runtime-activity.js +1 -29
  12. package/dist/cli.js +2 -1
  13. package/dist/commands/dag-rerun.js +55 -1
  14. package/dist/commands/init-model-catalog.js +464 -0
  15. package/dist/commands/init-upgrade.js +265 -97
  16. package/dist/commands/init.js +428 -27
  17. package/dist/commands/inspect-next.js +8 -0
  18. package/dist/commands/task-advance.js +31 -0
  19. package/dist/executors/dag-pi-executor.js +124 -18
  20. package/dist/executors/pi-event-serializer.js +42 -1
  21. package/dist/executors/pi-executor.js +51 -0
  22. package/dist/executors/pi-extension-resolver.js +233 -0
  23. package/dist/executors/pi-playwright-cli-tool.js +74 -28
  24. package/dist/executors/pi-sdk-executor.js +187 -59
  25. package/dist/executors/shell-executor.js +555 -34
  26. package/dist/executors/shell-write-guard.js +7 -0
  27. package/dist/shared/dag-failure-category.js +138 -0
  28. package/dist/shared/dag-prompt-override.js +27 -0
  29. package/dist/shared/operator/capabilities.js +181 -27
  30. package/dist/shared/playwright-cli-command-policy.js +15 -0
  31. package/dist/shared/update/console-notifier.js +100 -0
  32. package/dist/{cli → shared}/update/npm-client.js +70 -15
  33. package/dist/{cli → shared}/update/state.js +41 -13
  34. package/dist/task/config-types.js +28 -0
  35. package/dist/task/contract/apply.js +11 -1
  36. package/dist/task/contract/constants.js +3 -0
  37. package/dist/task/contract/diff.js +26 -0
  38. package/dist/task/contract/hash.js +3 -0
  39. package/dist/task/contract/observe.js +25 -4
  40. package/dist/task/contract/paths.js +2 -1
  41. package/dist/task/contract/project.js +20 -1
  42. package/dist/task/contract/schema.js +8 -1
  43. package/dist/task/contract/transaction.js +12 -0
  44. package/dist/task/source-prepare/build-draft.js +15 -0
  45. package/dist/task/source-prepare/completeness.js +188 -0
  46. package/dist/task/source-prepare/fragment-inventory.js +474 -0
  47. package/dist/task/source-prepare/index.js +3 -0
  48. package/dist/task/source-prepare/ledger-reconciliation.js +127 -0
  49. package/dist/task/source-prepare/ledger-review.js +214 -0
  50. package/dist/task/source-prepare/ledger.js +545 -0
  51. package/dist/task/source-prepare/parse-intent.js +24 -4
  52. package/dist/task/source-prepare/prepare.js +262 -1
  53. package/dist/task/source-prepare/semantic-intake.js +19 -3
  54. package/dist/task/source-prepare/source-fidelity-pi.js +384 -0
  55. package/dist/task/source-prepare/types.js +22 -0
  56. package/dist/worker/cli.js +18 -2
  57. package/dist/worker/console/chat/deferred-turn.js +91 -0
  58. package/dist/worker/console/chat/mcp-inventory.js +221 -0
  59. package/dist/worker/console/chat/operation-card.js +8 -1
  60. package/dist/worker/console/chat/pi-console-config.js +81 -10
  61. package/dist/worker/console/chat/pi-runtime.js +165 -83
  62. package/dist/worker/console/chat/repo-walk.js +10 -1
  63. package/dist/worker/console/chat/routes.js +480 -55
  64. package/dist/worker/console/chat/semantic-activity.js +20 -8
  65. package/dist/worker/console/chat/session-store.js +146 -2
  66. package/dist/worker/console/chat/turn-process.js +10 -10
  67. package/dist/worker/console/console-handoff.js +82 -0
  68. package/dist/worker/console/console-update-and-init.js +115 -0
  69. package/dist/worker/console/console-update-runtime.js +84 -0
  70. package/dist/worker/console/dag-execution-receipt.js +33 -0
  71. package/dist/worker/console/draft-store.js +49 -0
  72. package/dist/worker/console/inspect-split.js +18 -0
  73. package/dist/worker/console/operation-run-facts.js +19 -3
  74. package/dist/worker/console/operation-store.js +1 -1
  75. package/dist/worker/console/operator-actions.js +320 -4
  76. package/dist/worker/console/operator-surface-health.js +1 -0
  77. package/dist/worker/console/operator-user-error.js +2 -2
  78. package/dist/worker/console/pi-readiness.js +5 -4
  79. package/dist/worker/console/prd-intake-bridge.js +13 -0
  80. package/dist/worker/console/recovery-cta.js +4 -4
  81. package/dist/worker/console/recovery-error-copy.js +4 -4
  82. package/dist/worker/console/routes.js +46 -2
  83. package/dist/worker/console/security.js +63 -9
  84. package/dist/worker/console/server.js +111 -7
  85. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-BLXFe4qI.js → abnfDiagram-N423BO3Z-CTx1TrNa.js} +1 -1
  86. package/dist/worker/console/static/assets/{arc-7iOJeqho.js → arc-B4i9cVxX.js} +1 -1
  87. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CYoyj5K7.js → architectureDiagram-T3A2C74G-BAXE8_Rl.js} +1 -1
  88. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-fK01JNlR.js → blockDiagram-VBNYF7ZC-C5Xh59at.js} +1 -1
  89. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-bzbw5D_Z.js → c4Diagram-5PPSVZJV-B_asOzAu.js} +1 -1
  90. package/dist/worker/console/static/assets/channel-Dj_4Moei.js +1 -0
  91. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-Cf6hJFFG.js → chunk-2GRJ4B5K-wRO_iRNc.js} +1 -1
  92. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DSFXR-et.js → chunk-2Q5K7J3B-ByOaSh_G.js} +1 -1
  93. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BagJechl.js → chunk-5RXB4S5H-DjLzudan.js} +1 -1
  94. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-E7QNMFaW.js → chunk-5VM5RSS4-JCNGkXYT.js} +1 -1
  95. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BG_eOBrC.js → chunk-6Q2QTUOP-BhrPXXMZ.js} +1 -1
  96. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-Bo42dqol.js → chunk-GF5L2VYU-TJ5JuEBT.js} +1 -1
  97. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-dibM-87v.js → chunk-JWPE2WC7-VVthn_mD.js} +1 -1
  98. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-Bytrp3Oe.js → chunk-KBJHAD2P-D60-Mny4.js} +1 -1
  99. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-DBABILrr.js → chunk-RYQCIY6F-zXv7aVye.js} +1 -1
  100. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DCUk5Pf9.js → chunk-XXDRQBXY-By9VQoi1.js} +1 -1
  101. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0YYAyCa.js +1 -0
  102. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0YYAyCa.js +1 -0
  103. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BlGE9v6E.js → cose-bilkent-JH36ORCC-C4zQLe-M.js} +1 -1
  104. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DGl5ewph.js → cynefin-VYW2F7L2-wh5N2ReN.js} +1 -1
  105. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-DsJ_SVH_.js → cynefinDiagram-MW4NZA55-Dlu5wIqs.js} +1 -1
  106. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-BIhjFdzv.js → dagre-VZM6K2ZE-CrDgthc6.js} +1 -1
  107. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Dmy1ctTb.js → diagram-7IWD3JNH-zN1clg27.js} +1 -1
  108. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DYCtWUF3.js → diagram-B4RE2ZJO-BN-o7J7-.js} +1 -1
  109. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BMZFHVd2.js → diagram-LBJQPF4R-C8SuPt0d.js} +1 -1
  110. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-b_U8gfaO.js → diagram-Q27KOJAE-BoizuHbZ.js} +1 -1
  111. package/dist/worker/console/static/assets/{diagram-UB23O5K3-Dzy_bn-I.js → diagram-UB23O5K3-BzUzXixG.js} +1 -1
  112. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DJCiMNEI.js → ebnfDiagram-BXEA7PRR-Ev3lA4Cf.js} +1 -1
  113. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-28lD016B.js → erDiagram-JOGREHBK-GALUzRbs.js} +1 -1
  114. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-DGyHJmIw.js → flowDiagram-UKHOOZJN-CZJN65Sb.js} +1 -1
  115. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-CzdwUjrO.js → ganttDiagram-PKOTCBZU-JLB9OESl.js} +1 -1
  116. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-D9bGwuo8.js → gitGraphDiagram-DS77QQ5N-CcvCr4GD.js} +1 -1
  117. package/dist/worker/console/static/assets/index-CW88Fjbw.js +406 -0
  118. package/dist/worker/console/static/assets/index-DP0ZJl39.css +1 -0
  119. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-LJgJUQFC.js → infoDiagram-6WML65LV-HG5z7aVg.js} +1 -1
  120. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-98LaB8zb.js → ishikawaDiagram-WSZJBQD7-BHEu9chR.js} +1 -1
  121. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-D-ISzwlQ.js → journeyDiagram-NVQOT4AX-Cp_Up8-a.js} +1 -1
  122. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-gfYOI-EL.js → kanban-definition-27J2QSJJ-DvVeY-em.js} +1 -1
  123. package/dist/worker/console/static/assets/{linear-CyntZgKV.js → linear-aGmcjgTn.js} +1 -1
  124. package/dist/worker/console/static/assets/{mermaid.core-BBOR7dg0.js → mermaid.core-Biyo-tqA.js} +5 -5
  125. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CQAgwPMk.js → mindmap-definition-FAOFIHXS-DyxY2pIb.js} +1 -1
  126. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-DkMiZFuV.js → pegDiagram-VL7TDLO6-CkdGuc50.js} +1 -1
  127. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-DLNXa_0J.js → pieDiagram-7S7Q4E2Y-NNQI9xVR.js} +1 -1
  128. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-Dc7bdzjm.js → quadrantDiagram-CIZ2JOQS-PAJkuz_G.js} +1 -1
  129. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BxMB0QqW.js → railroadDiagram-AXF67PYL-ZwrQod0O.js} +1 -1
  130. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-FjumoKn4.js → requirementDiagram-LRYGKXZP-D3ZfrzM2.js} +1 -1
  131. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-CkhKc_E3.js → sankeyDiagram-W5VNT64P-DDGFmWk5.js} +1 -1
  132. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DoBWqTTH.js → sequenceDiagram-SI44F4Z6-DO6mmXTA.js} +1 -1
  133. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-CQeh_YeE.js → sizeCapture-X5ZJPWSS-DMbCQiJt.js} +1 -1
  134. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-LuHmFW-I.js → stateDiagram-OKZ733FA-Di_YUEfC.js} +1 -1
  135. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrdDvela.js +1 -0
  136. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CHwbDctY.js → swimlanes-SLNWSIFB-Bn2PphNJ.js} +2 -2
  137. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DPkEAULl.js +8 -0
  138. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-CoMngk0X.js → timeline-definition-Z64GVDOM-DPh8pRsp.js} +1 -1
  139. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-CURYbtbO.js → vennDiagram-T6HMQDX7-GMfl26pW.js} +1 -1
  140. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-BdqSECjU.js → wardleyDiagram-T6FBY63Y-DTlmVrmF.js} +1 -1
  141. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DbMUYuAg.js → xychartDiagram-ELKLHX3M-YGBjKAS5.js} +1 -1
  142. package/dist/worker/console/static/index.html +2 -2
  143. package/dist/worker/console/static-src/app/console-types.js +40 -1
  144. package/dist/worker/console/static-src/app/useOperatorActions.js +6 -1
  145. package/dist/worker/console/static-src/app/useRecoveryActions.js +2 -2
  146. package/dist/worker/console/static-src/app/useRecoveryConsole.js +38 -2
  147. package/dist/worker/console/static-src/app/useRunProgress.js +46 -0
  148. package/dist/worker/console/static-src/app/useTaskWizard.js +73 -1
  149. package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
  150. package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +74 -26
  151. package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
  152. package/dist/worker/console/static-src/operator-chat/mutation-gate.js +1 -1
  153. package/dist/worker/console/static-src/operator-chat/open-preview-in-browser.js +328 -0
  154. package/dist/worker/console/static-src/operator-chat/resource-diagnostics.js +204 -0
  155. package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +8 -1
  156. package/dist/worker/console/static-src/operator-chat/turn-submission.js +54 -0
  157. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +3 -0
  158. package/dist/worker/console/static-src/operator-chat/useChatStream.js +237 -11
  159. package/dist/worker/console/static-src/operator-chat/useChatThread.js +50 -22
  160. package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
  161. package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +26 -1
  162. package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
  163. package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
  164. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
  165. package/dist/worker/loop-agent/loop-agent-client.js +7 -3
  166. package/dist/worker/materialize/harness-task-lineage.js +5 -2
  167. package/dist/worker/observability/init-runtime-activity.js +26 -0
  168. package/dist/worker/observability/read-model.js +22 -0
  169. package/dist/worker/observe/node-input.js +160 -3
  170. package/dist/worker/observe/node-process.js +377 -0
  171. package/dist/worker/observe/routes.js +224 -3
  172. package/dist/worker/observe/shell-handler-keys.js +34 -0
  173. package/dist/worker/observe/static/api.js +67 -1
  174. package/dist/worker/observe/static/constants.js +8 -1
  175. package/dist/worker/observe/static/dag-history-labels.js +4 -0
  176. package/dist/worker/observe/static/format.js +60 -0
  177. package/dist/worker/observe/static/index.html +5 -0
  178. package/dist/worker/observe/static/markdown-render.js +20 -1
  179. package/dist/worker/observe/static/operator-chrome.js +4 -0
  180. package/dist/worker/observe/static/prompt-restart-candidates.d.ts +18 -0
  181. package/dist/worker/observe/static/prompt-restart-candidates.js +36 -0
  182. package/dist/worker/observe/static/state.js +13 -2
  183. package/dist/worker/observe/static/styles.css +85 -0
  184. package/dist/worker/observe/static/views/dag-inspector.js +912 -8
  185. package/dist/worker/observe/static/views/dag.js +8 -1
  186. package/dist/worker/observe/static/views/failures.js +5 -2
  187. package/dist/worker/observe/static/views/session-timeline.js +78 -9
  188. package/dist/worker/observe/static/views/task.js +55 -0
  189. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +856 -54
  190. package/dist/workflows/dag/backend-test-case-manifest.js +4 -0
  191. package/dist/workflows/dag/backend-test-execution-contract.js +18 -9
  192. package/dist/workflows/dag/backend-test-gap-fill.js +205 -0
  193. package/dist/workflows/dag/backend-test-intake-context.js +32 -0
  194. package/dist/workflows/dag/backend-test-layout.js +133 -0
  195. package/dist/workflows/dag/backend-test-markdown-workflow.js +343 -33
  196. package/dist/workflows/dag/backend-test-module-stem.js +5 -0
  197. package/dist/workflows/dag/backend-test-pytest-collection.js +454 -36
  198. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  199. package/dist/workflows/dag/backend-test-scenario-param.js +884 -140
  200. package/dist/workflows/dag/backend-test-scenario-partitions.js +321 -0
  201. package/dist/workflows/dag/backend-test-writer-completeness.js +110 -61
  202. package/dist/workflows/dag/contract-output-registry.js +15 -0
  203. package/dist/workflows/dag/contract-validator-registrations.js +3 -1
  204. package/dist/workflows/dag/convergence/controller.js +141 -0
  205. package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
  206. package/dist/workflows/dag/dynamic-runtime/map.js +25 -9
  207. package/dist/workflows/dag/dynamic-runtime/shared.js +1 -1
  208. package/dist/workflows/dag/failure-category.js +7 -116
  209. package/dist/workflows/dag/frontend-implementation-contract.js +465 -6
  210. package/dist/workflows/dag/frontend-plan-render.js +24 -0
  211. package/dist/workflows/dag/frontend-prewrite-gate.js +293 -84
  212. package/dist/workflows/dag/frontend-repair.js +14 -0
  213. package/dist/workflows/dag/frontend-review-context.js +92 -10
  214. package/dist/workflows/dag/frontend-risk.js +15 -2
  215. package/dist/workflows/dag/frontend-test-case-checklist.js +30 -4
  216. package/dist/workflows/dag/frontend-test-case-manifest.js +11 -4
  217. package/dist/workflows/dag/frontend-test-case-quality.js +11 -16
  218. package/dist/workflows/dag/frontend-test-environment-probe.js +230 -0
  219. package/dist/workflows/dag/frontend-test-html-report.js +3 -1
  220. package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
  221. package/dist/workflows/dag/frontend-test-layout.js +159 -0
  222. package/dist/workflows/dag/frontend-test-markdown.js +61 -0
  223. package/dist/workflows/dag/frontend-test-result-contract.js +188 -42
  224. package/dist/workflows/dag/frontend-test-standard-scenarios.js +70 -0
  225. package/dist/workflows/dag/frontend-verification-trace.js +29 -4
  226. package/dist/workflows/dag/init-hybrid.js +1019 -209
  227. package/dist/workflows/dag/node-execution.js +228 -15
  228. package/dist/workflows/dag/prompt.js +60 -1
  229. package/dist/workflows/dag/rerun-feedback.js +212 -0
  230. package/dist/workflows/dag/rerun-plan.js +224 -27
  231. package/dist/workflows/dag/rerun-run.js +61 -6
  232. package/dist/workflows/dag/rerun-task.js +61 -2
  233. package/dist/workflows/dag/retry-policy.js +109 -0
  234. package/dist/workflows/dag/structured-output-repair.js +712 -0
  235. package/dist/workflows/dag/types.js +185 -12
  236. package/dist/workflows/dag/validate.js +64 -20
  237. package/docs/README.md +1 -0
  238. package/docs/architecture/evolution.md +45 -0
  239. package/docs/init-surface.manifest.json +6 -0
  240. package/docs/operations/README.md +1 -1
  241. package/docs/operations/local-development-environment.md +1 -5
  242. package/docs/skills/vetted-skill-registry.md +14 -0
  243. package/docs/templates/README.md +2 -2
  244. package/docs/templates/agent-dag.schema.json +44 -0
  245. package/docs/templates/backend-test-dag.json +60 -35
  246. package/docs/templates/frontend-implementation-contract.schema.json +681 -24
  247. package/docs/templates/frontend-test-case-checklist.md +2 -2
  248. package/docs/templates/frontend-test-dag.json +8 -10
  249. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +1 -1
  250. package/docs/templates/init-managed-agents.md +13 -3
  251. package/harness.json +6 -4
  252. package/package.json +12 -4
  253. package/scripts/next-info.mjs +356 -0
  254. package/scripts/next-publish-gate.mjs +238 -0
  255. package/scripts/release-source-binding.mjs +251 -0
  256. package/skills/analyze-product-requirements/SKILL.md +8 -5
  257. package/skills/analyze-product-requirements/references/acceptance-criteria.md +1 -1
  258. package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +10 -6
  259. package/skills/analyze-product-requirements/references/example.md +50 -0
  260. package/skills/analyze-product-requirements/references/forward-test-cases.md +11 -7
  261. package/skills/analyze-product-requirements/references/kb-integration.md +5 -5
  262. package/skills/analyze-product-requirements/references/product-analysis-schema.md +8 -4
  263. package/skills/analyze-product-requirements/references/product-requirement-schema.md +2 -2
  264. package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +1 -1
  265. package/skills/analyze-product-requirements/scripts/test-validators.mjs +11 -1
  266. package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +20 -1
  267. package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +9 -0
  268. package/skills/codebase-scout/SKILL.md +1 -1
  269. package/skills/fe-test-ui-scout/SKILL.md +65 -0
  270. package/skills/fe-test-ui-scout/references/ledger-schema.md +62 -0
  271. package/skills/fe-test-ui-scout/references/recon-protocol.md +54 -0
  272. package/skills/frontend-implementation/references/node-contracts.md +2 -2
  273. package/skills/improve-codebase-architecture/SKILL.md +81 -0
  274. package/skills/improve-codebase-architecture/deepening.md +37 -0
  275. package/skills/improve-codebase-architecture/html-report.md +123 -0
  276. package/skills/improve-codebase-architecture/interface-design.md +44 -0
  277. package/skills/improve-codebase-architecture/language.md +53 -0
  278. package/skills/loop-agent/references/command-reference.md +11 -4
  279. package/skills/loop-agent/references/hybrid-dag.md +7 -0
  280. package/skills/playwright-cli/SKILL.md +23 -1
  281. package/skills/playwright-cli-case-generator/SKILL.md +29 -8
  282. package/dist/worker/console/static/assets/channel-BBOTJHvD.js +0 -1
  283. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Cm8Yf8tD.js +0 -1
  284. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Cm8Yf8tD.js +0 -1
  285. package/dist/worker/console/static/assets/index-B-qWGThd.js +0 -325
  286. package/dist/worker/console/static/assets/index-C-xRgY_0.css +0 -1
  287. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DZihfdKc.js +0 -1
  288. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CKnXCjHX.js +0 -8
@@ -1,6 +1,14 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { ensureUniqueDocumentNames, operatorRequestFits, operatorRequestTooLargeMessage, } from "../prd-file-import.js";
3
3
  import { requestId, WORKFLOW_OPTIONS, } from "./console-types.js";
4
+ export async function fetchLedgerSummary(taskId, fetchImpl) {
5
+ const impl = fetchImpl ?? fetch;
6
+ const response = await impl(`/api/tasks/${encodeURIComponent(taskId)}/ledger`, { credentials: "same-origin" });
7
+ if (!response.ok)
8
+ return { ok: false };
9
+ const summary = (await response.json());
10
+ return { ok: true, summary };
11
+ }
4
12
  /** Happy Path task wizard: import-prd → interview → contract → dag-confirm →
5
13
  * run. Owns task identity, interview projection and contract preflight/apply. */
6
14
  export function useTaskWizard(params) {
@@ -24,16 +32,27 @@ export function useTaskWizard(params) {
24
32
  const [contractDiffSummary, setContractDiffSummary] = useState(null);
25
33
  const [contractApplied, setContractApplied] = useState(false);
26
34
  const [spineOk, setSpineOk] = useState(null);
35
+ const [ledgerLoading, setLedgerLoading] = useState(false);
36
+ const [ledgerError, setLedgerError] = useState(null);
37
+ const [ledgerSummary, setLedgerSummary] = useState(null);
27
38
  const [contractPreflightKey, setContractPreflightKey] = useState(null);
28
39
  const contractPreflightRunning = useRef(false);
40
+ /** Epoch guard for ledger fetches: only the newest request may write wizard
41
+ * state, so a concurrent in-flight preflight response can never overwrite
42
+ * a fresh post-apply result (AC-001). */
43
+ const ledgerFetchEpoch = useRef(0);
29
44
  const resetContractLanding = useCallback(() => {
30
45
  setContractValidateOk(null);
31
46
  setContractValidateSummary(null);
32
47
  setContractDiffSummary(null);
33
48
  setContractApplied(false);
34
49
  setSpineOk(null);
50
+ setLedgerLoading(false);
51
+ setLedgerError(null);
52
+ setLedgerSummary(null);
35
53
  setContractPreflightKey(null);
36
54
  contractPreflightRunning.current = false;
55
+ ledgerFetchEpoch.current = 0;
37
56
  }, []);
38
57
  const enterContractStep = useCallback(() => {
39
58
  resetContractLanding();
@@ -56,6 +75,39 @@ export function useTaskWizard(params) {
56
75
  : "访谈已完成:草稿已绑定完整评估结果");
57
76
  }
58
77
  }, [enterContractStep, setOpMessage]);
78
+ /** Epoch-guarded shared ledger refresh used by both the contract-step
79
+ * preflight and the post-apply re-GET. `failureSemantics` keeps the
80
+ * preflight five-state behavior (non-ok → empty state, no error) while the
81
+ * post-apply refresh treats a non-ok/network failure as a safe-degrade
82
+ * error per AC-001. */
83
+ const refreshLedgerState = useCallback(async (id, failureSemantics) => {
84
+ const epoch = ++ledgerFetchEpoch.current;
85
+ setLedgerLoading(true);
86
+ setLedgerError(null);
87
+ try {
88
+ const outcome = await fetchLedgerSummary(id);
89
+ if (ledgerFetchEpoch.current !== epoch)
90
+ return;
91
+ if (!outcome.ok) {
92
+ setLedgerSummary(null);
93
+ if (failureSemantics) {
94
+ setLedgerError("ledger 接口不可达(安全降级)");
95
+ }
96
+ return;
97
+ }
98
+ setLedgerSummary(outcome.summary);
99
+ }
100
+ catch {
101
+ if (ledgerFetchEpoch.current !== epoch)
102
+ return;
103
+ setLedgerError("ledger 接口不可达(安全降级)");
104
+ setLedgerSummary(null);
105
+ }
106
+ finally {
107
+ if (ledgerFetchEpoch.current === epoch)
108
+ setLedgerLoading(false);
109
+ }
110
+ }, []);
59
111
  const runContractPreflight = useCallback(async (force = false) => {
60
112
  const id = taskId.trim();
61
113
  if (!id)
@@ -74,6 +126,9 @@ export function useTaskWizard(params) {
74
126
  setContractDiffSummary(null);
75
127
  setSpineOk(null);
76
128
  setContractApplied(false);
129
+ // Shared epoch-guarded refresh preserves the five-state semantics:
130
+ // non-ok → empty state, network failure → safe-degrade error.
131
+ await refreshLedgerState(id, false);
77
132
  try {
78
133
  const validateBody = await runAction("contractValidate", {
79
134
  taskId: id,
@@ -101,6 +156,7 @@ export function useTaskWizard(params) {
101
156
  contractPreflightKey,
102
157
  contractValidateOk,
103
158
  isActionSuccess,
159
+ refreshLedgerState,
104
160
  runAction,
105
161
  setOpMessage,
106
162
  summarizeEnvelope,
@@ -116,6 +172,11 @@ export function useTaskWizard(params) {
116
172
  return;
117
173
  }
118
174
  setContractApplied(true);
175
+ // AC-001: re-GET the read-only ledger right after apply succeeds and
176
+ // write the latest summary BEFORE spineCheck/setStep, so the first
177
+ // dag-confirm frame shows post-apply statistics (never a loading/empty
178
+ // flash); refresh failure safe-degrades via ledgerError.
179
+ await refreshLedgerState(id, true);
119
180
  const spineBody = await runAction("spineCheck", { taskId: id });
120
181
  if (isActionSuccess(spineBody)) {
121
182
  setSpineOk(true);
@@ -125,7 +186,15 @@ export function useTaskWizard(params) {
125
186
  }
126
187
  setSpineOk(false);
127
188
  setOpMessage("契约已应用,但 Spine 审计未通过:可重试 Spine");
128
- }, [assessmentId, isActionSuccess, runAction, setOpMessage, setStep, taskId]);
189
+ }, [
190
+ assessmentId,
191
+ isActionSuccess,
192
+ refreshLedgerState,
193
+ runAction,
194
+ setOpMessage,
195
+ setStep,
196
+ taskId,
197
+ ]);
129
198
  const retrySpineOnly = useCallback(async () => {
130
199
  const id = taskId.trim();
131
200
  if (!id)
@@ -282,6 +351,9 @@ export function useTaskWizard(params) {
282
351
  contractValidateOk,
283
352
  contractValidateSummary,
284
353
  contractDiffSummary,
354
+ ledgerLoading,
355
+ ledgerError,
356
+ ledgerSummary,
285
357
  contractApplied,
286
358
  spineOk,
287
359
  applyInterviewPayload,
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Operator-facing recovery advice per normalized DAG failure category
3
+ * (mirrors DAG_NORMALIZED_FAILURE_CATEGORIES). The task journey card used to
4
+ * stop at "原因分类为 X" without telling the operator what to do next; this
5
+ * maps each class to the concrete next move, aligned with the Recovery
6
+ * workspace CTAs (node rerun / reconcile / models page).
7
+ */
8
+ const FAILURE_CATEGORY_ADVICE = {
9
+ validation: "节点输出未通过契约或门禁校验。可在恢复页从失败节点重跑;若错误指向任务契约(如验证命令、Mock 策略),先修正任务配置并重新生成 DAG。",
10
+ executor: "执行器或模型提供方调用失败(网络、配额或运行时错误)。稍后可在恢复页从失败节点重跑;反复出现请到「模型与认证」页检查配置与凭据。",
11
+ "write-guard": "写入越过了授权边界(writeSet / allowedPaths)。检查计划中的写入路径是否越界,修正后从失败节点重跑。",
12
+ timeout: "节点执行超时。可在恢复页从失败节点重跑;反复超时建议缩小任务范围或排查卡住的命令。",
13
+ auth: "模型或服务认证失败。请先到「模型与认证」页检查 API Key 与模型配置,再从失败节点重跑。",
14
+ "human-required": "节点正在等待人工审批。完成审批后该节点可继续执行;也可在恢复页查看对账状态。",
15
+ "human-rejected": "人工审批被拒绝。请调整任务描述或契约后重新发起任务。",
16
+ "shell-command": "验证/构建命令以非零退出。进入 DAG 查看命令输出定位具体失败,修复后从失败节点重跑。",
17
+ "static-error": "静态检查(typecheck / lint 等)失败。修复对应代码错误后从失败节点重跑。",
18
+ "decision-envelope": "决策与证据不匹配(决策包络校验失败)。进入 DAG 查看节点决策依据,修正后重跑。",
19
+ unknown: "失败原因未归类。进入 DAG 查看节点详情,或在恢复页使用对账 / 诊断入口。",
20
+ };
21
+ export function failureCategoryAdvice(category) {
22
+ if (!category)
23
+ return undefined;
24
+ return FAILURE_CATEGORY_ADVICE[category];
25
+ }
@@ -10,7 +10,7 @@ import { parseAssistantContent } from "../../chat/assistant-content.js";
10
10
  * original request would have. `assistantId` is the in-flight assistant
11
11
  * message id to patch for streaming text; reconnect creates one if none. */
12
12
  export function createChatSseEventApplier(deps) {
13
- const { refs, onReconcile, setError, setInterview, setHumanGateCards, setArtifactCards, setStreaming, setStreamingAssistantId, setUnread, setOperationCards, setUsage, setMessages, setToolCalls, } = deps;
13
+ const { refs, onReconcile, setError, setInterview, setHumanGateCards, setArtifactCards, setStreaming, setTurnPhase = () => undefined, setDeferredTurn = () => undefined, setStreamingAssistantId, setUnread, setOperationCards, setUsage, setMessages, setToolCalls, } = deps;
14
14
  return (eventName, data, assistantId, options) => {
15
15
  if (options?.generation !== undefined &&
16
16
  refs.sessionGenerationRef.current !== options.generation)
@@ -49,6 +49,41 @@ export function createChatSseEventApplier(deps) {
49
49
  const eventAt = typeof data.at === "string" && Number.isFinite(Date.parse(data.at))
50
50
  ? Date.parse(data.at)
51
51
  : Date.now();
52
+ if (eventName === "queue_update") {
53
+ const revision = typeof payload.revision === "number" ? payload.revision : -1;
54
+ setDeferredTurn((current) => {
55
+ if (current && revision < current.revision)
56
+ return current;
57
+ return payload.deferredTurn && typeof payload.deferredTurn === "object"
58
+ ? payload.deferredTurn
59
+ : null;
60
+ });
61
+ return;
62
+ }
63
+ if (eventName === "user_message") {
64
+ const message = payload.message && typeof payload.message === "object"
65
+ ? payload.message
66
+ : null;
67
+ if (message &&
68
+ typeof message.id === "string" &&
69
+ typeof message.text === "string") {
70
+ const createdAt = typeof message.at === "string" && Number.isFinite(Date.parse(message.at))
71
+ ? Date.parse(message.at)
72
+ : Date.now();
73
+ setMessages((messages) => messages.some((item) => item.id === message.id)
74
+ ? messages
75
+ : [
76
+ ...messages,
77
+ {
78
+ id: message.id,
79
+ role: "user",
80
+ text: message.text,
81
+ createdAt,
82
+ },
83
+ ]);
84
+ }
85
+ return;
86
+ }
52
87
  if (turnId &&
53
88
  (eventName === "agent_start" || eventName === "message_update") &&
54
89
  refs.settledTurnIdsRef.current.has(turnId)) {
@@ -153,6 +188,7 @@ export function createChatSseEventApplier(deps) {
153
188
  }
154
189
  refs.streamingRef.current = true;
155
190
  setStreaming(true);
191
+ setTurnPhase("running");
156
192
  setStreamingAssistantId(resolvedAssistantId);
157
193
  return;
158
194
  }
@@ -168,6 +204,7 @@ export function createChatSseEventApplier(deps) {
168
204
  refs.activeTurnIdRef.current = null;
169
205
  refs.streamingRef.current = false;
170
206
  setStreaming(false);
207
+ setTurnPhase("idle");
171
208
  setStreamingAssistantId(null);
172
209
  if (eventName === "agent_settled" &&
173
210
  !replay &&
@@ -175,19 +212,30 @@ export function createChatSseEventApplier(deps) {
175
212
  document.hidden) {
176
213
  setUnread((current) => current + 1);
177
214
  }
178
- setMessages((m) => m.filter((msg) => !(msg.id === resolvedAssistantId &&
179
- msg.role === "assistant" &&
180
- !msg.text.trim())));
181
- // Close out tool calls that never got a tool_result (abort/fail):
182
- // without this the process rail keeps showing "运行中" forever even
183
- // though the turn is over. Match by turnId when the frame carries one
184
- // (covers tools attributed to remapped/stale assistant ids); fall back
185
- // to the resolved assistant id otherwise.
186
- setToolCalls((prev) => prev.map((t) => t.status === "running" &&
187
- ((turnId !== undefined && t.turnId === turnId) ||
188
- t.assistantMessageId === resolvedAssistantId)
189
- ? { ...t, status: "error", finishedAt: Date.now() }
190
- : t));
215
+ // Close dangling running tools first so the empty-bubble decision can
216
+ // see whether this assistant still owns any cards.
217
+ let assistantOwnsTools = false;
218
+ setToolCalls((prev) => {
219
+ assistantOwnsTools = prev.some((t) => t.assistantMessageId === resolvedAssistantId);
220
+ return prev.map((t) => t.status === "running" &&
221
+ ((turnId !== undefined && t.turnId === turnId) ||
222
+ t.assistantMessageId === resolvedAssistantId)
223
+ ? { ...t, status: "error", finishedAt: Date.now() }
224
+ : t);
225
+ });
226
+ // Drop only a true placeholder. An empty bubble that still owns tools
227
+ // (or has content blocks) is the grouping anchor; deleting it orphans
228
+ // the previous turn's bash cards onto the next prompt.
229
+ setMessages((m) => m.filter((msg) => {
230
+ if (msg.id !== resolvedAssistantId || msg.role !== "assistant") {
231
+ return true;
232
+ }
233
+ if (msg.text.trim())
234
+ return true;
235
+ if (msg.content && msg.content.length > 0)
236
+ return true;
237
+ return assistantOwnsTools;
238
+ }));
191
239
  return;
192
240
  }
193
241
  if (eventName === "operation-ref" || eventName === "operation-status") {
@@ -227,6 +275,15 @@ export function createChatSseEventApplier(deps) {
227
275
  const cacheWrite = sample.cacheWriteTokens ?? 0;
228
276
  const total = sample.totalTokens ?? input + output + cacheRead + cacheWrite;
229
277
  const cu = sample.contextUsage;
278
+ const nextContext = cu && typeof cu === "object"
279
+ ? {
280
+ tokens: typeof cu.tokens === "number" ? cu.tokens : null,
281
+ contextWindow: typeof cu.contextWindow === "number"
282
+ ? cu.contextWindow
283
+ : 0,
284
+ percent: typeof cu.percent === "number" ? cu.percent : null,
285
+ }
286
+ : current.contextUsage;
230
287
  return {
231
288
  inputTokens: current.inputTokens + input,
232
289
  outputTokens: current.outputTokens + output,
@@ -236,18 +293,9 @@ export function createChatSseEventApplier(deps) {
236
293
  cost: sample.cost === undefined
237
294
  ? current.cost
238
295
  : (current.cost ?? 0) + sample.cost,
239
- // Context usage is a live snapshot, not an accumulator: replace it.
240
- ...(cu && typeof cu === "object"
241
- ? {
242
- contextUsage: {
243
- tokens: typeof cu.tokens === "number" ? cu.tokens : null,
244
- contextWindow: typeof cu.contextWindow === "number"
245
- ? cu.contextWindow
246
- : 0,
247
- percent: typeof cu.percent === "number" ? cu.percent : null,
248
- },
249
- }
250
- : {}),
296
+ // Context fill is independent of per-message token deltas. Keep the
297
+ // last known snapshot unless this event carries a fresh one.
298
+ ...(nextContext ? { contextUsage: nextContext } : {}),
251
299
  };
252
300
  });
253
301
  return;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Pure composer input-history state machine for Operator Chat.
3
+ *
4
+ * Extracted so ArrowUp/ArrowUp recall, unsent-draft retention and history
5
+ * recording can be unit-tested without mounting the React composer.
6
+ */
7
+ export const INPUT_HISTORY_LIMIT = 100;
8
+ export function createInputHistoryState() {
9
+ return { entries: [], index: -1, draft: "" };
10
+ }
11
+ /** Record one sent text and reset browsing back to the present draft. */
12
+ export function recordInputHistoryEntry(state, text) {
13
+ if (!text.trim())
14
+ return state;
15
+ if (state.entries[state.entries.length - 1] === text) {
16
+ return state.index === -1 ? state : { ...state, index: -1, draft: "" };
17
+ }
18
+ const entries = [...state.entries, text].slice(-INPUT_HISTORY_LIMIT);
19
+ return { entries, index: -1, draft: "" };
20
+ }
21
+ /** Leave browse mode (manual typing edits the recalled text in place). */
22
+ export function resetInputHistoryBrowsing(state) {
23
+ return state.index === -1 ? state : { ...state, index: -1 };
24
+ }
25
+ /**
26
+ * Recall an earlier input with the arrow keys (terminal-style).
27
+ *
28
+ * Up only engages while the caret sits on the first line and Down while it
29
+ * sits on the last line, so plain caret movement inside multi-line drafts is
30
+ * never swallowed. The unsent draft is stashed when browsing leaves the
31
+ * present position and restored when Down walks past the newest entry.
32
+ */
33
+ export function navigateInputHistory(state, direction, context) {
34
+ const { text, caretStart, caretEnd } = context;
35
+ if (state.entries.length === 0)
36
+ return { handled: false };
37
+ if (direction === "up") {
38
+ if (text.slice(0, caretStart).includes("\n"))
39
+ return { handled: false };
40
+ if (state.index === -1) {
41
+ const index = state.entries.length - 1;
42
+ return {
43
+ handled: true,
44
+ state: { ...state, index, draft: text },
45
+ text: state.entries[index],
46
+ };
47
+ }
48
+ if (state.index === 0) {
49
+ // Already at the oldest entry: stay there (terminal behaviour).
50
+ return { handled: true, state, text: state.entries[0] };
51
+ }
52
+ const index = state.index - 1;
53
+ return {
54
+ handled: true,
55
+ state: { ...state, index },
56
+ text: state.entries[index],
57
+ };
58
+ }
59
+ if (state.index === -1)
60
+ return { handled: false };
61
+ if (text.slice(caretEnd).includes("\n"))
62
+ return { handled: false };
63
+ if (state.index >= state.entries.length - 1) {
64
+ return {
65
+ handled: true,
66
+ state: { ...state, index: -1 },
67
+ text: state.draft,
68
+ };
69
+ }
70
+ const index = state.index + 1;
71
+ return {
72
+ handled: true,
73
+ state: { ...state, index },
74
+ text: state.entries[index],
75
+ };
76
+ }
@@ -30,7 +30,7 @@ export function isStaleTokenFailure(code) {
30
30
  /** Chinese, actionable copy for mutation-gate rejections. */
31
31
  export function describeMutationGateFailure(code) {
32
32
  if (isStaleTokenFailure(code)) {
33
- return "页面已过期(控制台已重启),请刷新页面(F5)后重试。";
33
+ return "页面凭证已失效(控制台可能已重启),请刷新页面(F5)后重试。";
34
34
  }
35
35
  if (code === "host-not-loopback") {
36
36
  return "请求主机校验失败:非回环绑定时要求 Host 头,请刷新页面或检查访问地址。";