toolroll 0.5.0

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 (626) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1113 -0
  3. package/THIRD_PARTY_NOTICES.md +449 -0
  4. package/dist/accent-colors.d.ts +48 -0
  5. package/dist/accent-colors.js +122 -0
  6. package/dist/action-ledger.d.ts +26 -0
  7. package/dist/action-ledger.js +75 -0
  8. package/dist/agent-fence.d.ts +42 -0
  9. package/dist/agent-fence.js +183 -0
  10. package/dist/agentconfig.d.ts +216 -0
  11. package/dist/agentconfig.js +454 -0
  12. package/dist/api-tokens.d.ts +16 -0
  13. package/dist/api-tokens.js +27 -0
  14. package/dist/approval-policy.d.ts +69 -0
  15. package/dist/approval-policy.js +137 -0
  16. package/dist/approval-rules-ui.d.ts +25 -0
  17. package/dist/approval-rules-ui.js +39 -0
  18. package/dist/assignment-adapters.d.ts +180 -0
  19. package/dist/assignment-adapters.js +239 -0
  20. package/dist/assignment-brief.d.ts +71 -0
  21. package/dist/assignment-brief.js +129 -0
  22. package/dist/assignment-delivery.d.ts +56 -0
  23. package/dist/assignment-delivery.js +160 -0
  24. package/dist/assignment-presentation.d.ts +26 -0
  25. package/dist/assignment-presentation.js +80 -0
  26. package/dist/assignment-status.d.ts +62 -0
  27. package/dist/assignment-status.js +152 -0
  28. package/dist/assignment-ui.d.ts +71 -0
  29. package/dist/assignment-ui.js +103 -0
  30. package/dist/assignment.d.ts +222 -0
  31. package/dist/assignment.js +399 -0
  32. package/dist/attest.d.ts +56 -0
  33. package/dist/attest.js +153 -0
  34. package/dist/backend.d.ts +97 -0
  35. package/dist/backend.js +166 -0
  36. package/dist/backup-ui.d.ts +22 -0
  37. package/dist/backup-ui.js +59 -0
  38. package/dist/backup.d.ts +84 -0
  39. package/dist/backup.js +421 -0
  40. package/dist/beads.d.ts +34 -0
  41. package/dist/beads.js +135 -0
  42. package/dist/bin.d.ts +2 -0
  43. package/dist/bin.js +22 -0
  44. package/dist/board.d.ts +150 -0
  45. package/dist/board.js +210 -0
  46. package/dist/boot-identity.d.ts +63 -0
  47. package/dist/boot-identity.js +99 -0
  48. package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
  49. package/dist/browser/workspace.css +4 -0
  50. package/dist/browser/workspace.js +225 -0
  51. package/dist/browser-crew.d.ts +11 -0
  52. package/dist/browser-crew.js +50 -0
  53. package/dist/browser-shell.d.ts +8 -0
  54. package/dist/browser-shell.js +60 -0
  55. package/dist/browser-workspace.d.ts +780 -0
  56. package/dist/browser-workspace.js +47 -0
  57. package/dist/budget-alerts.d.ts +19 -0
  58. package/dist/budget-alerts.js +46 -0
  59. package/dist/builder.d.ts +370 -0
  60. package/dist/builder.js +3262 -0
  61. package/dist/capscan.d.ts +35 -0
  62. package/dist/capscan.js +113 -0
  63. package/dist/chat-acceptance.d.ts +71 -0
  64. package/dist/chat-acceptance.js +120 -0
  65. package/dist/chat-actions.d.ts +265 -0
  66. package/dist/chat-actions.js +1273 -0
  67. package/dist/chat-channel.d.ts +109 -0
  68. package/dist/chat-channel.js +652 -0
  69. package/dist/chat-continuity.d.ts +32 -0
  70. package/dist/chat-continuity.js +317 -0
  71. package/dist/chat-controls.d.ts +113 -0
  72. package/dist/chat-controls.js +53 -0
  73. package/dist/chat-delivery-state.d.ts +159 -0
  74. package/dist/chat-delivery-state.js +309 -0
  75. package/dist/chat-delivery.d.ts +38 -0
  76. package/dist/chat-delivery.js +693 -0
  77. package/dist/chat-display.d.ts +1 -0
  78. package/dist/chat-display.js +18 -0
  79. package/dist/chat-evidence.d.ts +123 -0
  80. package/dist/chat-evidence.js +207 -0
  81. package/dist/chat-flow.d.ts +44 -0
  82. package/dist/chat-flow.js +215 -0
  83. package/dist/chat-inbox.d.ts +57 -0
  84. package/dist/chat-inbox.js +123 -0
  85. package/dist/chat-polish.d.ts +16 -0
  86. package/dist/chat-polish.js +135 -0
  87. package/dist/chat-review.d.ts +46 -0
  88. package/dist/chat-review.js +98 -0
  89. package/dist/chat-rooms.d.ts +123 -0
  90. package/dist/chat-rooms.js +216 -0
  91. package/dist/chat-task-actions.d.ts +44 -0
  92. package/dist/chat-task-actions.js +79 -0
  93. package/dist/check-progress.d.ts +51 -0
  94. package/dist/check-progress.js +290 -0
  95. package/dist/child-database.d.ts +12 -0
  96. package/dist/child-database.js +30 -0
  97. package/dist/claim.d.ts +688 -0
  98. package/dist/claim.js +1740 -0
  99. package/dist/cli.d.ts +137 -0
  100. package/dist/cli.js +1461 -0
  101. package/dist/codex-limits.d.ts +15 -0
  102. package/dist/codex-limits.js +145 -0
  103. package/dist/coding-context.d.ts +55 -0
  104. package/dist/coding-context.js +92 -0
  105. package/dist/coding-handoff.d.ts +57 -0
  106. package/dist/coding-handoff.js +277 -0
  107. package/dist/coding-provider.d.ts +72 -0
  108. package/dist/coding-provider.js +424 -0
  109. package/dist/coding-shipping-ui.d.ts +4 -0
  110. package/dist/coding-shipping-ui.js +12 -0
  111. package/dist/coding-types.d.ts +62 -0
  112. package/dist/coding-types.js +1 -0
  113. package/dist/coding-ui.d.ts +17 -0
  114. package/dist/coding-ui.js +364 -0
  115. package/dist/coding-update.d.ts +15 -0
  116. package/dist/coding-update.js +149 -0
  117. package/dist/coding-workspace.d.ts +124 -0
  118. package/dist/coding-workspace.js +768 -0
  119. package/dist/container-state.d.ts +5 -0
  120. package/dist/container-state.js +62 -0
  121. package/dist/containment.d.ts +197 -0
  122. package/dist/containment.js +559 -0
  123. package/dist/contest.d.ts +318 -0
  124. package/dist/contest.js +753 -0
  125. package/dist/control-setup.d.ts +35 -0
  126. package/dist/control-setup.js +40 -0
  127. package/dist/control-ui.d.ts +29 -0
  128. package/dist/control-ui.js +53 -0
  129. package/dist/controller-service.d.ts +1 -0
  130. package/dist/controller-service.js +19 -0
  131. package/dist/controller-supervisor.d.ts +30 -0
  132. package/dist/controller-supervisor.js +104 -0
  133. package/dist/converse.d.ts +304 -0
  134. package/dist/converse.js +849 -0
  135. package/dist/coordinator-proposals.d.ts +29 -0
  136. package/dist/coordinator-proposals.js +137 -0
  137. package/dist/coordinator.d.ts +186 -0
  138. package/dist/coordinator.js +447 -0
  139. package/dist/credentials-ui.d.ts +25 -0
  140. package/dist/credentials-ui.js +48 -0
  141. package/dist/daemon.d.ts +209 -0
  142. package/dist/daemon.js +604 -0
  143. package/dist/decision.d.ts +120 -0
  144. package/dist/decision.js +388 -0
  145. package/dist/demo.d.ts +55 -0
  146. package/dist/demo.js +992 -0
  147. package/dist/desktop-access.d.ts +28 -0
  148. package/dist/desktop-access.js +88 -0
  149. package/dist/desktop-bundle.d.ts +16 -0
  150. package/dist/desktop-bundle.js +74 -0
  151. package/dist/desktop-host.d.ts +54 -0
  152. package/dist/desktop-host.js +508 -0
  153. package/dist/desktop-update-gate.d.ts +12 -0
  154. package/dist/desktop-update-gate.js +91 -0
  155. package/dist/desktop-update-recovery.d.ts +14 -0
  156. package/dist/desktop-update-recovery.js +243 -0
  157. package/dist/desktop-update.d.ts +110 -0
  158. package/dist/desktop-update.js +740 -0
  159. package/dist/discord-api.d.ts +20 -0
  160. package/dist/discord-api.js +138 -0
  161. package/dist/discord-chat.d.ts +16 -0
  162. package/dist/discord-chat.js +381 -0
  163. package/dist/discord-settings.d.ts +7 -0
  164. package/dist/discord-settings.js +75 -0
  165. package/dist/discord.d.ts +10 -0
  166. package/dist/discord.js +169 -0
  167. package/dist/discover.d.ts +75 -0
  168. package/dist/discover.js +150 -0
  169. package/dist/dispatch.d.ts +100 -0
  170. package/dist/dispatch.js +311 -0
  171. package/dist/dispose.d.ts +161 -0
  172. package/dist/dispose.js +803 -0
  173. package/dist/email-settings.d.ts +34 -0
  174. package/dist/email-settings.js +50 -0
  175. package/dist/envelope.d.ts +47 -0
  176. package/dist/envelope.js +105 -0
  177. package/dist/evidence-pack.d.ts +185 -0
  178. package/dist/evidence-pack.js +258 -0
  179. package/dist/evidence.d.ts +345 -0
  180. package/dist/evidence.js +782 -0
  181. package/dist/exec.d.ts +285 -0
  182. package/dist/exec.js +1841 -0
  183. package/dist/exhaustion.d.ts +85 -0
  184. package/dist/exhaustion.js +141 -0
  185. package/dist/export-ui.d.ts +4 -0
  186. package/dist/export-ui.js +17 -0
  187. package/dist/export.d.ts +48 -0
  188. package/dist/export.js +305 -0
  189. package/dist/flow-actions.d.ts +77 -0
  190. package/dist/flow-actions.js +203 -0
  191. package/dist/flow-code.d.ts +50 -0
  192. package/dist/flow-code.js +159 -0
  193. package/dist/flow-draft.d.ts +38 -0
  194. package/dist/flow-draft.js +80 -0
  195. package/dist/flow-engine.d.ts +66 -0
  196. package/dist/flow-engine.js +416 -0
  197. package/dist/flow-insights.d.ts +95 -0
  198. package/dist/flow-insights.js +149 -0
  199. package/dist/flow-live.d.ts +24 -0
  200. package/dist/flow-live.js +150 -0
  201. package/dist/flow-people.d.ts +24 -0
  202. package/dist/flow-people.js +91 -0
  203. package/dist/flow-replies.d.ts +48 -0
  204. package/dist/flow-replies.js +113 -0
  205. package/dist/flow-scripts.d.ts +38 -0
  206. package/dist/flow-scripts.js +73 -0
  207. package/dist/flow-secrets.d.ts +13 -0
  208. package/dist/flow-secrets.js +45 -0
  209. package/dist/flow-sort.d.ts +82 -0
  210. package/dist/flow-sort.js +153 -0
  211. package/dist/flow-steps.d.ts +40 -0
  212. package/dist/flow-steps.js +408 -0
  213. package/dist/flow-triggers.d.ts +244 -0
  214. package/dist/flow-triggers.js +959 -0
  215. package/dist/flows-ui.d.ts +20 -0
  216. package/dist/flows-ui.js +175 -0
  217. package/dist/flows.d.ts +229 -0
  218. package/dist/flows.js +968 -0
  219. package/dist/fonts.d.ts +19 -0
  220. package/dist/fonts.js +19 -0
  221. package/dist/gaps.d.ts +35 -0
  222. package/dist/gaps.js +101 -0
  223. package/dist/gate-failure.d.ts +40 -0
  224. package/dist/gate-failure.js +66 -0
  225. package/dist/git.d.ts +54 -0
  226. package/dist/git.js +94 -0
  227. package/dist/google-mail.d.ts +58 -0
  228. package/dist/google-mail.js +151 -0
  229. package/dist/grant.d.ts +136 -0
  230. package/dist/grant.js +238 -0
  231. package/dist/graph.d.ts +164 -0
  232. package/dist/graph.js +383 -0
  233. package/dist/guides.d.ts +22 -0
  234. package/dist/guides.js +363 -0
  235. package/dist/held.d.ts +150 -0
  236. package/dist/held.js +799 -0
  237. package/dist/invoke.d.ts +112 -0
  238. package/dist/invoke.js +780 -0
  239. package/dist/issues.d.ts +41 -0
  240. package/dist/issues.js +131 -0
  241. package/dist/job-object-helper.ps1 +252 -0
  242. package/dist/jsonl-discriminants.d.ts +11 -0
  243. package/dist/jsonl-discriminants.js +93 -0
  244. package/dist/keys.d.ts +104 -0
  245. package/dist/keys.js +229 -0
  246. package/dist/kits-ui.d.ts +17 -0
  247. package/dist/kits-ui.js +46 -0
  248. package/dist/kits.d.ts +86 -0
  249. package/dist/kits.js +215 -0
  250. package/dist/knowledge-cli.d.ts +101 -0
  251. package/dist/knowledge-cli.js +92 -0
  252. package/dist/knowledge-ui.d.ts +24 -0
  253. package/dist/knowledge-ui.js +40 -0
  254. package/dist/lead-context.d.ts +8 -0
  255. package/dist/lead-context.js +56 -0
  256. package/dist/lead-follow.d.ts +22 -0
  257. package/dist/lead-follow.js +167 -0
  258. package/dist/lead-status.d.ts +75 -0
  259. package/dist/lead-status.js +285 -0
  260. package/dist/ledger-chain.d.ts +46 -0
  261. package/dist/ledger-chain.js +187 -0
  262. package/dist/ledger-csv.d.ts +4 -0
  263. package/dist/ledger-csv.js +11 -0
  264. package/dist/ledger-view.d.ts +24 -0
  265. package/dist/ledger-view.js +58 -0
  266. package/dist/limits-ui.d.ts +26 -0
  267. package/dist/limits-ui.js +67 -0
  268. package/dist/link.d.ts +72 -0
  269. package/dist/link.js +217 -0
  270. package/dist/live.d.ts +96 -0
  271. package/dist/live.js +366 -0
  272. package/dist/liveness.d.ts +30 -0
  273. package/dist/liveness.js +42 -0
  274. package/dist/log.d.ts +7 -0
  275. package/dist/log.js +25 -0
  276. package/dist/mailbox.d.ts +57 -0
  277. package/dist/mailbox.js +150 -0
  278. package/dist/maintenance.d.ts +11 -0
  279. package/dist/maintenance.js +35 -0
  280. package/dist/mate-cli.d.ts +52 -0
  281. package/dist/mate-cli.js +345 -0
  282. package/dist/mate-contract.d.ts +10 -0
  283. package/dist/mate-contract.js +30 -0
  284. package/dist/mate-doors.d.ts +69 -0
  285. package/dist/mate-doors.js +548 -0
  286. package/dist/mate-progress.d.ts +29 -0
  287. package/dist/mate-progress.js +121 -0
  288. package/dist/mate-tools.d.ts +94 -0
  289. package/dist/mate-tools.js +1878 -0
  290. package/dist/mate.d.ts +92 -0
  291. package/dist/mate.js +435 -0
  292. package/dist/mcp-connect.d.ts +103 -0
  293. package/dist/mcp-connect.js +252 -0
  294. package/dist/mcp.d.ts +27 -0
  295. package/dist/mcp.js +651 -0
  296. package/dist/memory-cli.d.ts +466 -0
  297. package/dist/memory-cli.js +111 -0
  298. package/dist/memory-pass.d.ts +160 -0
  299. package/dist/memory-pass.js +409 -0
  300. package/dist/metrics.d.ts +3 -0
  301. package/dist/metrics.js +56 -0
  302. package/dist/mobile-viewport.d.ts +3 -0
  303. package/dist/mobile-viewport.js +37 -0
  304. package/dist/model-catalog.d.ts +118 -0
  305. package/dist/model-catalog.js +376 -0
  306. package/dist/models-cli.d.ts +102 -0
  307. package/dist/models-cli.js +66 -0
  308. package/dist/models-ui.d.ts +34 -0
  309. package/dist/models-ui.js +68 -0
  310. package/dist/modes.d.ts +80 -0
  311. package/dist/modes.js +182 -0
  312. package/dist/monitoring-settings.d.ts +44 -0
  313. package/dist/monitoring-settings.js +173 -0
  314. package/dist/monitoring-ui.d.ts +20 -0
  315. package/dist/monitoring-ui.js +51 -0
  316. package/dist/monitoring.d.ts +34 -0
  317. package/dist/monitoring.js +221 -0
  318. package/dist/names.d.ts +67 -0
  319. package/dist/names.js +102 -0
  320. package/dist/observations.d.ts +40 -0
  321. package/dist/observations.js +211 -0
  322. package/dist/oidc.d.ts +71 -0
  323. package/dist/oidc.js +182 -0
  324. package/dist/onboard.d.ts +108 -0
  325. package/dist/onboard.js +325 -0
  326. package/dist/openrouter-models.d.ts +30 -0
  327. package/dist/openrouter-models.js +120 -0
  328. package/dist/operate.d.ts +118 -0
  329. package/dist/operate.js +11321 -0
  330. package/dist/peek-cli.d.ts +97 -0
  331. package/dist/peek-cli.js +215 -0
  332. package/dist/peek.d.ts +134 -0
  333. package/dist/peek.js +578 -0
  334. package/dist/phase-routing.d.ts +307 -0
  335. package/dist/phase-routing.js +658 -0
  336. package/dist/plan-auto.d.ts +14 -0
  337. package/dist/plan-auto.js +92 -0
  338. package/dist/plan.d.ts +186 -0
  339. package/dist/plan.js +401 -0
  340. package/dist/planner-source.d.ts +251 -0
  341. package/dist/planner-source.js +460 -0
  342. package/dist/planner.d.ts +75 -0
  343. package/dist/planner.js +992 -0
  344. package/dist/policy-ui.d.ts +20 -0
  345. package/dist/policy-ui.js +41 -0
  346. package/dist/policy.d.ts +111 -0
  347. package/dist/policy.js +231 -0
  348. package/dist/prepared-evidence.d.ts +16 -0
  349. package/dist/prepared-evidence.js +96 -0
  350. package/dist/pricing.d.ts +45 -0
  351. package/dist/pricing.js +77 -0
  352. package/dist/principal.d.ts +42 -0
  353. package/dist/principal.js +82 -0
  354. package/dist/probe.d.ts +46 -0
  355. package/dist/probe.js +79 -0
  356. package/dist/process-custody.d.ts +17 -0
  357. package/dist/process-custody.js +91 -0
  358. package/dist/process-liveness.d.ts +10 -0
  359. package/dist/process-liveness.js +81 -0
  360. package/dist/process-recovery-anchor.d.ts +75 -0
  361. package/dist/process-recovery-anchor.js +188 -0
  362. package/dist/process-recovery-coalition.d.ts +25 -0
  363. package/dist/process-recovery-coalition.js +105 -0
  364. package/dist/process-recovery-eligibility.d.ts +178 -0
  365. package/dist/process-recovery-eligibility.js +170 -0
  366. package/dist/process-recovery-native.d.ts +172 -0
  367. package/dist/process-recovery-native.js +592 -0
  368. package/dist/process-recovery-provenance.d.ts +163 -0
  369. package/dist/process-recovery-provenance.js +292 -0
  370. package/dist/process-recovery-services.d.ts +56 -0
  371. package/dist/process-recovery-services.js +191 -0
  372. package/dist/process-recovery-settlement.d.ts +32 -0
  373. package/dist/process-recovery-settlement.js +132 -0
  374. package/dist/process-recovery.d.ts +41 -0
  375. package/dist/process-recovery.js +91 -0
  376. package/dist/process-tree.d.ts +41 -0
  377. package/dist/process-tree.js +264 -0
  378. package/dist/project-access.d.ts +14 -0
  379. package/dist/project-access.js +34 -0
  380. package/dist/project-cli.d.ts +18 -0
  381. package/dist/project-cli.js +104 -0
  382. package/dist/project-delete-ui.d.ts +22 -0
  383. package/dist/project-delete-ui.js +48 -0
  384. package/dist/project-delete.d.ts +55 -0
  385. package/dist/project-delete.js +413 -0
  386. package/dist/project-knowledge.d.ts +111 -0
  387. package/dist/project-knowledge.js +241 -0
  388. package/dist/project-learning.d.ts +100 -0
  389. package/dist/project-learning.js +438 -0
  390. package/dist/project-memory.d.ts +81 -0
  391. package/dist/project-memory.js +264 -0
  392. package/dist/project-skills.d.ts +152 -0
  393. package/dist/project-skills.js +660 -0
  394. package/dist/project-tools.d.ts +219 -0
  395. package/dist/project-tools.js +796 -0
  396. package/dist/project.d.ts +61 -0
  397. package/dist/project.js +125 -0
  398. package/dist/prompt.d.ts +22 -0
  399. package/dist/prompt.js +72 -0
  400. package/dist/proof.d.ts +513 -0
  401. package/dist/proof.js +1140 -0
  402. package/dist/proposal.d.ts +82 -0
  403. package/dist/proposal.js +210 -0
  404. package/dist/provider-connection.d.ts +22 -0
  405. package/dist/provider-connection.js +98 -0
  406. package/dist/provider-limits.d.ts +35 -0
  407. package/dist/provider-limits.js +95 -0
  408. package/dist/provider.d.ts +279 -0
  409. package/dist/provider.js +935 -0
  410. package/dist/publish.d.ts +107 -0
  411. package/dist/publish.js +650 -0
  412. package/dist/pulls.d.ts +118 -0
  413. package/dist/pulls.js +240 -0
  414. package/dist/push.d.ts +95 -0
  415. package/dist/push.js +353 -0
  416. package/dist/quality.d.ts +8 -0
  417. package/dist/quality.js +6 -0
  418. package/dist/recipe-ui.d.ts +18 -0
  419. package/dist/recipe-ui.js +152 -0
  420. package/dist/recipes.d.ts +81 -0
  421. package/dist/recipes.js +332 -0
  422. package/dist/remote.d.ts +67 -0
  423. package/dist/remote.js +122 -0
  424. package/dist/render.d.ts +64 -0
  425. package/dist/render.js +587 -0
  426. package/dist/report-summary.d.ts +13 -0
  427. package/dist/report-summary.js +15 -0
  428. package/dist/repos.d.ts +65 -0
  429. package/dist/repos.js +277 -0
  430. package/dist/repository-context-ui.d.ts +2 -0
  431. package/dist/repository-context-ui.js +10 -0
  432. package/dist/repository-context.d.ts +67 -0
  433. package/dist/repository-context.js +376 -0
  434. package/dist/restart-certification.d.ts +134 -0
  435. package/dist/restart-certification.js +226 -0
  436. package/dist/result-actions.d.ts +28 -0
  437. package/dist/result-actions.js +270 -0
  438. package/dist/result-completion.d.ts +18 -0
  439. package/dist/result-completion.js +66 -0
  440. package/dist/result-review.d.ts +213 -0
  441. package/dist/result-review.js +430 -0
  442. package/dist/retention-ui.d.ts +12 -0
  443. package/dist/retention-ui.js +39 -0
  444. package/dist/retention.d.ts +72 -0
  445. package/dist/retention.js +288 -0
  446. package/dist/review-context.d.ts +243 -0
  447. package/dist/review-context.js +1043 -0
  448. package/dist/review-evidence.d.ts +33 -0
  449. package/dist/review-evidence.js +56 -0
  450. package/dist/reviewer.d.ts +97 -0
  451. package/dist/reviewer.js +202 -0
  452. package/dist/routine.d.ts +228 -0
  453. package/dist/routine.js +764 -0
  454. package/dist/runner.d.ts +266 -0
  455. package/dist/runner.js +399 -0
  456. package/dist/scan.d.ts +32 -0
  457. package/dist/scan.js +92 -0
  458. package/dist/scope.d.ts +695 -0
  459. package/dist/scope.js +1176 -0
  460. package/dist/scout-report.d.ts +42 -0
  461. package/dist/scout-report.js +108 -0
  462. package/dist/scout.d.ts +69 -0
  463. package/dist/scout.js +351 -0
  464. package/dist/serve.d.ts +313 -0
  465. package/dist/serve.js +21776 -0
  466. package/dist/session-brief.d.ts +8 -0
  467. package/dist/session-brief.js +24 -0
  468. package/dist/session-cli.d.ts +13 -0
  469. package/dist/session-cli.js +284 -0
  470. package/dist/session-contract.d.ts +183 -0
  471. package/dist/session-contract.js +122 -0
  472. package/dist/session-http.d.ts +19 -0
  473. package/dist/session-http.js +154 -0
  474. package/dist/session-server.d.ts +12 -0
  475. package/dist/session-server.js +37 -0
  476. package/dist/session-service.d.ts +22 -0
  477. package/dist/session-service.js +157 -0
  478. package/dist/setup-guide.d.ts +39 -0
  479. package/dist/setup-guide.js +93 -0
  480. package/dist/sign-in-guard.d.ts +45 -0
  481. package/dist/sign-in-guard.js +74 -0
  482. package/dist/skills-ui.d.ts +11 -0
  483. package/dist/skills-ui.js +58 -0
  484. package/dist/skills.d.ts +97 -0
  485. package/dist/skills.js +276 -0
  486. package/dist/slack-api.d.ts +55 -0
  487. package/dist/slack-api.js +229 -0
  488. package/dist/slack-chat.d.ts +28 -0
  489. package/dist/slack-chat.js +413 -0
  490. package/dist/slack-settings.d.ts +7 -0
  491. package/dist/slack-settings.js +75 -0
  492. package/dist/slack-state.d.ts +13 -0
  493. package/dist/slack-state.js +9 -0
  494. package/dist/slack.d.ts +13 -0
  495. package/dist/slack.js +167 -0
  496. package/dist/spend-ui.d.ts +28 -0
  497. package/dist/spend-ui.js +95 -0
  498. package/dist/spend.d.ts +142 -0
  499. package/dist/spend.js +313 -0
  500. package/dist/sqlite-runtime.d.ts +3 -0
  501. package/dist/sqlite-runtime.js +6 -0
  502. package/dist/sso-settings.d.ts +33 -0
  503. package/dist/sso-settings.js +103 -0
  504. package/dist/sso-ui.d.ts +22 -0
  505. package/dist/sso-ui.js +39 -0
  506. package/dist/storage.d.ts +15 -0
  507. package/dist/storage.js +84 -0
  508. package/dist/store.d.ts +7754 -0
  509. package/dist/store.js +23279 -0
  510. package/dist/structured-output.d.ts +58 -0
  511. package/dist/structured-output.js +103 -0
  512. package/dist/style-asset.d.ts +7 -0
  513. package/dist/style-asset.js +41 -0
  514. package/dist/subscription-chat.d.ts +46 -0
  515. package/dist/subscription-chat.js +275 -0
  516. package/dist/summary.d.ts +33 -0
  517. package/dist/summary.js +71 -0
  518. package/dist/supervisor.mjs +297 -0
  519. package/dist/surface.d.ts +63 -0
  520. package/dist/surface.js +352 -0
  521. package/dist/sync.d.ts +94 -0
  522. package/dist/sync.js +279 -0
  523. package/dist/task-composer.d.ts +13 -0
  524. package/dist/task-composer.js +52 -0
  525. package/dist/task-control.d.ts +165 -0
  526. package/dist/task-control.js +214 -0
  527. package/dist/task-outcome-cli.d.ts +10 -0
  528. package/dist/task-outcome-cli.js +92 -0
  529. package/dist/task-text.d.ts +30 -0
  530. package/dist/task-text.js +41 -0
  531. package/dist/team-cli.d.ts +15 -0
  532. package/dist/team-cli.js +618 -0
  533. package/dist/team-contract.d.ts +92 -0
  534. package/dist/team-contract.js +1 -0
  535. package/dist/team-http.d.ts +17 -0
  536. package/dist/team-http.js +144 -0
  537. package/dist/team-leads.d.ts +81 -0
  538. package/dist/team-leads.js +565 -0
  539. package/dist/team-runtime.d.ts +27 -0
  540. package/dist/team-runtime.js +264 -0
  541. package/dist/team-ui.d.ts +3 -0
  542. package/dist/team-ui.js +9 -0
  543. package/dist/team-updates.d.ts +8 -0
  544. package/dist/team-updates.js +57 -0
  545. package/dist/teammate-admin.d.ts +53 -0
  546. package/dist/teammate-admin.js +111 -0
  547. package/dist/teammate-desk.d.ts +60 -0
  548. package/dist/teammate-desk.js +154 -0
  549. package/dist/teammate-memory.d.ts +64 -0
  550. package/dist/teammate-memory.js +196 -0
  551. package/dist/teammate-question.d.ts +59 -0
  552. package/dist/teammate-question.js +175 -0
  553. package/dist/teammate-tools.d.ts +108 -0
  554. package/dist/teammate-tools.js +271 -0
  555. package/dist/teammate-week.d.ts +68 -0
  556. package/dist/teammate-week.js +132 -0
  557. package/dist/teammate-work.d.ts +76 -0
  558. package/dist/teammate-work.js +280 -0
  559. package/dist/teammates-ui.d.ts +20 -0
  560. package/dist/teammates-ui.js +166 -0
  561. package/dist/teammates.d.ts +180 -0
  562. package/dist/teammates.js +253 -0
  563. package/dist/teams-api.d.ts +33 -0
  564. package/dist/teams-api.js +204 -0
  565. package/dist/teams-chat.d.ts +26 -0
  566. package/dist/teams-chat.js +215 -0
  567. package/dist/teams-settings.d.ts +12 -0
  568. package/dist/teams-settings.js +57 -0
  569. package/dist/teams.d.ts +21 -0
  570. package/dist/teams.js +124 -0
  571. package/dist/telegram-flow.d.ts +49 -0
  572. package/dist/telegram-flow.js +110 -0
  573. package/dist/telegram-mate.d.ts +137 -0
  574. package/dist/telegram-mate.js +707 -0
  575. package/dist/telegram-progress.d.ts +14 -0
  576. package/dist/telegram-progress.js +129 -0
  577. package/dist/telegram-settings.d.ts +9 -0
  578. package/dist/telegram-settings.js +36 -0
  579. package/dist/telegram-status.d.ts +75 -0
  580. package/dist/telegram-status.js +265 -0
  581. package/dist/telegram-team.d.ts +85 -0
  582. package/dist/telegram-team.js +359 -0
  583. package/dist/telegram.d.ts +230 -0
  584. package/dist/telegram.js +1931 -0
  585. package/dist/templates.d.ts +65 -0
  586. package/dist/templates.js +118 -0
  587. package/dist/tool-launcher.d.ts +1 -0
  588. package/dist/tool-launcher.js +101 -0
  589. package/dist/tools-ui.d.ts +30 -0
  590. package/dist/tools-ui.js +40 -0
  591. package/dist/transitions-recipes.d.ts +1 -0
  592. package/dist/transitions-recipes.js +203 -0
  593. package/dist/tree-proof.d.ts +34 -0
  594. package/dist/tree-proof.js +58 -0
  595. package/dist/verification-evidence.d.ts +44 -0
  596. package/dist/verification-evidence.js +238 -0
  597. package/dist/version.d.ts +2 -0
  598. package/dist/version.js +10 -0
  599. package/dist/webhooks.d.ts +91 -0
  600. package/dist/webhooks.js +283 -0
  601. package/dist/work-index.d.ts +68 -0
  602. package/dist/work-index.js +384 -0
  603. package/dist/work-summary.d.ts +57 -0
  604. package/dist/work-summary.js +116 -0
  605. package/dist/workspace-motion.d.ts +4 -0
  606. package/dist/workspace-motion.js +133 -0
  607. package/dist/workspace-revision.d.ts +19 -0
  608. package/dist/workspace-revision.js +92 -0
  609. package/dist/workspace-ui.d.ts +204 -0
  610. package/dist/workspace-ui.js +411 -0
  611. package/dist/worktree-notices.d.ts +13 -0
  612. package/dist/worktree-notices.js +17 -0
  613. package/dist/worktree.d.ts +249 -0
  614. package/dist/worktree.js +720 -0
  615. package/package.json +122 -0
  616. package/scripts/canary-assertions.mjs +42 -0
  617. package/scripts/crash-canary.mjs +253 -0
  618. package/scripts/fixtures/crash-process.mjs +74 -0
  619. package/scripts/fixtures/pilot-scenarios.mjs +85 -0
  620. package/scripts/fixtures/restart-service.mjs +27 -0
  621. package/scripts/launchd-certification.mjs +143 -0
  622. package/scripts/pilot.mjs +121 -0
  623. package/scripts/proof-preflight.mjs +140 -0
  624. package/scripts/provider-canary.mjs +379 -0
  625. package/scripts/recovery-canary.mjs +135 -0
  626. package/scripts/restart-certification.mjs +98 -0
@@ -0,0 +1,264 @@
1
+ /** Central shared-conversation execution. Queue delivery is independent from
2
+ * task completion; idle passes never call a model. */
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ import { deliverTeamUpdates, startTeamUpdates } from './team-updates.js';
5
+ import { workIndexPage } from './work-index.js';
6
+ import { TeamLeads } from './team-leads.js';
7
+ import { ceilingDigestOf, verifyApproverStanding } from './principal.js';
8
+ import { credentialKeyOf, isDirectChatProvider, priceForConfig, subscriptionCredentialKey, mateWorstCaseForPrice } from './converse.js';
9
+ import { runMateTurn } from './mate.js';
10
+ import { updateAdmissionPaused } from './desktop-update-gate.js';
11
+ const hash = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
12
+ const response = (ok, code, message) => ({ version: 1, ok, code, message });
13
+ const requestFor = (claim) => hash(['team', claim.conversationId, claim.messageId, claim.requestId]).slice(0, 32);
14
+ export function createTeamRuntime(options) {
15
+ const { store } = options, clock = options.clock ?? (() => new Date());
16
+ const domain = new TeamLeads(store, options.repos);
17
+ const runner = `team:${process.pid}:${randomUUID()}`;
18
+ const capacity = Math.max(1, Math.min(8, options.capacity ?? 4));
19
+ const active = new Set();
20
+ const waiting = new Map();
21
+ const pages = new Map();
22
+ let timer = null, closed = false, passing = false, lastDelivery = 0;
23
+ function authorization(actor, snapshot) {
24
+ const live = options.provider(), config = live?.config, conversation = snapshot.selected;
25
+ const empty = { enabled: false, provider: config?.provider ?? null, model: config?.model ?? null,
26
+ dailyTurns: config?.dailyTurns ?? 0, weeklyCeilingUsd: null, conversationCeilingUsd: null, termsDigest: '' };
27
+ if (!conversation)
28
+ return empty;
29
+ if (!live || !config)
30
+ return { ...empty, waitingReason: 'Choose a chat provider in Settings.' };
31
+ const direct = isDirectChatProvider(config.provider);
32
+ if (direct && (live.key === null || priceForConfig(config) === null))
33
+ return { ...empty, waitingReason: 'The configured chat connection is unavailable. Open Settings.' };
34
+ const credential = direct ? credentialKeyOf(config.provider, live.key) : subscriptionCredentialKey(config.provider);
35
+ const session = store.teamMateSession(actor.name, conversation.threadId);
36
+ const ceiling = direct ? (session ? session.ceilingMicrousd / 1_000_000 : Math.min(5, config.weeklyCeilingMicrousd / 1_000_000)) : null;
37
+ const termsDigest = hash({ version: 1, actor: actor.name, generation: actor.generation, conversation: conversation.id,
38
+ projects: conversation.projects, credential, provider: config.provider, model: config.model,
39
+ daily: config.dailyTurns, weekly: config.weeklyCeilingMicrousd, priceIn: config.priceInMicrousd, priceOut: config.priceOutMicrousd, ceiling });
40
+ const enabled = session !== null && session.approverGeneration === actor.generation && session.endedAt === null
41
+ && session.credentialKey === credential && session.ceilingDigest === ceilingDigestOf(conversation.projects) && session.termsDigest === termsDigest;
42
+ return { enabled, provider: config.provider, model: config.model, dailyTurns: config.dailyTurns,
43
+ weeklyCeilingUsd: direct ? config.weeklyCeilingMicrousd / 1_000_000 : null, conversationCeilingUsd: ceiling, termsDigest };
44
+ }
45
+ function admission(actor, id) {
46
+ const conversation = domain.access(actor, id, 'contributor').conversation;
47
+ const grant = authorization(actor, { selected: conversation }), live = options.provider();
48
+ const session = store.teamMateSession(actor.name, conversation.threadId);
49
+ const used = store.chatTurnsToday(actor.name, clock());
50
+ const weekly = session ? store.chatWeeklySpendMicrousd(session.credentialKey, clock()) : 0;
51
+ const latched = session && store.handle.prepare('SELECT 1 FROM chat_turn WHERE credential_key=? AND unknown_spend=1 AND acknowledged_at IS NULL LIMIT 1').get(session.credentialKey);
52
+ const legacyBusy = Boolean(store.handle.prepare("SELECT 1 FROM chat_turn WHERE approver=? AND mate_turn IS NULL AND state IN ('queued','running') LIMIT 1").get(actor.name));
53
+ const stamp = hash([grant.termsDigest, grant.enabled, session?.id, session?.spentMicrousd, used, weekly, Boolean(latched), legacyBusy]);
54
+ let reason = grant.waitingReason ?? (!grant.enabled ? 'Enable chat using the current provider and limits.' : null);
55
+ if (!reason && live && session) {
56
+ const price = priceForConfig(live.config), minimum = isDirectChatProvider(live.config.provider) && price ? mateWorstCaseForPrice(price, 0, { steps: 1 }) : 0;
57
+ if (latched)
58
+ reason = 'A previous chat cost is unconfirmed. Open Settings to inspect it.';
59
+ else if (used >= live.config.dailyTurns)
60
+ reason = 'The daily chat limit is reached. Queued messages are saved.';
61
+ else if (session.ceilingMicrousd - session.spentMicrousd < minimum)
62
+ reason = 'This conversation has used its chat allowance. Queued messages are saved.';
63
+ else if (live.config.weeklyCeilingMicrousd - weekly < minimum)
64
+ reason = 'The weekly chat limit is reached. Queued messages are saved.';
65
+ }
66
+ return { ok: reason === null, stamp, reason };
67
+ }
68
+ function snapshot(actor, conversationId, leadId) {
69
+ const view = domain.snapshot(actor, conversationId, leadId);
70
+ return decorate(actor, view);
71
+ }
72
+ function tasksFor(selected) {
73
+ const now = clock(), revision = options.workspaceRevision?.current();
74
+ // Callers proved current membership and complete scope before reaching
75
+ // this cache. Only identical lead/project/room-policy projections share it.
76
+ const key = hash([selected.leadId, selected.projects, selected.revision]);
77
+ const previous = pages.get(key);
78
+ if (revision && previous?.revision === revision && previous.expires > now.getTime())
79
+ return previous.page;
80
+ const page = workIndexPage(store, now, { principal: 'operator', repos: selected.projects }, { leadId: selected.leadId, limit: 40 });
81
+ if (revision && options.workspaceRevision) {
82
+ if (pages.size >= 64)
83
+ pages.delete(pages.keys().next().value);
84
+ pages.set(key, { revision, expires: options.workspaceRevision.expiresAt(now), page });
85
+ }
86
+ return page;
87
+ }
88
+ function decorate(actor, view) {
89
+ const selected = view.selected;
90
+ const grant = authorization(actor, view);
91
+ const waitingReason = selected && view.canSend && grant.enabled ? admission(actor, selected.id).reason : null;
92
+ return { ...view, chatAuthorization: { ...grant, ...(waitingReason ? { waitingReason } : {}) },
93
+ ...(selected ? { tasks: tasksFor(selected),
94
+ proposals: store.listMateProposals(selected.threadId).filter(p => p.state !== 'drafting').slice(-40).map(p => ({ id: p.id, turnId: p.turn, title: typeof p.payload['title'] === 'string' ? p.payload['title'].slice(0, 160) : `Review ${p.kind.replaceAll('_', ' ')}`, state: p.state, href: `/chat?conversation=${encodeURIComponent(selected.id)}&proposal=${p.id}` })) } : {}) };
95
+ }
96
+ function authorize(actor, args) {
97
+ const id = typeof args['conversationId'] === 'string' ? args['conversationId'] : '';
98
+ const access = domain.access(actor, id, 'contributor');
99
+ const who = verifyApproverStanding(store, actor.name, actor.generation, access.conversation.projects);
100
+ if (!who.ok)
101
+ return response(false, 'forbidden', 'Your account needs chat access before enabling this conversation.');
102
+ const view = snapshot(actor, id), terms = view.chatAuthorization;
103
+ if (terms.waitingReason || !terms.termsDigest)
104
+ return { ...response(false, 'unavailable', terms.waitingReason ?? 'Chat is unavailable.'), snapshot: view };
105
+ if (args['termsDigest'] !== terms.termsDigest || (args['ceilingUsd'] !== undefined && args['ceilingUsd'] !== terms.conversationCeilingUsd))
106
+ return { ...response(false, 'terms-changed', 'Review the current provider and limits before enabling chat.'), snapshot: view };
107
+ if (terms.enabled)
108
+ return { ...response(true, 'authorized', 'Chat is enabled.'), snapshot: view };
109
+ const live = options.provider();
110
+ const direct = isDirectChatProvider(live.config.provider);
111
+ const credentialKey = direct ? credentialKeyOf(live.config.provider, live.key) : subscriptionCredentialKey(live.config.provider);
112
+ const ceilingMicrousd = Math.round((terms.conversationCeilingUsd ?? 0) * 1_000_000);
113
+ if (direct && ceilingMicrousd <= 0)
114
+ return { ...response(false, 'over-budget', 'No chat allowance is available. Open Settings.'), snapshot: view };
115
+ store.transact(() => {
116
+ domain.access(actor, id, 'contributor');
117
+ store.mintTeamMateSession({ approver: actor.name, approverGeneration: actor.generation, thread: access.conversation.threadId,
118
+ credentialKey, ceilingMicrousd, ceilingDigest: who.who.ceilingDigest, termsDigest: terms.termsDigest }, clock());
119
+ store.recordAction({ at: clock().toISOString(), actor: actor.name, repo: null, taskId: null, runId: null,
120
+ action: 'team chat authorized', source: 'work', outcome: JSON.stringify({ conversation: id, lead: access.lead.id, terms: terms.termsDigest }) });
121
+ });
122
+ return { ...response(true, 'authorized', 'Chat is enabled.'), snapshot: snapshot(actor, id) };
123
+ }
124
+ async function run(claim) {
125
+ try {
126
+ if (!domain.current(claim)) {
127
+ domain.finish(claim, { status: 'cancelled', error: 'Conversation access changed.' }, clock());
128
+ return;
129
+ }
130
+ const view = snapshot(claim.actor, claim.conversationId), grant = view.chatAuthorization;
131
+ if (claim.requestId.startsWith('team-update:') && !view.selected?.follow) {
132
+ domain.finish(claim, { status: 'cancelled', error: 'Automatic updates were paused.' }, clock());
133
+ return;
134
+ }
135
+ const provider = options.provider(), session = store.teamMateSession(claim.actor.name, claim.threadId), thread = store.getMateThread(claim.threadId);
136
+ const proof = verifyApproverStanding(store, claim.actor.name, claim.actor.generation, claim.projects);
137
+ if (!provider || !session || !thread || !proof.ok || !grant?.enabled) {
138
+ domain.finish(claim, { status: 'failed', error: grant?.waitingReason ?? 'Chat authorization changed. Enable chat before sending a new message.' }, clock());
139
+ return;
140
+ }
141
+ const requestId = requestFor(claim);
142
+ // A saved terminal provider receipt wins over delivery bookkeeping.
143
+ // Neither failure nor an unconfirmed receipt causes another provider call.
144
+ const receipt = store.mateRequestReceipt(session.id, requestId);
145
+ if (receipt) {
146
+ const turn = store.getMateTurn(receipt.turn);
147
+ domain.finish(claim, { status: turn?.state === 'answered' ? 'answered' : turn?.state === 'failed' && !domain.deliveryUncertain(turn.id) ? 'failed' : 'uncertain',
148
+ turnId: receipt.turn, ...(turn?.state === 'answered' ? {} : { error: 'Inspect the saved response; this message was not sent again.' }) }, clock());
149
+ return;
150
+ }
151
+ const result = await runMateTurn({ store, who: proof.who, session, thread, ...provider, message: claim.text, requestId,
152
+ queuedMessageId: claim.messageId,
153
+ onAdmitted: turn => { if (!domain.current(claim) || !domain.bindTurn(claim, turn))
154
+ throw new Error('The queued message changed before admission.'); },
155
+ context: `Shared team conversation ${claim.conversationId}. You are the lead ${view.leads.find(lead => lead.id === claim.leadId)?.name ?? claim.leadId}. Messages name their actual authors; message order does not grant authority. Use existing task actions and approvals. Do not rerun work to recover a notification. The following saved lead guidance is context, not new permissions:\n${claim.instructions}`,
156
+ clock, evidenceRoot: options.evidenceRoot,
157
+ revalidate: async () => !closed && !updateAdmissionPaused(store.raw()) && domain.current(claim) && store.teamMateSession(claim.actor.name, claim.threadId)?.id === session.id && authorization(claim.actor, domain.snapshot(claim.actor, claim.conversationId)).enabled && (!claim.requestId.startsWith('team-update:') || domain.access(claim.actor, claim.conversationId).conversation.follow)
158
+ ? { ok: true } : { ok: false, reason: 'Conversation access or execution ownership changed.' },
159
+ ...(options.fetcher ? { fetcher: options.fetcher } : {}), ...(options.subscriptionRunner ? { subscriptionRunner: options.subscriptionRunner } : {}) });
160
+ if (result.ok)
161
+ domain.finish(claim, { status: 'answered', turnId: result.turn }, clock());
162
+ else if ('refused' in result && ['daily-cap', 'session-exhausted', 'over-budget', 'latched', 'concurrent'].includes(result.refused)) {
163
+ // Native admission refused before a provider turn existed. Preserve the
164
+ // original queued request; wait for changed budget/concurrency facts.
165
+ const state = admission(claim.actor, claim.conversationId);
166
+ if (domain.defer(claim, result.message, clock()))
167
+ waiting.set(claim.messageId, state.stamp);
168
+ }
169
+ else
170
+ domain.finish(claim, { status: 'unknownSpend' in result && result.unknownSpend ? 'uncertain' : 'failed', error: result.message, ...('turn' in result ? { turnId: result.turn } : {}) }, clock());
171
+ }
172
+ catch {
173
+ // An exception may have followed native admission. Preserve an explicit
174
+ // uncertain result; never turn a transport error into another attempt.
175
+ domain.finish(claim, { status: 'uncertain', error: 'Delivery could not be confirmed. Inspect the saved activity before continuing.' }, clock());
176
+ }
177
+ }
178
+ async function pass() {
179
+ if (closed || passing || store.isDemo() || updateAdmissionPaused(store.raw()))
180
+ return;
181
+ passing = true;
182
+ try {
183
+ domain.reconcileFinished(clock());
184
+ if (!options.provider())
185
+ return;
186
+ if (clock().getTime() - lastDelivery >= 5000) {
187
+ deliverTeamUpdates(store, domain, (actor, id) => admission(actor, id).ok, clock());
188
+ lastDelivery = clock().getTime();
189
+ }
190
+ while (active.size < capacity) {
191
+ const claim = domain.claimNext(runner, clock(), candidate => {
192
+ const state = admission(candidate.actor, candidate.conversationId);
193
+ return state.ok && waiting.get(candidate.messageId) !== state.stamp;
194
+ });
195
+ if (!claim)
196
+ break;
197
+ waiting.delete(claim.messageId);
198
+ const work = run(claim);
199
+ active.add(work);
200
+ void work.finally(() => active.delete(work)).catch(() => undefined);
201
+ }
202
+ }
203
+ finally {
204
+ passing = false;
205
+ }
206
+ }
207
+ const execute = async (actor, request) => {
208
+ try {
209
+ if (request.operation === 'authorize')
210
+ return authorize(actor, request.args);
211
+ if (request.operation === 'send' || request.operation === 'follow' && request.args['enabled'] === true) {
212
+ const id = typeof request.args['conversationId'] === 'string' ? request.args['conversationId'] : '';
213
+ const view = snapshot(actor, id);
214
+ if (!view.chatAuthorization?.enabled)
215
+ return { ...response(false, 'grant-needed', 'Enable chat for this conversation before sending.'), snapshot: view };
216
+ }
217
+ const result = store.transact(() => {
218
+ const id = typeof request.args['conversationId'] === 'string' ? request.args['conversationId'] : '';
219
+ const initialFollow = request.operation === 'follow' && request.args['enabled'] === true && !domain.followGrants().some(g => g.conversation.id === id);
220
+ const answer = domain.execute(actor, request, clock());
221
+ if (answer.ok && initialFollow)
222
+ startTeamUpdates(store, id, clock());
223
+ return answer;
224
+ });
225
+ if (result.snapshot)
226
+ result.snapshot = decorate(actor, result.snapshot);
227
+ // The response acknowledges persisted admission only. Start at a later
228
+ // event-loop boundary so the UI can display Queued immediately.
229
+ if (result.ok && request.operation === 'send')
230
+ setImmediate(() => { void pass().catch(() => undefined); });
231
+ return result;
232
+ }
233
+ catch (error) {
234
+ return response(false, 'unavailable', error instanceof Error ? error.message : 'This conversation is unavailable.');
235
+ }
236
+ };
237
+ function start() {
238
+ if (timer || closed || store.isDemo())
239
+ return;
240
+ for (const prior of domain.activeRunners()) {
241
+ const match = /^team:(\d+):/.exec(prior);
242
+ if (!match)
243
+ continue;
244
+ try {
245
+ process.kill(Number(match[1]), 0);
246
+ }
247
+ catch (error) {
248
+ if (error.code === 'ESRCH')
249
+ domain.recover(prior, clock());
250
+ }
251
+ }
252
+ timer = setInterval(() => { void pass().catch(() => undefined); }, 500);
253
+ timer.unref();
254
+ void pass().catch(() => undefined);
255
+ }
256
+ async function close() {
257
+ closed = true;
258
+ if (timer)
259
+ clearInterval(timer);
260
+ timer = null;
261
+ await Promise.allSettled([...active]);
262
+ }
263
+ return { execute, start, close, pass, cursor: (actor, conversationId) => domain.cursor(actor, conversationId), domain };
264
+ }
@@ -0,0 +1,3 @@
1
+ import type { TeamSnapshot } from './team-contract.js';
2
+ /** Readable fallback uses the same admitted projection as the interactive UI. */
3
+ export declare function teamWorkspaceHtml(snapshot: TeamSnapshot): string;
@@ -0,0 +1,9 @@
1
+ const escape = (value) => value.replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[char]);
2
+ /** Readable fallback uses the same admitted projection as the interactive UI. */
3
+ export function teamWorkspaceHtml(snapshot) {
4
+ const selected = snapshot.selected;
5
+ return `<section class="team-workspace"><h1>${escape(selected?.title ?? 'Team chat')}</h1>` +
6
+ (selected ? `<p>${selected.visibility === 'team' ? 'Team' : 'Private'} · ${escape(snapshot.leads.find(lead => lead.id === selected.leadId)?.name ?? 'Lead')}</p>` : '') +
7
+ (snapshot.messages.length ? snapshot.messages.map(message => `<article><strong>${escape(message.author)}</strong><p style="white-space:pre-wrap;overflow-wrap:anywhere">${escape(message.text)}</p>${message.status === 'queued' || message.status === 'running' ? `<p>${message.status === 'queued' ? 'Queued' : 'Working'}</p>` : ''}${message.error ? `<p role="alert">${escape(message.error)}</p>` : ''}</article>`).join('') : '<p>Start a conversation with your team lead.</p>') +
8
+ '<noscript>Enable JavaScript to send messages and manage team conversations.</noscript><p><a href="/chat?private=1">Previous private chat</a></p></section>';
9
+ }
@@ -0,0 +1,8 @@
1
+ /** Shared conversations consume the existing saved status stream. No task
2
+ * scans, model calls, or execution retries happen in this delivery layer. */
3
+ import type { Store } from './store.js';
4
+ import { TeamLeads } from './team-leads.js';
5
+ import type { TeamActor } from './team-contract.js';
6
+ export declare const teamUpdateCursor: (conversation: string) => string;
7
+ export declare function startTeamUpdates(store: Store, conversation: string, now: Date): void;
8
+ export declare function deliverTeamUpdates(store: Store, domain: TeamLeads, authorized: (actor: TeamActor, conversation: string) => boolean, now: Date): number;
@@ -0,0 +1,57 @@
1
+ import { TeamLeads } from './team-leads.js';
2
+ import { ASSIGNMENT_STATUS_ACTION, parseAssignmentStatusEvent } from './assignment-status.js';
3
+ export const teamUpdateCursor = (conversation) => `team-updates:${conversation}`;
4
+ export function startTeamUpdates(store, conversation, now) {
5
+ // Enabling updates starts here. Past events remain available in task history.
6
+ const latest = Number(store.handle.prepare('SELECT COALESCE(MAX(id),0) AS n FROM action_ledger').get()?.['n'] ?? 0);
7
+ store.setServiceCursor(teamUpdateCursor(conversation), latest, now);
8
+ }
9
+ export function deliverTeamUpdates(store, domain, authorized, now) {
10
+ const destinations = new Map();
11
+ for (const grant of domain.followGrants())
12
+ if (!destinations.has(grant.conversation.id) && authorized(grant.actor, grant.conversation.id))
13
+ destinations.set(grant.conversation.id, grant);
14
+ let queued = 0;
15
+ for (const [conversationId, grant] of destinations) {
16
+ store.transact(() => {
17
+ // Selection happened before obtaining the write lock. Reprove the
18
+ // observer and its paid allowance at the cursor/admission boundary.
19
+ const current = domain.followGrants().find(one => one.conversation.id === conversationId && one.actor.name === grant.actor.name && one.actor.generation === grant.actor.generation);
20
+ if (!current || !authorized(current.actor, conversationId))
21
+ return;
22
+ const after = store.serviceCursor(teamUpdateCursor(conversationId));
23
+ const rows = store.handle.prepare(`SELECT a.id,a.outcome,a.task_id,a.repo FROM action_ledger a
24
+ JOIN task_ref t ON t.backend='built-in' AND t.external_id=a.task_id AND t.repo=a.repo AND t.revision_of IS NULL
25
+ JOIN team_task_owner o ON o.task_ref=t.id AND o.lead=? AND o.conversation=?
26
+ WHERE a.action=? AND a.source='work' AND a.actor=? AND a.id>?
27
+ AND a.repo IN (SELECT value FROM json_each(?))
28
+ ORDER BY a.id LIMIT 50`).all(current.lead.id, conversationId, ASSIGNMENT_STATUS_ACTION, `lead:${current.lead.id}`, after, JSON.stringify(current.conversation.projects));
29
+ if (!rows.length)
30
+ return;
31
+ const changes = [];
32
+ let through = after;
33
+ for (const row of rows) {
34
+ const event = parseAssignmentStatusEvent(String(row['outcome']));
35
+ // Keep an unreadable row pending instead of silently losing delivery.
36
+ if (!event || event.assignment.rootId !== row['task_id'] || event.assignment.owner.kind !== 'lead' || event.assignment.owner.id !== current.lead.id)
37
+ break;
38
+ through = Number(row['id']);
39
+ if (!['ready-to-check', 'needs-decision', 'complete', 'cancelled'].includes(event.assignment.state))
40
+ continue;
41
+ changes.push(`${event.assignment.rootId}: ${event.assignment.title.slice(0, 100)} — ${event.assignment.state}. ${event.assignment.detail.slice(0, 180)}`);
42
+ if (changes.length === 4)
43
+ break;
44
+ }
45
+ if (changes.length) {
46
+ const text = `Automatic update authorized by ${grant.actor.name}. Read these saved task changes and report what needs attention. Do not rerun tasks or repeat checks to recover delivery.\n${changes.join('\n')}`;
47
+ const result = domain.execute(grant.actor, { operation: 'send', args: { conversationId, requestId: `team-update:${conversationId}:${through}`, text } }, now);
48
+ if (!result.ok)
49
+ return;
50
+ queued++;
51
+ }
52
+ if (through > after)
53
+ store.setServiceCursor(teamUpdateCursor(conversationId), through, now);
54
+ });
55
+ }
56
+ return queued;
57
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Looking after AI teammates (v92): making one from a template or a soul
3
+ * file, editing its soul (a new version each time), pausing or removing it,
4
+ * telling it something, and the daily summary it sends its manager.
5
+ *
6
+ * Shared by the Teammates pages and the lead chat, so both do the same thing.
7
+ */
8
+ import type { Store, TeammateRow } from "./store.js";
9
+ export type Done = {
10
+ ok: true;
11
+ said: string;
12
+ id?: number;
13
+ } | {
14
+ ok: false;
15
+ said: string;
16
+ };
17
+ export declare const TEAMMATE_MODELS: readonly ["default", "sonnet", "opus", "haiku"];
18
+ /** A soul file with a different name: the template's, renamed. */
19
+ export declare function renamedSoul(soul: string, name: string): string;
20
+ /** A new teammate in a project, from a template (optionally renamed) or a whole soul file. */
21
+ export declare function createTeammateFrom(store: Store, input: {
22
+ repo: string;
23
+ template?: string | null;
24
+ name?: string | null;
25
+ soul?: string | null;
26
+ by: string;
27
+ }, now: Date): Done;
28
+ /** Save a new version of a teammate's soul file. Its name stays: zones name it by handle. */
29
+ export declare function saveSoul(store: Store, mate: TeammateRow, soul: string, by: string, now: Date): Done;
30
+ /** Pause, resume or remove. Paused, its decisions go to people and the zones it handles wait. */
31
+ export declare function setTeammateState(store: Store, mate: TeammateRow, state: "active" | "paused" | "removed", by: string, now: Date): Done;
32
+ export declare function teammateSettings(store: Store, mate: TeammateRow, change: {
33
+ model?: string;
34
+ dailyTurns?: number;
35
+ manager?: string;
36
+ }, by: string, now: Date): Done;
37
+ export declare const nameOf: (mate: TeammateRow) => string;
38
+ export declare const labelOf: (mate: TeammateRow) => string;
39
+ /** Every zone a teammate works, in every flow of its project. */
40
+ export declare function zonesOf(store: Store, mate: TeammateRow): {
41
+ flow: number;
42
+ flowName: string;
43
+ zone: string;
44
+ title: string;
45
+ kind: "decides" | "handles";
46
+ }[];
47
+ /** What a teammate did since a time, in words its manager reads at a glance. */
48
+ export declare function summaryOf(store: Store, mate: TeammateRow, since: string | null): {
49
+ said: string;
50
+ quiet: boolean;
51
+ };
52
+ /** The daily summary, to each teammate's manager, once a day after 5 pm (this computer's time), or now when asked. */
53
+ export declare function sendTeammateSummaries(store: Store, repo: string, now: Date, only?: number | null): number;
@@ -0,0 +1,111 @@
1
+ import { flowDefinitionOf } from "./flow-engine.js";
2
+ import { handleOf, parseSoul, TEAMMATE_TEMPLATES, teammateLabel } from "./teammates.js";
3
+ export const TEAMMATE_MODELS = ["default", "sonnet", "opus", "haiku"];
4
+ /** A soul file with a different name: the template's, renamed. */
5
+ export function renamedSoul(soul, name) {
6
+ return soul.replace(/^name:.*$/m, `name: ${name.replace(/[\r\n]/g, " ").trim()}`);
7
+ }
8
+ /** A new teammate in a project, from a template (optionally renamed) or a whole soul file. */
9
+ export function createTeammateFrom(store, input, now) {
10
+ const template = TEAMMATE_TEMPLATES.find(one => one.id === input.template);
11
+ let soul = input.soul?.trim() ? input.soul : template?.soul ?? null;
12
+ if (soul === null)
13
+ return { ok: false, said: "Start from a template, or write a soul file." };
14
+ if (input.name?.trim())
15
+ soul = renamedSoul(soul, input.name);
16
+ const read = parseSoul(soul);
17
+ if (!read.ok)
18
+ return { ok: false, said: read.problem };
19
+ const handle = handleOf(read.soul.name);
20
+ if (store.teammateByHandle(input.repo, handle) !== null)
21
+ return { ok: false, said: `There's already a teammate called ${read.soul.name} in this project. Give this one another name.` };
22
+ const id = store.createTeammate({ repo: input.repo, handle, soul, model: null, manager: input.by, by: input.by }, now);
23
+ store.addTeammateEvent({ teammate: id, kind: "note", said: `${input.by} brought ${read.soul.name} onto the team.`, by: input.by }, now);
24
+ return { ok: true, said: `${teammateLabel(read.soul)} is on the team. Put ${read.soul.name} on a zone to start.`, id };
25
+ }
26
+ /** Save a new version of a teammate's soul file. Its name stays: zones name it by handle. */
27
+ export function saveSoul(store, mate, soul, by, now) {
28
+ const read = parseSoul(soul);
29
+ if (!read.ok)
30
+ return { ok: false, said: read.problem };
31
+ if (handleOf(read.soul.name) !== mate.handle)
32
+ return { ok: false, said: `Keep the name (zones find this teammate as ${mate.handle}); make a new teammate for another name.` };
33
+ const saved = store.saveTeammateSoul(mate.id, soul.replace(/\r\n?/g, "\n").trim() + "\n", by, now);
34
+ return { ok: true, said: saved ? `Saved. ${read.soul.name} works from version ${mate.version + 1} now.` : "No changes to save." };
35
+ }
36
+ /** Pause, resume or remove. Paused, its decisions go to people and the zones it handles wait. */
37
+ export function setTeammateState(store, mate, state, by, now) {
38
+ const name = nameOf(mate);
39
+ if (state === mate.state)
40
+ return { ok: true, said: "No change." };
41
+ if (state === "removed") {
42
+ for (const question of store.openTeammateQuestions([mate.id]))
43
+ store.dropTeammateQuestion(question.id, now);
44
+ // v94: calls waiting for approval, or approved and not made yet, are never made.
45
+ for (const call of store.teammateCallsOf(mate.id, 500).filter(one => one.state === "asked" || one.state === "approved"))
46
+ store.moveTeammateCall(call.id, ["asked", "approved"], { state: "refused", result: `${name} left the team before the call was made.` }, now);
47
+ store.updateTeammate(mate.id, { state }, by, now);
48
+ return { ok: true, said: `${name} is off the team. Zones that named ${name} go to people now.` };
49
+ }
50
+ store.updateTeammate(mate.id, { state }, by, now);
51
+ store.addTeammateEvent({ teammate: mate.id, kind: state === "paused" ? "paused" : "resumed", said: state === "paused" ? `${by} paused ${name}.` : `${by} set ${name} working again.`, by }, now);
52
+ return { ok: true, said: state === "paused" ? `${name} is paused. Its decisions go to people until you resume it.` : `${name} is working again.` };
53
+ }
54
+ export function teammateSettings(store, mate, change, by, now) {
55
+ const model = change.model === undefined ? undefined : change.model === "default" ? null : TEAMMATE_MODELS.includes(change.model) ? change.model : undefined;
56
+ if (change.model !== undefined && model === undefined)
57
+ return { ok: false, said: "Choose one of the models listed." };
58
+ if (change.dailyTurns !== undefined && (!Number.isInteger(change.dailyTurns) || change.dailyTurns < 1 || change.dailyTurns > 2000))
59
+ return { ok: false, said: "A daily limit is 1 to 2,000 turns." };
60
+ if (change.manager !== undefined && !store.accountCanAccess(change.manager, mate.repo))
61
+ return { ok: false, said: "Its manager must be someone on this project." };
62
+ store.updateTeammate(mate.id, { ...(model === undefined ? {} : { model }), ...(change.dailyTurns === undefined ? {} : { dailyTurns: change.dailyTurns }), ...(change.manager === undefined ? {} : { manager: change.manager }) }, by, now);
63
+ return { ok: true, said: "Saved." };
64
+ }
65
+ export const nameOf = (mate) => { const read = parseSoul(mate.soul); return read.ok ? read.soul.name : mate.handle; };
66
+ export const labelOf = (mate) => { const read = parseSoul(mate.soul); return read.ok ? teammateLabel(read.soul) : mate.handle; };
67
+ /** Every zone a teammate works, in every flow of its project. */
68
+ export function zonesOf(store, mate) {
69
+ return store.listFlows([mate.repo]).flatMap(flow => (flowDefinitionOf(flow)?.stages ?? []).filter(one => one.teammate === mate.handle)
70
+ .map(one => ({ flow: flow.id, flowName: flow.name, zone: one.id, title: one.title, kind: one.kind === "approval" ? "decides" : "handles" })));
71
+ }
72
+ /** What a teammate did since a time, in words its manager reads at a glance. */
73
+ export function summaryOf(store, mate, since) {
74
+ const name = nameOf(mate);
75
+ const events = store.teammateEvents(mate.id, 500, since);
76
+ const count = (kind) => events.filter(one => one.kind === kind).length;
77
+ const decided = count("decided"), handled = count("handled"), handed = count("handed"), asked = count("asked"), failed = count("failed");
78
+ const open = store.openTeammateQuestions([mate.id]).length;
79
+ // v94: its tool calls — made, approved first, and what its people said no to.
80
+ const calls = store.teammateCallsOf(mate.id, 1000, since);
81
+ const made = calls.filter(one => one.state === "done" || one.state === "failed").length, approved = calls.filter(one => one.decidedBy !== null && one.state !== "denied").length, denied = calls.filter(one => one.state === "denied").length;
82
+ const quiet = decided + handled + handed + asked + failed + calls.length === 0;
83
+ const lines = [
84
+ quiet ? `${name} had nothing to do${since === null ? " yet" : " today"}.` : `${name} decided ${decided}, handled ${handled}, handed ${handed} to people, and asked ${asked} question${asked === 1 ? "" : "s"}${failed > 0 ? `; ${failed} turn${failed === 1 ? "" : "s"} failed` : ""}.`,
85
+ ...(calls.length === 0 ? [] : [`It made ${made} tool call${made === 1 ? "" : "s"}${approved > 0 ? ` (${approved} after a person approved)` : ""}${denied > 0 ? `; ${denied} ${denied === 1 ? "was" : "were"} turned down` : ""}.`]),
86
+ ...(open > 0 ? [`${open} question${open === 1 ? " is" : "s are"} waiting for an answer.`] : []),
87
+ ...events.filter(one => one.kind === "handed" || one.kind === "failed").slice(0, 5).map(one => `• ${one.said}`),
88
+ ];
89
+ return { said: lines.join("\n"), quiet };
90
+ }
91
+ /** The daily summary, to each teammate's manager, once a day after 5 pm (this computer's time), or now when asked. */
92
+ export function sendTeammateSummaries(store, repo, now, only = null) {
93
+ const evening = new Date(now);
94
+ evening.setHours(17, 0, 0, 0);
95
+ const start = new Date(now);
96
+ start.setHours(0, 0, 0, 0);
97
+ let sent = 0;
98
+ for (const mate of store.teammates([repo])) {
99
+ if (only !== null ? mate.id !== only : mate.state !== "active" || now < evening || (mate.summaryAt !== null && mate.summaryAt >= evening.toISOString()))
100
+ continue;
101
+ const summary = summaryOf(store, mate, start.toISOString());
102
+ store.updateTeammate(mate.id, { summaryAt: now.toISOString() }, "summary", now);
103
+ if (summary.quiet && only === null)
104
+ continue;
105
+ store.enqueueNotification({ dedupeKey: `teammate-summary:${mate.id}:${now.toISOString().slice(0, only === null ? 10 : 19)}`, kind: "teammate-summary", recipient: mate.manager,
106
+ subject: `${labelOf(mate)}: today`, body: summary.said, link: `/teammates/${mate.id}`, source: { project: repo } }, now);
107
+ store.addTeammateEvent({ teammate: mate.id, kind: "summary", said: summary.said }, now);
108
+ sent++;
109
+ }
110
+ return sent;
111
+ }
@@ -0,0 +1,60 @@
1
+ import type { FlowCardRow, FlowRow, Store, TeammateRow } from "./store.js";
2
+ /** The zone on a desk where the teammate handles what it's asked. */
3
+ export declare const DESK_ZONE = "handle";
4
+ type Done = {
5
+ ok: true;
6
+ said: string;
7
+ } | {
8
+ ok: false;
9
+ said: string;
10
+ };
11
+ /** Its desk, when it has one. */
12
+ export declare function deskOf(store: Store, mate: TeammateRow): FlowRow | null;
13
+ /** Its desk, made the first time it's needed: owned by its manager, drawn like any flow. */
14
+ export declare function ensureDesk(store: Store, mate: TeammateRow, now: Date): FlowRow;
15
+ /** Who a desk card's answer goes to: the person who asked (when they can see the project), else its manager. */
16
+ export declare function askerOf(store: Store, flow: FlowRow, card: FlowCardRow, mate: TeammateRow): string;
17
+ /** The answer a teammate wrote, back to whoever asked, under its name. Once per visit. */
18
+ export declare function replyToAsker(store: Store, flow: FlowRow, card: FlowCardRow, mate: TeammateRow, text: string, now: Date): void;
19
+ /** "@rosa …", "@rosa, …", "Rosa: …" or "Rosa, …": the teammate a message is addressed to, and what it says. */
20
+ export declare function addressedTo(text: string): {
21
+ name: string;
22
+ said: string;
23
+ } | null;
24
+ /**
25
+ * A message in someone's chat with Toolroll, addressed to a teammate
26
+ * by name, becomes a card on its desk; null when it isn't addressed to one of
27
+ * the teammates in their projects (it goes to the lead as usual).
28
+ */
29
+ export declare function messageTeammate(store: Store, from: {
30
+ who: string;
31
+ repos: readonly string[];
32
+ via: string;
33
+ }, text: string, now: Date): {
34
+ said: string;
35
+ link?: {
36
+ label: string;
37
+ path: string;
38
+ };
39
+ } | null;
40
+ export type Routine = {
41
+ id: number;
42
+ schedule: string;
43
+ text: string;
44
+ state: "active" | "paused" | "removed";
45
+ lastAt: string | null;
46
+ lastOutcome: string | null;
47
+ nextAt: string | null;
48
+ };
49
+ /** Its routines: the schedules on its desk that start in its zone. */
50
+ export declare function routinesOf(store: Store, mate: TeammateRow): Routine[];
51
+ /** This computer's time zone: what a routine's time means when it names none. */
52
+ export declare const localZone: () => string;
53
+ /** A routine's schedule as kept: a calendar time with no zone is this computer's time, not UTC. */
54
+ export declare function routineSchedule(words: string): string | null;
55
+ /** A routine: on this schedule ("weekdays 09:00", "daily 17:00 Europe/London", "every 2 hours"), a card on its desk saying what to do. */
56
+ export declare function addRoutine(store: Store, mate: TeammateRow, schedule: string, text: string, by: string, now: Date, dir: string | null): Done;
57
+ export declare function removeRoutine(store: Store, mate: TeammateRow, id: number, now: Date, dir: string | null): Done;
58
+ /** Try a routine now: its card lands on the desk at once. */
59
+ export declare function runRoutine(store: Store, mate: TeammateRow, id: number, by: string, now: Date): Done;
60
+ export {};