@zhushanwen/subagent-core 0.4.0 → 0.6.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 (309) hide show
  1. package/dist/{chunk-4KN4TTG7.js → chunk-43ONBFZX.js} +1 -1
  2. package/dist/{chunk-X7SZ5HLQ.js → chunk-V3VHZ2VX.js} +20 -27
  3. package/dist/execution/engine/engines/zcode/constants.cjs +29 -41
  4. package/dist/execution/engine/engines/zcode/constants.d.cts +65 -53
  5. package/dist/execution/engine/engines/zcode/constants.d.ts +65 -53
  6. package/dist/execution/engine/engines/zcode/constants.js +17 -27
  7. package/dist/execution/engine/engines/zcode/reader.d.cts +2 -1
  8. package/dist/execution/engine/engines/zcode/reader.d.ts +2 -1
  9. package/dist/execution/engine/engines/zcode/reader.js +2 -2
  10. package/dist/index.cjs +17100 -14082
  11. package/dist/index.d.cts +5336 -4033
  12. package/dist/index.d.ts +5336 -4033
  13. package/dist/index.js +17020 -14055
  14. package/dist/{types-DpUO16pj.d.cts → types-C3fE3R9x.d.cts} +280 -112
  15. package/dist/{types-DpUO16pj.d.ts → types-C3fE3R9x.d.ts} +280 -112
  16. package/dist.bundle/index.cjs +34933 -0
  17. package/package.json +3 -3
  18. package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +0 -1
  19. package/src/__tests__/append-system-prompt-assembly.test.ts +8 -7
  20. package/src/__tests__/fr4-get-state-handshake.test.ts +2 -2
  21. package/src/__tests__/m2-append-content-probe.test.ts +0 -1
  22. package/src/__tests__/manifest-store.test.ts +10 -9
  23. package/src/__tests__/record-store-cache.test.ts +0 -2
  24. package/src/__tests__/record-store-index.test.ts +1 -2
  25. package/src/__tests__/review-fix-loop-script.test.ts +4 -2
  26. package/src/__tests__/review-fix-loop-utils.test.ts +10 -10
  27. package/src/__tests__/robustness-low-batch1.test.ts +6 -5
  28. package/src/__tests__/robustness-medium-batch1.test.ts +2 -2
  29. package/src/__tests__/robustness-medium-batch2.test.ts +17 -6
  30. package/src/__tests__/robustness-medium-batch4.test.ts +2 -2
  31. package/src/__tests__/session-runner.test.ts +1 -1
  32. package/src/core/__tests__/host-services.test.ts +2 -2
  33. package/src/core/__tests__/logger.test.ts +1 -1
  34. package/src/core/error-message.ts +9 -0
  35. package/src/core/host-services.ts +21 -5
  36. package/src/core/notify-ports.ts +18 -5
  37. package/src/execution/__tests__/agent-profile.test.ts +4 -4
  38. package/src/execution/__tests__/agent-registry.test.ts +370 -0
  39. package/src/execution/__tests__/agent-result-mapper.test.ts +18 -2
  40. package/src/execution/__tests__/agents-assembly.test.ts +2 -2
  41. package/src/execution/__tests__/alive-store.test.ts +1 -1
  42. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
  43. package/src/execution/__tests__/chat-engine-routing.test.ts +68 -33
  44. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +4 -4
  45. package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
  46. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  47. package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
  48. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  49. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
  50. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  51. package/src/execution/__tests__/config.test.ts +1 -1
  52. package/src/execution/__tests__/delivery-methods.test.ts +75 -62
  53. package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
  54. package/src/execution/__tests__/descendant-sweep.test.ts +6 -6
  55. package/src/execution/__tests__/dialog-queue.test.ts +2 -2
  56. package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
  57. package/src/execution/__tests__/epipe-fallback.test.ts +29 -24
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +21 -91
  59. package/src/execution/__tests__/execute-nesting.test.ts +34 -188
  60. package/src/execution/__tests__/execution-record.test.ts +217 -60
  61. package/src/execution/__tests__/execution-runtime-face.test.ts +5 -5
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +4 -4
  63. package/src/execution/__tests__/finalize-record.test.ts +173 -17
  64. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  65. package/src/execution/__tests__/gc-timer.test.ts +56 -3
  66. package/src/execution/__tests__/get-record-for-action-restart.test.ts +12 -12
  67. package/src/execution/__tests__/get-state-handshake.test.ts +1 -1
  68. package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
  69. package/src/execution/__tests__/helpers/session-runner-mocks.ts +113 -0
  70. package/src/execution/__tests__/helpers/spawn-mock.ts +150 -3
  71. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +137 -0
  72. package/src/execution/__tests__/keep-alive-no-progress.test.ts +50 -148
  73. package/src/execution/__tests__/kill-all-escalation.test.ts +2 -2
  74. package/src/execution/__tests__/lifecycle-predicates.test.ts +1 -2
  75. package/src/execution/__tests__/manifest-parentid.test.ts +4 -4
  76. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  77. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +1 -1
  78. package/src/execution/__tests__/model-resolver.test.ts +2 -2
  79. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +23 -121
  80. package/src/execution/__tests__/nested-visibility.test.ts +2 -0
  81. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  82. package/src/execution/__tests__/notify-ledger.test.ts +1000 -18
  83. package/src/execution/__tests__/output-collector.test.ts +117 -6
  84. package/src/execution/__tests__/pi-invocation.test.ts +36 -4
  85. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  86. package/src/execution/__tests__/record-store.test.ts +10 -9
  87. package/src/execution/__tests__/records-cwd-isolation.test.ts +2 -2
  88. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +29 -132
  89. package/src/execution/__tests__/recursive-visibility-env.test.ts +55 -179
  90. package/src/execution/__tests__/relay-env.test.ts +12 -1
  91. package/src/execution/__tests__/rpc-mode.test.ts +2 -2
  92. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +387 -0
  93. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +15 -9
  94. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +4 -4
  95. package/src/execution/__tests__/run-spawn-edges.test.ts +17 -15
  96. package/src/execution/__tests__/run-spawn-integration.test.ts +2 -2
  97. package/src/execution/__tests__/run-spawn-resume.test.ts +2 -2
  98. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +2 -2
  99. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +4 -4
  100. package/src/execution/__tests__/service-kill-escalation.test.ts +7 -5
  101. package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
  102. package/src/execution/__tests__/session-file-gc.test.ts +36 -1
  103. package/src/execution/__tests__/session-pending.test.ts +257 -14
  104. package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
  105. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +1 -1
  106. package/src/execution/__tests__/session-runner-close-prune.test.ts +2 -2
  107. package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
  108. package/src/execution/__tests__/session-runner-epipe.test.ts +3 -3
  109. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +5 -4
  110. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +290 -0
  111. package/src/execution/__tests__/session-runner-schema-env.test.ts +7 -5
  112. package/src/execution/__tests__/settled-watchdog.test.ts +282 -47
  113. package/src/execution/__tests__/spawn-args.test.ts +11 -10
  114. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +26 -23
  115. package/src/execution/__tests__/spawn-event-adapter.test.ts +3 -3
  116. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
  117. package/src/execution/__tests__/spawned-children.test.ts +2 -1
  118. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  119. package/src/execution/__tests__/start-sync-model-guard.test.ts +5 -5
  120. package/src/execution/__tests__/stdin-writer.test.ts +6 -4
  121. package/src/execution/__tests__/stream-sink-retirement.test.ts +6 -6
  122. package/src/execution/__tests__/subagent-actions-core.test.ts +48 -22
  123. package/src/execution/__tests__/subagent-service-message-close.test.ts +29 -26
  124. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +21 -8
  125. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -22
  126. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +30 -29
  127. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +45 -20
  128. package/src/execution/__tests__/subagent-service.test.ts +37 -30
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +88 -12
  130. package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +75 -0
  131. package/src/execution/__tests__/subprocess-agent-runner.test.ts +22 -20
  132. package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
  133. package/src/execution/__tests__/temp-prompt.test.ts +1 -1
  134. package/src/execution/__tests__/timeout-integration.test.ts +6 -5
  135. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +1 -1
  137. package/src/execution/__tests__/turn-limiter.test.ts +1 -1
  138. package/src/execution/__tests__/ui-request-handler-factory.test.ts +12 -6
  139. package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
  140. package/src/execution/__tests__/ui-request-queue.test.ts +142 -2
  141. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  142. package/src/execution/__tests__/worktree-manager.test.ts +14 -5
  143. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +4 -3
  144. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  145. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  146. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  147. package/src/execution/agent-registry.ts +74 -30
  148. package/src/execution/agent-result-mapper.ts +3 -0
  149. package/src/execution/cold-resurrect.ts +199 -0
  150. package/src/execution/collect-coordinator.ts +200 -0
  151. package/src/execution/config.ts +77 -5
  152. package/src/execution/engine/__tests__/common/capability-gate.test.ts +91 -0
  153. package/src/execution/engine/__tests__/common/data-dir.test.ts +1 -1
  154. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  155. package/src/execution/engine/__tests__/common/journal-wiring.test.ts +84 -0
  156. package/src/execution/engine/__tests__/common/kill-chain.test.ts +34 -7
  157. package/src/execution/engine/__tests__/common/persona-router.test.ts +4 -5
  158. package/src/execution/engine/__tests__/common/pool-manager.test.ts +213 -53
  159. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +149 -0
  160. package/src/execution/engine/__tests__/common/session-view-service.test.ts +499 -0
  161. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +22 -112
  162. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +15 -28
  163. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
  164. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +12 -12
  165. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +2 -2
  166. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +21 -82
  167. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +4 -7
  168. package/src/execution/engine/__tests__/engine-discovery.test.ts +15 -3
  169. package/src/execution/engine/__tests__/model-prompt.test.ts +15 -3
  170. package/src/execution/engine/__tests__/registry.test.ts +4 -2
  171. package/src/execution/engine/__tests__/routing.test.ts +115 -6
  172. package/src/execution/engine/common/capability-gate.ts +92 -0
  173. package/src/execution/engine/common/journal-wiring.ts +97 -0
  174. package/src/execution/engine/common/kill-chain.ts +42 -10
  175. package/src/execution/engine/common/nesting-guard.ts +66 -0
  176. package/src/execution/engine/common/persona-router.ts +18 -8
  177. package/src/execution/engine/common/pool-manager.ts +332 -78
  178. package/src/execution/engine/common/session-view-service.ts +506 -0
  179. package/src/execution/engine/common/session-view-types.ts +125 -0
  180. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +174 -28
  181. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +257 -0
  182. package/src/execution/{argv-mirror.ts → engine/engines/pi/argv-mirror.ts} +43 -21
  183. package/src/execution/{get-state-handshake.ts → engine/engines/pi/get-state-handshake.ts} +1 -1
  184. package/src/execution/{output-collector.ts → engine/engines/pi/output-collector.ts} +108 -19
  185. package/src/execution/engine/engines/pi/pi-engine.ts +434 -38
  186. package/src/execution/{pi-invocation.ts → engine/engines/pi/pi-invocation.ts} +2 -2
  187. package/src/execution/engine/engines/pi/reader.ts +11 -0
  188. package/src/execution/engine/engines/pi/registration.ts +4 -2
  189. package/src/execution/{session-runner.ts → engine/engines/pi/session-runner.ts} +617 -412
  190. package/src/execution/{spawn-event-adapter.ts → engine/engines/pi/spawn-event-adapter.ts} +75 -34
  191. package/src/execution/{stdin-writer.ts → engine/engines/pi/stdin-writer.ts} +10 -9
  192. package/src/execution/{temp-prompt.ts → engine/engines/pi/temp-prompt.ts} +2 -2
  193. package/src/execution/{turn-limiter.ts → engine/engines/pi/turn-limiter.ts} +1 -1
  194. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +54 -27
  195. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
  196. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +13 -12
  197. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +7 -210
  198. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +6 -110
  199. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +247 -0
  200. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +451 -0
  201. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +20 -8
  202. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +77 -110
  203. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +26 -320
  204. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +210 -0
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +353 -0
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +282 -0
  207. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +372 -0
  208. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +48 -148
  209. package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
  210. package/src/execution/engine/engines/zcode/connection.ts +24 -11
  211. package/src/execution/engine/engines/zcode/constants.ts +75 -71
  212. package/src/execution/engine/engines/zcode/golden-sample.ts +8 -46
  213. package/src/execution/engine/engines/zcode/parser.ts +12 -346
  214. package/src/execution/engine/engines/zcode/preparer.ts +12 -143
  215. package/src/execution/engine/engines/zcode/session-channel.ts +351 -39
  216. package/src/execution/engine/engines/zcode/zcode-engine.ts +665 -760
  217. package/src/execution/engine/host-task-spec.ts +32 -36
  218. package/src/execution/engine/model-validation.ts +177 -0
  219. package/src/execution/engine/port.ts +24 -6
  220. package/src/execution/engine/routing.ts +75 -1
  221. package/src/execution/engine/types.ts +30 -103
  222. package/src/execution/execution-record.ts +229 -144
  223. package/src/execution/finalize-record.ts +141 -99
  224. package/src/execution/idle-gc.ts +28 -0
  225. package/src/execution/lifecycle-predicates.ts +1 -1
  226. package/src/execution/notifier.ts +234 -25
  227. package/src/execution/notify-host.ts +232 -0
  228. package/src/execution/record-entry.ts +16 -0
  229. package/src/execution/record-store.ts +280 -103
  230. package/src/execution/round-settlement.ts +93 -0
  231. package/src/execution/session-file-gc.ts +96 -62
  232. package/src/execution/session-reconstructor.ts +256 -143
  233. package/src/execution/sessions-index.ts +117 -47
  234. package/src/execution/settled-watchdog.ts +264 -52
  235. package/src/execution/subagent-actions-core.ts +84 -28
  236. package/src/execution/subagent-service.ts +1225 -964
  237. package/src/execution/subprocess-agent-runner.ts +144 -97
  238. package/src/execution/sync-rebuild.ts +87 -0
  239. package/src/execution/types.ts +72 -0
  240. package/src/execution/ui-request-handler-factory.ts +102 -74
  241. package/src/execution/ui-request-queue.ts +50 -19
  242. package/src/index.ts +442 -316
  243. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +1 -1
  244. package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
  245. package/src/orchestration/__tests__/args-validator.test.ts +14 -0
  246. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  247. package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +1 -1
  248. package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +11 -9
  249. package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
  250. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  251. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  252. package/src/orchestration/__tests__/file-run-store.test.ts +7 -6
  253. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +2 -2
  254. package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +1 -1
  255. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
  256. package/src/orchestration/__tests__/lifecycle.test.ts +7 -5
  257. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
  258. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  259. package/src/orchestration/__tests__/run-snapshot.test.ts +8 -5
  260. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  261. package/src/orchestration/__tests__/script-lint.test.ts +17 -0
  262. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  263. package/src/orchestration/__tests__/test-mocks.ts +2 -0
  264. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +7 -6
  265. package/src/orchestration/__tests__/worker-message-pump-finalize-run.test.ts +229 -0
  266. package/src/orchestration/__tests__/{error-recovery-handlers.test.ts → worker-message-pump-handlers.test.ts} +27 -19
  267. package/src/orchestration/__tests__/{error-recovery-postmessage-defense.test.ts → worker-message-pump-postmessage-defense.test.ts} +8 -8
  268. package/src/orchestration/__tests__/{error-recovery-serialize-failed-result.test.ts → worker-message-pump-serialize-failed-result.test.ts} +2 -2
  269. package/src/orchestration/__tests__/{error-recovery-workflow-call.test.ts → worker-message-pump-workflow-call.test.ts} +1 -1
  270. package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +1 -1
  271. package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
  272. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  273. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
  274. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  275. package/src/orchestration/agent-opts-resolver.ts +1 -1
  276. package/src/orchestration/args-validator.ts +53 -31
  277. package/src/orchestration/execute-agent-call.ts +19 -73
  278. package/src/orchestration/launcher.ts +128 -81
  279. package/src/orchestration/lifecycle.ts +43 -45
  280. package/src/orchestration/models/ports.ts +4 -4
  281. package/src/orchestration/models/run-runtime.ts +2 -2
  282. package/src/orchestration/models/trace.ts +1 -1
  283. package/src/orchestration/models/types.ts +111 -22
  284. package/src/orchestration/models/workflow-run.ts +1 -1
  285. package/src/orchestration/script-lint.ts +91 -58
  286. package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +157 -150
  287. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  288. package/src/shared/__tests__/meta-parser.test.ts +151 -0
  289. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  290. package/src/shared/__tests__/resource-discovery.test.ts +258 -215
  291. package/src/shared/atomic-write.ts +12 -9
  292. package/src/shared/meta-parser.ts +158 -84
  293. package/src/shared/model-ref.ts +15 -2
  294. package/src/shared/resource-discovery.ts +9 -183
  295. package/src/shared/schema-jsonify.ts +1 -1
  296. package/workflows/review-fix-loop-utils.cjs +151 -89
  297. package/workflows/review-fix-loop-utils.d.cts +287 -0
  298. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  299. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  300. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  301. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  302. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  303. package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +0 -387
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -710
  305. package/src/execution/engine/engines/zcode/appserver-home.ts +0 -442
  306. package/src/execution/engine/engines/zcode/appserver-probe.ts +0 -141
  307. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  308. package/src/execution/execute-options-mapper.ts +0 -115
  309. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
@@ -12,7 +12,9 @@ import {
12
12
  getFullText,
13
13
  getFullTextFrom,
14
14
  getTotalUsage,
15
+ jsonlToAgentEvent,
15
16
  markReconstructedStatus,
17
+ resurrectClosed,
16
18
  nextRoundBaseTurnIndex,
17
19
  deriveOutcome,
18
20
  projectOutcome,
@@ -38,8 +40,12 @@ function makeRecord(over: Partial<ExecutionRecord> = {}): ExecutionRecord {
38
40
  id: "test-1",
39
41
  agent: "worker",
40
42
  model: "test-model",
43
+ slug: "t",
44
+ rootSessionId: undefined,
45
+ parentRecordId: undefined,
46
+ depth: 0,
41
47
  thinkingLevel: undefined,
42
- mode: "sync",
48
+ mode: "background",
43
49
  task: "test task",
44
50
  startedAt: 1000,
45
51
  status: "running",
@@ -75,6 +81,7 @@ describe("createRecord", () => {
75
81
  model: "m1",
76
82
  thinkingLevel: "high",
77
83
  mode: "background",
84
+ slug: "t",
78
85
  task: "review PR",
79
86
  startedAt: 2000,
80
87
  });
@@ -102,21 +109,21 @@ describe("createRecord", () => {
102
109
  it("stores controller when provided (background)", () => {
103
110
  const controller = new AbortController();
104
111
  const r = createRecord("r1", {
105
- agent: "w", model: "m", mode: "background", task: "t", startedAt: 0, controller,
112
+ agent: "w", model: "m", mode: "background", slug: "t", task: "t", startedAt: 0, controller,
106
113
  });
107
114
  expect(r.controller).toBe(controller);
108
115
  });
109
116
 
110
117
  it("stores rootSessionId when provided", () => {
111
118
  const r = createRecord("r1", {
112
- agent: "w", model: "m", mode: "sync", task: "t", startedAt: 0, rootSessionId: "sess-A",
119
+ agent: "w", model: "m", mode: "background", slug: "t", task: "t", startedAt: 0, rootSessionId: "sess-A",
113
120
  });
114
121
  expect(r.rootSessionId).toBe("sess-A");
115
122
  });
116
123
 
117
124
  it("defaults rootSessionId to undefined when omitted", () => {
118
125
  const r = createRecord("r1", {
119
- agent: "w", model: "m", mode: "sync", task: "t", startedAt: 0,
126
+ agent: "w", model: "m", mode: "background", slug: "t", task: "t", startedAt: 0,
120
127
  });
121
128
  expect(r.rootSessionId).toBeUndefined();
122
129
  });
@@ -478,7 +485,7 @@ describe("getEventLog", () => {
478
485
  // ============================================================
479
486
  describe("getCurrentActivity", () => {
480
487
  it("returns undefined when status is not running", () => {
481
- const r = makeRecord({ status: "done" });
488
+ const r = makeRecord({ status: "closed" });
482
489
  expect(getCurrentActivity(r)).toBeUndefined();
483
490
  });
484
491
 
@@ -673,7 +680,7 @@ describe("nextRoundBaseTurnIndex", () => {
673
680
  agent: "worker",
674
681
  model: "test-model",
675
682
  thinkingLevel: undefined,
676
- mode: "sync",
683
+ mode: "background",
677
684
  task: "t",
678
685
  slug: "t",
679
686
  startedAt: 1000,
@@ -753,8 +760,8 @@ describe("getAllToolCalls", () => {
753
760
  // 导出形状只有 4 个语义字段
754
761
  expect(Object.keys(tc!).sort()).toEqual(["args", "isError", "result", "toolName"]);
755
762
  // 内部字段不存在
756
- expect((tc as Record<string, unknown>)._status).toBeUndefined();
757
- expect((tc as Record<string, unknown>).startedTs).toBeUndefined();
763
+ expect((tc as unknown as Record<string, unknown>)._status).toBeUndefined();
764
+ expect((tc as unknown as Record<string, unknown>).startedTs).toBeUndefined();
758
765
  });
759
766
  });
760
767
 
@@ -797,70 +804,70 @@ describe("getTotalUsage", () => {
797
804
  describe("tryTransition", () => {
798
805
  it("returns true and sets status when transitioning from running", () => {
799
806
  const r = makeRecord({ status: "running" });
800
- expect(tryTransition(r, "done")).toBe(true);
801
- expect(r.status).toBe("done");
807
+ expect(tryTransition(r, "closed")).toBe(true);
808
+ expect(r.status).toBe("closed");
802
809
  });
803
810
 
804
- it("returns false when already terminal (done)", () => {
805
- const r = makeRecord({ status: "done" });
806
- expect(tryTransition(r, "failed")).toBe(false);
807
- expect(r.status).toBe("done");
811
+ it("returns false when already terminal (closed)", () => {
812
+ const r = makeRecord({ status: "closed" });
813
+ expect(tryTransition(r, "closed")).toBe(false);
814
+ expect(r.status).toBe("closed");
808
815
  });
809
816
 
810
- it("returns false when already terminal (cancelled)", () => {
811
- const r = makeRecord({ status: "cancelled" });
812
- expect(tryTransition(r, "done")).toBe(false);
817
+ it("returns false when already terminal (closed, cancelled reason)", () => {
818
+ const r = makeRecord({ status: "closed", closedReason: "cancelled" });
819
+ expect(tryTransition(r, "closed")).toBe(false);
813
820
  });
814
821
 
815
- it("returns false when already terminal (failed)", () => {
816
- const r = makeRecord({ status: "failed" });
817
- expect(tryTransition(r, "done")).toBe(false);
822
+ it("returns false when already terminal (closed, gc reason)", () => {
823
+ const r = makeRecord({ status: "closed", closedReason: "gc" });
824
+ expect(tryTransition(r, "closed")).toBe(false);
818
825
  });
819
826
 
820
- it("first transition wins in concurrent race (running → done beats running → cancelled)", () => {
827
+ it("first transition wins in concurrent race (running → closed is one-way)", () => {
821
828
  const r = makeRecord({ status: "running" });
822
- expect(tryTransition(r, "done")).toBe(true);
823
- expect(tryTransition(r, "cancelled")).toBe(false);
824
- expect(r.status).toBe("done");
829
+ expect(tryTransition(r, "closed")).toBe(true);
830
+ expect(tryTransition(r, "closed")).toBe(false);
831
+ expect(r.status).toBe("closed");
825
832
  });
826
833
 
827
- it("returns false when trying to transition from crashed to done", () => {
828
- const r = makeRecord({ status: "crashed" });
829
- expect(tryTransition(r, "done")).toBe(false);
830
- expect(r.status).toBe("crashed");
834
+ it("running 入态时 resurrectClosed 防御性 no-op(终态回边仅限 closed)", () => {
835
+ const r = makeRecord({ status: "running" });
836
+ expect(resurrectClosed(r)).toBe(false);
837
+ expect(r.status).toBe("running");
831
838
  });
832
839
  });
833
840
 
834
841
  describe("markReconstructedStatus", () => {
835
842
  it("directly sets status without CAS check", () => {
836
843
  const r = makeRecord({ status: "running" });
837
- markReconstructedStatus(r, "crashed");
838
- expect(r.status).toBe("crashed");
844
+ markReconstructedStatus(r, "closed");
845
+ expect(r.status).toBe("closed");
839
846
  });
840
847
 
841
848
  it("can overwrite terminal status (bypass CAS)", () => {
842
849
  // 重建场景:旧 record 可能已有终态,重建时需要直接覆盖
843
- const r = makeRecord({ status: "done" });
844
- markReconstructedStatus(r, "crashed");
845
- expect(r.status).toBe("crashed");
850
+ const r = makeRecord({ status: "closed" });
851
+ markReconstructedStatus(r, "closed");
852
+ expect(r.status).toBe("closed");
846
853
  });
847
854
 
848
855
  it("can overwrite running status", () => {
849
856
  const r = makeRecord({ status: "running" });
850
- markReconstructedStatus(r, "failed");
851
- expect(r.status).toBe("failed");
857
+ markReconstructedStatus(r, "closed");
858
+ expect(r.status).toBe("closed");
852
859
  });
853
860
 
854
- it("can set crashed on running record", () => {
861
+ it("can set closed on running record", () => {
855
862
  const r = makeRecord({ status: "running" });
856
- markReconstructedStatus(r, "crashed");
857
- expect(r.status).toBe("crashed");
863
+ markReconstructedStatus(r, "closed");
864
+ expect(r.status).toBe("closed");
858
865
  });
859
866
 
860
- it("can set crashed on done record (reconstruction override)", () => {
861
- const r = makeRecord({ status: "done" });
862
- markReconstructedStatus(r, "crashed");
863
- expect(r.status).toBe("crashed");
867
+ it("can re-set closed on closed record (reconstruction override)", () => {
868
+ const r = makeRecord({ status: "closed" });
869
+ markReconstructedStatus(r, "closed");
870
+ expect(r.status).toBe("closed");
864
871
  });
865
872
  });
866
873
 
@@ -870,9 +877,9 @@ describe("markReconstructedStatus", () => {
870
877
  describe("completeRecord", () => {
871
878
  it("writes outcome fields without resetting turnCount/totalTokens", () => {
872
879
  const r = makeRecord({ turnCount: 5, totalTokens: 42 });
873
- r.status = "done";
874
- completeRecord(r, SAMPLE_RESULT, "done");
875
- expect(r.status).toBe("done");
880
+ r.status = "closed";
881
+ completeRecord(r, SAMPLE_RESULT, "closed");
882
+ expect(r.status).toBe("closed");
876
883
  expect(r.endedAt).toBeTypeOf("number");
877
884
  expect(r.agentResult).toBe(SAMPLE_RESULT);
878
885
  expect(r.result).toBe("done");
@@ -883,9 +890,9 @@ describe("completeRecord", () => {
883
890
 
884
891
  it("stores error from result", () => {
885
892
  const r = makeRecord();
886
- r.status = "failed";
893
+ r.status = "closed";
887
894
  const failedResult: AgentResult = { ...SAMPLE_RESULT, success: false, error: "oops" };
888
- completeRecord(r, failedResult, "failed");
895
+ completeRecord(r, failedResult, "closed");
889
896
  expect(r.error).toBe("oops");
890
897
  });
891
898
 
@@ -1018,7 +1025,7 @@ describe("projections", () => {
1018
1025
  });
1019
1026
 
1020
1027
  it("currentActivity is undefined when status is not running", () => {
1021
- const r = makeRecord({ status: "done" });
1028
+ const r = makeRecord({ status: "closed" });
1022
1029
  expect(project(r).currentActivity).toBeUndefined();
1023
1030
  });
1024
1031
 
@@ -1073,13 +1080,13 @@ describe("projections", () => {
1073
1080
 
1074
1081
  describe("snapshot", () => {
1075
1082
  it("returns a readonly snapshot with identity + status fields", () => {
1076
- const r = makeRecord({ turnCount: 2, status: "done", endedAt: 5000, result: "ok" });
1083
+ const r = makeRecord({ turnCount: 2, status: "closed", endedAt: 5000, result: "ok" });
1077
1084
  const s = snapshot(r);
1078
1085
  expect(s.id).toBe("test-1");
1079
1086
  expect(s.agent).toBe("worker");
1080
- expect(s.mode).toBe("sync");
1087
+ expect(s.mode).toBe("background");
1081
1088
  expect(s.task).toBe("test task");
1082
- expect(s.status).toBe("done");
1089
+ expect(s.status).toBe("closed");
1083
1090
  expect(s.turns).toBe(2);
1084
1091
  expect(s.endedAt).toBe(5000);
1085
1092
  expect(s.result).toBe("ok");
@@ -1184,7 +1191,7 @@ describe("computeElapsedSeconds", () => {
1184
1191
  describe("projectLiveProgress (T3.21)", () => {
1185
1192
  it("projects live progress snapshot from running record", () => {
1186
1193
  const record = makeRecord({
1187
- mode: "sync",
1194
+ mode: "background",
1188
1195
  task: "test task",
1189
1196
  startedAt: 1000,
1190
1197
  status: "running",
@@ -1209,7 +1216,7 @@ describe("projectLiveProgress (T3.21)", () => {
1209
1216
 
1210
1217
  it("projectLiveProgress returns lastError when set", () => {
1211
1218
  const record = makeRecord({
1212
- mode: "sync", task: "failing", startedAt: 0, status: "running",
1219
+ mode: "background", task: "failing", startedAt: 0, status: "running",
1213
1220
  lastError: "something went wrong",
1214
1221
  });
1215
1222
  const result = projectLiveProgress(record);
@@ -1227,7 +1234,7 @@ describe("tool_end running index [perf]", () => {
1227
1234
  updateFromEvent(record, { type: "tool_start", toolName: name, args });
1228
1235
 
1229
1236
  const end = (record: ExecutionRecord, name: string, result: string) =>
1230
- updateFromEvent(record, { type: "tool_end", toolName: name, result, isError: false });
1237
+ updateFromEvent(record, { type: "tool_end", toolName: name, result: { content: [result] }, isError: false });
1231
1238
 
1232
1239
  it("同名并发两个 toolCall:tool_end LIFO 配对,结果写回各自槽位", () => {
1233
1240
  const record = makeRecord();
@@ -1239,12 +1246,12 @@ describe("tool_end running index [perf]", () => {
1239
1246
  const calls = record.turns[0]!.toolCalls;
1240
1247
  expect(calls).toHaveLength(2);
1241
1248
  expect(calls[0]).toMatchObject({ args: { cmd: "first" }, _status: "running" });
1242
- expect(calls[1]).toMatchObject({ result: "result-for-second", _status: "done" });
1249
+ expect(calls[1]).toMatchObject({ result: { content: ["result-for-second"] }, _status: "done" });
1243
1250
 
1244
1251
  // 第二个 end 配对剩下的 first
1245
1252
  end(record, "bash", "result-for-first");
1246
- expect(calls[0]).toMatchObject({ result: "result-for-first", _status: "done" });
1247
- expect(calls[1]).toMatchObject({ result: "result-for-second", _status: "done" });
1253
+ expect(calls[0]).toMatchObject({ result: { content: ["result-for-first"] }, _status: "done" });
1254
+ expect(calls[1]).toMatchObject({ result: { content: ["result-for-second"] }, _status: "done" });
1248
1255
  });
1249
1256
 
1250
1257
  it("索引 miss(无 tool_start 的外部注入 tool_end)→ fallback 全扫后 push 幽灵条目", () => {
@@ -1252,7 +1259,7 @@ describe("tool_end running index [perf]", () => {
1252
1259
  end(record, "external_tool", "injected");
1253
1260
  const calls = record.turns[0]!.toolCalls;
1254
1261
  expect(calls).toHaveLength(1);
1255
- expect(calls[0]).toMatchObject({ toolName: "external_tool", result: "injected", _status: "done" });
1262
+ expect(calls[0]).toMatchObject({ toolName: "external_tool", result: { content: ["injected"] }, _status: "done" });
1256
1263
  });
1257
1264
 
1258
1265
  it("跨 turn 滞后 tool_end:索引跨 turn 命中(与旧全扫语义一致)", () => {
@@ -1263,8 +1270,8 @@ describe("tool_end running index [perf]", () => {
1263
1270
  end(record, "write", "w-done"); // 正常配对 turn 1
1264
1271
  end(record, "read", "r-done"); // 滞后 end 配对 turn 0(跨 turn 兜底)
1265
1272
 
1266
- expect(record.turns[0]!.toolCalls[0]).toMatchObject({ toolName: "read", result: "r-done", _status: "done" });
1267
- expect(record.turns[1]!.toolCalls[0]).toMatchObject({ toolName: "write", result: "w-done", _status: "done" });
1273
+ expect(record.turns[0]!.toolCalls[0]).toMatchObject({ toolName: "read", result: { content: ["r-done"] }, _status: "done" });
1274
+ expect(record.turns[1]!.toolCalls[0]).toMatchObject({ toolName: "write", result: { content: ["w-done"] }, _status: "done" });
1268
1275
  });
1269
1276
  });
1270
1277
 
@@ -1335,6 +1342,156 @@ describe("createRecord 引擎留痕字段(P4)", () => {
1335
1342
  });
1336
1343
  });
1337
1344
 
1345
+ // ============================================================
1346
+ // jsonlToAgentEvent — subprocess JSONL → AgentEvent 翻译
1347
+ // ============================================================
1348
+ describe("jsonlToAgentEvent(JSONL → AgentEvent 翻译)", () => {
1349
+ it("不映射类型(session/message_start/turn_start/tool_execution_update)→ 空数组", () => {
1350
+ expect(jsonlToAgentEvent({ type: "session" })).toEqual([]);
1351
+ expect(jsonlToAgentEvent({ type: "message_start" })).toEqual([]);
1352
+ expect(jsonlToAgentEvent({ type: "turn_start" })).toEqual([]);
1353
+ expect(jsonlToAgentEvent({ type: "tool_execution_update" })).toEqual([]);
1354
+ });
1355
+
1356
+ it("未知类型 → 空数组(落空语义)", () => {
1357
+ expect(jsonlToAgentEvent({ type: "something_new" })).toEqual([]);
1358
+ });
1359
+
1360
+ it("tool_execution_start → tool_start(toolName/args 透传)", () => {
1361
+ expect(jsonlToAgentEvent({ type: "tool_execution_start", toolName: "read", args: { path: "/x.ts" } })).toEqual([
1362
+ { type: "tool_start", toolName: "read", args: { path: "/x.ts" } },
1363
+ ]);
1364
+ });
1365
+
1366
+ it("tool_execution_start:toolName 非字符串归一空串", () => {
1367
+ expect(jsonlToAgentEvent({ type: "tool_execution_start", toolName: 42 })).toEqual([
1368
+ { type: "tool_start", toolName: "", args: undefined },
1369
+ ]);
1370
+ });
1371
+
1372
+ it("tool_execution_end → tool_end(isError === true 才成立,result 透传)", () => {
1373
+ const result = { content: [{ type: "text", text: "out" }] };
1374
+ expect(
1375
+ jsonlToAgentEvent({ type: "tool_execution_end", toolName: "bash", args: { command: "ls" }, result, isError: true }),
1376
+ ).toEqual([
1377
+ { type: "tool_end", toolName: "bash", args: { command: "ls" }, result, isError: true },
1378
+ ]);
1379
+ // isError 非 true(字符串 "yes" / 缺失)→ false
1380
+ expect(
1381
+ jsonlToAgentEvent({ type: "tool_execution_end", toolName: "bash", isError: "yes" })[0],
1382
+ ).toMatchObject({ isError: false });
1383
+ expect(
1384
+ jsonlToAgentEvent({ type: "tool_execution_end", toolName: "bash" })[0],
1385
+ ).toMatchObject({ isError: false });
1386
+ });
1387
+
1388
+ it("message_update:thinking_delta(delta 字符串透传 / 非字符串归一空串)", () => {
1389
+ expect(
1390
+ jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { type: "thinking_delta", delta: "hmm" } }),
1391
+ ).toEqual([{ type: "thinking_delta", delta: "hmm" }]);
1392
+ expect(
1393
+ jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { type: "thinking_delta", delta: 42 } }),
1394
+ ).toEqual([{ type: "thinking_delta", delta: "" }]);
1395
+ });
1396
+
1397
+ it("message_update:text_delta(delta 非字符串 String() 归一)", () => {
1398
+ expect(
1399
+ jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { delta: "txt" } }),
1400
+ ).toEqual([{ type: "text_delta", delta: "txt" }]);
1401
+ expect(
1402
+ jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { delta: 42 } }),
1403
+ ).toEqual([{ type: "text_delta", delta: "42" }]);
1404
+ });
1405
+
1406
+ it("message_update:ame 缺失 / delta 缺失 → 不产出", () => {
1407
+ expect(jsonlToAgentEvent({ type: "message_update" })).toEqual([]);
1408
+ expect(jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: undefined })).toEqual([]);
1409
+ expect(jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { type: "other" } })).toEqual([]);
1410
+ });
1411
+
1412
+ it("turn_end → [{type:'turn_end'}]", () => {
1413
+ expect(jsonlToAgentEvent({ type: "turn_end" })).toEqual([{ type: "turn_end" }]);
1414
+ });
1415
+
1416
+ it("message_end:usage 拍平 + cost.total 提取 + stopReason=error 额外产 error 事件(双事件)", () => {
1417
+ const events = jsonlToAgentEvent({
1418
+ type: "message_end",
1419
+ message: {
1420
+ usage: { input: 10, output: 20, cacheRead: 5, cacheWrite: 3, cost: { total: 0.5 } },
1421
+ stopReason: "error",
1422
+ errorMessage: "boom",
1423
+ },
1424
+ });
1425
+ expect(events).toEqual([
1426
+ { type: "message_end", usage: { input: 10, output: 20, cacheRead: 5, cacheWrite: 3, cost: 0.5 } },
1427
+ { type: "error", message: "boom" },
1428
+ ]);
1429
+ });
1430
+
1431
+ it("message_end:stopReason=aborted 无 errorMessage → raw.reason fallback,再兜底 String(stopReason)", () => {
1432
+ expect(
1433
+ jsonlToAgentEvent({ type: "message_end", message: { stopReason: "aborted" }, reason: "user aborted" }),
1434
+ ).toEqual([
1435
+ { type: "error", message: "user aborted" },
1436
+ ]);
1437
+ expect(
1438
+ jsonlToAgentEvent({ type: "message_end", message: { stopReason: "aborted" } }),
1439
+ ).toEqual([
1440
+ { type: "error", message: "aborted" },
1441
+ ]);
1442
+ });
1443
+
1444
+ it("message_end:usage 缺 cost → cost undefined;stopReason=stop 不产 error 事件", () => {
1445
+ const events = jsonlToAgentEvent({
1446
+ type: "message_end",
1447
+ message: { usage: { input: 1, output: 1 }, stopReason: "stop" },
1448
+ });
1449
+ expect(events).toEqual([
1450
+ { type: "message_end", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, cost: undefined } },
1451
+ ]);
1452
+ });
1453
+
1454
+ it("message_end:message 缺失 / stopReason 正常 → 空数组或仅 usage", () => {
1455
+ expect(jsonlToAgentEvent({ type: "message_end" })).toEqual([]);
1456
+ expect(jsonlToAgentEvent({ type: "message_end", message: {} })).toEqual([]);
1457
+ });
1458
+
1459
+ it("compaction_start → [{type:'compaction'}]", () => {
1460
+ expect(jsonlToAgentEvent({ type: "compaction_start" })).toEqual([{ type: "compaction" }]);
1461
+ });
1462
+
1463
+ it("翻译产物喂 updateFromEvent 与 live 事件同构(text/tool/turn 收口进 turns[])", () => {
1464
+ const r = makeRecord();
1465
+ for (const event of [
1466
+ ...jsonlToAgentEvent({ type: "tool_execution_start", toolName: "read", args: { path: "/a.ts" } }),
1467
+ ...jsonlToAgentEvent({ type: "message_update", assistantMessageEvent: { delta: "answer" } }),
1468
+ ...jsonlToAgentEvent({ type: "tool_execution_end", toolName: "read", args: { path: "/a.ts" }, result: { content: [] }, isError: false }),
1469
+ ...jsonlToAgentEvent({ type: "message_end", message: { usage: { input: 7, output: 3, cacheRead: 0, cacheWrite: 0, cost: { total: 0.1 } } } }),
1470
+ ...jsonlToAgentEvent({ type: "turn_end" }),
1471
+ ]) {
1472
+ updateFromEvent(r, event);
1473
+ }
1474
+ expect(r.turns[0]?.text).toBe("answer");
1475
+ expect(r.turns[0]?.toolCalls[0]).toMatchObject({ toolName: "read", _status: "done" });
1476
+ expect(r.turns[0]?.usageDelta).toEqual({ input: 7, output: 3, cacheRead: 0, cacheWrite: 0, cost: 0.1 });
1477
+ expect(r.totalTokens).toBe(10);
1478
+ expect(r.turnCount).toBe(1);
1479
+ });
1480
+ });
1481
+
1482
+ // ============================================================
1483
+ // addUsage 分支语义(经 message_end 累积路径锁定)
1484
+ // ============================================================
1485
+ describe("addUsage 分支语义(message_end 累积路径)", () => {
1486
+ it("首条 usage 缺 cost → cost 保留 undefined;累加分支缺 cost → 归 0(number)", () => {
1487
+ const r = makeRecord();
1488
+ updateFromEvent(r, { type: "message_end", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0 } });
1489
+ expect(r.turns[0]!.usageDelta?.cost).toBeUndefined();
1490
+ updateFromEvent(r, { type: "message_end", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0 } });
1491
+ expect(r.turns[0]!.usageDelta?.cost).toBe(0);
1492
+ });
1493
+ });
1494
+
1338
1495
  // ============================================================
1339
1496
  // U1 engine 三字段 entry 往返(engineHandle 贯通)
1340
1497
  // ============================================================
@@ -70,7 +70,7 @@ describe("execution 运行时面(U10① D6)", () => {
70
70
  });
71
71
 
72
72
  afterEach(() => {
73
- fs.rmSync(agentDir, { recursive: true, force: true });
73
+ fs.rmSync(agentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
74
74
  });
75
75
 
76
76
  // ============================================================
@@ -88,7 +88,7 @@ describe("execution 运行时面(U10① D6)", () => {
88
88
 
89
89
  // 构造产物可用(实例方法存在)且未被登记进全局单例槽位——
90
90
  // session_start 单例流程行为零改动,宿主自持实例。
91
- expect(typeof service.lookupRecordAnyState).toBe("function");
91
+ expect(typeof service["lookupRecordAnyState"]).toBe("function");
92
92
  expect(getSubagentService()).toBeNull();
93
93
  });
94
94
 
@@ -99,7 +99,7 @@ describe("execution 运行时面(U10① D6)", () => {
99
99
  });
100
100
 
101
101
  // lookupRecordAnyState 契约:未初始化/disposed 时 assertReady 抛错 → 按「不存在」处理返回 undefined
102
- expect(service.lookupRecordAnyState("no-such-record")).toBeUndefined();
102
+ expect(service["lookupRecordAnyState"]("no-such-record")).toBeUndefined();
103
103
  });
104
104
 
105
105
  it("initSession(宿主注入最小 pi mock)后查询面同型可用", () => {
@@ -109,7 +109,7 @@ describe("execution 运行时面(U10① D6)", () => {
109
109
  });
110
110
  service.initSession({ pi: makePi(), sessionId: "s1" });
111
111
 
112
- expect(service.lookupRecordAnyState("no-such-record")).toBeUndefined();
112
+ expect(service["lookupRecordAnyState"]("no-such-record")).toBeUndefined();
113
113
  service.dispose();
114
114
  });
115
115
  });
@@ -265,7 +265,7 @@ describe("execution 运行时面(U10① D6)", () => {
265
265
  const service = subagentCore.createSubagentService({ cwd: agentDir, modelService });
266
266
 
267
267
  // 构造产物可用(实例方法存在),且不写进程单例槽位(第三宿主自持实例)
268
- expect(typeof service.lookupRecordAnyState).toBe("function");
268
+ expect(typeof service["lookupRecordAnyState"]).toBe("function");
269
269
  expect(subagentCore.getModelConfigService()).toBeNull();
270
270
  });
271
271
  });
@@ -33,14 +33,14 @@ vi.mock("node:child_process", async () => {
33
33
  });
34
34
 
35
35
  // buildSpawnArgs 包装为 spy(保留真实实现)——「显式 ref 拒单不触达 spawn 参数组装」的承重断言。
36
- vi.mock("../session-runner.ts", async (importOriginal) => {
37
- const actual = await importOriginal<typeof import("../session-runner.ts")>();
36
+ vi.mock("../engine/engines/pi/session-runner.ts", async (importOriginal) => {
37
+ const actual = await importOriginal<typeof import("../engine/engines/pi/session-runner.ts")>();
38
38
  return { ...actual, buildSpawnArgs: vi.fn(actual.buildSpawnArgs) };
39
39
  });
40
40
 
41
41
  import { ModelConfigService } from "../model-config-service.ts";
42
42
  import type { ModelInfo, ModelRegistryLike } from "../model-resolver.ts";
43
- import { buildSpawnArgs } from "../session-runner.ts";
43
+ import { buildSpawnArgs } from "../engine/engines/pi/session-runner.ts";
44
44
  import type { PiLike } from "../subagent-service.ts";
45
45
  import { SubagentService } from "../subagent-service.ts";
46
46
 
@@ -95,7 +95,7 @@ describe("显式 agent ref 失败报错(非静默降级 general-purpose)", (
95
95
 
96
96
  afterEach(() => {
97
97
  vi.restoreAllMocks();
98
- fs.rmSync(tmpDir, { recursive: true, force: true });
98
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
99
99
  });
100
100
 
101
101
  // ── 拒绝路径:显式 ref 失败 → 同步 reject + spawn 链路零触达 ──