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,64 @@
1
+ /**
2
+ * Turning snapshots into something worth reading.
3
+ *
4
+ * Pure string building. The clock is a parameter rather than a call, so the
5
+ * output is deterministic under test and the same report can be re-rendered
6
+ * later against the time it was taken.
7
+ */
8
+ import type { RepoSnapshot } from "./discover.js";
9
+ import type { TrackingState } from "./git.js";
10
+ import { type BackendKind, type Detection } from "./graph.js";
11
+ import { type Pull } from "./pulls.js";
12
+ import type { RemoteState } from "./remote.js";
13
+ export type ReportOptions = {
14
+ now: Date;
15
+ /** Where the scan looked, used only to make the empty result actionable. */
16
+ roots?: readonly string[];
17
+ maxBranches?: number;
18
+ /**
19
+ * Pull requests and issues per repository path. Undefined means they were
20
+ * never read — which the report says out loud rather than showing zeroes,
21
+ * because "none" and "did not look" are different answers.
22
+ */
23
+ remote?: RemoteMap;
24
+ };
25
+ export type RemoteMap = ReadonlyMap<string, RemoteState>;
26
+ export declare const DEFAULT_MAX_BRANCHES = 6;
27
+ export declare function formatAge(iso: string, now: Date): string;
28
+ export declare function formatTrack(track: TrackingState): string;
29
+ export declare function renderReport(snapshots: readonly RepoSnapshot[], options: ReportOptions): string;
30
+ /** One repository's open pull requests, as read. */
31
+ export type PullGroup = {
32
+ repo: string;
33
+ pulls: readonly Pull[];
34
+ problems: readonly string[];
35
+ };
36
+ export type PullsOptions = {
37
+ now: Date;
38
+ staleDays?: number;
39
+ };
40
+ /**
41
+ * How long since anything happened. Phrased as idleness rather than age
42
+ * because a pull request opened in May and discussed yesterday is not old in
43
+ * any sense the operator cares about.
44
+ */
45
+ export declare function formatIdle(iso: string, now: Date): string;
46
+ /**
47
+ * Grouped by whose move it is, because that is the only question being asked.
48
+ * Drafts and running builds are counted but not listed — nobody is blocked on
49
+ * them, and a report that lists everything is the attention problem it was
50
+ * written to solve.
51
+ */
52
+ export declare function renderPulls(groups: readonly PullGroup[], options: PullsOptions): string;
53
+ /**
54
+ * What work graph is already here.
55
+ *
56
+ * The recommended backend is marked with a pointer and nothing else is, because
57
+ * the one thing this report must not read as is a menu of things already
58
+ * switched on. Every line ends by saying what is *not* authorized, since
59
+ * detection is not authorization and a report that omitted that would be
60
+ * inviting exactly the wrong conclusion.
61
+ */
62
+ export declare function renderGraph(detections: readonly Detection[], options?: {
63
+ enrolled?: BackendKind;
64
+ }): string;
package/dist/render.js ADDED
@@ -0,0 +1,587 @@
1
+ /**
2
+ * Turning snapshots into something worth reading.
3
+ *
4
+ * Pure string building. The clock is a parameter rather than a call, so the
5
+ * output is deterministic under test and the same report can be re-rendered
6
+ * later against the time it was taken.
7
+ */
8
+ import { chooseBackend, setupOptions, LABELS as GRAPH_LABELS, } from "./graph.js";
9
+ import { classify, describe as describePull, idleDays, DEFAULT_STALE_DAYS, } from "./pulls.js";
10
+ export const DEFAULT_MAX_BRANCHES = 6;
11
+ const MINUTE = 60_000;
12
+ const HOUR = 60 * MINUTE;
13
+ const DAY = 24 * HOUR;
14
+ const MONTH = 30 * DAY;
15
+ const YEAR = 365 * DAY;
16
+ const INDENT = " ";
17
+ const GUTTER = 2;
18
+ /**
19
+ * Columns size themselves to the content, within bounds. Fixed widths either
20
+ * waste half the terminal on short names or let one long branch name shove
21
+ * every other column out of alignment — and truncating is not an option when
22
+ * the name is the thing you are about to type.
23
+ */
24
+ const MIN_NAME_WIDTH = 20;
25
+ const MAX_NAME_WIDTH = 44;
26
+ const MIN_STATE_WIDTH = 12;
27
+ const MAX_STATE_WIDTH = 20;
28
+ export function formatAge(iso, now) {
29
+ const then = Date.parse(iso);
30
+ if (Number.isNaN(then))
31
+ return "unknown";
32
+ // Clocks disagree across machines; a branch from the future is just recent.
33
+ const elapsed = Math.max(0, now.getTime() - then);
34
+ if (elapsed < MINUTE)
35
+ return "just now";
36
+ if (elapsed < HOUR)
37
+ return `${Math.floor(elapsed / MINUTE)}m ago`;
38
+ if (elapsed < DAY)
39
+ return `${Math.floor(elapsed / HOUR)}h ago`;
40
+ if (elapsed < MONTH)
41
+ return `${Math.floor(elapsed / DAY)}d ago`;
42
+ if (elapsed < YEAR)
43
+ return `${Math.floor(elapsed / MONTH)}mo ago`;
44
+ return `${Math.floor(elapsed / YEAR)}y ago`;
45
+ }
46
+ export function formatTrack(track) {
47
+ if (track.gone)
48
+ return "upstream gone";
49
+ const parts = [];
50
+ if (track.ahead > 0)
51
+ parts.push(`ahead ${track.ahead}`);
52
+ if (track.behind > 0)
53
+ parts.push(`behind ${track.behind}`);
54
+ return parts.join(", ");
55
+ }
56
+ /** A branch is in flight when it has diverged from its upstream or lost it. */
57
+ function isInFlight(branch) {
58
+ return branch.track.ahead > 0 || branch.track.behind > 0 || branch.track.gone;
59
+ }
60
+ export function renderReport(snapshots, options) {
61
+ const { now, roots = [], maxBranches = DEFAULT_MAX_BRANCHES, remote } = options;
62
+ if (snapshots.length === 0)
63
+ return renderEmpty(roots);
64
+ const sections = [...snapshots]
65
+ .sort(byRecency)
66
+ .map(snapshot => composeSection(snapshot, now, maxBranches, remote))
67
+ .filter(rows => rows.length > 0);
68
+ const totals = countInFlight(snapshots, remote);
69
+ const withheld = renderWithheld(snapshots, remote);
70
+ // "Nothing in flight" is a claim about what was looked at. If the budget ran
71
+ // out before some repositories were asked, saying it flatly would be the
72
+ // silence this tool exists to break — so the withheld line goes here too,
73
+ // and it is the whole point of this branch rather than a footnote.
74
+ if (sections.length === 0) {
75
+ return [...renderNothingInFlight(snapshots.length, remote, withheld.length > 0), ...withheld]
76
+ .join("\n")
77
+ .trimEnd();
78
+ }
79
+ const rows = sections.flat();
80
+ const nameWidth = widthOf(rows, row => row.indent.length + row.name.length, MIN_NAME_WIDTH, MAX_NAME_WIDTH);
81
+ const stateWidth = widthOf(rows, row => row.state.length, MIN_STATE_WIDTH, MAX_STATE_WIDTH);
82
+ const unmeasured = snapshots.filter(snapshot => !snapshot.hasTracking).length;
83
+ const body = sections.map(section => section.map(row => renderRow(row, nameWidth, stateWidth)).join("\n"));
84
+ return [renderHeader(totals, snapshots.length, unmeasured), "", ...body, ...withheld]
85
+ .join("\n")
86
+ .trimEnd();
87
+ }
88
+ /**
89
+ * One repository's block, from both halves.
90
+ *
91
+ * The local rows already end in a blank separator, so remote rows are spliced
92
+ * in ahead of it rather than appended after — otherwise a repository's pull
93
+ * requests would appear under the gap, reading as though they belonged to the
94
+ * repository below.
95
+ */
96
+ function composeSection(snapshot, now, maxBranches, remote) {
97
+ const local = collectRows(snapshot, now, maxBranches);
98
+ const fromRemote = collectRemoteRows(snapshot, remote, now);
99
+ if (fromRemote.length === 0)
100
+ return local;
101
+ if (local.length === 0) {
102
+ // Nothing local to say, but a pull request waiting is still news, and the
103
+ // repository needs a heading of its own to be attributed to.
104
+ return [
105
+ { indent: "", name: snapshot.name, state: snapshot.head ?? "detached", tail: "" },
106
+ ...fromRemote,
107
+ { indent: "", name: "", state: "", tail: "" },
108
+ ];
109
+ }
110
+ return [...local.slice(0, -1), ...fromRemote, local[local.length - 1]];
111
+ }
112
+ function countInFlight(snapshots, remote) {
113
+ const branches = snapshots.reduce((total, snapshot) => total + (snapshot.hasTracking ? snapshot.branches.filter(isInFlight).length : 0), 0);
114
+ let pulls = 0;
115
+ let issues = 0;
116
+ for (const snapshot of snapshots) {
117
+ const state = remote?.get(snapshot.path);
118
+ if (state === undefined)
119
+ continue;
120
+ pulls += state.pulls.length;
121
+ issues += state.issues.length;
122
+ }
123
+ return { branches, pulls, issues, remoteRead: remote !== undefined };
124
+ }
125
+ /**
126
+ * Pull requests waiting on somebody, and a count of open issues.
127
+ *
128
+ * Pull requests get a row each because a pull request that nobody has looked at
129
+ * is the single most actionable thing this report can surface — the case that
130
+ * motivated the tool was two of them sitting green and ignored for two months.
131
+ * Issues get a count: a hundred open issues is context, not a to-do list, and
132
+ * printing all of them would bury everything above.
133
+ */
134
+ function collectRemoteRows(snapshot, remote, now) {
135
+ const state = remote?.get(snapshot.path);
136
+ if (state === undefined || state.skipped)
137
+ return [];
138
+ const rows = [];
139
+ const waiting = state.pulls.filter(pull => {
140
+ const attention = classify(pull);
141
+ return attention === "human" || attention === "agent";
142
+ });
143
+ for (const pull of waiting) {
144
+ rows.push({
145
+ indent: INDENT,
146
+ name: `#${pull.number} ${pull.branch}`,
147
+ state: describePull(pull),
148
+ tail: formatIdle(pull.updatedAt, now),
149
+ });
150
+ }
151
+ if (state.issues.length > 0) {
152
+ rows.push({
153
+ indent: INDENT,
154
+ name: `${plural(state.issues.length, "issue", "issues")} open`,
155
+ state: "",
156
+ tail: "",
157
+ });
158
+ }
159
+ for (const problem of state.problems) {
160
+ rows.push({ indent: INDENT, name: `! ${problem}`, state: "", tail: "" });
161
+ }
162
+ return rows;
163
+ }
164
+ /** What the budget did not reach, named rather than silently missing. */
165
+ function renderWithheld(snapshots, remote) {
166
+ if (remote === undefined)
167
+ return [];
168
+ const skipped = snapshots.filter(snapshot => remote.get(snapshot.path)?.skipped === true);
169
+ if (skipped.length === 0)
170
+ return [];
171
+ // Named, not counted. "3 repositories were not checked" leaves an operator
172
+ // to work out which three, and the whole reason this line exists is that a
173
+ // repository nobody looked at must not be mistaken for one with nothing in
174
+ // it. Long lists are truncated, because at that point the budget is the
175
+ // story rather than the names.
176
+ const shown = skipped.slice(0, MAX_SKIPPED_NAMED).map(snapshot => snapshot.name);
177
+ const rest = skipped.length - shown.length;
178
+ const names = rest > 0 ? `${shown.join(", ")} and ${rest} more` : shown.join(", ");
179
+ return [
180
+ "",
181
+ `Not checked for pull requests or issues: ${names}.`,
182
+ "The network budget ran out. `toolroll pulls` reads them without one.",
183
+ ];
184
+ }
185
+ function renderRow(row, nameWidth, stateWidth) {
186
+ const name = pad(`${row.indent}${row.name}`, nameWidth);
187
+ return `${name}${pad(row.state, stateWidth)}${row.tail}`.trimEnd();
188
+ }
189
+ /**
190
+ * Only rows that carry a later column get a vote on how wide the earlier ones
191
+ * are. A free-text problem line has nothing to its right, so letting it size
192
+ * the table would push every real column off to the horizon.
193
+ */
194
+ function widthOf(rows, measure, min, max) {
195
+ const widest = rows
196
+ .filter(row => row.state !== "" || row.tail !== "")
197
+ .reduce((longest, row) => Math.max(longest, measure(row)), 0);
198
+ return Math.min(max, Math.max(min, widest + GUTTER));
199
+ }
200
+ /**
201
+ * The one line the milestone is actually about: every branch, pull request and
202
+ * issue in flight, counted together.
203
+ *
204
+ * Zeroes are dropped rather than printed. "3 branches, 0 pull requests, 0
205
+ * issues" reads as a system reporting on itself; "3 branches" reads as an
206
+ * answer. But a zero that was never *looked* for is different from one that
207
+ * was, which is why the remote counts only appear when the remote read
208
+ * actually happened.
209
+ */
210
+ function renderHeader(totals, repoCount, unmeasured) {
211
+ const parts = [plural(totals.branches, "branch", "branches")];
212
+ if (totals.remoteRead && totals.pulls > 0) {
213
+ parts.push(plural(totals.pulls, "pull request", "pull requests"));
214
+ }
215
+ if (totals.remoteRead && totals.issues > 0) {
216
+ parts.push(plural(totals.issues, "issue", "issues"));
217
+ }
218
+ const repos = plural(repoCount, "repository", "repositories");
219
+ const headline = `${joinWords(parts)} in flight across ${repos}`;
220
+ // A count that quietly excludes repositories it could not measure is a lie
221
+ // of omission. The remedy is named once here rather than on every repo — and
222
+ // it is printed, never run, because it writes to someone else's .git.
223
+ if (unmeasured === 0)
224
+ return headline;
225
+ const which = unmeasured === 1 ? "1 repository is" : `${unmeasured} repositories are`;
226
+ return [
227
+ headline,
228
+ `${which} listed by recency: ahead/behind was too slow to compute.`,
229
+ "`git commit-graph write --reachable` in it makes this permanent —",
230
+ "it writes to .git, so run it yourself.",
231
+ ].join("\n");
232
+ }
233
+ /** Repositories were found and read; none of them had anything outstanding. */
234
+ function renderNothingInFlight(repoCount, remote, anyWithheld) {
235
+ return [
236
+ anyWithheld
237
+ ? `Nothing in flight across the ${plural(repoCount, "repository", "repositories")} that were checked.`
238
+ : `Nothing in flight across ${plural(repoCount, "repository", "repositories")}.`,
239
+ remote === undefined
240
+ ? "Every branch is level with its upstream."
241
+ : "Every branch is level with its upstream, and nothing is waiting on a person.",
242
+ "",
243
+ "Uncommitted work is not counted here — add --dirty to read working trees.",
244
+ // Said in addition to, not instead of: an operator who ran --local has two
245
+ // things missing from this answer, and hearing about one of them would
246
+ // leave them believing the other was checked.
247
+ ...(remote === undefined
248
+ ? ["Pull requests and issues were not read — drop --local to include them."]
249
+ : []),
250
+ ];
251
+ }
252
+ /** "a, b and c" — the report is prose at this point, not a field list. */
253
+ function joinWords(parts) {
254
+ if (parts.length <= 1)
255
+ return parts[0] ?? "";
256
+ return `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}`;
257
+ }
258
+ function renderEmpty(roots) {
259
+ const where = roots.length > 0 ? ` under ${roots.join(", ")}` : "";
260
+ return [
261
+ `No git repositories found${where}.`,
262
+ "",
263
+ "Point it somewhere else with `toolroll <path>`, or go deeper with",
264
+ "`toolroll --depth 8`. Nothing has been written or configured.",
265
+ ].join("\n");
266
+ }
267
+ /** Past this, the budget is the story rather than which repositories missed out. */
268
+ const MAX_SKIPPED_NAMED = 6;
269
+ /** Long enough to catch work you have put down, short enough to exclude archaeology. */
270
+ const RECENT_WINDOW = 30 * DAY;
271
+ /**
272
+ * Which branches to show. With tracking, the ones that have diverged. Without
273
+ * it, recency is the only signal left — filtering on ahead/behind that was
274
+ * never computed would discard every branch and leave the repository
275
+ * represented by a complaint, and listing all of them buries the report under
276
+ * whichever repo happens to have the most abandoned branches.
277
+ */
278
+ function selectBranches(snapshot, now) {
279
+ const byRecent = [...snapshot.branches].sort(byCommittedAtDesc);
280
+ if (snapshot.hasTracking)
281
+ return { shown: byRecent.filter(isInFlight), note: null };
282
+ const recent = byRecent.filter(branch => isWithinWindow(branch.committedAt, now));
283
+ if (recent.length > 0)
284
+ return { shown: recent, note: null };
285
+ const count = plural(snapshot.branches.length, "branch", "branches");
286
+ return { shown: [], note: `${count}, none touched in 30 days` };
287
+ }
288
+ function isWithinWindow(iso, now) {
289
+ const then = Date.parse(iso);
290
+ return !Number.isNaN(then) && now.getTime() - then < RECENT_WINDOW;
291
+ }
292
+ function collectRows(snapshot, now, maxBranches) {
293
+ const { shown: selected, note } = selectBranches(snapshot, now);
294
+ // A quiet, clean repo with nothing outstanding is not worth a line.
295
+ if (selected.length === 0 &&
296
+ note === null &&
297
+ !snapshot.dirtyFiles &&
298
+ snapshot.problems.length === 0) {
299
+ return [];
300
+ }
301
+ const shown = selected.slice(0, maxBranches);
302
+ const withheld = selected.length - shown.length;
303
+ const rows = [
304
+ {
305
+ indent: "",
306
+ name: snapshot.name,
307
+ state: snapshot.head ?? "detached",
308
+ tail: renderDirty(snapshot.dirtyFiles),
309
+ },
310
+ ...shown.map(branch => ({
311
+ indent: INDENT,
312
+ name: branch.name,
313
+ state: formatTrack(branch.track),
314
+ tail: formatAge(branch.committedAt, now),
315
+ })),
316
+ ];
317
+ if (note !== null)
318
+ rows.push({ indent: INDENT, name: note, state: "", tail: "" });
319
+ if (withheld > 0) {
320
+ rows.push({ indent: INDENT, name: `… and ${withheld} more`, state: "", tail: "" });
321
+ }
322
+ for (const problem of snapshot.problems) {
323
+ rows.push({ indent: INDENT, name: `! ${problem}`, state: "", tail: "" });
324
+ }
325
+ rows.push({ indent: "", name: "", state: "", tail: "" });
326
+ return rows;
327
+ }
328
+ /** null means the working tree was not read, which is silence rather than "clean". */
329
+ function renderDirty(count) {
330
+ return count === null || count === 0 ? "" : `${count} uncommitted`;
331
+ }
332
+ /** Most recently touched repository first — recency is what "in flight" means. */
333
+ function byRecency(a, b) {
334
+ const difference = latestCommit(b) - latestCommit(a);
335
+ return difference !== 0 ? difference : a.name.localeCompare(b.name);
336
+ }
337
+ function latestCommit(snapshot) {
338
+ return snapshot.branches.reduce((latest, branch) => {
339
+ const at = Date.parse(branch.committedAt);
340
+ return Number.isNaN(at) ? latest : Math.max(latest, at);
341
+ }, 0);
342
+ }
343
+ function byCommittedAtDesc(a, b) {
344
+ return (Date.parse(b.committedAt) || 0) - (Date.parse(a.committedAt) || 0);
345
+ }
346
+ function pad(text, width) {
347
+ return text.length >= width ? `${text} ` : text.padEnd(width);
348
+ }
349
+ function plural(count, one, many) {
350
+ return `${count} ${count === 1 ? one : many}`;
351
+ }
352
+ /**
353
+ * How long since anything happened. Phrased as idleness rather than age
354
+ * because a pull request opened in May and discussed yesterday is not old in
355
+ * any sense the operator cares about.
356
+ */
357
+ export function formatIdle(iso, now) {
358
+ const age = formatAge(iso, now);
359
+ if (age === "unknown")
360
+ return "";
361
+ if (age === "just now")
362
+ return "just now";
363
+ return `${age.replace(" ago", "")} idle`;
364
+ }
365
+ /**
366
+ * Grouped by whose move it is, because that is the only question being asked.
367
+ * Drafts and running builds are counted but not listed — nobody is blocked on
368
+ * them, and a report that lists everything is the attention problem it was
369
+ * written to solve.
370
+ */
371
+ export function renderPulls(groups, options) {
372
+ const { now, staleDays = DEFAULT_STALE_DAYS } = options;
373
+ const entries = groups.flatMap(group => group.pulls.map(pull => ({ repo: group.repo, pull, attention: classify(pull) })));
374
+ const problems = groups.flatMap(group => group.problems.map(problem => `${group.repo}: ${problem}`));
375
+ const blocking = ["human", "agent"];
376
+ const sections = blocking
377
+ .map(attention => renderAttention(attention, entries, now))
378
+ .filter((section) => section !== null);
379
+ if (sections.length === 0) {
380
+ return [renderNothingWaiting(entries, problems), ...renderProblems(problems)]
381
+ .join("\n")
382
+ .trimEnd();
383
+ }
384
+ const waiting = entries.filter(entry => blocking.includes(entry.attention));
385
+ const stalled = waiting.filter(entry => (idleDays(entry.pull, now) ?? 0) >= staleDays);
386
+ return [
387
+ renderPullsHeader(waiting.length, stalled.length, staleDays),
388
+ "",
389
+ ...sections,
390
+ ...renderProblems(problems),
391
+ ...renderQuiet(entries),
392
+ ]
393
+ .join("\n")
394
+ .trimEnd();
395
+ }
396
+ const ATTENTION_HEADINGS = {
397
+ human: "Waiting on you",
398
+ agent: "Waiting on an agent",
399
+ machine: "Waiting on CI",
400
+ none: "In progress",
401
+ };
402
+ /**
403
+ * Longest-idle first. The one that has been ignored the longest is the one
404
+ * most likely to have been forgotten rather than deferred.
405
+ */
406
+ function renderAttention(attention, entries, now) {
407
+ const mine = entries
408
+ .filter(entry => entry.attention === attention)
409
+ .sort((a, b) => (idleDays(b.pull, now) ?? 0) - (idleDays(a.pull, now) ?? 0));
410
+ if (mine.length === 0)
411
+ return null;
412
+ const rows = mine.map(entry => ({
413
+ indent: INDENT,
414
+ name: `${entry.repo} #${entry.pull.number}`,
415
+ state: describePull(entry.pull),
416
+ tail: formatIdle(entry.pull.updatedAt, now),
417
+ }));
418
+ const nameWidth = widthOf(rows, row => row.indent.length + row.name.length, MIN_NAME_WIDTH, MAX_NAME_WIDTH);
419
+ const stateWidth = widthOf(rows, row => row.state.length, MIN_STATE_WIDTH, MAX_STATE_WIDTH);
420
+ return [
421
+ ATTENTION_HEADINGS[attention],
422
+ ...rows.map(row => renderRow(row, nameWidth, stateWidth)),
423
+ "",
424
+ ].join("\n");
425
+ }
426
+ function renderPullsHeader(waiting, stalled, staleDays) {
427
+ const headline = `${plural(waiting, "pull request", "pull requests")} waiting.`;
428
+ if (stalled === 0)
429
+ return headline;
430
+ const which = stalled === 1 ? "1 has" : `${stalled} have`;
431
+ return `${headline} ${which} been waiting more than ${plural(staleDays, "day", "days")}.`;
432
+ }
433
+ /**
434
+ * Nothing waiting is only good news if we managed to look. A repository whose
435
+ * pull requests could not be read has told us nothing, and saying "nothing is
436
+ * waiting" about it would be the silence this tool exists to break.
437
+ */
438
+ function renderNothingWaiting(entries, problems) {
439
+ if (problems.length > 0 && entries.length === 0)
440
+ return "No pull requests were read.";
441
+ const quiet = renderQuiet(entries);
442
+ return ["Nothing is waiting on you.", ...quiet].join("\n");
443
+ }
444
+ /** Drafts and running builds: counted, so their absence above is not a mystery. */
445
+ function renderQuiet(entries) {
446
+ const drafts = entries.filter(entry => entry.attention === "none").length;
447
+ const running = entries.filter(entry => entry.attention === "machine").length;
448
+ const parts = [
449
+ drafts > 0 ? `${plural(drafts, "draft", "drafts")} in progress` : null,
450
+ running > 0 ? `${running} waiting on CI` : null,
451
+ ].filter((part) => part !== null);
452
+ return parts.length === 0 ? [] : ["", `${parts.join(", ")}.`];
453
+ }
454
+ function renderProblems(problems) {
455
+ return problems.length === 0 ? [] : ["", ...problems.map(problem => `! ${problem}`)];
456
+ }
457
+ /**
458
+ * What work graph is already here.
459
+ *
460
+ * The recommended backend is marked with a pointer and nothing else is, because
461
+ * the one thing this report must not read as is a menu of things already
462
+ * switched on. Every line ends by saying what is *not* authorized, since
463
+ * detection is not authorization and a report that omitted that would be
464
+ * inviting exactly the wrong conclusion.
465
+ */
466
+ export function renderGraph(detections, options = {}) {
467
+ if (detections.length === 0) {
468
+ return [
469
+ "No work graph found in your repositories.",
470
+ "",
471
+ "Toolroll looked for `.beads/`, `backlog.md`, and open GitHub Issues.",
472
+ "Nothing was installed or created — a tracker is yours to set up.",
473
+ ].join("\n");
474
+ }
475
+ const choice = chooseBackend(detections, options.enrolled === undefined ? {} : { enrolled: options.enrolled });
476
+ const chosen = choice.action === "recommend" ? choice.kind : null;
477
+ const rows = detections.map(detection => ({
478
+ marker: detection.kind === chosen ? "▸ " : " ",
479
+ label: detection.label,
480
+ facts: describeDetection(detection),
481
+ }));
482
+ const labelWidth = Math.max(...rows.map(row => row.label.length));
483
+ const problems = detections.flatMap(detection => detection.problems);
484
+ return [
485
+ "Work graph — detected in your repos",
486
+ "",
487
+ ...rows.map(row => `${row.marker}${row.label.padEnd(labelWidth)} ${row.facts}`),
488
+ "",
489
+ ...describeChoice(choice),
490
+ ...(choice.action === "built-in" ? renderSetup() : []),
491
+ ...renderProblems(problems),
492
+ ]
493
+ .join("\n")
494
+ .trimEnd();
495
+ }
496
+ /**
497
+ * The way forward when nothing is set up.
498
+ *
499
+ * Without this the empty case is a dead end — "no tracker found, and the
500
+ * fallback does not exist yet" — which tells an operator nothing they can act
501
+ * on. §4 requires the opposite: print the upstream command *and* what it will
502
+ * do, and let them run it.
503
+ *
504
+ * The side effects are not a footnote. `bd init` rewrites AGENTS.md and
505
+ * installs agent integrations, and somebody who ran it because a tool
506
+ * suggested it and only found that out afterwards would be right to be angry.
507
+ */
508
+ function renderSetup() {
509
+ const lines = ["", "Setting one up — commands to run yourself, in your own shell:"];
510
+ for (const option of setupOptions()) {
511
+ lines.push("");
512
+ lines.push(` ${option.label}${option.note === null ? "" : ` — ${option.note}`}`);
513
+ if (option.install !== null)
514
+ lines.push(` ${option.install}`);
515
+ if (option.init !== null)
516
+ lines.push(` ${option.init}`);
517
+ if (option.sideEffects !== null)
518
+ lines.push(` → ${option.sideEffects}`);
519
+ }
520
+ lines.push("");
521
+ lines.push("Toolroll runs none of these. Re-run `toolroll graph` afterwards.");
522
+ return lines;
523
+ }
524
+ /** The middle column: where it is, how much is in it, and whether it could run. */
525
+ function describeDetection(detection) {
526
+ const parts = [];
527
+ if (detection.repos.length > 0) {
528
+ parts.push(`${plural(detection.repos.length, "repo", "repos")}`);
529
+ }
530
+ // A row with no number at all reads as zero. Absence of a count is its own
531
+ // fact and has to be said out loud.
532
+ parts.push(detection.count === null
533
+ ? "count unknown"
534
+ : `${detection.count.value} ${detection.count.of}`);
535
+ parts.push(describeDeps(detection.deps));
536
+ parts.push(describeRuntime(detection));
537
+ return parts.join(" · ");
538
+ }
539
+ function describeDeps(deps) {
540
+ if (deps === "native")
541
+ return "native deps";
542
+ if (deps === "none")
543
+ return "no deps";
544
+ return "deps unverified";
545
+ }
546
+ function describeRuntime(detection) {
547
+ const { runtime } = detection;
548
+ if (runtime.state === "missing")
549
+ return `${runtime.binary} not installed`;
550
+ if (runtime.state === "outdated")
551
+ return `${runtime.version} too old, needs ${runtime.needs}`;
552
+ if (runtime.state === "unreadable")
553
+ return "runtime would not answer";
554
+ return runtime.version === null ? "runtime ok" : `runtime ok (${runtime.version})`;
555
+ }
556
+ /**
557
+ * The closing line always says nothing is enrolled, including when a backend
558
+ * is recommended. A recommendation that read as an activation would be the one
559
+ * misunderstanding this whole module is written to prevent.
560
+ */
561
+ function describeChoice(choice) {
562
+ const lines = [];
563
+ if (choice.action === "recommend" && choice.why === "already enrolled") {
564
+ // An enrolled backend is not a suggestion, and must not read like one.
565
+ lines.push(`Enrolled: ${GRAPH_LABELS[choice.kind]}. Write access has been granted.`);
566
+ lines.push("`toolroll grants` shows exactly what, and `revoke` takes it back.");
567
+ return lines;
568
+ }
569
+ if (choice.action === "recommend") {
570
+ lines.push(`Suggested: ${GRAPH_LABELS[choice.kind]} — ${choice.why}.`);
571
+ if (!choice.dispatchable) {
572
+ // Deliberately not "it can be read, but…": when the runtime is missing
573
+ // it cannot be read either, and the sentence would contradict the row
574
+ // directly above it.
575
+ lines.push("Nothing here could be scheduled from it as it stands.");
576
+ }
577
+ }
578
+ else if (choice.action === "ambiguous") {
579
+ const names = choice.kinds.map(kind => GRAPH_LABELS[kind]).join(" and ");
580
+ lines.push(`${names} are both populated — ${choice.why}.`);
581
+ }
582
+ else {
583
+ lines.push(choice.why.charAt(0).toUpperCase() + choice.why.slice(1) + ".");
584
+ }
585
+ lines.push("Nothing is enrolled, and detection grants nothing.");
586
+ return lines;
587
+ }
@@ -0,0 +1,13 @@
1
+ import type { Store } from "./store.js";
2
+ /** The report a scout delivered, for get_task: title, summary, follow-ups —
3
+ * verified before it is read; the document itself stays on the task page. */
4
+ export declare function reportSummaryFor(store: Store, evidenceRoot: string | undefined, taskRef: number): {
5
+ title: string;
6
+ summary: string;
7
+ followUps: {
8
+ title: string;
9
+ goal: string;
10
+ }[];
11
+ } | {
12
+ problem: string;
13
+ } | null;
@@ -0,0 +1,15 @@
1
+ import { readVerifiedReport } from "./evidence.js";
2
+ /** The report a scout delivered, for get_task: title, summary, follow-ups —
3
+ * verified before it is read; the document itself stays on the task page. */
4
+ export function reportSummaryFor(store, evidenceRoot, taskRef) {
5
+ if (store.latestReportArtifact(taskRef) === null)
6
+ return null;
7
+ if (evidenceRoot === undefined)
8
+ return { problem: "a report exists, but this surface cannot read evidence" };
9
+ const view = readVerifiedReport(store, evidenceRoot, taskRef);
10
+ if (view === null)
11
+ return null;
12
+ if (!view.ok)
13
+ return { problem: view.problem };
14
+ return { title: view.report.title, summary: view.report.summary, followUps: view.report.followUps };
15
+ }