@adhdev/daemon-core 0.9.82-rc.45 → 0.9.82-rc.450

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 (427) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +9 -0
  2. package/dist/boot/process-hardening.d.ts +50 -0
  3. package/dist/build-info.d.ts +37 -0
  4. package/dist/chat/source-machine.d.ts +166 -0
  5. package/dist/chat/source-resolver.d.ts +104 -0
  6. package/dist/chat/subscription-updates.d.ts +1 -0
  7. package/dist/cli-adapter-types.d.ts +68 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +200 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +126 -64
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +5 -0
  12. package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
  13. package/dist/cli-adapters/provider-cli-shared.d.ts +74 -0
  14. package/dist/cli-adapters/pty-write-chunking.d.ts +34 -0
  15. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  16. package/dist/cli-adapters/resolve-executable.d.ts +69 -0
  17. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  18. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  19. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  20. package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
  21. package/dist/commands/chat-commands-read.d.ts +7 -0
  22. package/dist/commands/chat-commands-scope.d.ts +39 -0
  23. package/dist/commands/chat-commands-shared.d.ts +33 -0
  24. package/dist/commands/chat-commands-write.d.ts +14 -0
  25. package/dist/commands/chat-commands.d.ts +10 -23
  26. package/dist/commands/cli-manager.d.ts +25 -1
  27. package/dist/commands/handler.d.ts +125 -0
  28. package/dist/commands/high-family/index.d.ts +3 -0
  29. package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
  30. package/dist/commands/high-family/mesh-events.d.ts +2 -0
  31. package/dist/commands/high-family/mesh-status.d.ts +2 -0
  32. package/dist/commands/high-family/types.d.ts +64 -0
  33. package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
  34. package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
  35. package/dist/commands/low-family/diagnostics.d.ts +2 -0
  36. package/dist/commands/low-family/index.d.ts +3 -0
  37. package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
  38. package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
  39. package/dist/commands/low-family/notification.d.ts +2 -0
  40. package/dist/commands/low-family/refine-config.d.ts +2 -0
  41. package/dist/commands/low-family/session-host.d.ts +2 -0
  42. package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
  43. package/dist/commands/low-family/status-meta.d.ts +2 -0
  44. package/dist/commands/low-family/types.d.ts +33 -0
  45. package/dist/commands/med-family/cli-agent.d.ts +2 -0
  46. package/dist/commands/med-family/fast-forward.d.ts +2 -0
  47. package/dist/commands/med-family/ide.d.ts +10 -0
  48. package/dist/commands/med-family/index.d.ts +3 -0
  49. package/dist/commands/med-family/mesh-crud.d.ts +29 -0
  50. package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
  51. package/dist/commands/med-family/mesh-queue.d.ts +2 -0
  52. package/dist/commands/med-family/mesh-restart.d.ts +2 -0
  53. package/dist/commands/med-family/types.d.ts +152 -0
  54. package/dist/commands/mesh-coordinator.d.ts +85 -1
  55. package/dist/commands/router.d.ts +279 -2
  56. package/dist/commands/upgrade-helper.d.ts +41 -1
  57. package/dist/config/chat-history.d.ts +9 -0
  58. package/dist/config/config.d.ts +5 -0
  59. package/dist/config/mesh-config.d.ts +129 -1
  60. package/dist/config/mesh-json-config.d.ts +199 -0
  61. package/dist/config/repo-settings.d.ts +77 -0
  62. package/dist/daemon/dev-server.d.ts +0 -2
  63. package/dist/detection/ide-detector.d.ts +13 -0
  64. package/dist/detection/win32-ide-version.d.ts +37 -0
  65. package/dist/git/change-impact-config.d.ts +159 -0
  66. package/dist/git/git-commands.d.ts +12 -1
  67. package/dist/git/git-diff.d.ts +6 -0
  68. package/dist/git/git-executor.d.ts +11 -0
  69. package/dist/git/git-status.d.ts +57 -0
  70. package/dist/git/git-types.d.ts +2 -50
  71. package/dist/git/git-worktree.d.ts +71 -1
  72. package/dist/git/index.d.ts +3 -1
  73. package/dist/index.d.ts +66 -14
  74. package/dist/index.js +48475 -17084
  75. package/dist/index.js.map +1 -1
  76. package/dist/index.mjs +49521 -18300
  77. package/dist/index.mjs.map +1 -1
  78. package/dist/installer.d.ts +1 -4
  79. package/dist/ipc/local-ipc-server.d.ts +91 -0
  80. package/dist/launch.d.ts +1 -1
  81. package/dist/logging/async-batch-writer.d.ts +10 -0
  82. package/dist/logging/log-redactor.d.ts +24 -0
  83. package/dist/logging/log-tail-reader.d.ts +81 -0
  84. package/dist/logging/logger.d.ts +1 -1
  85. package/dist/mesh/contracts.d.ts +164 -0
  86. package/dist/mesh/coordinator-prompt.d.ts +89 -0
  87. package/dist/mesh/coordinator-registry.d.ts +59 -0
  88. package/dist/mesh/mesh-active-work.d.ts +174 -0
  89. package/dist/mesh/mesh-clone-grace.d.ts +8 -0
  90. package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
  91. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  92. package/dist/mesh/mesh-event-classify.d.ts +5 -0
  93. package/dist/mesh/mesh-event-forwarding.d.ts +41 -0
  94. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  95. package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
  96. package/dist/mesh/mesh-events-pending.d.ts +69 -0
  97. package/dist/mesh/mesh-events-stale.d.ts +61 -0
  98. package/dist/mesh/mesh-events-utils.d.ts +75 -0
  99. package/dist/mesh/mesh-events.d.ts +6 -49
  100. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  101. package/dist/mesh/mesh-host-ownership.d.ts +29 -0
  102. package/dist/mesh/mesh-init.d.ts +128 -0
  103. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
  104. package/dist/mesh/mesh-ledger.d.ts +115 -1
  105. package/dist/mesh/mesh-magi-status.d.ts +63 -0
  106. package/dist/mesh/mesh-missions.d.ts +189 -0
  107. package/dist/mesh/mesh-node-identity.d.ts +306 -0
  108. package/dist/mesh/mesh-queue-assignment.d.ts +113 -0
  109. package/dist/mesh/mesh-reconcile-loop.d.ts +79 -0
  110. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  111. package/dist/mesh/mesh-refine-gates.d.ts +428 -0
  112. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  113. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  114. package/dist/mesh/mesh-routing.d.ts +70 -0
  115. package/dist/mesh/mesh-runtime-store.d.ts +450 -0
  116. package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
  117. package/dist/mesh/mesh-task-inflight.d.ts +46 -0
  118. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  119. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  120. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  121. package/dist/mesh/mesh-work-queue.d.ts +300 -5
  122. package/dist/mesh/preview-freshness.d.ts +18 -0
  123. package/dist/mesh/refine-config.d.ts +216 -0
  124. package/dist/mesh/worktree-bootstrap-config.d.ts +145 -0
  125. package/dist/providers/acp-provider-instance.d.ts +5 -0
  126. package/dist/providers/approval-utils.d.ts +20 -0
  127. package/dist/providers/chat-message-normalization.d.ts +32 -1
  128. package/dist/providers/cli-provider-instance.d.ts +254 -3
  129. package/dist/providers/contracts.d.ts +149 -6
  130. package/dist/providers/external-sources.d.ts +71 -0
  131. package/dist/providers/manual-attendance.d.ts +63 -0
  132. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +126 -0
  133. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  134. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  135. package/dist/providers/native-history/constants.d.ts +12 -0
  136. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  137. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  138. package/dist/providers/native-history/index.d.ts +13 -0
  139. package/dist/providers/provider-instance-manager.d.ts +29 -0
  140. package/dist/providers/provider-instance.d.ts +23 -1
  141. package/dist/providers/provider-loader.d.ts +26 -4
  142. package/dist/providers/provider-trust.d.ts +31 -0
  143. package/dist/providers/read-chat-contract.d.ts +29 -0
  144. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  145. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  146. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  147. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  148. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  149. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  150. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  151. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  152. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  153. package/dist/providers/sdk/v1/index.d.ts +30 -0
  154. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  155. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  156. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  157. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  158. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  159. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  160. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  161. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  162. package/dist/providers/spec/adapter.d.ts +98 -0
  163. package/dist/providers/spec/cli-adapter.d.ts +223 -0
  164. package/dist/providers/spec/evaluator.d.ts +45 -0
  165. package/dist/providers/spec/fsm-driver.d.ts +444 -0
  166. package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
  167. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  168. package/dist/providers/spec/fsm-types.d.ts +202 -0
  169. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  170. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  171. package/dist/providers/spec/route.d.ts +4 -0
  172. package/dist/providers/spec/types.d.ts +222 -0
  173. package/dist/providers/status-monitor.d.ts +7 -7
  174. package/dist/providers/transcript-v2.d.ts +176 -0
  175. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  176. package/dist/providers/working-dir.d.ts +17 -0
  177. package/dist/repo-mesh-types.d.ts +519 -13
  178. package/dist/runtime-defaults.d.ts +2 -0
  179. package/dist/session-host/managed-host.d.ts +64 -0
  180. package/dist/sessions/registry.d.ts +6 -0
  181. package/dist/shared-types-extra.d.ts +2 -4
  182. package/dist/shared-types.d.ts +59 -2
  183. package/dist/status/normalize.d.ts +1 -1
  184. package/dist/status/normalize.js +1 -0
  185. package/dist/status/normalize.js.map +1 -1
  186. package/dist/status/normalize.mjs +1 -0
  187. package/dist/status/normalize.mjs.map +1 -1
  188. package/dist/status/reporter.d.ts +2 -0
  189. package/dist/status/snapshot.d.ts +26 -0
  190. package/dist/system/hash.d.ts +8 -0
  191. package/dist/system/load-better-sqlite3.d.ts +21 -0
  192. package/dist/types.d.ts +5 -0
  193. package/package.json +7 -3
  194. package/src/agent-stream/poller.ts +2 -3
  195. package/src/agent-stream/provider-adapter.ts +1 -1
  196. package/src/boot/daemon-lifecycle.ts +63 -12
  197. package/src/boot/process-hardening.ts +89 -0
  198. package/src/build-info.ts +73 -0
  199. package/src/chat/source-machine.ts +534 -0
  200. package/src/chat/source-resolver.ts +0 -0
  201. package/src/chat/subscription-updates.ts +20 -1
  202. package/src/cli-adapter-types.d.ts +3 -1
  203. package/src/cli-adapter-types.ts +68 -2
  204. package/src/cli-adapters/cli-script-runner.ts +421 -0
  205. package/src/cli-adapters/cli-state-engine.ts +1246 -0
  206. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  207. package/src/cli-adapters/provider-cli-adapter.ts +914 -1144
  208. package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
  209. package/src/cli-adapters/provider-cli-parse.ts +19 -0
  210. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  211. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  212. package/src/cli-adapters/provider-cli-shared.ts +121 -11
  213. package/src/cli-adapters/pty-transport.ts +2 -1
  214. package/src/cli-adapters/pty-write-chunking.ts +106 -0
  215. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  216. package/src/cli-adapters/resolve-executable.ts +204 -0
  217. package/src/cli-adapters/session-host-transport.ts +2 -1
  218. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
  219. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  220. package/src/cli-adapters/terminal-screen.ts +16 -81
  221. package/src/commands/WINDOWS-UPGRADE-LOCK-FAILURE.md +198 -0
  222. package/src/commands/chat-commands-debug-bundle.ts +398 -0
  223. package/src/commands/chat-commands-read.ts +2488 -0
  224. package/src/commands/chat-commands-scope.ts +54 -0
  225. package/src/commands/chat-commands-shared.ts +114 -0
  226. package/src/commands/chat-commands-write.ts +891 -0
  227. package/src/commands/chat-commands.ts +19 -1841
  228. package/src/commands/cli-manager.ts +596 -27
  229. package/src/commands/handler.ts +841 -2
  230. package/src/commands/high-family/index.ts +28 -0
  231. package/src/commands/high-family/mesh-coordinator-launch.ts +680 -0
  232. package/src/commands/high-family/mesh-events.ts +89 -0
  233. package/src/commands/high-family/mesh-status.ts +822 -0
  234. package/src/commands/high-family/types.ts +80 -0
  235. package/src/commands/low-family/coordinator-prompt.ts +72 -0
  236. package/src/commands/low-family/daemon-lifecycle.ts +107 -0
  237. package/src/commands/low-family/diagnostics.ts +57 -0
  238. package/src/commands/low-family/index.ts +37 -0
  239. package/src/commands/low-family/mesh-ledger.ts +62 -0
  240. package/src/commands/low-family/mesh-node-logs.ts +87 -0
  241. package/src/commands/low-family/notification.ts +116 -0
  242. package/src/commands/low-family/refine-config.ts +106 -0
  243. package/src/commands/low-family/session-host.ts +274 -0
  244. package/src/commands/low-family/spec-providerdev.ts +217 -0
  245. package/src/commands/low-family/status-meta.ts +112 -0
  246. package/src/commands/low-family/types.ts +39 -0
  247. package/src/commands/med-family/cli-agent.ts +238 -0
  248. package/src/commands/med-family/fast-forward.ts +230 -0
  249. package/src/commands/med-family/ide.ts +163 -0
  250. package/src/commands/med-family/index.ts +37 -0
  251. package/src/commands/med-family/mesh-crud.ts +1253 -0
  252. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  253. package/src/commands/med-family/mesh-queue.ts +167 -0
  254. package/src/commands/med-family/mesh-restart.ts +92 -0
  255. package/src/commands/med-family/types.ts +153 -0
  256. package/src/commands/mesh-coordinator.ts +334 -124
  257. package/src/commands/router.ts +2893 -3536
  258. package/src/commands/stream-commands.ts +8 -0
  259. package/src/commands/upgrade-helper.ts +310 -45
  260. package/src/config/chat-history.ts +493 -24
  261. package/src/config/config.ts +12 -0
  262. package/src/config/mesh-config.ts +619 -23
  263. package/src/config/mesh-json-config.ts +376 -0
  264. package/src/config/recent-activity.ts +8 -2
  265. package/src/config/repo-settings.ts +111 -0
  266. package/src/daemon/dev-auto-implement.ts +3 -2
  267. package/src/daemon/dev-cli-debug.ts +10 -1
  268. package/src/daemon/dev-server.ts +0 -541
  269. package/src/detection/cli-detector.ts +28 -9
  270. package/src/detection/ide-detector.ts +55 -16
  271. package/src/detection/win32-ide-version.ts +106 -0
  272. package/src/git/change-impact-config.ts +354 -0
  273. package/src/git/git-commands.ts +78 -15
  274. package/src/git/git-diff.ts +81 -11
  275. package/src/git/git-executor.ts +12 -0
  276. package/src/git/git-status.ts +767 -48
  277. package/src/git/git-types.ts +14 -62
  278. package/src/git/git-worktree.ts +261 -4
  279. package/src/git/index.ts +17 -0
  280. package/src/index.ts +198 -12
  281. package/src/installer.d.ts +1 -1
  282. package/src/installer.ts +8 -6
  283. package/src/ipc/local-ipc-server.ts +278 -0
  284. package/src/launch.d.ts +1 -1
  285. package/src/launch.ts +37 -28
  286. package/src/logging/async-batch-writer.ts +55 -0
  287. package/src/logging/command-log.ts +7 -5
  288. package/src/logging/log-redactor.ts +100 -0
  289. package/src/logging/log-tail-reader.ts +341 -0
  290. package/src/logging/logger.ts +14 -7
  291. package/src/mesh/contracts.ts +338 -0
  292. package/src/mesh/coordinator-prompt.ts +416 -34
  293. package/src/mesh/coordinator-registry.ts +121 -0
  294. package/src/mesh/mesh-active-work.ts +645 -0
  295. package/src/mesh/mesh-clone-grace.ts +68 -0
  296. package/src/mesh/mesh-coordinator-config.ts +97 -0
  297. package/src/mesh/mesh-delivery-policy.ts +315 -0
  298. package/src/mesh/mesh-event-classify.ts +51 -0
  299. package/src/mesh/mesh-event-forwarding.ts +1897 -0
  300. package/src/mesh/mesh-event-trace.ts +67 -0
  301. package/src/mesh/mesh-events-coordinator.ts +32 -0
  302. package/src/mesh/mesh-events-pending.ts +656 -0
  303. package/src/mesh/mesh-events-stale.ts +389 -0
  304. package/src/mesh/mesh-events-utils.ts +443 -0
  305. package/src/mesh/mesh-events.ts +33 -1035
  306. package/src/mesh/mesh-fast-forward.ts +843 -0
  307. package/src/mesh/mesh-host-ownership.ts +111 -0
  308. package/src/mesh/mesh-init.ts +350 -0
  309. package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
  310. package/src/mesh/mesh-ledger.ts +841 -102
  311. package/src/mesh/mesh-magi-status.ts +223 -0
  312. package/src/mesh/mesh-missions.ts +449 -0
  313. package/src/mesh/mesh-node-identity.ts +1985 -0
  314. package/src/mesh/mesh-queue-assignment.ts +1924 -0
  315. package/src/mesh/mesh-reconcile-loop.ts +2018 -0
  316. package/src/mesh/mesh-refine-batch.ts +205 -0
  317. package/src/mesh/mesh-refine-gates.ts +1673 -0
  318. package/src/mesh/mesh-refine-status.ts +231 -0
  319. package/src/mesh/mesh-review-inbox.ts +307 -0
  320. package/src/mesh/mesh-routing.ts +291 -0
  321. package/src/mesh/mesh-runtime-store.ts +1853 -0
  322. package/src/mesh/mesh-scheduling-runtime.ts +198 -0
  323. package/src/mesh/mesh-task-inflight.ts +70 -0
  324. package/src/mesh/mesh-task-stats.ts +161 -0
  325. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  326. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  327. package/src/mesh/mesh-work-queue.ts +1254 -141
  328. package/src/mesh/preview-freshness.ts +118 -0
  329. package/src/mesh/refine-config.ts +423 -0
  330. package/src/mesh/worktree-bootstrap-config.ts +450 -0
  331. package/src/providers/acp-provider-instance.ts +43 -10
  332. package/src/providers/approval-utils.d.ts +5 -0
  333. package/src/providers/approval-utils.ts +57 -5
  334. package/src/providers/chat-message-normalization.ts +92 -4
  335. package/src/providers/cli-provider-instance.ts +2177 -107
  336. package/src/providers/contracts.d.ts +55 -0
  337. package/src/providers/contracts.ts +160 -6
  338. package/src/providers/extension-provider-instance.ts +12 -7
  339. package/src/providers/external-sources.ts +218 -0
  340. package/src/providers/ide-provider-instance.ts +35 -12
  341. package/src/providers/manual-attendance.ts +85 -0
  342. package/src/providers/native-history/antigravity-cli-transcript.ts +1043 -0
  343. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  344. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  345. package/src/providers/native-history/constants.ts +19 -0
  346. package/src/providers/native-history/dispatcher.ts +373 -0
  347. package/src/providers/native-history/hermes-cli-transcript.ts +260 -0
  348. package/src/providers/native-history/index.ts +30 -0
  349. package/src/providers/provider-instance-manager.ts +71 -0
  350. package/src/providers/provider-instance.ts +19 -1
  351. package/src/providers/provider-loader.ts +668 -50
  352. package/src/providers/provider-schema.ts +87 -14
  353. package/src/providers/provider-trust.ts +114 -0
  354. package/src/providers/read-chat-contract.ts +76 -16
  355. package/src/providers/sdk/README.md +49 -0
  356. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  357. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  358. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  359. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  360. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  361. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  362. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  363. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  364. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  365. package/src/providers/sdk/v1/index.ts +152 -0
  366. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  367. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  368. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  369. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +509 -0
  370. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  371. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  372. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  373. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  374. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  375. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  376. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  377. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  378. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  379. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  380. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  381. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  382. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  383. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  384. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  385. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  386. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  387. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  388. package/src/providers/sdk/v1/validators/index.ts +19 -0
  389. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  390. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  391. package/src/providers/spec/adapter.ts +246 -0
  392. package/src/providers/spec/cli-adapter.ts +1064 -0
  393. package/src/providers/spec/evaluator.ts +407 -0
  394. package/src/providers/spec/fsm-driver.ts +1481 -0
  395. package/src/providers/spec/fsm-evaluator.ts +290 -0
  396. package/src/providers/spec/fsm-loader.ts +128 -0
  397. package/src/providers/spec/fsm-types.ts +301 -0
  398. package/src/providers/spec/native-history-executor.ts +1174 -0
  399. package/src/providers/spec/pre-launch-trust.ts +104 -0
  400. package/src/providers/spec/route.ts +51 -0
  401. package/src/providers/spec/types.ts +262 -0
  402. package/src/providers/status-monitor.d.ts +7 -7
  403. package/src/providers/status-monitor.ts +37 -22
  404. package/src/providers/transcript-v2.ts +567 -0
  405. package/src/providers/types/interactive-prompt.ts +536 -0
  406. package/src/providers/version-archive.ts +64 -24
  407. package/src/providers/working-dir.ts +23 -0
  408. package/src/repo-mesh-types.ts +758 -14
  409. package/src/runtime-defaults.ts +39 -0
  410. package/src/session-host/managed-host.ts +218 -0
  411. package/src/sessions/registry.ts +6 -0
  412. package/src/shared-types-extra.ts +2 -4
  413. package/src/shared-types.d.ts +8 -0
  414. package/src/shared-types.ts +64 -1
  415. package/src/status/builders.ts +26 -6
  416. package/src/status/normalize.ts +2 -0
  417. package/src/status/reporter.ts +19 -1
  418. package/src/status/snapshot.ts +95 -26
  419. package/src/system/hash.ts +23 -0
  420. package/src/system/host-memory.ts +29 -12
  421. package/src/system/load-better-sqlite3.ts +68 -0
  422. package/src/types.ts +5 -0
  423. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  424. package/dist/mesh/mesh-sync.d.ts +0 -53
  425. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  426. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  427. package/src/mesh/mesh-sync.ts +0 -111
@@ -245,6 +245,14 @@ export function normalizeProviderScriptArgs(args: any, scriptName?: string): Rec
245
245
  function buildControlScriptResult(scriptName: string, payload: any): Record<string, unknown> {
246
246
  if (!payload || typeof payload !== 'object') return {};
247
247
 
248
+ // The spec-driven control adapter (open_picker LIST/SELECT) already
249
+ // produced a structured controlResult by parsing the live screen. Honour
250
+ // it verbatim instead of re-deriving one from legacy payload shapes —
251
+ // otherwise the screen-parsed options/currentValue get clobbered.
252
+ if (payload.controlResult && typeof payload.controlResult === 'object') {
253
+ return { controlResult: payload.controlResult };
254
+ }
255
+
248
256
  const legacyListPayload = (() => {
249
257
  if (Array.isArray(payload.options)) return payload;
250
258
  if (/^listmodels$/i.test(scriptName) && Array.isArray(payload.models)) {
@@ -169,6 +169,43 @@ export function buildPinnedGlobalInstallCommand(options: {
169
169
  };
170
170
  }
171
171
 
172
+ /**
173
+ * Build an env for the `npm install` child whose PATH is prefixed with the
174
+ * directory of the node binary currently running this helper.
175
+ *
176
+ * npm runs lifecycle scripts (e.g. adhdev's `preinstall` Node-version guard) by
177
+ * spawning a bare `node`, which resolves from PATH — NOT from the node that runs
178
+ * npm. On Windows a machine can have several node installs (e.g. a standalone
179
+ * `C:\Program Files\nodejs` ahead of an nvm-managed node on PATH). Without this,
180
+ * the guard sees the wrong (unsupported) node version and aborts the upgrade,
181
+ * even though npm/adhdev actually run under a supported node. Pinning the
182
+ * running node's dir to the front of PATH makes lifecycle scripts use the same
183
+ * node as the install itself.
184
+ */
185
+ function buildInstallEnvWithNodeOnPath(baseEnv: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
186
+ // The Node-version guard this works around only fires on Windows, so scope the
187
+ // PATH rewrite to win32 — POSIX keeps its env untouched.
188
+ if (process.platform !== 'win32') return { ...baseEnv };
189
+ const nodeBinDir = path.dirname(process.execPath);
190
+ if (!nodeBinDir) return { ...baseEnv };
191
+ const env: NodeJS.ProcessEnv = { ...baseEnv };
192
+ // Windows env keys are case-insensitive and conventionally spelled `Path`;
193
+ // prepend to the existing key (whatever its case) to avoid creating a dupe.
194
+ const pathKey = Object.keys(env).find((k) => k.toLowerCase() === 'path') || 'PATH';
195
+ const current = env[pathKey] || '';
196
+ env[pathKey] = current ? `${nodeBinDir};${current}` : nodeBinDir;
197
+ // Belt-and-suspenders for the same Node-version guard: the PATH prepend above
198
+ // only works if the running helper's node is itself a supported version, but a
199
+ // helper launched via an nvm shim (e.g. `C:\nvm4w\nodejs\node.exe`) can resolve
200
+ // to Node 24 even though the real install target node is pinned via `--prefix`.
201
+ // In the AUTOMATIC upgrade path the install target is already pinned/verified,
202
+ // so authorize the lifecycle guard to proceed via the same bootstrap escape
203
+ // hatch the guard already honors. This is scoped to the helper-built env only —
204
+ // it never weakens the guard for a user-run `npm i -g adhdev`.
205
+ env.ADHDEV_BOOTSTRAP = '1';
206
+ return env;
207
+ }
208
+
172
209
  export function getNpmExecOptions(platform: NodeJS.Platform = process.platform): NpmExecOptions {
173
210
  if (platform === 'win32') {
174
211
  return { shell: false, windowsHide: true };
@@ -264,13 +301,14 @@ async function waitForPidExit(pid: number, timeoutMs: number): Promise<void> {
264
301
  }
265
302
  }
266
303
 
267
- export function stopSessionHostProcesses(appName: string): void {
304
+ export async function stopSessionHostProcesses(appName: string): Promise<void> {
268
305
  const pidFile = path.join(os.homedir(), '.adhdev', `${appName}-session-host.pid`);
306
+ let killedPid: number | null = null;
269
307
  try {
270
308
  if (fs.existsSync(pidFile)) {
271
309
  const pid = Number.parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
272
310
  if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
273
- killPid(pid);
311
+ if (killPid(pid)) killedPid = pid;
274
312
  }
275
313
  }
276
314
  } catch {
@@ -282,6 +320,164 @@ export function stopSessionHostProcesses(appName: string): void {
282
320
  // noop
283
321
  }
284
322
  }
323
+
324
+ // The session-host process keeps node-pty's `conpty.node` memory-mapped. On
325
+ // Windows a mapped native addon stays EXCLUSIVELY locked until the process
326
+ // fully exits and tears down the mapping — and that teardown lags `taskkill`
327
+ // by an indeterminate interval. `taskkill` only *requests* termination, so
328
+ // returning immediately lets the caller run `npm install` while conpty.node
329
+ // is still locked, which makes npm's copy-to-staging fail with EBUSY (the
330
+ // intermittent Windows upgrade failure). Wait for the killed process to
331
+ // actually disappear — like we already do for the parent daemon pid — so the
332
+ // file handle is released before the install runs. (POSIX can replace an open
333
+ // file freely, so the wait is harmless there.)
334
+ if (killedPid !== null) {
335
+ await waitForPidExit(killedPid, 15000);
336
+ }
337
+ }
338
+
339
+ // Native addons that stay EXCLUSIVELY locked on Windows while any process keeps
340
+ // them memory-mapped. node-pty's `conpty.node` is the confirmed offender; the
341
+ // ghostty VT dll has the same lifetime, so guard both.
342
+ const LOCKED_NATIVE_ADDON_BASENAMES = ['conpty.node', 'ghostty-vt.dll'];
343
+
344
+ /**
345
+ * Enumerate processes that have a locked native addon (conpty.node /
346
+ * ghostty-vt.dll) of *this* install memory-mapped.
347
+ *
348
+ * `stopSessionHostProcesses()` only knows the single managed session-host pid, so
349
+ * any *foreign* holder — e.g. an orphaned `pty_*probe*.cjs` left in `%TEMP%` — is
350
+ * invisible to it and keeps the addon locked through every install retry, dooming
351
+ * the upgrade with EBUSY. This scans by the module's full path so we only ever
352
+ * target a holder of the exact `packageRoot` being replaced (never an unrelated
353
+ * install's copy). Windows-only — these locks don't exist on POSIX.
354
+ */
355
+ export function listForeignNativeAddonHolders(
356
+ packageRoot: string | null | undefined,
357
+ ): Array<{ pid: number; commandLine: string | null }> {
358
+ if (process.platform !== 'win32' || !packageRoot) return [];
359
+ const rootLower = packageRoot.replace(/\//g, '\\').replace(/'/g, "''").toLowerCase();
360
+ const endsWithChecks = LOCKED_NATIVE_ADDON_BASENAMES
361
+ .map((name) => `$lf.EndsWith('${name}')`)
362
+ .join(' -or ');
363
+ // List pids of node processes whose loaded modules include a locked native
364
+ // addon living UNDER this install's package root. Accessing .Modules for a
365
+ // process we can't open throws — swallow per-process so one inaccessible
366
+ // process doesn't abort the whole scan.
367
+ const script = [
368
+ `$root = '${rootLower}'`,
369
+ `Get-Process node -ErrorAction SilentlyContinue | ForEach-Object {`,
370
+ ` $p = $_`,
371
+ ` try {`,
372
+ ` foreach ($m in $p.Modules) {`,
373
+ ` $fn = $m.FileName`,
374
+ ` if ($fn) {`,
375
+ ` $lf = $fn.ToLower()`,
376
+ ` if ($lf.StartsWith($root) -and (${endsWithChecks})) { $p.Id; break }`,
377
+ ` }`,
378
+ ` }`,
379
+ ` } catch {}`,
380
+ `}`,
381
+ ].join('\n');
382
+
383
+ let out = '';
384
+ try {
385
+ out = String(execFileSync('powershell.exe', [
386
+ '-NoProfile',
387
+ '-NonInteractive',
388
+ '-ExecutionPolicy', 'Bypass',
389
+ '-Command', script,
390
+ ], { encoding: 'utf8', timeout: 8000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true })).trim();
391
+ } catch {
392
+ return [];
393
+ }
394
+
395
+ const selfPid = process.pid;
396
+ const seen = new Set<number>();
397
+ const holders: Array<{ pid: number; commandLine: string | null }> = [];
398
+ for (const line of out.split(/\r?\n/)) {
399
+ const pid = Number.parseInt(line.trim(), 10);
400
+ if (!Number.isFinite(pid) || pid <= 0 || pid === selfPid || seen.has(pid)) continue;
401
+ seen.add(pid);
402
+ holders.push({ pid, commandLine: getProcessCommandLine(pid) });
403
+ }
404
+ return holders;
405
+ }
406
+
407
+ /**
408
+ * Terminate every foreign process holding this install's native addon mapped,
409
+ * then wait for each to actually exit so the mapping is released before npm
410
+ * copies the file into its staging dir. Returns what it found/killed so the
411
+ * caller can surface an actionable recovery message on failure.
412
+ */
413
+ export async function stopForeignNativeAddonHolders(
414
+ packageRoot: string | null | undefined,
415
+ options: { parentPid?: number } = {},
416
+ ): Promise<Array<{ pid: number; commandLine: string | null; killed: boolean }>> {
417
+ if (process.platform !== 'win32' || !packageRoot) return [];
418
+ const parentPid = Number.isFinite(options.parentPid) ? Number(options.parentPid) : -1;
419
+ const holders = listForeignNativeAddonHolders(packageRoot);
420
+ const results: Array<{ pid: number; commandLine: string | null; killed: boolean }> = [];
421
+ for (const holder of holders) {
422
+ // The parent daemon pid is already awaited for exit separately; never
423
+ // double-handle it here.
424
+ if (holder.pid === parentPid) continue;
425
+ appendUpgradeLog(
426
+ `Foreign native-addon holder found: pid ${holder.pid}${holder.commandLine ? ` — ${holder.commandLine}` : ''}`,
427
+ );
428
+ const killed = killPid(holder.pid);
429
+ if (killed) {
430
+ await waitForPidExit(holder.pid, 15000);
431
+ appendUpgradeLog(`Terminated foreign native-addon holder pid ${holder.pid}`);
432
+ } else {
433
+ appendUpgradeLog(`Failed to terminate foreign native-addon holder pid ${holder.pid}`);
434
+ }
435
+ results.push({ ...holder, killed });
436
+ }
437
+ return results;
438
+ }
439
+
440
+ function getUpgradeFailureNoticePath(): string {
441
+ const home = os.homedir();
442
+ const dir = path.join(home, '.adhdev');
443
+ try {
444
+ fs.mkdirSync(dir, { recursive: true });
445
+ } catch {
446
+ // noop — appendUpgradeLog already creates the dir; this is best-effort.
447
+ }
448
+ return path.join(dir, 'daemon-upgrade-last-error.txt');
449
+ }
450
+
451
+ function buildManualRecoveryCommand(installCommand: PinnedGlobalInstallCommand): string {
452
+ return [installCommand.command, ...installCommand.args]
453
+ .map((part) => (/\s/.test(part) ? `"${part}"` : part))
454
+ .join(' ');
455
+ }
456
+
457
+ /**
458
+ * On final failure, leave the user something actionable instead of only a buried
459
+ * log line: the pids/commandlines still holding the lock and a paste-ready
460
+ * recovery command. Written to a stable path the CLI can surface on next boot.
461
+ */
462
+ function emitUpgradeFailureNotice(lines: string[]): void {
463
+ const body = lines.join('\n');
464
+ appendUpgradeLog(`Upgrade blocked — user action required:\n${body}`);
465
+ try {
466
+ fs.writeFileSync(getUpgradeFailureNoticePath(), `[${new Date().toISOString()}]\n${body}\n`, 'utf8');
467
+ } catch {
468
+ // noop
469
+ }
470
+ }
471
+
472
+ // npm copies the current install's files into a staging dir before swapping in
473
+ // the new version. On Windows that copy of `conpty.node` can still race a
474
+ // just-killed session-host whose mapping hasn't been released yet, surfacing as
475
+ // EBUSY/EPERM. Treat those as transient and retry with backoff.
476
+ function isRetriableInstallLockError(error: any): boolean {
477
+ const code = error?.code;
478
+ if (code === 'EBUSY' || code === 'EPERM') return true;
479
+ const text = `${error?.message || ''} ${error?.stderr || ''}`;
480
+ return /\bEBUSY\b|\bEPERM\b|resource busy or locked/i.test(text);
285
481
  }
286
482
 
287
483
  function removeDaemonPidFile(): void {
@@ -293,42 +489,64 @@ function removeDaemonPidFile(): void {
293
489
  }
294
490
  }
295
491
 
296
- function cleanupStaleGlobalInstallDirs(pkgName: string, surface: CurrentGlobalInstallSurface): void {
297
- const prefixArgs = surface.installPrefix ? ['--prefix', surface.installPrefix] : [];
298
- const npmRoot = String(execNpmCommandSync(['root', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
299
- if (!npmRoot) return;
300
- const npmPrefix = surface.installPrefix
301
- || String(execNpmCommandSync(['prefix', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
302
- const binDir = process.platform === 'win32' ? npmPrefix : path.join(npmPrefix, 'bin');
303
- const packageBaseName = pkgName.startsWith('@') ? pkgName.split('/')[1] : pkgName;
304
- const binNames = new Set<string>([packageBaseName]);
305
- if (pkgName === '@adhdev/daemon-standalone') {
306
- binNames.add('adhdev-standalone');
307
- }
308
-
309
- if (pkgName.startsWith('@')) {
310
- const [scope, name] = pkgName.split('/');
311
- const scopeDir = path.join(npmRoot, scope);
312
- if (!fs.existsSync(scopeDir)) return;
313
- for (const entry of fs.readdirSync(scopeDir)) {
314
- if (!entry.startsWith(`.${name}-`)) continue;
315
- fs.rmSync(path.join(scopeDir, entry), { recursive: true, force: true });
316
- appendUpgradeLog(`Removed stale scoped staging dir: ${path.join(scopeDir, entry)}`);
492
+ /**
493
+ * Best-effort removal of a leftover npm staging entry.
494
+ *
495
+ * A stale staging dir can hold a locked native binary — e.g. `ghostty-vt.dll`
496
+ * from `@adhdev/ghostty-vt-node` still mapped by a lingering session-host
497
+ * process which makes `rmSync` throw `EPERM` on Windows. Staging cleanup is
498
+ * only housekeeping: the leftover is inert and npm creates its own fresh
499
+ * staging dir for the real install, so a lock on an old leftover must NOT abort
500
+ * the upgrade. Log and continue instead of letting the error propagate.
501
+ */
502
+ export function safeRemoveStaleEntry(target: string, label: string): void {
503
+ try {
504
+ fs.rmSync(target, { recursive: true, force: true });
505
+ appendUpgradeLog(`${label}: ${target}`);
506
+ } catch (error: any) {
507
+ appendUpgradeLog(`Skipped locked stale entry (${error?.code || 'error'}): ${target} — ${error?.message || String(error)}`);
508
+ }
509
+ }
510
+
511
+ export function cleanupStaleGlobalInstallDirs(pkgName: string, surface: CurrentGlobalInstallSurface): void {
512
+ // The whole routine is housekeeping — never let it throw out and abort the
513
+ // upgrade (npm root/prefix probing or readdir can fail for unrelated reasons).
514
+ try {
515
+ const prefixArgs = surface.installPrefix ? ['--prefix', surface.installPrefix] : [];
516
+ const npmRoot = String(execNpmCommandSync(['root', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
517
+ if (!npmRoot) return;
518
+ const npmPrefix = surface.installPrefix
519
+ || String(execNpmCommandSync(['prefix', '-g', ...prefixArgs], { encoding: 'utf8' }, surface)).trim();
520
+ const binDir = process.platform === 'win32' ? npmPrefix : path.join(npmPrefix, 'bin');
521
+ const packageBaseName = pkgName.startsWith('@') ? pkgName.split('/')[1] : pkgName;
522
+ const binNames = new Set<string>([packageBaseName]);
523
+ if (pkgName === '@adhdev/daemon-standalone') {
524
+ binNames.add('adhdev-standalone');
317
525
  }
318
- } else {
319
- for (const entry of fs.readdirSync(npmRoot)) {
320
- if (!entry.startsWith(`.${pkgName}-`)) continue;
321
- fs.rmSync(path.join(npmRoot, entry), { recursive: true, force: true });
322
- appendUpgradeLog(`Removed stale staging dir: ${path.join(npmRoot, entry)}`);
526
+
527
+ if (pkgName.startsWith('@')) {
528
+ const [scope, name] = pkgName.split('/');
529
+ const scopeDir = path.join(npmRoot, scope);
530
+ if (!fs.existsSync(scopeDir)) return;
531
+ for (const entry of fs.readdirSync(scopeDir)) {
532
+ if (!entry.startsWith(`.${name}-`)) continue;
533
+ safeRemoveStaleEntry(path.join(scopeDir, entry), 'Removed stale scoped staging dir');
534
+ }
535
+ } else {
536
+ for (const entry of fs.readdirSync(npmRoot)) {
537
+ if (!entry.startsWith(`.${pkgName}-`)) continue;
538
+ safeRemoveStaleEntry(path.join(npmRoot, entry), 'Removed stale staging dir');
539
+ }
323
540
  }
324
- }
325
541
 
326
- if (fs.existsSync(binDir)) {
327
- for (const entry of fs.readdirSync(binDir)) {
328
- if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
329
- fs.rmSync(path.join(binDir, entry), { recursive: true, force: true });
330
- appendUpgradeLog(`Removed stale bin staging entry: ${path.join(binDir, entry)}`);
542
+ if (fs.existsSync(binDir)) {
543
+ for (const entry of fs.readdirSync(binDir)) {
544
+ if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
545
+ safeRemoveStaleEntry(path.join(binDir, entry), 'Removed stale bin staging entry');
546
+ }
331
547
  }
548
+ } catch (error: any) {
549
+ appendUpgradeLog(`Stale staging cleanup skipped (${error?.code || 'error'}): ${error?.message || String(error)}`);
332
550
  }
333
551
  }
334
552
 
@@ -362,22 +580,69 @@ async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Prom
362
580
  await waitForPidExit(payload.parentPid, 15000);
363
581
  }
364
582
 
365
- stopSessionHostProcesses(sessionHostAppName);
583
+ await stopSessionHostProcesses(sessionHostAppName);
366
584
  removeDaemonPidFile();
585
+ // Kill any *foreign* process still holding this install's conpty.node mapped
586
+ // (the session-host stop above only covers the single managed pid). Do this
587
+ // BEFORE the staging GC so the just-released file can also be cleaned up now
588
+ // that no process maps it.
589
+ await stopForeignNativeAddonHolders(installCommand.surface.packageRoot, { parentPid: payload.parentPid });
367
590
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
368
591
 
369
592
  const spec = `${payload.packageName}@${payload.targetVersion || 'latest'}`;
370
593
  appendUpgradeLog(`Installing ${spec}`);
371
- const installOutput = execFileSync(
372
- installCommand.command,
373
- installCommand.args,
374
- {
375
- encoding: 'utf8',
376
- stdio: 'pipe',
377
- maxBuffer: 20 * 1024 * 1024,
378
- ...installCommand.execOptions,
379
- },
380
- );
594
+ // Windows can still race a lingering conpty.node mapping even after the
595
+ // session-host exits, so retry the install on transient lock errors there.
596
+ const maxInstallAttempts = process.platform === 'win32' ? 3 : 1;
597
+ let installOutput = '';
598
+ for (let attempt = 1; attempt <= maxInstallAttempts; attempt++) {
599
+ try {
600
+ installOutput = String(execFileSync(
601
+ installCommand.command,
602
+ installCommand.args,
603
+ {
604
+ encoding: 'utf8',
605
+ stdio: 'pipe',
606
+ maxBuffer: 20 * 1024 * 1024,
607
+ env: buildInstallEnvWithNodeOnPath(),
608
+ ...installCommand.execOptions,
609
+ },
610
+ ));
611
+ break;
612
+ } catch (error: any) {
613
+ if (attempt < maxInstallAttempts && isRetriableInstallLockError(error)) {
614
+ appendUpgradeLog(`Install attempt ${attempt} hit a file lock (${error?.code || 'lock'}); clearing holders + staging and retrying after backoff`);
615
+ // Re-run the active cleanup ("정리 → 확인 → 설치") rather than relying on
616
+ // backoff alone: a never-exiting foreign holder won't disappear on its
617
+ // own, so kill it again before the next attempt.
618
+ await stopForeignNativeAddonHolders(installCommand.surface.packageRoot, { parentPid: payload.parentPid });
619
+ cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
620
+ await new Promise((resolve) => setTimeout(resolve, attempt * 1500));
621
+ continue;
622
+ }
623
+ // Out of retries on a lock error: leave the user an actionable recovery
624
+ // notice naming whoever is still holding the native addon locked.
625
+ if (isRetriableInstallLockError(error)) {
626
+ const blockers = listForeignNativeAddonHolders(installCommand.surface.packageRoot);
627
+ const notice: string[] = [
628
+ `adhdev ${spec} could not be installed: a file lock (${error?.code || 'EBUSY/EPERM'}) is blocking the native addon.`,
629
+ ];
630
+ if (blockers.length > 0) {
631
+ notice.push('Processes still holding the lock:');
632
+ for (const b of blockers) {
633
+ notice.push(` pid ${b.pid}${b.commandLine ? ` — ${b.commandLine}` : ''}`);
634
+ }
635
+ notice.push('To recover, stop them and reinstall:');
636
+ notice.push(` Stop-Process -Id ${blockers.map((b) => b.pid).join(',')} -Force`);
637
+ } else {
638
+ notice.push('To recover, reinstall manually:');
639
+ }
640
+ notice.push(` ${buildManualRecoveryCommand(installCommand)}`);
641
+ emitUpgradeFailureNotice(notice);
642
+ }
643
+ throw error;
644
+ }
645
+ }
381
646
  if (installOutput.trim()) {
382
647
  appendUpgradeLog(installOutput.trim());
383
648
  }