@tea-agent/loop-agent 0.41.1-beta.0 → 0.42.0-next.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 (277) hide show
  1. package/CHANGELOG.md +78 -206
  2. package/dist/adapters/context-transfer/optional-pi-handoff.js +31 -0
  3. package/dist/adapters/context-transfer/pi-session.js +61 -0
  4. package/dist/application/dag/generate-task-dag.js +19 -75
  5. package/dist/application/task-lifecycle/advance.js +5 -24
  6. package/dist/application/task-lifecycle/observe.js +17 -171
  7. package/dist/application/task-lifecycle/plan-transitions.js +7 -42
  8. package/dist/application/task-lifecycle/recommendations.js +2 -13
  9. package/dist/build-stamp.json +3 -3
  10. package/dist/cli/command-definitions.js +12 -7
  11. package/dist/cli/program.js +23 -6
  12. package/dist/commands/client-recovery.js +0 -3
  13. package/dist/commands/dag-artifact.js +284 -0
  14. package/dist/commands/dag-context.js +184 -0
  15. package/dist/commands/dag-rerun.js +206 -1
  16. package/dist/commands/init.js +1 -27
  17. package/dist/commands/task-advance.js +0 -19
  18. package/dist/executors/dag-pi-executor.js +266 -3792
  19. package/dist/executors/pi-executor.js +4 -15
  20. package/dist/executors/pi-sdk-executor.js +3 -0
  21. package/dist/executors/shell-executor.js +217 -945
  22. package/dist/executors/shell-write-guard.js +0 -7
  23. package/dist/{worker → infrastructure}/console/app-data.js +4 -0
  24. package/dist/infrastructure/console/artifact-revision-store.js +430 -0
  25. package/dist/infrastructure/console/context-export-store.js +160 -0
  26. package/dist/infrastructure/console/dir-lock.js +132 -0
  27. package/dist/infrastructure/console/operation-store.js +197 -0
  28. package/dist/infrastructure/harness/artifact-store.js +10 -1
  29. package/dist/infrastructure/harness/atomic-write.js +12 -2
  30. package/dist/shared/context-transfer/artifact-revision.js +172 -0
  31. package/dist/shared/context-transfer.js +418 -0
  32. package/dist/shared/dag-failure-category.js +0 -12
  33. package/dist/shared/openspec-spec.js +4 -70
  34. package/dist/shared/operator/capabilities.js +14 -7
  35. package/dist/shared/operator/safe-run-summary.js +1 -0
  36. package/dist/shared/path-safety.js +93 -0
  37. package/dist/shared/preview.js +28 -4
  38. package/dist/task/config-types.js +80 -35
  39. package/dist/task/contract/adopt.js +0 -4
  40. package/dist/task/contract/import-revision.js +0 -4
  41. package/dist/task/contract/project.js +0 -3
  42. package/dist/task/contract/schema.js +1 -2
  43. package/dist/task/frontend-project-capability.js +20 -203
  44. package/dist/task/runtime.js +2 -5
  45. package/dist/task/source-prepare/build-draft.js +3 -3
  46. package/dist/task/source-prepare/fragment-inventory.js +9 -15
  47. package/dist/task/source-prepare/prepare.js +1 -89
  48. package/dist/task/source-prepare/semantic-intake.js +2 -6
  49. package/dist/task/source-references.js +1 -22
  50. package/dist/task/task-demand-routing.js +3 -0
  51. package/dist/worker/console/chat/chat-event-store.js +2 -2
  52. package/dist/worker/console/chat/pi-runtime.js +3 -2
  53. package/dist/worker/console/chat/resource-preferences-store.js +1 -1
  54. package/dist/worker/console/chat/routes.js +13 -4
  55. package/dist/worker/console/chat/semantic-activity.js +12 -11
  56. package/dist/worker/console/chat/session-stats.js +96 -0
  57. package/dist/worker/console/chat/session-store.js +1 -1
  58. package/dist/worker/console/chat/turn-process.js +28 -4
  59. package/dist/worker/console/chat/user-questions.js +1 -1
  60. package/dist/worker/console/console-update-runtime.js +1 -1
  61. package/dist/worker/console/context-transfer-diagnostics.js +198 -0
  62. package/dist/worker/console/dag-confirmation.js +1 -1
  63. package/dist/worker/console/dag-execution-receipt.js +1 -1
  64. package/dist/worker/console/doctor.js +1 -1
  65. package/dist/worker/console/draft-store.js +1 -1
  66. package/dist/worker/console/human-gate-token.js +1 -1
  67. package/dist/worker/console/index.js +3 -6
  68. package/dist/worker/console/interview/assessment.js +1 -1
  69. package/dist/worker/console/interview/session.js +1 -1
  70. package/dist/worker/console/operation-runner.js +45 -4
  71. package/dist/worker/console/operation-sse.js +1 -1
  72. package/dist/worker/console/operation-wait.js +1 -1
  73. package/dist/worker/console/operator-actions.js +107 -168
  74. package/dist/worker/console/operator-surface-health.js +1 -1
  75. package/dist/worker/console/operator-user-error.js +169 -0
  76. package/dist/worker/console/pi-plugins.js +60 -1
  77. package/dist/worker/console/routes.js +637 -8
  78. package/dist/worker/console/security.js +35 -0
  79. package/dist/worker/console/server.js +6 -6
  80. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Bho4we4c.js → abnfDiagram-N423BO3Z-DZZ8m3PO.js} +1 -1
  81. package/dist/worker/console/static/assets/{arc-TBDkTeK0.js → arc-D6PvaVd-.js} +1 -1
  82. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BF_fZrn2.js → architectureDiagram-T3A2C74G-B_OTOiI8.js} +1 -1
  83. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-CCnPgUe2.js → blockDiagram-VBNYF7ZC-Bv6rqHBg.js} +1 -1
  84. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-BCYZJLAT.js → c4Diagram-5PPSVZJV-B8eHr0oz.js} +1 -1
  85. package/dist/worker/console/static/assets/channel-BU5gOilw.js +1 -0
  86. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-D8K6adhU.js → chunk-2GRJ4B5K-DYwR0im2.js} +1 -1
  87. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-DkT1Q78b.js → chunk-2Q5K7J3B-D2WPGqXt.js} +1 -1
  88. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DuhvpIr7.js → chunk-5RXB4S5H-CQISJ_I7.js} +1 -1
  89. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BnK6dC49.js → chunk-5VM5RSS4-C0o2Du1e.js} +1 -1
  90. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-DPz__z7r.js → chunk-6Q2QTUOP-4f8kr-U7.js} +1 -1
  91. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-0kkppM2j.js → chunk-GF5L2VYU-D_OWvXzX.js} +1 -1
  92. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BB41iK5t.js → chunk-JWPE2WC7-CasdPz5X.js} +1 -1
  93. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-CiVrxKHU.js → chunk-KBJHAD2P-Cj8lRrla.js} +1 -1
  94. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-C2h9Xje1.js → chunk-RYQCIY6F-CUvD1FSd.js} +1 -1
  95. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-3iOSHdbM.js → chunk-XXDRQBXY-CqLw_eqB.js} +1 -1
  96. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-DIzKJGHr.js +1 -0
  97. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-DIzKJGHr.js +1 -0
  98. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-BN3A7tkk.js → cose-bilkent-JH36ORCC-ku-WqJPx.js} +1 -1
  99. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-CTuBy0Or.js → cynefin-VYW2F7L2-Bq_PYDhl.js} +1 -1
  100. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-wb6tUlMN.js → cynefinDiagram-MW4NZA55-BiGZV641.js} +1 -1
  101. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-GP1Ivx8B.js → dagre-VZM6K2ZE-C4JRlglF.js} +1 -1
  102. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-ejrcK6L0.js → diagram-7IWD3JNH-B0dNeWYG.js} +1 -1
  103. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-YFkCCvUU.js → diagram-B4RE2ZJO-Cj35YvYM.js} +1 -1
  104. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-B4rrvIaL.js → diagram-LBJQPF4R-uzQoJ2-8.js} +1 -1
  105. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C-YIZcUf.js → diagram-Q27KOJAE-D1a-Buoz.js} +1 -1
  106. package/dist/worker/console/static/assets/{diagram-UB23O5K3-BPF5wcL1.js → diagram-UB23O5K3-XjRrLRSs.js} +1 -1
  107. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-CU5SzXjO.js → ebnfDiagram-BXEA7PRR-Da_O24cW.js} +1 -1
  108. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CpL414DE.js → erDiagram-JOGREHBK-BLJ8jrYU.js} +1 -1
  109. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-MrhLzNau.js → flowDiagram-UKHOOZJN-B9GrLjM0.js} +1 -1
  110. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-Bg4qFuUo.js → ganttDiagram-PKOTCBZU-CeJ0TqiK.js} +1 -1
  111. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-ColxSXLR.js → gitGraphDiagram-DS77QQ5N-Bm2eNNFX.js} +1 -1
  112. package/dist/worker/console/static/assets/index-H9rFJiGL.css +1 -0
  113. package/dist/worker/console/static/assets/index-xwu9GxEc.js +451 -0
  114. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-Czvtm6gc.js → infoDiagram-6WML65LV-DB26i3d8.js} +1 -1
  115. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-B7Xp8HyJ.js → ishikawaDiagram-WSZJBQD7-BOGRyeZT.js} +1 -1
  116. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-DWYZcvph.js → journeyDiagram-NVQOT4AX-CZRoBO_6.js} +1 -1
  117. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-KTLZRUjx.js → kanban-definition-27J2QSJJ-qlWhJyoB.js} +1 -1
  118. package/dist/worker/console/static/assets/{linear-_Exn7bfl.js → linear-CfUiDDB3.js} +1 -1
  119. package/dist/worker/console/static/assets/{mermaid.core-Cxg8kX8V.js → mermaid.core-BQe6fpqj.js} +5 -5
  120. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-oKrlo2Bt.js → mindmap-definition-FAOFIHXS-zFzWHw64.js} +1 -1
  121. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-XAeteiNd.js → pegDiagram-VL7TDLO6-DFGUqjZO.js} +1 -1
  122. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BTf1K-lp.js → pieDiagram-7S7Q4E2Y-BB5i0l8Z.js} +1 -1
  123. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-C0IlY0Jf.js → quadrantDiagram-CIZ2JOQS-obbVZ_X5.js} +1 -1
  124. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-BVbKtZhW.js → railroadDiagram-AXF67PYL-BwdaNzc1.js} +1 -1
  125. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-C5e4JFcr.js → requirementDiagram-LRYGKXZP-CkTJaugh.js} +1 -1
  126. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-Cz30hc29.js → sankeyDiagram-W5VNT64P-BwJ-hIgq.js} +1 -1
  127. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DS33n6d0.js → sequenceDiagram-SI44F4Z6-BzSgmm7w.js} +1 -1
  128. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-46w7v-9T.js → sizeCapture-X5ZJPWSS-Bn3oj5Q1.js} +1 -1
  129. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-pbcD5SsZ.js → stateDiagram-OKZ733FA-dxhGtL8K.js} +1 -1
  130. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-Cld2qK9v.js +1 -0
  131. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DuivYBSj.js → swimlanes-SLNWSIFB-BLpEInya.js} +2 -2
  132. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-TIHpiT7w.js +8 -0
  133. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-Cb9VZVIl.js → timeline-definition-Z64GVDOM-ChJGYcXy.js} +1 -1
  134. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-D2-mfOgR.js → vennDiagram-T6HMQDX7-DK-qjRer.js} +1 -1
  135. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DeS2aC76.js → wardleyDiagram-T6FBY63Y-3qeaWAg-.js} +1 -1
  136. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-WGsrFjxH.js → xychartDiagram-ELKLHX3M-CootlyP9.js} +1 -1
  137. package/dist/worker/console/static/index.html +7 -2
  138. package/dist/worker/console/static-src/app/useOperatorActions.js +3 -2
  139. package/dist/worker/console/static-src/app/useRunProgress.js +9 -2
  140. package/dist/worker/console/static-src/operator-chat/dag-progress-link.js +22 -0
  141. package/dist/worker/console/static-src/operator-chat/useChatSessions.js +2 -0
  142. package/dist/worker/console/static-src/operator-chat/useChatThread.js +6 -0
  143. package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +28 -3
  144. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +106 -0
  145. package/dist/worker/console/static-src/shell/console-update-reload.js +25 -0
  146. package/dist/worker/console/workspace-context.js +28 -112
  147. package/dist/worker/console/workspace-registry.js +2 -2
  148. package/dist/worker/continuation/worker-continuation.js +278 -0
  149. package/dist/worker/observability/read-model.js +4 -0
  150. package/dist/worker/observe/health.js +1 -1
  151. package/dist/worker/observe/node-transparency.js +572 -0
  152. package/dist/worker/observe/routes.js +51 -1
  153. package/dist/worker/observe/static/api.js +69 -5
  154. package/dist/worker/observe/static/dag-context-reason-labels.d.ts +9 -0
  155. package/dist/worker/observe/static/dag-context-reason-labels.js +120 -0
  156. package/dist/worker/observe/static/dag-node-purpose.js +0 -5
  157. package/dist/worker/observe/static/state.js +3 -1
  158. package/dist/worker/observe/static/styles.css +1037 -126
  159. package/dist/worker/observe/static/views/dag-inspector.js +1217 -65
  160. package/dist/worker/observe/static/views/session-timeline.js +121 -25
  161. package/dist/worker/outcomes/adapters.js +19 -0
  162. package/dist/worker/outcomes/types.js +1 -0
  163. package/dist/worker/pool/attempt-lease.js +97 -66
  164. package/dist/worker/pool/begin-attempt-with-lease.js +1 -0
  165. package/dist/worker/pool/reconcile.js +46 -1
  166. package/dist/worker/pool/run-store.js +2 -0
  167. package/dist/worker/pool/state-projection.js +2 -0
  168. package/dist/worker/task-spec/workflow-routing.js +8 -3
  169. package/dist/workflows/dag/artifact-bindings.js +149 -0
  170. package/dist/workflows/dag/artifact-revision-schema-registry.js +31 -0
  171. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +99 -4
  172. package/dist/workflows/dag/backend-test-markdown-workflow.js +13 -1
  173. package/dist/workflows/dag/backend-test-result-contract.js +1 -1
  174. package/dist/workflows/dag/backend-test-writer-completeness.js +45 -3
  175. package/dist/workflows/dag/budget-enforcement.js +10 -0
  176. package/dist/workflows/dag/context-receipt.js +305 -0
  177. package/dist/workflows/dag/context-transfer/context-bundle.js +423 -0
  178. package/dist/workflows/dag/context-transfer/operator-actions.js +61 -0
  179. package/dist/workflows/dag/context-transfer/renderers.js +93 -0
  180. package/dist/workflows/dag/contract-validator-registrations.js +2 -1
  181. package/dist/workflows/dag/frontend-implementation-contract.js +162 -932
  182. package/dist/workflows/dag/frontend-plan-render.js +1 -2
  183. package/dist/workflows/dag/frontend-prewrite-gate.js +349 -255
  184. package/dist/workflows/dag/frontend-recovery-plan.js +10 -17
  185. package/dist/workflows/dag/frontend-recovery-run.js +20 -33
  186. package/dist/workflows/dag/frontend-repair.js +432 -1
  187. package/dist/workflows/dag/frontend-review-context.js +15 -261
  188. package/dist/workflows/dag/frontend-verification-trace.js +24 -249
  189. package/dist/workflows/dag/frontend-worktree-diff.js +17 -250
  190. package/dist/workflows/dag/frontend-writer-rollback.js +32 -0
  191. package/dist/workflows/dag/init-hybrid.js +740 -718
  192. package/dist/workflows/dag/interrupt-request.js +0 -7
  193. package/dist/workflows/dag/node-execution.js +136 -759
  194. package/dist/workflows/dag/path-safety.js +1 -0
  195. package/dist/workflows/dag/prompt.js +30 -38
  196. package/dist/workflows/dag/report.js +1 -37
  197. package/dist/workflows/dag/rerun-feedback.js +1 -256
  198. package/dist/workflows/dag/rerun-plan.js +557 -11
  199. package/dist/workflows/dag/rerun-run.js +601 -38
  200. package/dist/workflows/dag/rerun-task.js +0 -29
  201. package/dist/workflows/dag/retry-policy.js +109 -214
  202. package/dist/workflows/dag/runner.js +142 -430
  203. package/dist/workflows/dag/scheduler.js +16 -114
  204. package/dist/workflows/dag/skill-snapshot.js +17 -0
  205. package/dist/workflows/dag/types.js +195 -246
  206. package/dist/workflows/dag/validate.js +12 -28
  207. package/docs/architecture/runtime-boundaries.md +6 -6
  208. package/docs/architecture/worker-and-feature.md +1 -1
  209. package/docs/init-surface.manifest.json +12 -30
  210. package/docs/skills/vetted-skill-registry.md +2 -4
  211. package/docs/templates/README.md +0 -2
  212. package/docs/templates/agent-dag-report.schema.json +2 -8
  213. package/docs/templates/agent-dag.schema.json +33 -1
  214. package/docs/templates/backend-test-dag.json +18 -18
  215. package/docs/templates/frontend-implementation-contract.schema.json +1 -4
  216. package/docs/templates/product-line/task.yaml +1 -1
  217. package/harness.json +3 -3
  218. package/package.json +3 -1
  219. package/skills/frontend-bounded-implement/SKILL.md +14 -15
  220. package/skills/frontend-design-review/SKILL.md +41 -22
  221. package/skills/frontend-implementation/SKILL.md +52 -0
  222. package/skills/frontend-implementation/references/code-standards.md +33 -0
  223. package/skills/frontend-implementation/references/design-spec.md +56 -0
  224. package/skills/frontend-implementation/references/node-contracts.md +31 -0
  225. package/skills/frontend-review/SKILL.md +15 -20
  226. package/skills/frontend-review/references/review-findings.md +7 -6
  227. package/skills/frontend-verification/SKILL.md +1 -1
  228. package/skills/loop-agent/references/command-reference.md +6 -1
  229. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  230. package/dist/commands/dag-follow-up.js +0 -138
  231. package/dist/executors/pi-read-budget-policy.js +0 -239
  232. package/dist/worker/console/frontend-human-decision-adapter.js +0 -19
  233. package/dist/worker/console/frontend-split-operation-adapter.js +0 -20
  234. package/dist/worker/console/operation-store.js +0 -389
  235. package/dist/worker/console/static/assets/channel-bnXW0U3C.js +0 -1
  236. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-rZpq_twR.js +0 -1
  237. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-rZpq_twR.js +0 -1
  238. package/dist/worker/console/static/assets/index-D3CC4eUz.css +0 -1
  239. package/dist/worker/console/static/assets/index-DLt4ZFvD.js +0 -437
  240. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-zBMYiUyi.js +0 -1
  241. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-d_rms-5i.js +0 -8
  242. package/dist/worker/console/static-src/active-run-badge.js +0 -17
  243. package/dist/worker/materialize/frontend-split-task-materializer.js +0 -72
  244. package/dist/workflows/dag/dag-retry-schema.js +0 -138
  245. package/dist/workflows/dag/frontend-closeout.js +0 -221
  246. package/dist/workflows/dag/frontend-design-policy.js +0 -400
  247. package/dist/workflows/dag/frontend-human-decision.js +0 -182
  248. package/dist/workflows/dag/frontend-provider-capability-matrix.js +0 -159
  249. package/dist/workflows/dag/frontend-read-budgets.js +0 -12
  250. package/dist/workflows/dag/frontend-recovery-capsule.js +0 -455
  251. package/dist/workflows/dag/frontend-recovery-controller.js +0 -202
  252. package/dist/workflows/dag/frontend-recovery-lineage.js +0 -178
  253. package/dist/workflows/dag/frontend-review-findings.js +0 -270
  254. package/dist/workflows/dag/frontend-shadow-dual-write.js +0 -914
  255. package/dist/workflows/dag/frontend-shape-capsule-store.js +0 -191
  256. package/dist/workflows/dag/frontend-shape-facts.js +0 -409
  257. package/dist/workflows/dag/frontend-shape.js +0 -427
  258. package/dist/workflows/dag/frontend-source-fidelity-ledger.js +0 -108
  259. package/dist/workflows/dag/frontend-split-application-service.js +0 -203
  260. package/dist/workflows/dag/frontend-split-orchestrator.js +0 -899
  261. package/dist/workflows/dag/frontend-typed-event-store.js +0 -452
  262. package/dist/workflows/dag/frontend-typed-event-transaction.js +0 -180
  263. package/dist/workflows/dag/frontend-writer-admission.js +0 -285
  264. package/dist/workflows/dag/frontend-writer-status.js +0 -256
  265. package/dist/workflows/dag/recovery-lease.js +0 -80
  266. package/docs/templates/frontend-implementation-dag.json +0 -89
  267. package/docs/templates/spec-registry.schema.json +0 -45
  268. package/skills/frontend-bounded-implement/references/code-standards.md +0 -19
  269. package/skills/frontend-contract/SKILL.md +0 -23
  270. package/skills/frontend-contract/references/contract-protocol.md +0 -34
  271. package/skills/frontend-plan/SKILL.md +0 -26
  272. package/skills/frontend-plan/references/decision-contract.md +0 -37
  273. package/skills/frontend-plan/references/design-decisions.md +0 -17
  274. package/skills/frontend-scout/SKILL.md +0 -25
  275. package/skills/frontend-scout/references/design-evidence.md +0 -16
  276. package/skills/frontend-scout/references/scout-evidence.md +0 -23
  277. /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,10 +65,6 @@ function paramsOf(req) {
64
65
  function str(v) {
65
66
  return typeof v === "string" && v.trim() ? v.trim() : undefined;
66
67
  }
67
- function appendExplicitTaskKindArg(args, taskKind, taskKindExplicit) {
68
- if (taskKindExplicit)
69
- args.push("--task-kind", taskKind);
70
- }
71
68
  const TASK_ID_PLACEHOLDER_RE = /[<>]|^(?:id|task-?id|your-task-id|todo|tbd)$/i;
72
69
  /** Mirror of runtime GENERIC_TASK_SLUGS (not exported there); keep in sync. */
73
70
  const GENERIC_SLUG_SET = new Set(["test", "fix", "tmp", "new-task"]);
@@ -485,7 +482,7 @@ async function buildPromptOverrideCliArgs(ctx, overrides) {
485
482
  }
486
483
  return args;
487
484
  }
488
- async function acceptOperation(ctx, input) {
485
+ export async function acceptOperation(ctx, input) {
489
486
  const created = await ctx.operations.create({
490
487
  clientRequestId: input.clientRequestId,
491
488
  action: input.action,
@@ -521,12 +518,55 @@ async function acceptOperation(ctx, input) {
521
518
  },
522
519
  };
523
520
  }
521
+ if (input.onAdmitted) {
522
+ try {
523
+ await input.onAdmitted(created.operation);
524
+ }
525
+ catch {
526
+ // Lifecycle observation must never block admission.
527
+ }
528
+ }
529
+ if (input.prepare) {
530
+ try {
531
+ await input.prepare();
532
+ }
533
+ catch (error) {
534
+ const message = error instanceof Error ? error.message : String(error);
535
+ const preparedFailure = input.prepareFailure?.(error);
536
+ await ctx.operations.update(created.operation.operationId, {
537
+ state: "failed",
538
+ startedAt: created.operation.createdAt,
539
+ finishedAt: new Date().toISOString(),
540
+ errorCode: preparedFailure?.errorCode ?? "INVALID_INPUT",
541
+ errorMessage: message,
542
+ });
543
+ return {
544
+ kind: "error",
545
+ status: preparedFailure?.status ?? 400,
546
+ body: preparedFailure?.body ?? operatorFailed({
547
+ command: input.action,
548
+ outcome: "blocked",
549
+ code: "INVALID_INPUT",
550
+ message,
551
+ }),
552
+ };
553
+ }
554
+ }
555
+ const transferObserver = contextTransferSettledObserver(ctx, input.action, input.actionParams);
524
556
  const runnerDeps = {
525
557
  store: ctx.operations,
526
558
  events: ctx.events,
527
559
  client: ctx.client,
528
560
  repoRoot: ctx.repoRoot,
561
+ env: { ...process.env, LOOP_CONSOLE_APP_DATA: ctx.appData.root },
529
562
  runCommand: ctx.runCommand,
563
+ beforeTerminal: input.beforeTerminal,
564
+ onSettled: async (operation, state, info) => {
565
+ // Diagnostics are best-effort and must not prevent authoritative Worker
566
+ // settlement from running.
567
+ await Promise.resolve(transferObserver?.(operation, state, info)).catch(() => undefined);
568
+ await input.onSettled?.(operation, state, info);
569
+ },
530
570
  };
531
571
  scheduleOperation(created.operation.operationId, runnerDeps);
532
572
  return {
@@ -540,83 +580,62 @@ async function acceptOperation(ctx, input) {
540
580
  },
541
581
  };
542
582
  }
543
- function splitRuntimeMissing(action) {
544
- return {
545
- kind: "error",
546
- status: 503,
547
- body: operatorFailed({
548
- command: action,
549
- outcome: "blocked",
550
- code: "INTERNAL_ERROR",
551
- message: `${action} is unavailable: frontend split runtime is not wired`,
552
- }),
583
+ /**
584
+ * Map artifact revision / rerun operation outcomes onto the append-only
585
+ * context-transfer lifecycle event log. Only stages the Console truly
586
+ * observes (admission + settle) are recorded; CLI-kernel-internal stages
587
+ * stay in the kernel. Unknown actions emit nothing.
588
+ */
589
+ function contextTransferSettledObserver(ctx, action, actionParams) {
590
+ if (action !== "artifactRevisionStage" &&
591
+ action !== "artifactRevisionPlan" &&
592
+ action !== "artifactRevisionExecute") {
593
+ return undefined;
594
+ }
595
+ const strParam = (key) => {
596
+ const value = actionParams[key];
597
+ return typeof value === "string" ? value.trim() : undefined;
553
598
  };
554
- }
555
- function numOf(v) {
556
- return typeof v === "number" ? v : Number(v);
557
- }
558
- function splitCommandBase(p) {
559
- return {
560
- operationId: str(p.operationId) ?? "",
561
- expectedRevision: numOf(p.expectedRevision),
562
- expectedParentDigest: str(p.expectedParentDigest) ?? "",
563
- expectedManifestDigest: str(p.expectedManifestDigest) ?? "",
599
+ const baseFields = {
600
+ runId: strParam("runId"),
601
+ nodeId: strParam("nodeId"),
602
+ revisionId: strParam("revisionId"),
564
603
  };
565
- }
566
- function splitCommandDispatch(action, result) {
567
- if (result.outcome === "conflict") {
568
- return {
569
- kind: "error",
570
- status: 409,
571
- body: operatorFailed({
572
- command: action,
573
- outcome: "conflict",
574
- code: "CONFLICT",
575
- message: "frontend split CAS conflict (stale revision or binding)",
576
- }),
577
- };
578
- }
579
- return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
580
- }
581
- async function runSplitAction(action, run) {
582
- try {
583
- const result = await run();
584
- if (result && typeof result === "object" && "outcome" in result) {
585
- return splitCommandDispatch(action, result);
604
+ return (operation, state, info) => {
605
+ let event;
606
+ if (action === "artifactRevisionStage") {
607
+ event = info.ok ? "artifact_revision.validated" : "artifact_revision.rejected";
586
608
  }
587
- return {
588
- kind: "sync",
589
- status: 200,
590
- body: operatorSucceeded(action, result),
591
- };
592
- }
593
- catch (error) {
594
- return invalid(action, error instanceof Error ? error.message : String(error));
595
- }
596
- }
597
- function humanDecisionDispatch(action, result) {
598
- if (result.outcome === "rejected") {
599
- return {
600
- kind: "error",
601
- status: 409,
602
- body: operatorFailed({
603
- command: action,
604
- outcome: "conflict",
605
- code: "CONFLICT",
606
- message: result.reason,
607
- details: { projection: result.projection },
608
- }),
609
- };
610
- }
611
- return { kind: "sync", status: 200, body: operatorSucceeded(action, result) };
612
- }
613
- async function runHumanDecisionAction(action, run) {
614
- try {
615
- return humanDecisionDispatch(action, await run());
616
- }
617
- catch (error) {
618
- return invalid(action, error instanceof Error ? error.message : String(error));
619
- }
609
+ else if (action === "artifactRevisionPlan") {
610
+ event = info.ok ? "artifact_rerun.plan_created" : "artifact_rerun.blocked";
611
+ }
612
+ else if (state === "needs-reconcile") {
613
+ event = "artifact_rerun.needs_reconcile";
614
+ }
615
+ else {
616
+ event = info.ok ? "artifact_rerun.finished" : "artifact_rerun.failed";
617
+ }
618
+ // The stage CLI assigns the revision id; it only exists in the settle
619
+ // result, never in admission params.
620
+ let resultRevisionId;
621
+ const resultRevision = operation.result
622
+ ?.revision;
623
+ if (resultRevision && typeof resultRevision === "object") {
624
+ resultRevisionId = resultRevision.revisionId;
625
+ }
626
+ return recordContextTransferEvent({
627
+ appData: ctx.appData,
628
+ event,
629
+ fields: {
630
+ ...baseFields,
631
+ ...(typeof resultRevisionId === "string"
632
+ ? { revisionId: resultRevisionId }
633
+ : {}),
634
+ operationId: operation.operationId,
635
+ ...(info.ok ? {} : { reasonCode: info.errorCode ?? "INTERNAL_ERROR" }),
636
+ },
637
+ }).catch(() => undefined);
638
+ };
620
639
  }
621
640
  async function acceptConsoleUpdateAndInit(ctx, clientRequestId, channel) {
622
641
  if (!ctx.consoleUpdateExecutor) {
@@ -1959,7 +1978,7 @@ export async function dispatchOperatorAction(ctx, req) {
1959
1978
  const staged = await stageUtf8Text(ctx.appData, content, {
1960
1979
  extension: ".md",
1961
1980
  });
1962
- const importArgs = [
1981
+ const imported = await run([
1963
1982
  "task",
1964
1983
  "advance",
1965
1984
  taskId,
@@ -1968,10 +1987,8 @@ export async function dispatchOperatorAction(ctx, req) {
1968
1987
  staged.path,
1969
1988
  "--role",
1970
1989
  "requirement",
1971
- ];
1972
- appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
1973
- importArgs.push("--json");
1974
- const imported = await run(importArgs, {
1990
+ "--json",
1991
+ ], {
1975
1992
  cwd: ctx.repoRoot,
1976
1993
  artifactName: "import-prd-task-advance",
1977
1994
  expectJson: true,
@@ -2946,75 +2963,6 @@ export async function dispatchOperatorAction(ctx, req) {
2946
2963
  }),
2947
2964
  };
2948
2965
  }
2949
- case "frontendSplitWakeup": {
2950
- if (!ctx.splitOrchestrator)
2951
- return splitRuntimeMissing(action);
2952
- return runSplitAction(action, () => ctx.splitOrchestrator.wakeupChildren(splitCommandBase(p)));
2953
- }
2954
- case "frontendSplitChildCallback": {
2955
- if (!ctx.splitOrchestrator)
2956
- return splitRuntimeMissing(action);
2957
- return runSplitAction(action, () => ctx.splitOrchestrator.childCallback({
2958
- ...splitCommandBase(p),
2959
- observation: p.observation,
2960
- }));
2961
- }
2962
- case "frontendSplitWakeupIntegration": {
2963
- if (!ctx.splitOrchestrator)
2964
- return splitRuntimeMissing(action);
2965
- return runSplitAction(action, () => ctx.splitOrchestrator.wakeupIntegration(splitCommandBase(p)));
2966
- }
2967
- case "frontendSplitIntegrationCallback": {
2968
- if (!ctx.splitOrchestrator)
2969
- return splitRuntimeMissing(action);
2970
- return runSplitAction(action, () => ctx.splitOrchestrator.integrationCallback({
2971
- ...splitCommandBase(p),
2972
- completion: p.completion,
2973
- }));
2974
- }
2975
- case "frontendSplitFinalize": {
2976
- if (!ctx.splitOrchestrator)
2977
- return splitRuntimeMissing(action);
2978
- return runSplitAction(action, () => ctx.splitOrchestrator.finalize(splitCommandBase(p)));
2979
- }
2980
- case "frontendHumanDecisionMaterialize": {
2981
- if (!ctx.humanDecisionAdapter)
2982
- return splitRuntimeMissing(action);
2983
- return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.materialize({
2984
- operationId: str(p.operationId) ?? "",
2985
- expectedRecordRevision: numOf(p.expectedRecordRevision),
2986
- expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
2987
- envelope: p.envelope,
2988
- }));
2989
- }
2990
- case "frontendHumanDecisionApprove": {
2991
- if (!ctx.humanDecisionAdapter)
2992
- return splitRuntimeMissing(action);
2993
- return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.consume({
2994
- operationId: str(p.operationId) ?? "",
2995
- expectedRecordRevision: numOf(p.expectedRecordRevision),
2996
- expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
2997
- receipt: p.receipt,
2998
- currentTargetDigest: str(p.currentTargetDigest) ?? "",
2999
- now: str(p.now) ?? new Date().toISOString(),
3000
- }));
3001
- }
3002
- case "frontendSplitInitialize": {
3003
- if (!ctx.humanDecisionAdapter)
3004
- return splitRuntimeMissing(action);
3005
- return runHumanDecisionAction(action, () => ctx.humanDecisionAdapter.initializeSplit({
3006
- operationId: str(p.operationId) ?? "",
3007
- expectedRecordRevision: numOf(p.expectedRecordRevision),
3008
- expectedProjectionDigest: str(p.expectedProjectionDigest) ?? "",
3009
- execution: p.execution,
3010
- manifest: p.manifest,
3011
- receipt: p.receipt,
3012
- currentTargetDigest: str(p.currentTargetDigest) ?? "",
3013
- now: str(p.now) ?? new Date().toISOString(),
3014
- activeWriterOperationId: str(p.activeWriterOperationId) ?? null,
3015
- activeProviderOperationId: str(p.activeProviderOperationId) ?? null,
3016
- }));
3017
- }
3018
2966
  default: {
3019
2967
  // M5 official-command coverage uses one generic tail for newly registered
3020
2968
  // CLI actions. It remains inside dispatchOperatorAction (the sole dispatch
@@ -3399,14 +3347,7 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3399
3347
  const title = identity.title;
3400
3348
  const run = ctx.runCommand ?? ((a, o) => ctx.client.run(a, o));
3401
3349
  // Standard lifecycle entry: task advance create + PRD import(s).
3402
- // Preserve an explicitly selected business workflow from the very first
3403
- // task.json write. The task lifecycle otherwise defaults new tasks to
3404
- // standard, which caused frontend tasks to be promoted only during the
3405
- // final intake pass.
3406
- const createArgs = ["task", "advance", taskId, title];
3407
- appendExplicitTaskKindArg(createArgs, taskKind, taskKindExplicit);
3408
- createArgs.push("--json");
3409
- const advanceCreate = await run(createArgs, {
3350
+ const advanceCreate = await run(["task", "advance", taskId, title, "--json"], {
3410
3351
  cwd: ctx.repoRoot,
3411
3352
  artifactName: "bootstrap-task-advance-create",
3412
3353
  expectJson: true,
@@ -3440,7 +3381,7 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3440
3381
  const staged = await stageUtf8Text(ctx.appData, text, {
3441
3382
  extension: ".md",
3442
3383
  });
3443
- const importArgs = [
3384
+ const imported = await run([
3444
3385
  "task",
3445
3386
  "advance",
3446
3387
  taskId,
@@ -3448,10 +3389,8 @@ async function dispatchBootstrapFromPrd(ctx, p) {
3448
3389
  staged.path,
3449
3390
  "--role",
3450
3391
  role,
3451
- ];
3452
- appendExplicitTaskKindArg(importArgs, taskKind, taskKindExplicit);
3453
- importArgs.push("--json");
3454
- const imported = await run(importArgs, {
3392
+ "--json",
3393
+ ], {
3455
3394
  cwd: ctx.repoRoot,
3456
3395
  artifactName: `bootstrap-task-advance-prd-${label}`,
3457
3396
  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;
@@ -98,7 +99,9 @@ function getNpmRegistry() {
98
99
  /** 从 npm 配置的仓库拉取某包的全部已发布版本 + latest。 */
99
100
  export async function listPiPluginVersions(name) {
100
101
  const registry = (await getNpmRegistry()).replace(/\/+$/, "");
101
- const url = `${registry}/${encodeURIComponent(name).replace(/%2F/g, "/")}`;
102
+ // scoped 包名整段编码(@scope/name → %40scope%2Fname):与 npm 客户端请求
103
+ // packument 的形式一致,npmjs.org 与内网 Nexus(要求 %2F 不还原)都接受。
104
+ const url = `${registry}/${encodeURIComponent(name)}`;
102
105
  try {
103
106
  const res = await fetch(url, {
104
107
  headers: { accept: "application/json", "user-agent": "loop-agent/1.0" },
@@ -123,6 +126,62 @@ export async function listPiPluginVersions(name) {
123
126
  };
124
127
  }
125
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
+ }
126
185
  function runPi(args) {
127
186
  return new Promise((resolve) => {
128
187
  mkdirSync(getPiAgentDir(), { recursive: true });