@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,211 +0,0 @@
1
- // acquireActivateLock 30s 超时兜底单测 —— v4-lifecycle-convergence.md §3.3 A-2。
2
- //
3
- // 验证:前序 holder 持锁不 release(崩溃/死锁模拟)时,waiter
4
- // - 等待 29999ms 仍 pending(未误伤正常排队)
5
- // - 到 30001ms 抛含恢复指引的超时错误('activation timed out' + 'retry action: message')
6
- //
7
- // 测试策略:纯 Promise 链 + setTimeout 超时,用 vi.useFakeTimers() 控时,
8
- // advanceTimersByTimeAsync 同时推进 fake timer 与 microtask flush。
9
-
10
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
-
12
- import {
13
- _getActivateLockTailCountForTest,
14
- _resetLifecycleState,
15
- acquireActivateLock,
16
- } from "../lifecycle-manager.ts";
17
-
18
- describe("acquireActivateLock 30s 超时兜底 (v4 A-2)", () => {
19
- beforeEach(() => {
20
- vi.useFakeTimers();
21
- _resetLifecycleState();
22
- });
23
-
24
- afterEach(() => {
25
- _resetLifecycleState();
26
- vi.useRealTimers();
27
- });
28
-
29
- it("waiter 等待 29999ms 仍 pending;到 30001ms 抛含恢复指引的超时错误", async () => {
30
- // 第一个 holder 持锁后不 release(模拟崩溃/死锁)
31
- await acquireActivateLock("sa-stuck");
32
-
33
- // 第二个 waiter 必然排队(前序未 release)
34
- let errMsg: string | null = null;
35
- let gotRelease: (() => void) | null = null;
36
- const waiter = acquireActivateLock("sa-stuck")
37
- .then((release) => {
38
- gotRelease = release;
39
- })
40
- .catch((err: unknown) => {
41
- errMsg = err instanceof Error ? err.message : String(err);
42
- });
43
-
44
- // flush microtask:waiter 进入 prev.then 等待链
45
- await vi.advanceTimersByTimeAsync(0);
46
- expect(gotRelease).toBe(null); // 尚未拿到锁
47
- expect(errMsg).toBe(null);
48
-
49
- // 29999ms:未满 30s,waiter 仍 pending
50
- await vi.advanceTimersByTimeAsync(29999);
51
- expect(gotRelease).toBe(null);
52
- expect(errMsg).toBe(null);
53
-
54
- // 再推进 2ms(累计 30001ms):超时 timer 触发 → reject
55
- await vi.advanceTimersByTimeAsync(2);
56
- await waiter;
57
-
58
- // 超时:未拿到锁,抛含恢复指引的错误
59
- expect(gotRelease).toBe(null);
60
- expect(errMsg).not.toBe(null);
61
- expect(errMsg).toContain("activation timed out");
62
- expect(errMsg).toContain("retry action: message");
63
- expect(errMsg).toContain("sa-stuck");
64
- });
65
-
66
- it("首次 acquire(无前序 holder)立即返回 release,不触发超时", async () => {
67
- // 首次 acquire:prev=Promise.resolve(),立即 resolve,timer 被 clearTimeout 取消
68
- const release = await acquireActivateLock("sa-fresh");
69
- expect(typeof release).toBe("function");
70
-
71
- // 推进远超 30s,不应有任何未捕获的超时 reject(timer 已清除)
72
- await vi.advanceTimersByTimeAsync(60000);
73
- release();
74
- });
75
-
76
- it("[review 修复] 超时后前序 release → 链可推进:二次 acquire 立即获锁(锁链不瘫痪)", async () => {
77
- // 瘫痪路径回归:waiter 超时 reject 后,若其 current 永久 pending,tail 永久
78
- // pending → 前序 release 后后续 acquire 也只能 30s 超时(只能重启恢复)。
79
- // 修复后超时回调 resolve 自身 current 放行链尾:release1 后 tail settle,
80
- // 二次 acquire 的 prev 已 settle → 立即拿到 releaseFn。
81
- const release1 = await acquireActivateLock("sa-recover");
82
-
83
- let waiterErr: string | null = null;
84
- const waiter = acquireActivateLock("sa-recover").catch((err: unknown) => {
85
- waiterErr = err instanceof Error ? err.message : String(err);
86
- });
87
- await vi.advanceTimersByTimeAsync(0); // waiter 挂链
88
- await vi.advanceTimersByTimeAsync(30001); // 超时 reject(+ 超时放行链尾)
89
- await waiter;
90
- expect(waiterErr).toContain("activation timed out");
91
-
92
- release1(); // 前序释放 → tail settle(current 已被超时放行 resolve)
93
- await vi.advanceTimersByTimeAsync(0); // flush microtask 链
94
-
95
- // 二次 acquire:prev 是已 settle 的 tail → 立即拿到锁,不等 30s
96
- const release2 = await acquireActivateLock("sa-recover");
97
- expect(typeof release2).toBe("function");
98
- release2();
99
- await vi.advanceTimersByTimeAsync(0);
100
- });
101
-
102
- it("[review 修复] 前序持续持锁时超时不放行后续 waiter 提前获锁(互斥保持)", async () => {
103
- // 超时放行只 resolve 自身 current(tail 仍等 prev);前序未 release 时,
104
- // 新 acquire 依然排队等待,不会与前序 holder 形成双写者。
105
- const release1 = await acquireActivateLock("sa-mutex");
106
-
107
- const waiter1 = acquireActivateLock("sa-mutex").catch(() => {});
108
- await vi.advanceTimersByTimeAsync(30001); // waiter1 超时放行自身 current
109
- await waiter1;
110
-
111
- // 前序仍持锁:新 acquire 的 prev(= waiter1 的 tail)等待 release1,不提前获锁
112
- let gotRelease2 = false;
113
- const waiter2 = acquireActivateLock("sa-mutex").then(() => {
114
- gotRelease2 = true;
115
- });
116
- await vi.advanceTimersByTimeAsync(0);
117
- expect(gotRelease2).toBe(false); // 未提前获锁
118
-
119
- release1();
120
- await vi.advanceTimersByTimeAsync(0);
121
- await waiter2; // release1 后链推进,waiter2 获锁
122
- expect(gotRelease2).toBe(true);
123
- });
124
-
125
- it("[review 修复] 超时者对称自清:前序 release 推进链尾后 Map 条目回收;前序持锁期间不提前删", async () => {
126
- // round2 INFO 残留:超时者 releaseFn 永不被调用,原实现条目滞留 Map 直到下次
127
- // 同 recordId acquire 覆盖。修复后挂 tail 尾部自清——tail settle(前序已
128
- // release)时回收;tail pending(前序仍持锁)时回调不执行,条目保留(后续
129
- // acquire 仍排队等待,互斥不被破坏)。
130
- const release1 = await acquireActivateLock("sa-timeout-gc");
131
-
132
- const waiter = acquireActivateLock("sa-timeout-gc").catch(() => {});
133
- await vi.advanceTimersByTimeAsync(0); // waiter 挂链,Map 链尾已覆盖为 waiter 的 tail
134
- expect(_getActivateLockTailCountForTest()).toBe(1);
135
-
136
- await vi.advanceTimersByTimeAsync(30001); // 超时:reject + settleCurrent + tail.then 自清排队
137
- await waiter;
138
- // 前序仍持锁 → tail 仍 pending → 自清回调未执行 → 条目仍在
139
- expect(_getActivateLockTailCountForTest()).toBe(1);
140
-
141
- release1(); // 前序释放 → tail settle → 自清回调执行(identity 匹配,无新 waiter)
142
- await vi.advanceTimersByTimeAsync(0);
143
- expect(_getActivateLockTailCountForTest()).toBe(0);
144
- });
145
- });
146
-
147
- describe("activateLockTails tail-identity 自清(release 后回收)", () => {
148
- beforeEach(() => {
149
- vi.useFakeTimers();
150
- _resetLifecycleState();
151
- });
152
-
153
- afterEach(() => {
154
- _resetLifecycleState();
155
- vi.useRealTimers();
156
- });
157
-
158
- it("W3TC14: 无 waiter 时 release 后 Map 空 + release 后可再次 acquire", async () => {
159
- const release = await acquireActivateLock("sa-gc");
160
- // 自清新增的 test-only 观察点:acquire 后 Map 有 1 条链尾
161
- expect(_getActivateLockTailCountForTest()).toBe(1);
162
-
163
- release();
164
- // 自清经 queueMicrotask 异步执行——advanceTimersByTimeAsync(0) flush microtask
165
- await vi.advanceTimersByTimeAsync(0);
166
- // 无 waiter:Map 中链尾即本链尾,identity 匹配 → delete 回收
167
- expect(_getActivateLockTailCountForTest()).toBe(0);
168
-
169
- // release 后可再次 acquire:prev 回落 Promise.resolve(),立即 resolve 返回 release
170
- const release2 = await acquireActivateLock("sa-gc");
171
- expect(typeof release2).toBe("function");
172
- release2();
173
- await vi.advanceTimersByTimeAsync(0);
174
- expect(_getActivateLockTailCountForTest()).toBe(0);
175
- });
176
-
177
- it("W3TC15: 有 waiter 排队不删、最后释放者回收;不同 recordId 链独立", async () => {
178
- const release1 = await acquireActivateLock("sa-q");
179
-
180
- // 发起 acquire#2 同 recordId(不 await,.then 捕获 release2)
181
- let release2: (() => void) | null = null;
182
- const waiter = acquireActivateLock("sa-q").then((r) => {
183
- release2 = r;
184
- });
185
- // #2 进入等待链——此刻 Map 链尾已被 #2 覆盖
186
- await vi.advanceTimersByTimeAsync(0);
187
-
188
- release1();
189
- await vi.advanceTimersByTimeAsync(0);
190
- // ES7 核心:waiter 的链尾仍在——identity 不匹配不删
191
- expect(_getActivateLockTailCountForTest()).toBe(1);
192
-
193
- // acquire#2 在 release1 后正常 resolve(等待链不被 delete 破坏——waiter 持
194
- // acquire 时刻捕获的 prev Promise 引用而非 Map 查询)
195
- await waiter;
196
- expect(typeof release2).toBe("function");
197
-
198
- // 另一 recordId 独立链:同时持有时各自独立计数
199
- const releaseA = await acquireActivateLock("sa-a");
200
- expect(_getActivateLockTailCountForTest()).toBe(2); // sa-q + sa-a
201
-
202
- release2!();
203
- await vi.advanceTimersByTimeAsync(0);
204
- // 最后释放者回收:release2 的 identity 匹配 → sa-q 条目回收,sa-a 仍在
205
- expect(_getActivateLockTailCountForTest()).toBe(1);
206
-
207
- releaseA();
208
- await vi.advanceTimersByTimeAsync(0);
209
- expect(_getActivateLockTailCountForTest()).toBe(0);
210
- });
211
- });
@@ -1,383 +0,0 @@
1
- // lifecycle-manager 单测 —— V2 §5.2 模块 1(进程生命周期管理)五项职责。
2
- //
3
- // 测试策略:
4
- // - idle timer / ceiling LRU 用 vi.useFakeTimers() + advanceTimersByTime(同时 mock
5
- // Date.now(),让 lastTouched 时间戳可控)。
6
- // - activate 互斥锁是纯 Promise 链(无 timer),用 advanceTimersByTimeAsync(0)
7
- // flush microtask 验证串行化。
8
- // - 每个用例 beforeEach 调 _resetLifecycleState() 隔离模块级单例状态。
9
-
10
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
-
12
- import {
13
- DEFAULT_IDLE_TIMEOUT_MS,
14
- DEFAULT_MAX_ALIVE_PROCESSES,
15
- _resetLifecycleState,
16
- acquireActivateLock,
17
- armIdleTimer,
18
- disarmIdleTimer,
19
- evictIfOverCeiling,
20
- getActiveProcessCount,
21
- hasIdleTimer,
22
- reapAllAliveProcesses,
23
- registerActiveProcess,
24
- scanOrphanProcesses,
25
- touchActiveProcess,
26
- unregisterActiveProcess,
27
- } from "../lifecycle-manager.ts";
28
-
29
- describe("lifecycle-manager — V2 §5.2 模块 1", () => {
30
- beforeEach(() => {
31
- vi.useFakeTimers();
32
- _resetLifecycleState();
33
- // [F-4 同源修复] env 隔离:「默认超时」用例依赖 XYZ_SUBAGENT_IDLE_TIMEOUT_MS
34
- // 未设基线(getEnvIdleTimeoutMs 会覆盖 DEFAULT),宿主 export 即假红。空串 = 未设。
35
- vi.stubEnv("XYZ_SUBAGENT_IDLE_TIMEOUT_MS", "");
36
- });
37
-
38
- afterEach(() => {
39
- _resetLifecycleState();
40
- vi.useRealTimers();
41
- vi.unstubAllEnvs();
42
- });
43
-
44
- // ============================================================
45
- // 职责 1:idle timer
46
- // ============================================================
47
- describe("职责1 idle timer", () => {
48
- it("arm 后到 timeoutMs 触发 onTimeout(边界:差 1ms 不触发)", () => {
49
- const onTimeout = vi.fn();
50
- armIdleTimer("sa-1", onTimeout, 1000);
51
-
52
- expect(hasIdleTimer("sa-1")).toBe(true);
53
- vi.advanceTimersByTime(999);
54
- expect(onTimeout).not.toHaveBeenCalled();
55
-
56
- vi.advanceTimersByTime(1);
57
- expect(onTimeout).toHaveBeenCalledTimes(1);
58
- // 触发后自动从 Map 移除(不残留失效 entry)
59
- expect(hasIdleTimer("sa-1")).toBe(false);
60
- });
61
-
62
- it("disarm 后不再触发 onTimeout", () => {
63
- const onTimeout = vi.fn();
64
- armIdleTimer("sa-1", onTimeout, 1000);
65
- disarmIdleTimer("sa-1");
66
-
67
- expect(hasIdleTimer("sa-1")).toBe(false);
68
- vi.advanceTimersByTime(5000);
69
- expect(onTimeout).not.toHaveBeenCalled();
70
- });
71
-
72
- it("disarm 不存在的 record 为 no-op(不抛错)", () => {
73
- expect(() => disarmIdleTimer("never-armed")).not.toThrow();
74
- });
75
-
76
- it("重复 arm 刷新 timer:旧 timer 作废、重新计时", () => {
77
- const onTimeout = vi.fn();
78
- armIdleTimer("sa-1", onTimeout, 1000);
79
- vi.advanceTimersByTime(500); // 过了 500ms
80
-
81
- armIdleTimer("sa-1", onTimeout, 1000); // 刷新:重新计 1000ms
82
- vi.advanceTimersByTime(999);
83
- expect(onTimeout).not.toHaveBeenCalled(); // 旧 timer 已作废,新的还没到
84
-
85
- vi.advanceTimersByTime(1);
86
- expect(onTimeout).toHaveBeenCalledTimes(1);
87
- });
88
-
89
- it("默认超时 = DEFAULT_IDLE_TIMEOUT_MS", () => {
90
- const onTimeout = vi.fn();
91
- armIdleTimer("sa-1", onTimeout); // 不传 timeoutMs
92
-
93
- vi.advanceTimersByTime(DEFAULT_IDLE_TIMEOUT_MS - 1);
94
- expect(onTimeout).not.toHaveBeenCalled();
95
-
96
- vi.advanceTimersByTime(1);
97
- expect(onTimeout).toHaveBeenCalledTimes(1);
98
- });
99
-
100
- it("显式禁用值(0/负数)→ 不挂 timer(预算语义对齐:idle GC 可显式关闭;旧实现 0 落成 setTimeout(0) 立即 kill)", () => {
101
- const onTimeout = vi.fn();
102
- armIdleTimer("sa-disable-0", onTimeout, 0);
103
- expect(hasIdleTimer("sa-disable-0")).toBe(false);
104
- armIdleTimer("sa-disable-neg", onTimeout, -1);
105
- expect(hasIdleTimer("sa-disable-neg")).toBe(false);
106
-
107
- vi.advanceTimersByTime(DEFAULT_IDLE_TIMEOUT_MS * 2);
108
- expect(onTimeout).not.toHaveBeenCalled();
109
- });
110
-
111
- it("显式禁用值顺带 disarm 已有 armed timer(禁用不形同虚设)", () => {
112
- const onTimeout = vi.fn();
113
- armIdleTimer("sa-disable-late", onTimeout, 1000);
114
- expect(hasIdleTimer("sa-disable-late")).toBe(true);
115
- armIdleTimer("sa-disable-late", onTimeout, 0);
116
- expect(hasIdleTimer("sa-disable-late")).toBe(false);
117
- vi.advanceTimersByTime(2000);
118
- expect(onTimeout).not.toHaveBeenCalled();
119
- });
120
-
121
- // [U1] setTimeout 2^31-1 溢出 fail-fast:溢出 delay 被 Node 置 1ms 立即触发
122
- //(「长空闲保活」变「立即 kill」),arm 入口拦截且错误含上限值与恢复指引。
123
- // 显式禁用通道(<=0)不受影响(上方用例已锁)。
124
- it("idleTimeoutMs 溢出(>2^31-1)→ fail-fast throw,不挂 timer", () => {
125
- const onTimeout = vi.fn();
126
- expect(() => armIdleTimer("sa-overflow", onTimeout, 3_000_000_000)).toThrowError(/2147483647/);
127
- expect(() => armIdleTimer("sa-overflow", onTimeout, Number.MAX_SAFE_INTEGER)).toThrowError(
128
- /Recovery/,
129
- );
130
- expect(hasIdleTimer("sa-overflow")).toBe(false);
131
- vi.advanceTimersByTime(3_000_000_000);
132
- expect(onTimeout).not.toHaveBeenCalled();
133
- });
134
-
135
- it("env XYZ_SUBAGENT_IDLE_TIMEOUT_MS 溢出 → fail-fast throw(arm 入口统一拦截)", () => {
136
- vi.stubEnv("XYZ_SUBAGENT_IDLE_TIMEOUT_MS", "3000000000");
137
- const onTimeout = vi.fn();
138
- expect(() => armIdleTimer("sa-env-overflow", onTimeout)).toThrowError(/2147483647/);
139
- expect(hasIdleTimer("sa-env-overflow")).toBe(false);
140
- });
141
- });
142
-
143
- // ============================================================
144
- // 职责 2:全局 ceiling(LRU 挤出)
145
- // ============================================================
146
- describe("职责2 全局 ceiling", () => {
147
- it("register 超过上限时 evictIfOverCeiling 挤出最久空闲", () => {
148
- registerActiveProcess("sa-1"); // 最早
149
- vi.advanceTimersByTime(10);
150
- registerActiveProcess("sa-2");
151
- vi.advanceTimersByTime(10);
152
- registerActiveProcess("sa-3"); // 超限(size=3 > ceiling=2)
153
- expect(getActiveProcessCount()).toBe(3);
154
-
155
- const evicted: string[] = [];
156
- evictIfOverCeiling((id) => evicted.push(id), 2);
157
-
158
- expect(evicted).toEqual(["sa-1"]); // lastTouched 最老的被挤出
159
- expect(getActiveProcessCount()).toBe(2);
160
- });
161
-
162
- it("不超过上限时 evictIfOverCeiling 不挤出", () => {
163
- registerActiveProcess("sa-1");
164
- registerActiveProcess("sa-2");
165
-
166
- const evicted: string[] = [];
167
- evictIfOverCeiling((id) => evicted.push(id), 5);
168
-
169
- expect(evicted).toEqual([]);
170
- expect(getActiveProcessCount()).toBe(2);
171
- });
172
-
173
- it("touch 更新 LRU:被 touch 的不再是挤出候选", () => {
174
- registerActiveProcess("sa-1");
175
- vi.advanceTimersByTime(10);
176
- registerActiveProcess("sa-2");
177
- vi.advanceTimersByTime(10);
178
- touchActiveProcess("sa-1"); // sa-1 变最新 → sa-2 变最老
179
-
180
- const evicted: string[] = [];
181
- evictIfOverCeiling((id) => evicted.push(id), 1);
182
-
183
- expect(evicted).toEqual(["sa-2"]); // sa-2 最久未 touch,被挤出
184
- });
185
-
186
- it("touch 不存在的 record 为 no-op(不隐式创建)", () => {
187
- expect(() => touchActiveProcess("never-registered")).not.toThrow();
188
- expect(getActiveProcessCount()).toBe(0);
189
- });
190
-
191
- it("unregister 清理活进程集合", () => {
192
- registerActiveProcess("sa-1");
193
- registerActiveProcess("sa-2");
194
- unregisterActiveProcess("sa-1");
195
- expect(getActiveProcessCount()).toBe(1);
196
- });
197
-
198
- it("挤出时连带 disarm 被挤 record 的 idle timer", () => {
199
- registerActiveProcess("sa-1");
200
- armIdleTimer("sa-1", vi.fn(), 1000);
201
- registerActiveProcess("sa-2");
202
- vi.advanceTimersByTime(10);
203
- registerActiveProcess("sa-3"); // sa-1 最老,将被挤出
204
-
205
- evictIfOverCeiling(() => {
206
- /* kill */
207
- }, 2);
208
-
209
- expect(hasIdleTimer("sa-1")).toBe(false); // 挤出 cascade disarm
210
- });
211
-
212
- it("unregister 连带 disarm idle timer(进程终态 timer 不残留)", () => {
213
- registerActiveProcess("sa-1");
214
- armIdleTimer("sa-1", vi.fn(), 1000);
215
- unregisterActiveProcess("sa-1");
216
- expect(hasIdleTimer("sa-1")).toBe(false);
217
- });
218
-
219
- it("默认上限 = DEFAULT_MAX_ALIVE_PROCESSES(不传 maxAlive)", () => {
220
- for (let i = 0; i < DEFAULT_MAX_ALIVE_PROCESSES; i++) {
221
- registerActiveProcess(`sa-${i}`);
222
- vi.advanceTimersByTime(1); // 保证 lastTouched 严格递增
223
- }
224
- registerActiveProcess("sa-over"); // 超限
225
- const evicted: string[] = [];
226
- evictIfOverCeiling((id) => evicted.push(id)); // 用默认上限
227
-
228
- expect(evicted).toEqual(["sa-0"]); // 默认上限下挤出最早
229
- expect(getActiveProcessCount()).toBe(DEFAULT_MAX_ALIVE_PROCESSES);
230
- });
231
-
232
- it("大幅超限时 while 循环挤出多个直到 ≤ ceiling", () => {
233
- for (let i = 0; i < 5; i++) {
234
- registerActiveProcess(`sa-${i}`);
235
- vi.advanceTimersByTime(1);
236
- }
237
- const evicted: string[] = [];
238
- evictIfOverCeiling((id) => evicted.push(id), 2);
239
-
240
- expect(evicted).toEqual(["sa-0", "sa-1", "sa-2"]); // 挤出 3 个(5-2),按 LRU
241
- });
242
- });
243
-
244
- // ============================================================
245
- // 职责 3:shutdown 收割
246
- // ============================================================
247
- describe("职责3 shutdown 收割", () => {
248
- it("reapAllAliveProcesses 遍历活进程调 killFn 并返回列表", () => {
249
- registerActiveProcess("sa-1");
250
- registerActiveProcess("sa-2");
251
-
252
- const killed: string[] = [];
253
- const reaped = reapAllAliveProcesses((id) => killed.push(id));
254
-
255
- expect(killed).toHaveLength(2);
256
- expect(killed).toEqual(expect.arrayContaining(["sa-1", "sa-2"]));
257
- expect(reaped).toEqual(expect.arrayContaining(["sa-1", "sa-2"]));
258
- expect(getActiveProcessCount()).toBe(0);
259
- });
260
-
261
- it("reap 后 idle timer 已 disarm(advance 不再触发)", () => {
262
- registerActiveProcess("sa-1");
263
- const onTimeout = vi.fn();
264
- armIdleTimer("sa-1", onTimeout, 1000);
265
-
266
- reapAllAliveProcesses(() => {
267
- /* kill */
268
- });
269
- vi.advanceTimersByTime(10000);
270
-
271
- expect(onTimeout).not.toHaveBeenCalled(); // timer 已被 reap 清理
272
- });
273
-
274
- it("无活进程时 reapAll 返回空列表", () => {
275
- const reaped = reapAllAliveProcesses(() => {
276
- /* kill */
277
- });
278
- expect(reaped).toEqual([]);
279
- });
280
- });
281
-
282
- // ============================================================
283
- // 职责 4:孤儿扫描
284
- // ============================================================
285
- describe("职责4 孤儿扫描", () => {
286
- it("pid 存活 + 不在活进程集合 = 孤儿", () => {
287
- registerActiveProcess("sa-active"); // 在集合内
288
- const records = [
289
- { id: "sa-active", pid: 100 },
290
- { id: "sa-orphan", pid: 200 }, // pid 活但不在集合 → 孤儿
291
- { id: "sa-dead", pid: 300 }, // pid 不活 → 非孤儿
292
- { id: "sa-nopid" }, // 无 pid → 非孤儿
293
- ];
294
-
295
- const orphans = scanOrphanProcesses(records, (pid) => pid === 100 || pid === 200);
296
-
297
- expect(orphans).toEqual(["sa-orphan"]);
298
- });
299
-
300
- it("pid 不存活 = 非孤儿", () => {
301
- const records = [{ id: "sa-1", pid: 999 }];
302
- const orphans = scanOrphanProcesses(records, () => false); // 全不活
303
- expect(orphans).toEqual([]);
304
- });
305
-
306
- it("在活进程集合内 = 非孤儿(即使 pid 活)", () => {
307
- registerActiveProcess("sa-1");
308
- const records = [{ id: "sa-1", pid: 100 }];
309
- const orphans = scanOrphanProcesses(records, () => true);
310
- expect(orphans).toEqual([]);
311
- });
312
-
313
- it("无 pid 的 record 不视为孤儿", () => {
314
- const records = [
315
- { id: "sa-1" },
316
- { id: "sa-2", sessionFile: "/x.jsonl" },
317
- ];
318
- const orphans = scanOrphanProcesses(records, () => true);
319
- expect(orphans).toEqual([]);
320
- });
321
-
322
- it("扫描是只读(不改活进程集合)", () => {
323
- registerActiveProcess("sa-1");
324
- scanOrphanProcesses([{ id: "sa-2", pid: 200 }], () => true);
325
- expect(getActiveProcessCount()).toBe(1); // 集合不变
326
- });
327
- });
328
-
329
- // ============================================================
330
- // 职责 5:activate 互斥锁
331
- // ============================================================
332
- describe("职责5 activate 互斥锁", () => {
333
- it("首次 acquire 立即 resolve 返回 release 函数", async () => {
334
- const release = await acquireActivateLock("sa-1");
335
- expect(typeof release).toBe("function");
336
- release();
337
- });
338
-
339
- it("并发 acquire 同一 recordId 串行化:第二次等首次 release", async () => {
340
- const release1 = await acquireActivateLock("sa-1");
341
-
342
- let secondResolved = false;
343
- const secondPromise = acquireActivateLock("sa-1").then((r) => {
344
- secondResolved = true;
345
- return r;
346
- });
347
-
348
- await vi.advanceTimersByTimeAsync(0); // flush microtask
349
- expect(secondResolved).toBe(false); // 还在等首次 release
350
-
351
- release1();
352
- await vi.advanceTimersByTimeAsync(0); // flush microtask
353
- expect(secondResolved).toBe(true);
354
-
355
- const release2 = await secondPromise;
356
- release2();
357
- });
358
-
359
- it("不同 recordId 不互斥(各自独立链)", async () => {
360
- const release1 = await acquireActivateLock("sa-1");
361
-
362
- let secondResolved = false;
363
- acquireActivateLock("sa-2").then((r) => {
364
- secondResolved = true;
365
- r();
366
- });
367
-
368
- await vi.advanceTimersByTimeAsync(0); // flush microtask
369
- expect(secondResolved).toBe(true); // sa-2 不被 sa-1 阻塞
370
-
371
- release1();
372
- });
373
-
374
- it("release 后同 recordId 可再次 acquire", async () => {
375
- const r1 = await acquireActivateLock("sa-1");
376
- r1();
377
-
378
- const r2 = await acquireActivateLock("sa-1");
379
- expect(typeof r2).toBe("function");
380
- r2();
381
- });
382
- });
383
- });