@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
@@ -7,11 +7,14 @@
7
7
  * Migrated from @adhdev/core — this is now the single source of truth.
8
8
  */
9
9
 
10
- import { execSync } from 'child_process';
11
- import { existsSync } from 'fs';
10
+ import { exec } from 'child_process';
11
+ import { promisify } from 'util';
12
+ const execAsync = promisify(exec);
13
+ import { existsSync, statSync } from 'fs';
12
14
  import { platform, homedir } from 'os';
13
15
  import * as path from 'path';
14
16
  import type { ProviderLoader } from '../providers/provider-loader.js';
17
+ import { isKnownWin32GuiExe, readWin32IdeVersionFromDisk } from './win32-ide-version.js';
15
18
 
16
19
  // ─── Types ──────────────────────────────────────
17
20
 
@@ -73,25 +76,54 @@ function findCliCommand(command: string): string | null {
73
76
  const resolved = path.isAbsolute(candidate) ? candidate : path.resolve(candidate);
74
77
  return existsSync(resolved) ? resolved : null;
75
78
  }
76
- try {
77
- const result = execSync(
78
- platform() === 'win32' ? `where ${trimmed}` : `which ${trimmed}`,
79
- { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }
80
- ).trim();
81
- return result.split('\n')[0] || null;
82
- } catch {
83
- return null;
79
+ const isWin = platform() === 'win32';
80
+ const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
81
+ const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
82
+ for (const p of paths) {
83
+ if (!p) continue;
84
+ for (const ext of exes) {
85
+ const fullPath = path.join(p, trimmed + ext);
86
+ try {
87
+ if (existsSync(fullPath)) {
88
+ const stat = statSync(fullPath);
89
+ if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
90
+ return fullPath;
91
+ }
92
+ }
93
+ } catch { }
94
+ }
84
95
  }
96
+ return null;
85
97
  }
86
98
 
87
- function getIdeVersion(cliCommand: string): string | null {
99
+ /**
100
+ * Resolve an IDE version on demand (NOT at boot).
101
+ *
102
+ * Order of preference, all spawn-free where possible:
103
+ * 1. win32: read the bundled product.json/package.json next to the exe.
104
+ * 2. Otherwise spawn `<cli> --version` — but ONLY when the binary is not a
105
+ * known GUI executable (the #4 guard), so we never boot an IDE window.
106
+ *
107
+ * `win32ProcessNames` is provider.json `processNames.win32` (type → exe names),
108
+ * used to recognise GUI executables. Callers that have a ProviderLoader can
109
+ * pass `providerLoader.getWinProcessNames()`.
110
+ */
111
+ export async function getIdeVersion(
112
+ cliCommand: string,
113
+ win32ProcessNames: Record<string, string[]> = {},
114
+ ): Promise<string | null> {
115
+ if (platform() === 'win32') {
116
+ const fromDisk = readWin32IdeVersionFromDisk(cliCommand);
117
+ if (fromDisk) return fromDisk;
118
+ // Refuse to spawn a known GUI exe — it would launch the IDE window.
119
+ if (isKnownWin32GuiExe(cliCommand, win32ProcessNames)) return null;
120
+ }
88
121
  try {
89
- const result = execSync(`"${cliCommand}" --version`, {
122
+ const { stdout } = await execAsync(`"${cliCommand}" --version`, {
90
123
  encoding: 'utf-8',
91
124
  timeout: 10000,
92
- stdio: ['pipe', 'pipe', 'pipe'],
93
- }).trim();
94
- return result.split('\n')[0] || null;
125
+ });
126
+ return stdout.trim().split('\n')[0] || null;
95
127
  } catch {
96
128
  return null;
97
129
  }
@@ -152,7 +184,14 @@ export async function detectIDEs(providerLoader?: ProviderLoader): Promise<IDEIn
152
184
  const installed = os === 'darwin'
153
185
  ? !!(resolvedCli || appPath)
154
186
  : !!resolvedCli;
155
- const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
187
+ // Boot-time IDE detection must NOT spawn `<cli> --version`. On Windows
188
+ // the resolved "CLI" is frequently the GUI Electron exe (case-insensitive
189
+ // FS matches `...\cursor\cursor.exe` against `Cursor.exe`), and running it
190
+ // with `--version` boots the IDE window. `installed` is decided purely by
191
+ // existsSync above, and the dashboard drops `version` anyway — the only
192
+ // real version consumer is provider-loader.resolve() at CDP attach time,
193
+ // which fetches the version lazily. So leave it null here.
194
+ const version: string | null = null;
156
195
 
157
196
  results.push({
158
197
  id: def.id,
@@ -0,0 +1,106 @@
1
+ /**
2
+ * ADHDev — Windows IDE version detection (execution-free)
3
+ *
4
+ * On Windows the resolved "CLI" for a VS Code fork (Cursor, Antigravity, …)
5
+ * frequently resolves to the GUI Electron executable itself, because the
6
+ * case-insensitive filesystem matches `...\cursor\cursor.exe` against the
7
+ * real `Cursor.exe`. Running `<that exe> --version` boots the GUI instead of
8
+ * printing a version (Electron ignores the unknown flag and opens a window).
9
+ *
10
+ * To learn the version WITHOUT spawning anything, we read the bundled
11
+ * `product.json` / `package.json` that ship next to the executable. VS Code
12
+ * forks embed their version there. This is a pure filesystem read.
13
+ *
14
+ * It also exposes a guard so any remaining `--version` exec path can refuse to
15
+ * spawn a binary that is a known GUI executable for an IDE provider.
16
+ */
17
+
18
+ import * as fs from 'fs';
19
+ import * as path from 'path';
20
+
21
+ /**
22
+ * Candidate locations for the version manifest relative to the GUI exe dir.
23
+ * VS Code forks place `resources/app/{product,package}.json` next to the exe.
24
+ */
25
+ function manifestCandidates(exeDir: string): string[] {
26
+ return [
27
+ path.join(exeDir, 'resources', 'app', 'product.json'),
28
+ path.join(exeDir, 'resources', 'app', 'package.json'),
29
+ // Some packagings keep product.json one level up.
30
+ path.join(exeDir, 'product.json'),
31
+ ];
32
+ }
33
+
34
+ function parseVersionFromManifest(raw: string): string | null {
35
+ try {
36
+ const json = JSON.parse(raw) as Record<string, unknown>;
37
+ // product.json forks expose the IDE's own version here; package.json
38
+ // exposes the upstream VS Code engine version. Prefer the former.
39
+ const candidate = json.version;
40
+ if (typeof candidate === 'string' && candidate.trim()) {
41
+ return candidate.trim();
42
+ }
43
+ } catch {
44
+ /* not valid JSON — ignore */
45
+ }
46
+ return null;
47
+ }
48
+
49
+ /**
50
+ * Read an IDE version from disk (no process spawn).
51
+ *
52
+ * @param exePath Absolute path to the GUI executable (or any path inside the
53
+ * IDE install dir — we read the manifest relative to its directory).
54
+ * @returns The version string, or null if it could not be determined.
55
+ */
56
+ export function readWin32IdeVersionFromDisk(exePath: string): string | null {
57
+ if (!exePath) return null;
58
+ let exeDir: string;
59
+ try {
60
+ exeDir = fs.statSync(exePath).isDirectory() ? exePath : path.dirname(exePath);
61
+ } catch {
62
+ exeDir = path.dirname(exePath);
63
+ }
64
+ for (const candidate of manifestCandidates(exeDir)) {
65
+ try {
66
+ if (!fs.existsSync(candidate)) continue;
67
+ const version = parseVersionFromManifest(fs.readFileSync(candidate, 'utf-8'));
68
+ if (version) return version;
69
+ } catch {
70
+ /* ignore unreadable manifest */
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+
76
+ /**
77
+ * True when `binPath` resolves to a known GUI executable for some IDE.
78
+ *
79
+ * Used as a safety net: any code path about to run `<bin> --version` must skip
80
+ * the spawn when the binary is actually the GUI Electron exe, since that would
81
+ * launch the IDE window. Comparison is case-insensitive on the basename
82
+ * (Windows filesystem semantics) against every provider's `processNames.win32`.
83
+ *
84
+ * @param binPath Resolved binary path that would be exec'd.
85
+ * @param win32ProcessNames Map of provider type → list of GUI exe names
86
+ * (from provider.json `processNames.win32`, e.g. `["Cursor.exe"]`).
87
+ */
88
+ export function isKnownWin32GuiExe(
89
+ binPath: string | null | undefined,
90
+ win32ProcessNames: Record<string, string[]>,
91
+ ): boolean {
92
+ if (!binPath) return false;
93
+ // Use win32 basename semantics regardless of host OS: this matches Windows
94
+ // paths even when the daemon-core test/CI host is POSIX (where `/` is the
95
+ // only separator). On the real win32 target this is identical to basename().
96
+ const base = path.win32.basename(binPath).toLowerCase();
97
+ if (!base.endsWith('.exe')) return false;
98
+ for (const names of Object.values(win32ProcessNames)) {
99
+ for (const name of names) {
100
+ if (typeof name === 'string' && name.toLowerCase() === base) {
101
+ return true;
102
+ }
103
+ }
104
+ }
105
+ return false;
106
+ }
@@ -0,0 +1,354 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
2
+ import { join } from 'path';
3
+ import * as yaml from 'js-yaml';
4
+
5
+ /**
6
+ * "Change Impact" — config-driven classification of which git changes between the
7
+ * live daemon's build commit and the workspace HEAD actually require a daemon
8
+ * rebuild/restart (vs. a web-only redeploy, vs. nothing).
9
+ *
10
+ * The daemon-core git surface only knows the FACTS (which files / packages changed
11
+ * between buildCommit..HEAD). The POLICY — which packages are daemon-runtime, which
12
+ * are web-only, which root files are non-runtime, and what command to recommend —
13
+ * is declarative config injected from outside. This keeps git-status.ts repo-agnostic
14
+ * while preserving ADHDev's exact built-in behavior when no config is present.
15
+ *
16
+ * SECURITY: config is declarative only. JSON/YAML are parsed; arbitrary JS config
17
+ * (.js) is intentionally NOT supported, so loading a config can never execute code.
18
+ */
19
+
20
+ /** A change-impact classification bucket. */
21
+ export type ChangeImpactKind = 'daemon' | 'web' | 'none';
22
+
23
+ /**
24
+ * Recommended action for a given impact classification. `recommendedAction` is the
25
+ * stable classification key (always one of daemon|web|none, NOT config-overridable);
26
+ * config customizes only the human-facing `recommendedCommand` recipe.
27
+ */
28
+ export interface ChangeImpactTarget {
29
+ /** Human-facing command/recipe to act on the impact (e.g. deploy + restart). */
30
+ recommendedCommand: string;
31
+ }
32
+
33
+ export interface ChangeImpactConfig {
34
+ /**
35
+ * Package names (the `<name>` in `packages/<name>/`) whose change means the
36
+ * daemon runtime is stale and must be rebuilt/redeployed + restarted. When
37
+ * provided, this REPLACES the built-in daemon-runtime set.
38
+ */
39
+ daemonRuntimePackages?: string[];
40
+ /**
41
+ * Package names that are web-only — a change to one does not require a daemon
42
+ * restart, only a web redeploy. When provided, this REPLACES the built-in
43
+ * web-only set.
44
+ */
45
+ webOnlyPackages?: string[];
46
+ /**
47
+ * Glob patterns for root-level (non-package) files that demonstrably cannot
48
+ * change what the daemon runtime executes (markers, docs, license text). These
49
+ * are added on top of the built-in non-runtime root-file detection.
50
+ */
51
+ nonRuntimeRootFilePatterns?: string[];
52
+ /** Recommended action/command per impact classification. Missing keys fall back to built-in defaults. */
53
+ impactTargets?: Partial<Record<ChangeImpactKind, ChangeImpactTarget>>;
54
+ }
55
+
56
+ export interface ChangeImpactConfigLoadResult {
57
+ config?: ChangeImpactConfig;
58
+ source: string;
59
+ sourceType: 'repo_file' | 'unavailable' | 'invalid';
60
+ path?: string;
61
+ error?: string;
62
+ /**
63
+ * Stable identity of the config SOURCE, used as part of a cache key so a config
64
+ * edit invalidates any cached impact evaluation. Combines the resolved path and
65
+ * its mtime (or the path for the unavailable/invalid case).
66
+ */
67
+ sourceKey: string;
68
+ }
69
+
70
+ export const CHANGE_IMPACT_CONFIG_LOCATIONS = [
71
+ '.adhdev/change-impact.json',
72
+ '.adhdev/change-impact.yaml',
73
+ '.adhdev/change-impact.yml',
74
+ '.adhdev/repo-mesh-change-impact.json',
75
+ '.adhdev/repo-mesh-change-impact.yaml',
76
+ '.adhdev/repo-mesh-change-impact.yml',
77
+ ];
78
+
79
+ export const CHANGE_IMPACT_CONFIG_SCHEMA = {
80
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
81
+ title: 'ADHDev Change Impact Config',
82
+ type: 'object',
83
+ additionalProperties: false,
84
+ properties: {
85
+ daemonRuntimePackages: { type: 'array', items: { type: 'string', minLength: 1 } },
86
+ webOnlyPackages: { type: 'array', items: { type: 'string', minLength: 1 } },
87
+ nonRuntimeRootFilePatterns: { type: 'array', items: { type: 'string', minLength: 1 } },
88
+ impactTargets: {
89
+ type: 'object',
90
+ additionalProperties: false,
91
+ properties: {
92
+ daemon: { $ref: '#/$defs/target' },
93
+ web: { $ref: '#/$defs/target' },
94
+ none: { $ref: '#/$defs/target' },
95
+ },
96
+ },
97
+ },
98
+ $defs: {
99
+ target: {
100
+ type: 'object',
101
+ additionalProperties: false,
102
+ required: ['recommendedCommand'],
103
+ properties: {
104
+ recommendedCommand: { type: 'string', minLength: 1 },
105
+ },
106
+ },
107
+ },
108
+ } as const;
109
+
110
+ function isRecord(value: unknown): value is Record<string, unknown> {
111
+ return !!value && typeof value === 'object' && !Array.isArray(value);
112
+ }
113
+
114
+ function isStringArray(value: unknown): value is string[] {
115
+ return Array.isArray(value) && value.every(v => typeof v === 'string' && v.length > 0);
116
+ }
117
+
118
+ function validateTarget(value: unknown, key: string, errors: string[]): ChangeImpactTarget | undefined {
119
+ if (!isRecord(value)) {
120
+ errors.push(`impactTargets.${key} must be an object`);
121
+ return undefined;
122
+ }
123
+ const { recommendedCommand } = value;
124
+ if (typeof recommendedCommand !== 'string' || !recommendedCommand.length) {
125
+ errors.push(`impactTargets.${key}.recommendedCommand must be a non-empty string`);
126
+ return undefined;
127
+ }
128
+ // recommendedAction is the fixed classification key; config supplies only the command.
129
+ for (const k of Object.keys(value)) {
130
+ if (k !== 'recommendedCommand') errors.push(`impactTargets.${key}.${k} is not a recognized field (only recommendedCommand)`);
131
+ }
132
+ return { recommendedCommand };
133
+ }
134
+
135
+ export function validateChangeImpactConfig(raw: unknown, source = 'inline'): { valid: boolean; errors: string[]; config?: ChangeImpactConfig } {
136
+ const errors: string[] = [];
137
+ if (!isRecord(raw)) {
138
+ return { valid: false, errors: [`${source}: config must be an object`] };
139
+ }
140
+ const config: ChangeImpactConfig = {};
141
+
142
+ if (raw.daemonRuntimePackages !== undefined) {
143
+ if (isStringArray(raw.daemonRuntimePackages)) config.daemonRuntimePackages = [...raw.daemonRuntimePackages];
144
+ else errors.push('daemonRuntimePackages must be an array of non-empty strings');
145
+ }
146
+ if (raw.webOnlyPackages !== undefined) {
147
+ if (isStringArray(raw.webOnlyPackages)) config.webOnlyPackages = [...raw.webOnlyPackages];
148
+ else errors.push('webOnlyPackages must be an array of non-empty strings');
149
+ }
150
+ if (raw.nonRuntimeRootFilePatterns !== undefined) {
151
+ if (isStringArray(raw.nonRuntimeRootFilePatterns)) config.nonRuntimeRootFilePatterns = [...raw.nonRuntimeRootFilePatterns];
152
+ else errors.push('nonRuntimeRootFilePatterns must be an array of non-empty strings');
153
+ }
154
+ if (raw.impactTargets !== undefined) {
155
+ if (!isRecord(raw.impactTargets)) {
156
+ errors.push('impactTargets must be an object');
157
+ } else {
158
+ const targets: Partial<Record<ChangeImpactKind, ChangeImpactTarget>> = {};
159
+ for (const key of Object.keys(raw.impactTargets)) {
160
+ if (key !== 'daemon' && key !== 'web' && key !== 'none') {
161
+ errors.push(`impactTargets.${key} is not a recognized impact kind (daemon|web|none)`);
162
+ continue;
163
+ }
164
+ const target = validateTarget(raw.impactTargets[key], key, errors);
165
+ if (target) targets[key as ChangeImpactKind] = target;
166
+ }
167
+ if (Object.keys(targets).length) config.impactTargets = targets;
168
+ }
169
+ }
170
+ // Reject unknown top-level keys to catch typos early (mirrors additionalProperties:false).
171
+ for (const key of Object.keys(raw)) {
172
+ if (!['daemonRuntimePackages', 'webOnlyPackages', 'nonRuntimeRootFilePatterns', 'impactTargets'].includes(key)) {
173
+ errors.push(`unknown config key '${key}'`);
174
+ }
175
+ }
176
+
177
+ return { valid: errors.length === 0, errors, config: errors.length === 0 ? config : undefined };
178
+ }
179
+
180
+ function parseConfigText(path: string, text: string): unknown {
181
+ if (/\.json$/i.test(path)) return JSON.parse(text);
182
+ return yaml.load(text);
183
+ }
184
+
185
+ /**
186
+ * Locate and load the Change Impact config for a repo root. Declarative only —
187
+ * never executes config. Returns a sourceKey suitable for cache invalidation:
188
+ * config path + mtime, or the sentinel for the missing/invalid case.
189
+ */
190
+ export function loadChangeImpactConfig(repoRoot: string): ChangeImpactConfigLoadResult {
191
+ for (const relative of CHANGE_IMPACT_CONFIG_LOCATIONS) {
192
+ const configPath = join(repoRoot, relative);
193
+ if (!existsSync(configPath)) continue;
194
+ try {
195
+ const text = readFileSync(configPath, 'utf-8');
196
+ let mtimeMs = 0;
197
+ try {
198
+ mtimeMs = statSync(configPath).mtimeMs;
199
+ } catch {
200
+ // Best-effort; fall back to content length so edits still perturb the key.
201
+ mtimeMs = text.length;
202
+ }
203
+ const parsed = parseConfigText(configPath, text);
204
+ const validation = validateChangeImpactConfig(parsed, relative);
205
+ if (!validation.valid) {
206
+ return {
207
+ source: relative,
208
+ sourceType: 'invalid',
209
+ path: configPath,
210
+ error: validation.errors.join('; '),
211
+ sourceKey: `invalid:${configPath}:${mtimeMs}`,
212
+ };
213
+ }
214
+ return {
215
+ config: validation.config,
216
+ source: relative,
217
+ sourceType: 'repo_file',
218
+ path: configPath,
219
+ sourceKey: `file:${configPath}:${mtimeMs}`,
220
+ };
221
+ } catch (error: any) {
222
+ return {
223
+ source: relative,
224
+ sourceType: 'invalid',
225
+ path: configPath,
226
+ error: error?.message || String(error),
227
+ sourceKey: `error:${configPath}`,
228
+ };
229
+ }
230
+ }
231
+ return {
232
+ source: 'unavailable',
233
+ sourceType: 'unavailable',
234
+ error: `No change-impact config found. Checked: ${CHANGE_IMPACT_CONFIG_LOCATIONS.join(', ')}`,
235
+ sourceKey: 'unavailable',
236
+ };
237
+ }
238
+
239
+ /**
240
+ * Translate a config glob pattern into a RegExp matched against a forward-slash
241
+ * file path. Supports `**` (any path segments), `*` (any chars except `/`), and
242
+ * `?` (single non-slash char). No brace/character-class expansion — declarative,
243
+ * minimal, predictable. All other characters are matched literally.
244
+ */
245
+ export function globToRegExp(pattern: string): RegExp {
246
+ let out = '';
247
+ for (let i = 0; i < pattern.length; i++) {
248
+ const ch = pattern[i];
249
+ if (ch === '*') {
250
+ if (pattern[i + 1] === '*') {
251
+ // `**` → any sequence of characters including path separators.
252
+ out += '.*';
253
+ i++;
254
+ // Swallow a trailing slash after `**/` so `**/x` also matches `x`.
255
+ if (pattern[i + 1] === '/') i++;
256
+ } else {
257
+ out += '[^/]*';
258
+ }
259
+ } else if (ch === '?') {
260
+ out += '[^/]';
261
+ } else if ('.+^${}()|[]\\'.includes(ch)) {
262
+ out += '\\' + ch;
263
+ } else {
264
+ out += ch;
265
+ }
266
+ }
267
+ return new RegExp(`^${out}$`);
268
+ }
269
+
270
+ export interface ChangeImpactConfigSuggestion {
271
+ /** A non-executable, declarative config draft a human can save verbatim. */
272
+ suggestedConfig: ChangeImpactConfig;
273
+ /** Per-field human-facing rationale for the proposed classification. */
274
+ notes: string[];
275
+ /** Package directories discovered under `packages/` (and `oss/packages/`). */
276
+ discoveredPackages: { daemon: string[]; web: string[]; unclassified: string[] };
277
+ }
278
+
279
+ function listPackageDirs(packagesRoot: string): string[] {
280
+ try {
281
+ return readdirSync(packagesRoot, { withFileTypes: true })
282
+ .filter(entry => entry.isDirectory() && !entry.name.startsWith('.'))
283
+ .map(entry => entry.name);
284
+ } catch {
285
+ return [];
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Inspect a repo's package layout and propose a reasonable, declarative Change
291
+ * Impact config draft. This is heuristic scaffold ONLY — it never executes
292
+ * anything and the draft must be reviewed/saved by a human before it takes
293
+ * effect. The heuristic mirrors ADHDev's own conventions:
294
+ * - `web-*` / `*-web` packages → web-only (web redeploy, no daemon restart)
295
+ * - everything else under packages/ → daemon-runtime (rebuild + restart)
296
+ * - docs/license/marker root files → non-runtime
297
+ * Callers are expected to prune the draft to their actual runtime topology.
298
+ */
299
+ export function suggestChangeImpactConfig(repoRoot: string): ChangeImpactConfigSuggestion {
300
+ const notes: string[] = [];
301
+ const daemon = new Set<string>();
302
+ const web = new Set<string>();
303
+ const unclassified: string[] = [];
304
+
305
+ const roots = ['packages', join('oss', 'packages')];
306
+ for (const rel of roots) {
307
+ const packagesRoot = join(repoRoot, rel);
308
+ if (!existsSync(packagesRoot)) continue;
309
+ for (const name of listPackageDirs(packagesRoot)) {
310
+ if (/(^web[-.]|[-.]web$)/i.test(name) || /dashboard|frontend|ui$/i.test(name)) {
311
+ web.add(name);
312
+ } else {
313
+ daemon.add(name);
314
+ }
315
+ }
316
+ }
317
+
318
+ const daemonRuntimePackages = [...daemon].sort();
319
+ const webOnlyPackages = [...web].sort();
320
+
321
+ if (!daemonRuntimePackages.length && !webOnlyPackages.length) {
322
+ notes.push('No packages/ or oss/packages/ directories found — defaulting to an empty draft you should fill in by hand.');
323
+ } else {
324
+ if (daemonRuntimePackages.length) notes.push(`Classified ${daemonRuntimePackages.length} package(s) as daemon-runtime (change → rebuild/redeploy + restart).`);
325
+ if (webOnlyPackages.length) notes.push(`Classified ${webOnlyPackages.length} web-* package(s) as web-only (change → web redeploy, no daemon restart).`);
326
+ notes.push('Heuristic only: confirm each package actually matches its bucket before saving.');
327
+ }
328
+
329
+ const nonRuntimeRootFilePatterns = [
330
+ '*.md',
331
+ 'docs/**',
332
+ 'LICENSE',
333
+ 'LICENSE.*',
334
+ '.gitignore',
335
+ ];
336
+ notes.push('nonRuntimeRootFilePatterns lists root files that demonstrably cannot change daemon runtime behavior; extend with your repo markers.');
337
+
338
+ const suggestedConfig: ChangeImpactConfig = {
339
+ ...(daemonRuntimePackages.length ? { daemonRuntimePackages } : {}),
340
+ ...(webOnlyPackages.length ? { webOnlyPackages } : {}),
341
+ nonRuntimeRootFilePatterns,
342
+ impactTargets: {
343
+ daemon: { recommendedCommand: 'rebuild + redeploy the daemon, then restart it' },
344
+ web: { recommendedCommand: 'redeploy the web app (no daemon restart required)' },
345
+ none: { recommendedCommand: 'no action required' },
346
+ },
347
+ };
348
+
349
+ return {
350
+ suggestedConfig,
351
+ notes,
352
+ discoveredPackages: { daemon: daemonRuntimePackages, web: webOnlyPackages, unclassified },
353
+ };
354
+ }