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,57 @@
1
+ import { type ChatApp } from "./flow-triggers.js";
2
+ import { type ChatBinding } from "./chat-delivery-state.js";
3
+ import type { FlowCardSource, FlowTriggerRow, Store } from "./store.js";
4
+ /** "flow 12" or "flow off", after any mention of the bot; Telegram's "/flow 12" or "/flow@bot 12" too. */
5
+ export declare const FLOW_WORDS: RegExp;
6
+ /** A channel's own id: Teams puts the thread's message id on the end of a channel conversation. */
7
+ export declare const channelOf: (app: ChatApp, conversation: string) => string;
8
+ /** The flow a channel feeds, if it feeds one. */
9
+ export declare function watchedChannel(store: Store, app: ChatApp, installation: string, conversation: string): FlowTriggerRow | null;
10
+ /** What a receiver needs to know about a channel message: whether the channel feeds a flow, and whether these are the words that connect one. */
11
+ export declare function channelInbox(store: Store, app: ChatApp, installation: string, conversation: string, text: string): {
12
+ watched: boolean;
13
+ command: boolean;
14
+ };
15
+ /** "flow 12" / "flow off" from a paired approver in a channel: connect it to the flow, or stop it feeding one. */
16
+ export declare function connectChannel(store: Store, input: {
17
+ app: ChatApp;
18
+ installation: string;
19
+ conversation: string;
20
+ binding: Pick<ChatBinding, "id" | "approver">;
21
+ text: string;
22
+ repos: readonly string[];
23
+ followsConversation: boolean;
24
+ }, now: Date): string;
25
+ /**
26
+ * A message in a channel that feeds a flow: a new card (and what to say in
27
+ * its thread), a reply that joins a card's discussion (nothing to say), or
28
+ * why it was left out.
29
+ */
30
+ export declare function takeChannelMessage(store: Store, trigger: FlowTriggerRow, message: {
31
+ app: ChatApp;
32
+ conversation: string;
33
+ ts: string;
34
+ thread: string;
35
+ text: string;
36
+ who: string;
37
+ }, now: Date): {
38
+ said: string | null;
39
+ link?: {
40
+ label: string;
41
+ path: string;
42
+ };
43
+ };
44
+ /**
45
+ * Answer in the thread a card came from (an Update zone): one message,
46
+ * through the chat of whoever connected the channel. Idempotent per card
47
+ * visit, so a retried step never answers twice.
48
+ */
49
+ export declare function replyInChannel(store: Store, source: NonNullable<FlowCardSource["chat"]>, visit: {
50
+ card: number;
51
+ entry: number;
52
+ }, text: string, now: Date): {
53
+ ok: true;
54
+ } | {
55
+ ok: false;
56
+ said: string;
57
+ };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Chat channels as inboxes (v89): a Slack, Discord or Teams channel feeds a
3
+ * flow.
4
+ *
5
+ * - Connecting happens in the channel itself: a paired approver sends
6
+ * "flow 12" (or "flow off"), which proves the channel is one they are in
7
+ * and that the flow is one they can change. One channel feeds one flow; a
8
+ * channel that follows a team conversation is left as it is.
9
+ * - From then on every new message there — from anyone the app lets the bot
10
+ * see — is a card in that flow, and the bot says so in the message's
11
+ * thread. A reply in that thread joins the card's discussion.
12
+ * - The card remembers where it came from, so an Update zone can answer in
13
+ * that same thread, through the chat of the person who connected it.
14
+ *
15
+ * Nothing here gives a message any authority: a card's work waits for the
16
+ * usual approvals, and text that looks like a key never becomes a card.
17
+ */
18
+ import { flowCardHref, flowDefinitionOf } from "./flow-engine.js";
19
+ import { addTriggerCard, CHAT_APP_NAMES, triggerConfigOf } from "./flow-triggers.js";
20
+ import { ChatState, chatHash } from "./chat-delivery-state.js";
21
+ /** "flow 12" or "flow off", after any mention of the bot; Telegram's "/flow 12" or "/flow@bot 12" too. */
22
+ export const FLOW_WORDS = /^(?:<@[^>]+>\s*)?\/?flow(?:@[A-Za-z0-9_]{1,64})?\s+(off|[1-9][0-9]{0,9})\s*$/i;
23
+ const TITLE_CHARS = 120;
24
+ /** A channel's own id: Teams puts the thread's message id on the end of a channel conversation. */
25
+ export const channelOf = (app, conversation) => app === "teams" ? conversation.replace(/;messageid=[0-9]+$/, "") : conversation;
26
+ /** The flow a channel feeds, if it feeds one. */
27
+ export function watchedChannel(store, app, installation, conversation) {
28
+ return store.chatTriggerFor(app, installation, channelOf(app, conversation));
29
+ }
30
+ /** What a receiver needs to know about a channel message: whether the channel feeds a flow, and whether these are the words that connect one. */
31
+ export function channelInbox(store, app, installation, conversation, text) {
32
+ return { watched: watchedChannel(store, app, installation, conversation) !== null, command: FLOW_WORDS.test(text.trim()) };
33
+ }
34
+ /** "flow 12" / "flow off" from a paired approver in a channel: connect it to the flow, or stop it feeding one. */
35
+ export function connectChannel(store, input, now) {
36
+ const words = FLOW_WORDS.exec(input.text.trim());
37
+ if (words === null)
38
+ return "Send “flow” and a flow's number, like “flow 12”, or “flow off”.";
39
+ const chat = channelOf(input.app, input.conversation);
40
+ const current = store.chatTriggerFor(input.app, input.installation, chat);
41
+ const name = CHAT_APP_NAMES[input.app];
42
+ if (words[1].toLowerCase() === "off") {
43
+ if (current === null)
44
+ return "This channel doesn't feed a flow.";
45
+ const flow = store.getFlow(current.flow);
46
+ if (flow !== null && !input.repos.includes(flow.repo))
47
+ return "Only someone who can change that flow can stop this channel feeding it.";
48
+ store.updateFlowTrigger(current.id, { state: "removed", lastAt: now.toISOString(), lastOutcome: `Disconnected in ${name} by ${input.binding.approver}.` }, now);
49
+ return `This channel no longer feeds ${flow?.name ?? "its flow"}.`;
50
+ }
51
+ if (input.followsConversation)
52
+ return "This channel follows a team conversation. Send “team off” first to make it feed a flow instead.";
53
+ const flow = store.getFlow(Number(words[1]));
54
+ if (flow === null || flow.state !== "active" || !input.repos.includes(flow.repo) || flowDefinitionOf(flow) === null)
55
+ return `There's no flow ${words[1]} you can change. The number is in the flow's address: /flows/12.`;
56
+ if (current !== null && current.flow === flow.id)
57
+ return `This channel already feeds ${flow.name}.`;
58
+ store.transact(() => {
59
+ if (current !== null)
60
+ store.updateFlowTrigger(current.id, { state: "removed", lastAt: now.toISOString(), lastOutcome: `Moved to ${flow.name} by ${input.binding.approver}.` }, now);
61
+ const id = store.addFlowTrigger({ flow: flow.id, kind: "chat", hookHash: null, cursor: null, nextAt: null, by: input.binding.approver,
62
+ configJson: JSON.stringify({ kind: "chat", app: input.app, installation: input.installation, chat, binding: input.binding.id, zone: null }) }, now);
63
+ store.updateFlowTrigger(id, { lastAt: now.toISOString(), lastOutcome: `Connected in ${name} by ${input.binding.approver}.` }, now);
64
+ });
65
+ return `This channel now feeds ${flow.name}: each new message here becomes a card, and replies in its thread join the card's discussion. Send “flow off” to stop.`;
66
+ }
67
+ /** A message's words as a card: the first line is the title, all of it the details when there's more. */
68
+ function cardWords(text) {
69
+ const clean = text.replace(/<@[A-Z0-9]+>/g, "").replace(/\r\n?/g, "\n").trim();
70
+ const first = clean.split("\n")[0].trim();
71
+ const title = first.length > TITLE_CHARS ? `${first.slice(0, TITLE_CHARS - 1).trimEnd()}…` : first;
72
+ return { title: title || "Message", description: clean === title ? null : clean.slice(0, 4000) };
73
+ }
74
+ /**
75
+ * A message in a channel that feeds a flow: a new card (and what to say in
76
+ * its thread), a reply that joins a card's discussion (nothing to say), or
77
+ * why it was left out.
78
+ */
79
+ export function takeChannelMessage(store, trigger, message, now) {
80
+ const config = triggerConfigOf(trigger);
81
+ if (config?.kind !== "chat")
82
+ return { said: null };
83
+ const name = CHAT_APP_NAMES[message.app];
84
+ if (message.text.trim() === "")
85
+ return { said: null };
86
+ if (message.thread !== message.ts) {
87
+ // A reply in the thread of a message that became a card: it joins that card's discussion.
88
+ const card = store.flowTriggerCard(trigger.id, `msg:${message.thread}`);
89
+ if (card !== null && store.getFlowCard(card)?.state === "active")
90
+ store.addFlowComment({ card, author: `${message.who} (${name})`.slice(0, 64), body: message.text.slice(0, 2000), mentions: [] }, now);
91
+ return { said: null };
92
+ }
93
+ const words = cardWords(message.text);
94
+ const source = { kind: "chat", label: `${name} message`, url: null,
95
+ chat: { app: message.app, installation: config.installation, chat: config.chat, conversation: message.conversation, thread: message.ts, binding: config.binding } };
96
+ const made = addTriggerCard(store, trigger, { key: `msg:${message.ts}`, title: words.title, description: words.description, source }, name, now);
97
+ const flow = store.getFlow(trigger.flow);
98
+ if (made.made === "added") {
99
+ store.updateFlowTrigger(trigger.id, { lastAt: now.toISOString(), lastOutcome: "Added a card." }, now);
100
+ return { said: `Added to ${flow?.name ?? "the flow"} as a card. Replies here join its discussion.`, ...(flow === null ? {} : { link: { label: "Open the card", path: flowCardHref(flow.id, made.card) } }) };
101
+ }
102
+ return { said: made.made === "skipped" && made.note !== null ? `Not added: ${made.note.replace(/^[^:]+: /, "")}.` : null };
103
+ }
104
+ /**
105
+ * Answer in the thread a card came from (an Update zone): one message,
106
+ * through the chat of whoever connected the channel. Idempotent per card
107
+ * visit, so a retried step never answers twice.
108
+ */
109
+ export function replyInChannel(store, source, visit, text, now) {
110
+ if (source.app !== "slack" && source.app !== "discord" && source.app !== "teams")
111
+ return { ok: false, said: `Answering in a ${CHAT_APP_NAMES[source.app] ?? source.app} group isn't supported yet, so nothing was posted. The card's link is in the group.` };
112
+ const state = new ChatState(store, source.app);
113
+ const grant = state.bindingById(source.binding);
114
+ if (grant === null || !state.live(grant))
115
+ return { ok: false, said: `The person who connected that ${CHAT_APP_NAMES[source.app]} channel is no longer paired, so nothing was posted.` };
116
+ const id = chatHash(`${source.app}:flow-reply:${visit.card}:${visit.entry}`);
117
+ store.transact(() => {
118
+ if (state.enqueue({ id, installation: grant.installation, binding: grant.id, kind: "message", channel: source.conversation, member: grant.member,
119
+ ts: source.thread, thread: source.thread, payload: "{}", created: now.toISOString() }))
120
+ state.plan(id, [{ text: text.slice(0, 3500), channel: source.conversation }], now);
121
+ });
122
+ return { ok: true };
123
+ }
@@ -0,0 +1,16 @@
1
+ import type { ChatSnapshot } from './store.js';
2
+ /** Presentation only. These are recorded completions, not a claim that
3
+ * work happened since the user last visited, or that every result passed. */
4
+ export declare function completedWorkHtml(snapshot: ChatSnapshot, projectLabels: readonly string[], assignments?: Readonly<Record<string, {
5
+ state: string;
6
+ }>>): string;
7
+ /** Keep activity truthful: the turn's recorded step count is not a
8
+ * percentage or an invented tool phase. Billing detail stays available. */
9
+ export declare function chatWorkingHtml(input: {
10
+ details: string;
11
+ stopForm?: string;
12
+ keyed?: boolean;
13
+ }): string;
14
+ /** Recorded activity is inspectable, not a row of performance badges. */
15
+ export declare function chatActivityDetailsHtml(activity: string | null): string;
16
+ export declare const CHAT_POLISH_CSS = "\n /* Quiet workspace surfaces: color signals state, not an AI aesthetic. */\n body { background: var(--background); }\n .chat-workspace .chat-overview, .chat-workspace .chat-plan, .chat-workspace .result-panel,\n .chat-workspace .decide-card { background: var(--card); box-shadow: none; }\n .chat-workspace .result-panel { border-radius: .75rem; }\n .chat-workspace .chat-empty::before { content: none; }\n .chat-workspace .thread .msg.mate::before { background: var(--muted); box-shadow: none; border: 0; }\n .chat-workspace .thread .msg.op { box-shadow: none; border: 0; }\n .chat-workspace .completion-receipt { background: var(--card); box-shadow: none; }\n .chat-workspace .completion-receipt::after { content: none; }\n .chat-workspace .thread { min-height: 0; }\n .chat-workspace .chat-turn-history { margin: 1rem 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; box-shadow: none; padding: 0; }\n .chat-turn-history > summary { display: flex; align-items: center; gap: .75rem; min-height: 44px; cursor: pointer; font-size: .875rem; }\n .chat-turn-history > summary .meta { margin-left: auto; }\n .chat-turn-history .row { display: flex; flex-wrap: wrap; gap: .4rem; }\n .chat-turn-history .row .right { float: none; margin-left: auto; }\n .chat-workspace .task-live-summary { margin-bottom: .75rem; padding-bottom: .25rem; }\n .chat-workspace .task-journey > details, .chat-workspace .result-feedback-history,\n .chat-workspace .chat-limits, .chat-workspace .task-chat-agents {\n border: 0; border-radius: 0; background: transparent; box-shadow: none; padding: 0; margin: .25rem 0;\n }\n .chat-workspace .task-chat-agents > summary { min-height: 44px; cursor: pointer; font-size: .8125rem; color: var(--muted-foreground); }\n .chat-workspace .task-chat-agents p { margin: 0 0 .5rem; }\n .chat-workspace .decide-options .decide-option { border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; padding: .75rem 0; }\n .chat-workspace .chat-plan { padding: 1rem; margin-top: .5rem; }\n .chat-workspace .result-knowledge { margin-bottom: .5rem; }\n .chat-workspace .result-panel [data-result-view] > details { margin-block: 0; padding-block: 0; }\n .chat-workspace .result-panel [data-result-view] > details > summary { min-height: 44px; display: flex; align-items: center; }\n .chat-workspace .result-feedback-history > summary { min-height: 44px; }\n .chat-activity-details { border: 0; background: transparent; box-shadow: none; border-radius: 0; padding: 0; margin: 0; }\n .chat-activity-details > summary { min-height: 44px; display: flex; align-items: center; gap: .4rem; cursor: pointer; color: var(--muted-foreground); font-size: .75rem; }\n .chat-activity-details > summary::after { content: '\u2304'; }\n .chat-activity-details[open] > summary::after { transform: rotate(180deg); }\n .chat-activity-details .chat-activity { gap: .25rem .75rem; }\n .chat-activity-details .chat-activity span { border: 0; padding: 0; border-radius: 0; font: inherit; font-size: .75rem; }\n .chat-workspace .chat-message-foot { justify-content: flex-start; align-items: baseline; margin-top: .25rem; }\n .chat-activity-row { border: 0; background: transparent; box-shadow: none; padding: .5rem 0; min-height: 44px; gap: .65rem; }\n .chat-activity-row details { flex: 1; min-width: 0; border: 0; background: transparent; padding: 0; margin: 0; box-shadow: none; }\n .chat-activity-row summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; width: fit-content; font-size: .875rem; font-weight: 550; }\n .chat-activity-row summary::after { content: '\u2304'; margin-left: .65rem; color: var(--muted-foreground); }\n .chat-activity-row details[open] summary::after { transform: rotate(180deg); }\n .chat-activity-row .meta { padding-bottom: .5rem; overflow-wrap: anywhere; }\n .activity-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }\n .task-live-summary { border-bottom: 1px solid var(--border); margin-bottom: 1rem; padding-bottom: .5rem; }\n .task-live-summary .task-journey, .task-live-summary .task-control { border: 0; border-radius: 0; box-shadow: none; background: transparent; margin: 0; padding: .65rem 0; }\n .task-live-summary .task-journey h2 { font-size: 1rem; }\n .task-live-summary .agents-strip { margin: .4rem 0; }\n .chat-decisions .chat-section-head { margin-bottom: .5rem; }\n .chat-decisions h2 { font-size: .875rem; font-weight: 550; color: var(--muted-foreground); }\n .decision-context summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-size: .8125rem; color: var(--muted-foreground); }\n .decision-context { border: 0; padding: 0; margin: 0; background: transparent; box-shadow: none; }\n .decide-options { display: grid; gap: .5rem; }\n .decide-options .decide-option { margin: 0; padding: .65rem .75rem; border: 1px solid var(--border); border-radius: .75rem; background: var(--background); }\n .decide-options .decide-option .meta { display: block; margin-top: .3rem; overflow-wrap: anywhere; }\n .decide-options .decide-option button { min-height: 44px; max-width: 100%; white-space: normal; text-align: left; }\n .chat-completed { margin-top: 1rem; }\n .chat-completed h3 { font-size: .8125rem; font-weight: 550; margin: 0 0 .25rem; color: var(--muted-foreground); }\n .chat-completed-action { flex: none; font-size: .75rem; white-space: nowrap; color: var(--muted-foreground); }\n .chat-overview .chat-overview-stat { box-shadow: none; border: 0; background: transparent; border-radius: 0; }\n .chat-overview .chat-overview-stat + .chat-overview-stat { border-left: 1px solid var(--border); }\n .result-panel .result-request { border-top: 1px solid var(--border); padding-top: 1rem; }\n .result-panel .result-head h2 { color: var(--foreground); }\n .result-panel .result-request h3 { color: var(--foreground); font-size: .875rem; text-transform: none; letter-spacing: 0; }\n .result-panel .result-feedback-actions { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: .5rem; }\n .result-panel .result-feedback-actions > [data-request-changes] { order: 2; background: var(--foreground); color: var(--background); border-color: var(--foreground); box-shadow: none; }\n .result-panel .result-feedback-actions > button { width: auto; min-height: 44px; white-space: nowrap; }\n .result-panel .result-feedback-actions > .quiet { background: transparent; border-color: transparent; box-shadow: none; }\n .result-panel .result-feedback-actions > button:disabled { opacity: .45; cursor: default; }\n .result-panel .result-feedback-link { display: inline-flex; align-items: center; min-height: 44px; font-size: .8125rem; text-underline-offset: 3px; }\n .result-panel .result-pin > summary, .result-panel .result-notes > summary, .result-panel .result-details > summary { min-height: 44px; }\n .result-panel .diff-comment-form textarea { min-height: 80px; margin: 0; font-size: 1rem; }\n .result-panel .result-attention { background: transparent; border: 0; border-radius: 0; box-shadow: none; padding: 0; margin: .75rem 0; color: var(--foreground); }\n .result-panel .result-attention ul { margin: 0; padding-left: 1.15rem; }\n .result-panel .result-attention ul:has(> li:only-child) { list-style: none; padding-left: 0; }\n .result-panel .result-knowledge { border: 0; border-top: 1px solid var(--border); background: transparent; box-shadow: none; border-radius: 0; padding: .25rem 0; }\n .result-panel .revision-from-comments { border: 0; background: transparent; box-shadow: none; padding: .5rem 0; }\n .result-panel .result-pin summary { font-size: .8125rem; min-height: 44px; display: flex; align-items: center; cursor: pointer; }\n .result-panel .diff-comment-limit { font-size: .75rem; }\n .chat-main .chat-plan { box-shadow: none; }\n .proposal-review-notes { margin: .5rem 0; padding-left: 1.15rem; overflow-wrap: anywhere; }\n .proposal-review-notes li + li { margin-top: .5rem; }\n .proposal-actions .button-link, .proposal-actions button { min-height: 44px; white-space: nowrap; }\n .chat-stop-confirm > summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }\n .task-chat-title-line h1, .task-main-title, .resume-target, .resume-ceremony, .proposal-task_action, .chat-stop-confirm { overflow-wrap: anywhere; }\n .chat-main .chat-task-back { display: none; }\n .knowledge-library .knowledge-intro { padding: .5rem 0 1.25rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--border); }\n .knowledge-library .knowledge-instructions { line-height: 1.65; margin-bottom: .5rem; }\n .knowledge-library .knowledge-editor summary { width: fit-content; font-size: .875rem; font-weight: 550; }\n .knowledge-library .knowledge-editor, .knowledge-library > details { border: 0; border-bottom: 1px solid var(--border); border-radius: 0; box-shadow: none; background: transparent; padding: 0; }\n .knowledge-library .knowledge-editor { border-bottom: 0; }\n .knowledge-library .card { border: 0; border-bottom: 1px solid var(--border); border-radius: 0; padding: 0 0 .5rem; margin: 0; box-shadow: none; background: transparent; }\n .knowledge-library .card[open] { padding-bottom: 1rem; }\n .knowledge-library .card > summary { padding: .85rem 0; }\n @media (prefers-reduced-motion: no-preference) {\n .chat-activity-row .activity-dot { animation: quiet-activity 1.8s ease-in-out infinite; }\n .chat-completed .chat-overview-item { transition: background-color 140ms ease; }\n @keyframes quiet-activity { 50% { opacity: .35; } }\n }\n @media (max-width: 600px) {\n .chat-workspace .result-panel { background: transparent; border-radius: 0; }\n .chat-completed .chat-overview-item { align-items: flex-start; flex-wrap: wrap; gap: .35rem; }\n .chat-completed .chat-overview-copy { flex-basis: 65%; }\n .task-live-summary .task-journey { gap: .5rem; }\n }\n";
@@ -0,0 +1,135 @@
1
+ const escape = (value) => value.replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[char]));
2
+ /** Presentation only. These are recorded completions, not a claim that
3
+ * work happened since the user last visited, or that every result passed. */
4
+ export function completedWorkHtml(snapshot, projectLabels, assignments) {
5
+ const completed = snapshot.tasks.filter(task => assignments === undefined ? task.state === 'done'
6
+ && task.proofVerdict !== 'short' && task.proofVerdict !== 'refuted'
7
+ && !task.historyProblem && !task.otherActive?.length
8
+ && task.dispatch?.condition !== 'waiting' : assignments[task.id]?.state === 'complete').slice(0, 3);
9
+ if (!completed.length)
10
+ return '';
11
+ return `<section class="chat-completed" aria-label="Completed work"><h3>Completed work</h3>` + completed.map(task => {
12
+ return `<a class="chat-overview-item" href="/t/${encodeURIComponent(task.rootId ?? task.id)}"><span class="chat-overview-copy"><strong>${escape(task.title)}</strong><span>${escape(projectLabels[task.repoIndex] ?? `Project ${task.repoIndex + 1}`)}</span></span><span class="chat-completed-action">Open task <span aria-hidden="true">→</span></span></a>`;
13
+ }).join('') + '</section>';
14
+ }
15
+ /** Keep activity truthful: the turn's recorded step count is not a
16
+ * percentage or an invented tool phase. Billing detail stays available. */
17
+ export function chatWorkingHtml(input) {
18
+ return `<div class="chat-thinking chat-activity-row" id="latest" role="status"${input.keyed ? ' data-key="pending"' : ''}>` +
19
+ `<span class="activity-dot" aria-hidden="true"></span><details><summary>Working<span class="activity-ellipsis" aria-hidden="true">…</span></summary><p class="meta">${escape(input.details)}</p></details>` +
20
+ (input.stopForm ?? '') + '</div>';
21
+ }
22
+ /** Recorded activity is inspectable, not a row of performance badges. */
23
+ export function chatActivityDetailsHtml(activity) {
24
+ if (!activity)
25
+ return '';
26
+ return `<details class="chat-activity-details"><summary>Activity</summary><div class="chat-activity" aria-label="work performed">${activity.split(' · ').map(one => `<span>${escape(one)}</span>`).join('')}</div></details>`;
27
+ }
28
+ // Local primitives adapted from the researched interaction patterns. No
29
+ // imported kit, animation runtime, simulated progress, or changed authority.
30
+ export const CHAT_POLISH_CSS = `
31
+ /* Quiet workspace surfaces: color signals state, not an AI aesthetic. */
32
+ body { background: var(--background); }
33
+ .chat-workspace .chat-overview, .chat-workspace .chat-plan, .chat-workspace .result-panel,
34
+ .chat-workspace .decide-card { background: var(--card); box-shadow: none; }
35
+ .chat-workspace .result-panel { border-radius: .75rem; }
36
+ .chat-workspace .chat-empty::before { content: none; }
37
+ .chat-workspace .thread .msg.mate::before { background: var(--muted); box-shadow: none; border: 0; }
38
+ .chat-workspace .thread .msg.op { box-shadow: none; border: 0; }
39
+ .chat-workspace .completion-receipt { background: var(--card); box-shadow: none; }
40
+ .chat-workspace .completion-receipt::after { content: none; }
41
+ .chat-workspace .thread { min-height: 0; }
42
+ .chat-workspace .chat-turn-history { margin: 1rem 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; box-shadow: none; padding: 0; }
43
+ .chat-turn-history > summary { display: flex; align-items: center; gap: .75rem; min-height: 44px; cursor: pointer; font-size: .875rem; }
44
+ .chat-turn-history > summary .meta { margin-left: auto; }
45
+ .chat-turn-history .row { display: flex; flex-wrap: wrap; gap: .4rem; }
46
+ .chat-turn-history .row .right { float: none; margin-left: auto; }
47
+ .chat-workspace .task-live-summary { margin-bottom: .75rem; padding-bottom: .25rem; }
48
+ .chat-workspace .task-journey > details, .chat-workspace .result-feedback-history,
49
+ .chat-workspace .chat-limits, .chat-workspace .task-chat-agents {
50
+ border: 0; border-radius: 0; background: transparent; box-shadow: none; padding: 0; margin: .25rem 0;
51
+ }
52
+ .chat-workspace .task-chat-agents > summary { min-height: 44px; cursor: pointer; font-size: .8125rem; color: var(--muted-foreground); }
53
+ .chat-workspace .task-chat-agents p { margin: 0 0 .5rem; }
54
+ .chat-workspace .decide-options .decide-option { border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; padding: .75rem 0; }
55
+ .chat-workspace .chat-plan { padding: 1rem; margin-top: .5rem; }
56
+ .chat-workspace .result-knowledge { margin-bottom: .5rem; }
57
+ .chat-workspace .result-panel [data-result-view] > details { margin-block: 0; padding-block: 0; }
58
+ .chat-workspace .result-panel [data-result-view] > details > summary { min-height: 44px; display: flex; align-items: center; }
59
+ .chat-workspace .result-feedback-history > summary { min-height: 44px; }
60
+ .chat-activity-details { border: 0; background: transparent; box-shadow: none; border-radius: 0; padding: 0; margin: 0; }
61
+ .chat-activity-details > summary { min-height: 44px; display: flex; align-items: center; gap: .4rem; cursor: pointer; color: var(--muted-foreground); font-size: .75rem; }
62
+ .chat-activity-details > summary::after { content: '⌄'; }
63
+ .chat-activity-details[open] > summary::after { transform: rotate(180deg); }
64
+ .chat-activity-details .chat-activity { gap: .25rem .75rem; }
65
+ .chat-activity-details .chat-activity span { border: 0; padding: 0; border-radius: 0; font: inherit; font-size: .75rem; }
66
+ .chat-workspace .chat-message-foot { justify-content: flex-start; align-items: baseline; margin-top: .25rem; }
67
+ .chat-activity-row { border: 0; background: transparent; box-shadow: none; padding: .5rem 0; min-height: 44px; gap: .65rem; }
68
+ .chat-activity-row details { flex: 1; min-width: 0; border: 0; background: transparent; padding: 0; margin: 0; box-shadow: none; }
69
+ .chat-activity-row summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; width: fit-content; font-size: .875rem; font-weight: 550; }
70
+ .chat-activity-row summary::after { content: '⌄'; margin-left: .65rem; color: var(--muted-foreground); }
71
+ .chat-activity-row details[open] summary::after { transform: rotate(180deg); }
72
+ .chat-activity-row .meta { padding-bottom: .5rem; overflow-wrap: anywhere; }
73
+ .activity-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
74
+ .task-live-summary { border-bottom: 1px solid var(--border); margin-bottom: 1rem; padding-bottom: .5rem; }
75
+ .task-live-summary .task-journey, .task-live-summary .task-control { border: 0; border-radius: 0; box-shadow: none; background: transparent; margin: 0; padding: .65rem 0; }
76
+ .task-live-summary .task-journey h2 { font-size: 1rem; }
77
+ .task-live-summary .agents-strip { margin: .4rem 0; }
78
+ .chat-decisions .chat-section-head { margin-bottom: .5rem; }
79
+ .chat-decisions h2 { font-size: .875rem; font-weight: 550; color: var(--muted-foreground); }
80
+ .decision-context summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-size: .8125rem; color: var(--muted-foreground); }
81
+ .decision-context { border: 0; padding: 0; margin: 0; background: transparent; box-shadow: none; }
82
+ .decide-options { display: grid; gap: .5rem; }
83
+ .decide-options .decide-option { margin: 0; padding: .65rem .75rem; border: 1px solid var(--border); border-radius: .75rem; background: var(--background); }
84
+ .decide-options .decide-option .meta { display: block; margin-top: .3rem; overflow-wrap: anywhere; }
85
+ .decide-options .decide-option button { min-height: 44px; max-width: 100%; white-space: normal; text-align: left; }
86
+ .chat-completed { margin-top: 1rem; }
87
+ .chat-completed h3 { font-size: .8125rem; font-weight: 550; margin: 0 0 .25rem; color: var(--muted-foreground); }
88
+ .chat-completed-action { flex: none; font-size: .75rem; white-space: nowrap; color: var(--muted-foreground); }
89
+ .chat-overview .chat-overview-stat { box-shadow: none; border: 0; background: transparent; border-radius: 0; }
90
+ .chat-overview .chat-overview-stat + .chat-overview-stat { border-left: 1px solid var(--border); }
91
+ .result-panel .result-request { border-top: 1px solid var(--border); padding-top: 1rem; }
92
+ .result-panel .result-head h2 { color: var(--foreground); }
93
+ .result-panel .result-request h3 { color: var(--foreground); font-size: .875rem; text-transform: none; letter-spacing: 0; }
94
+ .result-panel .result-feedback-actions { display: flex; justify-content: flex-end; align-items: center; flex-wrap: wrap; gap: .5rem; }
95
+ .result-panel .result-feedback-actions > [data-request-changes] { order: 2; background: var(--foreground); color: var(--background); border-color: var(--foreground); box-shadow: none; }
96
+ .result-panel .result-feedback-actions > button { width: auto; min-height: 44px; white-space: nowrap; }
97
+ .result-panel .result-feedback-actions > .quiet { background: transparent; border-color: transparent; box-shadow: none; }
98
+ .result-panel .result-feedback-actions > button:disabled { opacity: .45; cursor: default; }
99
+ .result-panel .result-feedback-link { display: inline-flex; align-items: center; min-height: 44px; font-size: .8125rem; text-underline-offset: 3px; }
100
+ .result-panel .result-pin > summary, .result-panel .result-notes > summary, .result-panel .result-details > summary { min-height: 44px; }
101
+ .result-panel .diff-comment-form textarea { min-height: 80px; margin: 0; font-size: 1rem; }
102
+ .result-panel .result-attention { background: transparent; border: 0; border-radius: 0; box-shadow: none; padding: 0; margin: .75rem 0; color: var(--foreground); }
103
+ .result-panel .result-attention ul { margin: 0; padding-left: 1.15rem; }
104
+ .result-panel .result-attention ul:has(> li:only-child) { list-style: none; padding-left: 0; }
105
+ .result-panel .result-knowledge { border: 0; border-top: 1px solid var(--border); background: transparent; box-shadow: none; border-radius: 0; padding: .25rem 0; }
106
+ .result-panel .revision-from-comments { border: 0; background: transparent; box-shadow: none; padding: .5rem 0; }
107
+ .result-panel .result-pin summary { font-size: .8125rem; min-height: 44px; display: flex; align-items: center; cursor: pointer; }
108
+ .result-panel .diff-comment-limit { font-size: .75rem; }
109
+ .chat-main .chat-plan { box-shadow: none; }
110
+ .proposal-review-notes { margin: .5rem 0; padding-left: 1.15rem; overflow-wrap: anywhere; }
111
+ .proposal-review-notes li + li { margin-top: .5rem; }
112
+ .proposal-actions .button-link, .proposal-actions button { min-height: 44px; white-space: nowrap; }
113
+ .chat-stop-confirm > summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }
114
+ .task-chat-title-line h1, .task-main-title, .resume-target, .resume-ceremony, .proposal-task_action, .chat-stop-confirm { overflow-wrap: anywhere; }
115
+ .chat-main .chat-task-back { display: none; }
116
+ .knowledge-library .knowledge-intro { padding: .5rem 0 1.25rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--border); }
117
+ .knowledge-library .knowledge-instructions { line-height: 1.65; margin-bottom: .5rem; }
118
+ .knowledge-library .knowledge-editor summary { width: fit-content; font-size: .875rem; font-weight: 550; }
119
+ .knowledge-library .knowledge-editor, .knowledge-library > details { border: 0; border-bottom: 1px solid var(--border); border-radius: 0; box-shadow: none; background: transparent; padding: 0; }
120
+ .knowledge-library .knowledge-editor { border-bottom: 0; }
121
+ .knowledge-library .card { border: 0; border-bottom: 1px solid var(--border); border-radius: 0; padding: 0 0 .5rem; margin: 0; box-shadow: none; background: transparent; }
122
+ .knowledge-library .card[open] { padding-bottom: 1rem; }
123
+ .knowledge-library .card > summary { padding: .85rem 0; }
124
+ @media (prefers-reduced-motion: no-preference) {
125
+ .chat-activity-row .activity-dot { animation: quiet-activity 1.8s ease-in-out infinite; }
126
+ .chat-completed .chat-overview-item { transition: background-color 140ms ease; }
127
+ @keyframes quiet-activity { 50% { opacity: .35; } }
128
+ }
129
+ @media (max-width: 600px) {
130
+ .chat-workspace .result-panel { background: transparent; border-radius: 0; }
131
+ .chat-completed .chat-overview-item { align-items: flex-start; flex-wrap: wrap; gap: .35rem; }
132
+ .chat-completed .chat-overview-copy { flex-basis: 65%; }
133
+ .task-live-summary .task-journey { gap: .5rem; }
134
+ }
135
+ `;
@@ -0,0 +1,46 @@
1
+ import type { Store } from "./store.js";
2
+ import type { VerifiedApprover } from "./principal.js";
3
+ export type ReviewSnapshot = {
4
+ task: string;
5
+ root: string;
6
+ execution: string;
7
+ run: number;
8
+ artifact: number;
9
+ sha: string;
10
+ source: string;
11
+ title: string;
12
+ notes: {
13
+ id: number;
14
+ note: string;
15
+ path: string | null;
16
+ line: number | null;
17
+ }[];
18
+ };
19
+ type Problem = {
20
+ ok: false;
21
+ message: string;
22
+ };
23
+ /** Read precisely the result named, never silently substitute a newer version. */
24
+ export declare function readChatResult(store: Store, who: VerifiedApprover, evidenceRoot: string | undefined, task: string, run?: number): {
25
+ ok: true;
26
+ snapshot: ReviewSnapshot;
27
+ } | Problem;
28
+ export type ReviewRequest = {
29
+ snapshot: ReviewSnapshot;
30
+ operation: "note" | "revise";
31
+ note: string | null;
32
+ path: string | null;
33
+ line: number | null;
34
+ notes: number[];
35
+ };
36
+ export declare function reviewInputProblem(note: string | null, path: string | null, line: number | null): string | null;
37
+ /** Chat and the result form write the same comments and call the same revision service.
38
+ * A failed combined note+revision rolls back the note too; no half-completed action.
39
+ */
40
+ export declare function applyChatReview(store: Store, who: VerifiedApprover, evidenceRoot: string, request: ReviewRequest, now: Date, allowMode: boolean): {
41
+ ok: true;
42
+ taskId: string;
43
+ run: number;
44
+ said: string;
45
+ } | Problem;
46
+ export {};
@@ -0,0 +1,98 @@
1
+ import { readVerifiedArtifact } from "./evidence.js";
2
+ import { hasForbiddenControls, validateNote } from "./decision.js";
3
+ import { isRevisionFeedback, revisionSourceOf } from "./result-review.js";
4
+ import { createResultRevision } from "./result-actions.js";
5
+ /** Read precisely the result named, never silently substitute a newer version. */
6
+ export function readChatResult(store, who, evidenceRoot, task, run) {
7
+ const ref = store.lookupRef(task);
8
+ if (ref?.repo == null || !who.repos.includes(ref.repo))
9
+ return { ok: false, message: "That task is not in your projects." };
10
+ const family = store.taskFamilyOf(task, who.repos, false);
11
+ if (family === null || family.problem !== null)
12
+ return { ok: false, message: "This task's revision history needs repair." };
13
+ const found = run === undefined
14
+ ? store.runsFor(ref.id).find(one => (one.role === "builder" || one.role === "repair") && one.outcome !== null)
15
+ : store.getRun(run);
16
+ if (found == null || found.taskRef !== ref.id || found.outcome === null)
17
+ return { ok: false, message: "There is no finished result for that version yet." };
18
+ const artifact = store.artifactsFor(found.id).find(one => one.kind === "terminal-diff");
19
+ if (artifact === undefined || evidenceRoot === undefined)
20
+ return { ok: false, message: "The saved changes are unavailable. Feedback has not been added." };
21
+ const proven = readVerifiedArtifact(evidenceRoot, artifact);
22
+ if (!proven.ok)
23
+ return { ok: false, message: "The saved changes could not be verified. Restore the result before adding feedback." };
24
+ return { ok: true, snapshot: {
25
+ task, root: family.root.id, execution: family.current.id, run: found.id,
26
+ artifact: artifact.id, sha: artifact.sha256, source: revisionSourceOf(store.getScope(task)?.digest ?? null),
27
+ title: store.getTask(task)?.title ?? task,
28
+ notes: store.liveDiffComments(found.id).filter(isRevisionFeedback).map(one => ({ id: one.id, note: one.note, path: one.path, line: one.line })),
29
+ } };
30
+ }
31
+ export function reviewInputProblem(note, path, line) {
32
+ if (note !== null) {
33
+ const valid = validateNote(note);
34
+ if (!valid.ok)
35
+ return valid.problem;
36
+ }
37
+ if (path !== null && (path.length > 300 || path.trim() === "" || hasForbiddenControls(path)))
38
+ return "Choose a valid file path.";
39
+ if (line !== null && (path === null || !Number.isInteger(line) || line < 1 || line > 1_000_000))
40
+ return "Choose a file and a valid line number.";
41
+ if (note === null && (path !== null || line !== null))
42
+ return "Write a note before attaching it to a file.";
43
+ return null;
44
+ }
45
+ /** Chat and the result form write the same comments and call the same revision service.
46
+ * A failed combined note+revision rolls back the note too; no half-completed action.
47
+ */
48
+ export function applyChatReview(store, who, evidenceRoot, request, now, allowMode) {
49
+ try {
50
+ return store.transact(() => store.savepoint(() => {
51
+ const fail = (message) => { throw new ReviewRefusal(message); };
52
+ const { snapshot: saw, operation, note, path, line, notes } = request;
53
+ const problem = reviewInputProblem(note, path, line);
54
+ if (problem !== null)
55
+ return fail(problem);
56
+ const current = readChatResult(store, who, evidenceRoot, saw.task, saw.run);
57
+ if (!current.ok)
58
+ return fail(current.message);
59
+ const live = current.snapshot;
60
+ if (live.execution !== saw.execution || live.source !== saw.source || live.artifact !== saw.artifact || live.sha !== saw.sha)
61
+ return fail("This result changed. Review it again before confirming.");
62
+ if (operation === "revise" && saw.execution !== saw.task)
63
+ return fail("A newer revision is current. Review that version before requesting changes.");
64
+ if (!Array.isArray(notes) || new Set(notes).size !== notes.length || notes.some(id => !saw.notes.some(n => n.id === id) || !live.notes.some(n => n.id === id)))
65
+ return fail("Some feedback changed or was already used. Review it again.");
66
+ if (operation === "note" && (note === null || notes.length > 0))
67
+ return fail("A saved note needs feedback text and cannot consume other notes.");
68
+ const batch = [...notes].sort((a, b) => a - b);
69
+ if (note !== null) {
70
+ const id = store.addDiffComment({ artifactId: live.artifact, runId: live.run, path, line, note, author: who.name }, now);
71
+ if (id === null)
72
+ return fail("The note could not be saved.");
73
+ batch.push(id);
74
+ }
75
+ if (operation === "note")
76
+ return { ok: true, taskId: live.root, run: live.run, said: "Feedback saved. No work started." };
77
+ if (batch.length === 0)
78
+ return fail("Add feedback or select saved notes before requesting changes.");
79
+ const result = createResultRevision(store, evidenceRoot, {
80
+ run: live.run, batch: batch.join(","), source: live.source, actor: who.name, repos: who.repos, allowMode,
81
+ }, now);
82
+ if (!result.ok)
83
+ return fail(result.message);
84
+ const scope = store.getScope(result.id);
85
+ const approved = scope?.approvedDigest != null && scope.approvedDigest === scope.digest;
86
+ const planning = store.lookupRef(result.id)?.plan === "requested";
87
+ return { ok: true, taskId: result.id, run: live.run,
88
+ said: approved ? "Revision created under your automatic approval settings." : planning ? "Revision created. Updating the plan with your notes; you'll approve it next." : "Revision created. Review and approve it to start." };
89
+ }));
90
+ }
91
+ catch (error) {
92
+ if (error instanceof ReviewRefusal)
93
+ return { ok: false, message: error.message };
94
+ throw error;
95
+ }
96
+ }
97
+ class ReviewRefusal extends Error {
98
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Team conversations inside any chat transport: a group or channel follows
3
+ * one team conversation, a private chat may select one, and messages a
4
+ * paired teammate sends there are saved through the same team operation
5
+ * the browser and CLI use. The transport supplies identity (who sent it),
6
+ * where rooms are recorded, and how to reply; nothing here runs a model.
7
+ */
8
+ import type { Store } from "./store.js";
9
+ import { TeamLeads } from "./team-leads.js";
10
+ import { type PhoneLink } from "./chat-channel.js";
11
+ export type RoomCommand = {
12
+ kind: "list";
13
+ } | {
14
+ kind: "select";
15
+ index: number;
16
+ } | {
17
+ kind: "off";
18
+ };
19
+ /** `/team` lists, `/team <n>` chooses, `/team off` (or `private`) leaves.
20
+ * The bare word works too, because Slack and Discord keep unregistered
21
+ * slash text for themselves. Any other text is not ours. */
22
+ export declare function roomCommand(text: string): RoomCommand | null;
23
+ export declare const PAIR_FIRST = "Pair your account first: open Settings in Toolroll, choose this chat service, and send the code here in a private chat.";
24
+ /** A room is a grant from one exact pairing (`binding`): its delivery and its
25
+ * sends are rechecked against that person's current membership. */
26
+ export type Room = {
27
+ id: number;
28
+ chatId: string;
29
+ kind: "group" | "private";
30
+ conversation: string;
31
+ boundBy: string;
32
+ binding: number;
33
+ cursor: number;
34
+ };
35
+ /** Where a transport records which chat follows which conversation. */
36
+ export type RoomBackend = {
37
+ room(chatId: string): Room | null;
38
+ bind(args: {
39
+ chatId: string;
40
+ kind: "group" | "private";
41
+ conversation: string;
42
+ by: string;
43
+ binding: number;
44
+ }): {
45
+ ok: true;
46
+ } | {
47
+ ok: false;
48
+ reason: "group-taken";
49
+ };
50
+ /** The pairing a room was granted from, if it is still live. */
51
+ grant(binding: number): {
52
+ approver: string;
53
+ generation: number;
54
+ chatId: string;
55
+ } | null;
56
+ unbind(chatId: string, by: string): boolean;
57
+ };
58
+ export type RoomCounts = {
59
+ ignored: number;
60
+ chatQueued?: number;
61
+ chatRefused?: number;
62
+ statusReplies?: number;
63
+ };
64
+ export type RoomInbound = {
65
+ store: Store;
66
+ /** The transport's request-id prefix, e.g. "telegram", "slack". */
67
+ channel: string;
68
+ backend: RoomBackend;
69
+ chatId: string;
70
+ isGroup: boolean;
71
+ /** The paired sender, already proved by the transport; null when unpaired. */
72
+ sender: {
73
+ approver: string;
74
+ generation: number;
75
+ binding: number;
76
+ } | null;
77
+ /** A transport-unique key for this inbound message (update id, event id). */
78
+ updateKey: string;
79
+ text: string;
80
+ /** The enrolled ceiling; null when unreadable. */
81
+ projects: readonly string[] | null;
82
+ origin: string | null;
83
+ now: Date;
84
+ report: RoomCounts;
85
+ /** Queue one reply into the chat the message came from. */
86
+ say: (text: string, link?: PhoneLink) => void;
87
+ };
88
+ export declare function teamRequestId(channel: string, chatId: string, updateKey: string): string;
89
+ export declare function conversationRow(store: Store, id: string): {
90
+ conversation: string;
91
+ title: string;
92
+ thread: number;
93
+ lead: string;
94
+ leadName: string;
95
+ visibility: string;
96
+ } | null;
97
+ /**
98
+ * Handle one inbound message that belongs to the team layer. Returns true
99
+ * when it was consumed here (a `/team` command in any chat, any message in
100
+ * a followed room, or a private message while a conversation is selected);
101
+ * false hands the message to the transport's personal path untouched.
102
+ */
103
+ export declare function applyRoomInbound(input: RoomInbound): boolean;
104
+ /** Whether the pairing a room was granted from still holds: live, the same
105
+ * person, still a manager of a team conversation for a group (a viewer for a
106
+ * private selection). */
107
+ export declare function roomGrantAllowed(store: Store, domain: TeamLeads, backend: RoomBackend, room: Room): boolean;
108
+ export declare function teamDomain(store: Store, projects: readonly string[] | null): TeamLeads;
109
+ export type RoomMessage = {
110
+ id: number;
111
+ role: "assistant" | "operator";
112
+ text: string;
113
+ turn: number | null;
114
+ author: string | null;
115
+ requestId: string | null;
116
+ status: string | null;
117
+ };
118
+ /** The conversation messages a room has not received yet, oldest first. */
119
+ export declare function roomMessagesAfter(store: Store, thread: number, cursor: number, limit?: number): RoomMessage[];
120
+ /** What a room shows for one message: the lead's reply as is, a teammate's message with its author, this room's own messages and cancelled ones not at all. */
121
+ export declare function roomMessageText(message: RoomMessage, channel: string, chatId: string): string | null;
122
+ /** Whose binding a room card rides: the person the lead was answering, else any paired participant. */
123
+ export declare function roomCardApprover(store: Store, conversation: string, turn: number, paired: readonly string[]): string | null;