@adhdev/daemon-core 0.9.82-rc.37 → 0.9.82-rc.371

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 (384) 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 +55 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +116 -64
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  12. package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
  13. package/dist/cli-adapters/provider-cli-shared.d.ts +63 -0
  14. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  15. package/dist/cli-adapters/resolve-executable.d.ts +14 -0
  16. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  17. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  18. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  19. package/dist/commands/chat-commands.d.ts +27 -0
  20. package/dist/commands/cli-manager.d.ts +15 -1
  21. package/dist/commands/handler.d.ts +125 -0
  22. package/dist/commands/high-family/index.d.ts +3 -0
  23. package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
  24. package/dist/commands/high-family/mesh-events.d.ts +2 -0
  25. package/dist/commands/high-family/mesh-status.d.ts +2 -0
  26. package/dist/commands/high-family/types.d.ts +60 -0
  27. package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
  28. package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
  29. package/dist/commands/low-family/diagnostics.d.ts +2 -0
  30. package/dist/commands/low-family/index.d.ts +3 -0
  31. package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
  32. package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
  33. package/dist/commands/low-family/notification.d.ts +2 -0
  34. package/dist/commands/low-family/refine-config.d.ts +2 -0
  35. package/dist/commands/low-family/session-host.d.ts +2 -0
  36. package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
  37. package/dist/commands/low-family/status-meta.d.ts +2 -0
  38. package/dist/commands/low-family/types.d.ts +33 -0
  39. package/dist/commands/med-family/cli-agent.d.ts +2 -0
  40. package/dist/commands/med-family/fast-forward.d.ts +2 -0
  41. package/dist/commands/med-family/ide.d.ts +10 -0
  42. package/dist/commands/med-family/index.d.ts +3 -0
  43. package/dist/commands/med-family/mesh-crud.d.ts +2 -0
  44. package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
  45. package/dist/commands/med-family/mesh-queue.d.ts +2 -0
  46. package/dist/commands/med-family/mesh-restart.d.ts +2 -0
  47. package/dist/commands/med-family/types.d.ts +116 -0
  48. package/dist/commands/mesh-coordinator.d.ts +85 -1
  49. package/dist/commands/router.d.ts +666 -2
  50. package/dist/commands/upgrade-helper.d.ts +41 -1
  51. package/dist/config/chat-history.d.ts +9 -0
  52. package/dist/config/config.d.ts +5 -0
  53. package/dist/config/mesh-config.d.ts +77 -1
  54. package/dist/daemon/dev-server.d.ts +0 -2
  55. package/dist/detection/ide-detector.d.ts +13 -0
  56. package/dist/detection/win32-ide-version.d.ts +37 -0
  57. package/dist/git/change-impact-config.d.ts +159 -0
  58. package/dist/git/git-commands.d.ts +11 -1
  59. package/dist/git/git-diff.d.ts +6 -0
  60. package/dist/git/git-executor.d.ts +11 -0
  61. package/dist/git/git-status.d.ts +23 -0
  62. package/dist/git/git-types.d.ts +2 -50
  63. package/dist/git/index.d.ts +2 -0
  64. package/dist/index.d.ts +55 -13
  65. package/dist/index.js +46565 -19737
  66. package/dist/index.js.map +1 -1
  67. package/dist/index.mjs +43563 -16868
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/installer.d.ts +1 -4
  70. package/dist/ipc/local-ipc-server.d.ts +91 -0
  71. package/dist/launch.d.ts +1 -1
  72. package/dist/logging/async-batch-writer.d.ts +10 -0
  73. package/dist/logging/log-redactor.d.ts +24 -0
  74. package/dist/logging/log-tail-reader.d.ts +46 -0
  75. package/dist/logging/logger.d.ts +1 -1
  76. package/dist/mesh/contracts.d.ts +164 -0
  77. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  78. package/dist/mesh/coordinator-registry.d.ts +59 -0
  79. package/dist/mesh/mesh-active-work.d.ts +174 -0
  80. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  81. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  82. package/dist/mesh/mesh-events-coordinator.d.ts +91 -0
  83. package/dist/mesh/mesh-events-pending.d.ts +55 -0
  84. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  85. package/dist/mesh/mesh-events-utils.d.ts +61 -0
  86. package/dist/mesh/mesh-events.d.ts +6 -49
  87. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  88. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  89. package/dist/mesh/mesh-init.d.ts +86 -0
  90. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  91. package/dist/mesh/mesh-ledger.d.ts +77 -1
  92. package/dist/mesh/mesh-missions.d.ts +164 -0
  93. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  94. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  95. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  96. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  97. package/dist/mesh/mesh-routing.d.ts +70 -0
  98. package/dist/mesh/mesh-runtime-store.d.ts +429 -0
  99. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  100. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  101. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  102. package/dist/mesh/mesh-work-queue.d.ts +246 -5
  103. package/dist/mesh/preview-freshness.d.ts +18 -0
  104. package/dist/mesh/refine-config.d.ts +216 -0
  105. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  106. package/dist/providers/acp-provider-instance.d.ts +5 -0
  107. package/dist/providers/approval-utils.d.ts +20 -0
  108. package/dist/providers/chat-message-normalization.d.ts +12 -0
  109. package/dist/providers/cli-provider-instance.d.ts +108 -3
  110. package/dist/providers/contracts.d.ts +139 -6
  111. package/dist/providers/external-sources.d.ts +71 -0
  112. package/dist/providers/manual-attendance.d.ts +63 -0
  113. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  114. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  115. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  116. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  117. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  118. package/dist/providers/native-history/index.d.ts +13 -0
  119. package/dist/providers/provider-instance-manager.d.ts +14 -0
  120. package/dist/providers/provider-instance.d.ts +23 -1
  121. package/dist/providers/provider-loader.d.ts +26 -4
  122. package/dist/providers/provider-trust.d.ts +31 -0
  123. package/dist/providers/read-chat-contract.d.ts +29 -0
  124. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  125. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  126. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  127. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  128. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  129. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  130. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  131. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  132. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  133. package/dist/providers/sdk/v1/index.d.ts +30 -0
  134. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  135. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  136. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  137. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  138. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  139. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  140. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  141. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  142. package/dist/providers/spec/adapter.d.ts +91 -0
  143. package/dist/providers/spec/cli-adapter.d.ts +223 -0
  144. package/dist/providers/spec/evaluator.d.ts +45 -0
  145. package/dist/providers/spec/fsm-driver.d.ts +395 -0
  146. package/dist/providers/spec/fsm-evaluator.d.ts +76 -0
  147. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  148. package/dist/providers/spec/fsm-types.d.ts +174 -0
  149. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  150. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  151. package/dist/providers/spec/route.d.ts +4 -0
  152. package/dist/providers/spec/types.d.ts +222 -0
  153. package/dist/providers/status-monitor.d.ts +7 -7
  154. package/dist/providers/transcript-v2.d.ts +176 -0
  155. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  156. package/dist/providers/working-dir.d.ts +17 -0
  157. package/dist/repo-mesh-types.d.ts +295 -13
  158. package/dist/sessions/registry.d.ts +6 -0
  159. package/dist/shared-types-extra.d.ts +2 -4
  160. package/dist/shared-types.d.ts +59 -2
  161. package/dist/status/normalize.d.ts +1 -1
  162. package/dist/status/normalize.js +1 -0
  163. package/dist/status/normalize.js.map +1 -1
  164. package/dist/status/normalize.mjs +1 -0
  165. package/dist/status/normalize.mjs.map +1 -1
  166. package/dist/status/reporter.d.ts +2 -0
  167. package/dist/status/snapshot.d.ts +26 -0
  168. package/dist/system/hash.d.ts +8 -0
  169. package/dist/system/load-better-sqlite3.d.ts +21 -0
  170. package/dist/types.d.ts +5 -0
  171. package/package.json +7 -3
  172. package/src/agent-stream/poller.ts +2 -3
  173. package/src/agent-stream/provider-adapter.ts +1 -1
  174. package/src/boot/daemon-lifecycle.ts +63 -12
  175. package/src/boot/process-hardening.ts +89 -0
  176. package/src/build-info.ts +73 -0
  177. package/src/chat/source-machine.ts +534 -0
  178. package/src/chat/source-resolver.ts +0 -0
  179. package/src/chat/subscription-updates.ts +20 -1
  180. package/src/cli-adapter-types.d.ts +1 -0
  181. package/src/cli-adapter-types.ts +56 -2
  182. package/src/cli-adapters/cli-script-runner.ts +421 -0
  183. package/src/cli-adapters/cli-state-engine.ts +1221 -0
  184. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  185. package/src/cli-adapters/provider-cli-adapter.ts +775 -1141
  186. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  187. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  188. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  189. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  190. package/src/cli-adapters/provider-cli-shared.ts +110 -11
  191. package/src/cli-adapters/pty-transport.ts +2 -1
  192. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  193. package/src/cli-adapters/resolve-executable.ts +90 -0
  194. package/src/cli-adapters/session-host-transport.ts +2 -1
  195. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  196. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  197. package/src/cli-adapters/terminal-screen.ts +16 -81
  198. package/src/commands/WINDOWS-UPGRADE-LOCK-FAILURE.md +198 -0
  199. package/src/commands/chat-commands.ts +1917 -62
  200. package/src/commands/cli-manager.ts +502 -24
  201. package/src/commands/handler.ts +841 -2
  202. package/src/commands/high-family/index.ts +28 -0
  203. package/src/commands/high-family/mesh-coordinator-launch.ts +592 -0
  204. package/src/commands/high-family/mesh-events.ts +47 -0
  205. package/src/commands/high-family/mesh-status.ts +642 -0
  206. package/src/commands/high-family/types.ts +76 -0
  207. package/src/commands/low-family/coordinator-prompt.ts +72 -0
  208. package/src/commands/low-family/daemon-lifecycle.ts +107 -0
  209. package/src/commands/low-family/diagnostics.ts +57 -0
  210. package/src/commands/low-family/index.ts +37 -0
  211. package/src/commands/low-family/mesh-ledger.ts +62 -0
  212. package/src/commands/low-family/mesh-node-logs.ts +81 -0
  213. package/src/commands/low-family/notification.ts +116 -0
  214. package/src/commands/low-family/refine-config.ts +106 -0
  215. package/src/commands/low-family/session-host.ts +274 -0
  216. package/src/commands/low-family/spec-providerdev.ts +217 -0
  217. package/src/commands/low-family/status-meta.ts +112 -0
  218. package/src/commands/low-family/types.ts +39 -0
  219. package/src/commands/med-family/cli-agent.ts +218 -0
  220. package/src/commands/med-family/fast-forward.ts +198 -0
  221. package/src/commands/med-family/ide.ts +163 -0
  222. package/src/commands/med-family/index.ts +37 -0
  223. package/src/commands/med-family/mesh-crud.ts +788 -0
  224. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  225. package/src/commands/med-family/mesh-queue.ts +131 -0
  226. package/src/commands/med-family/mesh-restart.ts +92 -0
  227. package/src/commands/med-family/types.ts +120 -0
  228. package/src/commands/mesh-coordinator.ts +334 -124
  229. package/src/commands/router.ts +5121 -2369
  230. package/src/commands/stream-commands.ts +8 -0
  231. package/src/commands/upgrade-helper.ts +310 -45
  232. package/src/config/chat-history.ts +483 -24
  233. package/src/config/config.ts +12 -0
  234. package/src/config/mesh-config.ts +389 -6
  235. package/src/config/recent-activity.ts +8 -2
  236. package/src/daemon/dev-auto-implement.ts +3 -2
  237. package/src/daemon/dev-cli-debug.ts +10 -1
  238. package/src/daemon/dev-server.ts +0 -541
  239. package/src/detection/cli-detector.ts +28 -9
  240. package/src/detection/ide-detector.ts +55 -16
  241. package/src/detection/win32-ide-version.ts +106 -0
  242. package/src/git/change-impact-config.ts +354 -0
  243. package/src/git/git-commands.ts +55 -14
  244. package/src/git/git-diff.ts +81 -11
  245. package/src/git/git-executor.ts +12 -0
  246. package/src/git/git-status.ts +574 -43
  247. package/src/git/git-types.ts +14 -62
  248. package/src/git/git-worktree.ts +8 -1
  249. package/src/git/index.ts +16 -0
  250. package/src/index.ts +158 -12
  251. package/src/installer.d.ts +1 -1
  252. package/src/installer.ts +8 -6
  253. package/src/ipc/local-ipc-server.ts +278 -0
  254. package/src/launch.d.ts +1 -1
  255. package/src/launch.ts +37 -28
  256. package/src/logging/async-batch-writer.ts +55 -0
  257. package/src/logging/command-log.ts +7 -5
  258. package/src/logging/log-redactor.ts +100 -0
  259. package/src/logging/log-tail-reader.ts +220 -0
  260. package/src/logging/logger.ts +14 -7
  261. package/src/mesh/contracts.ts +338 -0
  262. package/src/mesh/coordinator-prompt.ts +234 -31
  263. package/src/mesh/coordinator-registry.ts +121 -0
  264. package/src/mesh/mesh-active-work.ts +645 -0
  265. package/src/mesh/mesh-delivery-policy.ts +315 -0
  266. package/src/mesh/mesh-event-trace.ts +67 -0
  267. package/src/mesh/mesh-events-coordinator.ts +2866 -0
  268. package/src/mesh/mesh-events-pending.ts +599 -0
  269. package/src/mesh/mesh-events-stale.ts +309 -0
  270. package/src/mesh/mesh-events-utils.ts +387 -0
  271. package/src/mesh/mesh-events.ts +30 -1035
  272. package/src/mesh/mesh-fast-forward.ts +839 -0
  273. package/src/mesh/mesh-host-ownership.ts +73 -0
  274. package/src/mesh/mesh-init.ts +260 -0
  275. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  276. package/src/mesh/mesh-ledger.ts +591 -102
  277. package/src/mesh/mesh-missions.ts +322 -0
  278. package/src/mesh/mesh-reconcile-loop.ts +1134 -0
  279. package/src/mesh/mesh-refine-batch.ts +197 -0
  280. package/src/mesh/mesh-refine-status.ts +231 -0
  281. package/src/mesh/mesh-review-inbox.ts +307 -0
  282. package/src/mesh/mesh-routing.ts +291 -0
  283. package/src/mesh/mesh-runtime-store.ts +1697 -0
  284. package/src/mesh/mesh-task-stats.ts +161 -0
  285. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  286. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  287. package/src/mesh/mesh-work-queue.ts +997 -141
  288. package/src/mesh/preview-freshness.ts +118 -0
  289. package/src/mesh/refine-config.ts +423 -0
  290. package/src/mesh/worktree-bootstrap-config.ts +331 -0
  291. package/src/providers/acp-provider-instance.ts +43 -10
  292. package/src/providers/approval-utils.d.ts +5 -0
  293. package/src/providers/approval-utils.ts +57 -5
  294. package/src/providers/chat-message-normalization.ts +45 -5
  295. package/src/providers/cli-provider-instance.ts +1310 -101
  296. package/src/providers/contracts.d.ts +55 -0
  297. package/src/providers/contracts.ts +150 -6
  298. package/src/providers/extension-provider-instance.ts +12 -7
  299. package/src/providers/external-sources.ts +218 -0
  300. package/src/providers/ide-provider-instance.ts +35 -12
  301. package/src/providers/manual-attendance.ts +85 -0
  302. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  303. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  304. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  305. package/src/providers/native-history/dispatcher.ts +340 -0
  306. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  307. package/src/providers/native-history/index.ts +30 -0
  308. package/src/providers/provider-instance-manager.ts +30 -0
  309. package/src/providers/provider-instance.ts +19 -1
  310. package/src/providers/provider-loader.ts +668 -50
  311. package/src/providers/provider-schema.ts +87 -14
  312. package/src/providers/provider-trust.ts +114 -0
  313. package/src/providers/read-chat-contract.ts +76 -16
  314. package/src/providers/sdk/README.md +49 -0
  315. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  316. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  317. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  318. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  319. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  320. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  321. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  322. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  323. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  324. package/src/providers/sdk/v1/index.ts +152 -0
  325. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  326. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  327. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  328. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  329. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  330. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  331. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  332. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  333. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  334. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  335. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  336. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  337. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  338. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  339. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  340. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  341. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  342. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  343. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  344. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  345. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  346. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  347. package/src/providers/sdk/v1/validators/index.ts +19 -0
  348. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  349. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  350. package/src/providers/spec/adapter.ts +235 -0
  351. package/src/providers/spec/cli-adapter.ts +1051 -0
  352. package/src/providers/spec/evaluator.ts +407 -0
  353. package/src/providers/spec/fsm-driver.ts +1305 -0
  354. package/src/providers/spec/fsm-evaluator.ts +272 -0
  355. package/src/providers/spec/fsm-loader.ts +120 -0
  356. package/src/providers/spec/fsm-types.ts +273 -0
  357. package/src/providers/spec/native-history-executor.ts +1136 -0
  358. package/src/providers/spec/pre-launch-trust.ts +104 -0
  359. package/src/providers/spec/route.ts +51 -0
  360. package/src/providers/spec/types.ts +262 -0
  361. package/src/providers/status-monitor.d.ts +7 -7
  362. package/src/providers/status-monitor.ts +37 -22
  363. package/src/providers/transcript-v2.ts +567 -0
  364. package/src/providers/types/interactive-prompt.ts +536 -0
  365. package/src/providers/version-archive.ts +64 -24
  366. package/src/providers/working-dir.ts +23 -0
  367. package/src/repo-mesh-types.ts +378 -14
  368. package/src/sessions/registry.ts +6 -0
  369. package/src/shared-types-extra.ts +2 -4
  370. package/src/shared-types.d.ts +8 -0
  371. package/src/shared-types.ts +64 -1
  372. package/src/status/builders.ts +26 -6
  373. package/src/status/normalize.ts +2 -0
  374. package/src/status/reporter.ts +19 -1
  375. package/src/status/snapshot.ts +95 -26
  376. package/src/system/hash.ts +23 -0
  377. package/src/system/host-memory.ts +29 -12
  378. package/src/system/load-better-sqlite3.ts +68 -0
  379. package/src/types.ts +5 -0
  380. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  381. package/dist/mesh/mesh-sync.d.ts +0 -53
  382. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  383. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  384. package/src/mesh/mesh-sync.ts +0 -111
@@ -0,0 +1,161 @@
1
+ /**
2
+ * M7: Operational stats (time/attempts) derived from existing truth.
3
+ *
4
+ * No cost/token accounting — ADHDev observes PTY/CDP and cannot see API
5
+ * tokens (explicit non-goal). Everything here is derived at query time from
6
+ * the SQLite ledger and queue rows; there is no separate aggregate table.
7
+ * Tasks with missing ledger evidence report incompleteEvidence instead of
8
+ * estimated numbers.
9
+ */
10
+
11
+ import { readLedgerEntries } from './mesh-ledger.js';
12
+ import type { MeshLedgerEntry } from './mesh-ledger.js';
13
+ import { getQueue } from './mesh-work-queue.js';
14
+
15
+ export interface MeshTaskStats {
16
+ taskId: string;
17
+ status: string;
18
+ dispatchedAt: string | null;
19
+ terminalAt: string | null;
20
+ terminalKind: 'task_completed' | 'task_failed' | null;
21
+ /** dispatched → terminal wall clock; null when evidence is incomplete. */
22
+ durationMs: number | null;
23
+ /** Number of task_dispatched ledger entries observed for this task. */
24
+ dispatchCount: number;
25
+ /** Queue requeueCount (0 when the row is gone or never requeued). */
26
+ requeueCount: number;
27
+ /** True when dispatch or terminal ledger evidence is missing — numbers are withheld, never estimated. */
28
+ incompleteEvidence?: true;
29
+ }
30
+
31
+ export interface MeshMissionStats {
32
+ missionId: string;
33
+ taskCount: number;
34
+ completed: number;
35
+ failed: number;
36
+ /** Sum of per-task durations with complete evidence. */
37
+ totalDurationMs: number;
38
+ /** First dispatch → last terminal across the mission's tasks; null without complete endpoints. */
39
+ wallClockMs: number | null;
40
+ /** Total requeue attempts across the mission's tasks. */
41
+ retries: number;
42
+ /** Task ids whose ledger evidence was incomplete (excluded from sums). */
43
+ incompleteTaskIds: string[];
44
+ }
45
+
46
+ function readPayloadTaskId(entry: MeshLedgerEntry): string {
47
+ const value = entry.payload?.taskId;
48
+ return typeof value === 'string' && value.trim() ? value.trim() : '';
49
+ }
50
+
51
+ function parseTime(value: string | null | undefined): number | null {
52
+ if (!value) return null;
53
+ const parsed = new Date(value).getTime();
54
+ return Number.isFinite(parsed) ? parsed : null;
55
+ }
56
+
57
+ /**
58
+ * Compute per-task stats from ledger entries. Scans a bounded tail window —
59
+ * stats are an operational view of recent work, not a full historical report.
60
+ */
61
+ export function computeMeshTaskStats(meshId: string, opts?: { taskIds?: string[]; missionId?: string; tail?: number }): MeshTaskStats[] {
62
+ const queue = getQueue(meshId);
63
+ const queueById = new Map(queue.map(task => [task.id, task]));
64
+
65
+ let targetIds: string[];
66
+ if (opts?.taskIds?.length) {
67
+ targetIds = [...new Set(opts.taskIds)];
68
+ } else if (opts?.missionId) {
69
+ targetIds = queue.filter(task => task.missionId === opts.missionId).map(task => task.id);
70
+ } else {
71
+ targetIds = queue.map(task => task.id);
72
+ }
73
+ if (targetIds.length === 0) return [];
74
+ const targetSet = new Set(targetIds);
75
+
76
+ const entries = readLedgerEntries(meshId, { tail: opts?.tail ?? 1000 });
77
+ const dispatches = new Map<string, { first: string; count: number }>();
78
+ const terminals = new Map<string, { at: string; kind: 'task_completed' | 'task_failed' }>();
79
+ for (const entry of entries) {
80
+ const taskId = readPayloadTaskId(entry);
81
+ if (!taskId || !targetSet.has(taskId)) continue;
82
+ if (entry.kind === 'task_dispatched') {
83
+ const existing = dispatches.get(taskId);
84
+ if (existing) existing.count += 1;
85
+ else dispatches.set(taskId, { first: entry.timestamp, count: 1 });
86
+ } else if (entry.kind === 'task_completed' || entry.kind === 'task_failed') {
87
+ // Last terminal wins (requeued tasks can have multiple terminals).
88
+ terminals.set(taskId, { at: entry.timestamp, kind: entry.kind });
89
+ }
90
+ }
91
+
92
+ return targetIds.map(taskId => {
93
+ const queueEntry = queueById.get(taskId);
94
+ const dispatch = dispatches.get(taskId);
95
+ const terminal = terminals.get(taskId);
96
+ // Direct dispatches (mesh_send_task) have no work-queue row, so queueEntry is undefined.
97
+ // Derive a terminal status from the attributed terminal ledger entry instead of reporting
98
+ // status='unknown' — without this a completed direct task showed unknown + terminalKind=null
99
+ // even though its task_completed event fired (see mesh-events-coordinator Fix B attribution).
100
+ const status = queueEntry?.status
101
+ ?? (terminal
102
+ ? (terminal.kind === 'task_completed' ? 'completed' : 'failed')
103
+ : 'unknown');
104
+ const isTerminalStatus = status === 'completed' || status === 'failed' || status === 'cancelled';
105
+ const dispatchTime = parseTime(dispatch?.first ?? queueEntry?.dispatchTimestamp);
106
+ const terminalTime = parseTime(terminal?.at);
107
+ const stats: MeshTaskStats = {
108
+ taskId,
109
+ status,
110
+ dispatchedAt: dispatch?.first ?? queueEntry?.dispatchTimestamp ?? null,
111
+ terminalAt: terminal?.at ?? null,
112
+ terminalKind: terminal?.kind ?? null,
113
+ durationMs: null,
114
+ dispatchCount: dispatch?.count ?? 0,
115
+ requeueCount: queueEntry?.requeueCount ?? 0,
116
+ };
117
+ if (dispatchTime !== null && terminalTime !== null && terminalTime >= dispatchTime) {
118
+ stats.durationMs = terminalTime - dispatchTime;
119
+ } else if (isTerminalStatus) {
120
+ // Terminal task without complete dispatch+terminal ledger evidence:
121
+ // withhold numbers rather than estimate (M7 rule).
122
+ stats.incompleteEvidence = true;
123
+ }
124
+ return stats;
125
+ });
126
+ }
127
+
128
+ /** Mission rollup — derived from per-task stats, no stored aggregates. */
129
+ export function computeMeshMissionStats(meshId: string, missionId: string): MeshMissionStats {
130
+ const tasks = computeMeshTaskStats(meshId, { missionId });
131
+ const stats: MeshMissionStats = {
132
+ missionId,
133
+ taskCount: tasks.length,
134
+ completed: 0,
135
+ failed: 0,
136
+ totalDurationMs: 0,
137
+ wallClockMs: null,
138
+ retries: 0,
139
+ incompleteTaskIds: [],
140
+ };
141
+ let firstDispatch: number | null = null;
142
+ let lastTerminal: number | null = null;
143
+ for (const task of tasks) {
144
+ if (task.status === 'completed') stats.completed += 1;
145
+ else if (task.status === 'failed') stats.failed += 1;
146
+ stats.retries += task.requeueCount;
147
+ if (task.incompleteEvidence) {
148
+ stats.incompleteTaskIds.push(task.taskId);
149
+ continue;
150
+ }
151
+ if (task.durationMs !== null) stats.totalDurationMs += task.durationMs;
152
+ const dispatchTime = parseTime(task.dispatchedAt);
153
+ const terminalTime = parseTime(task.terminalAt);
154
+ if (dispatchTime !== null && (firstDispatch === null || dispatchTime < firstDispatch)) firstDispatch = dispatchTime;
155
+ if (terminalTime !== null && (lastTerminal === null || terminalTime > lastTerminal)) lastTerminal = terminalTime;
156
+ }
157
+ if (firstDispatch !== null && lastTerminal !== null && lastTerminal >= firstDispatch) {
158
+ stats.wallClockMs = lastTerminal - firstDispatch;
159
+ }
160
+ return stats;
161
+ }
@@ -0,0 +1,185 @@
1
+ // ---------------------------------------------------------------------------
2
+ // mesh-unresolved-forward-outbox — durable retry for unresolved-delegate forwards
3
+ // ---------------------------------------------------------------------------
4
+ // A REMOTE worker daemon that is P2P-remote-controlled by a coordinator is NOT a
5
+ // member of the coordinator's mesh — it has no local mesh record. So when its
6
+ // completion event reaches setupMeshEventForwarding, resolveWorkerDelegateRouting
7
+ // returns mesh_unresolved: the worker carries the coordinator daemon anchor but no
8
+ // resolvable mesh id, so the normal queue-then-coordinator-pull path can't be used
9
+ // (the coordinator's reconcile PHASE 1 only pulls mesh.nodes, and this worker is in
10
+ // none of them — see docs/refactoring/2026-06-16-mesh-completion-polling-single-model.md).
11
+ //
12
+ // The ONLY delivery route for this case is a directed push to the coordinator
13
+ // daemon (mesh_forward_event over P2P). Previously that push was fire-and-forget:
14
+ // a single dispatchMeshCommand whose rejection was only logged, so one transient
15
+ // P2P failure dropped the completion forever (delivery_unroutable).
16
+ //
17
+ // This outbox makes that push DURABLE without inventing a new persistence layer:
18
+ // it reuses the existing mesh_pending_events SQLite table (the same store every
19
+ // other mesh coordinator event is persisted to), under a synthetic, reserved
20
+ // "mesh id" namespace so it never collides with a real mesh's queue. The worker's
21
+ // reconcile tick (PHASE 0) peeks the outbox, pushes each entry to its coordinator,
22
+ // and marks it drained (acked) ONLY on a successful push — a failed push leaves the
23
+ // row undrained for the next tick. Entries that exceed a max age are expired so the
24
+ // outbox can't grow unbounded when a coordinator stays permanently unreachable.
25
+ //
26
+ // Idempotency:
27
+ // - Enqueue is idempotent on the event fingerprint (mesh_pending_events has a
28
+ // UNIQUE (mesh_id, fingerprint) index + INSERT OR IGNORE), so the same
29
+ // completion fired twice on the worker queues once.
30
+ // - The receiver dedups independently: handleMeshForwardEvent → injectMeshSystemMessage
31
+ // → queuePendingMeshCoordinatorEvent recomputes the fingerprint and suppresses a
32
+ // duplicate, so an at-least-once retry that double-delivers is harmless.
33
+ // ---------------------------------------------------------------------------
34
+
35
+ import { randomUUID } from 'crypto';
36
+ import { LOG } from '../logging/logger.js';
37
+ import { MeshRuntimeStore } from './mesh-runtime-store.js';
38
+ import { buildPendingEventFingerprint, type PendingMeshCoordinatorEvent } from './mesh-events-pending.js';
39
+ import { readNonEmptyString } from './mesh-events-utils.js';
40
+
41
+ // Reserved synthetic mesh id for the worker-side unresolved-forward outbox. The `::`
42
+ // and leading `__` make it impossible to collide with a real mesh id (which are
43
+ // `mesh_*` / `mreg_*` slugs). Scoping rows by coordinator_daemon_id inside this one
44
+ // namespace lets a single worker forward to multiple coordinators.
45
+ export const UNRESOLVED_FORWARD_OUTBOX_MESH_ID = '__unresolved_forward_outbox__';
46
+
47
+ // Entries older than this are expired (dropped) rather than retried forever — a
48
+ // coordinator that has been unreachable this long is treated as gone. Generous
49
+ // enough to ride out a long coordinator outage / restart, bounded enough that a
50
+ // permanently-dead coordinator can't accumulate outbox rows indefinitely.
51
+ const UNRESOLVED_FORWARD_MAX_AGE_MS = 30 * 60 * 1000; // 30 minutes
52
+
53
+ export interface UnresolvedForwardEntry {
54
+ /** Row id in mesh_pending_events; pass back to ack/expire after a push attempt. */
55
+ id: string;
56
+ /** The coordinator daemon to push this event to (mesh_forward_event target). */
57
+ coordinatorDaemonId: string;
58
+ /** The flat payload to forward (already shaped for handleMeshForwardEvent). */
59
+ payload: Record<string, unknown>;
60
+ /** When the entry was first enqueued (epoch ms) — used for age-based expiry. */
61
+ queuedAt: number;
62
+ }
63
+
64
+ function getStore(): MeshRuntimeStore | undefined {
65
+ try { return MeshRuntimeStore.getInstance(); } catch { return undefined; }
66
+ }
67
+
68
+ /**
69
+ * Durably enqueue an unresolved-delegate forward for a coordinator daemon. The
70
+ * `forwardPayload` is the flat shape handleMeshForwardEvent reads on the coordinator.
71
+ * Idempotent on the event fingerprint. Returns true when a new row was written (or a
72
+ * duplicate was harmlessly ignored), false on a hard persistence failure.
73
+ */
74
+ export function enqueueUnresolvedDelegateForward(
75
+ coordinatorDaemonId: string,
76
+ eventName: string,
77
+ forwardPayload: Record<string, unknown>,
78
+ ): boolean {
79
+ const target = readNonEmptyString(coordinatorDaemonId);
80
+ const event = readNonEmptyString(eventName);
81
+ if (!target || !event) return false;
82
+ const store = getStore();
83
+ if (!store) return false;
84
+
85
+ const queuedAt = Date.now();
86
+ // Reuse the standard pending-event fingerprint so enqueue is idempotent AND the
87
+ // receiver's own dedup keys on a comparable identity. We synthesise the minimal
88
+ // PendingMeshCoordinatorEvent shape buildPendingEventFingerprint needs.
89
+ const fingerprintSource: PendingMeshCoordinatorEvent = {
90
+ event,
91
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
92
+ nodeLabel: readNonEmptyString(forwardPayload.nodeId) || readNonEmptyString(forwardPayload.workspace) || 'unresolved-delegate',
93
+ nodeId: readNonEmptyString(forwardPayload.nodeId) || undefined,
94
+ workspace: readNonEmptyString(forwardPayload.workspace) || undefined,
95
+ metadataEvent: forwardPayload,
96
+ queuedAt,
97
+ targetCoordinatorDaemonId: target,
98
+ };
99
+ // Scope the fingerprint to the coordinator so two coordinators awaiting the same
100
+ // worker session don't collapse into one outbox row.
101
+ const fingerprint = `${target}::${buildPendingEventFingerprint(fingerprintSource)}`;
102
+
103
+ try {
104
+ const inserted = store.insertPendingEvent({
105
+ id: randomUUID(),
106
+ meshId: UNRESOLVED_FORWARD_OUTBOX_MESH_ID,
107
+ coordinatorDaemonId: target,
108
+ event,
109
+ // Store the flat forward payload + the queue timestamp so the retry tick can
110
+ // rebuild the push args and apply age-based expiry without a schema change.
111
+ payload: { forwardPayload, coordinatorDaemonId: target, queuedAt },
112
+ fingerprint,
113
+ queuedAt,
114
+ });
115
+ if (inserted) {
116
+ LOG.info('MeshEvents', `Durably queued unresolved-delegate ${event} for coordinator ${target} (outbox)`);
117
+ }
118
+ return true;
119
+ } catch (e: any) {
120
+ LOG.warn('MeshEvents', `Failed to persist unresolved-delegate forward to outbox: ${e?.message || e}`);
121
+ return false;
122
+ }
123
+ }
124
+
125
+ /** Peek (non-destructive) every undrained outbox entry across all coordinators. */
126
+ export function peekUnresolvedDelegateForwards(): UnresolvedForwardEntry[] {
127
+ const store = getStore();
128
+ if (!store) return [];
129
+ let rows: Array<{ id: string; event: string; payload: unknown }>;
130
+ try {
131
+ rows = store.peekPendingEvents(UNRESOLVED_FORWARD_OUTBOX_MESH_ID);
132
+ } catch {
133
+ return [];
134
+ }
135
+ const out: UnresolvedForwardEntry[] = [];
136
+ for (const row of rows) {
137
+ const stored = row.payload && typeof row.payload === 'object' ? row.payload as Record<string, unknown> : {};
138
+ const coordinatorDaemonId = readNonEmptyString(stored.coordinatorDaemonId);
139
+ const forwardPayload = stored.forwardPayload && typeof stored.forwardPayload === 'object'
140
+ ? stored.forwardPayload as Record<string, unknown>
141
+ : undefined;
142
+ if (!coordinatorDaemonId || !forwardPayload) continue;
143
+ const queuedAt = typeof stored.queuedAt === 'number' ? stored.queuedAt : 0;
144
+ out.push({ id: row.id, coordinatorDaemonId, payload: forwardPayload, queuedAt });
145
+ }
146
+ return out;
147
+ }
148
+
149
+ /** Mark an outbox entry delivered (acked) after a successful push. */
150
+ export function ackUnresolvedDelegateForward(id: string): void {
151
+ const store = getStore();
152
+ if (!store) return;
153
+ try { store.markPendingEventsDrainedById([id]); } catch { /* best-effort */ }
154
+ }
155
+
156
+ /**
157
+ * Drop outbox entries that have exceeded the max retry age. Returns the count
158
+ * expired so the caller can log a fail-loud trace (a dropped completion is a real
159
+ * loss; it must be visible, not silent).
160
+ */
161
+ export function expireStaleUnresolvedDelegateForwards(nowMs: number = Date.now()): number {
162
+ const entries = peekUnresolvedDelegateForwards();
163
+ const staleIds = entries
164
+ .filter(e => e.queuedAt > 0 && nowMs - e.queuedAt >= UNRESOLVED_FORWARD_MAX_AGE_MS)
165
+ .map(e => e.id);
166
+ if (staleIds.length === 0) return 0;
167
+ const store = getStore();
168
+ if (!store) return 0;
169
+ try {
170
+ const removed = store.deletePendingEventsById(staleIds);
171
+ if (removed > 0) {
172
+ LOG.warn('MeshEvents', `Expired ${removed} unresolved-delegate forward(s) after ${Math.round(UNRESOLVED_FORWARD_MAX_AGE_MS / 60000)}m of failed retries — coordinator unreachable, completion dropped`);
173
+ }
174
+ return removed;
175
+ } catch {
176
+ return 0;
177
+ }
178
+ }
179
+
180
+ /** Test helper: purge the entire outbox. */
181
+ export function __clearUnresolvedDelegateForwardOutboxForTests(): void {
182
+ const store = getStore();
183
+ if (!store) return;
184
+ try { store.clearPendingEventsForMesh(UNRESOLVED_FORWARD_OUTBOX_MESH_ID); } catch { /* nothing to clear */ }
185
+ }
@@ -0,0 +1,152 @@
1
+ // ---------------------------------------------------------------------------
2
+ // mesh-warmup-deadline — cold-open-aware deadline for mesh P2P dispatches
3
+ // ---------------------------------------------------------------------------
4
+ // A dependency-free leaf so the warmup deadline + its connection-probe resolution
5
+ // can be shared by BOTH the dashboard git_status probe path (commands/router.ts)
6
+ // and the general task-dispatch path (mesh/mesh-events-coordinator.ts) without an
7
+ // import cycle (router ⇄ mesh-events). Pure except for timers + the injected
8
+ // `isConnected` probe, so it is unit-testable under fake timers with no real WebRTC.
9
+ // ---------------------------------------------------------------------------
10
+
11
+ /**
12
+ * Await `work` under a warmup-aware deadline so a cold-open DataChannel handshake
13
+ * is NOT charged against the command response budget — the root cause of the
14
+ * "first mesh dispatch to a cold peer false-times-out, the warm retry succeeds"
15
+ * signature. Two budgets, switched by the live peer connection state:
16
+ *
17
+ * - While `isConnected()` returns false the peer's channel is still opening; the
18
+ * cold-open `connectTimeoutMs` budget applies. This phase is deliberately
19
+ * generous because a TURN-relayed cross-machine handshake legitimately needs
20
+ * many seconds — but a genuine connect *failure* is surfaced by `work`
21
+ * rejecting on its own (the mesh manager fails the peer the instant its
22
+ * PeerConnection state goes terminal), so a real failure is never masked for
23
+ * the whole window.
24
+ * - The first time `isConnected()` returns true the channel is warm; from that
25
+ * instant the tight `responseTimeoutMs` governs how long the handler may take.
26
+ * Warm-channel callers therefore see behavior identical to the old single
27
+ * `Promise.race(work, responseTimeoutMs)`.
28
+ *
29
+ * Rejects with `Error('timeout')` when either budget is exhausted, mirroring the
30
+ * previous single-race contract. When no connection getter is wired callers must
31
+ * NOT pass `() => true` ("always warm") — that re-introduces the cold-open
32
+ * false-timeout. Use {@link resolveWarmupDeadlineOpts} which degrades conservatively.
33
+ */
34
+ export function awaitWithWarmupDeadline<T>(
35
+ work: Promise<T>,
36
+ opts: {
37
+ isConnected: () => boolean;
38
+ connectTimeoutMs: number;
39
+ responseTimeoutMs: number;
40
+ pollIntervalMs?: number;
41
+ },
42
+ ): Promise<T> {
43
+ const pollMs = Math.max(1, Math.min(opts.pollIntervalMs ?? 200, opts.connectTimeoutMs));
44
+ return new Promise<T>((resolve, reject) => {
45
+ let done = false;
46
+ let poll: ReturnType<typeof setInterval> | undefined;
47
+ let responseTimer: ReturnType<typeof setTimeout> | undefined;
48
+ const startedAt = Date.now();
49
+ const cleanup = () => {
50
+ if (poll) { clearInterval(poll); poll = undefined; }
51
+ if (responseTimer) { clearTimeout(responseTimer); responseTimer = undefined; }
52
+ };
53
+ const settle = (fn: () => void) => {
54
+ if (done) return;
55
+ done = true;
56
+ cleanup();
57
+ fn();
58
+ };
59
+ // Arm the response deadline exactly once, the moment the channel is warm.
60
+ const armResponse = () => {
61
+ if (responseTimer || done) return;
62
+ responseTimer = setTimeout(
63
+ () => settle(() => reject(new Error('timeout'))),
64
+ opts.responseTimeoutMs,
65
+ );
66
+ if (typeof responseTimer.unref === 'function') responseTimer.unref();
67
+ };
68
+ const onPoll = () => {
69
+ if (done) return;
70
+ if (opts.isConnected()) {
71
+ if (poll) { clearInterval(poll); poll = undefined; }
72
+ armResponse();
73
+ return;
74
+ }
75
+ if (Date.now() - startedAt >= opts.connectTimeoutMs) {
76
+ settle(() => reject(new Error('timeout')));
77
+ }
78
+ };
79
+ if (opts.isConnected()) {
80
+ // Already warm (e.g. a retry over an open channel) — skip the warmup
81
+ // phase entirely and let the response deadline govern from t0.
82
+ armResponse();
83
+ } else {
84
+ poll = setInterval(onPoll, pollMs);
85
+ if (typeof poll.unref === 'function') poll.unref();
86
+ }
87
+ work.then(
88
+ (val) => settle(() => resolve(val)),
89
+ (err) => settle(() => reject(err)),
90
+ );
91
+ });
92
+ }
93
+
94
+ /** Minimal connection-state reader: a mesh peer snapshot stamps its live state on `.state`. */
95
+ export function readWarmupConnectionState(connection: Record<string, unknown> | null | undefined): string | undefined {
96
+ const state = (connection as { state?: unknown } | null | undefined)?.state;
97
+ return typeof state === 'string' && state.length > 0 ? state : undefined;
98
+ }
99
+
100
+ export interface ResolvedWarmupDeadlineOpts {
101
+ isConnected: () => boolean;
102
+ connectTimeoutMs: number;
103
+ responseTimeoutMs: number;
104
+ }
105
+
106
+ /**
107
+ * Build {@link awaitWithWarmupDeadline} opts from an OPTIONAL live peer-connection
108
+ * probe, handling the missing-getter case fail-loud instead of silently degrading.
109
+ *
110
+ * When `getConnection` is wired the normal cold-open/warm split applies: the probe
111
+ * is consulted live and the channel is "warm" only once it reports `connected`.
112
+ *
113
+ * When `getConnection` is ABSENT the old call sites fell back to `() => true`
114
+ * ("always warm"), which charges a still-opening cold channel against the response
115
+ * budget and silently re-introduces the exact cold-open false-timeout the warmup
116
+ * deadline exists to prevent. Instead we degrade CONSERVATIVELY and FAIL LOUD:
117
+ * - `onMissingGetter` is invoked so the caller can warn (the degrade is visible,
118
+ * never silent) — keyed/throttled by the caller as it sees fit.
119
+ * - the channel is treated as NOT observably warm (`isConnected: () => false`),
120
+ * so the response deadline never arms early on an unobservable channel.
121
+ * - the cold peer is granted the COMBINED connect+response window as one deadline,
122
+ * so a slow-but-live cold open is never false-timed at the shorter response
123
+ * budget. A genuinely hung dispatch still rejects when the combined window
124
+ * lapses, and `work` rejecting on its own (a real transport failure) still
125
+ * settles immediately.
126
+ *
127
+ * Note: a present getter that returns a non-`connected` snapshot (or `null` for an
128
+ * unknown peer) correctly yields `isConnected() === false` — i.e. the generous
129
+ * connect budget, never "always warm". Only a wholly absent getter degrades.
130
+ */
131
+ export function resolveWarmupDeadlineOpts(opts: {
132
+ getConnection?: ((daemonId: string) => Record<string, unknown> | null) | undefined;
133
+ daemonId: string;
134
+ connectTimeoutMs: number;
135
+ responseTimeoutMs: number;
136
+ onMissingGetter?: (daemonId: string) => void;
137
+ }): ResolvedWarmupDeadlineOpts {
138
+ const { getConnection, daemonId, connectTimeoutMs, responseTimeoutMs } = opts;
139
+ if (getConnection) {
140
+ return {
141
+ isConnected: () => readWarmupConnectionState(getConnection(daemonId)) === 'connected',
142
+ connectTimeoutMs,
143
+ responseTimeoutMs,
144
+ };
145
+ }
146
+ opts.onMissingGetter?.(daemonId);
147
+ return {
148
+ isConnected: () => false,
149
+ connectTimeoutMs: connectTimeoutMs + responseTimeoutMs,
150
+ responseTimeoutMs,
151
+ };
152
+ }