@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
@@ -1,210 +0,0 @@
1
- // reader.test.ts —— sqlite 只读 SessionView(验收 4 的 mock 半边:真实 node:sqlite 建库
2
- // → turns/usage/toolCalls 派生;db 缺失/表漂移 → 结构化错误供降级)。真机半边(实录池
3
- // 内 db)在 zcode-engine.live.test.ts。
4
-
5
- import * as fs from "node:fs";
6
- import * as os from "node:os";
7
- import * as path from "node:path";
8
-
9
- import { beforeAll, beforeEach, describe, expect, it } from "vitest";
10
-
11
- import { readZcodeSessionView, ZcodeReaderError } from "../reader.ts";
12
-
13
- let tmpDir: string;
14
- let dbPath: string;
15
-
16
- // 建出与 zcode 0.16.5 同形的三表最小 schema(列裁剪到 reader 消费面)
17
- async function createDb(file: string): Promise<void> {
18
- const { DatabaseSync } = (await import("node:sqlite")) as { DatabaseSync: new (p: string) => unknown };
19
- type Db = {
20
- exec: (s: string) => void;
21
- prepare: (s: string) => { run: (...a: unknown[]) => void };
22
- close: () => void;
23
- };
24
- const db = new DatabaseSync(file) as unknown as Db;
25
- db.exec(
26
- "CREATE TABLE session (id TEXT PRIMARY KEY, time_created INTEGER);" +
27
- "CREATE TABLE message (id TEXT PRIMARY KEY, session_id TEXT, sequence INTEGER, data TEXT);" +
28
- "CREATE TABLE part (id TEXT PRIMARY KEY, message_id TEXT, session_id TEXT, sequence INTEGER, data TEXT);",
29
- );
30
- const insertMessage = db.prepare("INSERT INTO message (id, session_id, sequence, data) VALUES (?, ?, ?, ?)");
31
- const insertPart = db.prepare("INSERT INTO part (id, message_id, session_id, sequence, data) VALUES (?, ?, ?, ?, ?)");
32
-
33
- // session 1(目标):user prompt + assistant 两轮(text/reasoning/tool/step-finish×2)
34
- db.prepare("INSERT INTO session (id, time_created) VALUES (?, ?)").run("sess_target", 2000);
35
- insertMessage.run("msg_user", "sess_target", 0, JSON.stringify({ role: "user" }));
36
- insertPart.run("part_user_text", "msg_user", "sess_target", 0, JSON.stringify({ type: "text", text: "the task" }));
37
-
38
- insertMessage.run("msg_asst", "sess_target", 1, JSON.stringify({ role: "assistant" }));
39
- insertPart.run("p0", "msg_asst", "sess_target", 0, JSON.stringify({ type: "step-start" }));
40
- insertPart.run("p1", "msg_asst", "sess_target", 1, JSON.stringify({ type: "reasoning", text: "thinking hard" }));
41
- insertPart.run(
42
- "p2",
43
- "msg_asst",
44
- "sess_target",
45
- 2,
46
- JSON.stringify({
47
- type: "tool",
48
- tool: "Bash",
49
- state: JSON.stringify({ status: "completed", input: { command: "ls" }, output: "file-a\nfile-b" }),
50
- }),
51
- );
52
- insertPart.run(
53
- "p3",
54
- "msg_asst",
55
- "sess_target",
56
- 3,
57
- JSON.stringify({
58
- type: "step-finish",
59
- reason: "stop",
60
- cost: 0,
61
- tokens: { total: 110, input: 100, output: 10, reasoning: 0, cache: { read: 5, write: 0 } },
62
- }),
63
- );
64
- // 第二轮(同 assistant message 内第二个 step 段)
65
- insertPart.run("p4", "msg_asst", "sess_target", 4, JSON.stringify({ type: "text", text: "final answer" }));
66
- insertPart.run(
67
- "p5",
68
- "msg_asst",
69
- "sess_target",
70
- 5,
71
- JSON.stringify({
72
- type: "step-finish",
73
- reason: "stop",
74
- cost: 0.5,
75
- tokens: { total: 60, input: 50, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
76
- }),
77
- );
78
-
79
- // session 2(更早):验证「缺省取最新」与定向读取互不干扰
80
- db.prepare("INSERT INTO session (id, time_created) VALUES (?, ?)").run("sess_older", 1000);
81
- insertMessage.run("msg_old", "sess_older", 0, JSON.stringify({ role: "assistant" }));
82
- insertPart.run("part_old", "msg_old", "sess_older", 0, JSON.stringify({ type: "text", text: "old turn" }));
83
- insertPart.run(
84
- "part_old2",
85
- "msg_old",
86
- "sess_older",
87
- 1,
88
- JSON.stringify({ type: "step-finish", tokens: { input: 1, output: 1, cache: {} } }),
89
- );
90
- db.close();
91
- }
92
-
93
- beforeAll(async () => {
94
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "zcode-reader-"));
95
- dbPath = path.join(tmpDir, "db.sqlite");
96
- await createDb(dbPath);
97
- });
98
-
99
- describe("readZcodeSessionView:native 读取", () => {
100
- it("turns 派生:两轮闭合、text/thinking/toolCalls/usage 齐备(验收 4)", async () => {
101
- const view = await readZcodeSessionView(dbPath, "sess_target");
102
- expect(view.engineId).toBe("zcode");
103
- expect(view.source).toBe("native");
104
- expect(view.sessionId).toBe("sess_target");
105
- expect(view.turns).toHaveLength(2);
106
-
107
- const [t1, t2] = view.turns!;
108
- expect(t1!.text).toBe("");
109
- expect(t1!.thinking).toBe("thinking hard");
110
- expect(t1!.toolCalls).toHaveLength(1);
111
- expect(t1!.toolCalls[0]!.toolName).toBe("Bash");
112
- expect(t1!.toolCalls[0]!.args).toEqual({ command: "ls" });
113
- expect(t1!.toolCalls[0]!.result).toEqual({ content: ["file-a\nfile-b"] });
114
- expect(t1!.toolCalls[0]!.isError).toBeUndefined(); // status completed
115
- expect(t1!.closed).toBe(true);
116
-
117
- expect(t2!.text).toBe("final answer");
118
- expect(t2!.closed).toBe(true);
119
-
120
- // usage 聚合 = 两轮 usageDelta 之和(cost 累计第二段的 0.5)
121
- expect(view.usage).toEqual({ input: 150, output: 20, cacheRead: 5, cacheWrite: 0, cost: 0.5, total: 175 });
122
- });
123
-
124
- it("缺省 sessionId 取池内最新 session(time_created DESC)", async () => {
125
- const view = await readZcodeSessionView(dbPath);
126
- expect(view.sessionId).toBe("sess_target");
127
- });
128
-
129
- it("tool 状态非 completed 标 isError", async () => {
130
- // 单独建一个带失败工具调用的 session,避免污染上面的聚合断言
131
- const failDb = path.join(tmpDir, "fail.sqlite");
132
- await createDb(failDb);
133
- const { DatabaseSync } = (await import("node:sqlite")) as { DatabaseSync: new (p: string) => unknown };
134
- type Db = { prepare: (s: string) => { run: (...a: unknown[]) => void }; close: () => void };
135
- const db = new DatabaseSync(failDb) as unknown as Db;
136
- db.prepare("INSERT INTO session (id, time_created) VALUES (?, ?)").run("sess_fail", 3000);
137
- db
138
- .prepare("INSERT INTO message (id, session_id, sequence, data) VALUES (?, ?, ?, ?)")
139
- .run("msg_f", "sess_fail", 0, JSON.stringify({ role: "assistant" }));
140
- db
141
- .prepare("INSERT INTO part (id, message_id, session_id, sequence, data) VALUES (?, ?, ?, ?, ?)")
142
- .run(
143
- "pf",
144
- "msg_f",
145
- "sess_fail",
146
- 0,
147
- JSON.stringify({
148
- type: "tool",
149
- tool: "Edit",
150
- state: JSON.stringify({ status: "error", input: { file: "a" }, output: "conflict" }),
151
- }),
152
- );
153
- db.close();
154
- const view = await readZcodeSessionView(failDb, "sess_fail");
155
- expect(view.turns[0]!.toolCalls[0]!.isError).toBe(true);
156
- });
157
- });
158
-
159
- describe("readZcodeSessionView:结构化错误(供降级②③级,验收 4 负例)", () => {
160
- beforeEach(() => {
161
- // 无共享状态需重置;保留钩子位置说明负例组意图
162
- });
163
-
164
- it("db 文件缺失 → engine_session_read_failed(detail 含路径)", async () => {
165
- const missing = path.join(tmpDir, "nope.sqlite");
166
- try {
167
- await readZcodeSessionView(missing, "sess_x");
168
- expect.unreachable("should throw");
169
- } catch (err) {
170
- expect(err).toBeInstanceOf(ZcodeReaderError);
171
- const e = err as ZcodeReaderError;
172
- expect(e.code).toBe("engine_session_read_failed");
173
- expect(e.detail).toContain(missing);
174
- expect(e.message).toContain("降级");
175
- }
176
- });
177
-
178
- it("表结构漂移(缺 part 表)→ 结构化错误含漂移提示", async () => {
179
- const drifted = path.join(tmpDir, "drifted.sqlite");
180
- const { DatabaseSync } = (await import("node:sqlite")) as { DatabaseSync: new (p: string) => unknown };
181
- type Db = { exec: (s: string) => void; close: () => void };
182
- const db = new DatabaseSync(drifted) as unknown as Db;
183
- // 只建 session/message(zcode 升级把 part 改名的形态);塞一行 session 让定位
184
- // 通过、失败必然发生在 part 查询(表缺失)
185
- db.exec(
186
- "CREATE TABLE session (id TEXT PRIMARY KEY, time_created INTEGER);" +
187
- "CREATE TABLE message (id TEXT PRIMARY KEY, session_id TEXT, sequence INTEGER, data TEXT);" +
188
- "INSERT INTO session (id, time_created) VALUES ('sess_d', 1);",
189
- );
190
- db.close();
191
- try {
192
- await readZcodeSessionView(drifted);
193
- expect.unreachable("should throw");
194
- } catch (err) {
195
- const e = err as ZcodeReaderError;
196
- expect(e.code).toBe("engine_session_read_failed");
197
- expect(e.message).toContain("漂移");
198
- expect(e.message).toContain("golden");
199
- }
200
- });
201
-
202
- it("session 不存在 → 结构化错误(不静默空视图)", async () => {
203
- try {
204
- await readZcodeSessionView(dbPath, "sess_ghost");
205
- expect.unreachable("should throw");
206
- } catch (err) {
207
- expect((err as ZcodeReaderError).detail).toContain("sess_ghost");
208
- }
209
- });
210
- });
@@ -1,71 +0,0 @@
1
- // registration.test.ts —— 注册表接线(验收 6):'zcode' 可经 getEngine 获取、幂等
2
- // 覆盖、engineDataDir 默认走 common/data-dir SSOT。clearEngines 隔离全局注册表状态。
3
-
4
- import { afterEach, describe, expect, it, vi } from "vitest";
5
-
6
- // u0-data-discovery 注入化后 data-dir 回退值来自 HostServices.dataRoot() 端口——
7
- // 用例内 configureCore 假宿主控制端口态,afterEach reset 防跨用例泄漏
8
- import { configureCore, resetCoreForTests } from "../../../../../core/host-services.ts";
9
-
10
- import { clearEngines, getEngine, hasEngine, listEngines } from "../../../registry.ts";
11
- import { createZcodeEngine, registerZcodeEngine } from "../registration.ts";
12
-
13
- const FAKE_DATA_ROOT = "/fake-registration-data-root";
14
-
15
- afterEach(() => {
16
- clearEngines();
17
- resetCoreForTests();
18
- vi.restoreAllMocks();
19
- });
20
-
21
- describe("registerZcodeEngine", () => {
22
- it("登记后 getEngine('zcode') 可用,id/capabilities 正确", () => {
23
- registerZcodeEngine(() => "/tmp/data");
24
- expect(hasEngine("zcode")).toBe(true);
25
- expect(listEngines()).toContain("zcode");
26
- const engine = getEngine("zcode");
27
- expect(engine.id).toBe("zcode");
28
- expect(engine.capabilities().schemaEnforcement).toBe("emulated");
29
- });
30
-
31
- it("幂等:重复注册覆盖不堆积(listEngines 单条)", () => {
32
- registerZcodeEngine(() => "/tmp/data");
33
- registerZcodeEngine(() => "/tmp/data2");
34
- expect(listEngines().filter((id) => id === "zcode")).toHaveLength(1);
35
- // 覆盖后单例按新工厂重建(engineDataDir 已换)
36
- expect(hasEngine("zcode")).toBe(true);
37
- });
38
-
39
- it("createZcodeEngine DI 工厂:deps 直达引擎", () => {
40
- const engine = createZcodeEngine({ engineDataDir: () => "/tmp/x" });
41
- expect(engine.id).toBe("zcode");
42
- });
43
- });
44
-
45
- describe("engineDataDir 默认通道(common/data-dir SSOT)", () => {
46
- it("缺省经 getEngineDataDir 解析:env 优先,缺失回落宿主数据根(warn 一次)", async () => {
47
- // warn 断言走 getEngineDataDir 自带的 DI warn 参数——缺省 warn 通道是
48
- // core logger facade(configureCore 后经 pi-host 桥接落文件,不经
49
- // console.warn),spy console 永远收不到且会让 logger 落文件产生测试副作用。
50
- const { getEngineDataDir, resetDataDirWarnForTests } = await import("../../../common/data-dir.ts");
51
- const warns: string[] = [];
52
- const prev = process.env["XYZ_AGENT_DATA_DIR"];
53
- delete process.env["XYZ_AGENT_DATA_DIR"];
54
- try {
55
- resetCoreForTests();
56
- configureCore({ dataRoot: () => FAKE_DATA_ROOT, log: () => {} });
57
- resetDataDirWarnForTests();
58
- // 回退分支:无 env → HostServices.dataRoot()(假宿主值)+ warn 一次
59
- expect(getEngineDataDir(process.env, (m) => warns.push(m))).toBe(FAKE_DATA_ROOT);
60
- expect(warns).toHaveLength(1);
61
- expect(warns[0]).toContain("XYZ_AGENT_DATA_DIR");
62
- // env 分支:显式注入即取 env 值(透传链证据见 common/data-dir.ts 文件头)
63
- process.env["XYZ_AGENT_DATA_DIR"] = "/from-host";
64
- expect(getEngineDataDir(process.env, (m) => warns.push(m))).toBe("/from-host");
65
- expect(warns).toHaveLength(1);
66
- } finally {
67
- if (prev !== undefined) process.env["XYZ_AGENT_DATA_DIR"] = prev;
68
- else delete process.env["XYZ_AGENT_DATA_DIR"];
69
- }
70
- });
71
- });
@@ -1,247 +0,0 @@
1
- // session-channel-dispose-harvest.test.ts —— P0-1 U5 dispose 前收割单测(机制层)。
2
- //
3
- // 设计权威源:docs/design/timeout-zcode-turn-and-settled-watchdog.md §3.4(退化路径)、
4
- // §6 D7(dispose 收割兜底)、§11 P-Z3(close 吞没 → dispose 触发 failAllTurns)。
5
- // P-Z3 的「close 事件吞没」在真实子进程形态不可确定性注入(Node child 进程退出后
6
- // stdio 关闭即触发 close 事件)——真实现场归 Gate B;本文件用 mock 连接承载机制层
7
- // 可判定形态:不触发 onClose(= close 吞没的机制等价物)→ dispose → 在途 turn 收敛
8
- // 为明确失败。与 zcode-engine-dispose.test.ts(fake-appserver 子进程集成面)互补。
9
- //
10
- // 覆盖:
11
- // ① close 吞没形态:dispose 触发 failAllTurns——在途 turn 于 dispose 时收割
12
- // (P-Z3 核心断言),收割后到达的终态不再改写(settled 守卫);
13
- // ② grace 窗口内全部终态化:并发多会话 turn 全量收割,不留永久 pending;
14
- // ③ 正常 close 主路径零回归:onClose 收割先行 → dispose no-op 不改写收割错误;
15
- // ④ 终态已落定(成功)后 dispose:settled 守卫不改写已成功结果;
16
- // ⑤ dispose 收割后 closeSession 短路:runTurn finally 不再发 session/close
17
- // (防写死进程/惰性重建——D7 收割语义的必要闭环)+ 正常完成对照(发 close);
18
- // ⑥ 二次 dispose 幂等。
19
-
20
- import { afterEach, describe, expect, it } from "vitest";
21
-
22
- import type { AppServerConnection } from "../connection.ts";
23
- import {
24
- SessionChannel,
25
- type SessionTurnResult,
26
- type SessionTurnOptions,
27
- } from "../session-channel.ts";
28
-
29
- // ============================================================
30
- // mock 连接 + 驱动器(与 session-channel-turn-timers.test.ts 同形态,
31
- // 增补 onClose handler 的手动触发面——close 吞没注入的机制等价物)
32
- // ============================================================
33
-
34
- interface MockChannel {
35
- ch: SessionChannel;
36
- /** 我方发出的请求帧流水(method 序可断言)。 */
37
- requests: Array<{ method: string; params: unknown }>;
38
- /** 手动触发连接崩溃广播(close 吞没形态 = 不触发;正常形态 = 测试显式触发)。 */
39
- emitClose: (reason: string) => void;
40
- emit: (method: string, params: unknown) => void;
41
- emitTerminal: (sessionId: string | undefined, status: string) => void;
42
- }
43
-
44
- let sidSeq = 0;
45
-
46
- function makeMockChannel(): MockChannel {
47
- const notifications = new Map<string, (params: unknown) => void>();
48
- const requests: Array<{ method: string; params: unknown }> = [];
49
- const closeHandlers = new Set<(reason: string) => void>();
50
- const conn = {
51
- alive: true,
52
- onNotification: (method: string, h: (params: unknown) => void) => {
53
- notifications.set(method, h);
54
- return () => notifications.delete(method);
55
- },
56
- onClose: (h: (reason: string) => void) => {
57
- closeHandlers.add(h);
58
- return () => closeHandlers.delete(h);
59
- },
60
- request: (method: string, params: unknown) => {
61
- requests.push({ method, params });
62
- if (method === "session/create") {
63
- sidSeq += 1;
64
- return Promise.resolve({ session: { sessionId: `sess_h${sidSeq}` } });
65
- }
66
- if (method === "session/send") return Promise.resolve({ accepted: true });
67
- if (method === "session/read") return Promise.resolve({ messages: [] });
68
- return Promise.resolve({});
69
- },
70
- } as unknown as AppServerConnection;
71
- const ch = new SessionChannel(conn);
72
- return {
73
- ch,
74
- requests,
75
- emitClose: (reason) => {
76
- for (const fn of [...closeHandlers]) fn(reason);
77
- },
78
- emit: (method, params) => notifications.get(method)?.(params),
79
- emitTerminal: (sessionId, status) =>
80
- notifications
81
- .get("v4/telemetry/event")
82
- ?.({ kind: "turn.terminal", status, sessionId }),
83
- };
84
- }
85
-
86
- interface TurnTracker {
87
- outcome: "pending" | "fulfilled" | "rejected";
88
- result: SessionTurnResult | undefined;
89
- error: unknown;
90
- promise: Promise<SessionTurnResult>;
91
- /** onSessionCreated 回填(getter——回调晚于 tracker 构造,值拷贝会恒空)。 */
92
- readonly sessionId: string;
93
- }
94
-
95
- function startTurn(ch: SessionChannel, opts: SessionTurnOptions = {}): TurnTracker {
96
- let sessionId = "";
97
- const promise = ch.runTurn({ workspacePath: "/tmp/ws-harvest", mode: "yolo" }, "任务", {
98
- onSessionCreated: (sid) => {
99
- sessionId = sid;
100
- },
101
- ...opts,
102
- });
103
- const t: TurnTracker = {
104
- outcome: "pending",
105
- result: undefined,
106
- error: undefined,
107
- promise,
108
- get sessionId(): string {
109
- return sessionId;
110
- },
111
- };
112
- void promise.then(
113
- (r) => {
114
- t.outcome = "fulfilled";
115
- t.result = r;
116
- },
117
- (e) => {
118
- t.outcome = "rejected";
119
- t.error = e;
120
- },
121
- );
122
- return t;
123
- }
124
-
125
- /** 排空微任务链(create→subscribe→send 全是已 resolve 的 promise——一拍 setTimeout 足够)。 */
126
- function flush(): Promise<void> {
127
- return new Promise((resolve) => setTimeout(resolve, 0));
128
- }
129
-
130
- async function settle(t: TurnTracker): Promise<void> {
131
- await t.promise.then(
132
- () => undefined,
133
- () => undefined,
134
- );
135
- }
136
-
137
- let enginesChannels: SessionChannel[] = [];
138
- afterEach(() => {
139
- for (const ch of enginesChannels.splice(0)) ch.dispose();
140
- });
141
-
142
- // ============================================================
143
- // dispose 收割(P0-1 U5/D7:close 缺失/被吞没的退化路径闭合)
144
- // ============================================================
145
-
146
- describe("dispose 收割(P-Z3 机制层:close 吞没 → dispose 触发 failAllTurns)", () => {
147
- it("close 吞没形态:dispose 时在途 turn 收割为明确失败,迟到终态不再改写", async () => {
148
- const m = makeMockChannel();
149
- enginesChannels.push(m.ch);
150
- const t = startTurn(m.ch);
151
- await flush();
152
- expect(t.outcome).toBe("pending"); // send 已发、无终态——在途
153
-
154
- m.ch.dispose(); // close 吞没(onClose 未触发)→ dispose 收割兜底
155
- await settle(t);
156
-
157
- expect(t.outcome).toBe("rejected");
158
- const err = t.error as Error;
159
- expect(err).toBeInstanceOf(Error);
160
- expect(err.message).toContain("已 dispose");
161
- expect(err.message).toContain("收割");
162
- expect(err.message).toContain("恢复指引");
163
- // 收割后到达的权威终态:settled 守卫——落定结果不改写
164
- m.emitTerminal(t.sessionId, "success");
165
- expect(t.outcome).toBe("rejected");
166
- expect((t.error as Error).message).toBe(err.message);
167
- });
168
-
169
- it("grace 窗口内全部终态化:并发双会话 turn 全量收割,不留永久 pending", async () => {
170
- const m = makeMockChannel();
171
- enginesChannels.push(m.ch);
172
- const t1 = startTurn(m.ch);
173
- const t2 = startTurn(m.ch);
174
- await flush();
175
- expect(t1.sessionId).not.toBe(t2.sessionId); // 双会话确实并发
176
- expect(t1.outcome).toBe("pending");
177
- expect(t2.outcome).toBe("pending");
178
-
179
- m.ch.dispose();
180
- await Promise.all([settle(t1), settle(t2)]);
181
-
182
- expect(t1.outcome).toBe("rejected");
183
- expect(t2.outcome).toBe("rejected");
184
- expect((t1.error as Error).message).toContain("已 dispose");
185
- expect((t2.error as Error).message).toContain("已 dispose");
186
- });
187
-
188
- it("正常 close 主路径零回归:onClose 收割先行(错误=连接层 reason),dispose no-op 不改写", async () => {
189
- const m = makeMockChannel();
190
- enginesChannels.push(m.ch);
191
- const t = startTurn(m.ch);
192
- await flush();
193
-
194
- m.emitClose("进程退出(code=0 signal=SIGTERM)"); // onClose 主路径收割(正常 close 到达)
195
- await settle(t);
196
- expect(t.outcome).toBe("rejected");
197
- const onCloseErr = t.error as Error;
198
- expect(onCloseErr.message).toContain("app-server 进程退出");
199
-
200
- m.ch.dispose(); // activeTurns 已空——幂等 no-op,收割错误不被 dispose 文案改写
201
- expect(t.outcome).toBe("rejected");
202
- expect((t.error as Error).message).toBe(onCloseErr.message);
203
- });
204
-
205
- it("终态已落定(成功)后 dispose:settled 守卫不改写已成功结果", async () => {
206
- const m = makeMockChannel();
207
- enginesChannels.push(m.ch);
208
- const t = startTurn(m.ch);
209
- await flush();
210
- m.emitTerminal(t.sessionId, "success");
211
- await settle(t);
212
- expect(t.outcome).toBe("fulfilled");
213
-
214
- m.ch.dispose(); // 已成功收尾的 turn 不受 dispose 收割影响
215
- expect(t.outcome).toBe("fulfilled");
216
- expect(t.result?.terminal).toEqual({ status: "success", source: "turn.terminal" });
217
- });
218
-
219
- it("dispose 收割后 closeSession 短路:finally 不发 session/close(防写死进程/惰性重建);正常完成对照=发 close", async () => {
220
- const m1 = makeMockChannel();
221
- enginesChannels.push(m1.ch);
222
- const t1 = startTurn(m1.ch);
223
- await flush();
224
- m1.ch.dispose();
225
- await settle(t1);
226
- await flush(); // runTurn finally 的 closeSession 已过
227
- expect(t1.outcome).toBe("rejected");
228
- expect(m1.requests.map((r) => r.method)).not.toContain("session/close");
229
-
230
- // 对照:正常完成的 turn,finally 发 session/close(D4 用后即毁——零回归面)
231
- const m2 = makeMockChannel();
232
- enginesChannels.push(m2.ch);
233
- const t2 = startTurn(m2.ch);
234
- await flush();
235
- m2.emitTerminal(t2.sessionId, "success");
236
- await settle(t2);
237
- expect(t2.outcome).toBe("fulfilled");
238
- expect(m2.requests.map((r) => r.method)).toContain("session/close");
239
- });
240
-
241
- it("二次 dispose 幂等:无在途 turn 时 dispose 是 no-op 不抛", async () => {
242
- const m = makeMockChannel();
243
- enginesChannels.push(m.ch);
244
- expect(() => m.ch.dispose()).not.toThrow();
245
- expect(() => m.ch.dispose()).not.toThrow();
246
- });
247
- });