@zhushanwen/pi-subagent-workflow 8.6.0 → 8.7.0

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 (347) hide show
  1. package/package.json +9 -13
  2. package/relay/relay.mjs +1 -1
  3. package/src/host/__tests__/pi-host.test.ts +214 -0
  4. package/src/host/pi-host.ts +109 -0
  5. package/src/index.ts +89 -32
  6. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  7. package/src/injectors/__tests__/engine-section-stability.test.ts +341 -0
  8. package/src/injectors/__tests__/subagent-list-injector.test.ts +5 -5
  9. package/src/injectors/__tests__/workflow-list-injector.test.ts +5 -5
  10. package/src/injectors/engine-awareness.ts +123 -0
  11. package/src/injectors/model-list-injector.ts +1 -1
  12. package/src/injectors/subagent-list-injector.ts +8 -8
  13. package/src/injectors/workflow-list-injector.ts +8 -8
  14. package/src/interface/__tests__/detectors.test.ts +3 -3
  15. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  16. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  17. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  18. package/src/interface/bg-notify-render.ts +4 -4
  19. package/src/interface/commands.ts +3 -3
  20. package/src/interface/format.ts +2 -2
  21. package/src/interface/helpers.ts +1 -1
  22. package/src/interface/list-component.ts +4 -4
  23. package/src/interface/list-shared.ts +2 -2
  24. package/src/interface/list-view.ts +2 -2
  25. package/src/interface/subagent-actions.ts +263 -11
  26. package/src/interface/subagent-tool-schema.ts +20 -13
  27. package/src/interface/subagent-tool.ts +11 -6
  28. package/src/interface/subagents.ts +3 -3
  29. package/src/interface/tool-render.ts +34 -2
  30. package/src/interface/tool-workflow-script.ts +4 -4
  31. package/src/interface/tool-workflow.ts +6 -6
  32. package/src/interface/views/WorkflowsView.ts +5 -5
  33. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  34. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  35. package/src/interface/views/detail-content.ts +4 -4
  36. package/src/interface/views/format.ts +4 -4
  37. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +11 -11
  38. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  39. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  40. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  41. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  42. package/src/execution/__tests__/alive-store.test.ts +0 -147
  43. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  44. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  45. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  46. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  47. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  48. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  49. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  50. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  51. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  52. package/src/execution/__tests__/config.test.ts +0 -110
  53. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  54. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  55. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  56. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  57. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  59. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  60. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  61. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  63. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  64. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  65. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  66. package/src/execution/__tests__/format.test.ts +0 -458
  67. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  68. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  69. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  70. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  71. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  72. package/src/execution/__tests__/host-mode.test.ts +0 -87
  73. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  74. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  77. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  78. package/src/execution/__tests__/list-component.test.ts +0 -401
  79. package/src/execution/__tests__/list-fields.test.ts +0 -140
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  82. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  83. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  84. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  87. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  88. package/src/execution/__tests__/output-collector.test.ts +0 -358
  89. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  90. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  91. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  92. package/src/execution/__tests__/record-store.test.ts +0 -1057
  93. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  94. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  95. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  96. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  97. package/src/execution/__tests__/relay-env.test.ts +0 -42
  98. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  99. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  100. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  101. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  102. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  103. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  104. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  105. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  106. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  107. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  108. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  109. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  110. package/src/execution/__tests__/session-pending.test.ts +0 -197
  111. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  112. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  113. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  114. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  115. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  116. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  117. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  118. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  119. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  120. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  121. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  122. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  123. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  124. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  125. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  126. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  127. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  128. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  130. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  131. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  132. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  133. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  134. package/src/execution/__tests__/tool-action.test.ts +0 -476
  135. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  137. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  138. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  139. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  140. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  141. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  142. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  143. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  144. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  145. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  146. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  147. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  148. package/src/execution/agent-registry.ts +0 -199
  149. package/src/execution/agent-result-mapper.ts +0 -90
  150. package/src/execution/alive-store.ts +0 -92
  151. package/src/execution/argv-mirror.ts +0 -113
  152. package/src/execution/best-effort.ts +0 -38
  153. package/src/execution/channel-registry-access.ts +0 -144
  154. package/src/execution/concurrency-pool.ts +0 -116
  155. package/src/execution/config.ts +0 -96
  156. package/src/execution/dialog-queue.ts +0 -330
  157. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  158. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  159. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  160. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  161. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  162. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  163. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  164. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  165. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  166. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  167. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  168. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  169. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  170. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  171. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  172. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  173. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  174. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  175. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  176. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  177. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  178. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  179. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  180. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  181. package/src/execution/engine/common/data-dir.ts +0 -62
  182. package/src/execution/engine/common/errors.ts +0 -183
  183. package/src/execution/engine/common/event-journal.ts +0 -254
  184. package/src/execution/engine/common/journal-replay.ts +0 -62
  185. package/src/execution/engine/common/kill-chain.ts +0 -221
  186. package/src/execution/engine/common/nesting-guard.ts +0 -50
  187. package/src/execution/engine/common/persona-router.ts +0 -108
  188. package/src/execution/engine/common/pool-manager.ts +0 -226
  189. package/src/execution/engine/common/schema-emulation.ts +0 -189
  190. package/src/execution/engine/common/session-view-projection.ts +0 -51
  191. package/src/execution/engine/engine-discovery.ts +0 -65
  192. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  193. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  194. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  195. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  196. package/src/execution/engine/engines/pi/reader.ts +0 -48
  197. package/src/execution/engine/engines/pi/registration.ts +0 -35
  198. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  199. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  200. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  201. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  202. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  203. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  204. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  207. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  208. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  209. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  210. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  211. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  212. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  213. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  214. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  215. package/src/execution/engine/host-task-spec.ts +0 -47
  216. package/src/execution/engine/model-prompt.ts +0 -59
  217. package/src/execution/engine/paths.ts +0 -42
  218. package/src/execution/engine/port.ts +0 -153
  219. package/src/execution/engine/registry.ts +0 -123
  220. package/src/execution/engine/routing.ts +0 -218
  221. package/src/execution/engine/types.ts +0 -309
  222. package/src/execution/execute-options-mapper.ts +0 -112
  223. package/src/execution/execution-record.ts +0 -965
  224. package/src/execution/finalize-record.ts +0 -251
  225. package/src/execution/finalized-marker.ts +0 -51
  226. package/src/execution/get-state-handshake.ts +0 -104
  227. package/src/execution/host-mode.ts +0 -56
  228. package/src/execution/idle-gc.ts +0 -47
  229. package/src/execution/lifecycle-manager.ts +0 -513
  230. package/src/execution/lifecycle-predicates.ts +0 -65
  231. package/src/execution/manifest-store.ts +0 -256
  232. package/src/execution/model-config-service.ts +0 -219
  233. package/src/execution/model-resolver.ts +0 -248
  234. package/src/execution/notifier.ts +0 -330
  235. package/src/execution/notify-ledger.ts +0 -580
  236. package/src/execution/output-collector.ts +0 -228
  237. package/src/execution/path-encoding.ts +0 -60
  238. package/src/execution/pi-invocation.ts +0 -120
  239. package/src/execution/record-entry.ts +0 -132
  240. package/src/execution/record-store.ts +0 -1234
  241. package/src/execution/relay-env.ts +0 -37
  242. package/src/execution/session-context-resolver.ts +0 -64
  243. package/src/execution/session-file-gc.ts +0 -120
  244. package/src/execution/session-pending.ts +0 -164
  245. package/src/execution/session-reconstructor.ts +0 -678
  246. package/src/execution/session-runner.ts +0 -1781
  247. package/src/execution/sessions-index.ts +0 -304
  248. package/src/execution/spawn-event-adapter.ts +0 -363
  249. package/src/execution/stdin-writer.ts +0 -198
  250. package/src/execution/stream-sink.ts +0 -126
  251. package/src/execution/subagent-service.ts +0 -2141
  252. package/src/execution/subprocess-agent-runner.ts +0 -317
  253. package/src/execution/temp-prompt.ts +0 -62
  254. package/src/execution/tombstone-store.ts +0 -72
  255. package/src/execution/turn-limiter.ts +0 -102
  256. package/src/execution/types.ts +0 -973
  257. package/src/execution/ui-channels.ts +0 -216
  258. package/src/execution/ui-interaction-model.ts +0 -48
  259. package/src/execution/ui-request-handler-factory.ts +0 -212
  260. package/src/execution/ui-request-observability.ts +0 -81
  261. package/src/execution/ui-request-queue.ts +0 -184
  262. package/src/execution/worktree-manager.ts +0 -688
  263. package/src/execution/worktree-registry.ts +0 -222
  264. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  265. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  266. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  267. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  268. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  269. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  270. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  271. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  272. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  273. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  274. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  275. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  276. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  277. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  278. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  279. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  280. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  281. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  282. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  283. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  284. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  285. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  286. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  287. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  288. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  289. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  290. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  291. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  292. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  293. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  294. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  295. package/src/orchestration/agent-opts-resolver.ts +0 -174
  296. package/src/orchestration/args-validator.ts +0 -127
  297. package/src/orchestration/config-loader.ts +0 -315
  298. package/src/orchestration/error-recovery.ts +0 -1018
  299. package/src/orchestration/execute-agent-call.ts +0 -256
  300. package/src/orchestration/launcher.ts +0 -455
  301. package/src/orchestration/lifecycle.ts +0 -399
  302. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  303. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  304. package/src/orchestration/models/agent-call.ts +0 -83
  305. package/src/orchestration/models/budget.ts +0 -118
  306. package/src/orchestration/models/ports.ts +0 -164
  307. package/src/orchestration/models/run-runtime.ts +0 -104
  308. package/src/orchestration/models/run-spec.ts +0 -83
  309. package/src/orchestration/models/run-state.ts +0 -44
  310. package/src/orchestration/models/trace.ts +0 -183
  311. package/src/orchestration/models/types.ts +0 -301
  312. package/src/orchestration/models/workflow-run.ts +0 -254
  313. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  314. package/src/orchestration/models/workflow-script.ts +0 -117
  315. package/src/orchestration/script-lint.ts +0 -766
  316. package/src/orchestration/skill-discovery.ts +0 -115
  317. package/src/orchestration/worker-handle.ts +0 -115
  318. package/src/orchestration/worker-host.ts +0 -98
  319. package/src/orchestration/worker-script-builder.ts +0 -421
  320. package/src/orchestration/workflow-files.ts +0 -85
  321. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  322. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  323. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  324. package/src/shared/__tests__/model-ref.test.ts +0 -306
  325. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  326. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  327. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  328. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  329. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  330. package/src/shared/agent-event.ts +0 -13
  331. package/src/shared/agent-ref.ts +0 -57
  332. package/src/shared/meta-parser.ts +0 -261
  333. package/src/shared/model-ref.ts +0 -286
  334. package/src/shared/resource-discovery.ts +0 -811
  335. package/src/shared/resource-meta.ts +0 -65
  336. package/src/shared/schema-env.ts +0 -44
  337. package/src/shared/schema-jsonify.ts +0 -58
  338. package/src/shared/timer-delay.ts +0 -54
  339. package/src/shared/xml-injection.ts +0 -35
  340. package/workflows/README.md +0 -81
  341. package/workflows/_shared/agent-refs.cjs +0 -40
  342. package/workflows/chain.js +0 -131
  343. package/workflows/map-reduce.js +0 -174
  344. package/workflows/parallel.js +0 -148
  345. package/workflows/review-fix-loop-utils.cjs +0 -1309
  346. package/workflows/review-fix-loop.js +0 -1404
  347. package/workflows/scatter-gather.js +0 -178
@@ -16,25 +16,27 @@ import {
16
16
  isGuiCapable,
17
17
  } from "@xyz-agent/extension-protocol";
18
18
 
19
- import { SLUG_MAX_LENGTH } from "../execution/execute-options-mapper.ts";
20
- import { computeElapsedSeconds, projectOutcome } from "../execution/execution-record.ts";
21
- import { isResumable } from "../execution/lifecycle-predicates.ts";
22
- import type { ExecutionRecord } from "../execution/types.ts";
23
- import type { ModelInfo } from "../execution/model-resolver.ts";
24
- import type { SubagentService } from "../execution/subagent-service.ts";
25
- import { displayAgentName } from "../shared/agent-ref.ts";
19
+ import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core/execution/execute-options-mapper.ts";
20
+ import { computeElapsedSeconds, projectOutcome } from "@zhushanwen/subagent-core/execution/execution-record.ts";
21
+ import { isResumable } from "@zhushanwen/subagent-core/execution/lifecycle-predicates.ts";
22
+ import type { ExecutionRecord } from "@zhushanwen/subagent-core/execution/types.ts";
23
+ import type { ModelInfo } from "@zhushanwen/subagent-core/execution/model-resolver.ts";
24
+ import type { SubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
25
+ import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
26
26
  import type {
27
27
  BgResponse,
28
28
  CancelResponse,
29
29
  CloseResponse,
30
30
  ExecutionStatus,
31
31
  ExternalState,
32
+ ForkFromResponse,
32
33
  ListResponse,
33
34
  MessageResponse,
34
35
  SubagentListItem,
35
36
  SubagentRecord,
36
37
  SubagentToolResult,
37
- } from "../execution/types.ts";
38
+ } from "@zhushanwen/subagent-core/execution/types.ts";
39
+ import { ResurrectDeniedError } from "@zhushanwen/subagent-core/execution/types.ts";
38
40
  import { mapRunIcon, mapRunStatus } from "./gui-mappers.ts";
39
41
 
40
42
  // ============================================================
@@ -126,6 +128,100 @@ export interface CancelHandlerResult {
126
128
  response: CancelResponse;
127
129
  }
128
130
 
131
+ // ============================================================
132
+ // [v8.5 A1/B] message 拒绝文案分流 + fork-from 引导语框架
133
+ // ============================================================
134
+
135
+ /**
136
+ * [v8.5 A1] message 拒绝时的可行动文案分流。
137
+ *
138
+ * 背景:getRecordForAction 冷查只认 status==='running'(SP-2 可续聊重建),任何终态/
139
+ * 异归属记录都落到同一个「not found or not owned」错误,把两类完全不同的场景混为一谈:
140
+ * - user-close/cancelled:用户主动告别,记录真没了 → 引导 start 新的
141
+ * - parent-shutdown/gc/orphan 等:父会话重启/进程退出导致的断联,对话 jsonl 完好,
142
+ * resume/fork 基建现成 → 引导 fork-from 从旧记录接续
143
+ *
144
+ * 分流规则(消费方是 LLM,保持正交简单):
145
+ * - 找不到记录 → 原样透传 getRecordForAction 错误(id 打错最常见,原文案最准)
146
+ * - closed + user-close/cancelled →「已主动关闭,无法续聊」文案
147
+ * - 其余(closed 其他 reason / running 但异归属)→「断联可接续」文案
148
+ */
149
+ export function endedMessageGuard(service: SubagentService, id: string, original: unknown): Error {
150
+ // [v8.5 D] 透明重生守卫拒绝(worktree/异进程占用)原样透传——错误自带完整行动语言,
151
+ // 若被下方 fork-from 指引改写会误导 agent 走已被判死的通道(types.ts 契约声明)。
152
+ if (original instanceof ResurrectDeniedError) return original;
153
+ let snap: SubagentRecord | undefined;
154
+ try {
155
+ snap = service.lookupRecordAnyState(id);
156
+ } catch {
157
+ snap = undefined;
158
+ }
159
+ if (!snap) {
160
+ return original instanceof Error ? original : new Error(String(original));
161
+ }
162
+ if (snap.status === "closed") {
163
+ if (snap.closedReason === "cancelled" || snap.closedReason === "user-close") {
164
+ return new Error(
165
+ `subagent ${id} was deliberately closed by user (closedReason: ${snap.closedReason}) — ` +
166
+ `it cannot be messaged or resumed; nothing can reattach to it. ` +
167
+ `Recovery: start a new subagent (action:'start'); use action:'list' with includeFinished:true to review its final output.`,
168
+ );
169
+ }
170
+ return new Error(
171
+ `subagent ${id} is ended but reconnectable (closedReason: ${snap.closedReason ?? "unknown"}` +
172
+ `${describeClosedContext(snap)}). Its conversation history is intact at ${snap.sessionFile ?? "(session file unavailable)"}. ` +
173
+ `Recovery: resume from that history with {"action":"fork-from","forkFromParam":{"sourceSubagentId":"${id}"}}, ` +
174
+ `or read key points directly from the session file.`,
175
+ );
176
+ }
177
+ // running 但未通过 getRecordForAction:记录属于当前进程外的另一个 session 树
178
+ //(主会话重启前的遗留态,或其他并发 pi 进程的活跃 subagent)。无论哪种,历史
179
+ // jsonl 只读安全,fork-from 快照接续均有效。
180
+ return new Error(
181
+ `subagent ${id} is alive but belongs to a different session tree than this one` +
182
+ `${describeClosedContext(snap)}. You cannot message it from here. ` +
183
+ `Recovery: branch from its history with {"action":"fork-from","forkFromParam":{"sourceSubagentId":"${id}"}}` +
184
+ `${snap.sessionFile ? ` (source session: ${snap.sessionFile})` : ``}; otherwise start a new subagent.`,
185
+ );
186
+ }
187
+
188
+ /** 终态快照的上下文人话短语(仅作补充描述,主分支逻辑在 endedMessageGuard)。 */
189
+ function describeClosedContext(r: SubagentRecord): string {
190
+ switch (r.closedReason) {
191
+ case "parent-shutdown":
192
+ return " — it was disconnected when the previous parent session exited";
193
+ case "parent-fork":
194
+ return " — it was detached when the previous parent session forked";
195
+ case "parent-new":
196
+ return " — it was detached when the previous parent session switched";
197
+ case "disconnected":
198
+ return " — it ended in a previous session (exact cause unknown)";
199
+ default:
200
+ return "";
201
+ }
202
+ }
203
+
204
+ /**
205
+ * [v8.5 B] fork-from 开场引导语框架(prompt 未指定时注入):先从继承的历史重建状态
206
+ * 再继续,防猜。
207
+ */
208
+ const FORK_FROM_DEFAULT_PROMPT =
209
+ "You are taking over work from a previous subagent whose full conversation history you inherited (--fork). " +
210
+ "First reconstruct state from that history: list what was already done, decided, and left unfinished (a few bullet lines). " +
211
+ "Then continue the remaining work to completion.";
212
+
213
+ /**
214
+ * [v8.5 B] 有显式接续指令时的包裹框架:指令在前、上下文重建要求在后——指令首见即达,
215
+ * 不湮没在元说明里(弱模型友好)。
216
+ */
217
+ function wrapForkFromPrompt(prompt: string): string {
218
+ return (
219
+ prompt.trim() +
220
+ "\n\n(You are continuing a previous subagent's inherited conversation via --fork. " +
221
+ "Reconstruct state from that history first — what was done, decided, and remains — then execute the instruction above.)"
222
+ );
223
+ }
224
+
129
225
  // ============================================================
130
226
  // helpers(模块内)
131
227
  // ============================================================
@@ -386,8 +482,16 @@ export async function messageHandler(
386
482
  );
387
483
  const interrupt = input?.interrupt === true;
388
484
 
389
- // 归属守卫(决策 3):getRecordForAction 内部校验 rootSessionId
390
- const record = service.getRecordForAction(id);
485
+ // 归属守卫(决策 3):getRecordForAction 内部校验 rootSessionId
486
+ // [v8.5 A1] 拒绝时经 endedMessageGuard 分流:找不到 → 原错误;user-close/cancelled
487
+ // → 「已主动关闭」;断联/已完成/异归属 → fork-from 可行动指引。仅 message action
488
+ // 升级文案——close/cancel 维持原语义(它们不需要恢复通道)。
489
+ let record: ExecutionRecord;
490
+ try {
491
+ record = service.getRecordForAction(id, { allowReconnect: true });
492
+ } catch (err) {
493
+ throw endedMessageGuard(service, id, err);
494
+ }
391
495
 
392
496
  // SP-5 one-shot upgrade:非 chatMode 的 active record(running/idle)收到 message 时
393
497
  // 自动升级为 chatMode,后续走 deliverMessage 统一投递路径(热路径或冷路径 resume)。
@@ -462,6 +566,140 @@ export async function closeHandler(
462
566
  return { kind: "close", subagentId: id, response: { closed: true } };
463
567
  }
464
568
 
569
+ // ============================================================
570
+ // fork-from handler([v8.5 B] 断联恢复通道)
571
+ // ============================================================
572
+
573
+ export interface ForkFromHandlerInput {
574
+ sourceSubagentId?: string;
575
+ prompt?: string;
576
+ }
577
+
578
+ /** fork-from 领域对象(adapter 包成 forkFromResponse)。 */
579
+ export type ForkFromHandlerResult = {
580
+ kind: "fork-from";
581
+ /** 新 subagent 的 record id(后续续聊用 action:'message')。 */
582
+ subagentId: string;
583
+ /** 作为 --fork 继承源的旧记录 session 文件。 */
584
+ sourceSessionFile: string;
585
+ response: ForkFromResponse;
586
+ };
587
+
588
+ /**
589
+ * fork-from action handler:从旧 subagent 的会话历史 spawn 新 id 接续。
590
+ *
591
+ * 用于 subagent 因会话重启/进程退出而断联后的恢复:新进程以 --fork 指向旧 session
592
+ * 文件(copy-on-write 建分支会话),继承全部对话历史;源文件只读不续写。
593
+ * 旧记录本身不动——closed 单向状态机不变量、tryTransition 语义均不触碰。
594
+ *
595
+ * 守卫链(拒绝原因与行动语言对齐现有 MF-4 风格):
596
+ * 1. 本进程内存 running → 还活着,应走 message(防双写同一子 session 文件)
597
+ * 2. 不存在 → 引导 list 确认
598
+ * 3. 异进程活跃(磁盘 .alive pid 存活 / running 快照)→ 别处正跑,不可从此接续
599
+ * (同 id 双写风险;等待其结束或在其所属会话内操作)
600
+ * 4. tombstone/cancelled → 用户主动取消,真没了(不提供接续通道)
601
+ * 5. worktree 记录 → checkout 不可复用,fork 子进程 cwd 会回落主仓破坏隔离
602
+ * (对齐 deliverMessage 的 hadWorktree 守卫语义)
603
+ * 6. 无子 session 文件 → 无历史可继承(entry-only 孤儿:spawn 窗口期中断)
604
+ *
605
+ * @throws Error 各守卫命中 / service.execute 失败(引擎不支持等)
606
+ */
607
+ export async function forkFromHandler(
608
+ service: SubagentService,
609
+ input: ForkFromHandlerInput | undefined,
610
+ ): Promise<ForkFromHandlerResult> {
611
+ const id = input?.sourceSubagentId?.trim();
612
+ if (!id) throw new Error("forkFromParam.sourceSubagentId is required for action:'fork-from'");
613
+ const prompt = input?.prompt?.trim() ?? "";
614
+ const task = prompt ? wrapForkFromPrompt(prompt) : FORK_FROM_DEFAULT_PROMPT;
615
+
616
+ const source = assertAndLookupForkFromSource(service, id);
617
+
618
+ // slug 派生:源 slug + -resumed 后缀(截断到上限)。仅展示标签,不需唯一。
619
+ const baseSlug = (source.slug || source.agent || "resumed").slice(0, SLUG_MAX_LENGTH - "-resumed".length);
620
+ const handle = await service.execute({
621
+ task,
622
+ slug: `${baseSlug}-resumed`,
623
+ forkFromSessionFile: source.sessionFile,
624
+ });
625
+
626
+ return {
627
+ kind: "fork-from",
628
+ subagentId: handle.subagentId,
629
+ sourceSessionFile: source.sessionFile,
630
+ response: { newSubagentId: handle.subagentId, sourceSessionFile: source.sessionFile },
631
+ };
632
+ }
633
+
634
+ /** forkFromHandler 的守卫链(fork-from handler doc 的守卫 1–6 原样提取):按序校验
635
+ * 源记录可接续,命中即抛带行动语言的 Error;全部通过则返回源 SubagentRecord
636
+ * (守卫 6 已保证 sessionFile 非空,返回类型随之收窄)。 */
637
+ function assertAndLookupForkFromSource(service: SubagentService, id: string): SubagentRecord & { sessionFile: string } {
638
+ // 守卫 1:本进程内存 running —— 直接 message 即可,fork-from 会双写其 session 文件。
639
+ if (service.findRecord(id)) {
640
+ throw new Error(
641
+ `subagent ${id} is still active in this process — use action:'message' to continue it directly. ` +
642
+ `If you want a parallel branch from its history, close it first (action:'close'), then fork-from.`,
643
+ );
644
+ }
645
+
646
+ // 守卫 2:全态查找(内存 archived + 磁盘重建)。
647
+ const source = service.lookupRecordAnyState(id);
648
+ if (!source) {
649
+ throw new Error(
650
+ `No subagent record with id "${id}". It may never have existed or been garbage-collected — ` +
651
+ `use action:'list' with includeFinished:true to verify the id.`,
652
+ );
653
+ }
654
+
655
+ // 守卫 3:异进程活跃(磁盘分支 3 externalInstance = 另一进程的活 pid marker)。
656
+ // 双写防护:fork 虽 copy-on-write(历史 jsonl 只读),但源仍在异进程运行时接续容易
657
+ // 读到半截历史,等它结束再接更安全。判据只认 externalInstance(真实活 pid 探针
658
+ // 命中),不拦 status==='running' 的快照——后者含 B-1 跨重启回退重建的 running 记录
659
+ //(无活 pid,历史已完整落盘),它们正是 endedMessageGuard 指引 fork-from 的目标;
660
+ // 拦了会让 agent 在「建议 fork-from」与「fork-from 拒绝 running」两条错误间死循环。
661
+ if (source.externalInstance !== undefined) {
662
+ throw new Error(
663
+ `subagent ${id} is still running in another process (alive pid marker present). ` +
664
+ `Recovery: wait until it finishes, or operate it in its own session; then retry fork-from.`,
665
+ );
666
+ }
667
+
668
+ // 守卫 4:主动告别(cancelled tombstone / user-close 正式关闭)——close 语义无旁路:
669
+ // fork-from 与 message 一致拒绝(guard 一致性规格),文案升级为统一「主动关闭」形态
670
+ // (含 closedReason 显式列入),与 deliverMessage 的 X 分支同语系不同落地(此处强调不可 branch)。
671
+ if (source.status === "closed" && (source.closedReason === "cancelled" || source.closedReason === "user-close")) {
672
+ throw new Error(
673
+ `subagent ${id} was deliberately closed by user (closedReason: ${source.closedReason}) — ` +
674
+ `deliberately-closed records cannot be resumed or branched from; nothing can reattach to them. ` +
675
+ `Recovery: start a fresh subagent (action:'start'); use action:'list' with includeFinished:true to review its final output.`,
676
+ );
677
+ }
678
+
679
+ // 守卫 5:worktree 记录 —— WorktreeHandle 不可序列化,checkout 已被 reaper/cleanup
680
+ // 回收;fork 子进程若复用旧路径会回落主 repo(破坏文件隔离)。与 deliverMessage 的
681
+ // hadWorktree 守卫同一判据同一理由。
682
+ if (source.worktree === true) {
683
+ throw new Error(
684
+ `subagent ${id} was created with worktree isolation; that binding was lost when its parent process ended. ` +
685
+ `Resuming from its history would run outside the original worktree isolation. ` +
686
+ `Recovery: start a new subagent with action:'start' and carry over key findings manually ` +
687
+ `(read ${source.sessionFile ?? "its session file"} if needed).`,
688
+ );
689
+ }
690
+
691
+ // 守卫 6:无子 session 文件(entry-born 孤儿:spawn 窗口期中断,从未开跑)。
692
+ const sessionFile = source.sessionFile;
693
+ if (!sessionFile) {
694
+ throw new Error(
695
+ `subagent ${id} has no child session file to inherit from (it never started successfully). ` +
696
+ `Recovery: start a fresh subagent (action:'start') describing the task again.`,
697
+ );
698
+ }
699
+
700
+ return { ...source, sessionFile };
701
+ }
702
+
465
703
  // ============================================================
466
704
  // adapter(领域对象 → SubagentToolResult + {content, details})
467
705
  // ============================================================
@@ -475,7 +713,8 @@ type AdapterInput =
475
713
  | { action: "list"; domain: ListHandlerResult }
476
714
  | { action: "cancel"; domain: CancelHandlerResult }
477
715
  | { action: "message"; domain: MessageHandlerResult }
478
- | { action: "close"; domain: CloseHandlerResult };
716
+ | { action: "close"; domain: CloseHandlerResult }
717
+ | { action: "fork-from"; domain: ForkFromHandlerResult };
479
718
 
480
719
  export function adapter(
481
720
  input: AdapterInput,
@@ -495,6 +734,11 @@ export function adapter(
495
734
  result = { action, subagentId: input.domain.subagentId, sessionFile: null, cancelResponse: input.domain.response };
496
735
  } else if (action === "message") {
497
736
  result = { action, subagentId: input.domain.subagentId, sessionFile: null, messageResponse: input.domain.response };
737
+ } else if (action === "fork-from") {
738
+ // MF-3 同款瘦身:sourceSessionFile 真实路径只在 forkFromResponse 内层(LLM 接续
739
+ // 不需要拼路径,需要时 list/details 可取);顶层 sessionFile 保持 null 一致性。
740
+ const d = input.domain;
741
+ result = { action, subagentId: d.subagentId, sessionFile: null, forkFromResponse: d.response };
498
742
  } else {
499
743
  // action === "close"
500
744
  result = { action, subagentId: input.domain.subagentId, sessionFile: null, closeResponse: input.domain.response };
@@ -565,6 +809,14 @@ export function buildGuiComponent(
565
809
  items: [{ label: "messaged", value: input.domain.subagentId, severity: "ok" }],
566
810
  });
567
811
  }
812
+ if (action === "fork-from") {
813
+ return guiComponent("stats-line", {
814
+ items: [
815
+ { label: "forked-from", value: input.domain.sourceSessionFile },
816
+ { label: "new subagent", value: input.domain.subagentId, severity: "ok" },
817
+ ],
818
+ });
819
+ }
568
820
  if (action === "close") {
569
821
  return guiComponent("stats-line", {
570
822
  items: [{ label: "closed", value: input.domain.subagentId, severity: "warn" }],
@@ -12,22 +12,18 @@
12
12
  // 编译本 schema 并断言 required/description/enum/pattern 存活——SW 自身测试环境
13
13
  // 把 typebox alias 到 mock(丢 options),SO 侧测试以真实构造为对照基准。
14
14
  //
15
- // 层归属:Interface(工具 schema 的家)。SLUG_MAX_LENGTH schema 迁入:
16
- // 它的唯一语义就是 tool schema 的 maxLength(见原 execute-options-mapper 注释),
17
- // execution 侧经 re-export 保持既有 import 路径不变。
15
+ // 层归属:Interface(工具 schema 的家)。SLUG_MAX_LENGTH 权威定义回归 core
16
+ // execution/execute-options-mapper.ts(subagent-core 包抽离 u1-move:core 切面不得
17
+ // 反向 import 壳侧 interface,常量随之内化)——此处 re-export 保持既有 import 路径。
18
18
 
19
19
  import { StringEnum } from "@earendil-works/pi-ai";
20
20
  import { type Static, Type } from "typebox";
21
21
 
22
- import { THINKING_ORDER } from "../shared/model-ref.ts";
22
+ import { THINKING_ORDER } from "@zhushanwen/subagent-core/shared/model-ref.ts";
23
23
 
24
- /**
25
- * slug 最大长度(字符)。subagent/workflow 创建时 slug 超过此值会被截断。
26
- * subagent/workflow tool schema 的 maxLength 引用此常量(单一真相,勿再硬编码)。
27
- * 历史值 20 偏紧——描述性 slug 如 "audit-structured-output"(23)/"fix-subagent-wf-tools"(21)
28
- * 会撞上限,放宽到 35 兼顾「短到能塞进 TUI 标题行」与「容纳合理描述性 kebab-case 名」。
29
- */
30
- export const SLUG_MAX_LENGTH = 35;
24
+ import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core/execution/execute-options-mapper.ts";
25
+
26
+ export { SLUG_MAX_LENGTH };
31
27
 
32
28
  // Params schema(跨包契约测试的真实 typebox 校验入口)。
33
29
  //
@@ -42,8 +38,8 @@ export const SLUG_MAX_LENGTH = 35;
42
38
  // (subagent_start / subagent_list / subagent_cancel),让每个 tool 的 schema 真实
43
39
  // 反映必填性。勿在此基础上继续堆 action 条件逻辑——要加就拆 tool。
44
40
  export const SubagentParams = Type.Object({
45
- action: StringEnum(["start", "list", "cancel", "message", "close"], {
46
- description: "Operation: 'start' runs a subagent, 'list' shows subagents, 'cancel' stops a background subagent, 'message' sends a follow-up to a running subagent (one-shot subagents are auto-upgraded to conversation mode on first message), 'close' ends a running subagent (conversation-mode or one-shot).",
41
+ action: StringEnum(["start", "list", "cancel", "message", "close", "fork-from"], {
42
+ description: "Operation: 'start' runs a subagent, 'list' shows subagents, 'cancel' stops a background subagent, 'message' sends a follow-up to a running subagent (one-shot subagents are auto-upgraded to conversation mode on first message), 'close' ends a running subagent (conversation-mode or one-shot), 'fork-from' spawns a NEW subagent inheriting an older one's history (recovery for restart-disconnected subagents; the old record is untouched).",
47
43
  }),
48
44
  // ── action:"start" fields (flattened to top level). task/slug REQUIRED for start. ──
49
45
  // Missing/empty task or slug throws at runtime (startHandler).
@@ -150,6 +146,17 @@ export const SubagentParams = Type.Object({
150
146
  description: "If true, terminate immediately even if mid-round (in-progress work is lost). If false (default), let the current round finish, then close. When idle, the subagent closes immediately regardless.",
151
147
  })),
152
148
  })),
149
+ // action:"fork-from" → forkFromParam.sourceSubagentId REQUIRED ([v8.5 B] 断联恢复通道).
150
+ // 从旧 subagent 的会话历史 spawn 新 id:新进程 --fork 指向旧 session 文件(copy-on-write,
151
+ // 源文件只读不续写);旧记录/状态机不动。pi 引擎限定(非 pi 在 execute 层拒绝)。
152
+ forkFromParam: Type.Optional(Type.Object({
153
+ sourceSubagentId: Type.String({
154
+ description: "REQUIRED for action:'fork-from'. The OLD subagentId whose conversation history becomes the inherited context of the new subagent. Works for records disconnected by a session restart or already finished; cancelled/worktree-bound/still-running ones are rejected with guidance.",
155
+ }),
156
+ prompt: Type.Optional(Type.String({
157
+ description: "Continuation instruction for the new subagent (what to do next on top of the inherited history). When omitted, a standard handover frame is injected: reconstruct done/decided/remaining from the inherited history, then continue to completion. Whitespace-only treated as omitted.",
158
+ })),
159
+ })),
153
160
  });
154
161
 
155
162
  /** Params schema 的 Static 投影(消费方经 `Static<typeof SubagentParams>` 使用,见 subagent-tool.ts)。 */
@@ -16,11 +16,11 @@ import type { AgentToolResult, ExtensionAPI, ExtensionContext, Theme } from "@ea
16
16
  import { getLogger } from "@zhushanwen/pi-extension-logger";
17
17
  import type { Static } from "typebox";
18
18
 
19
- import { getSubagentService } from "../execution/subagent-service.ts";
20
- import type { SubagentToolResult } from "../execution/types.ts";
19
+ import { getSubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
20
+ import type { SubagentToolResult } from "@zhushanwen/subagent-core/execution/types.ts";
21
21
  import { extractAgentName } from "./format.ts";
22
22
  import { toGuiCtx } from "./gui-mappers.ts";
23
- import { adapter, cancelHandler, closeHandler, listHandler, messageHandler, startHandler } from "./subagent-actions.ts";
23
+ import { adapter, cancelHandler, closeHandler, forkFromHandler, listHandler, messageHandler, startHandler } from "./subagent-actions.ts";
24
24
  import { SubagentParams } from "./subagent-tool-schema.ts";
25
25
  import { type RenderContext,renderSubagentCall, renderSubagentResult } from "./tool-render.ts";
26
26
 
@@ -71,13 +71,14 @@ function assertNever(value: never): string {
71
71
  }
72
72
 
73
73
  /** Subagent action 字面量联合(与 parameters schema 的 StringEnum 取值一致)。 */
74
- type SubagentAction = "start" | "list" | "cancel" | "message" | "close";
74
+ type SubagentAction = "start" | "list" | "cancel" | "message" | "close" | "fork-from";
75
75
 
76
76
  /** 类型守卫:把 schema 投影出的 string 形式 action 收窄回字面量联合。
77
77
  * typebox v1 的 StringEnum Static 退化为 string,需运行时校验 + 类型收窄
78
78
  * 才能恢复 switch 的 exhaustiveness 约束。 */
79
79
  function isSubagentAction(value: string): value is SubagentAction {
80
- return value === "start" || value === "list" || value === "cancel" || value === "message" || value === "close";
80
+ return value === "start" || value === "list" || value === "cancel" || value === "message"
81
+ || value === "close" || value === "fork-from";
81
82
  }
82
83
 
83
84
  /** unknown 是否为含 model/thinkingLevel 的对象(类型守卫,替代全可选结构 `as`)。 */
@@ -165,6 +166,7 @@ action:"list" before action:"start" — a reusable running subagent may exist; c
165
166
  - action:"close" — end a running subagent and release its resources. REQUIRED closeParam: { subagentId }. Optional: force (default false; true terminates mid-round immediately). Always close when done.
166
167
  - action:"list" — list subagents. Pass listParam: { includeFinished?, limit? } (all optional). Read an item's sessionFile for full detail.
167
168
  - action:"cancel" — stop a background subagent (legacy verb; for conversation-mode use close). REQUIRED cancelParam: { subagentId }.
169
+ - action:"fork-from" — recovery for subagents disconnected by a session restart/exit: spawns a NEW subagent inheriting the old one's full history via --fork (source read-only, old record untouched). REQUIRED forkFromParam: { sourceSubagentId }. Optional: prompt (continuation instruction; handover frame injected if omitted). Returns { newSubagentId, sourceSessionFile }. Rejected with guidance: cancelled / worktree-bound / still-running sources.
168
170
 
169
171
  ## Examples
170
172
 
@@ -177,6 +179,7 @@ action:"list" before action:"start" — a reusable running subagent may exist; c
177
179
  {"action":"close","closeParam":{"subagentId":"sa-550e8400"}}
178
180
  {"action":"list","listParam":{"includeFinished":false,"limit":20}}
179
181
  {"action":"cancel","cancelParam":{"subagentId":"sa-550e8400"}}
182
+ {"action":"fork-from","forkFromParam":{"sourceSubagentId":"sa-550e8400","prompt":"continue from where it stopped; verify tests first"}}
180
183
  \`\`\`
181
184
 
182
185
  ## After launching — do NOT wait
@@ -204,7 +207,7 @@ When to use:
204
207
  - ✅ Long-interval rounds (>5min apart) → conversation:true + idleTimeoutMs increased
205
208
  - ❌ Single exploration/lookup → default (one-shot)
206
209
 
207
- idleTimeoutMs: per-subagent idle timeout (default 300000 / 5min). Env XYZ_SUBAGENT_IDLE_TIMEOUT_MS sets the global default; per-call param takes precedence. Pass 0 or a negative value to disable idle cleanup entirely.
210
+ idleTimeoutMs: per-subagent idle timeout (default 300000 / 5min). Env XYZ_SUBAGENT_IDLE_TIMEOUT_MS sets the global default; per-call param takes precedence.
208
211
 
209
212
  ## You cannot
210
213
 
@@ -323,6 +326,8 @@ const executeSubagent: SubagentExecuteCb = async (
323
326
  return adapter({ action: "message", domain: await messageHandler(service, params.messageParam) }, toGuiCtx(_ctx));
324
327
  case "close":
325
328
  return adapter({ action: "close", domain: await closeHandler(service, params.closeParam) }, toGuiCtx(_ctx));
329
+ case "fork-from":
330
+ return adapter({ action: "fork-from", domain: await forkFromHandler(service, params.forkFromParam) }, toGuiCtx(_ctx));
326
331
  default:
327
332
  // assertNever:让 exhaustiveness 成为承重约束——新增 action 时 tsc 报错,
328
333
  // 而非悄悄落入此分支。
@@ -9,9 +9,9 @@
9
9
 
10
10
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
11
11
 
12
- import { getSubagentService } from "../execution/subagent-service.ts";
13
- import type { SubagentService } from "../execution/subagent-service.ts";
14
- import { displayAgentName } from "../shared/agent-ref.ts";
12
+ import { getSubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
13
+ import type { SubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
14
+ import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
15
15
  import { messageHandler, startHandler } from "./subagent-actions.ts";
16
16
  import { parseSubagentRpcCommand } from "./command-actions.ts";
17
17
  import type { SubagentRpcAction } from "./command-actions.ts";
@@ -24,8 +24,8 @@ import type { AgentToolResult, Theme } from "@earendil-works/pi-coding-agent";
24
24
  import type {
25
25
  ListResponse,
26
26
  SubagentToolResult,
27
- } from "../execution/types.ts";
28
- import { displayAgentName } from "../shared/agent-ref.ts";
27
+ } from "@zhushanwen/subagent-core/execution/types.ts";
28
+ import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
29
29
  import {
30
30
  extractAgentName,
31
31
  firstLine,
@@ -208,6 +208,15 @@ function buildCompactLines(d: SubagentToolResult, theme: ThemeLike): string[] {
208
208
  width,
209
209
  )];
210
210
  }
211
+ // ── fork-from 分支:接续确认行([v8.5 B])──
212
+ if (d.action === "fork-from" && d.forkFromResponse) {
213
+ const src = shortSessionLabel(d.forkFromResponse.sourceSessionFile);
214
+ return [truncLine(
215
+ `${theme.fg("accent", "⑂")} ${theme.fg("dim", "forked-from ")}${theme.fg("accent", src)}` +
216
+ ` ${theme.fg("dim", "→ new: ")}${theme.fg("accent", d.subagentId ?? "?")}`,
217
+ width,
218
+ )];
219
+ }
211
220
  // ── start 分支:background ──
212
221
  if ("bgResponse" in d) {
213
222
  return [truncLine(
@@ -234,6 +243,16 @@ function buildExpandedLines(d: SubagentToolResult, theme: ThemeLike): string[] {
234
243
  width,
235
244
  )];
236
245
  }
246
+ if (d.action === "fork-from" && d.forkFromResponse) {
247
+ // expanded 与 compact 同形(一次性 block 无细节可展开),另附源文件完整路径行。
248
+ return [
249
+ truncLine(
250
+ `${theme.fg("accent", "⑂")} ${theme.fg("dim", "forked-from ")}${theme.fg("accent", d.forkFromResponse.sourceSessionFile)}` +
251
+ ` ${theme.fg("dim", "→ new: ")}${theme.fg("accent", d.subagentId ?? "?")}`,
252
+ width,
253
+ ),
254
+ ];
255
+ }
237
256
 
238
257
  const lines: string[] = [];
239
258
  // bg 占位 expanded 与 compact 同(一次性 block 无细节可展开)
@@ -261,11 +280,24 @@ function isDetailsStructurallyComplete(d: SubagentToolResult): boolean {
261
280
  return "listResponse" in d;
262
281
  case "cancel":
263
282
  return "cancelResponse" in d;
283
+ case "fork-from":
284
+ // [v8.5 B] 新 action 直接纳入 guard:缺内层分组才 fallback。
285
+ // message/close 维持历史现状(不落此 switch 显式分支,走 extractResultError
286
+ // 回显 content 首行)不变,避免触碰现有渲染回归面——review MF-13 曾引入
287
+ // message/close 显式分支后回退:无对应渲染分支却判「结构完整」会改走
288
+ // generic 无响应渲染,属静默行为变更。
289
+ return "forkFromResponse" in d;
264
290
  default:
265
291
  return false;
266
292
  }
267
293
  }
268
294
 
295
+ /** fork-from 渲染用的源文件短标签(basename;失败时原样返回——渲染不应抛错)。 */
296
+ function shortSessionLabel(file: string): string {
297
+ const idx = file.lastIndexOf("/");
298
+ return idx >= 0 ? file.slice(idx + 1) : file;
299
+ }
300
+
269
301
  /**
270
302
  * 从 tool result 的 content 里提取错误文本。
271
303
  *
@@ -30,12 +30,12 @@ import {
30
30
  guiResult,
31
31
  isGuiCapable,
32
32
  } from "@xyz-agent/extension-protocol";
33
- import type { WorkflowScriptRegistry } from "../orchestration/models/workflow-script-registry.ts";
34
- import { lintScript } from "../orchestration/script-lint.ts";
35
- import { deleteWorkflow, saveWorkflow } from "../orchestration/workflow-files.ts";
33
+ import type { WorkflowScriptRegistry } from "@zhushanwen/subagent-core/orchestration/models/workflow-script-registry.ts";
34
+ import { lintScript } from "@zhushanwen/subagent-core/orchestration/script-lint.ts";
35
+ import { deleteWorkflow, saveWorkflow } from "@zhushanwen/subagent-core/orchestration/workflow-files.ts";
36
36
  import { toGuiCtx } from "./gui-mappers.ts";
37
37
  import { renderTextFallback } from "./views/format.ts";
38
- import { parseResourceMetaDetailed } from "../shared/meta-parser.ts";
38
+ import { parseResourceMetaDetailed } from "@zhushanwen/subagent-core/shared/meta-parser.ts";
39
39
 
40
40
  // ── Parameter schema ─────────────────────────────────────────
41
41
 
@@ -31,12 +31,12 @@ import {
31
31
  } from "@xyz-agent/extension-protocol";
32
32
  import { type Static, Type } from "typebox";
33
33
 
34
- import { SLUG_MAX_LENGTH } from "../execution/execute-options-mapper.ts";
35
- import { THINKING_ORDER } from "../execution/model-resolver.ts";
36
- import type { LauncherDeps } from "../orchestration/launcher.ts";
37
- import { abortRun, runWorkflow } from "../orchestration/lifecycle.ts";
38
- import type { RunStore } from "../orchestration/models/ports.ts";
39
- import type { WorkflowRun } from "../orchestration/models/workflow-run.ts";
34
+ import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core/execution/execute-options-mapper.ts";
35
+ import { THINKING_ORDER } from "@zhushanwen/subagent-core/execution/model-resolver.ts";
36
+ import type { LauncherDeps } from "@zhushanwen/subagent-core/orchestration/launcher.ts";
37
+ import { abortRun, runWorkflow } from "@zhushanwen/subagent-core/orchestration/lifecycle.ts";
38
+ import type { RunStore } from "@zhushanwen/subagent-core/orchestration/models/ports.ts";
39
+ import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
40
40
  import { mapRunIcon, mapRunStatus, toGuiCtx } from "./gui-mappers.ts";
41
41
  import {
42
42
  acquireReentryGuard,
@@ -33,11 +33,11 @@ import {
33
33
  countAllToolCalls,
34
34
  getAllToolCalls,
35
35
  projectLiveProgress,
36
- } from "../../execution/execution-record.ts";
37
- import type { ExecutionTraceNode } from "../../orchestration/models/types.ts";
38
- import type { WorkflowRun } from "../../orchestration/models/workflow-run.ts";
39
- import { saveWorkflow } from "../../orchestration/workflow-files.ts";
40
- import { displayAgentName } from "../../shared/agent-ref.ts";
36
+ } from "@zhushanwen/subagent-core/execution/execution-record.ts";
37
+ import type { ExecutionTraceNode } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
38
+ import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
39
+ import { saveWorkflow } from "@zhushanwen/subagent-core/orchestration/workflow-files.ts";
40
+ import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
41
41
  import {
42
42
  BOX_BORDER_CHARS,
43
43
  BUDGET_TOKENS_DIVISOR,
@@ -13,9 +13,9 @@
13
13
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
14
14
 
15
15
  import { computeRenderSignature } from "../WorkflowsView.ts";
16
- import type { ExecutionRecord } from "../../../execution/types.ts";
17
- import type { ExecutionTraceNode, WorkerLogEntry } from "../../../orchestration/models/types.ts";
18
- import type { WorkflowRun } from "../../../orchestration/models/workflow-run.ts";
16
+ import type { ExecutionRecord } from "@zhushanwen/subagent-core/execution/types.ts";
17
+ import type { ExecutionTraceNode, WorkerLogEntry } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
18
+ import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
19
19
 
20
20
  // ── Fixtures(duck typing,对齐 detail-content-session-file.test.ts 先例)──
21
21
 
@@ -9,8 +9,8 @@ import { describe, expect, it } from "vitest";
9
9
 
10
10
  import { buildDetailContent } from "../detail-content.ts";
11
11
  import type { ThemeLike } from "../format.ts";
12
- import type { ExecutionTraceNode } from "../../../orchestration/models/types.ts";
13
- import type { WorkflowRun } from "../../../orchestration/models/workflow-run.ts";
12
+ import type { ExecutionTraceNode } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
13
+ import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
14
14
 
15
15
  /** plain theme: fg/bold 直接返回原文,无 ANSI 色码——测试断言纯文本。 */
16
16
  const plainTheme: ThemeLike = {
@@ -12,10 +12,10 @@
12
12
 
13
13
  import { Key, matchesKey } from "@earendil-works/pi-tui";
14
14
 
15
- import { getAllToolCalls, projectLiveProgress } from "../../execution/execution-record.ts";
16
- import type { AgentEventLogEntry } from "../../execution/types.ts";
17
- import type { ExecutionTraceNode } from "../../orchestration/models/types.ts";
18
- import type { WorkflowRun } from "../../orchestration/models/workflow-run.ts";
15
+ import { getAllToolCalls, projectLiveProgress } from "@zhushanwen/subagent-core/execution/execution-record.ts";
16
+ import type { AgentEventLogEntry } from "@zhushanwen/subagent-core/execution/types.ts";
17
+ import type { ExecutionTraceNode } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
18
+ import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
19
19
  import {
20
20
  BOX_BORDER_CHARS,
21
21
  BUDGET_TOKENS_DIVISOR,