@adhdev/daemon-core 0.9.82-rc.5 → 0.9.82-rc.500

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 (479) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +11 -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 +85 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +246 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +139 -64
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +5 -0
  12. package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
  13. package/dist/cli-adapters/provider-cli-shared.d.ts +74 -0
  14. package/dist/cli-adapters/pty-write-chunking.d.ts +34 -0
  15. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  16. package/dist/cli-adapters/resolve-executable.d.ts +69 -0
  17. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  18. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  19. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  20. package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
  21. package/dist/commands/chat-commands-read.d.ts +23 -0
  22. package/dist/commands/chat-commands-scope.d.ts +39 -0
  23. package/dist/commands/chat-commands-shared.d.ts +33 -0
  24. package/dist/commands/chat-commands-write.d.ts +14 -0
  25. package/dist/commands/chat-commands.d.ts +10 -23
  26. package/dist/commands/cli-manager.d.ts +71 -1
  27. package/dist/commands/handler.d.ts +125 -0
  28. package/dist/commands/high-family/index.d.ts +3 -0
  29. package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
  30. package/dist/commands/high-family/mesh-events.d.ts +2 -0
  31. package/dist/commands/high-family/mesh-status.d.ts +2 -0
  32. package/dist/commands/high-family/types.d.ts +64 -0
  33. package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
  34. package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
  35. package/dist/commands/low-family/diagnostics.d.ts +2 -0
  36. package/dist/commands/low-family/index.d.ts +3 -0
  37. package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
  38. package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
  39. package/dist/commands/low-family/notification.d.ts +2 -0
  40. package/dist/commands/low-family/refine-config.d.ts +2 -0
  41. package/dist/commands/low-family/session-host.d.ts +2 -0
  42. package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
  43. package/dist/commands/low-family/status-meta.d.ts +2 -0
  44. package/dist/commands/low-family/types.d.ts +33 -0
  45. package/dist/commands/med-family/cli-agent.d.ts +2 -0
  46. package/dist/commands/med-family/fast-forward.d.ts +2 -0
  47. package/dist/commands/med-family/ide.d.ts +10 -0
  48. package/dist/commands/med-family/index.d.ts +3 -0
  49. package/dist/commands/med-family/mesh-crud.d.ts +48 -0
  50. package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
  51. package/dist/commands/med-family/mesh-queue.d.ts +2 -0
  52. package/dist/commands/med-family/mesh-restart.d.ts +2 -0
  53. package/dist/commands/med-family/types.d.ts +152 -0
  54. package/dist/commands/mesh-coordinator.d.ts +85 -1
  55. package/dist/commands/router-aggregate-status.d.ts +24 -0
  56. package/dist/commands/router-mesh-session-owner.d.ts +59 -0
  57. package/dist/commands/router-refine.d.ts +151 -0
  58. package/dist/commands/router-worktree-cleanup.d.ts +133 -0
  59. package/dist/commands/router.d.ts +212 -11
  60. package/dist/commands/upgrade-helper.d.ts +41 -1
  61. package/dist/config/chat-history.d.ts +11 -0
  62. package/dist/config/config.d.ts +19 -0
  63. package/dist/config/mesh-config.d.ts +132 -1
  64. package/dist/config/mesh-json-config.d.ts +199 -0
  65. package/dist/config/registry-resolver.d.ts +54 -0
  66. package/dist/config/repo-settings.d.ts +77 -0
  67. package/dist/config/state-store.d.ts +30 -0
  68. package/dist/daemon/dev-server.d.ts +0 -2
  69. package/dist/detection/cli-detector.d.ts +17 -0
  70. package/dist/detection/ide-detector.d.ts +13 -0
  71. package/dist/detection/win32-ide-version.d.ts +37 -0
  72. package/dist/git/change-impact-config.d.ts +159 -0
  73. package/dist/git/git-commands.d.ts +27 -2
  74. package/dist/git/git-diff.d.ts +6 -0
  75. package/dist/git/git-executor.d.ts +11 -0
  76. package/dist/git/git-status.d.ts +85 -0
  77. package/dist/git/git-types.d.ts +5 -43
  78. package/dist/git/git-worktree.d.ts +71 -1
  79. package/dist/git/index.d.ts +3 -1
  80. package/dist/index.d.ts +74 -17
  81. package/dist/index.js +61082 -24164
  82. package/dist/index.js.map +1 -1
  83. package/dist/index.mjs +57034 -20299
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/installer.d.ts +1 -4
  86. package/dist/ipc/local-ipc-server.d.ts +91 -0
  87. package/dist/launch.d.ts +1 -1
  88. package/dist/logging/async-batch-writer.d.ts +10 -0
  89. package/dist/logging/debug-config.d.ts +16 -0
  90. package/dist/logging/log-redactor.d.ts +24 -0
  91. package/dist/logging/log-tail-reader.d.ts +81 -0
  92. package/dist/logging/logger.d.ts +1 -1
  93. package/dist/mesh/contracts.d.ts +256 -0
  94. package/dist/mesh/coordinator-prompt.d.ts +76 -0
  95. package/dist/mesh/coordinator-registry.d.ts +59 -0
  96. package/dist/mesh/mesh-active-work.d.ts +203 -0
  97. package/dist/mesh/mesh-clone-grace.d.ts +8 -0
  98. package/dist/mesh/mesh-completion-synthesis.d.ts +4 -0
  99. package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
  100. package/dist/mesh/mesh-delivery-policy.d.ts +104 -0
  101. package/dist/mesh/mesh-event-classify.d.ts +7 -0
  102. package/dist/mesh/mesh-event-forwarding.d.ts +58 -0
  103. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  104. package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
  105. package/dist/mesh/mesh-events-pending.d.ts +258 -0
  106. package/dist/mesh/mesh-events-stale.d.ts +61 -0
  107. package/dist/mesh/mesh-events-utils.d.ts +75 -0
  108. package/dist/mesh/mesh-events.d.ts +6 -37
  109. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  110. package/dist/mesh/mesh-host-ownership.d.ts +29 -0
  111. package/dist/mesh/mesh-idle-reminder.d.ts +68 -0
  112. package/dist/mesh/mesh-init.d.ts +128 -0
  113. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
  114. package/dist/mesh/mesh-ledger.d.ts +139 -1
  115. package/dist/mesh/mesh-magi-status.d.ts +63 -0
  116. package/dist/mesh/mesh-missions.d.ts +281 -0
  117. package/dist/mesh/mesh-node-identity.d.ts +310 -0
  118. package/dist/mesh/mesh-queue-assignment.d.ts +162 -0
  119. package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
  120. package/dist/mesh/mesh-reconcile-config.d.ts +6 -0
  121. package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
  122. package/dist/mesh/mesh-reconcile-loop.d.ts +84 -0
  123. package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -0
  124. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  125. package/dist/mesh/mesh-refine-gates.d.ts +457 -0
  126. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  127. package/dist/mesh/mesh-remote-event-pull.d.ts +15 -0
  128. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  129. package/dist/mesh/mesh-routing.d.ts +70 -0
  130. package/dist/mesh/mesh-runtime-store.d.ts +584 -0
  131. package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
  132. package/dist/mesh/mesh-task-inflight.d.ts +46 -0
  133. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  134. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +34 -0
  135. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  136. package/dist/mesh/mesh-work-queue.d.ts +403 -6
  137. package/dist/mesh/preview-freshness.d.ts +28 -0
  138. package/dist/mesh/refine-config.d.ts +216 -0
  139. package/dist/mesh/worktree-bootstrap-config.d.ts +219 -0
  140. package/dist/providers/acp-provider-instance.d.ts +5 -0
  141. package/dist/providers/approval-utils.d.ts +46 -0
  142. package/dist/providers/chat-message-normalization.d.ts +58 -0
  143. package/dist/providers/cli-provider-effect-format.d.ts +30 -0
  144. package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
  145. package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
  146. package/dist/providers/cli-provider-instance-types.d.ts +47 -0
  147. package/dist/providers/cli-provider-instance.d.ts +461 -30
  148. package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
  149. package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
  150. package/dist/providers/contracts.d.ts +196 -6
  151. package/dist/providers/external-sources.d.ts +71 -0
  152. package/dist/providers/manual-attendance.d.ts +79 -0
  153. package/dist/providers/native-history/antigravity-claim-registry.d.ts +39 -0
  154. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +137 -0
  155. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  156. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  157. package/dist/providers/native-history/constants.d.ts +12 -0
  158. package/dist/providers/native-history/dispatcher.d.ts +44 -0
  159. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  160. package/dist/providers/native-history/index.d.ts +13 -0
  161. package/dist/providers/provider-instance-manager.d.ts +30 -0
  162. package/dist/providers/provider-instance.d.ts +31 -1
  163. package/dist/providers/provider-loader.d.ts +42 -5
  164. package/dist/providers/provider-trust.d.ts +31 -0
  165. package/dist/providers/read-chat-contract.d.ts +29 -0
  166. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  167. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  168. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  169. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  170. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  171. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  172. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  173. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  174. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  175. package/dist/providers/sdk/v1/index.d.ts +30 -0
  176. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  177. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  178. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  179. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  180. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  181. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  182. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  183. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  184. package/dist/providers/spec/adapter.d.ts +98 -0
  185. package/dist/providers/spec/background-task-detector.d.ts +29 -0
  186. package/dist/providers/spec/cli-adapter.d.ts +224 -0
  187. package/dist/providers/spec/evaluator.d.ts +45 -0
  188. package/dist/providers/spec/fsm-driver.d.ts +449 -0
  189. package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
  190. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  191. package/dist/providers/spec/fsm-types.d.ts +202 -0
  192. package/dist/providers/spec/native-history-executor.d.ts +50 -0
  193. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  194. package/dist/providers/spec/route.d.ts +4 -0
  195. package/dist/providers/spec/types.d.ts +244 -0
  196. package/dist/providers/status-monitor.d.ts +7 -7
  197. package/dist/providers/transcript-v2.d.ts +176 -0
  198. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  199. package/dist/providers/working-dir.d.ts +17 -0
  200. package/dist/repo-mesh-types.d.ts +778 -3
  201. package/dist/runtime-defaults.d.ts +2 -0
  202. package/dist/session-host/managed-host.d.ts +64 -0
  203. package/dist/session-host/runtime-surface.d.ts +10 -16
  204. package/dist/sessions/registry.d.ts +26 -0
  205. package/dist/shared-types-extra.d.ts +2 -4
  206. package/dist/shared-types.d.ts +110 -55
  207. package/dist/status/chat-tail-hot-sessions.d.ts +40 -0
  208. package/dist/status/normalize.d.ts +1 -1
  209. package/dist/status/normalize.js +1 -0
  210. package/dist/status/normalize.js.map +1 -1
  211. package/dist/status/normalize.mjs +1 -0
  212. package/dist/status/normalize.mjs.map +1 -1
  213. package/dist/status/reporter.d.ts +2 -0
  214. package/dist/status/snapshot.d.ts +27 -0
  215. package/dist/system/hash.d.ts +8 -0
  216. package/dist/system/load-better-sqlite3.d.ts +21 -0
  217. package/dist/types.d.ts +20 -6
  218. package/package.json +11 -4
  219. package/src/agent-stream/poller.ts +2 -3
  220. package/src/agent-stream/provider-adapter.ts +1 -1
  221. package/src/boot/daemon-lifecycle.ts +83 -14
  222. package/src/boot/process-hardening.ts +89 -0
  223. package/src/build-info.ts +73 -0
  224. package/src/chat/source-machine.ts +534 -0
  225. package/src/chat/source-resolver.ts +0 -0
  226. package/src/chat/subscription-updates.ts +20 -1
  227. package/src/cli-adapter-types.d.ts +3 -1
  228. package/src/cli-adapter-types.ts +85 -2
  229. package/src/cli-adapters/cli-script-runner.ts +421 -0
  230. package/src/cli-adapters/cli-state-engine.ts +1379 -0
  231. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  232. package/src/cli-adapters/provider-cli-adapter.ts +1059 -1143
  233. package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
  234. package/src/cli-adapters/provider-cli-parse.ts +19 -0
  235. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  236. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  237. package/src/cli-adapters/provider-cli-shared.ts +121 -11
  238. package/src/cli-adapters/pty-transport.ts +2 -1
  239. package/src/cli-adapters/pty-write-chunking.ts +106 -0
  240. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  241. package/src/cli-adapters/resolve-executable.ts +204 -0
  242. package/src/cli-adapters/session-host-transport.ts +2 -1
  243. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
  244. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  245. package/src/cli-adapters/terminal-screen.ts +16 -81
  246. package/src/commands/chat-commands-debug-bundle.ts +398 -0
  247. package/src/commands/chat-commands-read.ts +2788 -0
  248. package/src/commands/chat-commands-scope.ts +54 -0
  249. package/src/commands/chat-commands-shared.ts +114 -0
  250. package/src/commands/chat-commands-write.ts +891 -0
  251. package/src/commands/chat-commands.ts +19 -1841
  252. package/src/commands/cli-manager.d.ts +2 -0
  253. package/src/commands/cli-manager.ts +724 -27
  254. package/src/commands/handler.ts +865 -2
  255. package/src/commands/high-family/index.ts +28 -0
  256. package/src/commands/high-family/mesh-coordinator-launch.ts +696 -0
  257. package/src/commands/high-family/mesh-events.ts +102 -0
  258. package/src/commands/high-family/mesh-status.ts +857 -0
  259. package/src/commands/high-family/types.ts +80 -0
  260. package/src/commands/low-family/coordinator-prompt.ts +125 -0
  261. package/src/commands/low-family/daemon-lifecycle.ts +120 -0
  262. package/src/commands/low-family/diagnostics.ts +57 -0
  263. package/src/commands/low-family/index.ts +37 -0
  264. package/src/commands/low-family/mesh-ledger.ts +62 -0
  265. package/src/commands/low-family/mesh-node-logs.ts +87 -0
  266. package/src/commands/low-family/notification.ts +116 -0
  267. package/src/commands/low-family/refine-config.ts +106 -0
  268. package/src/commands/low-family/session-host.ts +282 -0
  269. package/src/commands/low-family/spec-providerdev.ts +217 -0
  270. package/src/commands/low-family/status-meta.ts +112 -0
  271. package/src/commands/low-family/types.ts +39 -0
  272. package/src/commands/med-family/cli-agent.ts +270 -0
  273. package/src/commands/med-family/fast-forward.ts +230 -0
  274. package/src/commands/med-family/ide.ts +163 -0
  275. package/src/commands/med-family/index.ts +37 -0
  276. package/src/commands/med-family/mesh-crud.ts +1309 -0
  277. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  278. package/src/commands/med-family/mesh-queue.ts +167 -0
  279. package/src/commands/med-family/mesh-restart.ts +92 -0
  280. package/src/commands/med-family/types.ts +153 -0
  281. package/src/commands/mesh-coordinator.ts +334 -124
  282. package/src/commands/router-aggregate-status.ts +209 -0
  283. package/src/commands/router-mesh-session-owner.ts +114 -0
  284. package/src/commands/router-refine.ts +1794 -0
  285. package/src/commands/router-worktree-cleanup.ts +870 -0
  286. package/src/commands/router.ts +657 -2704
  287. package/src/commands/stream-commands.ts +8 -0
  288. package/src/commands/upgrade-helper.ts +310 -45
  289. package/src/config/chat-history.ts +517 -24
  290. package/src/config/config.ts +30 -0
  291. package/src/config/mesh-config.ts +542 -23
  292. package/src/config/mesh-json-config.ts +376 -0
  293. package/src/config/recent-activity.ts +8 -2
  294. package/src/config/registry-resolver.ts +100 -0
  295. package/src/config/repo-settings.ts +111 -0
  296. package/src/config/state-store.ts +55 -0
  297. package/src/daemon/dev-auto-implement.ts +3 -2
  298. package/src/daemon/dev-cli-debug.ts +10 -1
  299. package/src/daemon/dev-server.ts +0 -541
  300. package/src/detection/cli-detector.ts +94 -9
  301. package/src/detection/ide-detector.ts +55 -16
  302. package/src/detection/win32-ide-version.ts +106 -0
  303. package/src/git/change-impact-config.ts +354 -0
  304. package/src/git/git-commands.ts +113 -17
  305. package/src/git/git-diff.ts +81 -11
  306. package/src/git/git-executor.ts +12 -0
  307. package/src/git/git-status.ts +916 -51
  308. package/src/git/git-summary.ts +3 -0
  309. package/src/git/git-types.ts +17 -54
  310. package/src/git/git-worktree.ts +261 -4
  311. package/src/git/index.ts +17 -0
  312. package/src/index.ts +221 -13
  313. package/src/installer.d.ts +1 -1
  314. package/src/installer.ts +8 -6
  315. package/src/ipc/local-ipc-server.ts +278 -0
  316. package/src/launch.d.ts +1 -1
  317. package/src/launch.ts +37 -28
  318. package/src/logging/async-batch-writer.ts +55 -0
  319. package/src/logging/command-log.ts +7 -5
  320. package/src/logging/debug-config.ts +25 -0
  321. package/src/logging/debug-trace.ts +7 -2
  322. package/src/logging/log-redactor.ts +100 -0
  323. package/src/logging/log-tail-reader.ts +341 -0
  324. package/src/logging/logger.ts +14 -7
  325. package/src/mesh/contracts.ts +510 -0
  326. package/src/mesh/coordinator-prompt.ts +626 -34
  327. package/src/mesh/coordinator-registry.ts +121 -0
  328. package/src/mesh/mesh-active-work.ts +706 -0
  329. package/src/mesh/mesh-clone-grace.ts +68 -0
  330. package/src/mesh/mesh-completion-synthesis.ts +416 -0
  331. package/src/mesh/mesh-coordinator-config.ts +97 -0
  332. package/src/mesh/mesh-delivery-policy.ts +284 -0
  333. package/src/mesh/mesh-event-classify.ts +78 -0
  334. package/src/mesh/mesh-event-forwarding.ts +2042 -0
  335. package/src/mesh/mesh-event-trace.ts +67 -0
  336. package/src/mesh/mesh-events-coordinator.ts +32 -0
  337. package/src/mesh/mesh-events-pending.ts +1548 -0
  338. package/src/mesh/mesh-events-stale.ts +452 -0
  339. package/src/mesh/mesh-events-utils.ts +443 -0
  340. package/src/mesh/mesh-events.ts +43 -897
  341. package/src/mesh/mesh-fast-forward.ts +856 -0
  342. package/src/mesh/mesh-host-ownership.ts +111 -0
  343. package/src/mesh/mesh-idle-reminder.ts +153 -0
  344. package/src/mesh/mesh-init.ts +350 -0
  345. package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
  346. package/src/mesh/mesh-ledger.ts +898 -102
  347. package/src/mesh/mesh-magi-status.ts +223 -0
  348. package/src/mesh/mesh-missions.ts +695 -0
  349. package/src/mesh/mesh-node-identity.ts +2065 -0
  350. package/src/mesh/mesh-queue-assignment.ts +2498 -0
  351. package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
  352. package/src/mesh/mesh-reconcile-config.ts +66 -0
  353. package/src/mesh/mesh-reconcile-identity.ts +103 -0
  354. package/src/mesh/mesh-reconcile-loop.ts +1709 -0
  355. package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
  356. package/src/mesh/mesh-refine-batch.ts +205 -0
  357. package/src/mesh/mesh-refine-gates.ts +1792 -0
  358. package/src/mesh/mesh-refine-status.ts +231 -0
  359. package/src/mesh/mesh-remote-event-pull.ts +286 -0
  360. package/src/mesh/mesh-review-inbox.ts +308 -0
  361. package/src/mesh/mesh-routing.ts +291 -0
  362. package/src/mesh/mesh-runtime-store.ts +2318 -0
  363. package/src/mesh/mesh-scheduling-runtime.ts +198 -0
  364. package/src/mesh/mesh-task-inflight.ts +70 -0
  365. package/src/mesh/mesh-task-stats.ts +161 -0
  366. package/src/mesh/mesh-unresolved-forward-outbox.ts +215 -0
  367. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  368. package/src/mesh/mesh-work-queue.ts +1532 -161
  369. package/src/mesh/p2p-relay-failure.ts +2 -2
  370. package/src/mesh/preview-freshness.ts +163 -0
  371. package/src/mesh/refine-config.ts +423 -0
  372. package/src/mesh/worktree-bootstrap-config.ts +599 -0
  373. package/src/providers/acp-provider-instance.ts +43 -10
  374. package/src/providers/approval-utils.d.ts +5 -0
  375. package/src/providers/approval-utils.ts +100 -6
  376. package/src/providers/chat-message-normalization.ts +128 -4
  377. package/src/providers/cli-provider-effect-format.ts +53 -0
  378. package/src/providers/cli-provider-history-dedup.ts +75 -0
  379. package/src/providers/cli-provider-input-prompt.ts +133 -0
  380. package/src/providers/cli-provider-instance-types.ts +150 -0
  381. package/src/providers/cli-provider-instance.ts +2914 -498
  382. package/src/providers/cli-provider-status-helpers.ts +123 -0
  383. package/src/providers/cli-provider-transcript-merge.ts +114 -0
  384. package/src/providers/contracts.d.ts +55 -0
  385. package/src/providers/contracts.ts +207 -6
  386. package/src/providers/extension-provider-instance.ts +12 -7
  387. package/src/providers/external-sources.ts +218 -0
  388. package/src/providers/ide-provider-instance.ts +35 -12
  389. package/src/providers/manual-attendance.ts +105 -0
  390. package/src/providers/native-history/antigravity-claim-registry.ts +138 -0
  391. package/src/providers/native-history/antigravity-cli-transcript.ts +1275 -0
  392. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  393. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  394. package/src/providers/native-history/constants.ts +19 -0
  395. package/src/providers/native-history/dispatcher.ts +617 -0
  396. package/src/providers/native-history/hermes-cli-transcript.ts +312 -0
  397. package/src/providers/native-history/index.ts +30 -0
  398. package/src/providers/provider-instance-manager.ts +71 -0
  399. package/src/providers/provider-instance.ts +24 -1
  400. package/src/providers/provider-loader.ts +700 -55
  401. package/src/providers/provider-schema.ts +93 -14
  402. package/src/providers/provider-trust.ts +114 -0
  403. package/src/providers/read-chat-contract.ts +76 -16
  404. package/src/providers/sdk/README.md +49 -0
  405. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  406. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  407. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  408. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +261 -0
  409. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  410. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  411. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  412. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  413. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  414. package/src/providers/sdk/v1/index.ts +152 -0
  415. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  416. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  417. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  418. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +538 -0
  419. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  420. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  421. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  422. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  423. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  424. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  425. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  426. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  427. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  428. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  429. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  430. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  431. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  432. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  433. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  434. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  435. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  436. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  437. package/src/providers/sdk/v1/validators/index.ts +19 -0
  438. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  439. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  440. package/src/providers/spec/adapter.ts +246 -0
  441. package/src/providers/spec/background-task-detector.ts +178 -0
  442. package/src/providers/spec/cli-adapter.ts +1090 -0
  443. package/src/providers/spec/evaluator.ts +407 -0
  444. package/src/providers/spec/fsm-driver.ts +1528 -0
  445. package/src/providers/spec/fsm-evaluator.ts +290 -0
  446. package/src/providers/spec/fsm-loader.ts +128 -0
  447. package/src/providers/spec/fsm-types.ts +301 -0
  448. package/src/providers/spec/native-history-executor.ts +1256 -0
  449. package/src/providers/spec/pre-launch-trust.ts +104 -0
  450. package/src/providers/spec/route.ts +51 -0
  451. package/src/providers/spec/types.ts +284 -0
  452. package/src/providers/status-monitor.d.ts +7 -7
  453. package/src/providers/status-monitor.ts +37 -22
  454. package/src/providers/transcript-v2.ts +567 -0
  455. package/src/providers/types/interactive-prompt.ts +536 -0
  456. package/src/providers/version-archive.ts +64 -24
  457. package/src/providers/working-dir.ts +23 -0
  458. package/src/repo-mesh-types.ts +1040 -5
  459. package/src/runtime-defaults.ts +39 -0
  460. package/src/session-host/managed-host.ts +218 -0
  461. package/src/session-host/runtime-surface.ts +20 -80
  462. package/src/sessions/registry.ts +44 -0
  463. package/src/shared-types-extra.ts +2 -4
  464. package/src/shared-types.d.ts +8 -0
  465. package/src/shared-types.ts +148 -55
  466. package/src/status/builders.ts +69 -6
  467. package/src/status/chat-tail-hot-sessions.ts +117 -2
  468. package/src/status/normalize.ts +2 -0
  469. package/src/status/reporter.ts +19 -1
  470. package/src/status/snapshot.ts +100 -27
  471. package/src/system/hash.ts +23 -0
  472. package/src/system/host-memory.ts +29 -12
  473. package/src/system/load-better-sqlite3.ts +68 -0
  474. package/src/types.ts +26 -6
  475. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  476. package/dist/mesh/mesh-sync.d.ts +0 -53
  477. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  478. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  479. package/src/mesh/mesh-sync.ts +0 -111
@@ -8,8 +8,9 @@
8
8
 
9
9
  import { existsSync, readFileSync, writeFileSync } from 'fs';
10
10
  import { join } from 'path';
11
- import { randomUUID } from 'crypto';
12
- import { getConfigDir } from './config.js';
11
+ import { randomBytes, randomUUID } from 'crypto';
12
+ import { shortHash } from '../system/hash.js';
13
+ import { getConfigDir, loadConfig } from './config.js';
13
14
  import type {
14
15
  LocalMeshConfig,
15
16
  LocalMeshEntry,
@@ -18,8 +19,13 @@ 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 type { MagiKindPanelMap, MagiSlot, MagiTaskKind, DifficultyBrainMap } from '@adhdev/mesh-shared';
26
+ import { normalizeDifficultyBrainMap, DEFAULT_DIFFICULTY_BRAINS } from '@adhdev/mesh-shared';
27
+ import { mergeAndNormalizePolicy } from '../repo-mesh-types.js';
28
+ import { createDefaultMeshHostMetadata } from '../mesh/mesh-host-ownership.js';
23
29
 
24
30
  // ─── Persistence ────────────────────────────────
25
31
 
@@ -33,12 +39,85 @@ function loadMeshConfig(): LocalMeshConfig {
33
39
  try {
34
40
  const raw = JSON.parse(readFileSync(path, 'utf-8'));
35
41
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
36
- return raw as LocalMeshConfig;
42
+ const config = raw as LocalMeshConfig;
43
+ const migrated = migrateLoadedMeshConfig(config);
44
+ // Persist eagerly when the on-load migration changed anything, so the
45
+ // dead field is gone from disk even on a pure-read path (mesh_status /
46
+ // mesh_list_nodes) that never otherwise mutates the config. Best-effort:
47
+ // a write failure (e.g. read-only fs) must not break reads, so swallow.
48
+ if (migrated) {
49
+ try {
50
+ saveMeshConfig(config);
51
+ } catch {
52
+ // keep the in-memory strip; disk converges on the next mutating op
53
+ }
54
+ }
55
+ return config;
37
56
  } catch {
38
57
  return { meshes: [] };
39
58
  }
40
59
  }
41
60
 
61
+ /**
62
+ * In-place migration applied to every loaded meshes.json. Strips data that
63
+ * outlived the feature that wrote it so the persisted config converges on the
64
+ * current schema the next time it is saved.
65
+ *
66
+ * Currently: drops the dead `role` field from each node policy's providerRoles
67
+ * entries. providerRoles is retained for its `maxParallel` per-(node, provider)
68
+ * cap, but the routing `role` was removed (routing is governed solely by
69
+ * required_tags). A meshes.json written before the removal still carries
70
+ * `role: "validator"` etc.; this drops it on load so mesh_status / mesh_list_nodes
71
+ * never surface the dead field and the next saveMeshConfig() persists it gone.
72
+ *
73
+ * Returns true when the config was mutated (caller may persist eagerly).
74
+ */
75
+ function migrateLoadedMeshConfig(config: LocalMeshConfig): boolean {
76
+ let changed = false;
77
+ for (const mesh of config.meshes) {
78
+ if (!mesh || !Array.isArray(mesh.nodes)) continue;
79
+ for (const node of mesh.nodes) {
80
+ if (stripDeadRoleFromProviderRoles(node?.policy)) changed = true;
81
+ }
82
+ }
83
+ return changed;
84
+ }
85
+
86
+ /**
87
+ * Drop the legacy `role` field from each providerRoles entry of a node policy,
88
+ * in place. Keeps providerType + maxParallel (the still-meaningful per-(node,
89
+ * provider) cap). Defensive against malformed entries — non-object items are
90
+ * left untouched. Returns true when at least one `role` field was removed.
91
+ */
92
+ function stripDeadRoleFromProviderRoles(policy: unknown): boolean {
93
+ if (!policy || typeof policy !== 'object') return false;
94
+ const roles = (policy as { providerRoles?: unknown }).providerRoles;
95
+ if (!Array.isArray(roles)) return false;
96
+ let changed = false;
97
+ for (const entry of roles) {
98
+ if (entry && typeof entry === 'object' && !Array.isArray(entry)
99
+ && Object.prototype.hasOwnProperty.call(entry, 'role')) {
100
+ delete (entry as Record<string, unknown>).role;
101
+ changed = true;
102
+ }
103
+ }
104
+ return changed;
105
+ }
106
+
107
+ export function normalizeCapabilityTags(value: unknown): string[] | undefined {
108
+ if (!Array.isArray(value)) return undefined;
109
+ const seen = new Set<string>();
110
+ const tags = value
111
+ .map(tag => typeof tag === 'string' ? tag.trim() : '')
112
+ .filter(Boolean)
113
+ .filter(tag => {
114
+ if (seen.has(tag)) return false;
115
+ seen.add(tag);
116
+ return true;
117
+ });
118
+ return tags.length ? tags : undefined;
119
+ }
120
+
42
121
  function saveMeshConfig(config: LocalMeshConfig): void {
43
122
  const path = getMeshConfigPath();
44
123
  writeFileSync(path, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
@@ -74,24 +153,11 @@ export function normalizeRepoIdentity(remoteUrl: string): string {
74
153
 
75
154
  // ─── CRUD Operations ────────────────────────────
76
155
 
77
- const SESSION_CLEANUP_MODES = new Set(['preserve', 'stop', 'delete_stopped', 'stop_and_delete']);
78
- const SPAWNED_SESSION_VISIBILITY_MODES = new Set(['visible', 'hidden']);
79
-
80
- function mergeMeshPolicy(base: RepoMeshPolicy | undefined, patch: Partial<RepoMeshPolicy> | undefined): RepoMeshPolicy {
81
- const policy: RepoMeshPolicy = { ...DEFAULT_MESH_POLICY, ...(base || {}), ...(patch || {}) };
82
- if (!['block', 'warn', 'checkpoint_then_continue'].includes(policy.dirtyWorkspaceBehavior)) {
83
- policy.dirtyWorkspaceBehavior = 'warn';
84
- }
85
- const maxParallelTasks = Number(policy.maxParallelTasks);
86
- policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
87
- if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
88
- policy.sessionCleanupOnNodeRemove = 'preserve';
89
- }
90
- if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
91
- policy.spawnedSessionVisibility = 'visible';
92
- }
93
- return policy;
94
- }
156
+ // Single source of truth for default+merge+per-field normalization is
157
+ // mergeAndNormalizePolicy in repo-mesh-types.ts. This thin alias keeps the local
158
+ // call sites (createMesh/updateMesh) reading naturally while ensuring config
159
+ // writes go through the exact same normalizer the scheduler/display paths use.
160
+ const mergeMeshPolicy = mergeAndNormalizePolicy;
95
161
 
96
162
  export function listMeshes(): LocalMeshEntry[] {
97
163
  return loadMeshConfig().meshes;
@@ -112,6 +178,7 @@ export interface CreateMeshOptions {
112
178
  defaultBranch?: string;
113
179
  policy?: Partial<RepoMeshPolicy>;
114
180
  coordinator?: RepoMeshCoordinatorConfig;
181
+ meshHost?: RepoMeshHostMetadata;
115
182
  }
116
183
 
117
184
  export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
@@ -133,6 +200,7 @@ export function createMesh(opts: CreateMeshOptions): LocalMeshEntry {
133
200
  defaultBranch: opts.defaultBranch,
134
201
  policy: mergeMeshPolicy(undefined, opts.policy),
135
202
  coordinator: opts.coordinator || {},
203
+ meshHost: opts.meshHost || createDefaultMeshHostMetadata(),
136
204
  nodes: [],
137
205
  createdAt: now,
138
206
  updatedAt: now,
@@ -148,6 +216,7 @@ export interface UpdateMeshOptions {
148
216
  defaultBranch?: string;
149
217
  policy?: Partial<RepoMeshPolicy>;
150
218
  coordinator?: RepoMeshCoordinatorConfig;
219
+ meshHost?: RepoMeshHostMetadata;
151
220
  }
152
221
 
153
222
  export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEntry | undefined {
@@ -159,6 +228,7 @@ export function updateMesh(meshId: string, opts: UpdateMeshOptions): LocalMeshEn
159
228
  if (opts.defaultBranch !== undefined) mesh.defaultBranch = opts.defaultBranch;
160
229
  if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
161
230
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
231
+ if (opts.meshHost) mesh.meshHost = opts.meshHost;
162
232
  mesh.updatedAt = new Date().toISOString();
163
233
 
164
234
  saveMeshConfig(config);
@@ -174,6 +244,240 @@ export function deleteMesh(meshId: string): boolean {
174
244
  return true;
175
245
  }
176
246
 
247
+ function normalizeManualHostAddress(hostAddress: string): string {
248
+ const normalized = hostAddress.trim().replace(/\/+$/, '');
249
+ if (!normalized) throw new Error('hostAddress required');
250
+ let parsed: URL;
251
+ try {
252
+ parsed = new URL(normalized);
253
+ } catch {
254
+ throw new Error('hostAddress must be a valid http(s) or ws(s) URL');
255
+ }
256
+ if (!['http:', 'https:', 'ws:', 'wss:'].includes(parsed.protocol)) {
257
+ throw new Error('hostAddress must use http, https, ws, or wss');
258
+ }
259
+ return normalized;
260
+ }
261
+
262
+ export function tokenIdForManualPairing(token: string): string {
263
+ return `tok_${shortHash(token)}`;
264
+ }
265
+
266
+ function normalizeTokenExpiry(value: unknown): string | undefined {
267
+ if (typeof value !== 'string' || !value.trim()) return undefined;
268
+ const date = new Date(value);
269
+ if (Number.isNaN(date.getTime())) throw new Error('expiresAt must be a valid ISO date');
270
+ return date.toISOString();
271
+ }
272
+
273
+ function assertPairingTokenValid(pairing: RepoMeshHostMetadata['pairing'], rawToken: string, nowIso: string): { ok: true; tokenId: string } | { ok: false; reason: string; expectedTokenId?: string; presentedTokenId?: string } {
274
+ const token = rawToken.trim();
275
+ if (!token) return { ok: false, reason: 'token required' };
276
+ const presentedTokenId = tokenIdForManualPairing(token);
277
+ const expectedTokenId = pairing?.tokenId;
278
+ if (!expectedTokenId || pairing?.status === 'not_configured' || pairing?.status === 'revoked') {
279
+ return { ok: false, reason: 'host pairing token is not configured', presentedTokenId };
280
+ }
281
+ if (pairing.expiresAt && new Date(pairing.expiresAt).getTime() <= new Date(nowIso).getTime()) {
282
+ return { ok: false, reason: 'host pairing token expired', expectedTokenId, presentedTokenId };
283
+ }
284
+ if (presentedTokenId !== expectedTokenId) {
285
+ return { ok: false, reason: 'invalid pairing token', expectedTokenId, presentedTokenId };
286
+ }
287
+ return { ok: true, tokenId: presentedTokenId };
288
+ }
289
+
290
+ export interface ConfigureMeshHostPairingOptions {
291
+ hostAddress: string;
292
+ token: string;
293
+ now?: string;
294
+ }
295
+
296
+ export function configureMeshHostPairing(
297
+ meshId: string,
298
+ opts: ConfigureMeshHostPairingOptions,
299
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; hostAddress: string } | undefined {
300
+ const hostAddress = normalizeManualHostAddress(opts.hostAddress);
301
+ const token = opts.token.trim();
302
+ if (!token) throw new Error('token required');
303
+
304
+ const config = loadMeshConfig();
305
+ const mesh = config.meshes.find(m => m.id === meshId);
306
+ if (!mesh) return undefined;
307
+
308
+ const now = opts.now || new Date().toISOString();
309
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
310
+ const meshHost: RepoMeshHostMetadata = {
311
+ ...previous,
312
+ role: 'member',
313
+ hostAddress,
314
+ pairing: {
315
+ status: 'pairing',
316
+ tokenId: tokenIdForManualPairing(token),
317
+ lastPairedAt: now,
318
+ },
319
+ };
320
+
321
+ mesh.meshHost = meshHost;
322
+ mesh.updatedAt = now;
323
+ saveMeshConfig(config);
324
+ return { mesh, meshHost, hostAddress };
325
+ }
326
+
327
+ export interface CreateMeshHostPairingTokenOptions {
328
+ token?: string;
329
+ expiresAt?: string;
330
+ now?: string;
331
+ }
332
+
333
+ export function createMeshHostPairingToken(
334
+ meshId: string,
335
+ opts: CreateMeshHostPairingTokenOptions = {},
336
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; token: string; tokenId: string; expiresAt?: string } | undefined {
337
+ const config = loadMeshConfig();
338
+ const mesh = config.meshes.find(m => m.id === meshId);
339
+ if (!mesh) return undefined;
340
+ const now = opts.now || new Date().toISOString();
341
+ const token = (opts.token || `mhj_${randomBytes(24).toString('base64url')}`).trim();
342
+ if (!token) throw new Error('token required');
343
+ const tokenId = tokenIdForManualPairing(token);
344
+ const expiresAt = normalizeTokenExpiry(opts.expiresAt);
345
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
346
+ if (previous.role === 'member') {
347
+ throw new Error('Mesh Host daemon required to create host pairing tokens; member daemons cannot mint host join tokens.');
348
+ }
349
+ const meshHost: RepoMeshHostMetadata = {
350
+ ...previous,
351
+ role: 'host',
352
+ pairing: {
353
+ status: 'pairing',
354
+ tokenId,
355
+ lastPairedAt: now,
356
+ ...(expiresAt ? { expiresAt } : {}),
357
+ },
358
+ };
359
+ mesh.meshHost = meshHost;
360
+ mesh.updatedAt = now;
361
+ saveMeshConfig(config);
362
+ return { mesh, meshHost, token, tokenId, ...(expiresAt ? { expiresAt } : {}) };
363
+ }
364
+
365
+ export interface MeshHostJoinMemberNodeInput {
366
+ id?: string;
367
+ workspace: string;
368
+ repoRoot?: string;
369
+ daemonId?: string;
370
+ machineId?: string;
371
+ userOverrides?: Partial<RepoMeshNodeCapabilities>;
372
+ policy?: RepoMeshNodePolicy;
373
+ role?: RepoMeshDaemonRole;
374
+ }
375
+
376
+ export interface ApplyMeshHostJoinOptions {
377
+ token: string;
378
+ memberNode: MeshHostJoinMemberNodeInput;
379
+ memberMeshId?: string;
380
+ now?: string;
381
+ }
382
+
383
+ export function applyMeshHostJoinRequest(
384
+ meshId: string,
385
+ opts: ApplyMeshHostJoinOptions,
386
+ ): { accepted: true; mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata; node: LocalMeshNodeEntry; tokenId: string } | { accepted: false; mesh?: LocalMeshEntry; meshHost?: RepoMeshHostMetadata; tokenId?: string; reason: 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 previous = mesh.meshHost || createDefaultMeshHostMetadata();
392
+ if (previous.role === 'member') {
393
+ return { accepted: false, mesh, meshHost: previous, reason: 'Mesh Host daemon required to accept join requests' };
394
+ }
395
+ const meshHost: RepoMeshHostMetadata = { ...previous, role: 'host' };
396
+ const validation = assertPairingTokenValid(meshHost.pairing, opts.token, now);
397
+ if (!validation.ok) {
398
+ mesh.meshHost = {
399
+ ...meshHost,
400
+ pairing: {
401
+ ...(meshHost.pairing || { status: 'not_configured' as const }),
402
+ status: 'rejected',
403
+ lastRejectedAt: now,
404
+ },
405
+ };
406
+ mesh.updatedAt = now;
407
+ saveMeshConfig(config);
408
+ return { accepted: false, mesh, meshHost: mesh.meshHost, tokenId: validation.presentedTokenId, reason: validation.reason };
409
+ }
410
+
411
+ const workspace = opts.memberNode.workspace.trim();
412
+ if (!workspace) throw new Error('memberNode.workspace required');
413
+ const memberId = opts.memberNode.id?.trim();
414
+ let node = mesh.nodes.find(n => (memberId && n.id === memberId) || n.workspace === workspace);
415
+ if (node) {
416
+ node.workspace = workspace;
417
+ node.repoRoot = opts.memberNode.repoRoot;
418
+ node.daemonId = opts.memberNode.daemonId;
419
+ node.machineId = opts.memberNode.machineId;
420
+ node.userOverrides = opts.memberNode.userOverrides || node.userOverrides || {};
421
+ node.policy = { ...(node.policy || {}), ...(opts.memberNode.policy || {}) };
422
+ node.role = 'member';
423
+ } else {
424
+ if (mesh.nodes.length >= 10) throw new Error('Maximum 10 nodes per mesh');
425
+ node = {
426
+ id: memberId || `node_${randomUUID().replace(/-/g, '')}`,
427
+ workspace,
428
+ repoRoot: opts.memberNode.repoRoot,
429
+ daemonId: opts.memberNode.daemonId,
430
+ machineId: opts.memberNode.machineId,
431
+ userOverrides: opts.memberNode.userOverrides || {},
432
+ policy: opts.memberNode.policy || {},
433
+ role: 'member',
434
+ };
435
+ mesh.nodes.push(node);
436
+ }
437
+ mesh.meshHost = {
438
+ ...meshHost,
439
+ pairing: {
440
+ ...(meshHost.pairing || {}),
441
+ status: 'paired',
442
+ tokenId: validation.tokenId,
443
+ joinedAt: now,
444
+ lastPairedAt: meshHost.pairing?.lastPairedAt || now,
445
+ ...(meshHost.pairing?.expiresAt ? { expiresAt: meshHost.pairing.expiresAt } : {}),
446
+ },
447
+ };
448
+ mesh.updatedAt = now;
449
+ saveMeshConfig(config);
450
+ return { accepted: true, mesh, meshHost: mesh.meshHost, node, tokenId: validation.tokenId };
451
+ }
452
+
453
+ export function markMeshHostPairingJoined(
454
+ meshId: string,
455
+ opts: { hostDaemonId?: string; hostNodeId?: string; joinedAt?: string; token?: string; tokenId?: string },
456
+ ): { mesh: LocalMeshEntry; meshHost: RepoMeshHostMetadata } | undefined {
457
+ const config = loadMeshConfig();
458
+ const mesh = config.meshes.find(m => m.id === meshId);
459
+ if (!mesh) return undefined;
460
+ const now = opts.joinedAt || new Date().toISOString();
461
+ const previous = mesh.meshHost || createDefaultMeshHostMetadata();
462
+ const tokenId = opts.tokenId || (opts.token ? tokenIdForManualPairing(opts.token) : previous.pairing?.tokenId);
463
+ mesh.meshHost = {
464
+ ...previous,
465
+ role: 'member',
466
+ ...(opts.hostDaemonId ? { hostDaemonId: opts.hostDaemonId } : {}),
467
+ ...(opts.hostNodeId ? { hostNodeId: opts.hostNodeId } : {}),
468
+ pairing: {
469
+ ...(previous.pairing || {}),
470
+ status: 'paired',
471
+ ...(tokenId ? { tokenId } : {}),
472
+ joinedAt: now,
473
+ lastPairedAt: previous.pairing?.lastPairedAt || now,
474
+ },
475
+ };
476
+ mesh.updatedAt = now;
477
+ saveMeshConfig(config);
478
+ return { mesh, meshHost: mesh.meshHost };
479
+ }
480
+
177
481
  // ─── Node Operations ────────────────────────────
178
482
 
179
483
  export interface AddNodeOptions {
@@ -181,11 +485,19 @@ export interface AddNodeOptions {
181
485
  repoRoot?: string;
182
486
  daemonId?: string;
183
487
  machineId?: string;
488
+ capabilities?: string[];
184
489
  userOverrides?: Partial<RepoMeshNodeCapabilities>;
185
490
  policy?: RepoMeshNodePolicy;
186
491
  isLocalWorktree?: boolean;
187
492
  worktreeBranch?: string;
188
493
  clonedFromNodeId?: string;
494
+ worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
495
+ role?: RepoMeshDaemonRole;
496
+ /** Owning daemon's machine nickname. Defaults to this daemon's local
497
+ * config.machineNickname when omitted — a node is always added by (and on)
498
+ * the daemon that owns its workspace (self/base node or a local worktree
499
+ * clone), so the local config is the correct source. */
500
+ machineNickname?: string;
189
501
  }
190
502
 
191
503
  export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntry | undefined {
@@ -202,17 +514,35 @@ export function addNode(meshId: string, opts: AddNodeOptions): LocalMeshNodeEntr
202
514
  throw new Error('This workspace is already in the mesh');
203
515
  }
204
516
 
517
+ // A node is always added by the daemon that owns its workspace (the self/base
518
+ // node, or a local worktree clone spawned from this daemon), so this daemon's
519
+ // config.machineNickname is the correct owner nickname. Explicit opt wins.
520
+ const machineNickname = (() => {
521
+ const explicit = typeof opts.machineNickname === 'string' ? opts.machineNickname.trim() : '';
522
+ if (explicit) return explicit;
523
+ try {
524
+ const local = loadConfig().machineNickname;
525
+ return typeof local === 'string' && local.trim() ? local.trim() : undefined;
526
+ } catch {
527
+ return undefined;
528
+ }
529
+ })();
530
+
205
531
  const node: LocalMeshNodeEntry = {
206
532
  id: `node_${randomUUID().replace(/-/g, '')}`,
207
533
  workspace: opts.workspace.trim(),
208
534
  repoRoot: opts.repoRoot,
209
535
  daemonId: opts.daemonId,
210
536
  machineId: opts.machineId,
537
+ ...(machineNickname ? { machineNickname } : {}),
538
+ capabilities: normalizeCapabilityTags(opts.capabilities),
211
539
  userOverrides: opts.userOverrides || {},
212
540
  policy: opts.policy || {},
213
541
  isLocalWorktree: opts.isLocalWorktree,
214
542
  worktreeBranch: opts.worktreeBranch,
215
543
  clonedFromNodeId: opts.clonedFromNodeId,
544
+ worktreeBootstrap: opts.worktreeBootstrap,
545
+ role: opts.role,
216
546
  };
217
547
 
218
548
  mesh.nodes.push(node);
@@ -238,7 +568,35 @@ export function removeNode(meshId: string, nodeId: string): boolean {
238
568
  export function updateNode(
239
569
  meshId: string,
240
570
  nodeId: string,
241
- opts: { userOverrides?: Partial<RepoMeshNodeCapabilities>; policy?: RepoMeshNodePolicy },
571
+ opts: {
572
+ userOverrides?: Partial<RepoMeshNodeCapabilities>;
573
+ policy?: RepoMeshNodePolicy;
574
+ /** Operator-defined custom capability tags used by mesh queue matching.
575
+ * Passing an array replaces the node's custom tags (empty/whitespace
576
+ * entries dropped, deduped); an empty result clears them. Omit to leave
577
+ * the existing tags untouched. */
578
+ capabilities?: string[];
579
+ worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
580
+ /** Per-node instruction surfaced in the coordinator prompt. Pass an
581
+ * empty string or undefined to clear it. */
582
+ systemPrompt?: string;
583
+ /** Live self-reported platform/arch from the owning daemon's git_status
584
+ * envelope. Persisted distinctly from userOverrides (auto-detected, not
585
+ * operator intent) so capability-tag os=/arch= self-heals across loads. */
586
+ reportedPlatform?: string;
587
+ reportedArch?: string;
588
+ /** Owning daemon's self-reported machine nickname, carried on the
589
+ * git_status envelope. Persisted so the friendly label survives across
590
+ * coordinator restarts (mirrors reportedPlatform/reportedArch). */
591
+ reportedMachineNickname?: string;
592
+ /** Owning daemon's self-reported provider CLI/ACP versions + build version,
593
+ * carried on the git_status envelope. Persisted distinctly from userOverrides
594
+ * (auto-detected observability, not operator intent), mirroring the
595
+ * reportedPlatform/reportedArch self-heal so the value survives restarts and
596
+ * is overwritten by the next report. */
597
+ reportedProviderVersions?: Record<string, string>;
598
+ reportedDaemonBuildVersion?: string;
599
+ },
242
600
  ): LocalMeshNodeEntry | undefined {
243
601
  const config = loadMeshConfig();
244
602
  const mesh = config.meshes.find(m => m.id === meshId);
@@ -248,8 +606,169 @@ export function updateNode(
248
606
  if (!node) return undefined;
249
607
 
250
608
  if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
609
+ if (opts.reportedPlatform && opts.reportedPlatform.trim()) node.reportedPlatform = opts.reportedPlatform.trim();
610
+ if (opts.reportedArch && opts.reportedArch.trim()) node.reportedArch = opts.reportedArch.trim();
611
+ if (opts.reportedMachineNickname && opts.reportedMachineNickname.trim()) node.machineNickname = opts.reportedMachineNickname.trim();
612
+ if (opts.reportedProviderVersions && Object.keys(opts.reportedProviderVersions).length > 0) {
613
+ node.reportedProviderVersions = { ...opts.reportedProviderVersions };
614
+ }
615
+ if (opts.reportedDaemonBuildVersion && opts.reportedDaemonBuildVersion.trim()) {
616
+ node.reportedDaemonBuildVersion = opts.reportedDaemonBuildVersion.trim();
617
+ }
251
618
  if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
619
+ if (Object.prototype.hasOwnProperty.call(opts, 'capabilities')) {
620
+ // Explicit replace: normalize (trim/dedup/drop-empties); an empty result
621
+ // clears the tags entirely so the field never persists as [].
622
+ const tags = normalizeCapabilityTags(opts.capabilities);
623
+ if (tags && tags.length) node.capabilities = tags;
624
+ else delete node.capabilities;
625
+ }
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;
255
638
  }
639
+
640
+ // ─── MAGI Panels (machine-local cross-verification quorums) ──
641
+
642
+ // NOTE: the named-panel model (normalizeMagiPanel / list / get / upsert / remove,
643
+ // stored under meshes.json `magiPanels`) was REMOVED. MAGI now resolves its fan-out
644
+ // slots SOLELY from the per-task_kind `magiKindPanels` binding below. `normalizeMagiSlots`
645
+ // is the sole slot normalizer.
646
+
647
+ function normalizeReplicaCount(value: unknown): number | undefined {
648
+ if (typeof value !== 'number' || !Number.isFinite(value)) return undefined;
649
+ const n = Math.floor(value);
650
+ return n >= 1 ? n : undefined;
651
+ }
652
+
653
+ // ─── MAGI kind → panel bindings (MAGI-KIND-PANEL) ─────────
654
+ //
655
+ // Per-task_kind slot lists (machine-local, meshes.json `magiKindPanels`). A bare
656
+ // `mesh_magi_review({task_kind})` resolves its panel exclusively from here — an
657
+ // unconfigured kind is a hard error, never a synthesized fallback. Mirrors the named
658
+ // panel accessors above (normalize / list / get / set / remove).
659
+
660
+ /** The task kinds a kind-panel can be bound to. Unlike a named panel's defaultKind,
661
+ * 'freeform' IS a valid kind-panel key (this is a direct kind→slots binding). */
662
+ const MAGI_KIND_PANEL_KINDS: readonly MagiTaskKind[] = ['claim_audit', 'rca', 'design', 'freeform'];
663
+ const MAX_MAGI_KIND_SLOTS = 24;
664
+
665
+ function normalizeMagiTaskKindKey(raw: unknown): MagiTaskKind {
666
+ const s = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
667
+ if (!(MAGI_KIND_PANEL_KINDS as readonly string[]).includes(s)) {
668
+ throw new Error(`invalid_magi_kind_panel: task_kind must be one of ${MAGI_KIND_PANEL_KINDS.join(' / ')} (got '${s || '(empty)'}')`);
669
+ }
670
+ return s as MagiTaskKind;
671
+ }
672
+
673
+ /**
674
+ * Validate + normalize a kind-panel's slots (the SOLE MAGI slot normalizer): provider
675
+ * required per slot, trims strings, drops empties, clamps replica counts, and carries
676
+ * an optional per-slot `model`. Throws on structurally invalid input (empty list / no
677
+ * provider) so the write returns a clear error. Returns the normalized slot array.
678
+ */
679
+ export function normalizeMagiSlots(slots: unknown): MagiSlot[] {
680
+ if (!Array.isArray(slots) || slots.length === 0) {
681
+ throw new Error('invalid_magi_kind_panel: slots must be a non-empty array');
682
+ }
683
+ if (slots.length > MAX_MAGI_KIND_SLOTS) {
684
+ throw new Error(`invalid_magi_kind_panel: too many slots (max ${MAX_MAGI_KIND_SLOTS})`);
685
+ }
686
+ return slots.map((entry, idx) => {
687
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
688
+ throw new Error(`invalid_magi_kind_panel: slot[${idx}] must be an object`);
689
+ }
690
+ const s = entry as Record<string, unknown>;
691
+ const provider = typeof s.provider === 'string' ? s.provider.trim() : '';
692
+ if (!provider) {
693
+ throw new Error(`invalid_magi_kind_panel: slot[${idx}].provider is required`);
694
+ }
695
+ const nodeId = typeof s.nodeId === 'string' && s.nodeId.trim() ? s.nodeId.trim() : undefined;
696
+ const model = typeof s.model === 'string' && s.model.trim() ? s.model.trim() : undefined;
697
+ const capabilityTags = normalizeCapabilityTags(s.capabilityTags);
698
+ const n = normalizeReplicaCount(s.n);
699
+ return {
700
+ provider,
701
+ ...(nodeId ? { nodeId } : {}),
702
+ ...(model ? { model } : {}),
703
+ ...(capabilityTags ? { capabilityTags } : {}),
704
+ ...(n !== undefined ? { n } : {}),
705
+ };
706
+ });
707
+ }
708
+
709
+ /** All configured kind-panels (machine-local), keyed by task_kind. Empty when none. */
710
+ export function listMagiKindPanels(): MagiKindPanelMap {
711
+ return loadMeshConfig().magiKindPanels ?? {};
712
+ }
713
+
714
+ /** The slot list for one task_kind, or undefined when the kind is not configured. */
715
+ export function getMagiKindPanel(kind: string): MagiSlot[] | undefined {
716
+ let key: MagiTaskKind;
717
+ try { key = normalizeMagiTaskKindKey(kind); } catch { return undefined; }
718
+ return loadMeshConfig().magiKindPanels?.[key];
719
+ }
720
+
721
+ /**
722
+ * Upsert the slot list for one task_kind. Unlike named panels this ALWAYS overwrites
723
+ * (a kind has exactly one binding) — the editor pushes the full desired slot set.
724
+ * Returns the normalized, persisted slots.
725
+ */
726
+ export function setMagiKindPanel(kind: string, slots: unknown): MagiSlot[] {
727
+ const key = normalizeMagiTaskKindKey(kind);
728
+ const normalized = normalizeMagiSlots(slots);
729
+ const stored = loadMeshConfig();
730
+ const map = stored.magiKindPanels ?? {};
731
+ map[key] = normalized;
732
+ stored.magiKindPanels = map;
733
+ saveMeshConfig(stored);
734
+ return normalized;
735
+ }
736
+
737
+ /** Remove the binding for one task_kind. Returns true when a binding was removed. */
738
+ export function removeMagiKindPanel(kind: string): boolean {
739
+ let key: MagiTaskKind;
740
+ try { key = normalizeMagiTaskKindKey(kind); } catch { return false; }
741
+ const stored = loadMeshConfig();
742
+ if (!stored.magiKindPanels || !stored.magiKindPanels[key]) return false;
743
+ delete stored.magiKindPanels[key];
744
+ saveMeshConfig(stored);
745
+ return true;
746
+ }
747
+
748
+ // ─── Brain routing: per-difficulty brain presets (machine-local) ───
749
+
750
+ /**
751
+ * The difficulty→brain presets, machine-local. When nothing is configured yet,
752
+ * returns the sensible DEFAULT_DIFFICULTY_BRAINS so the coordinator always has a
753
+ * usable mapping (the operator can override via setDifficultyBrains). Returns a
754
+ * normalized copy — never the stored reference.
755
+ */
756
+ export function getDifficultyBrains(): DifficultyBrainMap {
757
+ const stored = loadMeshConfig().difficultyBrains;
758
+ const normalized = normalizeDifficultyBrainMap(stored);
759
+ return Object.keys(normalized).length > 0 ? normalized : { ...DEFAULT_DIFFICULTY_BRAINS };
760
+ }
761
+
762
+ /**
763
+ * Replace the difficulty→brain presets wholesale (the editor pushes the full map).
764
+ * Passing an empty/normalized-empty map clears the override, so getDifficultyBrains
765
+ * falls back to the defaults again. Returns the normalized, persisted map.
766
+ */
767
+ export function setDifficultyBrains(map: unknown): DifficultyBrainMap {
768
+ const normalized = normalizeDifficultyBrainMap(map);
769
+ const stored = loadMeshConfig();
770
+ if (Object.keys(normalized).length > 0) stored.difficultyBrains = normalized;
771
+ else delete stored.difficultyBrains;
772
+ saveMeshConfig(stored);
773
+ return normalized;
774
+ }