@zhushanwen/subagent-core 0.5.1 → 0.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 (318) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-Dv4QhSJ_.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +835 -668
  6. package/dist/{types-Dv4QhSJ_.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +835 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14123 -15467
  20. package/dist/index.d.cts +1179 -1540
  21. package/dist/index.d.ts +1179 -1540
  22. package/dist/index.js +7694 -10986
  23. package/dist.bundle/index.cjs +33485 -0
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/agent-registry.test.ts +1 -1
  30. package/src/execution/__tests__/alive-store.test.ts +1 -1
  31. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  32. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  33. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  34. package/src/execution/__tests__/collect-coordinator-service.test.ts +316 -0
  35. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  36. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +229 -0
  37. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  38. package/src/execution/__tests__/config.test.ts +1 -1
  39. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  40. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  41. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  42. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +21 -34
  43. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  44. package/src/execution/__tests__/gc-timer.test.ts +8 -23
  45. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  46. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  47. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  48. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  49. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  50. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  51. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  52. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  53. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  54. package/src/execution/__tests__/notify-ledger.test.ts +27 -0
  55. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  56. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  57. package/src/execution/__tests__/record-store.test.ts +60 -6
  58. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  59. package/src/execution/__tests__/relay-env.test.ts +12 -1
  60. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  61. package/src/execution/__tests__/session-file-gc.test.ts +1 -1
  62. package/src/execution/__tests__/session-pending.test.ts +119 -17
  63. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  64. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  65. package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
  66. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +14 -11
  67. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  68. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  69. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  70. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  71. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  72. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  73. package/src/execution/__tests__/sync-collect-recovery.test.ts +1102 -0
  74. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  75. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  76. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  77. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  78. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  79. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  80. package/src/execution/agent-registry.ts +6 -2
  81. package/src/execution/collect-coordinator.ts +200 -0
  82. package/src/execution/config.ts +77 -5
  83. package/src/execution/dialog-queue.ts +6 -73
  84. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  85. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  86. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  87. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  88. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  89. package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
  90. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  91. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  92. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  93. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  94. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  95. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  96. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  97. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  98. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  99. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +82 -55
  100. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  101. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  102. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  103. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +8 -3
  104. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  105. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  106. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  107. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  108. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  109. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  110. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  111. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  112. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  113. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  114. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  115. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  116. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  117. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  118. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  119. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  120. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  121. package/src/execution/engine/client/client-options.ts +103 -0
  122. package/src/execution/engine/client/engine-client.ts +687 -0
  123. package/src/execution/engine/client/mirror.ts +167 -0
  124. package/src/execution/engine/client/pid-file.ts +392 -0
  125. package/src/execution/engine/client/reaper.ts +95 -0
  126. package/src/execution/engine/client/remote-engine.ts +441 -0
  127. package/src/execution/engine/client/reverse-router.ts +255 -0
  128. package/src/execution/engine/common/capability-gate.ts +109 -22
  129. package/src/execution/engine/common/errors.ts +9 -25
  130. package/src/execution/engine/common/event-journal.ts +4 -50
  131. package/src/execution/engine/common/journal-replay.ts +3 -1
  132. package/src/execution/engine/common/kill-chain.ts +18 -251
  133. package/src/execution/engine/common/nesting-guard.ts +18 -114
  134. package/src/execution/engine/common/pool-manager.ts +4 -0
  135. package/src/execution/engine/common/session-view-service.ts +56 -84
  136. package/src/execution/engine/config.ts +151 -0
  137. package/src/execution/engine/d8-compat.ts +346 -0
  138. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  139. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  140. package/src/execution/engine/engine-discovery.ts +30 -7
  141. package/src/execution/engine/engine-inspect-package.ts +282 -0
  142. package/src/execution/engine/engine-manifest.ts +244 -0
  143. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  144. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  145. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  146. package/src/execution/engine/host/host-bridge.ts +150 -0
  147. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  148. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  149. package/src/execution/engine/host/spawned-children.ts +139 -0
  150. package/src/execution/engine/host-task-spec.ts +29 -2
  151. package/src/execution/engine/model-validation.ts +55 -2
  152. package/src/execution/engine/paths.ts +16 -41
  153. package/src/execution/engine/port.ts +48 -2
  154. package/src/execution/engine/registry.ts +153 -34
  155. package/src/execution/engine/routing.ts +225 -52
  156. package/src/execution/engine/types.ts +25 -200
  157. package/src/execution/execution-record.ts +7 -0
  158. package/src/execution/finalize-record.ts +40 -11
  159. package/src/execution/idle-gc.ts +89 -14
  160. package/src/execution/lifecycle-manager.ts +10 -7
  161. package/src/execution/lifecycle-predicates.ts +10 -8
  162. package/src/execution/notifier.ts +234 -25
  163. package/src/execution/notify-host.ts +21 -1
  164. package/src/execution/record-entry.ts +16 -0
  165. package/src/execution/record-store.ts +189 -31
  166. package/src/execution/relay-env.ts +19 -36
  167. package/src/execution/round-supervisor/domain.ts +89 -0
  168. package/src/execution/round-supervisor/index.ts +33 -0
  169. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  170. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  171. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  172. package/src/execution/round-supervisor/service-binding.ts +273 -0
  173. package/src/execution/round-supervisor/supervisor.ts +426 -0
  174. package/src/execution/session-pending.ts +68 -74
  175. package/src/execution/settled-watchdog.ts +39 -0
  176. package/src/execution/subagent-actions-core.ts +62 -6
  177. package/src/execution/subagent-service.ts +1161 -406
  178. package/src/execution/subprocess-agent-runner.ts +16 -8
  179. package/src/execution/sync-rebuild.ts +87 -0
  180. package/src/execution/types.ts +104 -117
  181. package/src/execution/ui-channels.ts +13 -214
  182. package/src/execution/ui-request-handler-factory.ts +7 -4
  183. package/src/execution/ui-request-observability.ts +2 -2
  184. package/src/execution/workflow-state-root.ts +67 -0
  185. package/src/execution/worktree-git-ops.ts +5 -0
  186. package/src/execution/worktree-manager.ts +11 -1
  187. package/src/index.ts +55 -26
  188. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  189. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  190. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  191. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  192. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  193. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  194. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  195. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  196. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  197. package/src/orchestration/execute-agent-call.ts +1 -1
  198. package/src/orchestration/file-run-store.ts +144 -59
  199. package/src/orchestration/models/types.ts +43 -42
  200. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  201. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  202. package/src/shared/zcode-model-ref.ts +31 -0
  203. package/dist/chunk-43ONBFZX.js +0 -240
  204. package/dist/chunk-A4IVZWVX.js +0 -31
  205. package/dist/chunk-APZY4IME.js +0 -27
  206. package/dist/chunk-V3VHZ2VX.js +0 -59
  207. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  208. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  209. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  210. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  211. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  212. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  213. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  214. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  215. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  216. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  217. package/src/__tests__/session-runner.test.ts +0 -69
  218. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  219. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  220. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  221. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  222. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  223. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  224. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  225. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  226. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  227. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  228. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  229. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  230. package/src/execution/__tests__/output-collector.test.ts +0 -469
  231. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  232. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  233. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  234. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  235. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  236. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  237. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  238. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  239. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  240. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  241. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  242. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  243. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  244. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  245. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  246. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  247. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  248. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  249. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  250. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  251. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  252. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  253. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  254. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  255. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  256. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  257. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  258. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  259. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  260. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  261. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  262. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  263. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  264. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  265. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  266. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  267. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  268. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  269. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  270. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  271. package/src/execution/engine/common/schema-emulation.ts +0 -189
  272. package/src/execution/engine/common/session-view-projection.ts +0 -51
  273. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  274. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  275. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  276. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  277. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  278. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  279. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  280. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  281. package/src/execution/engine/engines/pi/reader.ts +0 -59
  282. package/src/execution/engine/engines/pi/registration.ts +0 -37
  283. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  284. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  285. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  286. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  287. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  288. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  289. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  290. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  291. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  292. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  293. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  294. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  295. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  296. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  297. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  298. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  299. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  300. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  301. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  302. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  303. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  305. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  306. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  307. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  308. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  309. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  310. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  311. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  312. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  313. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  314. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  315. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  316. package/src/execution/round-settlement.ts +0 -93
  317. package/src/execution/ui-request-queue.ts +0 -215
  318. package/src/shared/schema-env.ts +0 -44
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhushanwen/subagent-core",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Cross-host shared subagent execution layer and workflow orchestration core (dual-form npm package: TS source for workspace, dist ESM+CJS for npm)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -22,28 +22,6 @@
22
22
  },
23
23
  "default": "./dist/index.js"
24
24
  },
25
- "./engines/zcode/reader": {
26
- "import": {
27
- "types": "./dist/execution/engine/engines/zcode/reader.d.ts",
28
- "default": "./dist/execution/engine/engines/zcode/reader.js"
29
- },
30
- "require": {
31
- "types": "./dist/execution/engine/engines/zcode/reader.d.cts",
32
- "default": "./dist/execution/engine/engines/zcode/reader.cjs"
33
- },
34
- "default": "./dist/execution/engine/engines/zcode/reader.js"
35
- },
36
- "./engines/zcode/constants": {
37
- "import": {
38
- "types": "./dist/execution/engine/engines/zcode/constants.d.ts",
39
- "default": "./dist/execution/engine/engines/zcode/constants.js"
40
- },
41
- "require": {
42
- "types": "./dist/execution/engine/engines/zcode/constants.d.cts",
43
- "default": "./dist/execution/engine/engines/zcode/constants.cjs"
44
- },
45
- "default": "./dist/execution/engine/engines/zcode/constants.js"
46
- },
47
25
  "./engine/paths": {
48
26
  "import": {
49
27
  "types": "./dist/execution/engine/paths.d.ts",
@@ -55,6 +33,17 @@
55
33
  },
56
34
  "default": "./dist/execution/engine/paths.js"
57
35
  },
36
+ "./engine/engine-discovery-scan": {
37
+ "import": {
38
+ "types": "./dist/execution/engine/engine-discovery-scan.d.ts",
39
+ "default": "./dist/execution/engine/engine-discovery-scan.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/execution/engine/engine-discovery-scan.d.cts",
43
+ "default": "./dist/execution/engine/engine-discovery-scan.cjs"
44
+ },
45
+ "default": "./dist/execution/engine/engine-discovery-scan.js"
46
+ },
58
47
  "./relay-env": {
59
48
  "import": {
60
49
  "types": "./dist/execution/relay-env.d.ts",
@@ -84,19 +73,24 @@
84
73
  "ajv": "^8.20.0",
85
74
  "proper-lockfile": "^4.1.2",
86
75
  "yaml": "^2.9.0",
87
- "@xyz-agent/extension-protocol": "0.8.1"
76
+ "@xyz-agent/extension-protocol": "0.8.2",
77
+ "@zhushanwen/subagent-engine-sdk": "0.2.0"
88
78
  },
89
79
  "devDependencies": {
90
80
  "@types/node": "^24.0.0",
91
81
  "@vitest/coverage-v8": "^4.1.9",
92
82
  "tsup": "^8.5.1",
93
83
  "typescript": "^5.7.0",
94
- "vitest": "^4.1.8"
84
+ "vitest": "^4.1.8",
85
+ "@zhushanwen/pi-subagent-cli": "0.1.1",
86
+ "@zhushanwen/zcode-subagent-cli": "0.1.1"
95
87
  },
96
88
  "scripts": {
97
89
  "build": "tsup",
98
90
  "build:bundle": "tsup",
99
91
  "test": "vitest run",
100
- "typecheck": "tsc --noEmit"
92
+ "typecheck": "tsc --noEmit",
93
+ "record:engine-fixtures": "node scripts/record-engine-fixtures.mjs",
94
+ "test:engine-protocol": "vitest run src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts"
101
95
  }
102
96
  }
@@ -81,7 +81,10 @@ describe("readLastJsonlLine 孤儿终态判定(超长末行 / 截断行)", (
81
81
  const rec = recovered("orphan-bigline");
82
82
  expect(rec.status).toBe("closed");
83
83
  expect(rec.closedReason).toBe("gc");
84
- expect(rec.error).toBeUndefined();
84
+ // 回归锚点本体:300KB 完整行不误判截断([F3] in-flight 重启中断 error 在场,
85
+ // 但无截断标记——64KB 固定尾窗的旧实现会把本行从中间切开判「truncated」)。
86
+ expect(rec.error).toContain("host restart");
87
+ expect(rec.error).not.toContain("truncated");
85
88
  });
86
89
 
87
90
  it("末行截断(无尾换行的半行 JSON)→ closed/gc + error 标记截断", () => {
@@ -91,7 +94,9 @@ describe("readLastJsonlLine 孤儿终态判定(超长末行 / 截断行)", (
91
94
  const rec = recovered("orphan-truncated");
92
95
  expect(rec.status).toBe("closed");
93
96
  expect(rec.closedReason).toBe("gc");
94
- expect(rec.error).toContain("truncated last line");
97
+ // [F3] 无 resumable 信号 = in-flight:截断判定并入重启中断文案(" last line truncated"
98
+ expect(rec.error).toContain("host restart");
99
+ expect(rec.error).toContain("truncated");
95
100
  });
96
101
 
97
102
  it("超长且截断的末行 → 仍判截断 error(扩窗是为完整行服务,不放宽截断判定)", () => {
@@ -99,15 +104,18 @@ describe("readLastJsonlLine 孤儿终态判定(超长末行 / 截断行)", (
99
104
  writeOrphanSession("orphan-bigcut", bigTruncated, { trailingNewline: false });
100
105
  const rec = recovered("orphan-bigcut");
101
106
  expect(rec.status).toBe("closed");
102
- expect(rec.error).toContain("truncated last line");
107
+ // [F3] 无 resumable 信号 = in-flight:截断判定并入重启中断文案
108
+ expect(rec.error).toContain("host restart");
109
+ expect(rec.error).toContain("truncated");
103
110
  });
104
111
 
105
- it("常规末行(多行文件、完整 JSON)→ closed/gc error", () => {
112
+ it("常规末行(多行文件、完整 JSON)→ closed/gc;无 resumable 信号 = in-flight 重启中断([F3])", () => {
106
113
  writeOrphanSession("orphan-normal", JSON.stringify({ type: "message", role: "assistant", content: "final" }));
107
114
  const rec = recovered("orphan-normal");
108
115
  expect(rec.status).toBe("closed");
109
116
  expect(rec.closedReason).toBe("gc");
110
- expect(rec.error).toBeUndefined();
117
+ // [F3] 末行完整但无 resumable/result 信号 = 在途被重启中断:投影不得谎报 completed
118
+ expect(rec.error).toContain("host restart");
111
119
  });
112
120
 
113
121
  it("仅 identity 单行文件(首行即末行,合法 JSON)→ closed 无 error", () => {
@@ -122,8 +130,9 @@ describe("readLastJsonlLine 孤儿终态判定(超长末行 / 截断行)", (
122
130
  // identity 首行 + 紧跟空行结尾:非空段只剩 identity(窗口到文件头,首段完整)
123
131
  fs.writeFileSync(path.join(sessionsDir, "2026-07-18T12-00-00-000Z_orphan-empty.jsonl"), identity + "\n", "utf8");
124
132
  const rec = recovered("orphan-empty");
125
- // 唯一非空行 = identity 首行(合法 JSON)→ 不判 error
133
+ // 唯一非空行 = identity 首行(合法 JSON)→ 无截断标记;[F3] in-flight 重启中断 error 在场
126
134
  expect(rec.status).toBe("closed");
127
- expect(rec.error).toBeUndefined();
135
+ expect(rec.error).toContain("host restart");
136
+ expect(rec.error).not.toContain("truncated");
128
137
  });
129
138
  });
@@ -1,9 +1,10 @@
1
1
  /**
2
- * 从任意 thrown 值提取可读的错误信息字符串:Error → `.message`,其它 → `String(e)`。
2
+ * toErrorMessage re-export shim——单源在 @zhushanwen/subagent-engine-sdk
3
+ * (round1-reuse R11 微副本收编;core → SDK 边界正向合法)。本文件路径不变,
4
+ * core 内部 8 个消费方 import 不动。
3
5
  *
4
- * 各包独立持有本 helper(core/renderer/runtime/subagent-core/electron/ext-guards 同实现),
5
- * 不引跨包依赖——收敛 `e instanceof Error ? e.message : String(e)` 样板。
6
+ * [A8 修复]:非 Error 的 object 入参经 SDK 单源输出 JSON 结构化文本(原
7
+ * String(e) = "[object Object]");Error 入参输出逐字节不变。core barrel 不导出
8
+ * 该符号(导出面零变化)。
6
9
  */
7
- export function toErrorMessage(e: unknown): string {
8
- return e instanceof Error ? e.message : String(e);
9
- }
10
+ export { toErrorMessage } from "@zhushanwen/subagent-engine-sdk";
@@ -32,12 +32,18 @@ export interface HostServices {
32
32
  /** 结构化日志:对齐现 getLogger 调用面(level/component/message/data)。缺省 sink 按级分化:
33
33
  * warn/error 走 console、debug no-op(对齐 pi-extension-logger 语义,见 NULL_HOST.log)。 */
34
34
  log(level: LogLevel, component: string, message: string, data?: unknown): void;
35
- /** agent/skill/workflow 资源发现根(可选端口,缺席 = 调用方降级)。宿主只提供根列表
36
- * (按优先级低→高);扫描 / 同名遮蔽(last-writer-wins)/ 遮蔽报告语义归 core 统一。 */
35
+ /** agent/skill/workflow/引擎包 资源发现根(可选端口,缺席 = 调用方降级)。宿主只提供根列表
36
+ * (按优先级低→高);扫描 / 同名遮蔽(last-writer-wins)/ 遮蔽报告语义归 core 统一。
37
+ *
38
+ * engines kind(W4,设计 §3.4 L1 第二通道):引擎包发现根——dir 下一级(及 org 分组
39
+ * 二级)子项 = 候选引擎包目录,命中 package.json `xyz-agent.subagentEngine` manifest
40
+ * 即发现。打包态主通道是 env `XYZ_AGENT_ENGINE_ROOTS`(W9 注入),此端口承载宿主
41
+ * 自身模块域(如 pi 宿主包 node_modules 的引擎包 dependencies 安装位)。 */
37
42
  discoveryRoots?(): {
38
43
  agents?: DiscoveryRoot[];
39
44
  skills?: DiscoveryRoot[];
40
45
  workflows?: DiscoveryRoot[];
46
+ engines?: DiscoveryRoot[];
41
47
  };
42
48
  }
43
49
 
@@ -92,11 +92,26 @@ export interface DeliveryHandle {
92
92
  dispose(): void;
93
93
  }
94
94
 
95
+ /** countActiveFromEntries 的过滤选项([F1] 与 pending-notifications 的
96
+ * CountActiveOptions 对齐的子集——core 契约面只暴露跨 session 基准一个字段)。 */
97
+ export interface CountActivePortOptions {
98
+ /**
99
+ * [W4 读侧过滤②] 跨 session 残留过滤基准:传入时端口实现按「register entry 的
100
+ * sessionId ≠ 基准 → 跳过」过滤——fork 继承的父级注册残留(翻 process 档后 U4
101
+ * 补注销不再中性化,永久留存于子 session 文件)不进差集。
102
+ * 缺省(undefined)= 不过滤(向后兼容:既有调用方零改动行为不变)。
103
+ */
104
+ currentSessionId?: string;
105
+ }
106
+
95
107
  export interface NotifyDomainPorts {
96
108
  /** pending 活跃计数(pi 会话 entries 中 register − unregister 差集的数值)。
97
109
  * 契约为 number 而非 pi 侧 CountActiveResult:core 消费面只读 count,契约面最窄;
98
- * pi 壳注入时拆 `countActiveFromEntries(entries).count`。 */
99
- countActiveFromEntries?(entries: unknown[]): number;
110
+ * pi 壳注入时拆 `countActiveFromEntries(entries).count`。
111
+ * [F1] 第二参为可选过滤基准(CountActivePortOptions)——core 消费方(后代判定
112
+ * 读侧)持有「被读 entries 所属 session」概念时必须传入,使跨 session 残留不进
113
+ * 差集;与 pending-notifications 实装签名(entries, opts?) 对齐。 */
114
+ countActiveFromEntries?(entries: unknown[], opts?: CountActivePortOptions): number;
100
115
  /** 投递内核工厂。签名与 @xyz-agent/session-delivery 的 createDelivery 结构兼容,
101
116
  * pi 壳直传其本体即可。缺席 = 消费方降级直发。 */
102
117
  createDelivery?(port: DeliveryPort, options?: DeliveryConfig): DeliveryHandle;
@@ -145,7 +145,7 @@ model: x/y`);
145
145
  describe("AgentRegistry.loadByPath", () => {
146
146
  let ws: string;
147
147
  beforeEach(() => { ws = tmpWorkspace(); });
148
- afterEach(() => { fs.rmSync(ws, { recursive: true, force: true }); });
148
+ afterEach(() => { fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 }); });
149
149
 
150
150
  it("按绝对路径加载 agent:frontmatter + body → AgentConfig", () => {
151
151
  const file = writeAgent(path.join(ws, ".pi", "agents"), "worker", `---
@@ -23,7 +23,7 @@ describe("alive-store", () => {
23
23
 
24
24
  afterEach(() => {
25
25
  if (tmpDir) {
26
- fs.rmSync(tmpDir, { recursive: true, force: true });
26
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
27
27
  }
28
28
  });
29
29
 
@@ -76,7 +76,12 @@ import type {
76
76
  import { ModelConfigService } from "../model-config-service.ts";
77
77
  import type { ModelInfo, ModelRegistryLike } from "../model-resolver.ts";
78
78
  import { toSubagentRecordEntry } from "../record-entry.ts";
79
- import { getChildByRecord } from "../engine/engines/pi/session-runner.ts";
79
+ // W10(§2.10 ②):子进程句柄断言改读 core 侧状态镜像(host/spawned-children——
80
+ // 协议化后 spawnedChildren 持有方在引擎进程,core 消费镜像面;判据 pid 同构)。
81
+ import {
82
+ coreSpawnedChildrenMirror,
83
+ _resetCoreSpawnedChildrenMirrorForTest,
84
+ } from "../engine/host/spawned-children.ts";
80
85
  import { SubagentService } from "../subagent-service.ts";
81
86
  import type { ExecuteOptions } from "../types.ts";
82
87
 
@@ -121,6 +126,23 @@ class FakeEngine implements EnginePort {
121
126
  }
122
127
 
123
128
  capabilities(): EngineCapabilities {
129
+ // [W3] id==='pi' 的注册占位按 pi 真实能力位声明(gate 同步面放行 pi 全参数——
130
+ // V4⑤ 反向守护;否则 maxTurns/conversation 会被误拦)。
131
+ if (this.id === "pi") {
132
+ return {
133
+ schemaEnforcement: "native",
134
+ steer: "unsupported",
135
+ conversation: "native",
136
+ personaInjection: "flag",
137
+ eventGranularity: "stream",
138
+ sandbox: "emulated",
139
+ sessionRead: "full",
140
+ resume: "native",
141
+ interrupt: "kill-only",
142
+ permissionMode: "native",
143
+ maxTurns: true,
144
+ };
145
+ }
124
146
  return ZCODE_LIKE_CAPS;
125
147
  }
126
148
  async probe(): Promise<ProbeReport> {
@@ -231,6 +253,7 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
231
253
  let agentDir: string;
232
254
 
233
255
  beforeEach(() => {
256
+ _resetCoreSpawnedChildrenMirrorForTest();
234
257
  // u0-data-discovery 注入化:execute 链路的 getEngineDataDir 回退段经
235
258
  // HostServices.dataRoot() 端口,未 configureCore 即消费抛 core_host_not_configured
236
259
  // (execute fail-safe 吞掉后表现为 mock 计数 0)——端口态显式配置,值不被断言
@@ -284,8 +307,10 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
284
307
  expect(mockSpawn).not.toHaveBeenCalled();
285
308
  });
286
309
 
287
- it("[缺省] 全缺省 → pi 原路径(spawn 启动,不经引擎注册表)", async () => {
288
- // 不注册任何引擎也照跑:pi 缺省免探免注册表校验(D4「pi 恒免探」)
310
+ it("[缺省] 全缺省 → pi 路由派发([W3] pi 缺省经 registry cli 形态 port 协议派发)", async () => {
311
+ // [W3 改写] 原「不注册任何引擎也照跑(inproc DI 直连 spawn)」随 chat 域收口
312
+ // 消亡:pi 路由 = registry 'pi' 的 cli 形态 port(pi-host-binding 解析)。未注册
313
+ // 时为不可用 stub——engine.run 抛 engine_not_found,record 按 MF-6 回退可恢复。
289
314
  clearEngines();
290
315
  const modelService = new ModelConfigService({ agentDir, cwd: agentDir });
291
316
  modelService.initModel({
@@ -296,8 +321,13 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
296
321
  const service = new SubagentService({ cwd: agentDir, modelService });
297
322
  service.initSession({ pi: makePi(), sessionId: "test-session" });
298
323
 
299
- await service.execute(baseOpts(agentDir));
300
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
324
+ const handle = await service.execute(baseOpts(agentDir));
325
+ // 不可用 stub:轮次派发在首次 engine.run 拒绝(engine_not_found)→ chatMode=false
326
+ // 一次性 run 终态销毁(无孤儿 record——拒绝点唯一化在 run)。
327
+ await vi.waitFor(() => {
328
+ const rec = service.queries.collectRecords(10, "all").find((r) => r.id === handle.subagentId);
329
+ expect(rec?.status).toBe("closed");
330
+ });
301
331
  });
302
332
 
303
333
  // ============================================================
@@ -305,9 +335,9 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
305
335
  // ============================================================
306
336
 
307
337
  it("[D5] 全缺省 pi record:engine===undefined 且 entry JSON 不含 engine 键", async () => {
308
- const { service } = setup(agentDir);
338
+ const { service, piEngine } = setup(agentDir);
309
339
  const handle = await service.execute(baseOpts(agentDir));
310
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
340
+ await vi.waitFor(() => expect(piEngine.runs.length).toBe(1));
311
341
 
312
342
  const rec = service.queries.collectRecords(10, "running").find((r) => r.id === handle.subagentId);
313
343
  expect(rec).toBeDefined();
@@ -318,12 +348,11 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
318
348
  it("[D5] 显式 engine:'pi' 路由回 pi:record 不盖章 engine", async () => {
319
349
  const { service, piEngine, zcode } = setup(agentDir);
320
350
  const handle = await service.execute(baseOpts(agentDir, { engine: "pi" }));
321
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
351
+ await vi.waitFor(() => expect(piEngine.runs.length).toBe(1));
322
352
 
323
353
  expect(zcode.runs.length).toBe(0);
324
- // piEngine 只是注册表占位——D2 单轨后 pi chat Service 内部 DI PiEngine 实例
325
- //(chatPiEngine,经 EnginePort 交接轮次),registry 占位实例仍未被 chat 域消费
326
- expect(piEngine.runs.length).toBe(0);
354
+ // [W3] pi chat 路由 = registry 'pi' port(cli 形态替身)——显式 pi 请求命中它
355
+ expect(piEngine.runs.length).toBe(1);
327
356
  const rec = service.queries.collectRecords(10, "running").find((r) => r.id === handle.subagentId);
328
357
  expect(rec?.engine).toBeUndefined();
329
358
  });
@@ -339,9 +368,11 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
339
368
  .catch((e: unknown) => e);
340
369
  expect(err).toBeInstanceOf(Error);
341
370
  expect((err as Error).message).toContain("不支持 conversation");
342
- // 恢复指引(EngineError.recovery)含「改用 engine: pi 或不传该参数」
343
- expect((err as { recovery?: string }).recovery).toContain("engine: pi");
344
- expect((err as { recovery?: string }).recovery).toContain("不传该参数");
371
+ // 恢复指引(EngineError.recovery):W3 协议化口径——调参数 / 修 manifest / 升级
372
+ // 引擎包(引擎包是能力声明载体;「改用 engine: pi」内置兜底指引已随协议化删除)
373
+ expect((err as { recovery?: string }).recovery).toContain("去掉 conversation 参数");
374
+ expect((err as { recovery?: string }).recovery).toContain("修 manifest capabilities");
375
+ expect((err as { recovery?: string }).recovery).toContain("升级引擎包");
345
376
  expect(zcode.runs.length).toBe(0);
346
377
  expect(service.queries.collectRecords(10, "all")).toHaveLength(0);
347
378
  });
@@ -369,22 +400,24 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
369
400
  expect(err).toBeInstanceOf(Error);
370
401
  expect((err as Error).message).toContain("engine_capability_unsupported");
371
402
  expect((err as Error).message).toContain("maxTurns");
372
- expect((err as { recovery?: string }).recovery).toContain("engine: pi");
403
+ // W3 协议化口径:恢复指引 = 去参数 / 修 manifest / 升级引擎包(不再指向 engine: pi
404
+ expect((err as { recovery?: string }).recovery).toContain("去掉 maxTurns 参数");
405
+ expect((err as { recovery?: string }).recovery).toContain("修 manifest capabilities");
373
406
  // 「不产生孤儿 record」断言落点(V4④):store 无新增条目、引擎未被触达
374
407
  expect(zcode.runs.length).toBe(0);
375
408
  expect(service.queries.collectRecords(10, "all")).toHaveLength(0);
376
409
  });
377
410
 
378
411
  it("[V4⑤ 反向] pi + maxTurns/fork/conversation/worktree → 零拦截(pi 既有合法能力无回归)", async () => {
379
- const { service, zcode } = setup(agentDir);
380
- // maxTurns=3(V4⑤ 场景原样):正常进入 pi 轮次(spawn 被调),无同步拒绝
412
+ const { service, piEngine, zcode } = setup(agentDir);
413
+ // maxTurns=3(V4⑤ 场景原样):正常进入 pi 轮次(engine.run 被调),无同步拒绝
381
414
  const handle = await service.execute(baseOpts(agentDir, { maxTurns: 3 }));
382
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
415
+ await vi.waitFor(() => expect(piEngine.runs.length).toBe(1));
383
416
  expect(zcode.runs.length).toBe(0);
384
417
  expect(service.queries.collectRecords(10, "running").find((r) => r.id === handle.subagentId)).toBeDefined();
385
- // fork / conversation 组合同样直通(第二次 spawn 被调,无 engine_capability_unsupported)
418
+ // fork / conversation 组合同样直通(第二次 run 被调,无 engine_capability_unsupported)
386
419
  await service.execute(baseOpts(agentDir, { fork: true, conversation: true }));
387
- await vi.waitFor(() => expect(mockSpawn.mock.calls.length).toBeGreaterThanOrEqual(2));
420
+ await vi.waitFor(() => expect(piEngine.runs.length).toBeGreaterThanOrEqual(2));
388
421
  // pi + worktree:预检放行(caps.sandbox='emulated')——execute 不因能力被拒而
389
422
  // reject(worktree 创建成败是另一维度,与拦截无关)
390
423
  await expect(service.execute(baseOpts(agentDir, { worktree: true }))).resolves.toBeTypeOf("object");
@@ -475,7 +508,7 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
475
508
 
476
509
  // 引擎经 RunContext.onChildSpawned 上报子进程 → 宿主记账(kill-chain 数据源)
477
510
  zcode.runs[0].ctx.onChildSpawned?.(child);
478
- expect(getChildByRecord(handle.subagentId)).toBe(child);
511
+ expect(coreSpawnedChildrenMirror().getChildByRecord(handle.subagentId)?.pid).toBe(child.pid);
479
512
 
480
513
  // cancel → controller.abort → engine 收到的 signal aborted(kill-chain 两级的第一级)
481
514
  expect(zcode.runs[0].ctx.signal?.aborted).toBe(false);
@@ -483,7 +516,8 @@ describe("chat 工具域引擎路由分叉(U0:D4/D5/D10)", () => {
483
516
  expect(zcode.runs[0].ctx.signal?.aborted).toBe(true);
484
517
  // 子进程退出后记账按句移除
485
518
  child.emit("close", 0, null);
486
- expect(getChildByRecord(handle.subagentId)).toBeUndefined();
519
+ // 按句移除断言(W10 注):inproc 双模不回灌 childStateChanged,镜像移除由
520
+ // protocol-blackbox 承载(同 subprocess-agent-runner-routing D10 注)。
487
521
  });
488
522
  });
489
523
 
@@ -507,15 +541,15 @@ describe("chat 引擎分支 U2:probe 兜底 / journal / engineHandle", () => {
507
541
  vi.clearAllMocks();
508
542
  });
509
543
 
510
- it("[兜底] 默认路由 zcode + probe 失败 → 回退 pi runSpawn + engineFallback 留痕", async () => {
544
+ it("[兜底] 默认路由 zcode + probe 失败 → 回退 pi 协议 run + engineFallback 留痕", async () => {
511
545
  writeGlobalConfig(agentDir, "zcode");
512
546
  const { service, zcode, piEngine } = setup(agentDir);
513
547
  zcode.probeFailed = true;
514
548
 
515
549
  const handle = await service.execute(baseOpts(agentDir));
516
- // 兜底 = 走 pi runSpawn 路径(spawn 被调),非 pi EnginePort 未被消费
517
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
518
- expect(piEngine.runs.length).toBe(0);
550
+ // 兜底 = 走 pi 协议 run 路径(engine.run 被调;[W3] pi run 域同路)
551
+ await vi.waitFor(() => expect(piEngine.runs.length).toBe(1));
552
+ expect(mockSpawn).not.toHaveBeenCalled();
519
553
 
520
554
  const rec = service.queries.collectRecords(10, "running").find((r) => r.id === handle.subagentId);
521
555
  expect(rec?.engine).toBe("pi");
@@ -668,9 +702,9 @@ describe("chat 引擎分支 U2:probe 兜底 / journal / engineHandle", () => {
668
702
  });
669
703
 
670
704
  it("[D5 回归] pi 纯缺省路径 entry 不含 engine/engineFallback/engineHandle 键", async () => {
671
- const { service, pi } = setup(agentDir);
705
+ const { service, piEngine, pi } = setup(agentDir);
672
706
  const handle = await service.execute(baseOpts(agentDir));
673
- await vi.waitFor(() => expect(mockSpawn).toHaveBeenCalled());
707
+ await vi.waitFor(() => expect(piEngine.runs.length).toBe(1));
674
708
 
675
709
  const rec = service.queries.collectRecords(10, "running").find((r) => r.id === handle.subagentId);
676
710
  const entryJson = JSON.stringify(toSubagentRecordEntry(rec!));