@tea-agent/loop-agent 0.41.1 → 0.42.0-next.10

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 (302) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +397 -5
  3. package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
  4. package/dist/adapters/context-transfer/pi-session.js +61 -0
  5. package/dist/application/dag/generate-task-dag.js +75 -19
  6. package/dist/application/dag/run-dag.js +41 -0
  7. package/dist/application/task-lifecycle/advance.js +24 -5
  8. package/dist/application/task-lifecycle/observe.js +171 -17
  9. package/dist/application/task-lifecycle/plan-transitions.js +42 -7
  10. package/dist/application/task-lifecycle/recommendations.js +13 -2
  11. package/dist/build-stamp.json +3 -3
  12. package/dist/cli/command-definitions.js +19 -0
  13. package/dist/cli/program.js +29 -2
  14. package/dist/commands/client-recovery.js +3 -0
  15. package/dist/commands/dag-artifact.js +284 -0
  16. package/dist/commands/dag-context.js +184 -0
  17. package/dist/commands/dag-follow-up.js +138 -0
  18. package/dist/commands/dag-rerun-task.js +2 -0
  19. package/dist/commands/dag-rerun.js +206 -1
  20. package/dist/commands/init.js +27 -1
  21. package/dist/commands/task-advance.js +19 -0
  22. package/dist/executors/dag-pi-executor.js +4013 -86
  23. package/dist/executors/pi-executor.js +15 -4
  24. package/dist/executors/pi-read-budget-policy.js +239 -0
  25. package/dist/executors/pi-sdk-executor.js +3 -0
  26. package/dist/executors/shell-executor.js +978 -188
  27. package/dist/executors/shell-write-guard.js +7 -0
  28. package/dist/{worker → infrastructure}/console/app-data.js +4 -0
  29. package/dist/infrastructure/console/artifact-revision-store.js +430 -0
  30. package/dist/infrastructure/console/context-export-store.js +160 -0
  31. package/dist/infrastructure/console/dir-lock.js +132 -0
  32. package/dist/infrastructure/console/operation-store.js +417 -0
  33. package/dist/infrastructure/harness/artifact-store.js +10 -1
  34. package/dist/infrastructure/harness/atomic-write.js +12 -2
  35. package/dist/shared/context-transfer/artifact-revision.js +172 -0
  36. package/dist/shared/context-transfer.js +418 -0
  37. package/dist/shared/dag-failure-category.js +12 -0
  38. package/dist/shared/openspec-spec.js +70 -4
  39. package/dist/shared/operator/capabilities.js +21 -0
  40. package/dist/shared/operator/safe-run-summary.js +1 -0
  41. package/dist/shared/path-safety.js +93 -0
  42. package/dist/shared/preview.js +28 -4
  43. package/dist/task/config-types.js +107 -6
  44. package/dist/task/contract/adopt.js +4 -0
  45. package/dist/task/contract/import-revision.js +4 -0
  46. package/dist/task/contract/project.js +3 -0
  47. package/dist/task/contract/schema.js +2 -1
  48. package/dist/task/frontend-project-capability.js +203 -20
  49. package/dist/task/runtime.js +5 -2
  50. package/dist/task/source-prepare/build-draft.js +3 -3
  51. package/dist/task/source-prepare/fragment-inventory.js +64 -25
  52. package/dist/task/source-prepare/prepare.js +126 -21
  53. package/dist/task/source-prepare/semantic-intake.js +6 -2
  54. package/dist/task/source-references.js +22 -1
  55. package/dist/task/task-demand-routing.js +3 -0
  56. package/dist/worker/console/chat/chat-event-store.js +2 -2
  57. package/dist/worker/console/chat/model-resolver.js +7 -4
  58. package/dist/worker/console/chat/pi-runtime.js +86 -5
  59. package/dist/worker/console/chat/resource-preferences-store.js +1 -1
  60. package/dist/worker/console/chat/routes.js +136 -53
  61. package/dist/worker/console/chat/sdd-data-alignment.js +222 -0
  62. package/dist/worker/console/chat/session-catalog.js +2 -0
  63. package/dist/worker/console/chat/session-store.js +43 -1
  64. package/dist/worker/console/chat/shortcuts.js +18 -2
  65. package/dist/worker/console/chat/user-questions.js +1 -1
  66. package/dist/worker/console/console-update-runtime.js +1 -1
  67. package/dist/worker/console/context-transfer-diagnostics.js +198 -0
  68. package/dist/worker/console/dag-confirmation.js +1 -1
  69. package/dist/worker/console/dag-execution-receipt.js +1 -1
  70. package/dist/worker/console/doctor.js +1 -1
  71. package/dist/worker/console/draft-store.js +1 -1
  72. package/dist/worker/console/frontend-human-decision-adapter.js +19 -0
  73. package/dist/worker/console/frontend-split-operation-adapter.js +20 -0
  74. package/dist/worker/console/human-gate-token.js +1 -1
  75. package/dist/worker/console/index.js +6 -3
  76. package/dist/worker/console/interview/assessment.js +1 -1
  77. package/dist/worker/console/interview/session.js +1 -1
  78. package/dist/worker/console/operation-runner.js +45 -4
  79. package/dist/worker/console/operation-sse.js +1 -1
  80. package/dist/worker/console/operation-wait.js +1 -1
  81. package/dist/worker/console/operator-actions.js +273 -10
  82. package/dist/worker/console/operator-surface-health.js +1 -1
  83. package/dist/worker/console/operator-user-error.js +169 -0
  84. package/dist/worker/console/pi-plugins.js +57 -0
  85. package/dist/worker/console/pi-readiness.js +3 -2
  86. package/dist/worker/console/routes.js +637 -8
  87. package/dist/worker/console/security.js +35 -0
  88. package/dist/worker/console/server.js +29 -4
  89. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-D7oU983t.js → abnfDiagram-N423BO3Z-CcS17TBr.js} +1 -1
  90. package/dist/worker/console/static/assets/{arc-BrKSRdFS.js → arc-COptKq2S.js} +1 -1
  91. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-CiXV7L56.js → architectureDiagram-T3A2C74G-h4LKMHjP.js} +1 -1
  92. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-D_Hs_gIG.js → blockDiagram-VBNYF7ZC-COA1MOH0.js} +1 -1
  93. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-DbM-Lqqh.js → c4Diagram-5PPSVZJV-DJUf0QPm.js} +1 -1
  94. package/dist/worker/console/static/assets/channel-DdBCaOJ6.js +1 -0
  95. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D1M8uqJw.js → chunk-2GRJ4B5K-mtWfKrUX.js} +1 -1
  96. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-4D3RFHT6.js → chunk-2Q5K7J3B-B8pXsxDQ.js} +1 -1
  97. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-CdwpY_n9.js → chunk-5RXB4S5H-ipKzByl1.js} +1 -1
  98. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BLeLZ9PG.js → chunk-5VM5RSS4-DYi3Ald_.js} +1 -1
  99. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-CeRNEMvc.js → chunk-6Q2QTUOP-DQtGYoty.js} +1 -1
  100. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-CjkHP8Vy.js → chunk-GF5L2VYU-BU0qS2YV.js} +1 -1
  101. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-B54ZUQY-.js → chunk-JWPE2WC7-DVH9dIGE.js} +1 -1
  102. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-4bKaMVmx.js → chunk-KBJHAD2P-Dt60SmgM.js} +1 -1
  103. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-Cyjfznu_.js → chunk-RYQCIY6F-BoaUGuEY.js} +1 -1
  104. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-CDN-zGFV.js → chunk-XXDRQBXY-_WHFDTp2.js} +1 -1
  105. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DZFra1GO.js +1 -0
  106. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DZFra1GO.js +1 -0
  107. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-HxJmz411.js → cose-bilkent-JH36ORCC-BxkbTIRd.js} +1 -1
  108. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DtSt5K2w.js → cynefin-VYW2F7L2-Bf2UVnoG.js} +1 -1
  109. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-VtkSpRmG.js → cynefinDiagram-MW4NZA55-Bo23q1J_.js} +1 -1
  110. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-Bj4DT4du.js → dagre-VZM6K2ZE-Dd_UU49i.js} +1 -1
  111. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-Bpuk6BmP.js → diagram-7IWD3JNH-ebUa1a9y.js} +1 -1
  112. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BHYGv_yO.js → diagram-B4RE2ZJO-BucthU8r.js} +1 -1
  113. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-DEx3WwnT.js → diagram-LBJQPF4R-BgqNpAkm.js} +1 -1
  114. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-Cj0dS5e8.js → diagram-Q27KOJAE-DC4q5NGa.js} +1 -1
  115. package/dist/worker/console/static/assets/{diagram-UB23O5K3-B97h8l21.js → diagram-UB23O5K3-CBqCaMeb.js} +1 -1
  116. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DMSFAhBd.js → ebnfDiagram-BXEA7PRR-CGtnbQ3-.js} +1 -1
  117. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-DhVOCbt6.js → erDiagram-JOGREHBK-CG3LUao5.js} +1 -1
  118. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-GlakITWL.js → flowDiagram-UKHOOZJN-D2ZVgoFS.js} +1 -1
  119. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-VxPpu9eQ.js → ganttDiagram-PKOTCBZU-DoYFZiKt.js} +1 -1
  120. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-Bs_e5DRT.js → gitGraphDiagram-DS77QQ5N-CKoP1s6j.js} +1 -1
  121. package/dist/worker/console/static/assets/index-CAZ2fC_X.css +1 -0
  122. package/dist/worker/console/static/assets/index-vbTcFnFs.js +449 -0
  123. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BXYuU4Uw.js → infoDiagram-6WML65LV-Duofv8p2.js} +1 -1
  124. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-C34erCbU.js → ishikawaDiagram-WSZJBQD7-D2nlCkA1.js} +1 -1
  125. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DZCAiOU3.js → journeyDiagram-NVQOT4AX-Dd4IHdus.js} +1 -1
  126. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-C9gaTdUm.js → kanban-definition-27J2QSJJ-Bi20AOdt.js} +1 -1
  127. package/dist/worker/console/static/assets/{linear-CvI0Z17U.js → linear-D59YJ9kB.js} +1 -1
  128. package/dist/worker/console/static/assets/{mermaid.core-DMMSIx7j.js → mermaid.core-Bl13LpNa.js} +5 -5
  129. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-BKKP0EO6.js → mindmap-definition-FAOFIHXS-C6DLP5eY.js} +1 -1
  130. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-C3LiFbl5.js → pegDiagram-VL7TDLO6-BjO4cy64.js} +1 -1
  131. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-Bb3Om2Dz.js → pieDiagram-7S7Q4E2Y-D7i2qZTG.js} +1 -1
  132. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DNthMjzc.js → quadrantDiagram-CIZ2JOQS-Dx8o_h0y.js} +1 -1
  133. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-miFsr4Tv.js → railroadDiagram-AXF67PYL-B55orI_t.js} +1 -1
  134. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-yXUncmn6.js → requirementDiagram-LRYGKXZP-zWaehp6f.js} +1 -1
  135. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DLeWKLak.js → sankeyDiagram-W5VNT64P-CcA-pjvD.js} +1 -1
  136. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-CI3he1R3.js → sequenceDiagram-SI44F4Z6-BOFbzNHI.js} +1 -1
  137. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B7jfDkS5.js → sizeCapture-X5ZJPWSS-BjAejah1.js} +1 -1
  138. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BmrZod7J.js → stateDiagram-OKZ733FA-DXYwxJwZ.js} +1 -1
  139. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Clg3V9t1.js +1 -0
  140. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-CDOlHVSY.js → swimlanes-SLNWSIFB-OYiOch8n.js} +2 -2
  141. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DX1dxAAW.js +8 -0
  142. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cz-XX1gy.js → timeline-definition-Z64GVDOM-cZfH3nmU.js} +1 -1
  143. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-caV4cI8C.js → vennDiagram-T6HMQDX7-BDE7b3E1.js} +1 -1
  144. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-dImPlnIO.js → wardleyDiagram-T6FBY63Y-kyyGy9WJ.js} +1 -1
  145. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-CtRYVJcn.js → xychartDiagram-ELKLHX3M-CJj6VTog.js} +1 -1
  146. package/dist/worker/console/static/index.html +7 -2
  147. package/dist/worker/console/static-src/active-run-badge.js +17 -0
  148. package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
  149. package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -5
  150. package/dist/worker/console/static-src/operator-chat/input-history.js +8 -6
  151. package/dist/worker/console/static-src/operator-chat/runtime-snapshot-store.js +10 -0
  152. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +258 -23
  153. package/dist/worker/console/static-src/operator-chat/useChatThread.js +112 -4
  154. package/dist/worker/console/static-src/operator-chat/useComposer.js +13 -4
  155. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +29 -6
  156. package/dist/worker/console/static-src/operator-chat/useRuntimeSnapshot.js +8 -2
  157. package/dist/worker/console/static-src/shell/console-update-reload.js +52 -0
  158. package/dist/worker/console/static-src/shell/workspace-route.js +11 -0
  159. package/dist/worker/console/workspace-context.js +142 -2
  160. package/dist/worker/console/workspace-registry.js +2 -2
  161. package/dist/worker/continuation/worker-continuation.js +278 -0
  162. package/dist/worker/materialize/frontend-split-task-materializer.js +72 -0
  163. package/dist/worker/observe/health.js +1 -1
  164. package/dist/worker/observe/node-transparency.js +572 -0
  165. package/dist/worker/observe/routes.js +55 -1
  166. package/dist/worker/observe/static/api.js +69 -5
  167. package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
  168. package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
  169. package/dist/worker/observe/static/dag-helpers.js +4 -2
  170. package/dist/worker/observe/static/dag-node-purpose.js +5 -0
  171. package/dist/worker/observe/static/inspect-workspace.js +23 -0
  172. package/dist/worker/observe/static/kpi.js +2 -2
  173. package/dist/worker/observe/static/operator-chrome.d.ts +10 -2
  174. package/dist/worker/observe/static/operator-chrome.js +37 -23
  175. package/dist/worker/observe/static/relations.js +2 -2
  176. package/dist/worker/observe/static/router.d.ts +12 -1
  177. package/dist/worker/observe/static/router.js +48 -6
  178. package/dist/worker/observe/static/run-processing.js +4 -2
  179. package/dist/worker/observe/static/shell-chrome.js +2 -2
  180. package/dist/worker/observe/static/state.js +8 -1
  181. package/dist/worker/observe/static/styles.css +1092 -86
  182. package/dist/worker/observe/static/views/dag-inspector.js +1228 -64
  183. package/dist/worker/observe/static/views/dag.js +10 -2
  184. package/dist/worker/observe/static/views/dags.js +3 -1
  185. package/dist/worker/observe/static/views/dashboard.js +14 -6
  186. package/dist/worker/observe/static/views/pool.js +7 -2
  187. package/dist/worker/observe/static/views/run.js +12 -3
  188. package/dist/worker/observe/static/views/session-timeline.js +142 -18
  189. package/dist/worker/observe/static/views/task.js +7 -2
  190. package/dist/worker/outcomes/adapters.js +19 -0
  191. package/dist/worker/outcomes/types.js +1 -0
  192. package/dist/worker/pool/attempt-lease.js +97 -66
  193. package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
  194. package/dist/worker/pool/reconcile.js +46 -1
  195. package/dist/worker/pool/run-store.js +2 -0
  196. package/dist/worker/pool/state-projection.js +2 -0
  197. package/dist/worker/task-spec/workflow-routing.js +8 -3
  198. package/dist/workflows/dag/artifact-bindings.js +149 -0
  199. package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
  200. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +215 -28
  201. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  202. package/dist/workflows/dag/backend-test-plan-protocol.js +106 -0
  203. package/dist/workflows/dag/backend-test-scenario-param.js +172 -25
  204. package/dist/workflows/dag/backend-test-scenario-partitions.js +62 -1
  205. package/dist/workflows/dag/backend-test-writer-completeness.js +104 -12
  206. package/dist/workflows/dag/budget-enforcement.js +10 -0
  207. package/dist/workflows/dag/context-receipt.js +305 -0
  208. package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
  209. package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
  210. package/dist/workflows/dag/context-transfer/renderers.js +93 -0
  211. package/dist/workflows/dag/contract-validator-registrations.js +1 -2
  212. package/dist/workflows/dag/dag-retry-schema.js +138 -0
  213. package/dist/workflows/dag/frontend-closeout.js +221 -0
  214. package/dist/workflows/dag/frontend-design-policy.js +400 -0
  215. package/dist/workflows/dag/frontend-human-decision.js +182 -0
  216. package/dist/workflows/dag/frontend-implementation-contract.js +1237 -192
  217. package/dist/workflows/dag/frontend-plan-render.js +2 -1
  218. package/dist/workflows/dag/frontend-prewrite-gate.js +256 -350
  219. package/dist/workflows/dag/frontend-provider-capability-matrix.js +159 -0
  220. package/dist/workflows/dag/frontend-recovery-capsule.js +455 -0
  221. package/dist/workflows/dag/frontend-recovery-controller.js +226 -0
  222. package/dist/workflows/dag/frontend-recovery-lineage.js +178 -0
  223. package/dist/workflows/dag/frontend-recovery-plan.js +21 -10
  224. package/dist/workflows/dag/frontend-recovery-run.js +166 -34
  225. package/dist/workflows/dag/frontend-repair.js +1 -432
  226. package/dist/workflows/dag/frontend-review-context.js +261 -15
  227. package/dist/workflows/dag/frontend-review-findings.js +270 -0
  228. package/dist/workflows/dag/frontend-shadow-dual-write.js +941 -0
  229. package/dist/workflows/dag/frontend-shape-capsule-store.js +191 -0
  230. package/dist/workflows/dag/frontend-shape-facts.js +419 -0
  231. package/dist/workflows/dag/frontend-shape.js +435 -0
  232. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +108 -0
  233. package/dist/workflows/dag/frontend-split-application-service.js +203 -0
  234. package/dist/workflows/dag/frontend-split-orchestrator.js +899 -0
  235. package/dist/workflows/dag/frontend-typed-event-store.js +452 -0
  236. package/dist/workflows/dag/frontend-typed-event-transaction.js +180 -0
  237. package/dist/workflows/dag/frontend-verification-trace.js +252 -25
  238. package/dist/workflows/dag/frontend-worktree-diff.js +250 -17
  239. package/dist/workflows/dag/frontend-writer-admission.js +319 -0
  240. package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
  241. package/dist/workflows/dag/frontend-writer-status.js +256 -0
  242. package/dist/workflows/dag/init-hybrid.js +1174 -562
  243. package/dist/workflows/dag/interrupt-request.js +7 -0
  244. package/dist/workflows/dag/node-execution.js +940 -31
  245. package/dist/workflows/dag/path-safety.js +1 -0
  246. package/dist/workflows/dag/prompt.js +99 -7
  247. package/dist/workflows/dag/recovery-lease.js +170 -0
  248. package/dist/workflows/dag/report.js +37 -1
  249. package/dist/workflows/dag/rerun-feedback.js +315 -1
  250. package/dist/workflows/dag/rerun-plan.js +568 -3
  251. package/dist/workflows/dag/rerun-run.js +642 -18
  252. package/dist/workflows/dag/rerun-task.js +251 -13
  253. package/dist/workflows/dag/retry-policy.js +219 -104
  254. package/dist/workflows/dag/runner.js +596 -121
  255. package/dist/workflows/dag/scheduler.js +133 -20
  256. package/dist/workflows/dag/skill-snapshot.js +17 -0
  257. package/dist/workflows/dag/types.js +426 -22
  258. package/dist/workflows/dag/validate.js +28 -12
  259. package/docs/architecture/runtime-boundaries.md +6 -6
  260. package/docs/architecture/worker-and-feature.md +1 -1
  261. package/docs/examples/README.md +5 -0
  262. package/docs/init-surface.manifest.json +30 -12
  263. package/docs/skills/vetted-skill-registry.md +4 -2
  264. package/docs/templates/README.md +2 -0
  265. package/docs/templates/agent-dag-report.schema.json +8 -2
  266. package/docs/templates/agent-dag.schema.json +33 -1
  267. package/docs/templates/backend-test-dag.json +23 -20
  268. package/docs/templates/frontend-implementation-contract.schema.json +4 -1
  269. package/docs/templates/frontend-implementation-dag.json +89 -0
  270. package/docs/templates/product-line/task.yaml +1 -1
  271. package/docs/templates/spec-registry.schema.json +45 -0
  272. package/harness.json +1 -1
  273. package/package.json +6 -3
  274. package/skills/frontend-bounded-implement/SKILL.md +15 -14
  275. package/skills/frontend-bounded-implement/references/code-standards.md +19 -0
  276. package/skills/frontend-contract/SKILL.md +23 -0
  277. package/skills/frontend-contract/references/contract-protocol.md +34 -0
  278. package/skills/frontend-design-review/SKILL.md +22 -41
  279. package/skills/frontend-plan/SKILL.md +26 -0
  280. package/skills/frontend-plan/references/decision-contract.md +37 -0
  281. package/skills/frontend-plan/references/design-decisions.md +17 -0
  282. package/skills/frontend-review/SKILL.md +20 -15
  283. package/skills/frontend-review/references/review-findings.md +6 -7
  284. package/skills/frontend-scout/SKILL.md +25 -0
  285. package/skills/frontend-scout/references/design-evidence.md +16 -0
  286. package/skills/frontend-scout/references/scout-evidence.md +23 -0
  287. package/skills/frontend-verification/SKILL.md +1 -1
  288. package/skills/loop-agent/references/command-reference.md +7 -0
  289. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  290. package/dist/worker/console/operation-store.js +0 -169
  291. package/dist/worker/console/static/assets/channel-D1xajGpe.js +0 -1
  292. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-BmuGTfRr.js +0 -1
  293. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-BmuGTfRr.js +0 -1
  294. package/dist/worker/console/static/assets/index-BLzcAykx.js +0 -451
  295. package/dist/worker/console/static/assets/index-Cs9JUSPs.css +0 -1
  296. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-D9ykKEWP.js +0 -1
  297. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BvPOXALT.js +0 -8
  298. package/skills/frontend-implementation/SKILL.md +0 -52
  299. package/skills/frontend-implementation/references/code-standards.md +0 -33
  300. package/skills/frontend-implementation/references/design-spec.md +0 -56
  301. package/skills/frontend-implementation/references/node-contracts.md +0 -31
  302. /package/dist/{worker → infrastructure}/console/repo-fingerprint.js +0 -0
@@ -4,13 +4,14 @@ import { DAG_RERUN_PROMPT_OVERRIDE_ENV, isDagRerunPromptOverrideEnabled, MAX_DAG
4
4
  import { buildOperatorResult, operatorFailed, operatorSucceeded, } from "../../shared/operator/envelope.js";
5
5
  import { CANONICAL_TASK_ID_PATTERN, formatLocalBusinessDate, getTaskPaths, loadTaskConfig, } from "../../task/runtime.js";
6
6
  import { diffTaskContract, validateDraftForTask, } from "../../task/contract/index.js";
7
- import { stageUtf8Text } from "./app-data.js";
7
+ import { stageUtf8Text } from "../../infrastructure/console/app-data.js";
8
8
  import { ALL_CONFIRMATION_CHALLENGES, hashDagBytes, } from "./dag-confirmation.js";
9
9
  import { capabilityForObserveTarget, DEFAULT_OBSERVE_BASE_URL, OBSERVE_START_COMMAND, probeAndClassifyObserve, } from "./observe-health-match.js";
10
10
  import { buildInspectDeepLink, buildObserveDeepLink, } from "./observe-link.js";
11
11
  import { resolveLatestDagRunIdForTask } from "./resolve-dag-run-for-task.js";
12
- import { repoFingerprintV1 } from "./repo-fingerprint.js";
12
+ import { repoFingerprintV1 } from "../../infrastructure/console/repo-fingerprint.js";
13
13
  import { scheduleOperation, } from "./operation-runner.js";
14
+ import { recordContextTransferEvent } from "./context-transfer-diagnostics.js";
14
15
  import { readinessGateFailure, } from "./pi-readiness.js";
15
16
  import { validatePiModelMatrixTiers, writePiModelMatrix, } from "./harness-pi-model-matrix.js";
16
17
  import { isAssessmentFreshForDraft } from "./interview/assessment.js";
@@ -64,6 +65,10 @@ function paramsOf(req) {
64
65
  function str(v) {
65
66
  return typeof v === "string" && v.trim() ? v.trim() : undefined;
66
67
  }
68
+ function appendExplicitTaskKindArg(args, taskKind, taskKindExplicit) {
69
+ if (taskKindExplicit)
70
+ args.push("--task-kind", taskKind);
71
+ }
67
72
  const TASK_ID_PLACEHOLDER_RE = /[<>]|^(?:id|task-?id|your-task-id|todo|tbd)$/i;
68
73
  /** Mirror of runtime GENERIC_TASK_SLUGS (not exported there); keep in sync. */
69
74
  const GENERIC_SLUG_SET = new Set(["test", "fix", "tmp", "new-task"]);
@@ -481,7 +486,7 @@ async function buildPromptOverrideCliArgs(ctx, overrides) {
481
486
  }
482
487
  return args;
483
488
  }
484
- async function acceptOperation(ctx, input) {
489
+ export async function acceptOperation(ctx, input) {
485
490
  const created = await ctx.operations.create({
486
491
  clientRequestId: input.clientRequestId,
487
492
  action: input.action,
@@ -517,12 +522,55 @@ async function acceptOperation(ctx, input) {
517
522
  },
518
523
  };
519
524
  }
525
+ if (input.onAdmitted) {
526
+ try {
527
+ await input.onAdmitted(created.operation);
528
+ }
529
+ catch {
530
+ // Lifecycle observation must never block admission.
531
+ }
532
+ }
533
+ if (input.prepare) {
534
+ try {
535
+ await input.prepare();
536
+ }
537
+ catch (error) {
538
+ const message = error instanceof Error ? error.message : String(error);
539
+ const preparedFailure = input.prepareFailure?.(error);
540
+ await ctx.operations.update(created.operation.operationId, {
541
+ state: "failed",
542
+ startedAt: created.operation.createdAt,
543
+ finishedAt: new Date().toISOString(),
544
+ errorCode: preparedFailure?.errorCode ?? "INVALID_INPUT",
545
+ errorMessage: message,
546
+ });
547
+ return {
548
+ kind: "error",
549
+ status: preparedFailure?.status ?? 400,
550
+ body: preparedFailure?.body ?? operatorFailed({
551
+ command: input.action,
552
+ outcome: "blocked",
553
+ code: "INVALID_INPUT",
554
+ message,
555
+ }),
556
+ };
557
+ }
558
+ }
559
+ const transferObserver = contextTransferSettledObserver(ctx, input.action, input.actionParams);
520
560
  const runnerDeps = {
521
561
  store: ctx.operations,
522
562
  events: ctx.events,
523
563
  client: ctx.client,
524
564
  repoRoot: ctx.repoRoot,
565
+ env: { ...process.env, LOOP_CONSOLE_APP_DATA: ctx.appData.root },
525
566
  runCommand: ctx.runCommand,
567
+ beforeTerminal: input.beforeTerminal,
568
+ onSettled: async (operation, state, info) => {
569
+ // Diagnostics are best-effort and must not prevent authoritative Worker
570
+ // settlement from running.
571
+ await Promise.resolve(transferObserver?.(operation, state, info)).catch(() => undefined);
572
+ await input.onSettled?.(operation, state, info);
573
+ },
526
574
  };
527
575
  scheduleOperation(created.operation.operationId, runnerDeps);
528
576
  return {
@@ -536,6 +584,141 @@ async function acceptOperation(ctx, input) {
536
584
  },
537
585
  };
538
586
  }
587
+ function splitRuntimeMissing(action) {
588
+ return {
589
+ kind: "error",
590
+ status: 503,
591
+ body: operatorFailed({
592
+ command: action,
593
+ outcome: "blocked",
594
+ code: "INTERNAL_ERROR",
595
+ message: `${action} is unavailable: frontend split runtime is not wired`,
596
+ }),
597
+ };
598
+ }
599
+ function numOf(v) {
600
+ return typeof v === "number" ? v : Number(v);
601
+ }
602
+ function splitCommandBase(p) {
603
+ return {
604
+ operationId: str(p.operationId) ?? "",
605
+ expectedRevision: numOf(p.expectedRevision),
606
+ expectedParentDigest: str(p.expectedParentDigest) ?? "",
607
+ expectedManifestDigest: str(p.expectedManifestDigest) ?? "",
608
+ };
609
+ }
610
+ function splitCommandDispatch(action, result) {
611
+ if (result.outcome === "conflict") {
612
+ return {
613
+ kind: "error",
614
+ status: 409,
615
+ body: operatorFailed({
616
+ command: action,
617
+ outcome: "conflict",
618
+ code: "CONFLICT",
619
+ message: "frontend split CAS conflict (stale revision or binding)",
620
+ }),
621
+ };
622
+ }
623
+ return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
624
+ }
625
+ async function runSplitAction(action, run) {
626
+ try {
627
+ const result = await run();
628
+ if (result && typeof result === "object" && "outcome" in result) {
629
+ return splitCommandDispatch(action, result);
630
+ }
631
+ return {
632
+ kind: "sync",
633
+ status: 200,
634
+ body: operatorSucceeded(action, result),
635
+ };
636
+ }
637
+ catch (error) {
638
+ return invalid(action, error instanceof Error ? error.message : String(error));
639
+ }
640
+ }
641
+ function humanDecisionDispatch(action, result) {
642
+ if (result.outcome === "rejected") {
643
+ return {
644
+ kind: "error",
645
+ status: 409,
646
+ body: operatorFailed({
647
+ command: action,
648
+ outcome: "conflict",
649
+ code: "CONFLICT",
650
+ message: result.reason,
651
+ details: { projection: result.projection },
652
+ }),
653
+ };
654
+ }
655
+ return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
656
+ }
657
+ async function runHumanDecisionAction(action, run) {
658
+ try {
659
+ return humanDecisionDispatch(action, await run());
660
+ }
661
+ catch (error) {
662
+ return invalid(action, error instanceof Error ? error.message : String(error));
663
+ }
664
+ }
665
+ /**
666
+ * Map artifact revision / rerun operation outcomes onto the append-only
667
+ * context-transfer lifecycle event log. Only stages the Console truly
668
+ * observes (admission + settle) are recorded; CLI-kernel-internal stages
669
+ * stay in the kernel. Unknown actions emit nothing.
670
+ */
671
+ function contextTransferSettledObserver(ctx, action, actionParams) {
672
+ if (action !== "artifactRevisionStage" &&
673
+ action !== "artifactRevisionPlan" &&
674
+ action !== "artifactRevisionExecute") {
675
+ return undefined;
676
+ }
677
+ const strParam = (key) => {
678
+ const value = actionParams[key];
679
+ return typeof value === "string" ? value.trim() : undefined;
680
+ };
681
+ const baseFields = {
682
+ runId: strParam("runId"),
683
+ nodeId: strParam("nodeId"),
684
+ revisionId: strParam("revisionId"),
685
+ };
686
+ return (operation, state, info) => {
687
+ let event;
688
+ if (action === "artifactRevisionStage") {
689
+ event = info.ok ? "artifact_revision.validated" : "artifact_revision.rejected";
690
+ }
691
+ else if (action === "artifactRevisionPlan") {
692
+ event = info.ok ? "artifact_rerun.plan_created" : "artifact_rerun.blocked";
693
+ }
694
+ else if (state === "needs-reconcile") {
695
+ event = "artifact_rerun.needs_reconcile";
696
+ }
697
+ else {
698
+ event = info.ok ? "artifact_rerun.finished" : "artifact_rerun.failed";
699
+ }
700
+ // The stage CLI assigns the revision id; it only exists in the settle
701
+ // result, never in admission params.
702
+ let resultRevisionId;
703
+ const resultRevision = operation.result
704
+ ?.revision;
705
+ if (resultRevision && typeof resultRevision === "object") {
706
+ resultRevisionId = resultRevision.revisionId;
707
+ }
708
+ return recordContextTransferEvent({
709
+ appData: ctx.appData,
710
+ event,
711
+ fields: {
712
+ ...baseFields,
713
+ ...(typeof resultRevisionId === "string"
714
+ ? { revisionId: resultRevisionId }
715
+ : {}),
716
+ operationId: operation.operationId,
717
+ ...(info.ok ? {} : { reasonCode: info.errorCode ?? "INTERNAL_ERROR" }),
718
+ },
719
+ }).catch(() => undefined);
720
+ };
721
+ }
539
722
  async function acceptConsoleUpdateAndInit(ctx, clientRequestId, channel) {
540
723
  if (!ctx.consoleUpdateExecutor) {
541
724
  return {
@@ -1877,7 +2060,7 @@ export async function dispatchOperatorAction(ctx, req) {
1877
2060
  const staged = await stageUtf8Text(ctx.appData, content, {
1878
2061
  extension: ".md",
1879
2062
  });
1880
- const imported = await run([
2063
+ const importArgs = [
1881
2064
  "task",
1882
2065
  "advance",
1883
2066
  taskId,
@@ -1886,8 +2069,10 @@ export async function dispatchOperatorAction(ctx, req) {
1886
2069
  staged.path,
1887
2070
  "--role",
1888
2071
  "requirement",
1889
- "--json",
1890
- ], {
2072
+ ];
2073
+ appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
2074
+ importArgs.push("--json");
2075
+ const imported = await run(importArgs, {
1891
2076
  cwd: ctx.repoRoot,
1892
2077
  artifactName: "import-prd-task-advance",
1893
2078
  expectJson: true,
@@ -2862,6 +3047,75 @@ export async function dispatchOperatorAction(ctx, req) {
2862
3047
  }),
2863
3048
  };
2864
3049
  }
3050
+ case "frontendSplitWakeup": {
3051
+ if (!ctx.splitOrchestrator)
3052
+ return splitRuntimeMissing(action);
3053
+ return runSplitAction(action, () => ctx.splitOrchestrator.wakeupChildren(splitCommandBase(p)));
3054
+ }
3055
+ case "frontendSplitChildCallback": {
3056
+ if (!ctx.splitOrchestrator)
3057
+ return splitRuntimeMissing(action);
3058
+ return runSplitAction(action, () => ctx.splitOrchestrator.childCallback({
3059
+ ...splitCommandBase(p),
3060
+ observation: p.observation,
3061
+ }));
3062
+ }
3063
+ case "frontendSplitWakeupIntegration": {
3064
+ if (!ctx.splitOrchestrator)
3065
+ return splitRuntimeMissing(action);
3066
+ return runSplitAction(action, () => ctx.splitOrchestrator.wakeupIntegration(splitCommandBase(p)));
3067
+ }
3068
+ case "frontendSplitIntegrationCallback": {
3069
+ if (!ctx.splitOrchestrator)
3070
+ return splitRuntimeMissing(action);
3071
+ return runSplitAction(action, () => ctx.splitOrchestrator.integrationCallback({
3072
+ ...splitCommandBase(p),
3073
+ completion: p.completion,
3074
+ }));
3075
+ }
3076
+ case "frontendSplitFinalize": {
3077
+ if (!ctx.splitOrchestrator)
3078
+ return splitRuntimeMissing(action);
3079
+ return runSplitAction(action, () => ctx.splitOrchestrator.finalize(splitCommandBase(p)));
3080
+ }
3081
+ case "frontendHumanDecisionMaterialize": {
3082
+ if (!ctx.humanDecisionAdapter)
3083
+ return splitRuntimeMissing(action);
3084
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.materialize({
3085
+ operationId: str(p.operationId) ?? "",
3086
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
3087
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
3088
+ envelope: p.envelope,
3089
+ }));
3090
+ }
3091
+ case "frontendHumanDecisionApprove": {
3092
+ if (!ctx.humanDecisionAdapter)
3093
+ return splitRuntimeMissing(action);
3094
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.consume({
3095
+ operationId: str(p.operationId) ?? "",
3096
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
3097
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
3098
+ receipt: p.receipt,
3099
+ currentTargetDigest: str(p.currentTargetDigest) ?? "",
3100
+ now: str(p.now) ?? new Date().toISOString(),
3101
+ }));
3102
+ }
3103
+ case "frontendSplitInitialize": {
3104
+ if (!ctx.humanDecisionAdapter)
3105
+ return splitRuntimeMissing(action);
3106
+ return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.initializeSplit({
3107
+ operationId: str(p.operationId) ?? "",
3108
+ expectedRecordRevision: numOf(p.expectedRecordRevision),
3109
+ expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
3110
+ execution: p.execution,
3111
+ manifest: p.manifest,
3112
+ receipt: p.receipt,
3113
+ currentTargetDigest: str(p.currentTargetDigest) ?? "",
3114
+ now: str(p.now) ?? new Date().toISOString(),
3115
+ activeWriterOperationId: str(p.activeWriterOperationId) ?? null,
3116
+ activeProviderOperationId: str(p.activeProviderOperationId) ?? null,
3117
+ }));
3118
+ }
2865
3119
  default: {
2866
3120
  // M5 official-command coverage uses one generic tail for newly registered
2867
3121
  // CLI actions. It remains inside dispatchOperatorAction (the sole dispatch
@@ -3246,7 +3500,14 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3246
3500
  const title = identity.title;
3247
3501
  const run = ctx.runCommand ?? ((a, o) => ctx.client.run(a, o));
3248
3502
  // Standard lifecycle entry: task advance create + PRD import(s).
3249
- const advanceCreate = await run(["task", "advance", taskId, title, "--json"], {
3503
+ // Preserve an explicitly selected business workflow from the very first
3504
+ // task.json write. The task lifecycle otherwise defaults new tasks to
3505
+ // standard, which caused frontend tasks to be promoted only during the
3506
+ // final intake pass.
3507
+ const createArgs = ["task", "advance", taskId, title];
3508
+ appendExplicitTaskKindArg(createArgs, taskKind, taskKindExplicit);
3509
+ createArgs.push("--json");
3510
+ const advanceCreate = await run(createArgs, {
3250
3511
  cwd: ctx.repoRoot,
3251
3512
  artifactName: "bootstrap-task-advance-create",
3252
3513
  expectJson: true,
@@ -3280,7 +3541,7 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3280
3541
  const staged = await stageUtf8Text(ctx.appData, text, {
3281
3542
  extension: ".md",
3282
3543
  });
3283
- const imported = await run([
3544
+ const importArgs = [
3284
3545
  "task",
3285
3546
  "advance",
3286
3547
  taskId,
@@ -3288,8 +3549,10 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3288
3549
  staged.path,
3289
3550
  "--role",
3290
3551
  role,
3291
- "--json",
3292
- ], {
3552
+ ];
3553
+ appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
3554
+ importArgs.push("--json");
3555
+ const imported = await run(importArgs, {
3293
3556
  cwd: ctx.repoRoot,
3294
3557
  artifactName: `bootstrap-task-advance-prd-${label}`,
3295
3558
  expectJson: true,
@@ -1,5 +1,5 @@
1
1
  import { deriveObserveRouteCapabilities, resolveObservePackageIdentity, } from "../observe/health.js";
2
- import { repoFingerprintV1 } from "./repo-fingerprint.js";
2
+ import { repoFingerprintV1 } from "../../infrastructure/console/repo-fingerprint.js";
3
3
  export function buildOperatorSurfaceHealthV1(input) {
4
4
  const { packageName, packageVersion } = resolveObservePackageIdentity();
5
5
  const snapshotAvailable = input.routes.some((route) => route.method === "GET" && route.pattern.test("/api/snapshot"));
@@ -14,6 +14,162 @@ const MUTATION_GATE_COPY = [
14
14
  copy: "请求主机校验失败:非回环绑定时要求 Host 头,请刷新页面或检查访问地址。",
15
15
  },
16
16
  ];
17
+ /**
18
+ * Context-transfer / artifact-revision 稳定 reason code(kernel CLI 会原样
19
+ * 透传到操作错误信息里)→ 面向操作者的中文语义。与 observe 侧
20
+ * dag-context-reason-labels.js 同源,保留原码便于诊断。
21
+ */
22
+ const CONTEXT_TRANSFER_CODE_COPY = [
23
+ {
24
+ pattern: /\bCONTEXT_RECEIPT_MISSING\b/,
25
+ copy: "该节点没有执行时上下文回执(CONTEXT_RECEIPT_MISSING):只有真实执行过的模型节点才有可导出的上下文;历史 run 不做事后回填。",
26
+ },
27
+ {
28
+ pattern: /\bCONTEXT_COMPONENT_UNAVAILABLE\b/,
29
+ copy: "部分上下文组件当前不可用(CONTEXT_COMPONENT_UNAVAILABLE),无法生成完整交接包。",
30
+ },
31
+ {
32
+ pattern: /\bCONTEXT_BUNDLE_TOO_LARGE\b/,
33
+ copy: "导出内容超出体积上限(CONTEXT_BUNDLE_TOO_LARGE),请缩小节点范围或联系维护者调整上限。",
34
+ },
35
+ {
36
+ pattern: /\bRAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED\b/,
37
+ copy: "原文导出包含敏感数据风险(RAW_EXPORT_ACKNOWLEDGEMENT_REQUIRED),需要先勾选风险确认。",
38
+ },
39
+ {
40
+ pattern: /\bSECRET_SCAN_CONFIRMATION_REQUIRED\b/,
41
+ copy: "候选文件疑似包含凭据(SECRET_SCAN_CONFIRMATION_REQUIRED),确认风险后才能继续。",
42
+ },
43
+ {
44
+ pattern: /\bARTIFACT_BINDING_UNAVAILABLE\b/,
45
+ copy: "缺少结构化产物关系(ARTIFACT_BINDING_UNAVAILABLE):只有带产物绑定的新 run 支持修订与派生,历史 run 仅可查看/下载。",
46
+ },
47
+ {
48
+ pattern: /\bARTIFACT_NOT_REVISION_ELIGIBLE\b/,
49
+ copy: "该产物不允许修订替换(ARTIFACT_NOT_REVISION_ELIGIBLE)。",
50
+ },
51
+ {
52
+ pattern: /\bARTIFACT_IDENTITY_AMBIGUOUS\b/,
53
+ copy: "产物身份不唯一(ARTIFACT_IDENTITY_AMBIGUOUS),无法安全定位修订目标。",
54
+ },
55
+ {
56
+ pattern: /\bARTIFACT_REVISION_SCHEMA_INVALID\b/,
57
+ copy: "候选文件不符合该产物声明的数据结构(ARTIFACT_REVISION_SCHEMA_INVALID),已拒绝入库。",
58
+ },
59
+ {
60
+ pattern: /\bARTIFACT_REVISION_PATH_INVALID\b/,
61
+ copy: "候选目标路径无效(ARTIFACT_REVISION_PATH_INVALID),已拒绝。",
62
+ },
63
+ {
64
+ pattern: /\bARTIFACT_REVISION_EXPIRED\b/,
65
+ copy: "修订候选已过期(ARTIFACT_REVISION_EXPIRED),请重新上传后再继续。",
66
+ },
67
+ {
68
+ pattern: /\bARTIFACT_REVISION_DRIFT\b/,
69
+ copy: "候选文件与登记内容不一致(ARTIFACT_REVISION_DRIFT),请重新上传。",
70
+ },
71
+ {
72
+ pattern: /\bARTIFACT_REVISION_QUOTA_EXCEEDED\b/,
73
+ copy: "修订暂存区配额已满(ARTIFACT_REVISION_QUOTA_EXCEEDED),请先丢弃不需要的修订或等待过期回收。",
74
+ },
75
+ {
76
+ pattern: /\bARTIFACT_CONSUMER_UNKNOWN\b/,
77
+ copy: "无法确定受影响的下游节点(ARTIFACT_CONSUMER_UNKNOWN),派生继续已被阻止。",
78
+ },
79
+ {
80
+ pattern: /\bARTIFACT_IMPACT_UNSAFE\b/,
81
+ copy: "影响范围包含不能自动重跑的节点(ARTIFACT_IMPACT_UNSAFE),派生继续已被阻止。",
82
+ },
83
+ {
84
+ pattern: /\bRERUN_PLAN_DRIFT\b|\bPLAN_DRIFT\b/,
85
+ copy: "继续运行计划与当前事实发生漂移(RERUN_PLAN_DRIFT),请重新生成计划后再执行。",
86
+ },
87
+ {
88
+ pattern: /\bWORKER_MANAGED_CONTINUATION_UNSUPPORTED\b/,
89
+ copy: "由 Worker 托管的运行暂不支持派生继续(WORKER_MANAGED_CONTINUATION_UNSUPPORTED),这是当前版本的明确边界,不是失败。",
90
+ },
91
+ {
92
+ pattern: /\bWORKER_CONTINUATION_AUTHORITY_MISMATCH\b/,
93
+ copy: "Worker 派生运行的归属事实不一致(WORKER_CONTINUATION_AUTHORITY_MISMATCH),请刷新计划并核对 Task Pool 状态。",
94
+ },
95
+ {
96
+ pattern: /\bWORKER_CONTINUATION_LEASE_CONFLICT\b/,
97
+ copy: "该 Worker Task 已有运行占用(WORKER_CONTINUATION_LEASE_CONFLICT),请等待当前运行结束或先完成恢复核对。",
98
+ },
99
+ {
100
+ pattern: /\bWORKER_CONTINUATION_NEEDS_RECONCILE\b/,
101
+ copy: "Worker 派生运行已存在但终态尚未完成核对(WORKER_CONTINUATION_NEEDS_RECONCILE),不会再次启动;请先执行恢复核对。",
102
+ },
103
+ {
104
+ pattern: /\bPARENT_IMMUTABILITY_VIOLATION\b/,
105
+ copy: "父运行事实发生变化(PARENT_IMMUTABILITY_VIOLATION),已阻止派生以保护历史证据。",
106
+ },
107
+ {
108
+ pattern: /\bPARENT_LIFECYCLE\b/,
109
+ copy: "父运行当前状态不允许派生继续(PARENT_LIFECYCLE)。",
110
+ },
111
+ {
112
+ pattern: /\bREQUEST_ID_REUSE_CONFLICT\b/,
113
+ copy: "相同请求 ID 已被其他操作占用(REQUEST_ID_REUSE_CONFLICT),请更换请求 ID 重试。",
114
+ },
115
+ {
116
+ pattern: /\bOPERATION_NEEDS_RECONCILE\b/,
117
+ copy: "操作记录需要先恢复核对(OPERATION_NEEDS_RECONCILE):上次执行未确认结束,请刷新操作状态后重试。",
118
+ },
119
+ {
120
+ pattern: /\bCONTEXT_EXPORT_FAILED\b/,
121
+ copy: "上下文导出失败(CONTEXT_EXPORT_FAILED),请稍后重试;若持续失败请检查该节点是否存在可导出的执行事实。",
122
+ },
123
+ {
124
+ pattern: /\bCONTEXT_EXPORT_UNAVAILABLE\b/,
125
+ copy: "导出内容不存在或已过期(CONTEXT_EXPORT_UNAVAILABLE),请重新生成。",
126
+ },
127
+ {
128
+ pattern: /\bLEASE_HELD\b/,
129
+ copy: "资源正被其他操作占用(LEASE_HELD),请等待当前操作结束或稍后重试。",
130
+ },
131
+ // 更新并初始化链路的稳定错误码。
132
+ {
133
+ pattern: /\bREGISTRY_VERSION_REGRESSION\b/,
134
+ copy: "所选渠道的最新版本比当前安装的版本更旧(REGISTRY_VERSION_REGRESSION),已阻止降级更新。请改用包含更新版本的渠道(如 next/beta)。",
135
+ },
136
+ {
137
+ pattern: /\bUPDATE_LOCKED\b/,
138
+ copy: "另一个 loop-agent 更新正在进行(UPDATE_LOCKED),请等待其结束后重试。",
139
+ },
140
+ {
141
+ pattern: /\bINSTALL_FAILED\b/,
142
+ copy: "新版本安装失败(INSTALL_FAILED),请检查网络与 npm registry 后重试。",
143
+ },
144
+ {
145
+ pattern: /\bINSTALL_VERIFICATION_FAILED\b/,
146
+ copy: "安装后校验未通过(INSTALL_VERIFICATION_FAILED),未接棒新版本;请重试或手动安装。",
147
+ },
148
+ {
149
+ pattern: /\bACTIVE_RUNTIME\b/,
150
+ copy: "当前存在活跃的 DAG/Worker 运行(ACTIVE_RUNTIME),更新已推迟;请等待运行结束后再更新。",
151
+ },
152
+ {
153
+ pattern: /\bCHAT_TURN_ACTIVE\b/,
154
+ copy: "对话正在执行中(CHAT_TURN_ACTIVE),更新已推迟;请等待当前回合结束后再更新。",
155
+ },
156
+ {
157
+ pattern: /\bOPERATION_ACTIVE\b/,
158
+ copy: "另一个 Console 操作正在进行(OPERATION_ACTIVE),请等待其结束后再更新。",
159
+ },
160
+ {
161
+ pattern: /\bHANDOFF_FAILED\b/,
162
+ copy: "新版本已安装,但接棒启动新 Console 失败(HANDOFF_FAILED);旧进程未被关闭,可直接重试或手动重启 Console。",
163
+ },
164
+ {
165
+ pattern: /\bINIT_NEEDS_RECONCILE\b/,
166
+ copy: "安全初始化未完全通过(INIT_NEEDS_RECONCILE):版本已就绪,请查看初始化待处理项后重试。",
167
+ },
168
+ {
169
+ pattern: /\bINVALID_VERSION\b/,
170
+ copy: "安装版本或渠道版本号无法解析(INVALID_VERSION),请重试;若持续出现请反馈。",
171
+ },
172
+ ];
17
173
  /** Map internal spawn/controller errors to actionable Chinese copy. */
18
174
  export function formatOperatorUserError(message) {
19
175
  const raw = (message ?? "").trim();
@@ -37,6 +193,19 @@ export function formatOperatorUserError(message) {
37
193
  if (/force-required|requires --force/i.test(raw)) {
38
194
  return "该终态需要强制 Discard。请确认后勾选强制再试。";
39
195
  }
196
+ if (/not-global|GLOBAL_INSTALL_UNPROVEN/i.test(raw)) {
197
+ return "当前 Console 由仓库内构建启动,不是全局 npm 安装,一键更新不可用。请全局安装(npm i -g @tea-agent/loop-agent)后从全局命令启动 Console 再更新,或手动更新本仓库后重启。";
198
+ }
199
+ if (/could not verify npm (?:latest|next) \(timeout\)/i.test(raw)) {
200
+ return "检查 npm 更新渠道超时:请确认本机网络或 npm registry 镜像可访问后重试。";
201
+ }
202
+ if (/could not verify npm (?:latest|next) \(/i.test(raw)) {
203
+ return "检查 npm 更新渠道失败:请确认本机 npm 可用、网络可访问 registry 后重试。";
204
+ }
205
+ for (const entry of CONTEXT_TRANSFER_CODE_COPY) {
206
+ if (entry.pattern.test(raw))
207
+ return entry.copy;
208
+ }
40
209
  for (const entry of MUTATION_GATE_COPY) {
41
210
  if (entry.pattern.test(raw))
42
211
  return entry.copy;
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, readFileSync } from "node:fs";
2
2
  import { spawn } from "node:child_process";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
+ import semver from "semver";
5
6
  import catalogData from "./pi-plugins.catalog.json" with { type: "json" };
6
7
  export function getPiAgentDir() {
7
8
  const envDir = process.env.PI_CODING_AGENT_DIR;
@@ -125,6 +126,62 @@ export async function listPiPluginVersions(name) {
125
126
  };
126
127
  }
127
128
  }
129
+ /** 单个已装插件的升级判定:latest 严格大于已装版本才算有更新。 */
130
+ export function isPluginUpgradable(installed, latest) {
131
+ if (!installed || !latest)
132
+ return false;
133
+ const current = semver.valid(installed);
134
+ const next = semver.valid(latest);
135
+ if (!current || !next)
136
+ return false;
137
+ return semver.gt(next, current);
138
+ }
139
+ /** 已装插件更新检查结果的最短缓存时长:避免前端频繁刷新打爆 registry。 */
140
+ const UPDATES_CACHE_TTL_MS = 60_000;
141
+ let cachedUpdates;
142
+ /**
143
+ * 检查所有已安装插件的可用更新:并发拉取每个包的 dist-tags.latest,
144
+ * 与 node_modules 里的实际版本做 semver 比较。单包失败不阻塞其它包。
145
+ * TTL 内重复调用直接复用上次结果(`force: true` 可绕过)。
146
+ */
147
+ export async function checkPiPluginUpdates(options) {
148
+ const now = options?.now ?? Date.now;
149
+ if (!options?.force &&
150
+ cachedUpdates &&
151
+ now() - cachedUpdates.at < UPDATES_CACHE_TTL_MS) {
152
+ return cachedUpdates.view;
153
+ }
154
+ const fetchPackument = options?.fetchPackument ?? listPiPluginVersions;
155
+ const installed = options?.listInstalled?.() ??
156
+ listPiPlugins()
157
+ .plugins.filter((p) => p.installed)
158
+ .map((p) => ({ name: p.name, installedVersion: p.installedVersion }));
159
+ const statuses = await Promise.all(installed.map(async (p) => {
160
+ const result = await fetchPackument(p.name);
161
+ if (!result.ok) {
162
+ return {
163
+ name: p.name,
164
+ installedVersion: p.installedVersion,
165
+ upgradable: false,
166
+ error: result.error,
167
+ };
168
+ }
169
+ return {
170
+ name: p.name,
171
+ installedVersion: p.installedVersion,
172
+ latest: result.latest,
173
+ upgradable: isPluginUpgradable(p.installedVersion, result.latest),
174
+ };
175
+ }));
176
+ const view = {
177
+ checked: statuses.length,
178
+ upgradableCount: statuses.filter((s) => s.upgradable).length,
179
+ checkedAt: new Date().toISOString(),
180
+ plugins: statuses,
181
+ };
182
+ cachedUpdates = { at: now(), view };
183
+ return view;
184
+ }
128
185
  function runPi(args) {
129
186
  return new Promise((resolve) => {
130
187
  mkdirSync(getPiAgentDir(), { recursive: true });
@@ -170,11 +170,12 @@ export async function discoverPiReadinessProbe(options) {
170
170
  const availableCount = countAvailableModels(snapshot);
171
171
  const providerConfigured = hasProviderConfig(snapshot);
172
172
  const availableModels = mapSnapshotAvailableModels(snapshot);
173
+ const credentialedAvailableCount = availableModels.filter((model) => model.hasCredentials !== false).length;
173
174
  const harnessMatrix = await resolveHarnessPiExecutorMatrix(repoRoot, availableModels);
174
175
  const resolvedHarnessModels = [];
175
176
  if (typeof runtime.getModel === "function") {
176
177
  for (const row of harnessMatrix) {
177
- if (!row.provider)
178
+ if (!row.provider || !row.resolved)
178
179
  continue;
179
180
  try {
180
181
  if (runtime.getModel(row.provider, row.modelId)) {
@@ -195,7 +196,7 @@ export async function discoverPiReadinessProbe(options) {
195
196
  .join(",")
196
197
  : "none";
197
198
  const authReady = availableCount > 0 || providerConfigured;
198
- const modelsAvailable = availableCount > 0 || resolvedHarnessModels.length > 0;
199
+ const modelsAvailable = credentialedAvailableCount > 0 || resolvedHarnessModels.length > 0;
199
200
  let interviewSessionOk = false;
200
201
  let sessionMessage;
201
202
  if (!authReady || !modelsAvailable) {