@zhushanwen/pi-subagent-workflow 8.6.0 → 8.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/package.json +9 -13
  2. package/relay/relay.mjs +1 -1
  3. package/src/host/__tests__/pi-host.test.ts +214 -0
  4. package/src/host/pi-host.ts +109 -0
  5. package/src/index.ts +89 -32
  6. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  7. package/src/injectors/__tests__/engine-section-stability.test.ts +341 -0
  8. package/src/injectors/__tests__/subagent-list-injector.test.ts +5 -5
  9. package/src/injectors/__tests__/workflow-list-injector.test.ts +5 -5
  10. package/src/injectors/engine-awareness.ts +123 -0
  11. package/src/injectors/model-list-injector.ts +1 -1
  12. package/src/injectors/subagent-list-injector.ts +8 -8
  13. package/src/injectors/workflow-list-injector.ts +8 -8
  14. package/src/interface/__tests__/detectors.test.ts +3 -3
  15. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  16. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  17. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  18. package/src/interface/bg-notify-render.ts +4 -4
  19. package/src/interface/commands.ts +3 -3
  20. package/src/interface/format.ts +2 -2
  21. package/src/interface/helpers.ts +1 -1
  22. package/src/interface/list-component.ts +4 -4
  23. package/src/interface/list-shared.ts +2 -2
  24. package/src/interface/list-view.ts +2 -2
  25. package/src/interface/subagent-actions.ts +263 -11
  26. package/src/interface/subagent-tool-schema.ts +20 -13
  27. package/src/interface/subagent-tool.ts +11 -6
  28. package/src/interface/subagents.ts +3 -3
  29. package/src/interface/tool-render.ts +34 -2
  30. package/src/interface/tool-workflow-script.ts +4 -4
  31. package/src/interface/tool-workflow.ts +6 -6
  32. package/src/interface/views/WorkflowsView.ts +5 -5
  33. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  34. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  35. package/src/interface/views/detail-content.ts +4 -4
  36. package/src/interface/views/format.ts +4 -4
  37. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +11 -11
  38. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  39. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  40. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  41. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  42. package/src/execution/__tests__/alive-store.test.ts +0 -147
  43. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  44. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  45. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  46. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  47. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  48. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  49. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  50. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  51. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  52. package/src/execution/__tests__/config.test.ts +0 -110
  53. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  54. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  55. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  56. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  57. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  59. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  60. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  61. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  63. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  64. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  65. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  66. package/src/execution/__tests__/format.test.ts +0 -458
  67. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  68. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  69. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  70. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  71. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  72. package/src/execution/__tests__/host-mode.test.ts +0 -87
  73. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  74. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  77. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  78. package/src/execution/__tests__/list-component.test.ts +0 -401
  79. package/src/execution/__tests__/list-fields.test.ts +0 -140
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  82. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  83. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  84. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  87. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  88. package/src/execution/__tests__/output-collector.test.ts +0 -358
  89. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  90. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  91. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  92. package/src/execution/__tests__/record-store.test.ts +0 -1057
  93. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  94. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  95. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  96. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  97. package/src/execution/__tests__/relay-env.test.ts +0 -42
  98. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  99. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  100. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  101. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  102. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  103. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  104. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  105. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  106. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  107. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  108. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  109. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  110. package/src/execution/__tests__/session-pending.test.ts +0 -197
  111. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  112. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  113. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  114. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  115. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  116. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  117. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  118. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  119. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  120. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  121. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  122. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  123. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  124. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  125. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  126. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  127. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  128. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  130. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  131. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  132. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  133. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  134. package/src/execution/__tests__/tool-action.test.ts +0 -476
  135. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  137. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  138. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  139. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  140. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  141. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  142. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  143. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  144. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  145. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  146. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  147. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  148. package/src/execution/agent-registry.ts +0 -199
  149. package/src/execution/agent-result-mapper.ts +0 -90
  150. package/src/execution/alive-store.ts +0 -92
  151. package/src/execution/argv-mirror.ts +0 -113
  152. package/src/execution/best-effort.ts +0 -38
  153. package/src/execution/channel-registry-access.ts +0 -144
  154. package/src/execution/concurrency-pool.ts +0 -116
  155. package/src/execution/config.ts +0 -96
  156. package/src/execution/dialog-queue.ts +0 -330
  157. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  158. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  159. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  160. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  161. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  162. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  163. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  164. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  165. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  166. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  167. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  168. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  169. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  170. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  171. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  172. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  173. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  174. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  175. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  176. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  177. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  178. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  179. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  180. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  181. package/src/execution/engine/common/data-dir.ts +0 -62
  182. package/src/execution/engine/common/errors.ts +0 -183
  183. package/src/execution/engine/common/event-journal.ts +0 -254
  184. package/src/execution/engine/common/journal-replay.ts +0 -62
  185. package/src/execution/engine/common/kill-chain.ts +0 -221
  186. package/src/execution/engine/common/nesting-guard.ts +0 -50
  187. package/src/execution/engine/common/persona-router.ts +0 -108
  188. package/src/execution/engine/common/pool-manager.ts +0 -226
  189. package/src/execution/engine/common/schema-emulation.ts +0 -189
  190. package/src/execution/engine/common/session-view-projection.ts +0 -51
  191. package/src/execution/engine/engine-discovery.ts +0 -65
  192. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  193. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  194. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  195. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  196. package/src/execution/engine/engines/pi/reader.ts +0 -48
  197. package/src/execution/engine/engines/pi/registration.ts +0 -35
  198. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  199. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  200. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  201. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  202. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  203. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  204. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  207. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  208. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  209. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  210. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  211. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  212. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  213. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  214. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  215. package/src/execution/engine/host-task-spec.ts +0 -47
  216. package/src/execution/engine/model-prompt.ts +0 -59
  217. package/src/execution/engine/paths.ts +0 -42
  218. package/src/execution/engine/port.ts +0 -153
  219. package/src/execution/engine/registry.ts +0 -123
  220. package/src/execution/engine/routing.ts +0 -218
  221. package/src/execution/engine/types.ts +0 -309
  222. package/src/execution/execute-options-mapper.ts +0 -112
  223. package/src/execution/execution-record.ts +0 -965
  224. package/src/execution/finalize-record.ts +0 -251
  225. package/src/execution/finalized-marker.ts +0 -51
  226. package/src/execution/get-state-handshake.ts +0 -104
  227. package/src/execution/host-mode.ts +0 -56
  228. package/src/execution/idle-gc.ts +0 -47
  229. package/src/execution/lifecycle-manager.ts +0 -513
  230. package/src/execution/lifecycle-predicates.ts +0 -65
  231. package/src/execution/manifest-store.ts +0 -256
  232. package/src/execution/model-config-service.ts +0 -219
  233. package/src/execution/model-resolver.ts +0 -248
  234. package/src/execution/notifier.ts +0 -330
  235. package/src/execution/notify-ledger.ts +0 -580
  236. package/src/execution/output-collector.ts +0 -228
  237. package/src/execution/path-encoding.ts +0 -60
  238. package/src/execution/pi-invocation.ts +0 -120
  239. package/src/execution/record-entry.ts +0 -132
  240. package/src/execution/record-store.ts +0 -1234
  241. package/src/execution/relay-env.ts +0 -37
  242. package/src/execution/session-context-resolver.ts +0 -64
  243. package/src/execution/session-file-gc.ts +0 -120
  244. package/src/execution/session-pending.ts +0 -164
  245. package/src/execution/session-reconstructor.ts +0 -678
  246. package/src/execution/session-runner.ts +0 -1781
  247. package/src/execution/sessions-index.ts +0 -304
  248. package/src/execution/spawn-event-adapter.ts +0 -363
  249. package/src/execution/stdin-writer.ts +0 -198
  250. package/src/execution/stream-sink.ts +0 -126
  251. package/src/execution/subagent-service.ts +0 -2141
  252. package/src/execution/subprocess-agent-runner.ts +0 -317
  253. package/src/execution/temp-prompt.ts +0 -62
  254. package/src/execution/tombstone-store.ts +0 -72
  255. package/src/execution/turn-limiter.ts +0 -102
  256. package/src/execution/types.ts +0 -973
  257. package/src/execution/ui-channels.ts +0 -216
  258. package/src/execution/ui-interaction-model.ts +0 -48
  259. package/src/execution/ui-request-handler-factory.ts +0 -212
  260. package/src/execution/ui-request-observability.ts +0 -81
  261. package/src/execution/ui-request-queue.ts +0 -184
  262. package/src/execution/worktree-manager.ts +0 -688
  263. package/src/execution/worktree-registry.ts +0 -222
  264. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  265. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  266. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  267. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  268. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  269. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  270. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  271. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  272. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  273. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  274. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  275. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  276. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  277. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  278. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  279. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  280. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  281. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  282. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  283. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  284. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  285. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  286. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  287. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  288. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  289. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  290. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  291. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  292. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  293. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  294. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  295. package/src/orchestration/agent-opts-resolver.ts +0 -174
  296. package/src/orchestration/args-validator.ts +0 -127
  297. package/src/orchestration/config-loader.ts +0 -315
  298. package/src/orchestration/error-recovery.ts +0 -1018
  299. package/src/orchestration/execute-agent-call.ts +0 -256
  300. package/src/orchestration/launcher.ts +0 -455
  301. package/src/orchestration/lifecycle.ts +0 -399
  302. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  303. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  304. package/src/orchestration/models/agent-call.ts +0 -83
  305. package/src/orchestration/models/budget.ts +0 -118
  306. package/src/orchestration/models/ports.ts +0 -164
  307. package/src/orchestration/models/run-runtime.ts +0 -104
  308. package/src/orchestration/models/run-spec.ts +0 -83
  309. package/src/orchestration/models/run-state.ts +0 -44
  310. package/src/orchestration/models/trace.ts +0 -183
  311. package/src/orchestration/models/types.ts +0 -301
  312. package/src/orchestration/models/workflow-run.ts +0 -254
  313. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  314. package/src/orchestration/models/workflow-script.ts +0 -117
  315. package/src/orchestration/script-lint.ts +0 -766
  316. package/src/orchestration/skill-discovery.ts +0 -115
  317. package/src/orchestration/worker-handle.ts +0 -115
  318. package/src/orchestration/worker-host.ts +0 -98
  319. package/src/orchestration/worker-script-builder.ts +0 -421
  320. package/src/orchestration/workflow-files.ts +0 -85
  321. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  322. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  323. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  324. package/src/shared/__tests__/model-ref.test.ts +0 -306
  325. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  326. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  327. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  328. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  329. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  330. package/src/shared/agent-event.ts +0 -13
  331. package/src/shared/agent-ref.ts +0 -57
  332. package/src/shared/meta-parser.ts +0 -261
  333. package/src/shared/model-ref.ts +0 -286
  334. package/src/shared/resource-discovery.ts +0 -811
  335. package/src/shared/resource-meta.ts +0 -65
  336. package/src/shared/schema-env.ts +0 -44
  337. package/src/shared/schema-jsonify.ts +0 -58
  338. package/src/shared/timer-delay.ts +0 -54
  339. package/src/shared/xml-injection.ts +0 -35
  340. package/workflows/README.md +0 -81
  341. package/workflows/_shared/agent-refs.cjs +0 -40
  342. package/workflows/chain.js +0 -131
  343. package/workflows/map-reduce.js +0 -174
  344. package/workflows/parallel.js +0 -148
  345. package/workflows/review-fix-loop-utils.cjs +0 -1309
  346. package/workflows/review-fix-loop.js +0 -1404
  347. package/workflows/scatter-gather.js +0 -178
@@ -1,267 +0,0 @@
1
- // src/execution/__tests__/run-and-finalize-chatmode.test.ts
2
- //
3
- // runAndFinalize 的 chatMode idle 分流测试(M2-A)。
4
- //
5
- // mock session-runner.runSpawn(受控返回 success/failed result),走 SubagentService
6
- // 真实的 runAndFinalize 分流逻辑,验证:
7
- // - chatMode + done → doFinalizeRoundToIdle:record.status=idle、留内存、round+1
8
- // - chatMode + failed → MF-6:回退 idle(可恢复),不销毁(agent 可重试 message 或 close)
9
- // - 非 chatMode + done → doFinalizeRecord:record.status=done、archived(现有行为不变)
10
- //
11
- // 分流效果通过「最终可观察状态」验证(record.status + store.getMutable 是否在内存),
12
- // 不依赖 spy 私有方法调用,更稳健。
13
-
14
- import * as fs from "node:fs";
15
- import * as os from "node:os";
16
- import * as path from "node:path";
17
-
18
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
19
-
20
- // mock logger(doFinalizeRecord 的 manifest 写入降级路径用 logger.error)
21
- const { loggerMock } = vi.hoisted(() => ({
22
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn(), info: vi.fn() },
23
- }));
24
- vi.mock("@zhushanwen/pi-extension-logger", () => ({ getLogger: () => loggerMock }));
25
-
26
- // mock session-runner:runSpawn 受控返回 result,killAllSpawnedChildren 空实现。
27
- // 注意:必须在 import SubagentService 之前 mock(vi.mock 提升到顶部)。
28
- vi.mock("../session-runner.ts", () => ({
29
- runSpawn: vi.fn(),
30
- killAllSpawnedChildren: vi.fn(),
31
- }));
32
-
33
- import { runSpawn } from "../session-runner.ts";
34
- import type { SessionRunnerContext } from "../session-runner.ts";
35
- import { createRecord } from "../execution-record.ts";
36
- import { ModelConfigService } from "../model-config-service.ts";
37
- import type { ModelInfo } from "../model-resolver.ts";
38
- import { RecordStore, type StatusFilter } from "../record-store.ts";
39
- import { SubagentService } from "../subagent-service.ts";
40
- import type { PiLike } from "../subagent-service.ts";
41
- import type {
42
- AgentResult,
43
- ExecutionRecord,
44
- ExecuteOptions,
45
- } from "../types.ts";
46
-
47
- const mockRunSpawn = vi.mocked(runSpawn);
48
-
49
- // ── 最小合法 ModelInfo(resolveModel 未注入 registry 会抛错,故 stub;runSpawn 被 mock 不消费)──
50
- const STUB_MODEL: ModelInfo = {
51
- id: "test-model",
52
- name: "Test",
53
- provider: "test",
54
- reasoning: false,
55
- };
56
-
57
- function makeTmpAgentDir(): string {
58
- return fs.mkdtempSync(path.join(os.tmpdir(), "chatmode-test-"));
59
- }
60
-
61
- function makePi(): PiLike & {
62
- appendEntry: ReturnType<typeof vi.fn>;
63
- events: { emit: ReturnType<typeof vi.fn> };
64
- sendMessage: ReturnType<typeof vi.fn>;
65
- } {
66
- return { appendEntry: vi.fn(), events: { emit: vi.fn() }, sendMessage: vi.fn() };
67
- }
68
-
69
- function makeResult(success: boolean): AgentResult {
70
- return {
71
- text: success ? "done" : "err",
72
- turns: 1,
73
- durationMs: 100,
74
- success,
75
- error: success ? undefined : "boom",
76
- sessionId: "sess-1",
77
- toolCalls: [],
78
- };
79
- }
80
-
81
- function makeRecord(chatMode: boolean, id = "sa-test"): ExecutionRecord {
82
- return createRecord(id, {
83
- agent: "general-purpose",
84
- model: "test-model",
85
- mode: "background",
86
- task: "do something",
87
- slug: "test",
88
- startedAt: 1000,
89
- rootSessionId: "root-session",
90
- chatMode,
91
- });
92
- }
93
-
94
- /** 暴露 runAndFinalize + store 的私有访问接口(测试专用 cast)。 */
95
- interface ServiceInternals {
96
- store: RecordStore;
97
- runAndFinalize: (
98
- record: ExecutionRecord,
99
- opts: ExecuteOptions,
100
- ctx: SessionRunnerContext,
101
- identity: {
102
- agent: string;
103
- agentConfig: unknown;
104
- resolved: { model: ModelInfo; thinkingLevel: string | undefined };
105
- },
106
- signal: undefined,
107
- priority: number,
108
- ) => Promise<AgentResult>;
109
- }
110
-
111
- describe("runAndFinalize chatMode idle 分流 (M2-A)", () => {
112
- let agentDir: string;
113
- let modelService: ModelConfigService;
114
- let service: SubagentService;
115
- let internals: ServiceInternals;
116
-
117
- beforeEach(() => {
118
- agentDir = makeTmpAgentDir();
119
- modelService = new ModelConfigService({ agentDir });
120
- service = new SubagentService({ cwd: agentDir, modelService });
121
- service.initSession({ pi: makePi(), sessionId: "root-session" });
122
- internals = service as unknown as ServiceInternals;
123
- mockRunSpawn.mockReset();
124
- });
125
-
126
- afterEach(() => {
127
- service.dispose();
128
- fs.rmSync(agentDir, { recursive: true, force: true });
129
- });
130
-
131
- /** 直接调私有 runAndFinalize(mock runSpawn 后走完整分流逻辑)。 */
132
- async function callRunAndFinalize(record: ExecutionRecord, success: boolean): Promise<void> {
133
- mockRunSpawn.mockResolvedValueOnce(makeResult(success));
134
- const opts: ExecuteOptions = { task: "do something", slug: "test" };
135
- const ctx: SessionRunnerContext = {
136
- cwd: agentDir,
137
- agentDir,
138
- skillDirs: [],
139
- mainCwd: agentDir,
140
- };
141
- const identity = {
142
- agent: "general-purpose",
143
- agentConfig: undefined,
144
- resolved: { model: STUB_MODEL, thinkingLevel: undefined },
145
- };
146
- await internals.runAndFinalize(record, opts, ctx, identity, undefined, 0);
147
- }
148
-
149
- it("chatMode + done → record running(旧 idle 折入),留内存,round 0→1", async () => {
150
- const record = makeRecord(true);
151
- internals.store.register(record);
152
- await callRunAndFinalize(record, true);
153
-
154
- expect(record.status).toBe("running");
155
- expect(record.round).toBe(1);
156
- // record 留内存(未 archive)——idle 分流核心断言(v4 B-1:idle 折入 running)
157
- expect(internals.store.getMutable(record.id)).toBe(record);
158
- });
159
-
160
- it("chatMode + failed → MF-6:回退 running(可恢复),不销毁对话(agent 可重试 message 或 close)", async () => {
161
- const record = makeRecord(true);
162
- internals.store.register(record);
163
- await callRunAndFinalize(record, false);
164
-
165
- // MF-6:chatMode 失败不终态销毁——record 回退 running(留内存),agent 可重试 message 或 close。
166
- expect(record.status).toBe("running");
167
- expect(internals.store.getMutable(record.id)).toBe(record); // 留内存(未 archive)
168
- // record.result 被 finalizeRoundToIdle 设值(MF-2:否则 notifier idle 恒 (empty))。
169
- // makeResult(false) 返回 text:"err" + error:"boom";text 非空 → record.result="err"。
170
- expect(record.result).toBeTruthy();
171
- });
172
-
173
- it("非 chatMode + done → record running(SP-5: 一次性完成后保持活跃,等待 message 触发升级)", async () => {
174
- const record = makeRecord(false);
175
- internals.store.register(record);
176
- await callRunAndFinalize(record, true);
177
-
178
- // SP-5: one-shot 完成后 record 保持 running(旧 idle,非终态归档),用户可通过 message 续聊。
179
- expect(record.status).toBe("running");
180
- expect(internals.store.getMutable(record.id)).toBe(record); // 留内存
181
- });
182
-
183
- it("chatMode 第二轮 done → round 累加(1→2,续聊场景)", async () => {
184
- // 模拟 resume 续聊:第一轮已完成(round=1,旧 idle 折入 running),第二轮 runAndFinalize 再次 done
185
- const record = makeRecord(true);
186
- record.status = "running"; // 第一轮已完成(v4 B-1:旧 idle 折入 running)
187
- record.round = 1;
188
- internals.store.register(record);
189
- await callRunAndFinalize(record, true);
190
-
191
- // 续聊第二轮 done:tryTransition(running→closed) 成功 → chatMode 分流 → finalizeRoundToIdle
192
- // → status 回到 running、round 1→2(record 保持活跃,等待下一轮续聊)。
193
- expect(record.status).toBe("running");
194
- expect(record.round).toBe(2);
195
- expect(mockRunSpawn).toHaveBeenCalled();
196
- });
197
-
198
- it("chatMode + done + closeAfterRound=true → finalizeRecord(done)(不进 idle,M2-B3)", async () => {
199
- // close 优雅关闭(force:false):running 时置 closeAfterRound=true,
200
- // runAndFinalize done 分流终态化为 done(而非进 idle)。
201
- const record = makeRecord(true);
202
- record.status = "running";
203
- record.closeAfterRound = true;
204
- internals.store.register(record);
205
- await callRunAndFinalize(record, true);
206
-
207
- expect(record.status).toBe("closed");
208
- expect(record.closeAfterRound).toBeUndefined(); // 清标志
209
- // 终态化 → archive → 内存无(与 idle 分流「留内存」对比)
210
- expect(internals.store.getMutable(record.id)).toBeUndefined();
211
- });
212
-
213
- it("chatMode + done + 无 closeAfterRound → 进 running(旧 idle 折入,M2-A 行为不变)", async () => {
214
- const record = makeRecord(true);
215
- record.status = "running";
216
- internals.store.register(record);
217
- await callRunAndFinalize(record, true);
218
-
219
- expect(record.status).toBe("running");
220
- expect(record.round).toBe(1);
221
- expect(internals.store.getMutable(record.id)).toBe(record);
222
- });
223
-
224
- it("[M5] 非 chatMode(one-shot)+ done + closeAfterRound=true → 轮完成时消费标志终态化(不进 running-resumable)", async () => {
225
- // one-shot busy 时 close(force:false) 置 closeAfterRound——旧代码非 chatMode 成功分支走
226
- // finalizeRoundToIdle 不消费,tool 返回 {closed:true} 谎报:record 永久 running-resumable、
227
- // 5min idle timer 杀进程、期间还能继续收 message。修复后在本分支消费终态化。
228
- const record = makeRecord(false);
229
- record.status = "running";
230
- record.closeAfterRound = true;
231
- internals.store.register(record);
232
- await callRunAndFinalize(record, true);
233
-
234
- expect(record.status).toBe("closed");
235
- expect(record.closedReason).toBe("user-close");
236
- expect(record.closeAfterRound).toBeUndefined(); // 标志已消费
237
- expect(internals.store.getMutable(record.id)).toBeUndefined(); // archived
238
- });
239
-
240
- it("[M5] chatMode + failed + closeAfterRound=true → 轮完成时消费标志终态化(不回退 resumable)", async () => {
241
- // 失败轮也视为「轮已完成」:close 意图兑现终态化(closedReason=gc),否则标志残留、
242
- // record 被 tool 谎报 closed 后仍可继续收 message。
243
- const record = makeRecord(true);
244
- record.status = "running";
245
- record.closeAfterRound = true;
246
- internals.store.register(record);
247
- await callRunAndFinalize(record, false); // 失败轮
248
-
249
- expect(record.status).toBe("closed");
250
- expect(record.closedReason).toBe("gc"); // !success → gc
251
- expect(record.closeAfterRound).toBeUndefined();
252
- expect(internals.store.getMutable(record.id)).toBeUndefined();
253
- });
254
-
255
- it("[S10] chatMode + failed(无 closeAfterRound)→ 回退 running 后 closedReason 不残留", async () => {
256
- // tryTransition 先设 closed+gc,finalizeRoundToIdle 回退 running——旧代码 closedReason="gc"
257
- // 残留在 running record 上(泄漏进 notify 载荷与 list 投影)。
258
- const record = makeRecord(true);
259
- record.status = "running";
260
- internals.store.register(record);
261
- await callRunAndFinalize(record, false);
262
-
263
- expect(record.status).toBe("running"); // MF-6 回退 resumable
264
- expect(record.closedReason).toBeUndefined(); // [S10] 不残留
265
- expect(internals.store.getMutable(record.id)).toBe(record);
266
- });
267
- });
@@ -1,253 +0,0 @@
1
- // src/execution/__tests__/run-spawn-chatmode-settled.test.ts
2
- //
3
- // [V2 模块 3] chatMode agent_settled 信号换挂单测(Step 3)。
4
- //
5
- // 验证 session-runner 的 V2 改动(5 处):
6
- // ① chatMode record agent_end 不触发 SIGTERM(进程保活,等 agent_settled)
7
- // ② chatMode record agent_settled 触发 armIdleTimer(fake timer + 超时后 kill)
8
- // ③ chatMode agent_settled 调 ctx.onRoundSettled(挂载点,mock 断言被调)
9
- // ④ 非 chatMode agent_settled 不 armIdleTimer、不调 onRoundSettled
10
- //
11
- // mock 结构与 run-spawn-edges.test.ts 一致(FakeChild + session-pending 受控 count=0)。
12
- // lifecycle-manager 用真实模块(hasIdleTimer / _resetLifecycleState 可观测 + 隔离)。
13
-
14
- import { spawn } from "node:child_process";
15
- import * as fs from "node:fs";
16
-
17
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
18
-
19
- vi.mock("node:child_process", async () => {
20
- const { FakeChild } = await import("./helpers/spawn-mock.ts");
21
- return {
22
- spawn: vi.fn(() => new FakeChild()),
23
- // buildEnvBlock 的 git branch 调用(execFile 异步):默认 err-first 兜底 → catch → branch=""
24
- execFile: vi.fn(
25
- (
26
- _cmd: string,
27
- _args: readonly string[],
28
- _opts: unknown,
29
- cb: (err: Error | null, stdout?: string, stderr?: string) => void,
30
- ) => cb(new Error("execFile not configured in this test")),
31
- ),
32
- };
33
- });
34
-
35
- vi.mock("node:fs", async () => {
36
- const actual = await import("node:fs");
37
- return {
38
- default: {
39
- ...actual,
40
- mkdirSync: vi.fn(),
41
- existsSync: vi.fn(() => false),
42
- appendFileSync: vi.fn(),
43
- writeFileSync: vi.fn(),
44
- readdirSync: vi.fn(() => []),
45
- },
46
- mkdirSync: vi.fn(),
47
- existsSync: vi.fn(() => false),
48
- appendFileSync: vi.fn(),
49
- writeFileSync: vi.fn(),
50
- readdirSync: vi.fn(() => []),
51
- promises: actual.promises,
52
- };
53
- });
54
-
55
- vi.mock("../alive-store.ts", () => ({
56
- writeAliveMarker: vi.fn(),
57
- }));
58
-
59
- // chatMode 测试不依赖后代判定(chatMode agent_end 早返回跳过 readActivePending),统一 count=0。
60
- // 非 chatMode 用例 ④ 的 agent_end 走正常 kill 分支(count=0 → SIGTERM)。
61
- vi.mock("../session-pending.ts", () => ({
62
- readActivePendingFromSessionFile: vi.fn(() => ({ count: 0 })),
63
- }));
64
-
65
- vi.mock("../temp-prompt.ts", () => ({
66
- writePromptToTempFile: vi.fn(async (agent: string) => {
67
- const safeName = agent.replace(/[^\w.-]+/g, "_");
68
- return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt-${safeName}.md` };
69
- }),
70
- cleanupTempPrompt: vi.fn(async () => {}),
71
- }));
72
-
73
- import { runSpawn } from "../session-runner.ts";
74
- import type { SessionRunnerContext } from "../session-runner.ts";
75
- import {
76
- DEFAULT_IDLE_TIMEOUT_MS,
77
- hasIdleTimer,
78
- _resetLifecycleState,
79
- } from "../lifecycle-manager.ts";
80
- import { createRecord } from "../execution-record.ts";
81
- import type { ExecutionRecord } from "../types.ts";
82
- import {
83
- emitStdoutLine,
84
- type FakeChild,
85
- lastSpawnedChild as lastSpawnedChildOf,
86
- makeCtx,
87
- makeOpts,
88
- makeRecord,
89
- sessionHeader,
90
- waitForSpawn as waitForSpawnOf,
91
- } from "./helpers/spawn-mock.ts";
92
-
93
- const mockSpawn = vi.mocked(spawn);
94
-
95
- const lastSpawnedChild = (): FakeChild => lastSpawnedChildOf(mockSpawn);
96
- const waitForSpawn = (timeoutMs = 1000): Promise<void> => waitForSpawnOf(mockSpawn, timeoutMs);
97
-
98
- /** 构造 chatMode record(spawn-mock.makeRecord 默认非 chatMode,此处显式开启)。 */
99
- function makeChatModeRecord(id = "sa-chat"): ExecutionRecord {
100
- return createRecord(id, {
101
- agent: "general-purpose",
102
- model: "test-model",
103
- mode: "sync",
104
- task: "chat task",
105
- slug: "chat",
106
- startedAt: 1_000_000,
107
- rootSessionId: "root-session",
108
- parentRecordId: undefined,
109
- depth: 0,
110
- chatMode: true,
111
- });
112
- }
113
-
114
- describe("[V2 模块 3] chatMode agent_settled 信号换挂", () => {
115
- beforeEach(() => {
116
- vi.clearAllMocks();
117
- // lifecycle-manager 是模块级单例(idleTimers Map 跨用例共享),每用例前清空防泄漏。
118
- _resetLifecycleState();
119
- });
120
-
121
- afterEach(() => {
122
- vi.restoreAllMocks();
123
- vi.useRealTimers();
124
- _resetLifecycleState();
125
- });
126
-
127
- it("① chatMode agent_end → 不触发 SIGTERM(进程保活,等 agent_settled)", async () => {
128
- const record = makeChatModeRecord("sa-chat-end");
129
- const promise = runSpawn(record, "Task: chatmode-end", makeOpts(), makeCtx());
130
-
131
- await waitForSpawn();
132
- const child = lastSpawnedChild();
133
-
134
- emitStdoutLine(child, sessionHeader());
135
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
136
- // 让事件 pump 处理 agent_end(stream flush 异步)
137
- await new Promise((r) => setTimeout(r, 20));
138
-
139
- // [V2 决策 1] chatMode agent_end 不 kill——进程不因轮次死,等 agent_settled。
140
- expect(child.killed).toBe(false);
141
- // agent_end 不 arm idle timer(arm 点是 agent_settled,不是 agent_end)
142
- expect(hasIdleTimer(record.id)).toBe(false);
143
-
144
- // 收尾:手动 close 让 runSpawn resolve(模拟后续 idle timer 超时 kill / 外部终止)
145
- child.stdout.end();
146
- child.stderr.end();
147
- child.emit("close", 143);
148
- const result = await promise;
149
- expect(result.success).toBe(true);
150
- });
151
-
152
- it("② chatMode agent_settled → armIdleTimer,idle 超时后 SIGTERM kill", async () => {
153
- const record = makeChatModeRecord("sa-chat-settled");
154
- const promise = runSpawn(record, "Task: chatmode-settled", makeOpts(), makeCtx());
155
-
156
- await waitForSpawn();
157
- const child = lastSpawnedChild();
158
-
159
- // 必须在 emit agent_settled 前启用 fake timers——armIdleTimer 内 setTimeout 在 agent_settled
160
- // 处理器里新建,新建时已是 fake timer 才可 advance。不 fake setImmediate:stream flush 靠
161
- // 真实事件循环。对齐 run-spawn-edges MF-3/MF-4 模式。
162
- vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "Date"] });
163
- try {
164
- emitStdoutLine(child, sessionHeader());
165
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
166
- await new Promise((r) => setImmediate(r));
167
- emitStdoutLine(child, { type: "agent_settled" });
168
- await new Promise((r) => setImmediate(r));
169
-
170
- // agent_settled → arm idle timer(DEFAULT_IDLE_TIMEOUT_MS = 5min)
171
- expect(hasIdleTimer(record.id)).toBe(true);
172
- // 进程仍存活(idle timer 未到期)
173
- expect(child.killed).toBe(false);
174
-
175
- // 未到 idle timeout(5min - 1ms):不 kill
176
- await vi.advanceTimersByTimeAsync(DEFAULT_IDLE_TIMEOUT_MS - 1);
177
- expect(child.killed).toBe(false);
178
-
179
- // idle timeout 到期:onTimeout → child.kill("SIGTERM")(复用现有 kill 路径)
180
- await vi.advanceTimersByTimeAsync(1);
181
- expect(child.killed).toBe(true);
182
- expect(child.killSignal).toBe("SIGTERM");
183
- // timer 触发后从 Map 移除(armIdleTimer 内 setTimeout 回调 idleTimers.delete)
184
- expect(hasIdleTimer(record.id)).toBe(false);
185
- } finally {
186
- vi.useRealTimers();
187
- }
188
-
189
- // 收尾:close 让 runSpawn resolve
190
- child.stdout.end();
191
- child.stderr.end();
192
- child.emit("close", 143);
193
- const result = await promise;
194
- expect(result.success).toBe(true);
195
- });
196
-
197
- it("③ chatMode agent_settled → 调 ctx.onRoundSettled(Step 3 挂载点,回调被调 1 次)", async () => {
198
- const record = makeChatModeRecord("sa-chat-cb");
199
- const onRoundSettled = vi.fn();
200
- const ctx: SessionRunnerContext = makeCtx({ onRoundSettled });
201
- const promise = runSpawn(record, "Task: chatmode-cb", makeOpts(), ctx);
202
-
203
- await waitForSpawn();
204
- const child = lastSpawnedChild();
205
-
206
- emitStdoutLine(child, sessionHeader());
207
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
208
- await new Promise((r) => setTimeout(r, 10));
209
- emitStdoutLine(child, { type: "agent_settled" });
210
- await new Promise((r) => setTimeout(r, 10));
211
-
212
- // agent_settled → onRoundSettled 被调,入参是当前 record
213
- expect(onRoundSettled).toHaveBeenCalledTimes(1);
214
- expect(onRoundSettled).toHaveBeenCalledWith(record);
215
-
216
- // 收尾:手动 close(idle timer 仍 armed,由 afterEach _resetLifecycleState 清理)
217
- child.stdout.end();
218
- child.stderr.end();
219
- child.emit("close", 143);
220
- const result = await promise;
221
- expect(result.success).toBe(true);
222
- });
223
-
224
- it("④ 非 chatMode agent_settled → 不 armIdleTimer、不调 onRoundSettled", async () => {
225
- // makeRecord 默认非 chatMode(createRecord 未传 chatMode)
226
- const record = makeRecord("sa-nonchat-settled");
227
- const onRoundSettled = vi.fn();
228
- const ctx: SessionRunnerContext = makeCtx({ onRoundSettled });
229
- const promise = runSpawn(record, "Task: nonchat-settled", makeOpts(), ctx);
230
-
231
- await waitForSpawn();
232
- const child = lastSpawnedChild();
233
-
234
- emitStdoutLine(child, sessionHeader());
235
- // 直接 emit agent_settled(非 chatMode:handler 应忽略,不 arm、不调回调)
236
- emitStdoutLine(child, { type: "agent_settled" });
237
- await new Promise((r) => setTimeout(r, 20));
238
-
239
- expect(hasIdleTimer(record.id)).toBe(false);
240
- expect(onRoundSettled).not.toHaveBeenCalled();
241
-
242
- // 收尾:emit agent_end 走正常 kill 分支(count=0 → SIGTERM)→ close resolve
243
- emitStdoutLine(child, { type: "agent_end", willRetry: false });
244
- await new Promise((r) => setTimeout(r, 10));
245
- expect(child.killed).toBe(true); // 非 chatMode agent_end → kill(现有行为,V2 不动)
246
-
247
- child.stdout.end();
248
- child.stderr.end();
249
- child.emit("close", 143);
250
- const result = await promise;
251
- expect(result.success).toBe(true);
252
- });
253
- });