@loompad/cli 0.1.0 → 1.1.2

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 (688) hide show
  1. package/ARCHITECTURE.md +96 -11
  2. package/CHANGELOG.md +1054 -0
  3. package/README.md +1473 -44
  4. package/THIRD_PARTY_NOTICES.md +275 -0
  5. package/dist/adapters/antigravity-cli.d.ts +62 -0
  6. package/dist/adapters/antigravity-cli.js +258 -0
  7. package/dist/adapters/antigravity-cli.js.map +1 -0
  8. package/dist/adapters/base.d.ts +61 -9
  9. package/dist/adapters/base.js +266 -15
  10. package/dist/adapters/base.js.map +1 -1
  11. package/dist/adapters/bridges/antigravity.d.ts +9 -12
  12. package/dist/adapters/bridges/antigravity.js +9 -12
  13. package/dist/adapters/bridges/antigravity.js.map +1 -1
  14. package/dist/adapters/echo.d.ts +1 -0
  15. package/dist/adapters/echo.js +59 -3
  16. package/dist/adapters/echo.js.map +1 -1
  17. package/dist/adapters/grok.d.ts +7 -0
  18. package/dist/adapters/grok.js +20 -10
  19. package/dist/adapters/grok.js.map +1 -1
  20. package/dist/adapters/index.d.ts +5 -1
  21. package/dist/adapters/index.js +53 -7
  22. package/dist/adapters/index.js.map +1 -1
  23. package/dist/adapters/model.d.ts +137 -0
  24. package/dist/adapters/model.js +527 -0
  25. package/dist/adapters/model.js.map +1 -0
  26. package/dist/adapters/opencode.d.ts +101 -1
  27. package/dist/adapters/opencode.js +874 -98
  28. package/dist/adapters/opencode.js.map +1 -1
  29. package/dist/cli/doctor.d.ts +32 -0
  30. package/dist/cli/doctor.js +89 -4
  31. package/dist/cli/doctor.js.map +1 -1
  32. package/dist/cli/index.js +2651 -87
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/tui-model.js +3 -1
  35. package/dist/cli/tui-model.js.map +1 -1
  36. package/dist/cli/tui.js +44 -1
  37. package/dist/cli/tui.js.map +1 -1
  38. package/dist/cli/ui.d.ts +2 -0
  39. package/dist/cli/ui.js +13 -0
  40. package/dist/cli/ui.js.map +1 -1
  41. package/dist/core/ades.d.ts +32 -16
  42. package/dist/core/ades.js +57 -20
  43. package/dist/core/ades.js.map +1 -1
  44. package/dist/core/agent-state.d.ts +14 -0
  45. package/dist/core/agent-state.js +32 -0
  46. package/dist/core/agent-state.js.map +1 -0
  47. package/dist/core/approvals.d.ts +33 -0
  48. package/dist/core/approvals.js +29 -0
  49. package/dist/core/approvals.js.map +1 -0
  50. package/dist/core/backup.d.ts +19 -0
  51. package/dist/core/backup.js +86 -0
  52. package/dist/core/backup.js.map +1 -0
  53. package/dist/core/baton.d.ts +2 -2
  54. package/dist/core/baton.js.map +1 -1
  55. package/dist/core/brain-extract.d.ts +17 -0
  56. package/dist/core/brain-extract.js +28 -2
  57. package/dist/core/brain-extract.js.map +1 -1
  58. package/dist/core/brain-index.d.ts +71 -0
  59. package/dist/core/brain-index.js +204 -5
  60. package/dist/core/brain-index.js.map +1 -1
  61. package/dist/core/brain.d.ts +58 -2
  62. package/dist/core/brain.js +79 -1
  63. package/dist/core/brain.js.map +1 -1
  64. package/dist/core/chat-import.d.ts +71 -0
  65. package/dist/core/chat-import.js +419 -0
  66. package/dist/core/chat-import.js.map +1 -0
  67. package/dist/core/checkpoint.d.ts +107 -0
  68. package/dist/core/checkpoint.js +259 -0
  69. package/dist/core/checkpoint.js.map +1 -0
  70. package/dist/core/claude-cli.js +1 -1
  71. package/dist/core/claude-cli.js.map +1 -1
  72. package/dist/core/continuity/artifacts.d.ts +14 -0
  73. package/dist/core/continuity/artifacts.js +118 -0
  74. package/dist/core/continuity/artifacts.js.map +1 -0
  75. package/dist/core/continuity/capabilities.d.ts +65 -0
  76. package/dist/core/continuity/capabilities.js +129 -0
  77. package/dist/core/continuity/capabilities.js.map +1 -0
  78. package/dist/core/continuity/contracts.d.ts +352 -0
  79. package/dist/core/continuity/contracts.js +117 -0
  80. package/dist/core/continuity/contracts.js.map +1 -0
  81. package/dist/core/continuity/engine.d.ts +55 -0
  82. package/dist/core/continuity/engine.js +504 -0
  83. package/dist/core/continuity/engine.js.map +1 -0
  84. package/dist/core/continuity/store.d.ts +73 -0
  85. package/dist/core/continuity/store.js +438 -0
  86. package/dist/core/continuity/store.js.map +1 -0
  87. package/dist/core/conversations.d.ts +19 -0
  88. package/dist/core/conversations.js +87 -0
  89. package/dist/core/conversations.js.map +1 -0
  90. package/dist/core/crew-coordination.d.ts +6 -0
  91. package/dist/core/crew-coordination.js +24 -0
  92. package/dist/core/crew-coordination.js.map +1 -0
  93. package/dist/core/crew-policy.d.ts +18 -0
  94. package/dist/core/crew-policy.js +40 -0
  95. package/dist/core/crew-policy.js.map +1 -0
  96. package/dist/core/crew-protocol.d.ts +64 -0
  97. package/dist/core/crew-protocol.js +146 -0
  98. package/dist/core/crew-protocol.js.map +1 -0
  99. package/dist/core/crew-requests.d.ts +14 -0
  100. package/dist/core/crew-requests.js +22 -0
  101. package/dist/core/crew-requests.js.map +1 -0
  102. package/dist/core/crew.d.ts +395 -0
  103. package/dist/core/crew.js +1857 -0
  104. package/dist/core/crew.js.map +1 -0
  105. package/dist/core/digest.d.ts +40 -0
  106. package/dist/core/digest.js +94 -0
  107. package/dist/core/digest.js.map +1 -0
  108. package/dist/core/distill.js +3 -5
  109. package/dist/core/distill.js.map +1 -1
  110. package/dist/core/eventlog.d.ts +27 -25
  111. package/dist/core/eventlog.js +97 -150
  112. package/dist/core/eventlog.js.map +1 -1
  113. package/dist/core/events/contracts.d.ts +51 -0
  114. package/dist/core/events/contracts.js +2 -0
  115. package/dist/core/events/contracts.js.map +1 -0
  116. package/dist/core/events/jsonl-store.d.ts +23 -0
  117. package/dist/core/events/jsonl-store.js +90 -0
  118. package/dist/core/events/jsonl-store.js.map +1 -0
  119. package/dist/core/events/sqlite-store.d.ts +37 -0
  120. package/dist/core/events/sqlite-store.js +215 -0
  121. package/dist/core/events/sqlite-store.js.map +1 -0
  122. package/dist/core/forecast.d.ts +44 -0
  123. package/dist/core/forecast.js +46 -0
  124. package/dist/core/forecast.js.map +1 -0
  125. package/dist/core/free-pool.d.ts +65 -0
  126. package/dist/core/free-pool.js +171 -0
  127. package/dist/core/free-pool.js.map +1 -0
  128. package/dist/core/git.d.ts +30 -0
  129. package/dist/core/git.js +50 -2
  130. package/dist/core/git.js.map +1 -1
  131. package/dist/core/github-events.d.ts +53 -0
  132. package/dist/core/github-events.js +227 -0
  133. package/dist/core/github-events.js.map +1 -0
  134. package/dist/core/goal-lanes.d.ts +53 -0
  135. package/dist/core/goal-lanes.js +99 -0
  136. package/dist/core/goal-lanes.js.map +1 -0
  137. package/dist/core/hosted.d.ts +27 -0
  138. package/dist/core/hosted.js +50 -0
  139. package/dist/core/hosted.js.map +1 -0
  140. package/dist/core/http-server.d.ts +5 -0
  141. package/dist/core/http-server.js +8 -0
  142. package/dist/core/http-server.js.map +1 -0
  143. package/dist/core/invite-link.d.ts +31 -0
  144. package/dist/core/invite-link.js +45 -0
  145. package/dist/core/invite-link.js.map +1 -0
  146. package/dist/core/loops.d.ts +37 -0
  147. package/dist/core/loops.js +81 -0
  148. package/dist/core/loops.js.map +1 -0
  149. package/dist/core/mcp-catalog.d.ts +182 -0
  150. package/dist/core/mcp-catalog.js +431 -0
  151. package/dist/core/mcp-catalog.js.map +1 -0
  152. package/dist/core/mcp.d.ts +87 -0
  153. package/dist/core/mcp.js +181 -0
  154. package/dist/core/mcp.js.map +1 -0
  155. package/dist/core/memory.d.ts +1 -0
  156. package/dist/core/memory.js +5 -2
  157. package/dist/core/memory.js.map +1 -1
  158. package/dist/core/model-tools.d.ts +97 -0
  159. package/dist/core/model-tools.js +388 -0
  160. package/dist/core/model-tools.js.map +1 -0
  161. package/dist/core/notify.js +19 -1
  162. package/dist/core/notify.js.map +1 -1
  163. package/dist/core/orchestra.d.ts +635 -0
  164. package/dist/core/orchestra.js +2120 -0
  165. package/dist/core/orchestra.js.map +1 -0
  166. package/dist/core/permissions.d.ts +56 -0
  167. package/dist/core/permissions.js +122 -0
  168. package/dist/core/permissions.js.map +1 -0
  169. package/dist/core/preview-proxy.d.ts +70 -0
  170. package/dist/core/preview-proxy.js +563 -0
  171. package/dist/core/preview-proxy.js.map +1 -0
  172. package/dist/core/preview-shot.d.ts +46 -0
  173. package/dist/core/preview-shot.js +109 -0
  174. package/dist/core/preview-shot.js.map +1 -0
  175. package/dist/core/process.d.ts +36 -0
  176. package/dist/core/process.js +168 -0
  177. package/dist/core/process.js.map +1 -0
  178. package/dist/core/prompt-queue.d.ts +136 -0
  179. package/dist/core/prompt-queue.js +269 -0
  180. package/dist/core/prompt-queue.js.map +1 -0
  181. package/dist/core/prompts.d.ts +53 -0
  182. package/dist/core/prompts.js +127 -0
  183. package/dist/core/prompts.js.map +1 -0
  184. package/dist/core/proof.d.ts +82 -0
  185. package/dist/core/proof.js +216 -0
  186. package/dist/core/proof.js.map +1 -0
  187. package/dist/core/provider-text.d.ts +23 -0
  188. package/dist/core/provider-text.js +66 -0
  189. package/dist/core/provider-text.js.map +1 -0
  190. package/dist/core/providers.d.ts +152 -0
  191. package/dist/core/providers.js +343 -0
  192. package/dist/core/providers.js.map +1 -0
  193. package/dist/core/quota.d.ts +33 -0
  194. package/dist/core/quota.js +74 -0
  195. package/dist/core/quota.js.map +1 -0
  196. package/dist/core/recipes.d.ts +50 -0
  197. package/dist/core/recipes.js +99 -0
  198. package/dist/core/recipes.js.map +1 -0
  199. package/dist/core/registry.d.ts +54 -0
  200. package/dist/core/registry.js +62 -5
  201. package/dist/core/registry.js.map +1 -1
  202. package/dist/core/relay-client.d.ts +67 -0
  203. package/dist/core/relay-client.js +184 -0
  204. package/dist/core/relay-client.js.map +1 -0
  205. package/dist/core/relay-protocol.d.ts +140 -0
  206. package/dist/core/relay-protocol.js +189 -0
  207. package/dist/core/relay-protocol.js.map +1 -0
  208. package/dist/core/replay.d.ts +18 -0
  209. package/dist/core/replay.js +191 -0
  210. package/dist/core/replay.js.map +1 -0
  211. package/dist/core/review-triage.d.ts +41 -0
  212. package/dist/core/review-triage.js +124 -0
  213. package/dist/core/review-triage.js.map +1 -0
  214. package/dist/core/router.js +2 -2
  215. package/dist/core/router.js.map +1 -1
  216. package/dist/core/routes.d.ts +39 -3
  217. package/dist/core/routes.js +137 -4
  218. package/dist/core/routes.js.map +1 -1
  219. package/dist/core/run-command.d.ts +14 -0
  220. package/dist/core/run-command.js +45 -0
  221. package/dist/core/run-command.js.map +1 -0
  222. package/dist/core/runner-setup.d.ts +36 -0
  223. package/dist/core/runner-setup.js +114 -0
  224. package/dist/core/runner-setup.js.map +1 -0
  225. package/dist/core/search.js +0 -0
  226. package/dist/core/search.js.map +1 -1
  227. package/dist/core/semantic.d.ts +92 -0
  228. package/dist/core/semantic.js +227 -0
  229. package/dist/core/semantic.js.map +1 -0
  230. package/dist/core/servers.d.ts +115 -0
  231. package/dist/core/servers.js +305 -0
  232. package/dist/core/servers.js.map +1 -0
  233. package/dist/core/setup.js +64 -6
  234. package/dist/core/setup.js.map +1 -1
  235. package/dist/core/shield.d.ts +17 -0
  236. package/dist/core/shield.js +81 -0
  237. package/dist/core/shield.js.map +1 -0
  238. package/dist/core/shift.d.ts +69 -0
  239. package/dist/core/shift.js +120 -0
  240. package/dist/core/shift.js.map +1 -0
  241. package/dist/core/skill-install.d.ts +125 -0
  242. package/dist/core/skill-install.js +328 -0
  243. package/dist/core/skill-install.js.map +1 -0
  244. package/dist/core/skills.d.ts +116 -0
  245. package/dist/core/skills.js +223 -0
  246. package/dist/core/skills.js.map +1 -0
  247. package/dist/core/step-conditions.d.ts +65 -0
  248. package/dist/core/step-conditions.js +102 -0
  249. package/dist/core/step-conditions.js.map +1 -0
  250. package/dist/core/subagents.d.ts +45 -0
  251. package/dist/core/subagents.js +90 -0
  252. package/dist/core/subagents.js.map +1 -0
  253. package/dist/core/team-canon.d.ts +42 -0
  254. package/dist/core/team-canon.js +121 -0
  255. package/dist/core/team-canon.js.map +1 -0
  256. package/dist/core/team-crypto.d.ts +97 -0
  257. package/dist/core/team-crypto.js +175 -0
  258. package/dist/core/team-crypto.js.map +1 -0
  259. package/dist/core/team-hub.d.ts +514 -0
  260. package/dist/core/team-hub.js +964 -0
  261. package/dist/core/team-hub.js.map +1 -0
  262. package/dist/core/team-landing.d.ts +239 -0
  263. package/dist/core/team-landing.js +504 -0
  264. package/dist/core/team-landing.js.map +1 -0
  265. package/dist/core/team-leases.d.ts +44 -0
  266. package/dist/core/team-leases.js +145 -0
  267. package/dist/core/team-leases.js.map +1 -0
  268. package/dist/core/team-memory.d.ts +42 -0
  269. package/dist/core/team-memory.js +84 -0
  270. package/dist/core/team-memory.js.map +1 -0
  271. package/dist/core/team-policy.d.ts +85 -0
  272. package/dist/core/team-policy.js +191 -0
  273. package/dist/core/team-policy.js.map +1 -0
  274. package/dist/core/thread-md.d.ts +6 -0
  275. package/dist/core/thread-md.js +42 -0
  276. package/dist/core/thread-md.js.map +1 -0
  277. package/dist/core/turn-stats.d.ts +61 -0
  278. package/dist/core/turn-stats.js +124 -0
  279. package/dist/core/turn-stats.js.map +1 -0
  280. package/dist/core/updater.d.ts +73 -0
  281. package/dist/core/updater.js +153 -0
  282. package/dist/core/updater.js.map +1 -0
  283. package/dist/core/usage.d.ts +75 -0
  284. package/dist/core/usage.js +163 -0
  285. package/dist/core/usage.js.map +1 -0
  286. package/dist/core/windows-jobs.d.ts +15 -0
  287. package/dist/core/windows-jobs.js +170 -0
  288. package/dist/core/windows-jobs.js.map +1 -0
  289. package/dist/core/worktree-merge.d.ts +57 -0
  290. package/dist/core/worktree-merge.js +123 -0
  291. package/dist/core/worktree-merge.js.map +1 -0
  292. package/dist/core/worktree.d.ts +5 -0
  293. package/dist/core/worktree.js +45 -5
  294. package/dist/core/worktree.js.map +1 -1
  295. package/dist/core/worktrees.d.ts +6 -0
  296. package/dist/core/worktrees.js +21 -0
  297. package/dist/core/worktrees.js.map +1 -0
  298. package/dist/daemon/app-page.d.ts +0 -17
  299. package/dist/daemon/app-page.js +10 -6346
  300. package/dist/daemon/app-page.js.map +1 -1
  301. package/dist/daemon/auth.d.ts +24 -3
  302. package/dist/daemon/auth.js +66 -7
  303. package/dist/daemon/auth.js.map +1 -1
  304. package/dist/daemon/board.d.ts +7 -0
  305. package/dist/daemon/board.js +12 -1
  306. package/dist/daemon/board.js.map +1 -1
  307. package/dist/daemon/brand-icons.d.ts +6 -1
  308. package/dist/daemon/brand-icons.js +11 -3
  309. package/dist/daemon/brand-icons.js.map +1 -1
  310. package/dist/daemon/client.d.ts +665 -1
  311. package/dist/daemon/client.js +381 -3
  312. package/dist/daemon/client.js.map +1 -1
  313. package/dist/daemon/delivery.d.ts +34 -0
  314. package/dist/daemon/delivery.js +63 -0
  315. package/dist/daemon/delivery.js.map +1 -0
  316. package/dist/daemon/deploys.d.ts +62 -0
  317. package/dist/daemon/deploys.js +159 -0
  318. package/dist/daemon/deploys.js.map +1 -0
  319. package/dist/daemon/landing.d.ts +192 -0
  320. package/dist/daemon/landing.js +992 -0
  321. package/dist/daemon/landing.js.map +1 -0
  322. package/dist/daemon/onboard.d.ts +150 -0
  323. package/dist/daemon/onboard.js +390 -0
  324. package/dist/daemon/onboard.js.map +1 -0
  325. package/dist/daemon/proof.d.ts +70 -0
  326. package/dist/daemon/proof.js +172 -0
  327. package/dist/daemon/proof.js.map +1 -0
  328. package/dist/daemon/push.d.ts +19 -1
  329. package/dist/daemon/push.js +90 -3
  330. package/dist/daemon/push.js.map +1 -1
  331. package/dist/daemon/relay.d.ts +82 -0
  332. package/dist/daemon/relay.js +351 -0
  333. package/dist/daemon/relay.js.map +1 -0
  334. package/dist/daemon/routes/agent-discovery.d.ts +4 -0
  335. package/dist/daemon/routes/agent-discovery.js +29 -0
  336. package/dist/daemon/routes/agent-discovery.js.map +1 -0
  337. package/dist/daemon/routes/agent-settings.d.ts +4 -0
  338. package/dist/daemon/routes/agent-settings.js +94 -0
  339. package/dist/daemon/routes/agent-settings.js.map +1 -0
  340. package/dist/daemon/routes/agents.d.ts +4 -0
  341. package/dist/daemon/routes/agents.js +105 -0
  342. package/dist/daemon/routes/agents.js.map +1 -0
  343. package/dist/daemon/routes/alerts.d.ts +4 -0
  344. package/dist/daemon/routes/alerts.js +137 -0
  345. package/dist/daemon/routes/alerts.js.map +1 -0
  346. package/dist/daemon/routes/approvals.d.ts +4 -0
  347. package/dist/daemon/routes/approvals.js +40 -0
  348. package/dist/daemon/routes/approvals.js.map +1 -0
  349. package/dist/daemon/routes/assets.d.ts +3 -0
  350. package/dist/daemon/routes/assets.js +64 -0
  351. package/dist/daemon/routes/assets.js.map +1 -0
  352. package/dist/daemon/routes/board.d.ts +4 -0
  353. package/dist/daemon/routes/board.js +147 -0
  354. package/dist/daemon/routes/board.js.map +1 -0
  355. package/dist/daemon/routes/brain.d.ts +4 -0
  356. package/dist/daemon/routes/brain.js +270 -0
  357. package/dist/daemon/routes/brain.js.map +1 -0
  358. package/dist/daemon/routes/chats.d.ts +4 -0
  359. package/dist/daemon/routes/chats.js +249 -0
  360. package/dist/daemon/routes/chats.js.map +1 -0
  361. package/dist/daemon/routes/clients.d.ts +4 -0
  362. package/dist/daemon/routes/clients.js +49 -0
  363. package/dist/daemon/routes/clients.js.map +1 -0
  364. package/dist/daemon/routes/cloud.d.ts +4 -0
  365. package/dist/daemon/routes/cloud.js +46 -0
  366. package/dist/daemon/routes/cloud.js.map +1 -0
  367. package/dist/daemon/routes/config.d.ts +4 -0
  368. package/dist/daemon/routes/config.js +35 -0
  369. package/dist/daemon/routes/config.js.map +1 -0
  370. package/dist/daemon/routes/context.d.ts +51 -0
  371. package/dist/daemon/routes/context.js +2 -0
  372. package/dist/daemon/routes/context.js.map +1 -0
  373. package/dist/daemon/routes/crews.d.ts +4 -0
  374. package/dist/daemon/routes/crews.js +149 -0
  375. package/dist/daemon/routes/crews.js.map +1 -0
  376. package/dist/daemon/routes/files.d.ts +3 -0
  377. package/dist/daemon/routes/files.js +253 -0
  378. package/dist/daemon/routes/files.js.map +1 -0
  379. package/dist/daemon/routes/git.d.ts +4 -0
  380. package/dist/daemon/routes/git.js +96 -0
  381. package/dist/daemon/routes/git.js.map +1 -0
  382. package/dist/daemon/routes/history.d.ts +4 -0
  383. package/dist/daemon/routes/history.js +101 -0
  384. package/dist/daemon/routes/history.js.map +1 -0
  385. package/dist/daemon/routes/integrations-project.d.ts +3 -0
  386. package/dist/daemon/routes/integrations-project.js +103 -0
  387. package/dist/daemon/routes/integrations-project.js.map +1 -0
  388. package/dist/daemon/routes/integrations.d.ts +3 -0
  389. package/dist/daemon/routes/integrations.js +111 -0
  390. package/dist/daemon/routes/integrations.js.map +1 -0
  391. package/dist/daemon/routes/logs.d.ts +3 -0
  392. package/dist/daemon/routes/logs.js +40 -0
  393. package/dist/daemon/routes/logs.js.map +1 -0
  394. package/dist/daemon/routes/messages.d.ts +4 -0
  395. package/dist/daemon/routes/messages.js +60 -0
  396. package/dist/daemon/routes/messages.js.map +1 -0
  397. package/dist/daemon/routes/observability.d.ts +4 -0
  398. package/dist/daemon/routes/observability.js +247 -0
  399. package/dist/daemon/routes/observability.js.map +1 -0
  400. package/dist/daemon/routes/onboard.d.ts +12 -0
  401. package/dist/daemon/routes/onboard.js +67 -0
  402. package/dist/daemon/routes/onboard.js.map +1 -0
  403. package/dist/daemon/routes/orchestra.d.ts +4 -0
  404. package/dist/daemon/routes/orchestra.js +110 -0
  405. package/dist/daemon/routes/orchestra.js.map +1 -0
  406. package/dist/daemon/routes/pairing.d.ts +4 -0
  407. package/dist/daemon/routes/pairing.js +155 -0
  408. package/dist/daemon/routes/pairing.js.map +1 -0
  409. package/dist/daemon/routes/preview.d.ts +24 -0
  410. package/dist/daemon/routes/preview.js +122 -0
  411. package/dist/daemon/routes/preview.js.map +1 -0
  412. package/dist/daemon/routes/project-actions.d.ts +4 -0
  413. package/dist/daemon/routes/project-actions.js +53 -0
  414. package/dist/daemon/routes/project-actions.js.map +1 -0
  415. package/dist/daemon/routes/project-team.d.ts +4 -0
  416. package/dist/daemon/routes/project-team.js +201 -0
  417. package/dist/daemon/routes/project-team.js.map +1 -0
  418. package/dist/daemon/routes/projects.d.ts +14 -0
  419. package/dist/daemon/routes/projects.js +138 -0
  420. package/dist/daemon/routes/projects.js.map +1 -0
  421. package/dist/daemon/routes/prompts.d.ts +4 -0
  422. package/dist/daemon/routes/prompts.js +44 -0
  423. package/dist/daemon/routes/prompts.js.map +1 -0
  424. package/dist/daemon/routes/proof.d.ts +4 -0
  425. package/dist/daemon/routes/proof.js +22 -0
  426. package/dist/daemon/routes/proof.js.map +1 -0
  427. package/dist/daemon/routes/providers.d.ts +3 -0
  428. package/dist/daemon/routes/providers.js +60 -0
  429. package/dist/daemon/routes/providers.js.map +1 -0
  430. package/dist/daemon/routes/public.d.ts +4 -0
  431. package/dist/daemon/routes/public.js +64 -0
  432. package/dist/daemon/routes/public.js.map +1 -0
  433. package/dist/daemon/routes/queue.d.ts +4 -0
  434. package/dist/daemon/routes/queue.js +140 -0
  435. package/dist/daemon/routes/queue.js.map +1 -0
  436. package/dist/daemon/routes/routing.d.ts +4 -0
  437. package/dist/daemon/routes/routing.js +61 -0
  438. package/dist/daemon/routes/routing.js.map +1 -0
  439. package/dist/daemon/routes/runtime-handler.d.ts +2 -0
  440. package/dist/daemon/routes/runtime-handler.js +63 -0
  441. package/dist/daemon/routes/runtime-handler.js.map +1 -0
  442. package/dist/daemon/routes/search.d.ts +4 -0
  443. package/dist/daemon/routes/search.js +17 -0
  444. package/dist/daemon/routes/search.js.map +1 -0
  445. package/dist/daemon/routes/servers.d.ts +4 -0
  446. package/dist/daemon/routes/servers.js +133 -0
  447. package/dist/daemon/routes/servers.js.map +1 -0
  448. package/dist/daemon/routes/setup.d.ts +3 -0
  449. package/dist/daemon/routes/setup.js +50 -0
  450. package/dist/daemon/routes/setup.js.map +1 -0
  451. package/dist/daemon/routes/shift.d.ts +4 -0
  452. package/dist/daemon/routes/shift.js +30 -0
  453. package/dist/daemon/routes/shift.js.map +1 -0
  454. package/dist/daemon/routes/specs.d.ts +4 -0
  455. package/dist/daemon/routes/specs.js +57 -0
  456. package/dist/daemon/routes/specs.js.map +1 -0
  457. package/dist/daemon/routes/task-delivery.d.ts +4 -0
  458. package/dist/daemon/routes/task-delivery.js +38 -0
  459. package/dist/daemon/routes/task-delivery.js.map +1 -0
  460. package/dist/daemon/routes/team.d.ts +4 -0
  461. package/dist/daemon/routes/team.js +193 -0
  462. package/dist/daemon/routes/team.js.map +1 -0
  463. package/dist/daemon/routes/terminals.d.ts +4 -0
  464. package/dist/daemon/routes/terminals.js +87 -0
  465. package/dist/daemon/routes/terminals.js.map +1 -0
  466. package/dist/daemon/routes/tools.d.ts +4 -0
  467. package/dist/daemon/routes/tools.js +180 -0
  468. package/dist/daemon/routes/tools.js.map +1 -0
  469. package/dist/daemon/routes/updates.d.ts +4 -0
  470. package/dist/daemon/routes/updates.js +89 -0
  471. package/dist/daemon/routes/updates.js.map +1 -0
  472. package/dist/daemon/routes/voice.d.ts +4 -0
  473. package/dist/daemon/routes/voice.js +53 -0
  474. package/dist/daemon/routes/voice.js.map +1 -0
  475. package/dist/daemon/runner.d.ts +186 -0
  476. package/dist/daemon/runner.js +612 -0
  477. package/dist/daemon/runner.js.map +1 -0
  478. package/dist/daemon/runtime/accounting.d.ts +130 -0
  479. package/dist/daemon/runtime/accounting.js +303 -0
  480. package/dist/daemon/runtime/accounting.js.map +1 -0
  481. package/dist/daemon/runtime/agents.d.ts +16 -0
  482. package/dist/daemon/runtime/agents.js +71 -0
  483. package/dist/daemon/runtime/agents.js.map +1 -0
  484. package/dist/daemon/runtime/briefings.d.ts +134 -0
  485. package/dist/daemon/runtime/briefings.js +329 -0
  486. package/dist/daemon/runtime/briefings.js.map +1 -0
  487. package/dist/daemon/runtime/native-usage.d.ts +21 -0
  488. package/dist/daemon/runtime/native-usage.js +71 -0
  489. package/dist/daemon/runtime/native-usage.js.map +1 -0
  490. package/dist/daemon/runtime/queue.d.ts +94 -0
  491. package/dist/daemon/runtime/queue.js +222 -0
  492. package/dist/daemon/runtime/queue.js.map +1 -0
  493. package/dist/daemon/runtime/relay.d.ts +93 -0
  494. package/dist/daemon/runtime/relay.js +240 -0
  495. package/dist/daemon/runtime/relay.js.map +1 -0
  496. package/dist/daemon/runtime/turns.d.ts +202 -0
  497. package/dist/daemon/runtime/turns.js +663 -0
  498. package/dist/daemon/runtime/turns.js.map +1 -0
  499. package/dist/daemon/runtime-support.d.ts +76 -0
  500. package/dist/daemon/runtime-support.js +134 -0
  501. package/dist/daemon/runtime-support.js.map +1 -0
  502. package/dist/daemon/runtime.d.ts +739 -70
  503. package/dist/daemon/runtime.js +2751 -470
  504. package/dist/daemon/runtime.js.map +1 -1
  505. package/dist/daemon/server.d.ts +82 -55
  506. package/dist/daemon/server.js +674 -1435
  507. package/dist/daemon/server.js.map +1 -1
  508. package/dist/daemon/shift.d.ts +70 -0
  509. package/dist/daemon/shift.js +170 -0
  510. package/dist/daemon/shift.js.map +1 -0
  511. package/dist/daemon/specs.d.ts +92 -0
  512. package/dist/daemon/specs.js +285 -0
  513. package/dist/daemon/specs.js.map +1 -0
  514. package/dist/daemon/system.d.ts +208 -0
  515. package/dist/daemon/system.js +557 -0
  516. package/dist/daemon/system.js.map +1 -0
  517. package/dist/daemon/tasks.js +1 -1
  518. package/dist/daemon/team-brain.d.ts +136 -0
  519. package/dist/daemon/team-brain.js +659 -0
  520. package/dist/daemon/team-brain.js.map +1 -0
  521. package/dist/daemon/team-coordinator.d.ts +78 -0
  522. package/dist/daemon/team-coordinator.js +408 -0
  523. package/dist/daemon/team-coordinator.js.map +1 -0
  524. package/dist/daemon/team.d.ts +339 -0
  525. package/dist/daemon/team.js +1433 -0
  526. package/dist/daemon/team.js.map +1 -0
  527. package/dist/daemon/terminals.d.ts +22 -3
  528. package/dist/daemon/terminals.js +236 -16
  529. package/dist/daemon/terminals.js.map +1 -1
  530. package/dist/hub/client.d.ts +120 -0
  531. package/dist/hub/client.js +228 -0
  532. package/dist/hub/client.js.map +1 -0
  533. package/dist/hub/server.d.ts +32 -0
  534. package/dist/hub/server.js +180 -0
  535. package/dist/hub/server.js.map +1 -0
  536. package/dist/hub/supabase-client.d.ts +220 -0
  537. package/dist/hub/supabase-client.js +843 -0
  538. package/dist/hub/supabase-client.js.map +1 -0
  539. package/dist/observability/ask.d.ts +91 -0
  540. package/dist/observability/ask.js +179 -0
  541. package/dist/observability/ask.js.map +1 -0
  542. package/dist/observability/clickhouse.d.ts +33 -0
  543. package/dist/observability/clickhouse.js +48 -0
  544. package/dist/observability/clickhouse.js.map +1 -0
  545. package/dist/observability/decisions.d.ts +176 -0
  546. package/dist/observability/decisions.js +377 -0
  547. package/dist/observability/decisions.js.map +1 -0
  548. package/dist/observability/index.d.ts +89 -0
  549. package/dist/observability/index.js +348 -0
  550. package/dist/observability/index.js.map +1 -0
  551. package/dist/observability/insights.d.ts +151 -0
  552. package/dist/observability/insights.js +319 -0
  553. package/dist/observability/insights.js.map +1 -0
  554. package/dist/observability/logs-query.d.ts +82 -0
  555. package/dist/observability/logs-query.js +102 -0
  556. package/dist/observability/logs-query.js.map +1 -0
  557. package/dist/observability/logs.d.ts +72 -0
  558. package/dist/observability/logs.js +295 -0
  559. package/dist/observability/logs.js.map +1 -0
  560. package/dist/observability/metrics.d.ts +86 -0
  561. package/dist/observability/metrics.js +303 -0
  562. package/dist/observability/metrics.js.map +1 -0
  563. package/dist/observability/otlp.d.ts +127 -0
  564. package/dist/observability/otlp.js +242 -0
  565. package/dist/observability/otlp.js.map +1 -0
  566. package/dist/observability/snapshots.d.ts +43 -0
  567. package/dist/observability/snapshots.js +129 -0
  568. package/dist/observability/snapshots.js.map +1 -0
  569. package/dist/observability/triage.d.ts +49 -0
  570. package/dist/observability/triage.js +284 -0
  571. package/dist/observability/triage.js.map +1 -0
  572. package/dist/providers/adapter.d.ts +50 -0
  573. package/dist/providers/adapter.js +38 -0
  574. package/dist/providers/adapter.js.map +1 -0
  575. package/dist/providers/agent.d.ts +110 -0
  576. package/dist/providers/agent.js +487 -0
  577. package/dist/providers/agent.js.map +1 -0
  578. package/dist/providers/approvals.d.ts +24 -0
  579. package/dist/providers/approvals.js +78 -0
  580. package/dist/providers/approvals.js.map +1 -0
  581. package/dist/providers/attachments.d.ts +20 -0
  582. package/dist/providers/attachments.js +51 -0
  583. package/dist/providers/attachments.js.map +1 -0
  584. package/dist/providers/claude/adapter.d.ts +99 -0
  585. package/dist/providers/claude/adapter.js +790 -0
  586. package/dist/providers/claude/adapter.js.map +1 -0
  587. package/dist/providers/codex/adapter.d.ts +113 -0
  588. package/dist/providers/codex/adapter.js +881 -0
  589. package/dist/providers/codex/adapter.js.map +1 -0
  590. package/dist/providers/codex/instructions.d.ts +11 -0
  591. package/dist/providers/codex/instructions.js +154 -0
  592. package/dist/providers/codex/instructions.js.map +1 -0
  593. package/dist/providers/codex/rpc.d.ts +36 -0
  594. package/dist/providers/codex/rpc.js +104 -0
  595. package/dist/providers/codex/rpc.js.map +1 -0
  596. package/dist/providers/contracts.d.ts +339 -0
  597. package/dist/providers/contracts.js +19 -0
  598. package/dist/providers/contracts.js.map +1 -0
  599. package/dist/providers/directory.d.ts +70 -0
  600. package/dist/providers/directory.js +95 -0
  601. package/dist/providers/directory.js.map +1 -0
  602. package/dist/providers/errors.d.ts +47 -0
  603. package/dist/providers/errors.js +24 -0
  604. package/dist/providers/errors.js.map +1 -0
  605. package/dist/providers/index.d.ts +18 -0
  606. package/dist/providers/index.js +19 -0
  607. package/dist/providers/index.js.map +1 -0
  608. package/dist/providers/ingestion.d.ts +80 -0
  609. package/dist/providers/ingestion.js +330 -0
  610. package/dist/providers/ingestion.js.map +1 -0
  611. package/dist/providers/live.d.ts +22 -0
  612. package/dist/providers/live.js +56 -0
  613. package/dist/providers/live.js.map +1 -0
  614. package/dist/providers/process.d.ts +29 -0
  615. package/dist/providers/process.js +71 -0
  616. package/dist/providers/process.js.map +1 -0
  617. package/dist/providers/reaper.d.ts +33 -0
  618. package/dist/providers/reaper.js +65 -0
  619. package/dist/providers/reaper.js.map +1 -0
  620. package/dist/providers/service.d.ts +87 -0
  621. package/dist/providers/service.js +256 -0
  622. package/dist/providers/service.js.map +1 -0
  623. package/dist/sdk.d.ts +1 -1
  624. package/dist/sdk.js +1 -1
  625. package/dist/sdk.js.map +1 -1
  626. package/dist/types.d.ts +385 -6
  627. package/dist/types.js +1 -0
  628. package/dist/types.js.map +1 -1
  629. package/dist/version.d.ts +7 -0
  630. package/dist/version.js +16 -0
  631. package/dist/version.js.map +1 -0
  632. package/dist/web/app.css +4646 -0
  633. package/dist/web/app.js +22640 -0
  634. package/dist/web/app.js.map +7 -0
  635. package/dist/web/shell.html +39 -0
  636. package/docs/README.md +21 -0
  637. package/docs/SETUP.md +10 -0
  638. package/docs/adapters.md +21 -8
  639. package/docs/brain-continuity.md +186 -0
  640. package/docs/cloud.md +108 -0
  641. package/docs/crews.md +62 -0
  642. package/docs/design-system.md +31 -2
  643. package/docs/integration-notes.md +128 -20
  644. package/docs/loompad.md +105 -0
  645. package/docs/observability.md +220 -0
  646. package/docs/play-store.md +123 -0
  647. package/docs/proposals/agent-teams.md +249 -0
  648. package/docs/proposals/brain-continuity-implementation.md +468 -0
  649. package/docs/proposals/brain-session-continuity.md +623 -0
  650. package/docs/proposals/t3code-port.md +81 -0
  651. package/docs/proposals/t3code-reference.md +95 -0
  652. package/docs/refactoring/AGENT-TEAMS-PROGRESS.md +88 -0
  653. package/docs/refactoring/BOUNDARIES.md +120 -0
  654. package/docs/refactoring/BRAIN-AUDIT.md +176 -0
  655. package/docs/refactoring/BRAIN-NOTES.md +390 -0
  656. package/docs/refactoring/BRAIN-TODO.md +214 -0
  657. package/docs/refactoring/NOTES.md +129 -0
  658. package/docs/refactoring/T3-PORT-NOTES.md +165 -0
  659. package/docs/refactoring/T3-PORT-TODO.md +123 -0
  660. package/docs/refactoring/TODO.md +46 -0
  661. package/docs/refactoring/brain-benchmark-2026-09-28.json +48 -0
  662. package/docs/refactoring/brain-benchmark-audit-2026-09-28.json +48 -0
  663. package/docs/release-notes/v0.2.0.md +35 -0
  664. package/docs/release-notes/v0.2.1.md +59 -0
  665. package/docs/release-notes/v0.2.3.md +77 -0
  666. package/docs/release-notes/v0.2.4.md +128 -0
  667. package/docs/release-notes/v0.2.5.md +153 -0
  668. package/docs/release-notes/v0.2.6.md +62 -0
  669. package/docs/release-notes/v1.0.0.md +120 -0
  670. package/docs/release-notes/v1.0.1.md +77 -0
  671. package/docs/release-notes/v1.1.0.md +71 -0
  672. package/docs/release-notes/v1.1.1.md +38 -0
  673. package/docs/release-notes/v1.1.2.md +21 -0
  674. package/docs/teams-architecture.md +697 -0
  675. package/docs/teams.md +171 -0
  676. package/docs/windows.md +85 -0
  677. package/package.json +22 -9
  678. package/dist/adapters/claude-code.d.ts +0 -26
  679. package/dist/adapters/claude-code.js +0 -209
  680. package/dist/adapters/claude-code.js.map +0 -1
  681. package/dist/adapters/codex.d.ts +0 -51
  682. package/dist/adapters/codex.js +0 -291
  683. package/dist/adapters/codex.js.map +0 -1
  684. package/docs/img/board-linear.png +0 -0
  685. package/docs/img/board-projects.png +0 -0
  686. package/docs/img/brain.png +0 -0
  687. package/docs/img/settings.png +0 -0
  688. package/docs/img/workspace.png +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,1060 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.2] — 2026-10-17
11
+
12
+ ### Fixed
13
+
14
+ - **A working agent's row in the Fleet spun over the row below it.** The
15
+ spinner's style applied to anything marked busy, so a busy Fleet row
16
+ shrank to a spinning dot with its name and status spilling over the next
17
+ row. The same thing happened to the terminal's input while a command ran,
18
+ the ✨ commit-message button while it worked, and busy nodes in the
19
+ Observatory graph. Only the spinner spins now.
20
+
21
+
22
+ ## [1.1.1] — 2026-10-16
23
+
24
+ Found installing 1.1.0 on a Mac whose projects live on an external drive.
25
+
26
+ ### Fixed
27
+
28
+ - **Loom Desktop explains a slow start instead of sitting blank.** The first
29
+ time it reads projects on an external drive (or in Documents or Desktop),
30
+ macOS asks whether Loom Desktop may access those files, and the background
31
+ service waits for the answer. The window now says *Starting Loom…* at once,
32
+ and after a few seconds that macOS may be asking, and to choose Allow.
33
+ - **It no longer starts a second background service** onto a port that's
34
+ taken when the first is running but waiting on that prompt. It waits for
35
+ the first one, up to five minutes.
36
+ - **The error page gives an installed app's advice**: quit and reopen, where
37
+ the permission lives in System Settings, and where the log is. It no longer
38
+ says "run npm run build". The pairing request has a timeout.
39
+ - **Builds prune compiled files whose source is gone.** Leftovers in a
40
+ long-lived checkout changed the build fingerprint the desktop app and the
41
+ CLI compare, so the same release could look like two builds and each would
42
+ restart the other's background service.
43
+
44
+
45
+ ## [1.1.0] — 2026-10-16
46
+
47
+ ### Can you trust what your agents did?
48
+
49
+ - **Proof**: when a reply claims the tests, build, typecheck or lint pass,
50
+ Loom checks the claim against what that turn actually ran, and re-runs the
51
+ tests in a clean worktree holding exactly the agent's changes. The verdict
52
+ is a card in the thread: Verified, Didn't hold (with why), or Unverified.
53
+ Every turn card has **Check it**; `loom proof` from a terminal.
54
+ - **Loop watch**: the same command failing three times in a turn (or the same
55
+ call five times) gets a card with Stop / Nudge it / Hand it off, and a push.
56
+ `watchdog.auto: "nudge"` also stops it and tells it to step back, once.
57
+ - **Blast-Radius Shield**: a force-push, `reset --hard`, a recursive delete
58
+ outside the project, `DROP TABLE`, `terraform destroy`, `npm publish`,
59
+ `sudo`, `curl | sh`, and the like get a red card and a push the moment an
60
+ agent runs them. `shield.auto: "stop"` (the default on a night shift) stops
61
+ the turn.
62
+ - **Review Triage**: every turn card says which files to read first, and why:
63
+ an added secret, a deleted or skipped test, auth code, a migration, CI,
64
+ dependencies, risky calls, a big change with no test.
65
+ - **Scorecards**: each agent's record of how often its "done" held up, its
66
+ circles and shield trips, and cost per verified result, in the
67
+ Observatory leaderboard, the phone, and `loom scorecard`.
68
+
69
+ ### Work that carries on without you
70
+
71
+ - **Night Shift**: line up tasks, one per line. They run one after another, a
72
+ chat each, while you're away, guarded by Proof, the loop watch and the
73
+ shield, and stop at a stop-by time or a budget. One morning report says how
74
+ each went. Desktop ⋯ → Night shift, phone 🌙, or `loom shift`.
75
+ - **Quota Relay**: an agent that hits its usage limit mid-task hands its work
76
+ (and a briefing) to the next agent, routes new prompts there while it's out,
77
+ and takes the baton back when the window resets.
78
+ - **Pre-flight forecast**: the composer shows what a turn on the chosen agent
79
+ usually costs and takes, from its own recent turns, and turns amber when
80
+ one more could cross its daily budget.
81
+ - **Replay**: export any chat as one self-contained HTML page to share, with
82
+ no scripts and nothing to load. ⋯ → Export as replay, or `loom replay`.
83
+ - **Design Mode**: a picked element in the Browser tab brings its computed
84
+ styles and its own screenshot into the composer.
85
+
86
+ ### Agent Teams
87
+
88
+ - **Persistent teammates** (P2) with their own native sessions and **crew
89
+ memory**. Teammates can now `remember` decisions, constraints and
90
+ conventions themselves.
91
+ - **Parallel builders** in isolated worktrees, and **races** where you pick
92
+ the result (P3).
93
+ - **Team coordination**: crews across teammates' daemons, owner requests, and
94
+ runners that execute crew goals. Full crew controls on desktop and phone.
95
+
96
+ ### Windows and a lighter daemon
97
+
98
+ - Windows **Job Object** containment, native continuity on Windows, and
99
+ OpenCode 1.19 continuity. Fixes for ConPTY exit races and CLI launching.
100
+ - **Memory**: the daemon starts ~25 MB lighter (the Claude SDK loads on first
101
+ use), idle OpenCode servers stop after 30 minutes, CLI probes are cached,
102
+ event reads are indexed, and long sessions no longer leak turn text,
103
+ attachments or socket backlogs.
104
+ - OpenCode bash calls report their exit code, so a failing command no longer
105
+ reads as a success.
106
+
107
+ ### Fixed
108
+
109
+ - A prompt sent to an agent just after its usage window reset, before the
110
+ baton came back, failed with "does not hold the baton". A stand-in that was
111
+ mid-turn at the reset kept the baton for good.
112
+ - A runner's dropped progress heartbeat left a goal's PR invisible to the
113
+ team for up to a minute; it's re-sent after 5 seconds.
114
+ - Phone sign-in aligned with GitHub; OAuth callbacks are validated.
115
+
116
+
117
+ ### One link to bring a teammate in, and crews of agents
118
+
119
+ - **Invite** (a project's header, or `loom invite`) gives you one https link.
120
+ Opening it signs the teammate in with GitHub, joins the team, and clones the
121
+ repo; for a private repo, your Loom grants push access on join and theirs
122
+ accepts GitHub's invitation. It then opens the repo with *their* agents,
123
+ shares it with the team, and sets up your crews. Without Loom, the link's
124
+ page shows one command that installs it and joins. `loom join <link>` does
125
+ the same from a terminal.
126
+ - **Crews** (Agent Teams, Phase 1): a lead, builders, a reviewer and a tester
127
+ work one goal in its own worktree. The Lead plans, you approve, and each card
128
+ is built, reviewed (with rounds of changes) and tested; then you apply the
129
+ branch. Use the Crew tab, or `loom crew create|goal|say|approve|stop|resume|apply`.
130
+ - The Crew tab: the crew's faces in a hero, each teammate as a card that
131
+ lights up while it works, the goal's progress, a board with a column per
132
+ stage, an approval banner, the channel as a conversation, and a composer
133
+ that knows whether you're starting, answering or changing the plan. Pick
134
+ which agent sits in each seat when you make a crew, and swap one later.
135
+ - Crews keep going when an agent misbehaves: a teammate that goes silent is
136
+ interrupted and retried once (`stallMinutes`, default 8); a turn that errors
137
+ is retried once; a reviewer or tester whose turn failed fails the card
138
+ instead of approving it.
139
+ - **Fixed:** OpenCode chat turns could end after a step that only ran tools,
140
+ before the answer, when the model was slow to start its next step. And
141
+ interrupting an OpenCode turn that never answered no longer waits out the hour.
142
+ - **Fixed:** a project forgot which tab you were on whenever it redrew while
143
+ loading, so you landed back on Chat.
144
+ - Team invite links are https links now. `loom://team/join#…` links still work
145
+ anywhere a link is accepted.
146
+
147
+ ### A hundred small things (the enhancement sweep)
148
+
149
+ Ranked, filed as #109–#208, and built top down. Each one was tried in the
150
+ running app with real agents before the next started.
151
+
152
+ **In the thread**
153
+ - **Find** (⌘F) with highlighted matches; **drafts** that survive reloads and
154
+ chat switches; **↑** recalls your last prompts; **[ / ]** jump between them.
155
+ - A reply's ⋯ menu: **Retry**, **Retry with…** another agent, **Continue** a
156
+ stopped reply, **Edit & resend**, **Quote**, **Star**, **Copy link**
157
+ (permalinks), **Branch from here**, **Make a card**, **Read aloud**.
158
+ - 👍 / 👎 on replies, counted on the Insights leaderboard.
159
+ - Day separators, relative times that stay fresh, **Show more** on very long
160
+ messages, a token estimate in the composer, **Reply length** (Brief /
161
+ Normal / Detailed), `{{variables}}` in saved prompts.
162
+ - **Mermaid** blocks get *Draw diagram* — the renderer is fetched the first
163
+ time you press it, never before.
164
+ - Export a thread to Markdown (also `loom export`).
165
+ - Error cards you can act on: a countdown on rate limits, *Send to…* another
166
+ agent, *Copy details*.
167
+ - A prompt sent while Loom is down waits and sends itself.
168
+ - Very long live threads trim themselves; the outline rail lists your prompts.
169
+
170
+ **The sidebar**
171
+ - Pin, archive and unread dots on chats; **folders** (right-click → Move to
172
+ folder…, fold them, rename or ungroup); **Group chats by agent**.
173
+ - *Since you were here*: back on a new day, Main opens with what happened
174
+ while you were away.
175
+
176
+ **Orchestra**
177
+ - The plan as a **graph** and a **timeline**; a live cost and time ticker;
178
+ **Run again**; a finish flourish.
179
+ - **Resume**: a run Loom stopped by restarting picks up where it was.
180
+ - **Race**: every picked agent takes the same goal in its own worktree; the
181
+ entrants sit side by side with a diff each, and *Pick this one* merges only
182
+ that one.
183
+
184
+ **Agents, memory, board, insights**
185
+ - Per-agent **standing instructions**, **pictures**, model **temperature and
186
+ max tokens**, and **Check** — installed, signed in, model listed, no prompt
187
+ sent.
188
+ - Memory you can **edit**, **export** and **import**; which memories agents
189
+ actually get (*used N×*, Most used); a **graph** of memories joined by the
190
+ files they share.
191
+ - Board cards with **priority** and **due** dates; **WIP limits** on columns.
192
+ - Insights: an agent **leaderboard**, an activity **heatmap**, costs as
193
+ **CSV**, and month-end at this pace.
194
+ - Diffs **side by side**, and **revert one file** of a turn.
195
+
196
+ **The app around it**
197
+ - Tab title and favicon show what's working and who needs you; a finished turn
198
+ in a hidden tab notifies (with an optional chime); **?** lists every
199
+ shortcut; **focus mode** (⌘.); a first-run tour.
200
+ - Text size, density and accent colour; view transitions between tabs;
201
+ reduced-motion respected; skeleton loaders; the branch in the status bar;
202
+ empty states you can recognise; a project whose folder is gone says so.
203
+ - Terminal find and clear. Diagnostics says what's running. Project settings →
204
+ Storage shows the log's size and compacts it.
205
+ - Voice input without a transcriber uses the browser's own speech recognition.
206
+ - CLI: `loom backup`, `loom export`, `loom stats`, `loom completion zsh|bash`,
207
+ `loom orchestra:resume`; `loom pair` carries the Loom Cloud route.
208
+ - Hardened edges: security headers, a throttled pairing claim, JSON errors
209
+ instead of Express's HTML pages (which leaked stack traces).
210
+
211
+ **On the phone**
212
+ - Follows the system theme; long-press a message to copy or share; a copy
213
+ button on code; pull to refresh; unread and working dots on the chat chips;
214
+ haptics.
215
+ - The daemon card graphs **link quality** over the last two minutes.
216
+ - An **offline copy** of the project list and your last eight threads, per
217
+ paired daemon, cleared on unpair.
218
+ - Android's status bar no longer covers every screen's header.
219
+
220
+ **Fixed on the way**
221
+ - Every *Rename…* used `window.prompt`, which the desktop app doesn't have —
222
+ they silently did nothing. An in-app dialog replaces all seven.
223
+ - A turn's diff was logged to Main whatever chat the turn ran in.
224
+ - An orchestra task's second attempt sent an empty prompt.
225
+ - A queued prompt lost its reply length.
226
+ - A skipped tab transition filled the console with uncaught rejections.
227
+ - `npm test` skipped four DOM suites; it runs them now.
228
+
229
+ ### Replies you can watch being written
230
+
231
+ - **The thread showed nothing between your send and the finished reply** —
232
+ fifteen seconds of a blank pane, then a wall of text. Nothing between an
233
+ adapter and the socket carried text that wasn't a finished event.
234
+ - Replies now stream token by token: Claude Code (`--include-partial-messages`),
235
+ OpenCode 1.18+ (`session.next.text.delta`, which the adapter had never
236
+ listened for), OpenAI-compatible model agents, and every orchestra worker in
237
+ its own task thread. The typing is a `stream` socket frame and is **never
238
+ logged** — the finished message is still the record, exactly once.
239
+ - Model agents logged a reply as a message per sentence (and a message per
240
+ reasoning token), which read as one answer chopped into a stack of bubbles.
241
+ They log it once now.
242
+ - **Stop keeps what was written.** A turn stopped mid-reply used to throw away
243
+ everything you'd watched arrive; it's kept, marked *stopped*.
244
+ - From the moment you send, the thread shows who's on it, for how long, and
245
+ what they're doing ("Codex · shell: npm test · 54s") instead of nothing.
246
+
247
+ ### A thread that reads like a document
248
+
249
+ - One reading column; replies have a byline (the agent's mark, name, model and
250
+ time) instead of a bordered bubble; prose is Geist, mono only for code.
251
+ - A run of tool calls folds into one line — *Ran 3 commands, read 2 files* —
252
+ that opens to the list.
253
+ - Every turn ends on a footer: who, how long, which model, what it cost.
254
+ - An orchestrator's plan is a card of tasks, agents and files, not a page of
255
+ JSON. An empty round says "still looking" rather than "didn't parse". A
256
+ task's status updates in its own row instead of adding a line per state.
257
+ - Code blocks are syntax-highlighted with a language label; markdown tables
258
+ render; errors are a card with the provider's raw payload folded away.
259
+ - The thread stays where you are when you've scrolled up to read, with a
260
+ **Latest** pill, instead of yanking you to the bottom on every event.
261
+ - **Load earlier messages** pages the thread backwards (`?before=` on the
262
+ events API); it stopped at the last 60 events before.
263
+ - An empty thread offers something to start with instead of a blank pane.
264
+
265
+ ### Picking who and on what
266
+
267
+ - The agent and its model are one control in the composer. The agent picker
268
+ shows each agent's model and permission mode, hides switched-off agents, and
269
+ ticks with a check (it was the info icon).
270
+ - The model picker has descriptions, keyboard navigation, **free models
271
+ first**, and fits the window (it ran off the top with Orchestrate open).
272
+ - **Picking a model agent's model from the list broke the agent.** The list
273
+ leads each id with its provider (`openrouter/google/gemma…`), and that whole
274
+ string went to the provider as the model name. It's split now, on save and
275
+ for configs already saved that way.
276
+ - A model agent with the generic id is named by its model ("gemma-4-31b-it").
277
+ - **Ask several models** is in the composer's More menu: tick models, and
278
+ what's in the box goes to each, a thread apiece. It was CLI-only.
279
+
280
+ ### Orchestrate
281
+
282
+ - The cast panel reads as Lead / Team / At once, and each worker chip has two
283
+ zones — include/leave out, and its model and mode — so a click on the chip
284
+ no longer lands on a badge and opens a menu instead.
285
+ - The cast is remembered per project; a reload reset it to "every agent" and
286
+ the next run quietly used agents you'd left out.
287
+ - Each task thread is pinned to its worker: the sidebar says who, and the
288
+ composer in that thread aims at that agent.
289
+ - A finished run ends on a result card with **Apply to your branch**; a run
290
+ that ended before any task finished no longer offers an Apply with nothing
291
+ on its branch.
292
+ - Loom's own `.loom/` state no longer counts as "uncommitted changes" in the
293
+ warning every run showed.
294
+ - Fleet said "no agents running" above a run with workers in flight.
295
+
296
+ ### One workspace at every window size
297
+
298
+ - **Narrowing the window swapped in the phone layout** and took the sidebar,
299
+ the tabs and the panels away. On anything with a mouse the workspace now
300
+ stays at every width: the sidebar slims, then slides in behind a toggle; tabs
301
+ go icon-only (each with a tooltip); the right panel steps aside. The single
302
+ column is for touch phones only.
303
+ - Tabs say what they are: **Chat, Orchestra, Agents, Board, Memory, Insights**
304
+ (they were Thread, Fleet, Brain and Observatory), each with a one-line hint.
305
+ - A turn reads as a timeline: the agent's mark, a hairline through its tool
306
+ steps, a node where it ends. Your prompt is the card that opens a turn;
307
+ code blocks have an editor header; file edits are a review card
308
+ ("Edited 3 files +12 −4"); a reply can be copied from its byline; the
309
+ composer's border lights up when you're in it and send lights up when
310
+ there's something to send.
311
+
312
+ ### And the rest
313
+
314
+ - **Loom on Node older than 22.5 showed every thread empty** — no node:sqlite,
315
+ so it opened a fresh JSONL log beside the real one (a shell that put nvm's
316
+ Node 20 first after a reboot). The CLI now refuses to start on <22.5 and says
317
+ why, and the log refuses to open an empty fallback beside a log.db.
318
+
319
+ - `loom up --restart` left the old daemon alive — its port freed, the process
320
+ and everything it held still running — because shutdown waited on the
321
+ browser's keep-alive and WebSocket connections forever. They're closed now,
322
+ and a stuck shutdown exits after five seconds.
323
+ - The sidebar rebuilt itself every five seconds, dropping hover and focus under
324
+ the pointer; it only redraws when something changed. Older threads fold
325
+ behind "Show N older".
326
+ - The everyday confirmations (abort a run, remove a project, clear the queue,
327
+ update Loom) are an in-app dialog; the browser's own was dismissed unseen by
328
+ some embedders, so Abort simply did nothing.
329
+ - Escape closes any composer menu; the right panel opens by default only on
330
+ wide windows; a reload reopens the project you were in.
331
+ - **Reload mid-reply and the reply is still there.** A thread's first page
332
+ carries what agents are typing in it right now, and stream frames carry their
333
+ offset, so a window opened mid-answer shows the whole reply so far and keeps
334
+ going without repeating or dropping words.
335
+ - When the daemon stops answering, one banner says so and how to start it,
336
+ instead of a "Failed to fetch" toast every few seconds; it clears itself and
337
+ the views refresh when the daemon is back.
338
+ - Terminals stopped stacking a "restored scrollback" divider and prompt for
339
+ every restart nobody typed through.
340
+
341
+ ### On the phone
342
+
343
+ - Replies stream in live, over the LAN, the tailnet or Loom Cloud, and render
344
+ as markdown — code blocks, lists, bold, inline code. The orchestrator's plan
345
+ reads as a plan card, not a JSON dump, and the Fleet previews drop the marks.
346
+ - The Pair screen's second button said "Paste link instead" and actually
347
+ submitted the fields. It now says Connect when something's typed (Enter works
348
+ too) and pastes from the clipboard when nothing is.
349
+ - A thread that can't load (the route still settling, the daemon down) says so
350
+ and retries until it does, instead of sitting blank; "Network request failed"
351
+ became a sentence that says what to check.
352
+
353
+ ## [1.0.1] — 2026-09-21
354
+
355
+ ### Orchestra spawns its workers again
356
+
357
+ - **An orchestrator's plan was being thrown away before it ran.** Every run
358
+ planned tasks and started none: the Fleet sat idle, no task threads appeared,
359
+ and the thread said *"your reply had no ```loom actions block"* directly
360
+ underneath a reply that plainly contained one.
361
+ - The engine parses accumulated turn text, and that text was capped to its
362
+ **last** 20,000 characters. A plan's block sits at the END of a long reply,
363
+ so the cap kept the closing fence and threw away the opening one; the parser
364
+ saw an unterminated block and reported nothing to run. **The better the
365
+ orchestrator planned, the more certainly its plan was binned.** Measured on a
366
+ real run: seven consecutive plans of 6, 5, 5, 5, 5, 8 and 8 tasks, every one
367
+ parseable from the log and every one destroyed.
368
+ - The budget is now far clear of any plausible reply, and when it is reached
369
+ the cut is made at the start of the actions block rather than at a blind
370
+ character offset — so what protects memory can never decapitate the payload.
371
+
372
+ ### Answer an agent where it asked
373
+
374
+ - **An agent's question is now a card you can answer in the thread.** It was a
375
+ line of text with nothing to click, which made the one moment Loom exists to
376
+ surface — an agent blocked on a human — the worst affordance in the app.
377
+ - The answer goes to **the agent that asked**, taken from the card. Through the
378
+ composer it went to `state.selected`, which in an orchestra thread is the
379
+ orchestrator — so answering a worker sent the answer to the wrong agent.
380
+ - A question that plainly offers a choice becomes buttons. Anything ambiguous
381
+ falls back to the text box, because a wrong guess puts words in your mouth
382
+ and sends them to an agent.
383
+
384
+ ### A giant icon no longer eats the Board
385
+
386
+ - Board → GitHub rendered a single enormous ⓘ filling the pane whenever `gh`
387
+ couldn't list pull requests, pushing the columns out of view.
388
+ - `svg()` emitted no width or height, so an icon in a container that forgot its
389
+ CSS rule stretched to fill the line — and `.bnote` was such a container.
390
+ Icons now carry an intrinsic size, so a **future** icon dropped somewhere
391
+ unstyled looks slightly wrong instead of covering the screen.
392
+
393
+ ## [1.0.0] — 2026-09-21
394
+
395
+ ### Rewind — put the work back the way it was
396
+
397
+ - **A checkpoint before every turn**, and **Rewind** on the Update card of the
398
+ turn it undoes. There is a **Rewind…** list under More for all of them, and
399
+ `loom rewind` in the terminal. The honest answer to *undo that* used to be
400
+ "read the diff and retype it": `turn_diff` looks like the answer and isn't,
401
+ since its patch is truncated at 12KB and an untracked file appears in it as
402
+ a line with no content.
403
+ - **It restores files, not history.** HEAD does not move, your commits are not
404
+ touched, and the thread is not edited. What happened still happened.
405
+ - **`.gitignore` applies at capture**, so `node_modules`, build output, `.env`
406
+ and `.loom/` are never read, never stored and never restored — which is why
407
+ a rewind cannot eat the event log.
408
+ - **A rewind is itself rewindable.** It saves what it is about to replace
409
+ before replacing it, and hands that back: *Undo the rewind* in the thread,
410
+ an id on the command line.
411
+ - **Refused while an agent is mid-turn**, naming who. Replacing the tree under
412
+ a running agent puts the damage in whatever it writes next.
413
+ - Checkpoints live on hidden refs under `refs/loom/checkpoints/`, so no branch
414
+ listing, no stash and no `git log` shows one. The newest 60 are kept.
415
+
416
+ ### A transcript you can turn up
417
+
418
+ - **Normal / Thinking / Verbose**, under More. Normal drops reasoning entirely
419
+ rather than folding it — the working out is not the transcript. Verbose
420
+ opens it and attaches the raw payload to tool calls and to the
421
+ orchestrator's brief, the two places a summary stands in for something
422
+ bigger. Remembered per project.
423
+ - **A long block is readable to the end.** Code wraps instead of scrolling out
424
+ of the bubble, and every block — markdown or raw — carries a copy button.
425
+ The orchestrator's `{"actions": …}` plan used to be clipped in a scroll box
426
+ with no way to reach the closing brace.
427
+
428
+ ### Orchestrating from Main stays in Main
429
+
430
+ - **The orchestrator answers in the thread you asked in.** It used to open one
431
+ of its own and walk you into it, leaving the goal you typed behind in a
432
+ thread that then said nothing about it.
433
+ - **Each task row opens that task's thread.** They were findable only by
434
+ hunting the sidebar for a title you half remembered.
435
+ - **A borrowed thread is given back.** Replying in a run's own thread steers
436
+ the run for good; a thread the run borrowed stops answering for it once the
437
+ run is terminal, so Main goes back to being Main rather than forwarding
438
+ every later message to a finished goal.
439
+
440
+ ### A thread says who's working in it, and whether it's still going
441
+
442
+ - **A task thread is labelled with the agent doing that task**, not with
443
+ whoever holds the project baton. During a run with four workers every task
444
+ thread used to claim to be the baton holder, so a Codex task and an
445
+ Antigravity task looked identical. A thread pinned to an agent answers the
446
+ same way.
447
+ - **Thread rows show status** — a live pulse while a task runs, green when it
448
+ finishes, red when it fails, amber when it's waiting. Every answer comes
449
+ from a status the daemon already reports; a thread it can't know about gets
450
+ no mark rather than a guess.
451
+ - The status payload now carries one row per task (thread, agent, kind,
452
+ state) instead of only a count, which is what made both of those possible.
453
+
454
+ ### Models in Orchestrate
455
+
456
+ - **Every agent chip carries its model**, orchestrator and workers alike,
457
+ beside its permission chip. Orchestrate could pick who ran a goal and never
458
+ what they ran it on: the model picker was bound to the one agent the chat
459
+ composer is aimed at, which in Orchestrate is nobody.
460
+ - **A dashed “+ model” chip** adds an API model to the cast and opens its
461
+ picker straight away. Until a model is picked the chip warns, and Orchestrate
462
+ refuses to start — naming the agent — rather than failing three tasks in.
463
+ - The model list's provider-asked source had no case in its footer, so it
464
+ printed *“no model list for this agent”* directly above 446 of them. And it
465
+ no longer offers a model agent a **Default**, which for that kind is the one
466
+ option that cannot work.
467
+
468
+ ## [0.2.6] — 2026-09-20
469
+
470
+ ### Right-click, and a composer that fits
471
+
472
+ - **Right-click a project** for everything you can do to it: open, new chat,
473
+ settings, **rename**, copy path, and **Remove from Loom**. Those were
474
+ scattered — settings behind a gear, rename nowhere at all, and removing a
475
+ project only in `loom projects --forget`.
476
+ - It says **Remove from Loom**, not Delete, and the confirm says the folder,
477
+ the history and `.loom/` stay on disk. A menu item that says delete and
478
+ doesn't is as bad as one that says delete and does.
479
+ - **Right-click a thread** to open it, rename it, pin which agent answers in
480
+ it, or forget it. The main thread offers only what applies to it, rather
481
+ than offering everything and refusing half.
482
+ - Escape and any click outside close the menu, arrow keys walk it, and it
483
+ flips rather than hanging off the edge of the window.
484
+ - **MCPs and Skills moved into a More menu** in the composer, which also
485
+ reaches Prompts and Attach. That row was holding the model, the agent, a
486
+ permission chip, five buttons and send, and wrapped on a narrow window. The
487
+ count badge stayed outside — *two skills are on* is the part you need
488
+ without opening anything.
489
+
490
+ ### Setup tells the truth about this machine
491
+
492
+ - **Claude Code showed "not installed" on machines where it is.** Anthropic's
493
+ installer puts the binary in `~/.local/bin`, and Loom trusted `PATH` alone —
494
+ which an interactive shell has and a detached daemon may not. Codex, Grok
495
+ and Antigravity already looked in their known locations; claude-code was the
496
+ one still guessing. Telling someone to reinstall software they already have
497
+ is the worst kind of wrong answer.
498
+ - **The Model (API) row said "couldn't confirm it's signed in" and printed a
499
+ blank command.** There is nothing to sign in to: a model agent is usable
500
+ when a provider has a key, so it says which providers are configured, and
501
+ when none is, it gives you `loom providers:set …` instead of an empty box.
502
+ - **The desktop app says Loom in the menu bar**, in a dev run as well as a
503
+ packaged one. macOS takes that title from the running bundle, not from
504
+ `app.setName()` — which is why setting the name in code never fixed it. The
505
+ `.app` filename is unchanged, so the Homebrew cask keeps working.
506
+
507
+ ## [0.2.5] — 2026-09-20
508
+
509
+ ### Install it with Homebrew
510
+
511
+ - **`brew tap nickthelegend/loom https://github.com/nickthelegend/loom` then
512
+ `brew install --cask loom-desktop`** — and `brew upgrade --cask` after that,
513
+ which is a real update path for the macOS build that can't replace itself.
514
+ The cask carries both architectures and is regenerated from the published
515
+ checksums by the release job, so it can't go stale.
516
+ - **Check for Updates… recognises a Homebrew install** and hands you the
517
+ `brew upgrade` command instead of downloading over a copy brew is tracking —
518
+ the same rule the Linux `.deb` already had. **Run it in Loom** runs it in
519
+ Loom's own terminal, the one in the dock, so you watch the upgrade rather
520
+ than having it happen invisibly inside the app.
521
+ - It does **not** get you past Gatekeeper, and doesn't pretend to: brew
522
+ quarantines cask downloads on purpose. First launch asks once, as it does
523
+ for a dmg you downloaded yourself. The cask deliberately does not strip the
524
+ quarantine attribute — that protection exists *because* the app is unsigned.
525
+
526
+ ### A model agent can write, when you say so
527
+
528
+ - **`--write`** gives a model agent `write_file`, and **`--run "npm test"`**
529
+ gives it `run` with an allow-list. Every write and every command is a card
530
+ in the thread that you allow or deny before anything happens — the same
531
+ approval surface Claude Code's "always ask" already uses, now asked from
532
+ inside the daemon instead of over MCP.
533
+ - **It asks in `auto` too**, which is stricter than the CLI mapping and
534
+ deliberately so: a CLI in your roster is one you installed and signed into,
535
+ and a model agent is a name you picked off a provider's list an hour ago.
536
+ `bypass` is the only mode that doesn't ask, because that is what bypass
537
+ means.
538
+ - **The card says what would happen** — *write src/app.ts: 40 lines
539
+ (replacing 12) — fix the port* — rather than dumping the whole new file at
540
+ you.
541
+ - The allow-list is a prefix match on whole commands and there is no shell, so
542
+ `npm test` permits `npm test --watch` and refuses `npm testify`,
543
+ `npm test; rm -rf ~`, backticks, pipes and redirection. A tool is only
544
+ offered when it can be used: no allow-list, no `run` tool at all.
545
+ - With nobody to ask — no daemon, a script, a test — the answer is **no**. A
546
+ tool that proceeded because the UI wasn't wired up would be the worst
547
+ failure this could have.
548
+
549
+ ### A model agent can read the project
550
+
551
+ - **`"tools": true`** on a `model` agent gives it `read_file`, `list_files`
552
+ and `search` — read-only, inside the project, `.git` and `.loom` excluded,
553
+ every path resolved and proven contained before anything opens it. A
554
+ reviewer that can't read the file it's reviewing is being asked to guess.
555
+ - Each call appears in the thread as a `tool_call`, like any other agent's
556
+ work, and the loop is bounded: after eight hops the model is told to answer
557
+ with what it has rather than being cut off mid-thought.
558
+ - **No writing and no shell.** A model that can write files is exactly as
559
+ dangerous as a CLI that can, and the right answer is the permission layer
560
+ Loom already has. That's the rest of #87, and it stays open for it — a free
561
+ model editing a repository because it felt like it is not a thing to ship
562
+ quietly.
563
+
564
+ ### Ask several models at once
565
+
566
+ - **`loom ask --models a,b,c "…"`** sends one prompt to several models at the
567
+ same time, each in its own thread named after the model, with the project's
568
+ memory brief attached. `--free` picks the free ones the providers have right
569
+ now, up to `--limit`. With free quota, asking five models costs what asking
570
+ one costs — and *which of these is right* is a judgement a person makes in
571
+ ten seconds and a model makes badly.
572
+ - The agents that run are **transient**: five asks don't leave five agents in
573
+ your roster. The threads stay, because those are the part worth keeping.
574
+ - One model failing doesn't take the others down — its thread carries the
575
+ error, the rest carry their answers.
576
+
577
+ ### A thread remembers who answers in it
578
+
579
+ - **Pin an agent to a thread** and it answers there, whoever holds the baton —
580
+ so two threads can be talking to two agents at once, which is the point of
581
+ having agents that cost nothing. Picking an agent for a new chat now pins it
582
+ instead of handing over the baton, and the sidebar shows which thread is
583
+ with whom.
584
+ - **It doesn't take the baton.** The baton is the write lock for work on the
585
+ repository; a conversation doesn't need it, and taking it would stop
586
+ whatever is actually working.
587
+ - A thread can pin a **model** too, for agents that can change model per turn
588
+ (the `model` kind). Binding one to an agent that bakes its model into a
589
+ spawned process is refused where you can fix it, rather than ignored where
590
+ you'd never notice. The main thread still follows the baton — that's what
591
+ makes it the main thread — and a thread whose agent has left the roster
592
+ falls back to the baton rather than becoming one nobody can type in.
593
+
594
+ ### Agents that are models, not CLIs
595
+
596
+ - **A new agent kind, `model`.** It's an HTTP endpoint rather than a
597
+ subprocess: OpenAI-compatible chat completions, streamed into the thread as
598
+ they arrive, with reasoning shown as reasoning and token counts on
599
+ `run_complete`. Nothing to install. It has no tools yet, so what it's for is
600
+ the thinking work — planning, reviewing, summarising, answering — which is
601
+ most of what a fleet does between edits.
602
+ - **Providers, and keys where keys belong.** OpenRouter, AgentRouter, OpenAI,
603
+ Groq and a local Ollama are known by name; anything else speaking
604
+ `/v1/chat/completions` works with a base URL. The project config names a
605
+ *provider*, never a secret: keys live in the environment or in
606
+ `~/.loom/providers.json` (0600), and no route, log or listing ever returns
607
+ one — you get the last four characters. `loom providers`,
608
+ `loom providers:set <id> --key …`.
609
+ - **`loom models`** asks each configured provider what it can run right now,
610
+ cached for ten minutes and refreshable, with the free ones marked. A model
611
+ list that's typed out by hand goes stale; one that's asked for doesn't.
612
+ - **Fallbacks that read the answer.** A dry free pool (402) or a rate limit
613
+ (429) moves to the next model in `fallbacks` and says so once in the thread;
614
+ a wrong or retired model name (503) stops, because trying something else
615
+ would hide the typo rather than fix it. Each refusal is explained in its own
616
+ terms — a rejected *client* is not a rejected key.
617
+
618
+ ### Retrieval that can follow a synonym
619
+
620
+ - **A semantic channel for the brain** (`brain.semantic`, or Settings →
621
+ Brain): all-MiniLM-L6-v2 embeddings unioned with the three lexical channels,
622
+ so *how does login work* reaches a note about Supabase JWKS. Measured on the
623
+ recall set that shipped with 0.2.4: recall@5 **0.50 → 1.00** on synonyms,
624
+ **0.80 → 1.00** across word forms, unchanged at **1.00** on literal queries.
625
+ Warm cost is about a millisecond a query.
626
+ - It is **not** a dependency and never will be: the model is 23MB but its ONNX
627
+ runtime is ~470MB, so Loom asks you to install that yourself
628
+ (`npm i -g @huggingface/transformers`) and behaves exactly as before when
629
+ it's missing — a channel that can be absent must fail into the old answer,
630
+ not into an error. Vectors are cached per memory hash beside the brain, and
631
+ the model stays offline after its first download.
632
+
633
+ ### macOS gets the update too
634
+
635
+ - **Help → Check for Updates… on macOS** now finds the build for your
636
+ architecture, downloads it, and **verifies its SHA-256** against the
637
+ checksums the release publishes — a file that doesn't match is deleted
638
+ rather than opened — then opens the disk image for you to drag across. The
639
+ drag stays yours: macOS only lets an app signed by a certificate it trusts
640
+ replace itself, and this build is ad-hoc signed. The checking is the part
641
+ worth having; the checksums have shipped since 0.2.0 and nobody compares
642
+ them by hand.
643
+
644
+ ## [0.2.4] — 2026-09-20
645
+
646
+ ### The desktop app can update itself, where that's honest
647
+
648
+ - **Help → Check for Updates…** on **Windows** and the **Linux AppImage**:
649
+ it asks before downloading, installs on quit, and restarts only when you
650
+ press Restart. On **macOS** it refuses and says why — the build is ad-hoc
651
+ signed, and macOS only replaces an app signed by a certificate it already
652
+ trusts — and opens the releases page instead. A `.deb` install is left to
653
+ the package manager that owns it. The release now publishes the update feed
654
+ for those two platforms and deliberately not for macOS: advertising an
655
+ update the OS will refuse to install is worse than advertising none.
656
+
657
+ ### Dark mode in the preview
658
+
659
+ - **Auto / light / dark for the previewed page**, independent of Loom's own
660
+ theme and remembered per project, alongside the widths. It re-points the
661
+ page's own `prefers-color-scheme` rules through the proxy bridge and makes
662
+ `matchMedia` answer to match, so both CSS-themed and JS-themed apps follow;
663
+ Auto restores every rule exactly as it shipped. Where Loom can't reach the
664
+ page it says so rather than offering a switch that does nothing, and the
665
+ screenshot — a real browser — honours the scheme either way.
666
+ - The width you chose is now actually **read back**: it was being saved and
667
+ never restored, which is the same as not remembering it.
668
+ - A screenshot and an element pick both carry the conditions they were taken
669
+ under (*375×812, dark mode*) into the prompt.
670
+
671
+ ### The baton can carry the work
672
+
673
+ - **`git.mergeOnHandoff`** (with `worktreePerAgent`): handing the baton from A
674
+ to B merges `agent/A` into B's checkout, so the next agent starts from what
675
+ the last one finished. It refuses rather than guesses — uncommitted work on
676
+ either side, or a merge already in progress, is reported instead of merged —
677
+ and a conflict is left in the tree with the files named, in the briefing and
678
+ in the handoff event. A conflict stops a route instead of prompting an agent
679
+ on top of conflict markers.
680
+
681
+ ### Routes: steps that decide whether to run
682
+
683
+ - **A route step can carry a condition on the previous turn** and is skipped
684
+ when it doesn't hold: `loom route 'planner,executor,reviewer?lines>200' "…"`,
685
+ or `{ "step": "reviewer", "when": "lines>200" }` in the project config.
686
+ Conditions read the turn's own diff — `changed>N`, `changed<N`, `lines>N`,
687
+ `lines<N`, `touched:<glob>`, `!touched:<glob>` — and nothing else: a
688
+ condition must be something Loom measured, never a judgement about the work.
689
+ Unreadable ones are refused when the route is defined rather than quietly
690
+ never matching, the first step can't be conditional (no turn to measure),
691
+ and a skipped step appears in the thread with the numbers that decided it.
692
+ Skipping isn't failing — the route completes.
693
+
694
+ ### A pull request you asked for
695
+
696
+ - **Open PR on a review card.** With branch-per-card on, a card in review shows
697
+ what a PR would carry — the branch, its commits, its files and the exact
698
+ command — and opens it only when you press the button. Asking pushes
699
+ nothing; publishing has never been implicit and still isn't.
700
+
701
+ ### Coming back to a project
702
+
703
+ - **A digest of what happened while you were away** — goals, landings,
704
+ failures, a dead server, and what's waiting on you, newest first and each
705
+ line clicking through to the moment it came from. Shown when you've actually
706
+ been away; `loom digest --since 8` in the terminal.
707
+ - **The desktop app's notifications carry the question itself**, not "an agent
708
+ needs you", and on macOS you can answer from the notification. Nothing fires
709
+ while you're looking at that conversation.
710
+
711
+ ### Goals: a spend cap, and more than one at a time
712
+
713
+ - **`loom orchestrate --max-usd 2`** stops a goal at its cap the way the team
714
+ budget always did — running work finishes, nothing new starts, and the goal
715
+ waits for you. A project default lives in `budgets.perGoalUsd`, and a word
716
+ lands in the thread at 80% rather than the stop being the first you hear.
717
+ - **`maxConcurrentGoals`** lets disjoint goals run side by side. A goal's
718
+ scope is the `touches` its plan declares; one that hasn't said what it
719
+ touches counts as everything and waits. Overlaps queue with the collision
720
+ named. Still one at a time unless you ask for more.
721
+
722
+ ### The queue can wait, and can be kept
723
+
724
+ - **Queue for later**: a prompt can be held for a time, until a goal actually
725
+ **lands**, until that goal's **checks go green**, or until the project has
726
+ been quiet for a while. The row says what it's waiting for and a click
727
+ releases it. (`loom queue at 03:00 …`, `loom queue after green:<runId> …`)
728
+ - **Recipes**: save what's queued and run it on any project. Steps remember
729
+ their target by **role**, so a recipe travels; anything the project can't
730
+ resolve becomes an Auto prompt rather than a refusal. (`loom queue save`,
731
+ `loom queue run`, `loom queue recipes`)
732
+ - **Drag to reorder** in the web app; the arrows stay for anyone who can't
733
+ drag, and the phone gained up/down controls it never had.
734
+
735
+ ## [0.2.3] — 2026-09-20
736
+
737
+ ### The Browser tab knows your dev servers
738
+
739
+ - **Loom can run them.** Declared under `servers` in `.loom/config.json` and
740
+ suggested from `package.json` (a suggestion you accept, never something that
741
+ starts itself). Start, stop and restart from the Browser tab or the CLI.
742
+ - **The state is a fact, not a guess**: *running* means a port answered,
743
+ *starting* means the process is up and nothing is listening yet, and
744
+ *crashed* carries the exit code.
745
+ - **Its output is there too**, under the page it serves — which is where the
746
+ reason for a blank frame usually is — and a server that dies while an agent
747
+ is working against it says so in the thread.
748
+ - Clicking a server points the preview at it; no more typing ports from memory.
749
+ - Every server Loom started is stopped when the daemon goes, so nothing is left
750
+ holding a port.
751
+ - `loom servers`, `loom servers start|stop|restart <name>`, `loom servers logs
752
+ <name>`.
753
+ - **The preview emulates a width** — Fit / 375 / 768 / 1280, remembered per
754
+ project and scaled down when the dock is narrower than the page.
755
+ - **It reloads when an agent changes files** (a toggle, on by default), so
756
+ watching a change land doesn't involve remembering to refresh.
757
+ - **The previewed page reports back.** Loom previews a server through its own
758
+ proxy — forwarding everything, including the hot-reload socket — and injects
759
+ one script. The **Page** pane shows the page's console and its requests,
760
+ live, and a click puts a line into the composer as context.
761
+ - **An element picker.** Click the thing that's wrong in the preview and its
762
+ selector, text, box and markup land in the composer.
763
+ - **A camera button puts the view into the composer.** The page is another
764
+ origin and can't photograph itself, so the daemon takes the shot with the
765
+ project's own Playwright; a project without it is told exactly that.
766
+
767
+ ### An Update button that actually updates
768
+
769
+ - **Loom says when a newer version is out** — checked against the published
770
+ release, cached for hours, shown as a pill in the status bar.
771
+ - **One button in Settings → Updates**, which says exactly what it will run
772
+ before it runs it: a git checkout pulls and rebuilds, a global npm install
773
+ reinstalls itself, and anything else is pointed at the release rather than
774
+ having a command guessed at and run over it.
775
+ - **A checkout with uncommitted changes is refused** (modified tracked files —
776
+ an untracked scratch file doesn't stop a fast-forward).
777
+ - The commands' output streams while they run, then the daemon restarts on the
778
+ new build and the page reconnects to it.
779
+ - `loom update [--check] [--yes]` does the same from the terminal.
780
+
781
+ ## [0.2.1] — 2026-09-20
782
+
783
+ ### The prompt queue
784
+
785
+ - **What you type while something is running now waits where you can see it.** A
786
+ prompt sent to a busy agent used to be queued invisibly — logged into the
787
+ thread as if it had been sent, with nothing to look at and nothing to change —
788
+ and a goal typed while another goal ran was refused outright.
789
+ - **The queue is a surface**, above the composer on the web, the desktop app and
790
+ the phone, and `loom queue` in the terminal: every waiting prompt with who
791
+ takes it, editable in place, movable, removable, pausable.
792
+ - **Each prompt names its own target:** one agent, the **orchestrator** (a whole
793
+ new goal, started when the running one finishes), or the auto router — and you
794
+ can change it while the prompt waits. The baton moves with it.
795
+ - **A question holds the queue:** an agent that stops to ask you something isn't
796
+ answered by whatever you queued behind it. The queue waits and names who
797
+ asked; your typed reply goes straight out and lifts the hold, so what was
798
+ waiting runs next. A pause you set yourself stays until you resume it.
799
+ - **Stop pauses the queue** instead of emptying it, and a prompt that can't be
800
+ sent (budget, quarantine, a policy, a missing agent) stays put with the reason
801
+ on the queue rather than disappearing.
802
+ - **A prompt enters the conversation when it is sent**, not when it is queued, so
803
+ the thread stays an honest record of what each agent was actually asked.
804
+ - Survives a daemon restart, reloaded **paused** (`.loom/queue.json`). API:
805
+ `GET/POST /api/projects/:id/queue`, `PATCH|DELETE .../queue/:itemId`,
806
+ `POST .../queue/pause`, `DELETE .../queue`, plus a live `queue` socket frame.
807
+
808
+ ### Fixed
809
+
810
+ - **An override of `loom/review` made while that review is still running** is no
811
+ longer overwritten when the review finishes (D61) — found on a real PR, where
812
+ a late review wrote `failure` over the owner's decision.
813
+ - **A turn is no longer blamed for Loom's own `.loom/` files.** In a project that
814
+ doesn't gitignore `.loom/`, the event log and the queue file were landing in
815
+ the agent's turn diff.
816
+ - **grok-code and agy** are detected from their own auth files instead of being
817
+ reported signed-out, and the status bar says **live**, not offline, before a
818
+ project is open.
819
+ - **A reply that lands after its window closed** no longer throws from a redraw.
820
+ - **An overridden review leaves its status where the owner put it.** A review
821
+ coming back to a commit that was already overridden kept the decision but
822
+ posted nothing, leaving its own "reviewing…" status pending — on a repo that
823
+ requires `loom/review`, for ever.
824
+ - **Retargeting a queued prompt** to an agent the project doesn't have is
825
+ refused when you make the change, not when the queue reaches it.
826
+
827
+ ### Loom Teams, Phase 6: land in turn, hear it now
828
+
829
+ - **6 more design decisions** (D79–D84), settled with the owner.
830
+ - **The landing train:** on a repo with no merge queue, Land queues a goal in its
831
+ lanes and Loom merges it on its turn: fresh main in, the fast tests, a push,
832
+ green checks on that commit, then `gh pr merge --squash`. The slot is a team-hub
833
+ lease on `.loom/landing/<lane>` held as a hard zone, so every hub (in-memory,
834
+ `loom hub`, hosted SQL) arbitrates it with no new API. Waiting goals show
835
+ **queued** and go as soon as the lane frees. A red check on its turn hands the
836
+ lane on, and the goal rejoins when it's green. Repos with a merge queue land as
837
+ before.
838
+ - **Lanes:** `landing.lanes` in `loom.team.json` are path scopes; goals in
839
+ different lanes land at the same time.
840
+ - **GitHub webhooks into the hub, no App needed:** `loom hub` takes
841
+ `POST /github/webhook/:teamId`, checks `X-Hub-Signature-256` against the team's
842
+ secret, and posts PR, check, review and deploy events to the feed.
843
+ `loom team webhook [--install] [--rotate]` sets it up. The hosted hub gets a
844
+ `github-webhook` Edge Function and `supabase/migrations/0009_phase6.sql`
845
+ (deployment pending).
846
+ - **Polling and webhooks agree:** one mapping (`src/core/github-events.ts`) gives
847
+ both the same dedupe keys, so a fact is posted once. Failing checks are now one
848
+ feed event per check and commit, and `gh pr list` polling reads `headRefOid`.
849
+ - **Faster fixes:** a check result or merge for one of your goal PRs makes your
850
+ daemon look at it immediately, not at the next 30-second poll.
851
+ - **UI:** a `queued` landing chip (desktop and phone), and feed lines for the
852
+ train and for reviews that arrive by webhook.
853
+
854
+ ## [0.2.0] — 2026-09-19
855
+
856
+ Loom Teams: five phases, 78 design decisions, several people and their agents on
857
+ one repo. The sections below go phase by phase, newest first.
858
+
859
+ ### Loom Teams: loose ends closed
860
+
861
+ - **Paste-the-URL sign-in** for the hosted hub on machines without a browser
862
+ (`loom team signin --paste`; `loom runner join` uses it by default).
863
+ - **Stacks fold when a lower PR keeps failing:** its lower PRs close and the top
864
+ one retargets the base branch, so the normal fix loop can fix it.
865
+ - **CI minutes per goal:** Actions time on a goal's branch is recorded when it
866
+ lands and shown in team spend (desktop and phone).
867
+ - **Docs:** a Teams user guide ([docs/teams.md](docs/teams.md)), a docs index,
868
+ a source map, and READMEs for `supabase/`, `src/hub/`, `test/`, `scripts/`
869
+ and `hardware/`.
870
+
871
+ ### Loom Teams, Phase 5: runners
872
+
873
+ - **12 more design decisions** (D67–D78), settled in a design interview.
874
+ - **Runners:** a member's always-on Loom daemon that takes goals from the team
875
+ hub. Pair it with `loom runner pair` / `join` (a device of the same member,
876
+ revocable with key rotation); keep it up with `loom runner install` or
877
+ `Dockerfile.runner`.
878
+ - **Jobs on the hub:** start / continue / fix / return / land, with atomic claims,
879
+ heartbeats carrying a progress snapshot, and stale reclaim (MemoryHub, `loom
880
+ hub`, SQL `0007_runners.sql`).
881
+ - **Move a running goal** to a runner at a safe point (branches pushed to
882
+ `refs/loom/run/<id>/*`, the orchestrator resumes there) and **bring it back**;
883
+ Land reaches goals that live on a runner.
884
+ - **Trust tier:** a fresh clone (or container) per goal, a scrubbed environment,
885
+ `runners.permissions` as the ceiling, shared runners only when
886
+ `runners.shared` allows, a fine-grained token checked by `loom runner doctor`.
887
+ - **Away-from-keyboard CI fixes:** the owner's runner takes a goal that needs
888
+ someone once the owner has been offline 15 minutes.
889
+ - **Deploys and release notes:** deployment results in the feed, a phone alert
890
+ when a failed deploy contains your goal, `loom team release-notes --since`.
891
+ - **Phone:** tapping an alert opens its project and goal.
892
+
893
+ ### Loom Teams, Phase 4: land safely
894
+
895
+ - **15 more design decisions** (D52–D66), settled in a design interview.
896
+ - **Checks come back to the owner:** the owner's daemon polls its goal PRs every
897
+ 30s (`gh pr checks --required`). A failing check is rerun once; a pass on rerun
898
+ is labelled `loom:flaky`. A real failure's log tail (fenced as untrusted) reopens
899
+ the goal, and the fix is pushed to the same PR. At most 2 attempts, then the
900
+ goal needs a human and the phone is alerted.
901
+ - **Cross-vendor review:** a different-vendor agent reviews each goal PR on open
902
+ and after each fix (max 3), posts a COMMENT review and a `loom/review` status;
903
+ only high findings fail it, and they share the fix budget. Owners can override
904
+ with a reason.
905
+ - **Land** (`loom land`, a button on desktop and phone): fresh main merged in,
906
+ `landing.fastTest` from `loom.team.json`, push, `gh pr merge --auto --squash`.
907
+ Conflicts get one agent attempt; hard-zone conflicts go to a human.
908
+ - **Stacks** (opt-in, `delivery.stack: "auto"`): big goals become 2–4 PRs cut
909
+ along the integration branch's merge commits, landed bottom-up.
910
+ - **Adopt:** a teammate takes a stuck goal whose owner is away, fixes it on the
911
+ owner's branch, and hands it back; the owner's daemon backs off meanwhile.
912
+ - **Budgets:** per-goal cap (pauses the goal) and per-member daily cap (no new
913
+ goals); cost rollups per member/day, per goal and per landed PR.
914
+ - **Doctor:** `loom team doctor` reports merge-queue traps and opens a PR adding
915
+ `merge_group:` to workflows. It never changes settings.
916
+ - **Hosted hub:** `SupabaseHubClient` over RPC and Realtime, GitHub sign-in via
917
+ Supabase (loopback), `loom team signin` defaults to hosted; SQL `0005`
918
+ (`extend_lease`, `team_member_list`) and `0006` (landing feed events).
919
+
920
+ ### Loom Teams, Phase 3: one brain
921
+
922
+ - **12 more design decisions** (D40–D51), settled in a design interview.
923
+ - **Team memories:** durable memories from a shared project are published to the
924
+ hub sealed under the team key, with an HMAC of the normalized text. The hub
925
+ merges exact twins as confirmations without reading them (MemoryHub, `loom hub`
926
+ and SQL `0004_team_memories.sql`, tested on Postgres).
927
+ - **Who can change what:** only a memory's author edits or forgets it; a teammate
928
+ records a correction that supersedes it. Resolving keeps the loser, linked to
929
+ the winner, which inherits its confirmations.
930
+ - **Tiered briefings:** canon > confirmed by 2+ > your own > a teammate's
931
+ proposal, each line labelled. Failures and facts age out of briefings after ~90
932
+ days unless re-confirmed.
933
+ - **Untrusted memories:** a turn that read the web, GitHub issue/PR text or a
934
+ fetched URL marks what it taught as untrusted. Untrusted memories stay personal
935
+ until you trust them.
936
+ - **Canon in `AGENTS.md`:** a Loom-managed section with per-line markers; lines
937
+ added by hand count too. Promotion goes through one rolling `loom/canon` PR,
938
+ which also adds `@AGENTS.md` to `CLAUDE.md`. The native-memory import skips the
939
+ section, so canon never loops back in.
940
+ - **Live team context** in worker and handoff briefings, up to 1.5k characters:
941
+ - teammates' leases on the same paths;
942
+ - open PRs that change them (PR feed events now carry changed paths);
943
+ - failing checks;
944
+ - predicted conflicts.
945
+ - **Inbox:** contradictions, near-duplicates, corrections, untrusted memories and
946
+ promotion candidates. REST `/api/projects/:id/team/brain[/:action]` and
947
+ `loom team brain`.
948
+
949
+ ### Loom Teams, Phase 2: stop colliding
950
+
951
+ - **12 more design decisions** (D28–D39), settled in a design interview.
952
+ - **Leases:**
953
+ - scopes are expanded to real files plus directory prefixes, and hard zones come
954
+ from `loom.team.json`;
955
+ - hub claim, extend, renew, landing and release, with atomic hard-zone
956
+ arbitration, in both MemoryHub and SQL (tested on Postgres).
957
+ - **Orchestra holds** stop a task from starting:
958
+ - **decide:** the task overlaps a teammate's lease and needs an `overlap`
959
+ decision;
960
+ - **wait:** it waits for another goal's PR to merge, then rebases onto main;
961
+ - **zone:** it queues behind a held hard zone;
962
+ - **capacity:** the team is at its agent limit;
963
+ - "Stop waiting" releases a wait by hand.
964
+ - **Drift:** when a worker edits outside its declared touches, the lease widens and
965
+ the team is told. Drift into someone else's hard zone pauses the worker.
966
+ - **WIP refs** (`refs/loom/wip/<member>/<run>`) plus `git merge-tree` predict
967
+ conflicts. Both owners and both orchestrators hear about them.
968
+ - **Leases are released when the goal lands.** "Landing" means a merged PR, a
969
+ delivered push, or an applied run.
970
+ - **Team policy enforced:** permission ceiling (`bypassRequiresPlan`), agent
971
+ allowlist, protected-branch delivery (forces a PR), and per-member and
972
+ team-wide concurrency caps.
973
+ - **Fixes:**
974
+ - an orchestrator replying with no actions while nothing was running looped
975
+ until the round limit, and now waits for a human;
976
+ - an abort during a run's final wrap-up was overwritten by "completed";
977
+ - a member's own `gh` poll reporting their PR merged was ignored.
978
+
979
+ ### Loom Teams, Phase 1: see each other
980
+
981
+ - **The design is settled:** 27 decisions from a design interview, recorded in
982
+ docs/teams-architecture.md §1a.
983
+ - **Team crypto:**
984
+ - an XChaCha20-Poly1305 team key;
985
+ - an X25519 sealed box for key envelopes;
986
+ - Ed25519 signatures on everything a daemon publishes;
987
+ - the invite link carries the key in its `#fragment`.
988
+ - **The hub:**
989
+ - the `HubClient` protocol, with `MemoryHub` as the reference rules;
990
+ - `loom hub`, a self-hosted hub over HTTP + WebSocket;
991
+ - the hosted hub's SQL (RLS plus rule functions), tested against a real Postgres.
992
+ - **Team Link in the daemon:**
993
+ - sign-in, create, invite, join and leave;
994
+ - removal rotates the key forward;
995
+ - opt-in project sharing, with auto-match on the git remote;
996
+ - heartbeats carry intent only;
997
+ - a goal/plan/PR feed, with `gh` polling when there is no GitHub App.
998
+ - **Worker commits carry `Loom-Goal`, `Loom-Task`, `Loom-Agent` and `Loom-Member`
999
+ trailers.**
1000
+ - **The orchestra protocol gains `touches`** (declared file globs per task).
1001
+ - **Fix:** a removed member's daemon now hears its own removal. It was cut off
1002
+ before the announcement.
1003
+
1004
+ ### Permissions, plan mode, git delivery, fleet, prompts
1005
+
1006
+ - **Permission modes per agent: bypass, auto, always ask.**
1007
+ - Each is mapped onto each CLI's own flags, and every cell was verified against
1008
+ the real CLI (`scripts/verify-permissions.mjs`).
1009
+ - Always ask on Claude Code routes each tool use to a real approval in Loom,
1010
+ through a built-in MCP permission-prompt server. Verified with the real CLI
1011
+ (`scripts/verify-approvals.mjs`).
1012
+ - Two cells measured broken are shown as unavailable instead of lying: OpenCode
1013
+ "ask", and Antigravity "auto" (which writes to agy's scratch folder).
1014
+ - **Plan mode.**
1015
+ - Chat turns write a markdown plan instead of code.
1016
+ - Orchestras commit `plans/<run>/PLAN.md` plus a spec per task before workers
1017
+ start, and write results back at the end.
1018
+ - **Git delivery policy: none, commit, push, or PR.** Covers chat turns and finished
1019
+ orchestras. PR mode pushes the run's branch and opens a PR with `gh`.
1020
+ - **Fleet:** `GET /api/activity` and a Fleet view of every agent's thread, task and
1021
+ last step.
1022
+ - **Prompt manager:** saved and pinned prompts, plus automatic sent-prompt history
1023
+ (`/api/prompts`).
1024
+ - **Teams:** researched architecture in docs/teams-architecture.md.
1025
+
1026
+ ### Orchestra: one orchestrator, many parallel workers
1027
+
1028
+ - **`loom orchestrate "<goal>"`**, plus Orchestrate mode in the app.
1029
+ - Any agent can orchestrate: Claude Code, Codex, Antigravity, Grok or OpenCode.
1030
+ It plans the goal into a task graph.
1031
+ - Worker agents run every ready task at once, mixed kinds or several of the same
1032
+ kind. Each task gets its own thread and git worktree.
1033
+ - Finished work merges into `loom/orchestra/<run>/main`, and the orchestrator
1034
+ reviews, follows up, or finishes.
1035
+ - `orchestra:apply` merges the run into your branch. Nothing touches it before
1036
+ that.
1037
+ - Verified against the real CLIs:
1038
+ - Claude orchestrating Codex and Antigravity (278 s);
1039
+ - Codex orchestrating Grok, OpenCode and Claude Code (82 s, $0.31).
1040
+ - Both delivered working code with passing tests
1041
+ (`scripts/verify-orchestra.mjs`).
1042
+ - Design credit: Agent Orchestrator (Apache-2.0). See THIRD_PARTY_NOTICES.md.
1043
+
1044
+ ### Loom Cloud: reach your agents from any network
1045
+
1046
+ - A Supabase Realtime relay, end-to-end encrypted (XChaCha20-Poly1305). The key
1047
+ exists only in the pairing QR's URL fragment, so Supabase relays ciphertext.
1048
+ - Relayed requests run against the daemon with the phone's own token. The admin
1049
+ bootstrap is refused over the relay.
1050
+ - New commands: `loom cloud enable|disable|rotate`. Setup guide: docs/cloud.md.
1051
+ - Connection patterns credited to T3 Code (MIT).
1052
+
1053
+ ### Fixes found by running the real agents
1054
+
1055
+ - A worker's `.loom/` state made `git add` fail whenever the project gitignored
1056
+ `.loom/`. That failed every real Codex task.
1057
+ - A project reached through a symlink (every macOS temp dir) registered twice, so
1058
+ two runtimes ran over one `.loom/`.
1059
+ - OpenCode's default model is refused headless ("Model is unavailable"). With no
1060
+ model pinned, the adapter now picks one the server can actually run.
1061
+ - `test/git.test.ts` assumed the default branch is `main`; CI runners use `master`.
1062
+
1063
+
10
1064
  ### Hardening (production-readiness pass)
11
1065
 
12
1066
  - **Closed a DNS-rebinding path to the admin token.** `GET /api/bootstrap` handed