@zhushanwen/subagent-core 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-Dv4QhSJ_.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +835 -668
  6. package/dist/{types-Dv4QhSJ_.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +835 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14123 -15467
  20. package/dist/index.d.cts +1179 -1540
  21. package/dist/index.d.ts +1179 -1540
  22. package/dist/index.js +7694 -10986
  23. package/dist.bundle/index.cjs +33485 -0
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/agent-registry.test.ts +1 -1
  30. package/src/execution/__tests__/alive-store.test.ts +1 -1
  31. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  32. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  33. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  34. package/src/execution/__tests__/collect-coordinator-service.test.ts +316 -0
  35. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  36. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +229 -0
  37. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  38. package/src/execution/__tests__/config.test.ts +1 -1
  39. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  40. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  41. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  42. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +21 -34
  43. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  44. package/src/execution/__tests__/gc-timer.test.ts +8 -23
  45. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  46. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  47. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  48. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  49. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  50. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  51. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  52. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  53. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  54. package/src/execution/__tests__/notify-ledger.test.ts +27 -0
  55. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  56. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  57. package/src/execution/__tests__/record-store.test.ts +60 -6
  58. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  59. package/src/execution/__tests__/relay-env.test.ts +12 -1
  60. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  61. package/src/execution/__tests__/session-file-gc.test.ts +1 -1
  62. package/src/execution/__tests__/session-pending.test.ts +119 -17
  63. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  64. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  65. package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
  66. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +14 -11
  67. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  68. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  69. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  70. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  71. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  72. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  73. package/src/execution/__tests__/sync-collect-recovery.test.ts +1102 -0
  74. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  75. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  76. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  77. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  78. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  79. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  80. package/src/execution/agent-registry.ts +6 -2
  81. package/src/execution/collect-coordinator.ts +200 -0
  82. package/src/execution/config.ts +77 -5
  83. package/src/execution/dialog-queue.ts +6 -73
  84. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  85. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  86. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  87. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  88. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  89. package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
  90. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  91. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  92. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  93. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  94. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  95. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  96. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  97. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  98. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  99. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +82 -55
  100. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  101. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  102. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  103. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +8 -3
  104. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  105. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  106. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  107. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  108. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  109. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  110. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  111. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  112. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  113. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  114. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  115. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  116. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  117. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  118. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  119. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  120. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  121. package/src/execution/engine/client/client-options.ts +103 -0
  122. package/src/execution/engine/client/engine-client.ts +687 -0
  123. package/src/execution/engine/client/mirror.ts +167 -0
  124. package/src/execution/engine/client/pid-file.ts +392 -0
  125. package/src/execution/engine/client/reaper.ts +95 -0
  126. package/src/execution/engine/client/remote-engine.ts +441 -0
  127. package/src/execution/engine/client/reverse-router.ts +255 -0
  128. package/src/execution/engine/common/capability-gate.ts +109 -22
  129. package/src/execution/engine/common/errors.ts +9 -25
  130. package/src/execution/engine/common/event-journal.ts +4 -50
  131. package/src/execution/engine/common/journal-replay.ts +3 -1
  132. package/src/execution/engine/common/kill-chain.ts +18 -251
  133. package/src/execution/engine/common/nesting-guard.ts +18 -114
  134. package/src/execution/engine/common/pool-manager.ts +4 -0
  135. package/src/execution/engine/common/session-view-service.ts +56 -84
  136. package/src/execution/engine/config.ts +151 -0
  137. package/src/execution/engine/d8-compat.ts +346 -0
  138. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  139. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  140. package/src/execution/engine/engine-discovery.ts +30 -7
  141. package/src/execution/engine/engine-inspect-package.ts +282 -0
  142. package/src/execution/engine/engine-manifest.ts +244 -0
  143. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  144. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  145. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  146. package/src/execution/engine/host/host-bridge.ts +150 -0
  147. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  148. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  149. package/src/execution/engine/host/spawned-children.ts +139 -0
  150. package/src/execution/engine/host-task-spec.ts +29 -2
  151. package/src/execution/engine/model-validation.ts +55 -2
  152. package/src/execution/engine/paths.ts +16 -41
  153. package/src/execution/engine/port.ts +48 -2
  154. package/src/execution/engine/registry.ts +153 -34
  155. package/src/execution/engine/routing.ts +225 -52
  156. package/src/execution/engine/types.ts +25 -200
  157. package/src/execution/execution-record.ts +7 -0
  158. package/src/execution/finalize-record.ts +40 -11
  159. package/src/execution/idle-gc.ts +89 -14
  160. package/src/execution/lifecycle-manager.ts +10 -7
  161. package/src/execution/lifecycle-predicates.ts +10 -8
  162. package/src/execution/notifier.ts +234 -25
  163. package/src/execution/notify-host.ts +21 -1
  164. package/src/execution/record-entry.ts +16 -0
  165. package/src/execution/record-store.ts +189 -31
  166. package/src/execution/relay-env.ts +19 -36
  167. package/src/execution/round-supervisor/domain.ts +89 -0
  168. package/src/execution/round-supervisor/index.ts +33 -0
  169. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  170. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  171. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  172. package/src/execution/round-supervisor/service-binding.ts +273 -0
  173. package/src/execution/round-supervisor/supervisor.ts +426 -0
  174. package/src/execution/session-pending.ts +68 -74
  175. package/src/execution/settled-watchdog.ts +39 -0
  176. package/src/execution/subagent-actions-core.ts +62 -6
  177. package/src/execution/subagent-service.ts +1161 -406
  178. package/src/execution/subprocess-agent-runner.ts +16 -8
  179. package/src/execution/sync-rebuild.ts +87 -0
  180. package/src/execution/types.ts +104 -117
  181. package/src/execution/ui-channels.ts +13 -214
  182. package/src/execution/ui-request-handler-factory.ts +7 -4
  183. package/src/execution/ui-request-observability.ts +2 -2
  184. package/src/execution/workflow-state-root.ts +67 -0
  185. package/src/execution/worktree-git-ops.ts +5 -0
  186. package/src/execution/worktree-manager.ts +11 -1
  187. package/src/index.ts +55 -26
  188. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  189. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  190. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  191. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  192. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  193. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  194. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  195. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  196. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  197. package/src/orchestration/execute-agent-call.ts +1 -1
  198. package/src/orchestration/file-run-store.ts +144 -59
  199. package/src/orchestration/models/types.ts +43 -42
  200. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  201. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  202. package/src/shared/zcode-model-ref.ts +31 -0
  203. package/dist/chunk-43ONBFZX.js +0 -240
  204. package/dist/chunk-A4IVZWVX.js +0 -31
  205. package/dist/chunk-APZY4IME.js +0 -27
  206. package/dist/chunk-V3VHZ2VX.js +0 -59
  207. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  208. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  209. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  210. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  211. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  212. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  213. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  214. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  215. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  216. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  217. package/src/__tests__/session-runner.test.ts +0 -69
  218. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  219. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  220. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  221. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  222. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  223. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  224. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  225. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  226. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  227. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  228. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  229. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  230. package/src/execution/__tests__/output-collector.test.ts +0 -469
  231. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  232. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  233. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  234. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  235. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  236. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  237. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  238. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  239. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  240. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  241. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  242. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  243. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  244. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  245. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  246. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  247. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  248. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  249. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  250. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  251. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  252. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  253. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  254. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  255. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  256. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  257. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  258. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  259. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  260. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  261. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  262. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  263. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  264. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  265. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  266. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  267. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  268. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  269. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  270. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  271. package/src/execution/engine/common/schema-emulation.ts +0 -189
  272. package/src/execution/engine/common/session-view-projection.ts +0 -51
  273. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  274. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  275. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  276. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  277. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  278. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  279. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  280. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  281. package/src/execution/engine/engines/pi/reader.ts +0 -59
  282. package/src/execution/engine/engines/pi/registration.ts +0 -37
  283. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  284. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  285. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  286. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  287. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  288. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  289. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  290. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  291. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  292. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  293. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  294. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  295. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  296. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  297. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  298. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  299. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  300. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  301. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  302. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  303. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  305. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  306. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  307. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  308. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  309. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  310. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  311. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  312. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  313. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  314. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  315. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  316. package/src/execution/round-settlement.ts +0 -93
  317. package/src/execution/ui-request-queue.ts +0 -215
  318. package/src/shared/schema-env.ts +0 -44
@@ -1,220 +0,0 @@
1
- // src/execution/__tests__/descendant-sweep-guards.test.ts
2
- //
3
- // [S-17c / T2-②] sweepDescendantsOfSession 守卫分支补充(与 descendant-sweep.test.ts
4
- // 互补,不改动其既有用例)。
5
- //
6
- // 覆盖该文件未锁定的分支:
7
- // - register entry 缺 sessionId(TODO T5 marker fallback 锚点)→ skipped 留痕不杀;
8
- // - readProcessCmdline 两条失败边:ps 非零退出(status≠0/error)与 spawnSync 同步
9
- // 抛错 → cmdline undefined → "cmdline probe failed" 保守跳过;
10
- // - killPidWithEscalation 的 SIGTERM 发送失败(EPERM 等权限/垂死窗口)→ debug
11
- // 留痕不武装升级(30s 后无 SIGKILL);
12
- // - SIGKILL 升级窗口内目标自行退出(ESRCH)→ 吞掉不崩(目标已达成)。
13
- //
14
- // 真实 fs(临时目录)+ mock spawnSync / process.kill / logger——同 descendant-sweep
15
- // 布局,新增 logger mock 用于 SIGTERM 失败留痕断言。
16
-
17
- import { spawnSync } from "node:child_process";
18
- import * as fs from "node:fs";
19
- import * as os from "node:os";
20
- import * as path from "node:path";
21
-
22
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
23
-
24
- const { loggerMock } = vi.hoisted(() => ({
25
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn() },
26
- }));
27
- vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
28
-
29
- // 只 mock spawnSync(ps 探测受控);spawn 等其余实现保留 actual(本文件不经 runSpawn)。
30
- vi.mock("node:child_process", async () => {
31
- const actual = await import("node:child_process");
32
- return {
33
- ...actual,
34
- spawnSync: vi.fn(),
35
- };
36
- });
37
-
38
- import { sweepDescendantsOfSession } from "../engine/engines/pi/session-runner.ts";
39
- import { clearPendingCursors } from "../session-pending.ts";
40
- import { writeAliveMarker } from "../alive-store.ts";
41
-
42
- const mockSpawnSync = vi.mocked(spawnSync);
43
-
44
- const ALIVE_PID = 424_242;
45
-
46
- /** process.kill 受控:signal=0 探活与真实信号分别处置,信号调用记录到 kills。 */
47
- const kills: Array<{ pid: number; signal: string | number }> = [];
48
-
49
- function entryLine(customType: string, data: Record<string, unknown>): string {
50
- return `${JSON.stringify({
51
- type: "custom",
52
- customType,
53
- data,
54
- timestamp: "2026-09-01T00:00:00.000Z",
55
- id: `e-${Math.random().toString(36).slice(2)}`,
56
- })}\n`;
57
- }
58
-
59
- function registerData(fields: Record<string, unknown>): Record<string, unknown> {
60
- return { id: "bg-1", type: "session", name: "desc", status: "active", registeredAt: 1, ...fields };
61
- }
62
-
63
- /** ps -p <pid> -o command= 的完整 SpawnSyncReturns 形态(字段补齐省 as 链)。 */
64
- function psResult(stdout: string, status = 0): ReturnType<typeof spawnSync> {
65
- return {
66
- pid: 0,
67
- output: [null, stdout, ""],
68
- stdout,
69
- stderr: "",
70
- status,
71
- signal: null,
72
- } as ReturnType<typeof spawnSync>;
73
- }
74
-
75
- let sessionDir = "";
76
-
77
- beforeEach(() => {
78
- vi.clearAllMocks();
79
- clearPendingCursors();
80
- kills.length = 0;
81
- sessionDir = fs.mkdtempSync(path.join(os.tmpdir(), "desc-sweep-guard-"));
82
- vi.spyOn(process, "kill").mockImplementation(((pid: number, signal?: string | number) => {
83
- if (signal === undefined || signal === 0) return true; // 探活恒真(目标在窗口内存活)
84
- kills.push({ pid, signal });
85
- return true;
86
- }) as typeof process.kill);
87
- });
88
-
89
- afterEach(() => {
90
- vi.restoreAllMocks();
91
- clearPendingCursors();
92
- fs.rmSync(sessionDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
93
- });
94
-
95
- /** 层主 + 一个带 .alive marker 的直接后代(标准单层树)。 */
96
- function writeSingleLevelTree(): { rootFile: string; childFile: string } {
97
- const rootFile = path.join(sessionDir, "20260901T000000-000_root-sess.jsonl");
98
- const childFile = path.join(sessionDir, "20260901T000001-000_child-sess.jsonl");
99
- fs.writeFileSync(rootFile, entryLine("pending:register", registerData({ sessionId: "child-sess" })));
100
- fs.writeFileSync(childFile, "other entry line\n");
101
- writeAliveMarker(childFile, { pid: ALIVE_PID, id: "child-sess", startedAt: Date.now() });
102
- return { rootFile, childFile };
103
- }
104
-
105
- /** ps 探测默认桩:存活 pid 返回 pi rpc 形态。 */
106
- function stubCmdlineByPid(): void {
107
- mockSpawnSync.mockImplementation((_cmd: string, args?: readonly string[]) => {
108
- const pid = Number(args?.[1]);
109
- return psResult(`node /usr/local/bin/pi --mode rpc --session-dir /tmp/sess-${pid}\n`);
110
- });
111
- }
112
-
113
- describe("[S-17c] sweep 守卫:pending 项缺 sessionId(T5 marker fallback 锚点)", () => {
114
- it("register entry 无 sessionId → skipped 留痕(reason 指向 T5 兜底),不杀任何进程", () => {
115
- stubCmdlineByPid();
116
- const rootFile = path.join(sessionDir, "20260901T000000-000_root2.jsonl");
117
- fs.writeFileSync(rootFile, entryLine("pending:register", registerData({ sessionId: undefined })));
118
-
119
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-nosessid");
120
-
121
- expect(r.killed).toHaveLength(0);
122
- expect(r.skipped).toHaveLength(1);
123
- // sessionId 字段回退为 pending 操作 id(诊断线索),reason 说明 marker 兜底锚点
124
- expect(r.skipped[0]).toMatchObject({
125
- sessionId: "bg-1",
126
- reason: expect.stringContaining("no sessionId (marker-based fallback pending T5)"),
127
- });
128
- expect(kills).toHaveLength(0);
129
- });
130
- });
131
-
132
- describe("[S-17c] sweep 守卫:readProcessCmdline 失败边(保守跳过不动手)", () => {
133
- it.each([
134
- [
135
- "ps 非零退出(进程刚死,ps -p 无此进程)",
136
- () =>
137
- mockSpawnSync.mockImplementation(() => psResult("", 1)),
138
- ],
139
- [
140
- "spawnSync 同步抛错(ps 不可用)",
141
- () =>
142
- mockSpawnSync.mockImplementation(() => {
143
- throw new Error("ps binary missing");
144
- }),
145
- ],
146
- ])("%s → cmdline probe failed,跳过不杀", (_label, setupProbe) => {
147
- const { rootFile } = writeSingleLevelTree();
148
- setupProbe();
149
-
150
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-ps-fail");
151
-
152
- // [防误杀] 探测失败 = 无法证明是 pi rpc 形态 → 一律不动手
153
- expect(r.killed).toHaveLength(0);
154
- expect(r.skipped).toHaveLength(1);
155
- expect(r.skipped[0]).toMatchObject({
156
- pid: ALIVE_PID,
157
- reason: expect.stringContaining("cmdline probe failed (ps unavailable)"),
158
- });
159
- expect(kills).toHaveLength(0);
160
- });
161
- });
162
-
163
- describe("[S-17c] killPidWithEscalation:SIGTERM/ SIGKILL 失败边", () => {
164
- it("SIGTERM 发送即失败(权限/垂死窗口 EPERM)→ debug 留痕不武装升级,30s 后无 SIGKILL", async () => {
165
- vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
166
- stubCmdlineByPid();
167
- vi.spyOn(process, "kill").mockImplementation(((pid: number, signal?: string | number) => {
168
- if (signal === undefined || signal === 0) return true;
169
- if (signal === "SIGTERM") {
170
- const err = new Error("operation not permitted") as NodeJS.ErrnoException;
171
- err.code = "EPERM";
172
- throw err;
173
- }
174
- kills.push({ pid, signal });
175
- return true;
176
- }) as typeof process.kill);
177
-
178
- const { rootFile } = writeSingleLevelTree();
179
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-sigterm-fail");
180
-
181
- // killed 列表记录的是处置意图;实际 SIGTERM 未送达(失败留痕,best-effort continue)
182
- expect(r.killed).toEqual([ALIVE_PID]);
183
- expect(loggerMock.debug).toHaveBeenCalledWith(
184
- expect.stringContaining(`SIGTERM to pid ${ALIVE_PID} failed (best-effort continue)`),
185
- );
186
-
187
- // 无升级 timer:SIGTERM 失败后直接 return,越过 30s 窗口也不补发 SIGKILL
188
- await vi.advanceTimersByTimeAsync(30_000);
189
- expect(kills).toHaveLength(0);
190
- });
191
-
192
- it("SIGKILL 升级窗口内目标自行退出(ESRCH)→ 吞掉不崩,SIGTERM 已达即目标达成", async () => {
193
- vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
194
- stubCmdlineByPid();
195
- // 探活恒真(fire 时窗口内仍活);SIGTERM 送达成功;SIGKILL 时进程已退出(ESRCH)
196
- vi.spyOn(process, "kill").mockImplementation(((pid: number, signal?: string | number) => {
197
- if (signal === undefined || signal === 0) return true;
198
- if (signal === "SIGKILL") {
199
- const err = new Error("No such process") as NodeJS.ErrnoException;
200
- err.code = "ESRCH";
201
- throw err;
202
- }
203
- kills.push({ pid, signal });
204
- return true;
205
- }) as typeof process.kill);
206
-
207
- const { rootFile } = writeSingleLevelTree();
208
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-sigkill-esrch");
209
-
210
- expect(r.killed).toEqual([ALIVE_PID]);
211
- expect(kills).toEqual([{ pid: ALIVE_PID, signal: "SIGTERM" }]);
212
-
213
- // 升级 fire:ESRCH 是预期终态(进程在窗口内自行退出),吞掉不崩不重试
214
- await vi.advanceTimersByTimeAsync(30_000);
215
- expect(kills).toEqual([{ pid: ALIVE_PID, signal: "SIGTERM" }]);
216
- expect(loggerMock.debug).not.toHaveBeenCalledWith(
217
- expect.stringContaining("SIGTERM to pid"),
218
- );
219
- });
220
- });
@@ -1,269 +0,0 @@
1
- // src/execution/__tests__/descendant-sweep.test.ts
2
- //
3
- // [T2-② / P-T2b 主路径] 后代级联补杀 sweep + session-pending 差集清单导出。
4
- //
5
- // 设计:docs/design/subagent-core-unbounded-wait-audit.md §7.2 T2-②;P-T2b 裁决
6
- //(probe/p-t2b-report.md):pi SIGTERM 不级联孤儿后台后代(NO-CASCADE 三次稳定复现),
7
- // 补杀为主路径。覆盖:
8
- // - listActivePendingFromSessionFile:register−unregister 差集、sessionId 提取、
9
- // 与 count 口径共享增量游标(交错调用不错位)。
10
- // - sweepDescendantsOfSession:迭代展开至叶、pid 存活校验、cmdline(pi/--mode rpc)
11
- // 防误杀校验、反查失败 skip(T5 marker fallback TODO 锚点)。
12
- // - looksLikePiRpcProcess:命中 / 拒绝形态矩阵。
13
- // - killPidWithEscalation:SIGTERM 后 30s 仍活升级 SIGKILL(fake timers)。
14
- //
15
- // 真实 fs(临时目录)+ mock process.kill / spawnSync——session-pending 增量游标与
16
- // findSessionFileByHeaderId 的文件形态语义被真实执行。
17
-
18
- import { spawnSync } from "node:child_process";
19
- import * as fs from "node:fs";
20
- import * as os from "node:os";
21
- import * as path from "node:path";
22
-
23
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
24
-
25
- // 只 mock spawnSync(ps 探测受控);spawn 等其余实现保留 actual(本文件不经 runSpawn)。
26
- vi.mock("node:child_process", async () => {
27
- const actual = await import("node:child_process");
28
- return {
29
- ...actual,
30
- spawnSync: vi.fn(),
31
- };
32
- });
33
-
34
- import {
35
- looksLikePiRpcProcess,
36
- sweepDescendantsOfSession,
37
- } from "../engine/engines/pi/session-runner.ts";
38
- import {
39
- clearPendingCursors,
40
- listActivePendingFromSessionFile,
41
- readActivePendingFromSessionFile,
42
- } from "../session-pending.ts";
43
- import { writeAliveMarker } from "../alive-store.ts";
44
-
45
- const mockSpawnSync = vi.mocked(spawnSync);
46
-
47
- const ALIVE_PID_CHILD = 424_242;
48
- const ALIVE_PID_GRAND = 424_243;
49
- const DEAD_PID = 999_999;
50
-
51
- /** process.kill 受控:signal=0 探活(死 pid 抛 ESRCH),其余记录到 kills。 */
52
- const kills: Array<{ pid: number; signal: string | number }> = [];
53
-
54
- function entryLine(customType: string, data: Record<string, unknown>): string {
55
- return `${JSON.stringify({
56
- type: "custom",
57
- customType,
58
- data,
59
- timestamp: "2026-09-01T00:00:00.000Z",
60
- id: `e-${Math.random().toString(36).slice(2)}`,
61
- })}\n`;
62
- }
63
-
64
- function registerData(id: string, sessionId: string): Record<string, unknown> {
65
- return { id, type: "session", name: `desc-${id}`, status: "active", registeredAt: 1, expiresAt: undefined, sessionId };
66
- }
67
-
68
- let sessionDir = "";
69
-
70
- beforeEach(() => {
71
- clearPendingCursors();
72
- kills.length = 0;
73
- mockSpawnSync.mockReset();
74
- sessionDir = fs.mkdtempSync(path.join(os.tmpdir(), "desc-sweep-"));
75
- vi.spyOn(process, "kill").mockImplementation(((pid: number, signal?: string | number) => {
76
- if ((signal ?? 0) === 0) {
77
- if (pid === DEAD_PID) {
78
- const err = new Error("No such process") as NodeJS.ErrnoException;
79
- err.code = "ESRCH";
80
- throw err;
81
- }
82
- return true;
83
- }
84
- kills.push({ pid, signal: signal as string | number });
85
- return true;
86
- }) as typeof process.kill);
87
- });
88
-
89
- afterEach(() => {
90
- vi.restoreAllMocks();
91
- clearPendingCursors();
92
- fs.rmSync(sessionDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
93
- });
94
-
95
- /** 标准三层树:root(层主)→ child-sess → grand-sess(叶)。 */
96
- function writeThreeLevelTree(): { rootFile: string; childFile: string; grandFile: string } {
97
- const rootFile = path.join(sessionDir, "20260901T000000-000_root-sess.jsonl");
98
- const childFile = path.join(sessionDir, "20260901T000001-000_child-sess.jsonl");
99
- const grandFile = path.join(sessionDir, "20260901T000002-000_grand-sess.jsonl");
100
- // 层主:注册了 child(未 unregister)
101
- fs.writeFileSync(rootFile, entryLine("pending:register", registerData("bg-1", "child-sess")));
102
- // child:注册了 grand(未 unregister)——sweep 须迭代至叶
103
- fs.writeFileSync(childFile, entryLine("pending:register", registerData("bg-2", "grand-sess")));
104
- // grand:叶,无 pending
105
- fs.writeFileSync(grandFile, "other entry line\n");
106
- // .alive sidecar:pid 线索来源
107
- writeAliveMarker(childFile, { pid: ALIVE_PID_CHILD, id: "child-sess", startedAt: Date.now() });
108
- writeAliveMarker(grandFile, { pid: ALIVE_PID_GRAND, id: "grand-sess", startedAt: Date.now() });
109
- return { rootFile, childFile, grandFile };
110
- }
111
-
112
- /** ps -p <pid> -o command= 的完整 SpawnSyncReturns 形态(测试桩用,字段补齐省 as 链)。 */
113
- function psResult(stdout: string): ReturnType<typeof spawnSync> {
114
- return {
115
- pid: 0,
116
- output: [null, stdout, ""],
117
- stdout,
118
- stderr: "",
119
- status: 0,
120
- signal: null,
121
- } as ReturnType<typeof spawnSync>;
122
- }
123
-
124
- /** ps 探测默认桩:全部存活 pid 返回 pi rpc 形态。 */
125
- function stubCmdlineByPid(): void {
126
- mockSpawnSync.mockImplementation((_cmd: string, args?: readonly string[]) => {
127
- const pid = Number(args?.[1]);
128
- return psResult(`node /usr/local/bin/pi --mode rpc --no-extensions --session-dir /tmp/sess-${pid}\n`);
129
- });
130
- }
131
-
132
- describe("[T2-②] listActivePendingFromSessionFile(差集清单)", () => {
133
- it("register−unregister 差集 + sessionId/type 提取", () => {
134
- const f = path.join(sessionDir, "a.jsonl");
135
- fs.writeFileSync(
136
- f,
137
- entryLine("pending:register", registerData("bg-1", "sess-1")) +
138
- entryLine("pending:register", registerData("bg-2", "sess-2")) +
139
- entryLine("pending:unregister", { id: "bg-1" }),
140
- );
141
- const r = listActivePendingFromSessionFile(f);
142
- expect(r.error).toBeUndefined();
143
- expect(r.items).toHaveLength(1);
144
- expect(r.items[0]).toMatchObject({ id: "bg-2", sessionId: "sess-2", type: "session" });
145
- });
146
-
147
- it("count 与 list 交错调用共享增量游标(结果一致、不丢条目)", () => {
148
- const f = path.join(sessionDir, "b.jsonl");
149
- fs.writeFileSync(f, entryLine("pending:register", registerData("bg-1", "sess-1")));
150
- // 先 count(建立游标),后 append 再 list——增量读入新行
151
- const c1 = readActivePendingFromSessionFile(f);
152
- expect(c1.count).toBe(0); // 端口缺席时缺省 0(core notify-ports 默认实现)
153
- fs.appendFileSync(f, entryLine("pending:register", registerData("bg-2", "sess-2")));
154
- const r = listActivePendingFromSessionFile(f);
155
- expect(r.items.map((i) => i.id).sort()).toEqual(["bg-1", "bg-2"]);
156
- });
157
-
158
- it("sessionFile undefined / 不可读 → error 面空清单", () => {
159
- expect(listActivePendingFromSessionFile(undefined).error).toBeDefined();
160
- expect(listActivePendingFromSessionFile(path.join(sessionDir, "missing.jsonl")).error).toBeDefined();
161
- });
162
- });
163
-
164
- describe("[T2-②] sweepDescendantsOfSession(迭代补杀)", () => {
165
- it("层主→后代→孙迭代展开至叶,双校验通过者逐个 SIGTERM", () => {
166
- const { rootFile } = writeThreeLevelTree();
167
- stubCmdlineByPid();
168
-
169
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "keep-alive watchdog");
170
- expect(r.killed.sort()).toEqual([ALIVE_PID_CHILD, ALIVE_PID_GRAND].sort());
171
- expect(r.skipped).toHaveLength(0);
172
- const sigterms = kills.filter((k) => k.signal === "SIGTERM").map((k) => k.pid);
173
- expect(sigterms.sort()).toEqual([ALIVE_PID_CHILD, ALIVE_PID_GRAND].sort());
174
- });
175
-
176
- it("SIGTERM 后 30s 仍存活 → 升级 SIGKILL(fake timers)", async () => {
177
- vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
178
- const { rootFile } = writeThreeLevelTree();
179
- stubCmdlineByPid();
180
-
181
- sweepDescendantsOfSession(rootFile, sessionDir, "test-escalation");
182
- expect(kills.filter((k) => k.signal === "SIGKILL")).toHaveLength(0);
183
-
184
- await vi.advanceTimersByTimeAsync(30_000);
185
- const sigkills = kills.filter((k) => k.signal === "SIGKILL").map((k) => k.pid);
186
- expect(sigkills.sort()).toEqual([ALIVE_PID_CHILD, ALIVE_PID_GRAND].sort());
187
- });
188
-
189
- it("cmdline 非 pi --mode rpc → pid 复用守卫拦截,不杀(但迭代继续展开其后代)", () => {
190
- const { rootFile, childFile, grandFile } = writeThreeLevelTree();
191
- // 伪造无关进程占住 child 的 pid;grand 正常
192
- mockSpawnSync.mockImplementation((_cmd: string, args?: readonly string[]) => {
193
- const pid = Number(args?.[1]);
194
- return psResult(
195
- pid === ALIVE_PID_CHILD ? "vim notes.txt\n" : "pi --mode rpc\n",
196
- );
197
- });
198
- void childFile;
199
- void grandFile;
200
-
201
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-guard");
202
- expect(r.killed).toEqual([ALIVE_PID_GRAND]); // child 被拦,grand 不受影响
203
- expect(r.skipped).toHaveLength(1);
204
- expect(r.skipped[0]).toMatchObject({ sessionId: "child-sess", pid: ALIVE_PID_CHILD });
205
- expect(r.skipped[0].reason).toContain("pid reuse guard");
206
- expect(kills.map((k) => k.pid)).toEqual([ALIVE_PID_GRAND]);
207
- });
208
-
209
- it("存活校验不过(pid 已死)→ skip 不杀", () => {
210
- const { rootFile, childFile } = writeThreeLevelTree();
211
- // child 的 marker 指向死 pid
212
- writeAliveMarker(childFile, { pid: DEAD_PID, id: "child-sess", startedAt: Date.now() });
213
- stubCmdlineByPid();
214
-
215
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-dead");
216
- expect(r.killed).toEqual([ALIVE_PID_GRAND]);
217
- expect(r.skipped[0]).toMatchObject({ pid: DEAD_PID, reason: expect.stringContaining("not alive") });
218
- });
219
-
220
- it("sessionId 反查失败 / 无 alive marker → skip 留 T5 锚点原因,不中断其余分支", () => {
221
- const rootFile = path.join(sessionDir, "20260901T000010-000_root2.jsonl");
222
- const childFile = path.join(sessionDir, "20260901T000011-000_naked-sess.jsonl");
223
- // 两条 register:missing-sess 反查不到;naked-sess 有文件但无 .alive marker
224
- fs.writeFileSync(
225
- rootFile,
226
- entryLine("pending:register", registerData("bg-m", "missing-sess")) +
227
- entryLine("pending:register", { id: "bg-n", type: "session", name: "naked", status: "active", registeredAt: 1, expiresAt: undefined, sessionId: "naked-sess" }),
228
- );
229
- fs.writeFileSync(childFile, "");
230
-
231
- const r = sweepDescendantsOfSession(rootFile, sessionDir, "test-skip");
232
- expect(r.killed).toHaveLength(0);
233
- expect(r.skipped).toHaveLength(2);
234
- const reasons = r.skipped.map((s) => s.reason).join(" | ");
235
- expect(reasons).toContain("not found in sessionDir");
236
- expect(reasons).toContain("pending T5");
237
- expect(reasons).toContain("no alive marker");
238
- });
239
-
240
- it("rootSessionFile undefined → 空 result(无层主快照不扫)", () => {
241
- stubCmdlineByPid();
242
- const r = sweepDescendantsOfSession(undefined, sessionDir, "test-empty");
243
- expect(r.killed).toHaveLength(0);
244
- expect(r.skipped).toHaveLength(0);
245
- expect(kills).toHaveLength(0);
246
- });
247
- });
248
-
249
- describe("[T2-②] looksLikePiRpcProcess(pid 复用防误杀校验)", () => {
250
- it.each([
251
- ["pi --mode rpc --no-extensions --session-dir /tmp/x", true],
252
- ["node /usr/local/bin/pi --mode rpc --session-dir /tmp/x", true],
253
- ["/opt/pi/bin/pi --mode=rpc", true],
254
- ["pi.js --mode rpc", true],
255
- ])("命中 pi rpc 形态: %s", (cmdline, expected) => {
256
- expect(looksLikePiRpcProcess(cmdline)).toBe(expected);
257
- });
258
-
259
- it.each([
260
- ["vim notes.txt"],
261
- ["nginx: master process"],
262
- ["tail -f /dev/null"],
263
- ["node server.js --mode rpc"], // 有 --mode rpc 但命令不是 pi
264
- ["pi --mode json"], // pi 但非 rpc
265
- ["api --mode rpc"], // 含 "pi" 子串但非 pi 词形
266
- ])("拒绝无关形态: %s", (cmdline) => {
267
- expect(looksLikePiRpcProcess(cmdline)).toBe(false);
268
- });
269
- });