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

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 (382) 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/types.d.ts +116 -0
  47. package/dist/commands/mesh-coordinator.d.ts +85 -1
  48. package/dist/commands/router.d.ts +666 -2
  49. package/dist/commands/upgrade-helper.d.ts +41 -1
  50. package/dist/config/chat-history.d.ts +9 -0
  51. package/dist/config/config.d.ts +5 -0
  52. package/dist/config/mesh-config.d.ts +77 -1
  53. package/dist/daemon/dev-server.d.ts +0 -2
  54. package/dist/detection/ide-detector.d.ts +13 -0
  55. package/dist/detection/win32-ide-version.d.ts +37 -0
  56. package/dist/git/change-impact-config.d.ts +159 -0
  57. package/dist/git/git-commands.d.ts +11 -1
  58. package/dist/git/git-diff.d.ts +6 -0
  59. package/dist/git/git-executor.d.ts +11 -0
  60. package/dist/git/git-status.d.ts +23 -0
  61. package/dist/git/git-types.d.ts +2 -50
  62. package/dist/git/index.d.ts +2 -0
  63. package/dist/index.d.ts +55 -13
  64. package/dist/index.js +46516 -19739
  65. package/dist/index.js.map +1 -1
  66. package/dist/index.mjs +43516 -16870
  67. package/dist/index.mjs.map +1 -1
  68. package/dist/installer.d.ts +1 -4
  69. package/dist/ipc/local-ipc-server.d.ts +91 -0
  70. package/dist/launch.d.ts +1 -1
  71. package/dist/logging/async-batch-writer.d.ts +10 -0
  72. package/dist/logging/log-redactor.d.ts +24 -0
  73. package/dist/logging/log-tail-reader.d.ts +46 -0
  74. package/dist/logging/logger.d.ts +1 -1
  75. package/dist/mesh/contracts.d.ts +164 -0
  76. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  77. package/dist/mesh/coordinator-registry.d.ts +59 -0
  78. package/dist/mesh/mesh-active-work.d.ts +174 -0
  79. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  80. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  81. package/dist/mesh/mesh-events-coordinator.d.ts +91 -0
  82. package/dist/mesh/mesh-events-pending.d.ts +55 -0
  83. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  84. package/dist/mesh/mesh-events-utils.d.ts +61 -0
  85. package/dist/mesh/mesh-events.d.ts +6 -49
  86. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  87. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  88. package/dist/mesh/mesh-init.d.ts +86 -0
  89. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  90. package/dist/mesh/mesh-ledger.d.ts +77 -1
  91. package/dist/mesh/mesh-missions.d.ts +164 -0
  92. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  93. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  94. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  95. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  96. package/dist/mesh/mesh-routing.d.ts +70 -0
  97. package/dist/mesh/mesh-runtime-store.d.ts +429 -0
  98. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  99. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  100. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  101. package/dist/mesh/mesh-work-queue.d.ts +246 -5
  102. package/dist/mesh/preview-freshness.d.ts +18 -0
  103. package/dist/mesh/refine-config.d.ts +216 -0
  104. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  105. package/dist/providers/acp-provider-instance.d.ts +5 -0
  106. package/dist/providers/approval-utils.d.ts +20 -0
  107. package/dist/providers/chat-message-normalization.d.ts +12 -0
  108. package/dist/providers/cli-provider-instance.d.ts +108 -3
  109. package/dist/providers/contracts.d.ts +139 -6
  110. package/dist/providers/external-sources.d.ts +71 -0
  111. package/dist/providers/manual-attendance.d.ts +63 -0
  112. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  113. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  114. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  115. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  116. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  117. package/dist/providers/native-history/index.d.ts +13 -0
  118. package/dist/providers/provider-instance-manager.d.ts +14 -0
  119. package/dist/providers/provider-instance.d.ts +23 -1
  120. package/dist/providers/provider-loader.d.ts +26 -4
  121. package/dist/providers/provider-trust.d.ts +31 -0
  122. package/dist/providers/read-chat-contract.d.ts +29 -0
  123. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  124. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  125. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  126. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  127. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  128. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  129. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  130. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  131. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  132. package/dist/providers/sdk/v1/index.d.ts +30 -0
  133. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  134. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  135. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  136. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  137. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  138. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  139. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  140. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  141. package/dist/providers/spec/adapter.d.ts +91 -0
  142. package/dist/providers/spec/cli-adapter.d.ts +223 -0
  143. package/dist/providers/spec/evaluator.d.ts +45 -0
  144. package/dist/providers/spec/fsm-driver.d.ts +395 -0
  145. package/dist/providers/spec/fsm-evaluator.d.ts +76 -0
  146. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  147. package/dist/providers/spec/fsm-types.d.ts +174 -0
  148. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  149. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  150. package/dist/providers/spec/route.d.ts +4 -0
  151. package/dist/providers/spec/types.d.ts +222 -0
  152. package/dist/providers/status-monitor.d.ts +7 -7
  153. package/dist/providers/transcript-v2.d.ts +176 -0
  154. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  155. package/dist/providers/working-dir.d.ts +17 -0
  156. package/dist/repo-mesh-types.d.ts +295 -13
  157. package/dist/sessions/registry.d.ts +6 -0
  158. package/dist/shared-types-extra.d.ts +2 -4
  159. package/dist/shared-types.d.ts +59 -2
  160. package/dist/status/normalize.d.ts +1 -1
  161. package/dist/status/normalize.js +1 -0
  162. package/dist/status/normalize.js.map +1 -1
  163. package/dist/status/normalize.mjs +1 -0
  164. package/dist/status/normalize.mjs.map +1 -1
  165. package/dist/status/reporter.d.ts +2 -0
  166. package/dist/status/snapshot.d.ts +26 -0
  167. package/dist/system/hash.d.ts +8 -0
  168. package/dist/system/load-better-sqlite3.d.ts +21 -0
  169. package/dist/types.d.ts +5 -0
  170. package/package.json +7 -3
  171. package/src/agent-stream/poller.ts +2 -3
  172. package/src/agent-stream/provider-adapter.ts +1 -1
  173. package/src/boot/daemon-lifecycle.ts +63 -12
  174. package/src/boot/process-hardening.ts +89 -0
  175. package/src/build-info.ts +73 -0
  176. package/src/chat/source-machine.ts +534 -0
  177. package/src/chat/source-resolver.ts +0 -0
  178. package/src/chat/subscription-updates.ts +20 -1
  179. package/src/cli-adapter-types.d.ts +1 -0
  180. package/src/cli-adapter-types.ts +56 -2
  181. package/src/cli-adapters/cli-script-runner.ts +421 -0
  182. package/src/cli-adapters/cli-state-engine.ts +1221 -0
  183. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  184. package/src/cli-adapters/provider-cli-adapter.ts +775 -1141
  185. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  186. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  187. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  188. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  189. package/src/cli-adapters/provider-cli-shared.ts +110 -11
  190. package/src/cli-adapters/pty-transport.ts +2 -1
  191. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  192. package/src/cli-adapters/resolve-executable.ts +90 -0
  193. package/src/cli-adapters/session-host-transport.ts +2 -1
  194. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  195. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  196. package/src/cli-adapters/terminal-screen.ts +16 -81
  197. package/src/commands/WINDOWS-UPGRADE-LOCK-FAILURE.md +198 -0
  198. package/src/commands/chat-commands.ts +1917 -62
  199. package/src/commands/cli-manager.ts +502 -24
  200. package/src/commands/handler.ts +841 -2
  201. package/src/commands/high-family/index.ts +28 -0
  202. package/src/commands/high-family/mesh-coordinator-launch.ts +592 -0
  203. package/src/commands/high-family/mesh-events.ts +47 -0
  204. package/src/commands/high-family/mesh-status.ts +642 -0
  205. package/src/commands/high-family/types.ts +76 -0
  206. package/src/commands/low-family/coordinator-prompt.ts +72 -0
  207. package/src/commands/low-family/daemon-lifecycle.ts +107 -0
  208. package/src/commands/low-family/diagnostics.ts +57 -0
  209. package/src/commands/low-family/index.ts +37 -0
  210. package/src/commands/low-family/mesh-ledger.ts +62 -0
  211. package/src/commands/low-family/mesh-node-logs.ts +81 -0
  212. package/src/commands/low-family/notification.ts +116 -0
  213. package/src/commands/low-family/refine-config.ts +106 -0
  214. package/src/commands/low-family/session-host.ts +274 -0
  215. package/src/commands/low-family/spec-providerdev.ts +217 -0
  216. package/src/commands/low-family/status-meta.ts +112 -0
  217. package/src/commands/low-family/types.ts +39 -0
  218. package/src/commands/med-family/cli-agent.ts +218 -0
  219. package/src/commands/med-family/fast-forward.ts +198 -0
  220. package/src/commands/med-family/ide.ts +163 -0
  221. package/src/commands/med-family/index.ts +35 -0
  222. package/src/commands/med-family/mesh-crud.ts +788 -0
  223. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  224. package/src/commands/med-family/mesh-queue.ts +131 -0
  225. package/src/commands/med-family/types.ts +120 -0
  226. package/src/commands/mesh-coordinator.ts +334 -124
  227. package/src/commands/router.ts +5121 -2369
  228. package/src/commands/stream-commands.ts +8 -0
  229. package/src/commands/upgrade-helper.ts +310 -45
  230. package/src/config/chat-history.ts +483 -24
  231. package/src/config/config.ts +12 -0
  232. package/src/config/mesh-config.ts +389 -6
  233. package/src/config/recent-activity.ts +8 -2
  234. package/src/daemon/dev-auto-implement.ts +3 -2
  235. package/src/daemon/dev-cli-debug.ts +10 -1
  236. package/src/daemon/dev-server.ts +0 -541
  237. package/src/detection/cli-detector.ts +28 -9
  238. package/src/detection/ide-detector.ts +55 -16
  239. package/src/detection/win32-ide-version.ts +106 -0
  240. package/src/git/change-impact-config.ts +354 -0
  241. package/src/git/git-commands.ts +55 -14
  242. package/src/git/git-diff.ts +81 -11
  243. package/src/git/git-executor.ts +12 -0
  244. package/src/git/git-status.ts +574 -43
  245. package/src/git/git-types.ts +14 -62
  246. package/src/git/git-worktree.ts +8 -1
  247. package/src/git/index.ts +16 -0
  248. package/src/index.ts +158 -12
  249. package/src/installer.d.ts +1 -1
  250. package/src/installer.ts +8 -6
  251. package/src/ipc/local-ipc-server.ts +278 -0
  252. package/src/launch.d.ts +1 -1
  253. package/src/launch.ts +37 -28
  254. package/src/logging/async-batch-writer.ts +55 -0
  255. package/src/logging/command-log.ts +7 -5
  256. package/src/logging/log-redactor.ts +100 -0
  257. package/src/logging/log-tail-reader.ts +220 -0
  258. package/src/logging/logger.ts +14 -7
  259. package/src/mesh/contracts.ts +338 -0
  260. package/src/mesh/coordinator-prompt.ts +234 -31
  261. package/src/mesh/coordinator-registry.ts +121 -0
  262. package/src/mesh/mesh-active-work.ts +645 -0
  263. package/src/mesh/mesh-delivery-policy.ts +315 -0
  264. package/src/mesh/mesh-event-trace.ts +67 -0
  265. package/src/mesh/mesh-events-coordinator.ts +2866 -0
  266. package/src/mesh/mesh-events-pending.ts +599 -0
  267. package/src/mesh/mesh-events-stale.ts +309 -0
  268. package/src/mesh/mesh-events-utils.ts +387 -0
  269. package/src/mesh/mesh-events.ts +30 -1035
  270. package/src/mesh/mesh-fast-forward.ts +839 -0
  271. package/src/mesh/mesh-host-ownership.ts +73 -0
  272. package/src/mesh/mesh-init.ts +260 -0
  273. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  274. package/src/mesh/mesh-ledger.ts +591 -102
  275. package/src/mesh/mesh-missions.ts +322 -0
  276. package/src/mesh/mesh-reconcile-loop.ts +1134 -0
  277. package/src/mesh/mesh-refine-batch.ts +197 -0
  278. package/src/mesh/mesh-refine-status.ts +231 -0
  279. package/src/mesh/mesh-review-inbox.ts +307 -0
  280. package/src/mesh/mesh-routing.ts +291 -0
  281. package/src/mesh/mesh-runtime-store.ts +1697 -0
  282. package/src/mesh/mesh-task-stats.ts +161 -0
  283. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  284. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  285. package/src/mesh/mesh-work-queue.ts +997 -141
  286. package/src/mesh/preview-freshness.ts +118 -0
  287. package/src/mesh/refine-config.ts +423 -0
  288. package/src/mesh/worktree-bootstrap-config.ts +331 -0
  289. package/src/providers/acp-provider-instance.ts +43 -10
  290. package/src/providers/approval-utils.d.ts +5 -0
  291. package/src/providers/approval-utils.ts +57 -5
  292. package/src/providers/chat-message-normalization.ts +45 -5
  293. package/src/providers/cli-provider-instance.ts +1310 -101
  294. package/src/providers/contracts.d.ts +55 -0
  295. package/src/providers/contracts.ts +150 -6
  296. package/src/providers/extension-provider-instance.ts +12 -7
  297. package/src/providers/external-sources.ts +218 -0
  298. package/src/providers/ide-provider-instance.ts +35 -12
  299. package/src/providers/manual-attendance.ts +85 -0
  300. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  301. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  302. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  303. package/src/providers/native-history/dispatcher.ts +340 -0
  304. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  305. package/src/providers/native-history/index.ts +30 -0
  306. package/src/providers/provider-instance-manager.ts +30 -0
  307. package/src/providers/provider-instance.ts +19 -1
  308. package/src/providers/provider-loader.ts +668 -50
  309. package/src/providers/provider-schema.ts +87 -14
  310. package/src/providers/provider-trust.ts +114 -0
  311. package/src/providers/read-chat-contract.ts +76 -16
  312. package/src/providers/sdk/README.md +49 -0
  313. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  314. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  315. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  316. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  317. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  318. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  319. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  320. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  321. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  322. package/src/providers/sdk/v1/index.ts +152 -0
  323. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  324. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  325. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  326. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  327. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  328. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  329. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  330. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  331. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  332. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  333. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  334. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  335. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  336. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  337. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  338. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  339. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  340. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  341. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  342. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  343. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  344. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  345. package/src/providers/sdk/v1/validators/index.ts +19 -0
  346. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  347. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  348. package/src/providers/spec/adapter.ts +235 -0
  349. package/src/providers/spec/cli-adapter.ts +1051 -0
  350. package/src/providers/spec/evaluator.ts +407 -0
  351. package/src/providers/spec/fsm-driver.ts +1305 -0
  352. package/src/providers/spec/fsm-evaluator.ts +272 -0
  353. package/src/providers/spec/fsm-loader.ts +120 -0
  354. package/src/providers/spec/fsm-types.ts +273 -0
  355. package/src/providers/spec/native-history-executor.ts +1136 -0
  356. package/src/providers/spec/pre-launch-trust.ts +104 -0
  357. package/src/providers/spec/route.ts +51 -0
  358. package/src/providers/spec/types.ts +262 -0
  359. package/src/providers/status-monitor.d.ts +7 -7
  360. package/src/providers/status-monitor.ts +37 -22
  361. package/src/providers/transcript-v2.ts +567 -0
  362. package/src/providers/types/interactive-prompt.ts +536 -0
  363. package/src/providers/version-archive.ts +64 -24
  364. package/src/providers/working-dir.ts +23 -0
  365. package/src/repo-mesh-types.ts +378 -14
  366. package/src/sessions/registry.ts +6 -0
  367. package/src/shared-types-extra.ts +2 -4
  368. package/src/shared-types.d.ts +8 -0
  369. package/src/shared-types.ts +64 -1
  370. package/src/status/builders.ts +26 -6
  371. package/src/status/normalize.ts +2 -0
  372. package/src/status/reporter.ts +19 -1
  373. package/src/status/snapshot.ts +95 -26
  374. package/src/system/hash.ts +23 -0
  375. package/src/system/host-memory.ts +29 -12
  376. package/src/system/load-better-sqlite3.ts +68 -0
  377. package/src/types.ts +5 -0
  378. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  379. package/dist/mesh/mesh-sync.d.ts +0 -53
  380. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  381. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  382. package/src/mesh/mesh-sync.ts +0 -111
@@ -8,7 +8,8 @@
8
8
 
9
9
  import { existsSync, readFileSync, writeFileSync } from 'fs';
10
10
  import { join } from 'path';
11
- import { randomUUID } from 'crypto';
11
+ import { randomBytes, randomUUID } from 'crypto';
12
+ import { shortHash } from '../system/hash.js';
12
13
  import { getConfigDir } from './config.js';
13
14
  import type {
14
15
  LocalMeshConfig,
@@ -18,8 +19,11 @@ import type {
18
19
  RepoMeshNodePolicy,
19
20
  RepoMeshNodeCapabilities,
20
21
  RepoMeshCoordinatorConfig,
22
+ RepoMeshHostMetadata,
23
+ RepoMeshDaemonRole,
21
24
  } from '../repo-mesh-types.js';
22
- import { DEFAULT_MESH_POLICY } from '../repo-mesh-types.js';
25
+ import { DEFAULT_MESH_POLICY, normalizeMeshSchedulingStrategy } from '../repo-mesh-types.js';
26
+ import { createDefaultMeshHostMetadata } from '../mesh/mesh-host-ownership.js';
23
27
 
24
28
  // ─── Persistence ────────────────────────────────
25
29
 
@@ -33,12 +37,85 @@ function loadMeshConfig(): LocalMeshConfig {
33
37
  try {
34
38
  const raw = JSON.parse(readFileSync(path, 'utf-8'));
35
39
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
36
- return raw as LocalMeshConfig;
40
+ const config = raw as LocalMeshConfig;
41
+ const migrated = migrateLoadedMeshConfig(config);
42
+ // Persist eagerly when the on-load migration changed anything, so the
43
+ // dead field is gone from disk even on a pure-read path (mesh_status /
44
+ // mesh_list_nodes) that never otherwise mutates the config. Best-effort:
45
+ // a write failure (e.g. read-only fs) must not break reads, so swallow.
46
+ if (migrated) {
47
+ try {
48
+ saveMeshConfig(config);
49
+ } catch {
50
+ // keep the in-memory strip; disk converges on the next mutating op
51
+ }
52
+ }
53
+ return config;
37
54
  } catch {
38
55
  return { meshes: [] };
39
56
  }
40
57
  }
41
58
 
59
+ /**
60
+ * In-place migration applied to every loaded meshes.json. Strips data that
61
+ * outlived the feature that wrote it so the persisted config converges on the
62
+ * current schema the next time it is saved.
63
+ *
64
+ * Currently: drops the dead `role` field from each node policy's providerRoles
65
+ * entries. providerRoles is retained for its `maxParallel` per-(node, provider)
66
+ * cap, but the routing `role` was removed (routing is governed solely by
67
+ * required_tags). A meshes.json written before the removal still carries
68
+ * `role: "validator"` etc.; this drops it on load so mesh_status / mesh_list_nodes
69
+ * never surface the dead field and the next saveMeshConfig() persists it gone.
70
+ *
71
+ * Returns true when the config was mutated (caller may persist eagerly).
72
+ */
73
+ function migrateLoadedMeshConfig(config: LocalMeshConfig): boolean {
74
+ let changed = false;
75
+ for (const mesh of config.meshes) {
76
+ if (!mesh || !Array.isArray(mesh.nodes)) continue;
77
+ for (const node of mesh.nodes) {
78
+ if (stripDeadRoleFromProviderRoles(node?.policy)) changed = true;
79
+ }
80
+ }
81
+ return changed;
82
+ }
83
+
84
+ /**
85
+ * Drop the legacy `role` field from each providerRoles entry of a node policy,
86
+ * in place. Keeps providerType + maxParallel (the still-meaningful per-(node,
87
+ * provider) cap). Defensive against malformed entries — non-object items are
88
+ * left untouched. Returns true when at least one `role` field was removed.
89
+ */
90
+ function stripDeadRoleFromProviderRoles(policy: unknown): boolean {
91
+ if (!policy || typeof policy !== 'object') return false;
92
+ const roles = (policy as { providerRoles?: unknown }).providerRoles;
93
+ if (!Array.isArray(roles)) return false;
94
+ let changed = false;
95
+ for (const entry of roles) {
96
+ if (entry && typeof entry === 'object' && !Array.isArray(entry)
97
+ && Object.prototype.hasOwnProperty.call(entry, 'role')) {
98
+ delete (entry as Record<string, unknown>).role;
99
+ changed = true;
100
+ }
101
+ }
102
+ return changed;
103
+ }
104
+
105
+ function normalizeCapabilityTags(value: unknown): string[] | undefined {
106
+ if (!Array.isArray(value)) return undefined;
107
+ const seen = new Set<string>();
108
+ const tags = value
109
+ .map(tag => typeof tag === 'string' ? tag.trim() : '')
110
+ .filter(Boolean)
111
+ .filter(tag => {
112
+ if (seen.has(tag)) return false;
113
+ seen.add(tag);
114
+ return true;
115
+ });
116
+ return tags.length ? tags : undefined;
117
+ }
118
+
42
119
  function saveMeshConfig(config: LocalMeshConfig): void {
43
120
  const path = getMeshConfigPath();
44
121
  writeFileSync(path, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
@@ -78,21 +155,60 @@ const SESSION_CLEANUP_MODES = new Set(['preserve', 'stop', 'delete_stopped', 'st
78
155
  const SPAWNED_SESSION_VISIBILITY_MODES = new Set(['visible', 'hidden']);
79
156
 
80
157
  function mergeMeshPolicy(base: RepoMeshPolicy | undefined, patch: Partial<RepoMeshPolicy> | undefined): RepoMeshPolicy {
81
- const policy: RepoMeshPolicy = { ...DEFAULT_MESH_POLICY, ...(base || {}), ...(patch || {}) };
158
+ const autoFastForward = normalizeAutoFastForwardPolicy({
159
+ ...DEFAULT_MESH_POLICY.autoFastForward,
160
+ ...((base?.autoFastForward && typeof base.autoFastForward === 'object') ? base.autoFastForward : {}),
161
+ ...((patch?.autoFastForward && typeof patch.autoFastForward === 'object') ? patch.autoFastForward : {}),
162
+ });
163
+ const policy: RepoMeshPolicy = {
164
+ ...DEFAULT_MESH_POLICY,
165
+ ...(base || {}),
166
+ ...(patch || {}),
167
+ autoFastForward,
168
+ };
82
169
  if (!['block', 'warn', 'checkpoint_then_continue'].includes(policy.dirtyWorkspaceBehavior)) {
83
170
  policy.dirtyWorkspaceBehavior = 'warn';
84
171
  }
85
172
  const maxParallelTasks = Number(policy.maxParallelTasks);
86
173
  policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
174
+ policy.allowAutoPublishSubmoduleMainCommits = policy.allowAutoPublishSubmoduleMainCommits === true;
87
175
  if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
88
176
  policy.sessionCleanupOnNodeRemove = 'preserve';
89
177
  }
90
178
  if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
91
- policy.spawnedSessionVisibility = 'visible';
179
+ policy.spawnedSessionVisibility = DEFAULT_MESH_POLICY.spawnedSessionVisibility;
180
+ }
181
+ // Load-balancing: normalize the scheduling strategy so an invalid/blank value
182
+ // falls back to 'first_eligible' (strict no-change). Only persist the field when
183
+ // it is explicitly a non-default value to keep existing meshes.json untouched.
184
+ const normalizedStrategy = normalizeMeshSchedulingStrategy(policy.schedulingStrategy);
185
+ if (normalizedStrategy === 'first_eligible') {
186
+ delete policy.schedulingStrategy;
187
+ } else {
188
+ policy.schedulingStrategy = normalizedStrategy;
189
+ }
190
+ // Convergence routing: strict opt-in (default false). Only persist when explicitly
191
+ // enabled so existing meshes.json stays byte-for-byte untouched.
192
+ if (policy.autoConvergeCodeChange === true) {
193
+ policy.autoConvergeCodeChange = true;
194
+ } else {
195
+ delete policy.autoConvergeCodeChange;
92
196
  }
93
197
  return policy;
94
198
  }
95
199
 
200
+ function normalizeAutoFastForwardPolicy(value: unknown): NonNullable<RepoMeshPolicy['autoFastForward']> {
201
+ const record = value && typeof value === 'object' && !Array.isArray(value)
202
+ ? value as Record<string, unknown>
203
+ : {};
204
+ const maxBehind = Number(record.maxBehind);
205
+ return {
206
+ enabled: record.enabled !== false,
207
+ ...(Number.isFinite(maxBehind) && maxBehind >= 0 ? { maxBehind: Math.floor(maxBehind) } : {}),
208
+ requireCleanSubmodules: record.requireCleanSubmodules !== false,
209
+ };
210
+ }
211
+
96
212
  export function listMeshes(): LocalMeshEntry[] {
97
213
  return loadMeshConfig().meshes;
98
214
  }
@@ -112,6 +228,7 @@ export interface CreateMeshOptions {
112
228
  defaultBranch?: string;
113
229
  policy?: Partial<RepoMeshPolicy>;
114
230
  coordinator?: RepoMeshCoordinatorConfig;
231
+ meshHost?: RepoMeshHostMetadata;
115
232
  }
116
233
 
117
234
  export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
@@ -133,6 +250,7 @@ export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
133
250
  defaultBranch: opts.defaultBranch,
134
251
  policy: mergeMeshPolicy(undefined, opts.policy),
135
252
  coordinator: opts.coordinator || {},
253
+ meshHost: opts.meshHost || createDefaultMeshHostMetadata(),
136
254
  nodes: [],
137
255
  createdAt: now,
138
256
  updatedAt: now,
@@ -148,6 +266,7 @@ export interface UpdateMeshOptions {
148
266
  defaultBranch?: string;
149
267
  policy?: Partial<RepoMeshPolicy>;
150
268
  coordinator?: RepoMeshCoordinatorConfig;
269
+ meshHost?: RepoMeshHostMetadata;
151
270
  }
152
271
 
153
272
  export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEntry | undefined {
@@ -159,6 +278,7 @@ export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEn
159
278
  if (opts.defaultBranch !== undefined) mesh.defaultBranch = opts.defaultBranch;
160
279
  if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
161
280
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
281
+ if (opts.meshHost) mesh.meshHost = opts.meshHost;
162
282
  mesh.updatedAt = new Date().toISOString();
163
283
 
164
284
  saveMeshConfig(config);
@@ -174,6 +294,240 @@ export function deleteMesh(meshId: string): boolean {
174
294
  return true;
175
295
  }
176
296
 
297
+ function normalizeManualHostAddress(hostAddress: string): string {
298
+ const normalized = hostAddress.trim().replace(/\/+$/, '');
299
+ if (!normalized) throw new Error('hostAddress required');
300
+ let parsed: URL;
301
+ try {
302
+ parsed = new URL(normalized);
303
+ } catch {
304
+ throw new Error('hostAddress must be a valid http(s) or ws(s) URL');
305
+ }
306
+ if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
307
+ throw new Error('hostAddress must use http, https, ws, or wss');
308
+ }
309
+ return normalized;
310
+ }
311
+
312
+ export function tokenIdForManualPairing(token: string): string {
313
+ return `tok_${shortHash(token)}`;
314
+ }
315
+
316
+ function normalizeTokenExpiry(value: unknown): string | undefined {
317
+ if (typeof value !== 'string' || !value.trim()) return undefined;
318
+ const date = new Date(value);
319
+ if (Number.isNaN(date.getTime())) throw new Error('expiresAt must be a valid ISO date');
320
+ return date.toISOString();
321
+ }
322
+
323
+ function assertPairingTokenValid(pairing: RepoMeshHostMetadata['pairing'], rawToken: string, nowIso: string): { ok: true; tokenId: string } | { ok: false; reason: string; expectedTokenId?: string; presentedTokenId?: string } {
324
+ const token = rawToken.trim();
325
+ if (!token) return { ok: false, reason: 'token required' };
326
+ const presentedTokenId = tokenIdForManualPairing(token);
327
+ const expectedTokenId = pairing?.tokenId;
328
+ if (!expectedTokenId || pairing?.status === 'not_configured' || pairing?.status === 'revoked') {
329
+ return { ok: false, reason: 'host pairing token is not configured', presentedTokenId };
330
+ }
331
+ if (pairing.expiresAt && new Date(pairing.expiresAt).getTime() <= new Date(nowIso).getTime()) {
332
+ return { ok: false, reason: 'host pairing token expired', expectedTokenId, presentedTokenId };
333
+ }
334
+ if (presentedTokenId !== expectedTokenId) {
335
+ return { ok: false, reason: 'invalid pairing token', expectedTokenId, presentedTokenId };
336
+ }
337
+ return { ok: true, tokenId: presentedTokenId };
338
+ }
339
+
340
+ export interface ConfigureMeshHostPairingOptions {
341
+ hostAddress: string;
342
+ token: string;
343
+ now?: string;
344
+ }
345
+
346
+ export function configureMeshHostPairing(
347
+ meshId: string,
348
+ opts: ConfigureMeshHostPairingOptions,
349
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; hostAddress: string } | undefined {
350
+ const hostAddress = normalizeManualHostAddress(opts.hostAddress);
351
+ const token = opts.token.trim();
352
+ if (!token) throw new Error('token required');
353
+
354
+ const config = loadMeshConfig();
355
+ const mesh = config.meshes.find(m => m.id === meshId);
356
+ if (!mesh) return undefined;
357
+
358
+ const now = opts.now || new Date().toISOString();
359
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
360
+ const meshHost: RepoMeshHostMetadata = {
361
+ ...previous,
362
+ role: 'member',
363
+ hostAddress,
364
+ pairing: {
365
+ status: 'pairing',
366
+ tokenId: tokenIdForManualPairing(token),
367
+ lastPairedAt: now,
368
+ },
369
+ };
370
+
371
+ mesh.meshHost = meshHost;
372
+ mesh.updatedAt = now;
373
+ saveMeshConfig(config);
374
+ return { mesh, meshHost, hostAddress };
375
+ }
376
+
377
+ export interface CreateMeshHostPairingTokenOptions {
378
+ token?: string;
379
+ expiresAt?: string;
380
+ now?: string;
381
+ }
382
+
383
+ export function createMeshHostPairingToken(
384
+ meshId: string,
385
+ opts: CreateMeshHostPairingTokenOptions = {},
386
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; token: string; tokenId: string; expiresAt?: string } | undefined {
387
+ const config = loadMeshConfig();
388
+ const mesh = config.meshes.find(m => m.id === meshId);
389
+ if (!mesh) return undefined;
390
+ const now = opts.now || new Date().toISOString();
391
+ const token = (opts.token || `mhj_${randomBytes(24).toString('base64url')}`).trim();
392
+ if (!token) throw new Error('token required');
393
+ const tokenId = tokenIdForManualPairing(token);
394
+ const expiresAt = normalizeTokenExpiry(opts.expiresAt);
395
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
396
+ if (previous.role === 'member') {
397
+ throw new Error('Mesh Host daemon required to create host pairing tokens; member daemons cannot mint host join tokens.');
398
+ }
399
+ const meshHost: RepoMeshHostMetadata = {
400
+ ...previous,
401
+ role: 'host',
402
+ pairing: {
403
+ status: 'pairing',
404
+ tokenId,
405
+ lastPairedAt: now,
406
+ ...(expiresAt ? { expiresAt } : {}),
407
+ },
408
+ };
409
+ mesh.meshHost = meshHost;
410
+ mesh.updatedAt = now;
411
+ saveMeshConfig(config);
412
+ return { mesh, meshHost, token, tokenId, ...(expiresAt ? { expiresAt } : {}) };
413
+ }
414
+
415
+ export interface MeshHostJoinMemberNodeInput {
416
+ id?: string;
417
+ workspace: string;
418
+ repoRoot?: string;
419
+ daemonId?: string;
420
+ machineId?: string;
421
+ userOverrides?: Partial<RepoMeshNodeCapabilities>;
422
+ policy?: RepoMeshNodePolicy;
423
+ role?: RepoMeshDaemonRole;
424
+ }
425
+
426
+ export interface ApplyMeshHostJoinOptions {
427
+ token: string;
428
+ memberNode: MeshHostJoinMemberNodeInput;
429
+ memberMeshId?: string;
430
+ now?: string;
431
+ }
432
+
433
+ export function applyMeshHostJoinRequest(
434
+ meshId: string,
435
+ opts: ApplyMeshHostJoinOptions,
436
+ ): { accepted: true; mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; node: LocalMeshNodeEntry; tokenId: string } | { accepted: false; mesh?: LocalMeshEntry; meshHost?: RepoMeshHostMetadata; tokenId?: string; reason: string } | undefined {
437
+ const config = loadMeshConfig();
438
+ const mesh = config.meshes.find(m => m.id === meshId);
439
+ if (!mesh) return undefined;
440
+ const now = opts.now || new Date().toISOString();
441
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
442
+ if (previous.role === 'member') {
443
+ return { accepted: false, mesh, meshHost: previous, reason: 'Mesh Host daemon required to accept join requests' };
444
+ }
445
+ const meshHost: RepoMeshHostMetadata = { ...previous, role: 'host' };
446
+ const validation = assertPairingTokenValid(meshHost.pairing, opts.token, now);
447
+ if (!validation.ok) {
448
+ mesh.meshHost = {
449
+ ...meshHost,
450
+ pairing: {
451
+ ...(meshHost.pairing || { status: 'not_configured' as const }),
452
+ status: 'rejected',
453
+ lastRejectedAt: now,
454
+ },
455
+ };
456
+ mesh.updatedAt = now;
457
+ saveMeshConfig(config);
458
+ return { accepted: false, mesh, meshHost: mesh.meshHost, tokenId: validation.presentedTokenId, reason: validation.reason };
459
+ }
460
+
461
+ const workspace = opts.memberNode.workspace.trim();
462
+ if (!workspace) throw new Error('memberNode.workspace required');
463
+ const memberId = opts.memberNode.id?.trim();
464
+ let node = mesh.nodes.find(n => (memberId && n.id === memberId) || n.workspace === workspace);
465
+ if (node) {
466
+ node.workspace = workspace;
467
+ node.repoRoot = opts.memberNode.repoRoot;
468
+ node.daemonId = opts.memberNode.daemonId;
469
+ node.machineId = opts.memberNode.machineId;
470
+ node.userOverrides = opts.memberNode.userOverrides || node.userOverrides || {};
471
+ node.policy = { ...(node.policy || {}), ...(opts.memberNode.policy || {}) };
472
+ node.role = 'member';
473
+ } else {
474
+ if (mesh.nodes.length >= 10) throw new Error('Maximum 10 nodes per mesh');
475
+ node = {
476
+ id: memberId || `node_${randomUUID().replace(/-/g, '')}`,
477
+ workspace,
478
+ repoRoot: opts.memberNode.repoRoot,
479
+ daemonId: opts.memberNode.daemonId,
480
+ machineId: opts.memberNode.machineId,
481
+ userOverrides: opts.memberNode.userOverrides || {},
482
+ policy: opts.memberNode.policy || {},
483
+ role: 'member',
484
+ };
485
+ mesh.nodes.push(node);
486
+ }
487
+ mesh.meshHost = {
488
+ ...meshHost,
489
+ pairing: {
490
+ ...(meshHost.pairing || {}),
491
+ status: 'paired',
492
+ tokenId: validation.tokenId,
493
+ joinedAt: now,
494
+ lastPairedAt: meshHost.pairing?.lastPairedAt || now,
495
+ ...(meshHost.pairing?.expiresAt ? { expiresAt: meshHost.pairing.expiresAt } : {}),
496
+ },
497
+ };
498
+ mesh.updatedAt = now;
499
+ saveMeshConfig(config);
500
+ return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
501
+ }
502
+
503
+ export function markMeshHostPairingJoined(
504
+ meshId: string,
505
+ opts: { hostDaemonId?: string; hostNodeId?: string; joinedAt?: string; token?: string; tokenId?: string },
506
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata } | undefined {
507
+ const config = loadMeshConfig();
508
+ const mesh = config.meshes.find(m => m.id === meshId);
509
+ if (!mesh) return undefined;
510
+ const now = opts.joinedAt || new Date().toISOString();
511
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
512
+ const tokenId = opts.tokenId || (opts.token ? tokenIdForManualPairing(opts.token) : previous.pairing?.tokenId);
513
+ mesh.meshHost = {
514
+ ...previous,
515
+ role: 'member',
516
+ ...(opts.hostDaemonId ? { hostDaemonId: opts.hostDaemonId } : {}),
517
+ ...(opts.hostNodeId ? { hostNodeId: opts.hostNodeId } : {}),
518
+ pairing: {
519
+ ...(previous.pairing || {}),
520
+ status: 'paired',
521
+ ...(tokenId ? { tokenId } : {}),
522
+ joinedAt: now,
523
+ lastPairedAt: previous.pairing?.lastPairedAt || now,
524
+ },
525
+ };
526
+ mesh.updatedAt = now;
527
+ saveMeshConfig(config);
528
+ return { mesh, meshHost: mesh.meshHost };
529
+ }
530
+
177
531
  // ─── Node Operations ────────────────────────────
178
532
 
179
533
  export interface AddNodeOptions {
@@ -181,11 +535,14 @@ export interface AddNodeOptions {
181
535
  repoRoot?: string;
182
536
  daemonId?: string;
183
537
  machineId?: string;
538
+ capabilities?: string[];
184
539
  userOverrides?: Partial<RepoMeshNodeCapabilities>;
185
540
  policy?: RepoMeshNodePolicy;
186
541
  isLocalWorktree?: boolean;
187
542
  worktreeBranch?: string;
188
543
  clonedFromNodeId?: string;
544
+ worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
545
+ role?: RepoMeshDaemonRole;
189
546
  }
190
547
 
191
548
  export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntry | undefined {
@@ -208,11 +565,14 @@ export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntr
208
565
  repoRoot: opts.repoRoot,
209
566
  daemonId: opts.daemonId,
210
567
  machineId: opts.machineId,
568
+ capabilities: normalizeCapabilityTags(opts.capabilities),
211
569
  userOverrides: opts.userOverrides || {},
212
570
  policy: opts.policy || {},
213
571
  isLocalWorktree: opts.isLocalWorktree,
214
572
  worktreeBranch: opts.worktreeBranch,
215
573
  clonedFromNodeId: opts.clonedFromNodeId,
574
+ worktreeBootstrap: opts.worktreeBootstrap,
575
+ role: opts.role,
216
576
  };
217
577
 
218
578
  mesh.nodes.push(node);
@@ -238,7 +598,19 @@ export function removeNode(meshId: string, nodeId: string): boolean {
238
598
  export function updateNode(
239
599
  meshId: string,
240
600
  nodeId: string,
241
- opts: { userOverrides?: Partial<RepoMeshNodeCapabilities>; policy?: RepoMeshNodePolicy },
601
+ opts: {
602
+ userOverrides?: Partial<RepoMeshNodeCapabilities>;
603
+ policy?: RepoMeshNodePolicy;
604
+ worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
605
+ /** Per-node instruction surfaced in the coordinator prompt. Pass an
606
+ * empty string or undefined to clear it. */
607
+ systemPrompt?: string;
608
+ /** Live self-reported platform/arch from the owning daemon's git_status
609
+ * envelope. Persisted distinctly from userOverrides (auto-detected, not
610
+ * operator intent) so capability-tag os=/arch= self-heals across loads. */
611
+ reportedPlatform?: string;
612
+ reportedArch?: string;
613
+ },
242
614
  ): LocalMeshNodeEntry | undefined {
243
615
  const config = loadMeshConfig();
244
616
  const mesh = config.meshes.find(m => m.id === meshId);
@@ -248,7 +620,18 @@ export function updateNode(
248
620
  if (!node) return undefined;
249
621
 
250
622
  if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
623
+ if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
624
+ if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
251
625
  if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
626
+ if (opts.worktreeBootstrap) node.worktreeBootstrap = opts.worktreeBootstrap;
627
+ if (Object.prototype.hasOwnProperty.call(opts, 'systemPrompt')) {
628
+ // Honor explicit clears: { systemPrompt: undefined } drops the field.
629
+ if (opts.systemPrompt && opts.systemPrompt.trim()) {
630
+ node.systemPrompt = opts.systemPrompt;
631
+ } else {
632
+ delete node.systemPrompt;
633
+ }
634
+ }
252
635
  mesh.updatedAt = new Date().toISOString();
253
636
  saveMeshConfig(config);
254
637
  return node;
@@ -92,12 +92,18 @@ export function buildSessionReadStateKey(sessionId: string, providerSessionId?:
92
92
 
93
93
  export function getSessionSeenAt(state: DaemonState, sessionId: string, providerSessionId?: string | null): number {
94
94
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
95
- return state.sessionReads?.[providerKey] || state.sessionReads?.[sessionId] || 0;
95
+ return Math.max(state.sessionReads?.[providerKey] || 0, state.sessionReads?.[sessionId] || 0);
96
96
  }
97
97
 
98
98
  export function getSessionSeenMarker(state: DaemonState, sessionId: string, providerSessionId?: string | null): string {
99
99
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
100
- return state.sessionReadMarkers?.[providerKey] || state.sessionReadMarkers?.[sessionId] || '';
100
+ const providerSeenAt = state.sessionReads?.[providerKey] || 0;
101
+ const sessionSeenAt = state.sessionReads?.[sessionId] || 0;
102
+ const providerMarker = state.sessionReadMarkers?.[providerKey] || '';
103
+ const sessionMarker = state.sessionReadMarkers?.[sessionId] || '';
104
+ if (sessionSeenAt > providerSeenAt && sessionMarker) return sessionMarker;
105
+ if (providerSeenAt > sessionSeenAt && providerMarker) return providerMarker;
106
+ return providerMarker || sessionMarker;
101
107
  }
102
108
 
103
109
  export function getSessionNotificationDismissal(state: DaemonState, sessionId: string, providerSessionId?: string | null): string {
@@ -9,6 +9,7 @@
9
9
  import * as fs from 'fs';
10
10
  import * as path from 'path';
11
11
  import * as os from 'os';
12
+ import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from '@adhdev/session-host-core';
12
13
  import type * as http from 'http';
13
14
  import type { ChildProcess } from 'child_process';
14
15
  import type { DevServerContext, ProviderCategory } from './dev-server-types.js';
@@ -482,8 +483,8 @@ export async function handleAutoImplement(ctx: DevServerContext, type: string, r
482
483
  const isWin = os.platform() === 'win32';
483
484
  child = pty.spawn(isWin ? 'cmd.exe' : (process.env.SHELL || '/bin/zsh'), [isWin ? '/c' : '-c', shellCmd], {
484
485
  name: 'xterm-256color',
485
- cols: 120,
486
- rows: 40,
486
+ cols: DEFAULT_SESSION_HOST_COLS,
487
+ rows: DEFAULT_SESSION_HOST_ROWS,
487
488
  cwd: providerDir,
488
489
  env: { ...process.env, ...(spawn.env || {}) },
489
490
  });
@@ -802,7 +802,16 @@ export async function handleCliSend(ctx: DevServerContext, req: http.IncomingMes
802
802
  }
803
803
 
804
804
  try {
805
- ctx.instanceManager!.sendEvent(target.instanceId, 'send_message', { text });
805
+ if (target.category === 'cli') {
806
+ const bundle = getCliTargetBundle(ctx, type, instanceId);
807
+ if (!bundle) {
808
+ ctx.json(res, 404, { error: `No running CLI adapter found for: ${type || instanceId}` });
809
+ return;
810
+ }
811
+ await bundle.adapter.sendMessage(text);
812
+ } else {
813
+ ctx.instanceManager!.sendEvent(target.instanceId, 'send_message', { text });
814
+ }
806
815
  ctx.json(res, 200, { sent: true, type: target.type, instanceId: target.instanceId });
807
816
  } catch (e: any) {
808
817
  ctx.json(res, 500, { error: `Send failed: ${e.message}` });