@adhdev/daemon-core 0.9.82-rc.49 → 0.9.82-rc.491

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 (473) 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 +220 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +137 -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 +23 -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 +71 -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 +48 -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-aggregate-status.d.ts +24 -0
  56. package/dist/commands/router-mesh-session-owner.d.ts +59 -0
  57. package/dist/commands/router-refine.d.ts +151 -0
  58. package/dist/commands/router-worktree-cleanup.d.ts +133 -0
  59. package/dist/commands/router.d.ts +203 -15
  60. package/dist/commands/upgrade-helper.d.ts +41 -1
  61. package/dist/config/chat-history.d.ts +11 -0
  62. package/dist/config/config.d.ts +19 -0
  63. package/dist/config/mesh-config.d.ts +66 -0
  64. package/dist/config/mesh-json-config.d.ts +199 -0
  65. package/dist/config/registry-resolver.d.ts +54 -0
  66. package/dist/config/repo-settings.d.ts +77 -0
  67. package/dist/config/state-store.d.ts +30 -0
  68. package/dist/daemon/dev-server.d.ts +0 -2
  69. package/dist/detection/cli-detector.d.ts +17 -0
  70. package/dist/detection/ide-detector.d.ts +13 -0
  71. package/dist/detection/win32-ide-version.d.ts +37 -0
  72. package/dist/git/change-impact-config.d.ts +159 -0
  73. package/dist/git/git-commands.d.ts +26 -2
  74. package/dist/git/git-diff.d.ts +6 -0
  75. package/dist/git/git-executor.d.ts +11 -0
  76. package/dist/git/git-status.d.ts +80 -0
  77. package/dist/git/git-types.d.ts +2 -50
  78. package/dist/git/git-worktree.d.ts +71 -1
  79. package/dist/git/index.d.ts +3 -1
  80. package/dist/index.d.ts +70 -17
  81. package/dist/index.js +53556 -19074
  82. package/dist/index.js.map +1 -1
  83. package/dist/index.mjs +53380 -19063
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/installer.d.ts +1 -4
  86. package/dist/ipc/local-ipc-server.d.ts +91 -0
  87. package/dist/launch.d.ts +1 -1
  88. package/dist/logging/async-batch-writer.d.ts +10 -0
  89. package/dist/logging/debug-config.d.ts +16 -0
  90. package/dist/logging/log-redactor.d.ts +24 -0
  91. package/dist/logging/log-tail-reader.d.ts +81 -0
  92. package/dist/logging/logger.d.ts +1 -1
  93. package/dist/mesh/contracts.d.ts +256 -0
  94. package/dist/mesh/coordinator-prompt.d.ts +76 -0
  95. package/dist/mesh/coordinator-registry.d.ts +59 -0
  96. package/dist/mesh/mesh-active-work.d.ts +203 -0
  97. package/dist/mesh/mesh-clone-grace.d.ts +8 -0
  98. package/dist/mesh/mesh-completion-synthesis.d.ts +4 -0
  99. package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
  100. package/dist/mesh/mesh-delivery-policy.d.ts +104 -0
  101. package/dist/mesh/mesh-event-classify.d.ts +7 -0
  102. package/dist/mesh/mesh-event-forwarding.d.ts +58 -0
  103. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  104. package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
  105. package/dist/mesh/mesh-events-pending.d.ts +258 -0
  106. package/dist/mesh/mesh-events-stale.d.ts +61 -0
  107. package/dist/mesh/mesh-events-utils.d.ts +75 -0
  108. package/dist/mesh/mesh-events.d.ts +6 -49
  109. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  110. package/dist/mesh/mesh-host-ownership.d.ts +21 -1
  111. package/dist/mesh/mesh-init.d.ts +128 -0
  112. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
  113. package/dist/mesh/mesh-ledger.d.ts +139 -1
  114. package/dist/mesh/mesh-magi-status.d.ts +63 -0
  115. package/dist/mesh/mesh-missions.d.ts +281 -0
  116. package/dist/mesh/mesh-node-identity.d.ts +310 -0
  117. package/dist/mesh/mesh-queue-assignment.d.ts +162 -0
  118. package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
  119. package/dist/mesh/mesh-reconcile-config.d.ts +6 -0
  120. package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
  121. package/dist/mesh/mesh-reconcile-loop.d.ts +84 -0
  122. package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -0
  123. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  124. package/dist/mesh/mesh-refine-gates.d.ts +457 -0
  125. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  126. package/dist/mesh/mesh-remote-event-pull.d.ts +15 -0
  127. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  128. package/dist/mesh/mesh-routing.d.ts +70 -0
  129. package/dist/mesh/mesh-runtime-store.d.ts +567 -0
  130. package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
  131. package/dist/mesh/mesh-task-inflight.d.ts +46 -0
  132. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  133. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +34 -0
  134. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  135. package/dist/mesh/mesh-work-queue.d.ts +392 -1
  136. package/dist/mesh/preview-freshness.d.ts +28 -0
  137. package/dist/mesh/refine-config.d.ts +97 -0
  138. package/dist/mesh/worktree-bootstrap-config.d.ts +219 -0
  139. package/dist/providers/acp-provider-instance.d.ts +5 -0
  140. package/dist/providers/approval-utils.d.ts +46 -0
  141. package/dist/providers/chat-message-normalization.d.ts +58 -1
  142. package/dist/providers/cli-provider-effect-format.d.ts +30 -0
  143. package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
  144. package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
  145. package/dist/providers/cli-provider-instance-types.d.ts +45 -0
  146. package/dist/providers/cli-provider-instance.d.ts +426 -30
  147. package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
  148. package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
  149. package/dist/providers/contracts.d.ts +196 -6
  150. package/dist/providers/external-sources.d.ts +71 -0
  151. package/dist/providers/manual-attendance.d.ts +79 -0
  152. package/dist/providers/native-history/antigravity-claim-registry.d.ts +39 -0
  153. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +137 -0
  154. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  155. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  156. package/dist/providers/native-history/constants.d.ts +12 -0
  157. package/dist/providers/native-history/dispatcher.d.ts +44 -0
  158. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  159. package/dist/providers/native-history/index.d.ts +13 -0
  160. package/dist/providers/provider-instance-manager.d.ts +30 -0
  161. package/dist/providers/provider-instance.d.ts +31 -1
  162. package/dist/providers/provider-loader.d.ts +42 -5
  163. package/dist/providers/provider-trust.d.ts +31 -0
  164. package/dist/providers/read-chat-contract.d.ts +29 -0
  165. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  166. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  167. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  168. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  169. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  170. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  171. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  172. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  173. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  174. package/dist/providers/sdk/v1/index.d.ts +30 -0
  175. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  176. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  177. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  178. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  179. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  180. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  181. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  182. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  183. package/dist/providers/spec/adapter.d.ts +98 -0
  184. package/dist/providers/spec/cli-adapter.d.ts +223 -0
  185. package/dist/providers/spec/evaluator.d.ts +45 -0
  186. package/dist/providers/spec/fsm-driver.d.ts +449 -0
  187. package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
  188. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  189. package/dist/providers/spec/fsm-types.d.ts +202 -0
  190. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  191. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  192. package/dist/providers/spec/route.d.ts +4 -0
  193. package/dist/providers/spec/types.d.ts +244 -0
  194. package/dist/providers/status-monitor.d.ts +7 -7
  195. package/dist/providers/transcript-v2.d.ts +176 -0
  196. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  197. package/dist/providers/working-dir.d.ts +17 -0
  198. package/dist/repo-mesh-types.d.ts +616 -12
  199. package/dist/runtime-defaults.d.ts +2 -0
  200. package/dist/session-host/managed-host.d.ts +64 -0
  201. package/dist/session-host/runtime-surface.d.ts +10 -16
  202. package/dist/sessions/registry.d.ts +26 -0
  203. package/dist/shared-types-extra.d.ts +2 -4
  204. package/dist/shared-types.d.ts +110 -55
  205. package/dist/status/chat-tail-hot-sessions.d.ts +40 -0
  206. package/dist/status/normalize.d.ts +1 -1
  207. package/dist/status/normalize.js +1 -0
  208. package/dist/status/normalize.js.map +1 -1
  209. package/dist/status/normalize.mjs +1 -0
  210. package/dist/status/normalize.mjs.map +1 -1
  211. package/dist/status/reporter.d.ts +2 -0
  212. package/dist/status/snapshot.d.ts +27 -0
  213. package/dist/system/hash.d.ts +8 -0
  214. package/dist/system/load-better-sqlite3.d.ts +21 -0
  215. package/dist/types.d.ts +20 -6
  216. package/package.json +11 -4
  217. package/src/agent-stream/poller.ts +2 -3
  218. package/src/agent-stream/provider-adapter.ts +1 -1
  219. package/src/boot/daemon-lifecycle.ts +80 -14
  220. package/src/boot/process-hardening.ts +89 -0
  221. package/src/build-info.ts +73 -0
  222. package/src/chat/source-machine.ts +534 -0
  223. package/src/chat/source-resolver.ts +0 -0
  224. package/src/chat/subscription-updates.ts +20 -1
  225. package/src/cli-adapter-types.d.ts +3 -1
  226. package/src/cli-adapter-types.ts +68 -2
  227. package/src/cli-adapters/cli-script-runner.ts +421 -0
  228. package/src/cli-adapters/cli-state-engine.ts +1282 -0
  229. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  230. package/src/cli-adapters/provider-cli-adapter.ts +1048 -1143
  231. package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
  232. package/src/cli-adapters/provider-cli-parse.ts +19 -0
  233. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  234. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  235. package/src/cli-adapters/provider-cli-shared.ts +121 -11
  236. package/src/cli-adapters/pty-transport.ts +2 -1
  237. package/src/cli-adapters/pty-write-chunking.ts +106 -0
  238. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  239. package/src/cli-adapters/resolve-executable.ts +204 -0
  240. package/src/cli-adapters/session-host-transport.ts +2 -1
  241. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
  242. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  243. package/src/cli-adapters/terminal-screen.ts +16 -81
  244. package/src/commands/chat-commands-debug-bundle.ts +398 -0
  245. package/src/commands/chat-commands-read.ts +2788 -0
  246. package/src/commands/chat-commands-scope.ts +54 -0
  247. package/src/commands/chat-commands-shared.ts +114 -0
  248. package/src/commands/chat-commands-write.ts +891 -0
  249. package/src/commands/chat-commands.ts +19 -1841
  250. package/src/commands/cli-manager.d.ts +2 -0
  251. package/src/commands/cli-manager.ts +724 -27
  252. package/src/commands/handler.ts +865 -2
  253. package/src/commands/high-family/index.ts +28 -0
  254. package/src/commands/high-family/mesh-coordinator-launch.ts +696 -0
  255. package/src/commands/high-family/mesh-events.ts +102 -0
  256. package/src/commands/high-family/mesh-status.ts +857 -0
  257. package/src/commands/high-family/types.ts +80 -0
  258. package/src/commands/low-family/coordinator-prompt.ts +125 -0
  259. package/src/commands/low-family/daemon-lifecycle.ts +120 -0
  260. package/src/commands/low-family/diagnostics.ts +57 -0
  261. package/src/commands/low-family/index.ts +37 -0
  262. package/src/commands/low-family/mesh-ledger.ts +62 -0
  263. package/src/commands/low-family/mesh-node-logs.ts +87 -0
  264. package/src/commands/low-family/notification.ts +116 -0
  265. package/src/commands/low-family/refine-config.ts +106 -0
  266. package/src/commands/low-family/session-host.ts +282 -0
  267. package/src/commands/low-family/spec-providerdev.ts +217 -0
  268. package/src/commands/low-family/status-meta.ts +112 -0
  269. package/src/commands/low-family/types.ts +39 -0
  270. package/src/commands/med-family/cli-agent.ts +270 -0
  271. package/src/commands/med-family/fast-forward.ts +230 -0
  272. package/src/commands/med-family/ide.ts +163 -0
  273. package/src/commands/med-family/index.ts +37 -0
  274. package/src/commands/med-family/mesh-crud.ts +1309 -0
  275. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  276. package/src/commands/med-family/mesh-queue.ts +167 -0
  277. package/src/commands/med-family/mesh-restart.ts +92 -0
  278. package/src/commands/med-family/types.ts +153 -0
  279. package/src/commands/mesh-coordinator.ts +334 -124
  280. package/src/commands/router-aggregate-status.ts +209 -0
  281. package/src/commands/router-mesh-session-owner.ts +114 -0
  282. package/src/commands/router-refine.ts +1794 -0
  283. package/src/commands/router-worktree-cleanup.ts +870 -0
  284. package/src/commands/router.ts +567 -4149
  285. package/src/commands/stream-commands.ts +8 -0
  286. package/src/commands/upgrade-helper.ts +310 -45
  287. package/src/config/chat-history.ts +517 -24
  288. package/src/config/config.ts +30 -0
  289. package/src/config/mesh-config.ts +300 -24
  290. package/src/config/mesh-json-config.ts +376 -0
  291. package/src/config/recent-activity.ts +8 -2
  292. package/src/config/registry-resolver.ts +100 -0
  293. package/src/config/repo-settings.ts +111 -0
  294. package/src/config/state-store.ts +55 -0
  295. package/src/daemon/dev-auto-implement.ts +3 -2
  296. package/src/daemon/dev-cli-debug.ts +10 -1
  297. package/src/daemon/dev-server.ts +0 -541
  298. package/src/detection/cli-detector.ts +94 -9
  299. package/src/detection/ide-detector.ts +55 -16
  300. package/src/detection/win32-ide-version.ts +106 -0
  301. package/src/git/change-impact-config.ts +354 -0
  302. package/src/git/git-commands.ts +112 -16
  303. package/src/git/git-diff.ts +81 -11
  304. package/src/git/git-executor.ts +12 -0
  305. package/src/git/git-status.ts +822 -48
  306. package/src/git/git-types.ts +14 -62
  307. package/src/git/git-worktree.ts +261 -4
  308. package/src/git/index.ts +17 -0
  309. package/src/index.ts +190 -13
  310. package/src/installer.d.ts +1 -1
  311. package/src/installer.ts +8 -6
  312. package/src/ipc/local-ipc-server.ts +278 -0
  313. package/src/launch.d.ts +1 -1
  314. package/src/launch.ts +37 -28
  315. package/src/logging/async-batch-writer.ts +55 -0
  316. package/src/logging/command-log.ts +7 -5
  317. package/src/logging/debug-config.ts +25 -0
  318. package/src/logging/debug-trace.ts +7 -2
  319. package/src/logging/log-redactor.ts +100 -0
  320. package/src/logging/log-tail-reader.ts +341 -0
  321. package/src/logging/logger.ts +14 -7
  322. package/src/mesh/contracts.ts +510 -0
  323. package/src/mesh/coordinator-prompt.ts +627 -34
  324. package/src/mesh/coordinator-registry.ts +121 -0
  325. package/src/mesh/mesh-active-work.ts +706 -0
  326. package/src/mesh/mesh-clone-grace.ts +68 -0
  327. package/src/mesh/mesh-completion-synthesis.ts +416 -0
  328. package/src/mesh/mesh-coordinator-config.ts +97 -0
  329. package/src/mesh/mesh-delivery-policy.ts +284 -0
  330. package/src/mesh/mesh-event-classify.ts +78 -0
  331. package/src/mesh/mesh-event-forwarding.ts +2030 -0
  332. package/src/mesh/mesh-event-trace.ts +67 -0
  333. package/src/mesh/mesh-events-coordinator.ts +32 -0
  334. package/src/mesh/mesh-events-pending.ts +1548 -0
  335. package/src/mesh/mesh-events-stale.ts +452 -0
  336. package/src/mesh/mesh-events-utils.ts +443 -0
  337. package/src/mesh/mesh-events.ts +43 -1035
  338. package/src/mesh/mesh-fast-forward.ts +856 -0
  339. package/src/mesh/mesh-host-ownership.ts +41 -3
  340. package/src/mesh/mesh-init.ts +350 -0
  341. package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
  342. package/src/mesh/mesh-ledger.ts +897 -102
  343. package/src/mesh/mesh-magi-status.ts +223 -0
  344. package/src/mesh/mesh-missions.ts +695 -0
  345. package/src/mesh/mesh-node-identity.ts +2065 -0
  346. package/src/mesh/mesh-queue-assignment.ts +2498 -0
  347. package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
  348. package/src/mesh/mesh-reconcile-config.ts +66 -0
  349. package/src/mesh/mesh-reconcile-identity.ts +103 -0
  350. package/src/mesh/mesh-reconcile-loop.ts +1696 -0
  351. package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
  352. package/src/mesh/mesh-refine-batch.ts +205 -0
  353. package/src/mesh/mesh-refine-gates.ts +1792 -0
  354. package/src/mesh/mesh-refine-status.ts +231 -0
  355. package/src/mesh/mesh-remote-event-pull.ts +279 -0
  356. package/src/mesh/mesh-review-inbox.ts +308 -0
  357. package/src/mesh/mesh-routing.ts +291 -0
  358. package/src/mesh/mesh-runtime-store.ts +2292 -0
  359. package/src/mesh/mesh-scheduling-runtime.ts +198 -0
  360. package/src/mesh/mesh-task-inflight.ts +70 -0
  361. package/src/mesh/mesh-task-stats.ts +161 -0
  362. package/src/mesh/mesh-unresolved-forward-outbox.ts +215 -0
  363. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  364. package/src/mesh/mesh-work-queue.ts +1489 -145
  365. package/src/mesh/preview-freshness.ts +163 -0
  366. package/src/mesh/refine-config.ts +129 -12
  367. package/src/mesh/worktree-bootstrap-config.ts +599 -0
  368. package/src/providers/acp-provider-instance.ts +43 -10
  369. package/src/providers/approval-utils.d.ts +5 -0
  370. package/src/providers/approval-utils.ts +100 -6
  371. package/src/providers/chat-message-normalization.ts +126 -4
  372. package/src/providers/cli-provider-effect-format.ts +53 -0
  373. package/src/providers/cli-provider-history-dedup.ts +75 -0
  374. package/src/providers/cli-provider-input-prompt.ts +133 -0
  375. package/src/providers/cli-provider-instance-types.ts +131 -0
  376. package/src/providers/cli-provider-instance.ts +2771 -499
  377. package/src/providers/cli-provider-status-helpers.ts +123 -0
  378. package/src/providers/cli-provider-transcript-merge.ts +114 -0
  379. package/src/providers/contracts.d.ts +55 -0
  380. package/src/providers/contracts.ts +207 -6
  381. package/src/providers/extension-provider-instance.ts +12 -7
  382. package/src/providers/external-sources.ts +218 -0
  383. package/src/providers/ide-provider-instance.ts +35 -12
  384. package/src/providers/manual-attendance.ts +105 -0
  385. package/src/providers/native-history/antigravity-claim-registry.ts +138 -0
  386. package/src/providers/native-history/antigravity-cli-transcript.ts +1275 -0
  387. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  388. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  389. package/src/providers/native-history/constants.ts +19 -0
  390. package/src/providers/native-history/dispatcher.ts +617 -0
  391. package/src/providers/native-history/hermes-cli-transcript.ts +312 -0
  392. package/src/providers/native-history/index.ts +30 -0
  393. package/src/providers/provider-instance-manager.ts +71 -0
  394. package/src/providers/provider-instance.ts +24 -1
  395. package/src/providers/provider-loader.ts +700 -55
  396. package/src/providers/provider-schema.ts +93 -14
  397. package/src/providers/provider-trust.ts +114 -0
  398. package/src/providers/read-chat-contract.ts +76 -16
  399. package/src/providers/sdk/README.md +49 -0
  400. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  401. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  402. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  403. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +261 -0
  404. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  405. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  406. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  407. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  408. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  409. package/src/providers/sdk/v1/index.ts +152 -0
  410. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  411. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  412. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  413. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +538 -0
  414. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  415. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  416. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  417. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  418. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  419. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  420. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  421. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  422. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  423. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  424. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  425. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  426. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  427. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  428. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  429. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  430. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  431. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  432. package/src/providers/sdk/v1/validators/index.ts +19 -0
  433. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  434. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  435. package/src/providers/spec/adapter.ts +246 -0
  436. package/src/providers/spec/cli-adapter.ts +1064 -0
  437. package/src/providers/spec/evaluator.ts +407 -0
  438. package/src/providers/spec/fsm-driver.ts +1528 -0
  439. package/src/providers/spec/fsm-evaluator.ts +290 -0
  440. package/src/providers/spec/fsm-loader.ts +128 -0
  441. package/src/providers/spec/fsm-types.ts +301 -0
  442. package/src/providers/spec/native-history-executor.ts +1241 -0
  443. package/src/providers/spec/pre-launch-trust.ts +104 -0
  444. package/src/providers/spec/route.ts +51 -0
  445. package/src/providers/spec/types.ts +284 -0
  446. package/src/providers/status-monitor.d.ts +7 -7
  447. package/src/providers/status-monitor.ts +37 -22
  448. package/src/providers/transcript-v2.ts +567 -0
  449. package/src/providers/types/interactive-prompt.ts +536 -0
  450. package/src/providers/version-archive.ts +64 -24
  451. package/src/providers/working-dir.ts +23 -0
  452. package/src/repo-mesh-types.ts +861 -14
  453. package/src/runtime-defaults.ts +39 -0
  454. package/src/session-host/managed-host.ts +218 -0
  455. package/src/session-host/runtime-surface.ts +20 -80
  456. package/src/sessions/registry.ts +44 -0
  457. package/src/shared-types-extra.ts +2 -4
  458. package/src/shared-types.d.ts +8 -0
  459. package/src/shared-types.ts +148 -55
  460. package/src/status/builders.ts +69 -6
  461. package/src/status/chat-tail-hot-sessions.ts +117 -2
  462. package/src/status/normalize.ts +2 -0
  463. package/src/status/reporter.ts +19 -1
  464. package/src/status/snapshot.ts +100 -27
  465. package/src/system/hash.ts +23 -0
  466. package/src/system/host-memory.ts +29 -12
  467. package/src/system/load-better-sqlite3.ts +68 -0
  468. package/src/types.ts +26 -6
  469. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  470. package/dist/mesh/mesh-sync.d.ts +0 -53
  471. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  472. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  473. package/src/mesh/mesh-sync.ts +0 -111
@@ -0,0 +1,599 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join, resolve as pathResolve } from 'path';
3
+ import { execFile, execFileSync } from 'node:child_process';
4
+ import { createHash } from 'node:crypto';
5
+ import { promisify } from 'node:util';
6
+ import * as yaml from 'js-yaml';
7
+ import { resolveWin32Executable, buildWin32ExecFileSpawn } from '../cli-adapters/resolve-executable.js';
8
+ import {
9
+ isMeshConfigRecord,
10
+ normalizeMeshCommandConfig,
11
+ type MeshRefineValidationCommandPlan,
12
+ type RepoMeshRefineValidationCommandConfig,
13
+ } from './refine-config.js';
14
+ import type { MeshAsyncJobLifecycle } from '../repo-mesh-types.js';
15
+
16
+ // 'complete' is the terminal status the coordinator's markWorktreeBootstrapTerminalState
17
+ // (router.ts) stamps when the worktree_bootstrap_complete event fires — distinct from
18
+ // 'ready' (which carries a staleInputs digest from an in-process run). It is terminal and
19
+ // must be recognized as such by evaluateWorktreeBootstrapState so a later re-hydration never
20
+ // round-trips it back to 'stale'/'never_ran'.
21
+ export type WorktreeBootstrapStatus = 'ready' | 'complete' | 'running' | 'failed' | 'not_configured' | 'disabled' | 'stale';
22
+
23
+ export interface RepoMeshWorktreeBootstrapConfig {
24
+ version: 1;
25
+ enabled?: boolean;
26
+ runOnClone?: boolean;
27
+ required?: boolean;
28
+ commands?: RepoMeshRefineValidationCommandConfig[];
29
+ staleInputs?: string[];
30
+ }
31
+
32
+ export interface WorktreeBootstrapState extends MeshAsyncJobLifecycle {
33
+ status: WorktreeBootstrapStatus;
34
+ required: boolean;
35
+ configSource?: string;
36
+ configSourceType?: 'repo_file' | 'mesh_policy' | 'unavailable' | 'invalid';
37
+ lastCommand?: string;
38
+ exitCode?: number | null;
39
+ commandsRun?: Array<Record<string, unknown>>;
40
+ staleInputs?: string[];
41
+ /**
42
+ * M2-1: sha256 per staleInputs path recorded when the bootstrap reached
43
+ * 'ready'. evaluateWorktreeBootstrapState compares current file hashes
44
+ * against this to detect staleness (e.g. base merge changed a lockfile).
45
+ * Missing files hash to the literal 'absent'.
46
+ */
47
+ staleInputsDigest?: Record<string, string>;
48
+ /** M2-1: why an evaluated state resolved to stale (digest_mismatch | never_ran). */
49
+ staleReason?: string;
50
+ }
51
+
52
+ // Fix (3) safety net: a worktree node whose bootstrap state is stuck 'running' far longer than
53
+ // any real bootstrap (observed ~2m8s) is almost certainly one whose terminal-state stamp never
54
+ // reached this daemon's mesh view — the claim/dispatch defer guards would otherwise gate it
55
+ // forever. This backstop lets a dispatch through ONLY when BOTH hold: the 'running' state is
56
+ // older than WORKTREE_BOOTSTRAP_STALE_RUNNING_MS AND the node's working tree is git-clean. The
57
+ // clean co-requirement is the real guard — a genuinely in-progress bootstrap (npm install /
58
+ // native-addon repair) leaves the tree mid-build, so a clean tree means the bootstrap work has
59
+ // settled. The threshold is floored well above the observed real bootstrap so a slow-but-live
60
+ // bootstrap is never downgraded. Conservative by design: when clean-ness cannot be verified (no
61
+ // local workspace on disk, or git errors) it returns false and the gate stays closed.
62
+ export const WORKTREE_BOOTSTRAP_STALE_RUNNING_MS = 10 * 60 * 1000;
63
+
64
+ /**
65
+ * Enumerate registered submodule paths for a worktree, generically (no hardcoded
66
+ * 'oss'/'adhdev-providers'). Reads `.gitmodules` via `git config --file .gitmodules
67
+ * --get-regexp path`, whose lines are `submodule.<name>.path <relativePath>`. Paths
68
+ * are returned normalized to forward slashes (git porcelain always emits '/'),
69
+ * trailing slash stripped. Returns an empty set when there are no submodules or the
70
+ * lookup fails — callers must then treat any change as dirty (conservative).
71
+ */
72
+ export function getRegisteredSubmodulePaths(workspace: string): Set<string> {
73
+ const paths = new Set<string>();
74
+ try {
75
+ const out = execFileSync(
76
+ resolveWin32Executable('git'),
77
+ ['config', '--file', '.gitmodules', '--get-regexp', 'path'],
78
+ { cwd: workspace, encoding: 'utf8', timeout: 10_000, windowsHide: true },
79
+ );
80
+ for (const line of String(out).split(/\r?\n/)) {
81
+ const trimmed = line.trim();
82
+ if (!trimmed) continue;
83
+ // `submodule.<name>.path <relativePath>` — value is everything after the first space.
84
+ const spaceIdx = trimmed.indexOf(' ');
85
+ if (spaceIdx < 0) continue;
86
+ const value = trimmed.slice(spaceIdx + 1).trim().replace(/\\/g, '/').replace(/\/+$/, '');
87
+ if (value) paths.add(value);
88
+ }
89
+ } catch {
90
+ // No .gitmodules / not a submodule superproject / git error → no exemptions.
91
+ }
92
+ return paths;
93
+ }
94
+
95
+ /**
96
+ * Read each registered submodule's configured `branch` from `.gitmodules`, keyed
97
+ * by the submodule's normalized path (matching {@link getRegisteredSubmodulePaths}).
98
+ *
99
+ * `.gitmodules` stores `submodule.<name>.path` and (optionally)
100
+ * `submodule.<name>.branch`; this joins the two on `<name>`. The special branch
101
+ * value `.` ("track the superproject's branch") is deliberately OMITTED so callers
102
+ * fall through to remote-HEAD detection instead of treating `.` as a literal branch
103
+ * name. Returns an empty map when there are no submodules, no `.gitmodules`, or the
104
+ * lookup fails (conservative — callers then detect or fall back).
105
+ */
106
+ export function getSubmoduleConfiguredBranches(workspace: string): Map<string, string> {
107
+ const branchesByPath = new Map<string, string>();
108
+ try {
109
+ const out = execFileSync(
110
+ resolveWin32Executable('git'),
111
+ ['config', '--file', '.gitmodules', '--list'],
112
+ { cwd: workspace, encoding: 'utf8', timeout: 10_000, windowsHide: true },
113
+ );
114
+ // Join `submodule.<name>.path` with `submodule.<name>.branch` on <name>.
115
+ const pathByName = new Map<string, string>();
116
+ const branchByName = new Map<string, string>();
117
+ for (const line of String(out).split(/\r?\n/)) {
118
+ const trimmed = line.trim();
119
+ if (!trimmed) continue;
120
+ const eq = trimmed.indexOf('=');
121
+ if (eq < 0) continue;
122
+ const key = trimmed.slice(0, eq);
123
+ const value = trimmed.slice(eq + 1).trim();
124
+ // key: submodule.<name>.<field>; <name> may itself contain dots, so match
125
+ // the leading `submodule.` and trailing `.<field>` and take the middle.
126
+ const match = /^submodule\.(.+)\.(path|branch)$/.exec(key);
127
+ if (!match) continue;
128
+ const name = match[1];
129
+ if (match[2] === 'path') {
130
+ const norm = value.replace(/\\/g, '/').replace(/\/+$/, '');
131
+ if (norm) pathByName.set(name, norm);
132
+ } else if (value) {
133
+ branchByName.set(name, value);
134
+ }
135
+ }
136
+ for (const [name, submodulePath] of pathByName) {
137
+ const branch = branchByName.get(name);
138
+ if (branch && branch !== '.') branchesByPath.set(submodulePath, branch);
139
+ }
140
+ } catch {
141
+ // No .gitmodules / git error → no configured branches.
142
+ }
143
+ return branchesByPath;
144
+ }
145
+
146
+ /** Fallback submodule branch when no configured/detected default can be resolved. */
147
+ export const SUBMODULE_DEFAULT_BRANCH_FALLBACK = 'main';
148
+
149
+ function isPlausibleBranchName(name: unknown): name is string {
150
+ return typeof name === 'string' && name.length > 0 && !/\s/.test(name) && name !== 'HEAD';
151
+ }
152
+
153
+ /**
154
+ * Resolve the default branch a submodule's commits are published to / checked for
155
+ * reachability against. Generalizes the previously hardcoded `main` so a submodule
156
+ * whose default branch is `master`/`trunk`/etc. is handled. Priority (each tier
157
+ * falls through to the next on miss/error):
158
+ *
159
+ * 1. `.gitmodules` `submodule.<name>.branch` (via {@link getSubmoduleConfiguredBranches};
160
+ * `.` is ignored) — an explicit, local, zero-cost declaration.
161
+ * 2. the submodule checkout's LOCAL remote HEAD: `git symbolic-ref --short
162
+ * refs/remotes/<remote>/HEAD` → strip the `<remote>/` prefix (no network).
163
+ * 3. the submodule remote's advertised HEAD: `git ls-remote --symref <remote> HEAD`
164
+ * → `ref: refs/heads/<branch>` (one network round-trip).
165
+ * 4. fallback {@link SUBMODULE_DEFAULT_BRANCH_FALLBACK} (`'main'`).
166
+ *
167
+ * Because the final fallback is `'main'` and every earlier tier that resolves `'main'`
168
+ * yields the same string, a repo whose submodules default to `main` (the common case)
169
+ * produces byte-identical downstream fetch/merge-base/push ref targets — only a
170
+ * read-only resolution probe is added.
171
+ */
172
+ export async function resolveSubmoduleDefaultBranch(opts: {
173
+ /** The submodule's local checkout — cwd for symbolic-ref / ls-remote. */
174
+ submoduleRepoPath: string;
175
+ /** The superproject workspace — for the `.gitmodules` branch lookup (tier 1). */
176
+ superprojectWorkspace?: string;
177
+ /** The submodule's path relative to the superproject (key into `.gitmodules`). */
178
+ submodulePath?: string;
179
+ /** Remote name (default `origin`). */
180
+ remote?: string;
181
+ /** Timeout for the local probe (tier 2); the network probe (tier 3) gets max(this, 30s). */
182
+ timeoutMs?: number;
183
+ }): Promise<string> {
184
+ const remote = opts.remote?.trim() || 'origin';
185
+ const localTimeout = opts.timeoutMs ?? 10_000;
186
+ const git = resolveWin32Executable('git');
187
+ const execFileAsync = promisify(execFile);
188
+
189
+ // Tier 1: .gitmodules configured branch (local, zero-cost).
190
+ if (opts.superprojectWorkspace && opts.submodulePath) {
191
+ try {
192
+ const normalized = opts.submodulePath.replace(/\\/g, '/').replace(/\/+$/, '');
193
+ const configured = getSubmoduleConfiguredBranches(opts.superprojectWorkspace).get(normalized);
194
+ if (isPlausibleBranchName(configured)) return configured;
195
+ } catch { /* fall through */ }
196
+ }
197
+
198
+ // Tier 2: the local remote HEAD (no network) — set by clone/`git remote set-head`.
199
+ try {
200
+ const { stdout } = await execFileAsync(
201
+ git,
202
+ ['symbolic-ref', '--short', `refs/remotes/${remote}/HEAD`],
203
+ { cwd: opts.submoduleRepoPath, encoding: 'utf8', timeout: localTimeout, windowsHide: true },
204
+ );
205
+ const short = String(stdout || '').trim();
206
+ const prefix = `${remote}/`;
207
+ const branch = short.startsWith(prefix) ? short.slice(prefix.length) : short;
208
+ if (isPlausibleBranchName(branch)) return branch;
209
+ } catch { /* fall through */ }
210
+
211
+ // Tier 3: the remote's advertised HEAD (one network round-trip).
212
+ try {
213
+ const { stdout } = await execFileAsync(
214
+ git,
215
+ ['ls-remote', '--symref', remote, 'HEAD'],
216
+ { cwd: opts.submoduleRepoPath, encoding: 'utf8', timeout: Math.max(localTimeout, 30_000), windowsHide: true },
217
+ );
218
+ const match = /^ref:\s+refs\/heads\/(\S+)\s+HEAD/m.exec(String(stdout || ''));
219
+ if (match && isPlausibleBranchName(match[1])) return match[1];
220
+ } catch { /* fall through */ }
221
+
222
+ return SUBMODULE_DEFAULT_BRANCH_FALLBACK;
223
+ }
224
+
225
+ /**
226
+ * True when `git status --porcelain` output represents a worktree that is clean
227
+ * EXCEPT for submodule-gitlink-pointer moves. A worktree task that commits inside a
228
+ * registered submodule (e.g. oss/) leaves the superproject's gitlink outOfSync — a
229
+ * porcelain line of exactly " M <submodulePath>" (or "M <submodulePath>") — which is
230
+ * a NORMAL product of that task and must NOT disqualify the stale backstop. Any other
231
+ * line (a real file edit, an untracked file, a staged add, an unmerged path) means the
232
+ * tree is genuinely dirty → not clean. We filter gitlink lines explicitly rather than
233
+ * using `git status --ignore-submodules=all`, which would also mask a submodule with
234
+ * genuinely-uncommitted *content* (=dirty still surfaces pointer moves we want to ignore;
235
+ * =all would over-suppress).
236
+ */
237
+ function isCleanIgnoringSubmoduleGitlinks(porcelain: string, submodulePaths: Set<string>): boolean {
238
+ const lines = porcelain.split(/\r?\n/).filter(line => line.length > 0);
239
+ for (const line of lines) {
240
+ // Porcelain v1 line: two status chars (XY) + space + path. A submodule gitlink
241
+ // pointer move shows X or Y as 'M' with the other position a space, e.g.
242
+ // " M oss" (worktree-modified) or "M oss" (index-modified). Quoted paths
243
+ // (core.quotePath) wrap in double-quotes — those never match a bare submodule path,
244
+ // so they correctly fall through as dirty.
245
+ const status = line.slice(0, 2);
246
+ const path = line.slice(3).trim().replace(/\\/g, '/').replace(/\/+$/, '');
247
+ const isGitlinkPointerMove = (status === ' M' || status === 'M ') && submodulePaths.has(path);
248
+ if (!isGitlinkPointerMove) return false; // any non-gitlink change → dirty
249
+ }
250
+ return true;
251
+ }
252
+
253
+ export function isWorktreeBootstrapStaleRunning(
254
+ node: { worktreeBootstrap?: { status?: string; startedAt?: string; updatedAt?: string; completedAt?: string }; workspace?: string } | undefined,
255
+ nowMs: number = Date.now(),
256
+ ): boolean {
257
+ const wb = node?.worktreeBootstrap;
258
+ if (!wb || wb.status !== 'running') return false;
259
+ const startedRaw = wb.updatedAt || wb.startedAt;
260
+ if (!startedRaw) return false;
261
+ const startedMs = Date.parse(startedRaw);
262
+ if (!Number.isFinite(startedMs)) return false;
263
+ if (nowMs - startedMs <= WORKTREE_BOOTSTRAP_STALE_RUNNING_MS) return false;
264
+ const workspace = typeof node?.workspace === 'string' ? node.workspace.trim() : '';
265
+ if (!workspace || !existsSync(workspace)) return false; // only verifiable for a local workspace
266
+ try {
267
+ const out = execFileSync(resolveWin32Executable('git'), ['status', '--porcelain'], {
268
+ cwd: workspace,
269
+ encoding: 'utf8',
270
+ timeout: 10_000,
271
+ windowsHide: true,
272
+ });
273
+ const porcelain = String(out).replace(/\r?\n$/, '');
274
+ if (porcelain.trim() === '') return true; // truly clean
275
+ // A worktree task that committed inside a submodule leaves the superproject's
276
+ // submodule-gitlink pointer outOfSync (" M oss"); that is the normal aftermath of the
277
+ // task this backstop exists to unstick, not an in-progress bootstrap, so a tree dirty
278
+ // ONLY by gitlink pointer moves still counts as clean here.
279
+ const submodulePaths = getRegisteredSubmodulePaths(workspace);
280
+ if (submodulePaths.size === 0) return false; // no submodules → no exemption, dirty
281
+ return isCleanIgnoringSubmoduleGitlinks(porcelain, submodulePaths);
282
+ } catch {
283
+ return false; // cannot verify clean → stay conservative (gate remains closed)
284
+ }
285
+ }
286
+
287
+ /**
288
+ * COMPLETION-PROPAGATION F7 (C2): the single shared consume-ready / bootstrap-pending defer
289
+ * predicate. A task must NOT be injected into a worktree node whose bootstrap is still 'running'
290
+ * — the provider is not yet ready to consume input, so the inject lands in the input buffer and
291
+ * is silently swallowed (empty session). Both the remote dispatch guard (the router agent_command
292
+ * handler) and the local queue-claim gate (tryAssignQueueTask) route through THIS predicate so
293
+ * they agree on exactly when to defer. Returns true = defer. The stale-'running' backstop
294
+ * (isWorktreeBootstrapStaleRunning) is honored here too: a 'running' state far older than any real
295
+ * bootstrap whose worktree is git-clean is treated as silently complete (do NOT defer), so a node
296
+ * whose terminal stamp never reached this daemon is not stranded forever.
297
+ */
298
+ export function shouldDeferDispatchForBootstrap(
299
+ node: { worktreeBootstrap?: { status?: string; startedAt?: string; updatedAt?: string; completedAt?: string }; workspace?: string } | undefined,
300
+ nowMs: number = Date.now(),
301
+ ): boolean {
302
+ if (node?.worktreeBootstrap?.status !== 'running') return false;
303
+ return !isWorktreeBootstrapStaleRunning(node, nowMs);
304
+ }
305
+
306
+ export interface WorktreeBootstrapConfigLoadResult {
307
+ config?: RepoMeshWorktreeBootstrapConfig;
308
+ source: string;
309
+ sourceType: 'repo_file' | 'mesh_policy' | 'unavailable' | 'invalid';
310
+ path?: string;
311
+ error?: string;
312
+ }
313
+
314
+ export const MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
315
+ '.adhdev/worktree_bootstrap.json',
316
+ '.adhdev/worktree_bootstrap.yaml',
317
+ '.adhdev/worktree_bootstrap.yml',
318
+ '.adhdev/worktree-bootstrap.json',
319
+ '.adhdev/worktree-bootstrap.yaml',
320
+ '.adhdev/worktree-bootstrap.yml',
321
+ ];
322
+
323
+ export const MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA = {
324
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
325
+ title: 'ADHDev Repo Mesh Worktree Bootstrap Config',
326
+ type: 'object',
327
+ additionalProperties: false,
328
+ required: ['version'],
329
+ properties: {
330
+ version: { const: 1 },
331
+ enabled: { type: 'boolean', default: true },
332
+ runOnClone: { type: 'boolean', default: true },
333
+ required: { type: 'boolean', default: true },
334
+ staleInputs: { type: 'array', maxItems: 16, items: { type: 'string', minLength: 1 } },
335
+ commands: {
336
+ type: 'array',
337
+ minItems: 1,
338
+ maxItems: 4,
339
+ items: {
340
+ type: 'object',
341
+ additionalProperties: false,
342
+ required: ['command'],
343
+ properties: {
344
+ command: { type: 'string', minLength: 1 },
345
+ args: { type: 'array', items: { type: 'string' } },
346
+ category: { enum: ['typecheck', 'test', 'lint', 'build', 'custom'] },
347
+ cwd: { type: 'string' },
348
+ timeoutMs: { type: 'number', minimum: 1000, maximum: 600000 },
349
+ outputLimitBytes: { type: 'number', minimum: 1024, maximum: 1048576 },
350
+ env: { type: 'object', additionalProperties: { type: 'string' } },
351
+ },
352
+ },
353
+ },
354
+ },
355
+ } as const;
356
+
357
+ const DEFAULT_TIMEOUT_MS = 120_000;
358
+ const DEFAULT_OUTPUT_LIMIT_BYTES = 128 * 1024;
359
+ const OUTPUT_SUMMARY_CHARS = 2_000;
360
+
361
+ function parseConfigText(path: string, text: string): unknown {
362
+ if (/\.json$/i.test(path)) return JSON.parse(text);
363
+ return yaml.load(text);
364
+ }
365
+
366
+ function truncateOutput(value: unknown): string {
367
+ const text = typeof value === 'string' ? value : value == null ? '' : String(value);
368
+ if (text.length <= OUTPUT_SUMMARY_CHARS) return text;
369
+ return `${text.slice(0, OUTPUT_SUMMARY_CHARS)}\n[truncated ${text.length - OUTPUT_SUMMARY_CHARS} chars]`;
370
+ }
371
+
372
+ export function validateMeshWorktreeBootstrapConfig(config: unknown, source = 'inline'): {
373
+ valid: boolean;
374
+ errors: string[];
375
+ commands: MeshRefineValidationCommandPlan[];
376
+ rejectedCommands: Array<Record<string, unknown>>;
377
+ } {
378
+ const errors: string[] = [];
379
+ const commands: MeshRefineValidationCommandPlan[] = [];
380
+ const rejectedCommands: Array<Record<string, unknown>> = [];
381
+ if (!isMeshConfigRecord(config)) return { valid: false, errors: ['config must be an object'], commands, rejectedCommands };
382
+ if (config.version !== 1) errors.push('version must be 1');
383
+ if (config.enabled !== undefined && typeof config.enabled !== 'boolean') errors.push('enabled must be a boolean when provided');
384
+ if (config.runOnClone !== undefined && typeof config.runOnClone !== 'boolean') errors.push('runOnClone must be a boolean when provided');
385
+ if (config.required !== undefined && typeof config.required !== 'boolean') errors.push('required must be a boolean when provided');
386
+ if (config.staleInputs !== undefined && (!Array.isArray(config.staleInputs) || !config.staleInputs.every(input => typeof input === 'string' && input.trim()))) {
387
+ errors.push('staleInputs must be an array of non-empty strings when provided');
388
+ }
389
+ if (config.commands !== undefined && !Array.isArray(config.commands)) errors.push('commands must be an array');
390
+ if (Array.isArray(config.commands)) {
391
+ config.commands.forEach((entry, index) => {
392
+ const normalized = normalizeMeshCommandConfig(entry, `${source}:commands[${index}]`);
393
+ if (normalized.command) commands.push(normalized.command);
394
+ if (normalized.rejected) rejectedCommands.push(normalized.rejected);
395
+ });
396
+ }
397
+ if (config.enabled !== false && config.runOnClone !== false && commands.length === 0) errors.push('commands must contain at least one command when bootstrap is enabled');
398
+ if (rejectedCommands.length) errors.push('one or more bootstrap commands are invalid');
399
+ return { valid: errors.length === 0, errors, commands, rejectedCommands };
400
+ }
401
+
402
+ export function loadMeshWorktreeBootstrapConfig(mesh: any, workspace: string): WorktreeBootstrapConfigLoadResult {
403
+ const inline = mesh?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrapConfig || mesh?.policy?.worktreeBootstrap;
404
+ if (inline !== undefined) {
405
+ const validation = validateMeshWorktreeBootstrapConfig(inline, 'mesh.policy.worktreeBootstrapConfig');
406
+ if (!validation.valid) return { source: 'mesh.policy.worktreeBootstrapConfig', sourceType: 'invalid', error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')) };
407
+ return { config: inline as RepoMeshWorktreeBootstrapConfig, source: 'mesh.policy.worktreeBootstrapConfig', sourceType: 'mesh_policy' };
408
+ }
409
+ for (const relative of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
410
+ const configPath = join(workspace, relative);
411
+ if (!existsSync(configPath)) continue;
412
+ try {
413
+ const parsed = parseConfigText(configPath, readFileSync(configPath, 'utf-8'));
414
+ const validation = validateMeshWorktreeBootstrapConfig(parsed, relative);
415
+ if (!validation.valid) return { source: relative, sourceType: 'invalid', path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')) };
416
+ return { config: parsed as RepoMeshWorktreeBootstrapConfig, source: relative, sourceType: 'repo_file', path: configPath };
417
+ } catch (error: any) {
418
+ return { source: relative, sourceType: 'invalid', path: configPath, error: error?.message || String(error) };
419
+ }
420
+ }
421
+ return { source: 'unavailable', sourceType: 'unavailable', error: `No worktree bootstrap config found. Checked: ${MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS.join(', ')}` };
422
+ }
423
+
424
+ /** M2-1: hash staleInputs files so 'ready' can be invalidated when they change. */
425
+ export function computeStaleInputsDigest(workspace: string, staleInputs: string[] | undefined): Record<string, string> {
426
+ const digest: Record<string, string> = {};
427
+ for (const relative of staleInputs ?? []) {
428
+ const filePath = join(workspace, relative);
429
+ try {
430
+ digest[relative] = createHash('sha256').update(readFileSync(filePath)).digest('hex');
431
+ } catch {
432
+ digest[relative] = 'absent';
433
+ }
434
+ }
435
+ return digest;
436
+ }
437
+
438
+ /**
439
+ * M2-1: the official bootstrap state contract. Resolves the effective state
440
+ * for a node workspace from config presence + the persisted last-run state +
441
+ * a staleInputs digest comparison. Read-only — never runs commands.
442
+ *
443
+ * ready — last run succeeded and staleInputs are unchanged
444
+ * stale — never ran, or a staleInputs file changed since 'ready'
445
+ * running/failed — persisted lifecycle state passes through
446
+ * not_configured / disabled / (invalid → failed) — from config resolution
447
+ */
448
+ export function evaluateWorktreeBootstrapState(mesh: any, workspace: string, persisted?: WorktreeBootstrapState | null): WorktreeBootstrapState {
449
+ const loaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
450
+ if (!loaded.config) {
451
+ return { status: 'not_configured', required: false, configSource: loaded.source, configSourceType: loaded.sourceType, error: loaded.error };
452
+ }
453
+ const required = loaded.config.required !== false;
454
+ if (loaded.config.enabled === false || loaded.config.runOnClone === false) {
455
+ return { status: 'disabled', required, configSource: loaded.path || loaded.source, configSourceType: loaded.sourceType };
456
+ }
457
+ if (loaded.sourceType === 'invalid') {
458
+ return { status: 'failed', required, configSource: loaded.path || loaded.source, configSourceType: 'invalid', error: loaded.error };
459
+ }
460
+ if (persisted?.status === 'running') return { ...persisted, required };
461
+ if (persisted?.status === 'failed') return { ...persisted, required };
462
+ // 'complete' is the terminal stamp written by markWorktreeBootstrapTerminalState
463
+ // (router.ts) on the worktree_bootstrap_complete event. Pass it through unchanged so a
464
+ // later getMeshWithCache re-hydration never re-derives it back to 'stale'/'never_ran' —
465
+ // doing so would reopen the dispatch/claim gate against a node whose bootstrap is done.
466
+ if (persisted?.status === 'complete') return { ...persisted, required };
467
+ if (persisted?.status === 'ready') {
468
+ const staleInputs = loaded.config.staleInputs ?? persisted.staleInputs ?? [];
469
+ if (staleInputs.length > 0 && persisted.staleInputsDigest) {
470
+ const current = computeStaleInputsDigest(workspace, staleInputs);
471
+ const changed = staleInputs.filter(p => current[p] !== persisted.staleInputsDigest![p]);
472
+ if (changed.length > 0) {
473
+ return {
474
+ ...persisted,
475
+ status: 'stale',
476
+ required,
477
+ staleReason: `digest_mismatch: ${changed.join(', ')}`,
478
+ };
479
+ }
480
+ }
481
+ return { ...persisted, required };
482
+ }
483
+ return {
484
+ status: 'stale',
485
+ required,
486
+ configSource: loaded.path || loaded.source,
487
+ configSourceType: loaded.sourceType,
488
+ staleInputs: loaded.config.staleInputs,
489
+ staleReason: 'never_ran',
490
+ };
491
+ }
492
+
493
+ export async function runMeshWorktreeBootstrap(mesh: any, workspace: string): Promise<WorktreeBootstrapState> {
494
+ const loaded = loadMeshWorktreeBootstrapConfig(mesh, workspace);
495
+ if (!loaded.config) {
496
+ return { status: 'not_configured', required: false, configSource: loaded.source, configSourceType: loaded.sourceType, error: loaded.error };
497
+ }
498
+ const required = loaded.config.required !== false;
499
+ if (loaded.config.enabled === false || loaded.config.runOnClone === false) {
500
+ return { status: 'disabled', required, configSource: loaded.path || loaded.source, configSourceType: loaded.sourceType };
501
+ }
502
+ const validation = validateMeshWorktreeBootstrapConfig(loaded.config, loaded.source);
503
+ if (!validation.valid) {
504
+ return { status: 'failed', required, configSource: loaded.path || loaded.source, configSourceType: 'invalid', error: String(validation.rejectedCommands[0]?.reason || validation.errors.join('; ')), commandsRun: [] };
505
+ }
506
+
507
+ const execFileAsync = promisify(execFile);
508
+ const state: WorktreeBootstrapState = {
509
+ status: 'running',
510
+ required,
511
+ configSource: loaded.path || loaded.source,
512
+ configSourceType: loaded.sourceType,
513
+ startedAt: new Date().toISOString(),
514
+ commandsRun: [],
515
+ staleInputs: loaded.config.staleInputs,
516
+ };
517
+ const staleInputPaths = loaded.config.staleInputs ?? [];
518
+ // Snapshot which staleInputs files are absent at bootstrap start.
519
+ // Files already present before we start are not interference signals.
520
+ const initiallyAbsent = staleInputPaths.filter(p => !existsSync(join(workspace, p)));
521
+ for (const command of validation.commands) {
522
+ // Check if any initially-absent staleInputs files appeared since bootstrap started
523
+ // (indicates another process modified the environment mid-run).
524
+ if (initiallyAbsent.length > 0) {
525
+ const appearedNow = initiallyAbsent.filter(p => existsSync(join(workspace, p)));
526
+ if (appearedNow.length > 0) {
527
+ state.status = 'stale';
528
+ state.completedAt = new Date().toISOString();
529
+ state.error = `Bootstrap interrupted: staleInputs files appeared during run: ${appearedNow.join(', ')}`;
530
+ return state;
531
+ }
532
+ }
533
+ const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
534
+ const startedAt = Date.now();
535
+ state.lastCommand = command.displayCommand;
536
+ // On win32 a bare npm/npx/tsc is a .cmd shim that libuv's spawn search
537
+ // (which appends only .com/.exe) cannot resolve → spawn ENOENT. Resolve
538
+ // to an absolute path first (no-op on non-win32 / already-absolute).
539
+ const resolvedCommand = resolveWin32Executable(command.command);
540
+ // A win32 .cmd/.bat shim (npm/npx/tsc) cannot be exec'd directly — wrap
541
+ // it in cmd.exe /c (no-op off win32 / for a real .exe).
542
+ const spawn = buildWin32ExecFileSpawn(resolvedCommand, command.args);
543
+ try {
544
+ const result = await execFileAsync(spawn.file, spawn.args, {
545
+ cwd,
546
+ encoding: 'utf8',
547
+ timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS,
548
+ maxBuffer: command.outputLimitBytes || DEFAULT_OUTPUT_LIMIT_BYTES,
549
+ env: { ...process.env, CI: process.env.CI || '1', ...(command.env || {}) },
550
+ windowsHide: true,
551
+ ...(spawn.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}),
552
+ });
553
+ state.commandsRun?.push({
554
+ command: command.command,
555
+ args: command.args,
556
+ displayCommand: command.displayCommand,
557
+ category: command.category,
558
+ source: command.source,
559
+ cwd,
560
+ passed: true,
561
+ durationMs: Date.now() - startedAt,
562
+ exitCode: 0,
563
+ stdout: truncateOutput(result.stdout),
564
+ stderr: truncateOutput(result.stderr),
565
+ });
566
+ } catch (error: any) {
567
+ const exitCode = typeof error?.code === 'number' ? error.code : null;
568
+ state.status = 'failed';
569
+ state.exitCode = exitCode;
570
+ state.error = error?.message || String(error);
571
+ state.completedAt = new Date().toISOString();
572
+ state.commandsRun?.push({
573
+ command: command.command,
574
+ args: command.args,
575
+ displayCommand: command.displayCommand,
576
+ category: command.category,
577
+ source: command.source,
578
+ cwd,
579
+ passed: false,
580
+ durationMs: Date.now() - startedAt,
581
+ exitCode,
582
+ signal: typeof error?.signal === 'string' ? error.signal : null,
583
+ timedOut: error?.killed === true || /timed out/i.test(String(error?.message || '')),
584
+ stdout: truncateOutput(error?.stdout),
585
+ stderr: truncateOutput(error?.stderr || error?.message),
586
+ });
587
+ return state;
588
+ }
589
+ }
590
+ state.status = 'ready';
591
+ state.exitCode = 0;
592
+ state.completedAt = new Date().toISOString();
593
+ // M2-1: record staleInputs hashes so evaluateWorktreeBootstrapState can
594
+ // invalidate this 'ready' when an input (e.g. lockfile) changes later.
595
+ if (staleInputPaths.length > 0) {
596
+ state.staleInputsDigest = computeStaleInputsDigest(workspace, staleInputPaths);
597
+ }
598
+ return state;
599
+ }