tinybeeai 0.0.0-stage → 0.16.1

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 (1034) hide show
  1. package/.railway/railway.ts +83 -0
  2. package/.railway/tsconfig.json +13 -0
  3. package/AGENTS.md +102 -0
  4. package/Dockerfile +108 -0
  5. package/LICENSE +21 -0
  6. package/README.md +275 -2
  7. package/bin/localdost.js +29 -0
  8. package/bin/tinybeeai.js +28 -0
  9. package/compose.yml +63 -0
  10. package/demo/payloads/ci_failure.json +46 -0
  11. package/demo/payloads/outage.json +18 -0
  12. package/demo/payloads/pr_comment_edited.json +50 -0
  13. package/demo/payloads/pr_merged.json +80 -0
  14. package/demo/payloads/pr_opened.json +69 -0
  15. package/demo/payloads/pr_synchronize.json +69 -0
  16. package/demo/payloads/ticket_created.json +138 -0
  17. package/demo/sample-app/playwright.config.ts +20 -0
  18. package/demo/sample-app/server.ts +163 -0
  19. package/demo/sample-app/tests/checkout.spec.ts +13 -0
  20. package/demo/sample-app/tests/smoke.spec.ts +8 -0
  21. package/dist/agent/approval-retries.js +59 -0
  22. package/dist/agent/approval-retries.js.map +1 -0
  23. package/dist/agent/approvals.js +390 -0
  24. package/dist/agent/approvals.js.map +1 -0
  25. package/dist/agent/chat-bridge.js +154 -0
  26. package/dist/agent/chat-bridge.js.map +1 -0
  27. package/dist/agent/chat-lead.js +475 -0
  28. package/dist/agent/chat-lead.js.map +1 -0
  29. package/dist/agent/chat-loop.js +106 -0
  30. package/dist/agent/chat-loop.js.map +1 -0
  31. package/dist/agent/chat-mcp.js +49 -0
  32. package/dist/agent/chat-mcp.js.map +1 -0
  33. package/dist/agent/chat-tool-blocks.js +453 -0
  34. package/dist/agent/chat-tool-blocks.js.map +1 -0
  35. package/dist/agent/chat-view.js +94 -0
  36. package/dist/agent/chat-view.js.map +1 -0
  37. package/dist/agent/chat-views.js +781 -0
  38. package/dist/agent/chat-views.js.map +1 -0
  39. package/dist/agent/chat.js +1703 -0
  40. package/dist/agent/chat.js.map +1 -0
  41. package/dist/agent/destinations.js +150 -0
  42. package/dist/agent/destinations.js.map +1 -0
  43. package/dist/agent/llm-cli.js +451 -0
  44. package/dist/agent/llm-cli.js.map +1 -0
  45. package/dist/agent/llm-codex.js +493 -0
  46. package/dist/agent/llm-codex.js.map +1 -0
  47. package/dist/agent/llm-openai.js +211 -0
  48. package/dist/agent/llm-openai.js.map +1 -0
  49. package/dist/agent/llm.js +1464 -0
  50. package/dist/agent/llm.js.map +1 -0
  51. package/dist/agent/memory.js +33 -0
  52. package/dist/agent/memory.js.map +1 -0
  53. package/dist/agent/mock-views.js +93 -0
  54. package/dist/agent/mock-views.js.map +1 -0
  55. package/dist/agent/model-availability.js +207 -0
  56. package/dist/agent/model-availability.js.map +1 -0
  57. package/dist/agent/model-errors.js +188 -0
  58. package/dist/agent/model-errors.js.map +1 -0
  59. package/dist/agent/model-guard.js +311 -0
  60. package/dist/agent/model-guard.js.map +1 -0
  61. package/dist/agent/prompts.js +374 -0
  62. package/dist/agent/prompts.js.map +1 -0
  63. package/dist/agent/qa-lenses/qa-auth.md +32 -0
  64. package/dist/agent/qa-lenses/qa-check-then-act.md +33 -0
  65. package/dist/agent/qa-lenses/qa-control-has-no-effect.md +32 -0
  66. package/dist/agent/qa-lenses/qa-dates.md +31 -0
  67. package/dist/agent/qa-lenses/qa-double-submit.md +34 -0
  68. package/dist/agent/qa-lenses/qa-feature-flag.md +29 -0
  69. package/dist/agent/qa-lenses/qa-migration.md +35 -0
  70. package/dist/agent/qa-lenses/qa-money.md +38 -0
  71. package/dist/agent/qa-lenses/qa-response-shape-break.md +33 -0
  72. package/dist/agent/qa-lenses/qa-validation.md +29 -0
  73. package/dist/agent/qa-prompts.js +660 -0
  74. package/dist/agent/qa-prompts.js.map +1 -0
  75. package/dist/agent/reasoning.js +55 -0
  76. package/dist/agent/reasoning.js.map +1 -0
  77. package/dist/agent/redact.js +48 -0
  78. package/dist/agent/redact.js.map +1 -0
  79. package/dist/agent/rules.js +927 -0
  80. package/dist/agent/rules.js.map +1 -0
  81. package/dist/agent/runs.js +440 -0
  82. package/dist/agent/runs.js.map +1 -0
  83. package/dist/agent/send-retry.js +62 -0
  84. package/dist/agent/send-retry.js.map +1 -0
  85. package/dist/agent/team-notes.js +288 -0
  86. package/dist/agent/team-notes.js.map +1 -0
  87. package/dist/agent/token-meter.js +31 -0
  88. package/dist/agent/token-meter.js.map +1 -0
  89. package/dist/agent/triage.js +506 -0
  90. package/dist/agent/triage.js.map +1 -0
  91. package/dist/api.js +1047 -0
  92. package/dist/api.js.map +1 -0
  93. package/dist/approval-targets.js +107 -0
  94. package/dist/approval-targets.js.map +1 -0
  95. package/dist/bee/cloudflared.js +108 -0
  96. package/dist/bee/cloudflared.js.map +1 -0
  97. package/dist/bee/health.js +99 -0
  98. package/dist/bee/health.js.map +1 -0
  99. package/dist/bee/hive-client.js +75 -0
  100. package/dist/bee/hive-client.js.map +1 -0
  101. package/dist/bee/identity.js +39 -0
  102. package/dist/bee/identity.js.map +1 -0
  103. package/dist/bee/models.js +510 -0
  104. package/dist/bee/models.js.map +1 -0
  105. package/dist/bee/pairing.js +351 -0
  106. package/dist/bee/pairing.js.map +1 -0
  107. package/dist/bee/relay-client.js +50 -0
  108. package/dist/bee/relay-client.js.map +1 -0
  109. package/dist/bee/routes.js +214 -0
  110. package/dist/bee/routes.js.map +1 -0
  111. package/dist/bee/setup-page.js +223 -0
  112. package/dist/bee/setup-page.js.map +1 -0
  113. package/dist/bee/state.js +41 -0
  114. package/dist/bee/state.js.map +1 -0
  115. package/dist/bee/status.js +117 -0
  116. package/dist/bee/status.js.map +1 -0
  117. package/dist/bee/tunnel-manager.js +245 -0
  118. package/dist/bee/tunnel-manager.js.map +1 -0
  119. package/dist/bee/updater.js +268 -0
  120. package/dist/bee/updater.js.map +1 -0
  121. package/dist/boot.js +41 -0
  122. package/dist/boot.js.map +1 -0
  123. package/dist/call/index.js +145 -0
  124. package/dist/call/index.js.map +1 -0
  125. package/dist/case-folders.js +294 -0
  126. package/dist/case-folders.js.map +1 -0
  127. package/dist/cases.js +554 -0
  128. package/dist/cases.js.map +1 -0
  129. package/dist/chat-blocks.js +709 -0
  130. package/dist/chat-blocks.js.map +1 -0
  131. package/dist/chat-parse-util.js +38 -0
  132. package/dist/chat-parse-util.js.map +1 -0
  133. package/dist/chat-results.js +96 -0
  134. package/dist/chat-results.js.map +1 -0
  135. package/dist/chat-stats.js +193 -0
  136. package/dist/chat-stats.js.map +1 -0
  137. package/dist/chat-view-specs.js +186 -0
  138. package/dist/chat-view-specs.js.map +1 -0
  139. package/dist/cli/doctor-ops.js +361 -0
  140. package/dist/cli/doctor-ops.js.map +1 -0
  141. package/dist/cli/doctor.js +289 -0
  142. package/dist/cli/doctor.js.map +1 -0
  143. package/dist/cli/dogfood.js +70 -0
  144. package/dist/cli/dogfood.js.map +1 -0
  145. package/dist/cli/env-file.js +34 -0
  146. package/dist/cli/env-file.js.map +1 -0
  147. package/dist/cli/eval-chat-cases.js +359 -0
  148. package/dist/cli/eval-chat-cases.js.map +1 -0
  149. package/dist/cli/eval-chat-results.js +85 -0
  150. package/dist/cli/eval-chat-results.js.map +1 -0
  151. package/dist/cli/eval-chat.js +508 -0
  152. package/dist/cli/eval-chat.js.map +1 -0
  153. package/dist/cli/eval-designer.js +67 -0
  154. package/dist/cli/eval-designer.js.map +1 -0
  155. package/dist/cli/eval-qa-review.js +284 -0
  156. package/dist/cli/eval-qa-review.js.map +1 -0
  157. package/dist/cli/golden-export.js +35 -0
  158. package/dist/cli/golden-export.js.map +1 -0
  159. package/dist/cli/index.js +90 -0
  160. package/dist/cli/index.js.map +1 -0
  161. package/dist/cli/init.js +746 -0
  162. package/dist/cli/init.js.map +1 -0
  163. package/dist/cli/scan-repo.js +199 -0
  164. package/dist/cli/scan-repo.js.map +1 -0
  165. package/dist/cli/seed.js +108 -0
  166. package/dist/cli/seed.js.map +1 -0
  167. package/dist/cli/tinybee.js +247 -0
  168. package/dist/cli/tinybee.js.map +1 -0
  169. package/dist/config.js +138 -0
  170. package/dist/config.js.map +1 -0
  171. package/dist/connect/aivision-local.js +833 -0
  172. package/dist/connect/aivision-local.js.map +1 -0
  173. package/dist/connect/aivision-token.js +84 -0
  174. package/dist/connect/aivision-token.js.map +1 -0
  175. package/dist/connect/crypto.js +65 -0
  176. package/dist/connect/crypto.js.map +1 -0
  177. package/dist/connect/deps.js +110 -0
  178. package/dist/connect/deps.js.map +1 -0
  179. package/dist/connect/engines.js +144 -0
  180. package/dist/connect/engines.js.map +1 -0
  181. package/dist/connect/github-access.js +74 -0
  182. package/dist/connect/github-access.js.map +1 -0
  183. package/dist/connect/github-app.js +129 -0
  184. package/dist/connect/github-app.js.map +1 -0
  185. package/dist/connect/index.js +9 -0
  186. package/dist/connect/index.js.map +1 -0
  187. package/dist/connect/model-choices.js +201 -0
  188. package/dist/connect/model-choices.js.map +1 -0
  189. package/dist/connect/providers.js +900 -0
  190. package/dist/connect/providers.js.map +1 -0
  191. package/dist/connect/readiness.js +232 -0
  192. package/dist/connect/readiness.js.map +1 -0
  193. package/dist/connect/redact.js +16 -0
  194. package/dist/connect/redact.js.map +1 -0
  195. package/dist/connect/registry.js +406 -0
  196. package/dist/connect/registry.js.map +1 -0
  197. package/dist/connect/store.js +283 -0
  198. package/dist/connect/store.js.map +1 -0
  199. package/dist/connect/tunnel.js +134 -0
  200. package/dist/connect/tunnel.js.map +1 -0
  201. package/dist/connect/types.js +8 -0
  202. package/dist/connect/types.js.map +1 -0
  203. package/dist/connections/index.js +5 -0
  204. package/dist/connections/index.js.map +1 -0
  205. package/dist/connections/manager.js +223 -0
  206. package/dist/connections/manager.js.map +1 -0
  207. package/dist/connections/presets.js +264 -0
  208. package/dist/connections/presets.js.map +1 -0
  209. package/dist/connections/store.js +132 -0
  210. package/dist/connections/store.js.map +1 -0
  211. package/dist/connections/tools.js +206 -0
  212. package/dist/connections/tools.js.map +1 -0
  213. package/dist/db-schema.js +355 -0
  214. package/dist/db-schema.js.map +1 -0
  215. package/dist/db.js +379 -0
  216. package/dist/db.js.map +1 -0
  217. package/dist/delivery.js +49 -0
  218. package/dist/delivery.js.map +1 -0
  219. package/dist/deploy-wait.js +701 -0
  220. package/dist/deploy-wait.js.map +1 -0
  221. package/dist/disk.js +243 -0
  222. package/dist/disk.js.map +1 -0
  223. package/dist/dot-health.js +966 -0
  224. package/dist/dot-health.js.map +1 -0
  225. package/dist/dot-remove.js +246 -0
  226. package/dist/dot-remove.js.map +1 -0
  227. package/dist/events.js +38 -0
  228. package/dist/events.js.map +1 -0
  229. package/dist/evidence-pack.js +423 -0
  230. package/dist/evidence-pack.js.map +1 -0
  231. package/dist/flows/answers.js +289 -0
  232. package/dist/flows/answers.js.map +1 -0
  233. package/dist/flows/change.js +811 -0
  234. package/dist/flows/change.js.map +1 -0
  235. package/dist/flows/checkStatus.js +524 -0
  236. package/dist/flows/checkStatus.js.map +1 -0
  237. package/dist/flows/ci.js +236 -0
  238. package/dist/flows/ci.js.map +1 -0
  239. package/dist/flows/ciFailure.js +76 -0
  240. package/dist/flows/ciFailure.js.map +1 -0
  241. package/dist/flows/common.js +522 -0
  242. package/dist/flows/common.js.map +1 -0
  243. package/dist/flows/default-branch.js +29 -0
  244. package/dist/flows/default-branch.js.map +1 -0
  245. package/dist/flows/defectDraft.js +447 -0
  246. package/dist/flows/defectDraft.js.map +1 -0
  247. package/dist/flows/defects.js +623 -0
  248. package/dist/flows/defects.js.map +1 -0
  249. package/dist/flows/digest.js +295 -0
  250. package/dist/flows/digest.js.map +1 -0
  251. package/dist/flows/impact.js +82 -0
  252. package/dist/flows/impact.js.map +1 -0
  253. package/dist/flows/index.js +23 -0
  254. package/dist/flows/index.js.map +1 -0
  255. package/dist/flows/intent-sources.js +72 -0
  256. package/dist/flows/intent-sources.js.map +1 -0
  257. package/dist/flows/mergeCases.js +169 -0
  258. package/dist/flows/mergeCases.js.map +1 -0
  259. package/dist/flows/nightlyRun.js +82 -0
  260. package/dist/flows/nightlyRun.js.map +1 -0
  261. package/dist/flows/outage.js +64 -0
  262. package/dist/flows/outage.js.map +1 -0
  263. package/dist/flows/postMerge.js +5 -0
  264. package/dist/flows/postMerge.js.map +1 -0
  265. package/dist/flows/prCheck.js +5 -0
  266. package/dist/flows/prCheck.js.map +1 -0
  267. package/dist/flows/prTarget.js +66 -0
  268. package/dist/flows/prTarget.js.map +1 -0
  269. package/dist/flows/qa.js +363 -0
  270. package/dist/flows/qa.js.map +1 -0
  271. package/dist/flows/questions.js +160 -0
  272. package/dist/flows/questions.js.map +1 -0
  273. package/dist/flows/recovery.js +64 -0
  274. package/dist/flows/recovery.js.map +1 -0
  275. package/dist/flows/rerun.js +50 -0
  276. package/dist/flows/rerun.js.map +1 -0
  277. package/dist/flows/testDesign.js +294 -0
  278. package/dist/flows/testDesign.js.map +1 -0
  279. package/dist/flows/testDesignJob.js +46 -0
  280. package/dist/flows/testDesignJob.js.map +1 -0
  281. package/dist/flows/testRepo.js +228 -0
  282. package/dist/flows/testRepo.js.map +1 -0
  283. package/dist/flows/testSavings.js +381 -0
  284. package/dist/flows/testSavings.js.map +1 -0
  285. package/dist/flows/testStatus.js +343 -0
  286. package/dist/flows/testStatus.js.map +1 -0
  287. package/dist/flows/ticketContext.js +425 -0
  288. package/dist/flows/ticketContext.js.map +1 -0
  289. package/dist/flows/ticketReview.js +249 -0
  290. package/dist/flows/ticketReview.js.map +1 -0
  291. package/dist/flows/ticks.js +73 -0
  292. package/dist/flows/ticks.js.map +1 -0
  293. package/dist/hive/admin.js +122 -0
  294. package/dist/hive/admin.js.map +1 -0
  295. package/dist/hive/auth.js +130 -0
  296. package/dist/hive/auth.js.map +1 -0
  297. package/dist/hive/billing.js +278 -0
  298. package/dist/hive/billing.js.map +1 -0
  299. package/dist/hive/config.js +63 -0
  300. package/dist/hive/config.js.map +1 -0
  301. package/dist/hive/db.js +186 -0
  302. package/dist/hive/db.js.map +1 -0
  303. package/dist/hive/embed.js +76 -0
  304. package/dist/hive/embed.js.map +1 -0
  305. package/dist/hive/errors.js +17 -0
  306. package/dist/hive/errors.js.map +1 -0
  307. package/dist/hive/google.js +75 -0
  308. package/dist/hive/google.js.map +1 -0
  309. package/dist/hive/index.js +25 -0
  310. package/dist/hive/index.js.map +1 -0
  311. package/dist/hive/jwt.js +57 -0
  312. package/dist/hive/jwt.js.map +1 -0
  313. package/dist/hive/keys.js +61 -0
  314. package/dist/hive/keys.js.map +1 -0
  315. package/dist/hive/mail.js +27 -0
  316. package/dist/hive/mail.js.map +1 -0
  317. package/dist/hive/native-push.js +255 -0
  318. package/dist/hive/native-push.js.map +1 -0
  319. package/dist/hive/pairing.js +342 -0
  320. package/dist/hive/pairing.js.map +1 -0
  321. package/dist/hive/presence.js +121 -0
  322. package/dist/hive/presence.js.map +1 -0
  323. package/dist/hive/push.js +185 -0
  324. package/dist/hive/push.js.map +1 -0
  325. package/dist/hive/relay.js +205 -0
  326. package/dist/hive/relay.js.map +1 -0
  327. package/dist/hive/routes.js +228 -0
  328. package/dist/hive/routes.js.map +1 -0
  329. package/dist/hive/server.js +12 -0
  330. package/dist/hive/server.js.map +1 -0
  331. package/dist/hive/session.js +28 -0
  332. package/dist/hive/session.js.map +1 -0
  333. package/dist/hive/tenants.js +287 -0
  334. package/dist/hive/tenants.js.map +1 -0
  335. package/dist/hive/tunnel/cloudflare.js +160 -0
  336. package/dist/hive/tunnel/cloudflare.js.map +1 -0
  337. package/dist/hive/tunnel/mock.js +52 -0
  338. package/dist/hive/tunnel/mock.js.map +1 -0
  339. package/dist/hive/tunnel/provider.js +19 -0
  340. package/dist/hive/tunnel/provider.js.map +1 -0
  341. package/dist/hive/updates.js +61 -0
  342. package/dist/hive/updates.js.map +1 -0
  343. package/dist/http-error.js +11 -0
  344. package/dist/http-error.js.map +1 -0
  345. package/dist/impact/classify.js +226 -0
  346. package/dist/impact/classify.js.map +1 -0
  347. package/dist/impact/find.js +259 -0
  348. package/dist/impact/find.js.map +1 -0
  349. package/dist/impact/pr.js +54 -0
  350. package/dist/impact/pr.js.map +1 -0
  351. package/dist/impact/store.js +365 -0
  352. package/dist/impact/store.js.map +1 -0
  353. package/dist/impact/text.js +158 -0
  354. package/dist/impact/text.js.map +1 -0
  355. package/dist/index.js +288 -0
  356. package/dist/index.js.map +1 -0
  357. package/dist/integrations/adf.js +397 -0
  358. package/dist/integrations/adf.js.map +1 -0
  359. package/dist/integrations/bot-marker.js +103 -0
  360. package/dist/integrations/bot-marker.js.map +1 -0
  361. package/dist/integrations/github-issues.js +705 -0
  362. package/dist/integrations/github-issues.js.map +1 -0
  363. package/dist/integrations/github.js +1284 -0
  364. package/dist/integrations/github.js.map +1 -0
  365. package/dist/integrations/issue-create.js +60 -0
  366. package/dist/integrations/issue-create.js.map +1 -0
  367. package/dist/integrations/jira.js +279 -0
  368. package/dist/integrations/jira.js.map +1 -0
  369. package/dist/integrations/linear.js +273 -0
  370. package/dist/integrations/linear.js.map +1 -0
  371. package/dist/integrations/own-identity-warm.js +47 -0
  372. package/dist/integrations/own-identity-warm.js.map +1 -0
  373. package/dist/integrations/own-identity.js +39 -0
  374. package/dist/integrations/own-identity.js.map +1 -0
  375. package/dist/integrations/status-change.js +42 -0
  376. package/dist/integrations/status-change.js.map +1 -0
  377. package/dist/lead-defects.js +202 -0
  378. package/dist/lead-defects.js.map +1 -0
  379. package/dist/lead-digest.js +333 -0
  380. package/dist/lead-digest.js.map +1 -0
  381. package/dist/lead-release.js +286 -0
  382. package/dist/lead-release.js.map +1 -0
  383. package/dist/lead.js +328 -0
  384. package/dist/lead.js.map +1 -0
  385. package/dist/legacy-names.js +51 -0
  386. package/dist/legacy-names.js.map +1 -0
  387. package/dist/limits.js +44 -0
  388. package/dist/limits.js.map +1 -0
  389. package/dist/link-trust.js +224 -0
  390. package/dist/link-trust.js.map +1 -0
  391. package/dist/links.js +219 -0
  392. package/dist/links.js.map +1 -0
  393. package/dist/loopback.js +35 -0
  394. package/dist/loopback.js.map +1 -0
  395. package/dist/model-cap.js +60 -0
  396. package/dist/model-cap.js.map +1 -0
  397. package/dist/model-usage.js +173 -0
  398. package/dist/model-usage.js.map +1 -0
  399. package/dist/monitor/backfill.js +39 -0
  400. package/dist/monitor/backfill.js.map +1 -0
  401. package/dist/monitor/browser-probe.js +198 -0
  402. package/dist/monitor/browser-probe.js.map +1 -0
  403. package/dist/monitor/catch-up.js +31 -0
  404. package/dist/monitor/catch-up.js.map +1 -0
  405. package/dist/monitor/pollers.js +1606 -0
  406. package/dist/monitor/pollers.js.map +1 -0
  407. package/dist/monitor/probes.js +178 -0
  408. package/dist/monitor/probes.js.map +1 -0
  409. package/dist/monitor/self-health.js +228 -0
  410. package/dist/monitor/self-health.js.map +1 -0
  411. package/dist/monitor/statuspage.js +105 -0
  412. package/dist/monitor/statuspage.js.map +1 -0
  413. package/dist/nightly-scheduler.js +127 -0
  414. package/dist/nightly-scheduler.js.map +1 -0
  415. package/dist/nightly.js +141 -0
  416. package/dist/nightly.js.map +1 -0
  417. package/dist/notify/headline.js +114 -0
  418. package/dist/notify/headline.js.map +1 -0
  419. package/dist/notify/push.js +174 -0
  420. package/dist/notify/push.js.map +1 -0
  421. package/dist/object-cards.js +585 -0
  422. package/dist/object-cards.js.map +1 -0
  423. package/dist/object-links.js +47 -0
  424. package/dist/object-links.js.map +1 -0
  425. package/dist/onboarding-checks.js +141 -0
  426. package/dist/onboarding-checks.js.map +1 -0
  427. package/dist/onboarding.js +401 -0
  428. package/dist/onboarding.js.map +1 -0
  429. package/dist/path-filters.js +62 -0
  430. package/dist/path-filters.js.map +1 -0
  431. package/dist/phone/alerts.js +67 -0
  432. package/dist/phone/alerts.js.map +1 -0
  433. package/dist/phone/auth.js +240 -0
  434. package/dist/phone/auth.js.map +1 -0
  435. package/dist/phone/pairing.js +442 -0
  436. package/dist/phone/pairing.js.map +1 -0
  437. package/dist/phone/prefs.js +27 -0
  438. package/dist/phone/prefs.js.map +1 -0
  439. package/dist/phone/tailscale.js +161 -0
  440. package/dist/phone/tailscale.js.map +1 -0
  441. package/dist/pr-scope.js +441 -0
  442. package/dist/pr-scope.js.map +1 -0
  443. package/dist/proc.js +156 -0
  444. package/dist/proc.js.map +1 -0
  445. package/dist/profile/cache.js +108 -0
  446. package/dist/profile/cache.js.map +1 -0
  447. package/dist/profile/ci.js +216 -0
  448. package/dist/profile/ci.js.map +1 -0
  449. package/dist/profile/index.js +8 -0
  450. package/dist/profile/index.js.map +1 -0
  451. package/dist/profile/job.js +135 -0
  452. package/dist/profile/job.js.map +1 -0
  453. package/dist/profile/queries/go-tags.scm +47 -0
  454. package/dist/profile/queries/java-tags.scm +25 -0
  455. package/dist/profile/queries/javascript-tags.scm +104 -0
  456. package/dist/profile/queries/python-tags.scm +19 -0
  457. package/dist/profile/queries/typescript-tags.scm +28 -0
  458. package/dist/profile/scan-thread.js +42 -0
  459. package/dist/profile/scan-thread.js.map +1 -0
  460. package/dist/profile/scan-worker.js +16 -0
  461. package/dist/profile/scan-worker.js.map +1 -0
  462. package/dist/profile/scan.js +351 -0
  463. package/dist/profile/scan.js.map +1 -0
  464. package/dist/profile/stack.js +528 -0
  465. package/dist/profile/stack.js.map +1 -0
  466. package/dist/profile/store.js +35 -0
  467. package/dist/profile/store.js.map +1 -0
  468. package/dist/profile/tests.js +399 -0
  469. package/dist/profile/tests.js.map +1 -0
  470. package/dist/queue.js +350 -0
  471. package/dist/queue.js.map +1 -0
  472. package/dist/refs.js +756 -0
  473. package/dist/refs.js.map +1 -0
  474. package/dist/release-notes.js +272 -0
  475. package/dist/release-notes.js.map +1 -0
  476. package/dist/reports/build.js +243 -0
  477. package/dist/reports/build.js.map +1 -0
  478. package/dist/reports/index.js +211 -0
  479. package/dist/reports/index.js.map +1 -0
  480. package/dist/reports/store.js +150 -0
  481. package/dist/reports/store.js.map +1 -0
  482. package/dist/reports/ticket-titles.js +124 -0
  483. package/dist/reports/ticket-titles.js.map +1 -0
  484. package/dist/reports/trace-map.js +1278 -0
  485. package/dist/reports/trace-map.js.map +1 -0
  486. package/dist/reports/traceability.js +422 -0
  487. package/dist/reports/traceability.js.map +1 -0
  488. package/dist/repos/mirror.js +356 -0
  489. package/dist/repos/mirror.js.map +1 -0
  490. package/dist/repos-github.js +108 -0
  491. package/dist/repos-github.js.map +1 -0
  492. package/dist/repos.js +891 -0
  493. package/dist/repos.js.map +1 -0
  494. package/dist/review/backend-anthropic.js +90 -0
  495. package/dist/review/backend-anthropic.js.map +1 -0
  496. package/dist/review/backend-cli.js +248 -0
  497. package/dist/review/backend-cli.js.map +1 -0
  498. package/dist/review/backend-codex.js +81 -0
  499. package/dist/review/backend-codex.js.map +1 -0
  500. package/dist/review/backend-mock.js +686 -0
  501. package/dist/review/backend-mock.js.map +1 -0
  502. package/dist/review/backend-only.js +168 -0
  503. package/dist/review/backend-only.js.map +1 -0
  504. package/dist/review/backend.js +105 -0
  505. package/dist/review/backend.js.map +1 -0
  506. package/dist/review/baseline/render-v1.js +483 -0
  507. package/dist/review/baseline/render-v1.js.map +1 -0
  508. package/dist/review/change-summary.js +197 -0
  509. package/dist/review/change-summary.js.map +1 -0
  510. package/dist/review/changelog.js +40 -0
  511. package/dist/review/changelog.js.map +1 -0
  512. package/dist/review/check.js +494 -0
  513. package/dist/review/check.js.map +1 -0
  514. package/dist/review/checkout.js +185 -0
  515. package/dist/review/checkout.js.map +1 -0
  516. package/dist/review/classify.js +178 -0
  517. package/dist/review/classify.js.map +1 -0
  518. package/dist/review/coverage.js +347 -0
  519. package/dist/review/coverage.js.map +1 -0
  520. package/dist/review/decision-eval.js +121 -0
  521. package/dist/review/decision-eval.js.map +1 -0
  522. package/dist/review/deliver.js +104 -0
  523. package/dist/review/deliver.js.map +1 -0
  524. package/dist/review/designer-eval.js +280 -0
  525. package/dist/review/designer-eval.js.map +1 -0
  526. package/dist/review/dogfood-digest.js +136 -0
  527. package/dist/review/dogfood-digest.js.map +1 -0
  528. package/dist/review/dogfood-eval.js +486 -0
  529. package/dist/review/dogfood-eval.js.map +1 -0
  530. package/dist/review/environment.js +109 -0
  531. package/dist/review/environment.js.map +1 -0
  532. package/dist/review/eval.js +405 -0
  533. package/dist/review/eval.js.map +1 -0
  534. package/dist/review/glob.js +110 -0
  535. package/dist/review/glob.js.map +1 -0
  536. package/dist/review/golden-export.js +219 -0
  537. package/dist/review/golden-export.js.map +1 -0
  538. package/dist/review/impact.js +406 -0
  539. package/dist/review/impact.js.map +1 -0
  540. package/dist/review/imports.js +542 -0
  541. package/dist/review/imports.js.map +1 -0
  542. package/dist/review/index.js +512 -0
  543. package/dist/review/index.js.map +1 -0
  544. package/dist/review/intent.js +128 -0
  545. package/dist/review/intent.js.map +1 -0
  546. package/dist/review/lenses.js +167 -0
  547. package/dist/review/lenses.js.map +1 -0
  548. package/dist/review/linked-tickets.js +293 -0
  549. package/dist/review/linked-tickets.js.map +1 -0
  550. package/dist/review/merge.js +370 -0
  551. package/dist/review/merge.js.map +1 -0
  552. package/dist/review/on-demand.js +218 -0
  553. package/dist/review/on-demand.js.map +1 -0
  554. package/dist/review/prompt-eval.js +299 -0
  555. package/dist/review/prompt-eval.js.map +1 -0
  556. package/dist/review/prompt-variants.js +37 -0
  557. package/dist/review/prompt-variants.js.map +1 -0
  558. package/dist/review/readability-eval.js +217 -0
  559. package/dist/review/readability-eval.js.map +1 -0
  560. package/dist/review/readability.js +295 -0
  561. package/dist/review/readability.js.map +1 -0
  562. package/dist/review/render.js +2409 -0
  563. package/dist/review/render.js.map +1 -0
  564. package/dist/review/repo.js +194 -0
  565. package/dist/review/repo.js.map +1 -0
  566. package/dist/review/report-plan.js +90 -0
  567. package/dist/review/report-plan.js.map +1 -0
  568. package/dist/review/routes.js +195 -0
  569. package/dist/review/routes.js.map +1 -0
  570. package/dist/review/run-summary.js +34 -0
  571. package/dist/review/run-summary.js.map +1 -0
  572. package/dist/review/run.js +245 -0
  573. package/dist/review/run.js.map +1 -0
  574. package/dist/review/scope.js +454 -0
  575. package/dist/review/scope.js.map +1 -0
  576. package/dist/review/security.js +432 -0
  577. package/dist/review/security.js.map +1 -0
  578. package/dist/review/signals.js +550 -0
  579. package/dist/review/signals.js.map +1 -0
  580. package/dist/review/specs.js +150 -0
  581. package/dist/review/specs.js.map +1 -0
  582. package/dist/review/ste.js +133 -0
  583. package/dist/review/ste.js.map +1 -0
  584. package/dist/review/test-repo-file.js +18 -0
  585. package/dist/review/test-repo-file.js.map +1 -0
  586. package/dist/review/test-repo-lines.js +53 -0
  587. package/dist/review/test-repo-lines.js.map +1 -0
  588. package/dist/review/ticket-on-demand.js +232 -0
  589. package/dist/review/ticket-on-demand.js.map +1 -0
  590. package/dist/review/yaml.js +298 -0
  591. package/dist/review/yaml.js.map +1 -0
  592. package/dist/room.js +361 -0
  593. package/dist/room.js.map +1 -0
  594. package/dist/routes/activity.js +219 -0
  595. package/dist/routes/activity.js.map +1 -0
  596. package/dist/routes/call.js +29 -0
  597. package/dist/routes/call.js.map +1 -0
  598. package/dist/routes/cards.js +40 -0
  599. package/dist/routes/cards.js.map +1 -0
  600. package/dist/routes/cases.js +133 -0
  601. package/dist/routes/cases.js.map +1 -0
  602. package/dist/routes/connect.js +268 -0
  603. package/dist/routes/connect.js.map +1 -0
  604. package/dist/routes/connection-presets.js +32 -0
  605. package/dist/routes/connection-presets.js.map +1 -0
  606. package/dist/routes/connections.js +177 -0
  607. package/dist/routes/connections.js.map +1 -0
  608. package/dist/routes/disk.js +19 -0
  609. package/dist/routes/disk.js.map +1 -0
  610. package/dist/routes/docs.js +71 -0
  611. package/dist/routes/docs.js.map +1 -0
  612. package/dist/routes/dot-suggest.js +1002 -0
  613. package/dist/routes/dot-suggest.js.map +1 -0
  614. package/dist/routes/evidence-pack.js +16 -0
  615. package/dist/routes/evidence-pack.js.map +1 -0
  616. package/dist/routes/health.js +121 -0
  617. package/dist/routes/health.js.map +1 -0
  618. package/dist/routes/impact.js +48 -0
  619. package/dist/routes/impact.js.map +1 -0
  620. package/dist/routes/lead.js +50 -0
  621. package/dist/routes/lead.js.map +1 -0
  622. package/dist/routes/links.js +13 -0
  623. package/dist/routes/links.js.map +1 -0
  624. package/dist/routes/markdown.js +62 -0
  625. package/dist/routes/markdown.js.map +1 -0
  626. package/dist/routes/onboarding.js +47 -0
  627. package/dist/routes/onboarding.js.map +1 -0
  628. package/dist/routes/phone.js +231 -0
  629. package/dist/routes/phone.js.map +1 -0
  630. package/dist/routes/release-notes.js +30 -0
  631. package/dist/routes/release-notes.js.map +1 -0
  632. package/dist/routes/reports.js +102 -0
  633. package/dist/routes/reports.js.map +1 -0
  634. package/dist/routes/repos.js +91 -0
  635. package/dist/routes/repos.js.map +1 -0
  636. package/dist/routes/review.js +283 -0
  637. package/dist/routes/review.js.map +1 -0
  638. package/dist/routes/roles.js +114 -0
  639. package/dist/routes/roles.js.map +1 -0
  640. package/dist/routes/room.js +21 -0
  641. package/dist/routes/room.js.map +1 -0
  642. package/dist/routes/runner.js +156 -0
  643. package/dist/routes/runner.js.map +1 -0
  644. package/dist/routes/runs.js +84 -0
  645. package/dist/routes/runs.js.map +1 -0
  646. package/dist/routes/setup.js +18 -0
  647. package/dist/routes/setup.js.map +1 -0
  648. package/dist/routes/test-runs.js +220 -0
  649. package/dist/routes/test-runs.js.map +1 -0
  650. package/dist/routes/ticket-status.js +17 -0
  651. package/dist/routes/ticket-status.js.map +1 -0
  652. package/dist/routes/traceability.js +143 -0
  653. package/dist/routes/traceability.js.map +1 -0
  654. package/dist/routes/true.js +142 -0
  655. package/dist/routes/true.js.map +1 -0
  656. package/dist/routes/updates.js +70 -0
  657. package/dist/routes/updates.js.map +1 -0
  658. package/dist/runner/adapters/index.js +12 -0
  659. package/dist/runner/adapters/index.js.map +1 -0
  660. package/dist/runner/adapters/playwright.js +68 -0
  661. package/dist/runner/adapters/playwright.js.map +1 -0
  662. package/dist/runner/aivision/cases.js +172 -0
  663. package/dist/runner/aivision/cases.js.map +1 -0
  664. package/dist/runner/aivision/cli.js +201 -0
  665. package/dist/runner/aivision/cli.js.map +1 -0
  666. package/dist/runner/aivision/index.js +281 -0
  667. package/dist/runner/aivision/index.js.map +1 -0
  668. package/dist/runner/aivision/server.js +394 -0
  669. package/dist/runner/aivision/server.js.map +1 -0
  670. package/dist/runner/aivision/shared.js +140 -0
  671. package/dist/runner/aivision/shared.js.map +1 -0
  672. package/dist/runner/artifact-cap.js +189 -0
  673. package/dist/runner/artifact-cap.js.map +1 -0
  674. package/dist/runner/artifacts.js +433 -0
  675. package/dist/runner/artifacts.js.map +1 -0
  676. package/dist/runner/command.js +564 -0
  677. package/dist/runner/command.js.map +1 -0
  678. package/dist/runner/copyfiles.js +221 -0
  679. package/dist/runner/copyfiles.js.map +1 -0
  680. package/dist/runner/engines.js +32 -0
  681. package/dist/runner/engines.js.map +1 -0
  682. package/dist/runner/evidence.js +114 -0
  683. package/dist/runner/evidence.js.map +1 -0
  684. package/dist/runner/host-env.js +160 -0
  685. package/dist/runner/host-env.js.map +1 -0
  686. package/dist/runner/index.js +1221 -0
  687. package/dist/runner/index.js.map +1 -0
  688. package/dist/runner/observe.js +603 -0
  689. package/dist/runner/observe.js.map +1 -0
  690. package/dist/runner/playwright-json.js +108 -0
  691. package/dist/runner/playwright-json.js.map +1 -0
  692. package/dist/runner/pwgen/exec.js +192 -0
  693. package/dist/runner/pwgen/exec.js.map +1 -0
  694. package/dist/runner/pwgen/explore.js +111 -0
  695. package/dist/runner/pwgen/explore.js.map +1 -0
  696. package/dist/runner/pwgen/index.js +423 -0
  697. package/dist/runner/pwgen/index.js.map +1 -0
  698. package/dist/runner/pwgen/propose.js +69 -0
  699. package/dist/runner/pwgen/propose.js.map +1 -0
  700. package/dist/runner/pwgen/source.js +632 -0
  701. package/dist/runner/pwgen/source.js.map +1 -0
  702. package/dist/runner/setup.js +222 -0
  703. package/dist/runner/setup.js.map +1 -0
  704. package/dist/runner/step-reporter.js +107 -0
  705. package/dist/runner/step-reporter.js.map +1 -0
  706. package/dist/runner/test-repo.js +326 -0
  707. package/dist/runner/test-repo.js.map +1 -0
  708. package/dist/runner/typed-value.js +46 -0
  709. package/dist/runner/typed-value.js.map +1 -0
  710. package/dist/runner/verify.js +133 -0
  711. package/dist/runner/verify.js.map +1 -0
  712. package/dist/runner/worktree.js +349 -0
  713. package/dist/runner/worktree.js.map +1 -0
  714. package/dist/sandbox.js +61 -0
  715. package/dist/sandbox.js.map +1 -0
  716. package/dist/server.js +262 -0
  717. package/dist/server.js.map +1 -0
  718. package/dist/shadow-week.js +126 -0
  719. package/dist/shadow-week.js.map +1 -0
  720. package/dist/shutdown.js +92 -0
  721. package/dist/shutdown.js.map +1 -0
  722. package/dist/slack/index.js +645 -0
  723. package/dist/slack/index.js.map +1 -0
  724. package/dist/stages/config.js +147 -0
  725. package/dist/stages/config.js.map +1 -0
  726. package/dist/stages/index.js +41 -0
  727. package/dist/stages/index.js.map +1 -0
  728. package/dist/suites.js +293 -0
  729. package/dist/suites.js.map +1 -0
  730. package/dist/target-url.js +116 -0
  731. package/dist/target-url.js.map +1 -0
  732. package/dist/test-runs.js +662 -0
  733. package/dist/test-runs.js.map +1 -0
  734. package/dist/ticket-keys.js +97 -0
  735. package/dist/ticket-keys.js.map +1 -0
  736. package/dist/ticket-supersede.js +105 -0
  737. package/dist/ticket-supersede.js.map +1 -0
  738. package/dist/tinybee/ed25519.js +99 -0
  739. package/dist/tinybee/ed25519.js.map +1 -0
  740. package/dist/tinybee/models-routes.js +19 -0
  741. package/dist/tinybee/models-routes.js.map +1 -0
  742. package/dist/tinybee/pair-payload.js +41 -0
  743. package/dist/tinybee/pair-payload.js.map +1 -0
  744. package/dist/tinybee/update-manifest.js +77 -0
  745. package/dist/tinybee/update-manifest.js.map +1 -0
  746. package/dist/tinybee/well-known.js +64 -0
  747. package/dist/tinybee/well-known.js.map +1 -0
  748. package/dist/tinybee/workflows/activity.js +23 -0
  749. package/dist/tinybee/workflows/activity.js.map +1 -0
  750. package/dist/tinybee/workflows/cron.js +210 -0
  751. package/dist/tinybee/workflows/cron.js.map +1 -0
  752. package/dist/tinybee/workflows/engine.js +371 -0
  753. package/dist/tinybee/workflows/engine.js.map +1 -0
  754. package/dist/tinybee/workflows/from-text.js +203 -0
  755. package/dist/tinybee/workflows/from-text.js.map +1 -0
  756. package/dist/tinybee/workflows/routes.js +189 -0
  757. package/dist/tinybee/workflows/routes.js.map +1 -0
  758. package/dist/tinybee/workflows/scheduler.js +100 -0
  759. package/dist/tinybee/workflows/scheduler.js.map +1 -0
  760. package/dist/tinybee/workflows/skills.js +227 -0
  761. package/dist/tinybee/workflows/skills.js.map +1 -0
  762. package/dist/tinybee/workflows/store.js +205 -0
  763. package/dist/tinybee/workflows/store.js.map +1 -0
  764. package/dist/tinybee/workflows/types.js +180 -0
  765. package/dist/tinybee/workflows/types.js.map +1 -0
  766. package/dist/tinybee/workflows/yaml.js +323 -0
  767. package/dist/tinybee/workflows/yaml.js.map +1 -0
  768. package/dist/true/api.js +495 -0
  769. package/dist/true/api.js.map +1 -0
  770. package/dist/true/client.js +292 -0
  771. package/dist/true/client.js.map +1 -0
  772. package/dist/true/clock.js +36 -0
  773. package/dist/true/clock.js.map +1 -0
  774. package/dist/true/events.js +125 -0
  775. package/dist/true/events.js.map +1 -0
  776. package/dist/true/hosts.js +98 -0
  777. package/dist/true/hosts.js.map +1 -0
  778. package/dist/true/index.js +29 -0
  779. package/dist/true/index.js.map +1 -0
  780. package/dist/true/key.js +54 -0
  781. package/dist/true/key.js.map +1 -0
  782. package/dist/true/line.js +69 -0
  783. package/dist/true/line.js.map +1 -0
  784. package/dist/true/mask.js +31 -0
  785. package/dist/true/mask.js.map +1 -0
  786. package/dist/true/names.js +114 -0
  787. package/dist/true/names.js.map +1 -0
  788. package/dist/true/outbox.js +233 -0
  789. package/dist/true/outbox.js.map +1 -0
  790. package/dist/true/replay.js +164 -0
  791. package/dist/true/replay.js.map +1 -0
  792. package/dist/true/settings.js +123 -0
  793. package/dist/true/settings.js.map +1 -0
  794. package/dist/true/status.js +189 -0
  795. package/dist/true/status.js.map +1 -0
  796. package/dist/true/sync-cases.js +222 -0
  797. package/dist/true/sync-cases.js.map +1 -0
  798. package/dist/true/sync-manual.js +295 -0
  799. package/dist/true/sync-manual.js.map +1 -0
  800. package/dist/true/sync-runs.js +109 -0
  801. package/dist/true/sync-runs.js.map +1 -0
  802. package/dist/true/worker.js +414 -0
  803. package/dist/true/worker.js.map +1 -0
  804. package/dist/types.js +32 -0
  805. package/dist/types.js.map +1 -0
  806. package/dist/updates/asks.js +38 -0
  807. package/dist/updates/asks.js.map +1 -0
  808. package/dist/updates/index.js +835 -0
  809. package/dist/updates/index.js.map +1 -0
  810. package/dist/updates/owner.js +24 -0
  811. package/dist/updates/owner.js.map +1 -0
  812. package/dist/updates/prefs.js +118 -0
  813. package/dist/updates/prefs.js.map +1 -0
  814. package/dist/updates/route.js +78 -0
  815. package/dist/updates/route.js.map +1 -0
  816. package/dist/updates/sources.js +345 -0
  817. package/dist/updates/sources.js.map +1 -0
  818. package/dist/updates/words.js +452 -0
  819. package/dist/updates/words.js.map +1 -0
  820. package/dist/version.js +53 -0
  821. package/dist/version.js.map +1 -0
  822. package/dist/view-compute.js +382 -0
  823. package/dist/view-compute.js.map +1 -0
  824. package/dist/view-spec.js +894 -0
  825. package/dist/view-spec.js.map +1 -0
  826. package/dist/web/apple-touch-icon.png +0 -0
  827. package/dist/web/assets/ApprovalCard-Br_z5z7G.css +1 -0
  828. package/dist/web/assets/ApprovalCard-CfGhGFo_.js +3 -0
  829. package/dist/web/assets/CardFromRef-BaTGmZ9c.js +2 -0
  830. package/dist/web/assets/CardFromRef-DO7i2uDd.css +1 -0
  831. package/dist/web/assets/Cases-8l_6UcLh.js +2 -0
  832. package/dist/web/assets/Cases-CpfED0uB.css +1 -0
  833. package/dist/web/assets/Chat-BKDiR0qt.js +3 -0
  834. package/dist/web/assets/Chat-DxjdyYUu.css +1 -0
  835. package/dist/web/assets/ConfirmDialog-CIMveD-b.js +2 -0
  836. package/dist/web/assets/ConnectSheet-Cm5vbZdR.js +4 -0
  837. package/dist/web/assets/Docs-HKGuY0WE.js +2 -0
  838. package/dist/web/assets/Docs-fodKx8S7.css +1 -0
  839. package/dist/web/assets/DotDetail-DskS3NWe.js +2 -0
  840. package/dist/web/assets/DotDetail-OWRSD_1x.css +1 -0
  841. package/dist/web/assets/DotStage-BZDclfzV.css +1 -0
  842. package/dist/web/assets/DotStage-CtMNzCN3.js +2 -0
  843. package/dist/web/assets/Dots-BqCsS34m.js +2 -0
  844. package/dist/web/assets/EvidencePack-DQ3kCJX4.js +2 -0
  845. package/dist/web/assets/EvidencePack-DV_9ETsA.css +1 -0
  846. package/dist/web/assets/FailedDeliveries-1F2kFcs9.js +2 -0
  847. package/dist/web/assets/FailedDeliveries-DXa2_VvI.css +1 -0
  848. package/dist/web/assets/Feed-5wiHRTFK.js +2 -0
  849. package/dist/web/assets/GfmView-C-NYaduC.js +4 -0
  850. package/dist/web/assets/ImpactList-C-RNuDB0.js +2 -0
  851. package/dist/web/assets/ImpactList-C612dFdw.css +1 -0
  852. package/dist/web/assets/Inbox-kc1bKVL_.js +2 -0
  853. package/dist/web/assets/JoinScreen-C3L4wmP3.js +2 -0
  854. package/dist/web/assets/JoinScreen-COeAUv5v.css +1 -0
  855. package/dist/web/assets/LeadDialog-N3Zul9Rw.js +8 -0
  856. package/dist/web/assets/LeadDialog-xyWjAuAS.css +1 -0
  857. package/dist/web/assets/ListeningLine-BRFNaczY.js +2 -0
  858. package/dist/web/assets/ListeningLine-pN8CgyiK.css +1 -0
  859. package/dist/web/assets/Mascots-pIyGpxtD.js +2 -0
  860. package/dist/web/assets/ModelChoices-BxO1zyyr.js +2 -0
  861. package/dist/web/assets/ModelChoices-DQJnVxfs.css +1 -0
  862. package/dist/web/assets/NewDotDialog-CDPUWmgN.js +2 -0
  863. package/dist/web/assets/NewDotDialog-DrPPqkSZ.css +1 -0
  864. package/dist/web/assets/NewTestRunDialog-BQBthVHE.js +2 -0
  865. package/dist/web/assets/NoBreakNames-Csxdqdt6.js +2 -0
  866. package/dist/web/assets/Pair-omex_K7H.js +2 -0
  867. package/dist/web/assets/PushSection-CmqHlE_2.js +2 -0
  868. package/dist/web/assets/ReleaseNotes-B6VqFewP.js +2 -0
  869. package/dist/web/assets/ReleaseNotes-DBJUL7Vm.css +1 -0
  870. package/dist/web/assets/ReportPage-BHS1xWEt.js +162 -0
  871. package/dist/web/assets/Reports-BEHnDIb1.js +2 -0
  872. package/dist/web/assets/ReviewChangeDialog-BVSt-cw-.js +2 -0
  873. package/dist/web/assets/ReviewChangeDialog-BbIlHRx0.css +1 -0
  874. package/dist/web/assets/Room-BoG_uge4.js +2 -0
  875. package/dist/web/assets/Room-evAfiW_e.css +1 -0
  876. package/dist/web/assets/RunActions-ZY7yf1AF.js +2 -0
  877. package/dist/web/assets/RunDetail-C8St20GQ.css +1 -0
  878. package/dist/web/assets/RunDetail-qADXjBvd.js +9 -0
  879. package/dist/web/assets/RunRow-BKEJv8ib.js +2 -0
  880. package/dist/web/assets/RunnerTry-Dgpp67-s.js +6 -0
  881. package/dist/web/assets/RunnerTry-DsweWOfO.css +1 -0
  882. package/dist/web/assets/Settings-fs-QJwNM.js +2 -0
  883. package/dist/web/assets/Setup-DI6hBEP-.js +2 -0
  884. package/dist/web/assets/TestRows-wh03T5Li.js +4 -0
  885. package/dist/web/assets/TestRun-DTOyF-Pv.js +2 -0
  886. package/dist/web/assets/TestRuns-ggDjm1Q8.js +2 -0
  887. package/dist/web/assets/TinyBeeAddLaptop-bc3pmh3T.js +2 -0
  888. package/dist/web/assets/TinyBeeAi-CkyOzhm5.js +2 -0
  889. package/dist/web/assets/TinyBeeConnections-B2K_P38u.js +2 -0
  890. package/dist/web/assets/TinyBeeHome-DSpxX5KS.js +3 -0
  891. package/dist/web/assets/TinyBeePlan-BamiLziu.js +2 -0
  892. package/dist/web/assets/TinyBeeSignup-vHcz0Wen.js +2 -0
  893. package/dist/web/assets/TinyBeeSkills-By9RLUse.js +2 -0
  894. package/dist/web/assets/TinyBeeWorkflow-DeNO7Jsh.js +2 -0
  895. package/dist/web/assets/TinyBeeWorkflowEditor-B6OGC2OT.js +2 -0
  896. package/dist/web/assets/TinyBeeWorkflows-BN4-h6lt.js +2 -0
  897. package/dist/web/assets/Trace-BBCI1aIB.css +1 -0
  898. package/dist/web/assets/Trace-aF92UWaH.js +2 -0
  899. package/dist/web/assets/UpdatesSection-CCWEbkue.js +2 -0
  900. package/dist/web/assets/Welcome-CCcy558Q.js +2 -0
  901. package/dist/web/assets/activity-C3qilrDm.css +1 -0
  902. package/dist/web/assets/activity-CBfTSxqw.js +2 -0
  903. package/dist/web/assets/authedMedia-BTYt_tyu.js +2 -0
  904. package/dist/web/assets/beeApi-BHW8Tx1s.js +2 -0
  905. package/dist/web/assets/data-CmXvx3Mj.js +2 -0
  906. package/dist/web/assets/engines-CfdJODFj.css +1 -0
  907. package/dist/web/assets/format-BBZ8vFyT.js +2 -0
  908. package/dist/web/assets/forms-Coc7p2UF.css +1 -0
  909. package/dist/web/assets/hivePush-DZJDokj7.js +2 -0
  910. package/dist/web/assets/impactModel-MY1OFuiP.js +2 -0
  911. package/dist/web/assets/index-B6qKm1NW.js +13 -0
  912. package/dist/web/assets/index-BvKyT1X7.css +1 -0
  913. package/dist/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  914. package/dist/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  915. package/dist/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  916. package/dist/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  917. package/dist/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  918. package/dist/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  919. package/dist/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  920. package/dist/web/assets/lead-BL_P_kri.css +1 -0
  921. package/dist/web/assets/model-BIQy5IVG.js +2 -0
  922. package/dist/web/assets/modelsApi-PUSySRQw.js +2 -0
  923. package/dist/web/assets/newDotModel-BaLLyw57.js +2 -0
  924. package/dist/web/assets/onboarding-bfKqnM4Z.css +1 -0
  925. package/dist/web/assets/phone-Rs7FoyG0.css +1 -0
  926. package/dist/web/assets/phoneApi-BG_1-M-D.js +3 -0
  927. package/dist/web/assets/releaseModel-EynYMVOC.js +2 -0
  928. package/dist/web/assets/releaseNotesModel-A1Rtv3cV.js +2 -0
  929. package/dist/web/assets/reports-BWaA1HhM.js +37 -0
  930. package/dist/web/assets/reports-DXwdWQsB.css +1 -0
  931. package/dist/web/assets/router-W6nZsQ33.js +2 -0
  932. package/dist/web/assets/runs-BY0Owv93.css +1 -0
  933. package/dist/web/assets/shadowWeekModel-BUUiww09.js +2 -0
  934. package/dist/web/assets/storage-yvL36AWt.js +2 -0
  935. package/dist/web/assets/store-IqrqHuFR.js +2 -0
  936. package/dist/web/assets/testruns-BzIZ0cR0.css +1 -0
  937. package/dist/web/assets/testruns-DyaqX4ji.js +2 -0
  938. package/dist/web/assets/true-9Q68cs5b.js +2 -0
  939. package/dist/web/assets/true-DPGBpoir.css +1 -0
  940. package/dist/web/assets/ui-DcmhYyYp.js +13 -0
  941. package/dist/web/assets/ui-DxEDgbIx.css +1 -0
  942. package/dist/web/assets/usePauseDot-BV60ZVy1.js +2 -0
  943. package/dist/web/assets/usePauseDot-NrSzMI1C.css +1 -0
  944. package/dist/web/assets/usePush-Dsm-TjlG.js +2 -0
  945. package/dist/web/assets/useRefChips-CbafNx59.js +68 -0
  946. package/dist/web/assets/useRestoreDot-D0B6W82H.js +2 -0
  947. package/dist/web/assets/view-worker-pyeVAhUT.js +2 -0
  948. package/dist/web/assets/workflowUi-QYsd3n9J.js +2 -0
  949. package/dist/web/favicon.png +0 -0
  950. package/dist/web/icon-192.png +0 -0
  951. package/dist/web/icon-512.png +0 -0
  952. package/dist/web/icon-maskable-512.png +0 -0
  953. package/dist/web/index.html +45 -0
  954. package/dist/web/manifest.webmanifest +23 -0
  955. package/dist/web/mascots/argus-attention.svg +7 -0
  956. package/dist/web/mascots/argus-ok.svg +7 -0
  957. package/dist/web/mascots/argus-outage.svg +7 -0
  958. package/dist/web/mascots/argus-running.svg +7 -0
  959. package/dist/web/mascots/bolt-attention.svg +7 -0
  960. package/dist/web/mascots/bolt-ok.svg +7 -0
  961. package/dist/web/mascots/bolt-outage.svg +7 -0
  962. package/dist/web/mascots/bolt-running.svg +7 -0
  963. package/dist/web/mascots/echo-attention.svg +7 -0
  964. package/dist/web/mascots/echo-ok.svg +7 -0
  965. package/dist/web/mascots/echo-outage.svg +7 -0
  966. package/dist/web/mascots/echo-running.svg +7 -0
  967. package/dist/web/mascots/lens-attention.svg +7 -0
  968. package/dist/web/mascots/lens-ok.svg +7 -0
  969. package/dist/web/mascots/lens-outage.svg +7 -0
  970. package/dist/web/mascots/lens-running.svg +7 -0
  971. package/dist/web/mascots/moss-attention.svg +7 -0
  972. package/dist/web/mascots/moss-ok.svg +7 -0
  973. package/dist/web/mascots/moss-outage.svg +7 -0
  974. package/dist/web/mascots/moss-running.svg +7 -0
  975. package/dist/web/mascots/nit-attention.svg +7 -0
  976. package/dist/web/mascots/nit-ok.svg +7 -0
  977. package/dist/web/mascots/nit-outage.svg +7 -0
  978. package/dist/web/mascots/nit-running.svg +7 -0
  979. package/dist/web/mascots/nova-attention.svg +7 -0
  980. package/dist/web/mascots/nova-ok.svg +7 -0
  981. package/dist/web/mascots/nova-outage.svg +7 -0
  982. package/dist/web/mascots/nova-running.svg +7 -0
  983. package/dist/web/mascots/penn-attention.svg +7 -0
  984. package/dist/web/mascots/penn-ok.svg +7 -0
  985. package/dist/web/mascots/penn-outage.svg +7 -0
  986. package/dist/web/mascots/penn-running.svg +7 -0
  987. package/dist/web/mascots/pip-attention.svg +7 -0
  988. package/dist/web/mascots/pip-ok.svg +7 -0
  989. package/dist/web/mascots/pip-outage.svg +7 -0
  990. package/dist/web/mascots/pip-running.svg +7 -0
  991. package/dist/web/mascots/ward-attention.svg +7 -0
  992. package/dist/web/mascots/ward-ok.svg +7 -0
  993. package/dist/web/mascots/ward-outage.svg +7 -0
  994. package/dist/web/mascots/ward-running.svg +7 -0
  995. package/dist/web/sw.js +98 -0
  996. package/dist/webhook-seen.js +53 -0
  997. package/dist/webhook-seen.js.map +1 -0
  998. package/dist/webhooks.js +625 -0
  999. package/dist/webhooks.js.map +1 -0
  1000. package/dist/zip.js +63 -0
  1001. package/dist/zip.js.map +1 -0
  1002. package/docs/API-V2.md +532 -0
  1003. package/docs/CHAT-EVAL.md +130 -0
  1004. package/docs/CHAT-UI.md +416 -0
  1005. package/docs/CONNECTIONS.md +89 -0
  1006. package/docs/DATA-MODEL.md +518 -0
  1007. package/docs/DEPLOY.md +577 -0
  1008. package/docs/DOGFOOD-LEDGER.md +81 -0
  1009. package/docs/GITHUB.md +148 -0
  1010. package/docs/INTEGRATION-MODEL.md +200 -0
  1011. package/docs/LEAD-DOT.md +553 -0
  1012. package/docs/LIST-PATTERNS.md +52 -0
  1013. package/docs/MULTI-REPO.md +766 -0
  1014. package/docs/PARITY.md +276 -0
  1015. package/docs/PR-REVIEW-QA.md +1266 -0
  1016. package/docs/PR-REVIEW.md +357 -0
  1017. package/docs/SANDBOX.md +320 -0
  1018. package/docs/SETUP.md +776 -0
  1019. package/docs/SLACK.md +80 -0
  1020. package/docs/STAGES.md +619 -0
  1021. package/docs/TRACE-MAP.md +89 -0
  1022. package/docs/TRACKERS.md +225 -0
  1023. package/docs/VOICE.md +36 -0
  1024. package/docs/tinybee/00-README.md +45 -0
  1025. package/docs/tinybee/01-PRD.md +216 -0
  1026. package/docs/tinybee/02-architecture-pairing.md +199 -0
  1027. package/docs/tinybee/03-local-agent.md +222 -0
  1028. package/docs/tinybee/04-local-setup-ui.md +128 -0
  1029. package/docs/tinybee/05-mobile-app-ux.md +199 -0
  1030. package/docs/tinybee/06-environments-and-delivery.md +148 -0
  1031. package/docs/tinybee/07-coding-agent-handoff.md +116 -0
  1032. package/docs/tinybee/OPEN-QUESTIONS.md +26 -0
  1033. package/docs/tinybee/PROGRESS.md +134 -0
  1034. package/package.json +111 -4
@@ -0,0 +1,163 @@
1
+ // Tiny shop used by the demo. A seeded bug (checkout total ignores the discount) is toggled
2
+ // with GET /__localdost/bug?on=1 so a simulated merge produces a real failing Playwright test.
3
+ // Erasable TypeScript only, so Node 24 can run this file directly.
4
+ import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http';
5
+ import { pathToFileURL } from 'node:url';
6
+
7
+ const PRODUCT = { sku: 'TRAIL-01', name: 'Trail Running Shoes', price: 120 };
8
+ const CODES: Record<string, number> = { LOYAL10: 0.1, WELCOME5: 0.05 };
9
+
10
+ let bugOn = false;
11
+ let running: { server: Server; url: string } | undefined;
12
+
13
+ interface Cart {
14
+ qty: number;
15
+ code: string;
16
+ }
17
+
18
+ function money(n: number): string {
19
+ return `$${n.toFixed(2)}`;
20
+ }
21
+
22
+ function readCart(req: IncomingMessage): Cart {
23
+ const raw = /(?:^|;\s*)cart=([^;]+)/.exec(req.headers.cookie ?? '')?.[1];
24
+ if (!raw) return { qty: 0, code: '' };
25
+ const [qty, code] = decodeURIComponent(raw).split(':');
26
+ return { qty: Math.max(0, Math.min(99, Number(qty) || 0)), code: (code ?? '').toUpperCase() };
27
+ }
28
+
29
+ /** The real pricing logic; the seeded bug skips the discount. */
30
+ export function totals(cart: Cart, bug = bugOn) {
31
+ const subtotal = cart.qty * PRODUCT.price;
32
+ const rate = CODES[cart.code] ?? 0;
33
+ const discount = Math.round(subtotal * rate * 100) / 100;
34
+ const total = bug ? subtotal : subtotal - discount;
35
+ return { subtotal, discount, total };
36
+ }
37
+
38
+ function page(title: string, body: string): string {
39
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
40
+ <title>${title} | Demo Shop</title>
41
+ <style>body{font-family:system-ui,sans-serif;max-width:480px;margin:24px auto;padding:0 16px;color:#1d1d29}
42
+ button{background:#6059E4;color:#fff;border:0;border-radius:8px;padding:10px 16px;font-size:16px}
43
+ input{padding:8px;font-size:16px;width:120px}label{display:block;margin:8px 0}
44
+ dl{display:grid;grid-template-columns:1fr auto;gap:6px}dd{margin:0;text-align:right}</style>
45
+ </head><body><header><a href="/">Demo Shop</a></header>${body}</body></html>`;
46
+ }
47
+
48
+ function send(res: ServerResponse, status: number, html: string, headers: Record<string, string> = {}): void {
49
+ res.writeHead(status, { 'content-type': 'text/html; charset=utf-8', ...headers });
50
+ res.end(html);
51
+ }
52
+
53
+ function json(res: ServerResponse, value: unknown): void {
54
+ res.writeHead(200, { 'content-type': 'application/json' });
55
+ res.end(JSON.stringify(value));
56
+ }
57
+
58
+ async function readBody(req: IncomingMessage): Promise<URLSearchParams> {
59
+ let data = '';
60
+ for await (const chunk of req) {
61
+ data += chunk;
62
+ if (data.length > 10_000) break;
63
+ }
64
+ return new URLSearchParams(data);
65
+ }
66
+
67
+ async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {
68
+ const url = new URL(req.url ?? '/', 'http://localhost');
69
+
70
+ if (url.pathname === '/health') return json(res, { ok: true, bug: bugOn });
71
+
72
+ if (url.pathname === '/__localdost/bug') {
73
+ bugOn = url.searchParams.get('on') === '1';
74
+ return json(res, { bug: bugOn });
75
+ }
76
+
77
+ if (url.pathname === '/' && req.method === 'GET') {
78
+ return send(
79
+ res,
80
+ 200,
81
+ page(
82
+ PRODUCT.name,
83
+ `<main><h1>${PRODUCT.name}</h1><p data-testid="price">${money(PRODUCT.price)}</p>
84
+ <form method="post" action="/cart">
85
+ <label>Quantity <input name="qty" type="number" min="1" max="99" value="1"></label>
86
+ <label>Discount code <input name="code" placeholder="LOYAL10"></label>
87
+ <button type="submit">Add to cart</button></form></main>`,
88
+ ),
89
+ );
90
+ }
91
+
92
+ if (url.pathname === '/cart' && req.method === 'POST') {
93
+ const form = await readBody(req);
94
+ const qty = Math.max(1, Math.min(99, Number(form.get('qty')) || 1));
95
+ const code = (form.get('code') ?? '')
96
+ .trim()
97
+ .toUpperCase()
98
+ .replace(/[^A-Z0-9]/g, '');
99
+ res.writeHead(303, { location: '/checkout', 'set-cookie': `cart=${encodeURIComponent(`${qty}:${code}`)}; Path=/; HttpOnly; SameSite=Lax` });
100
+ res.end();
101
+ return;
102
+ }
103
+
104
+ if (url.pathname === '/checkout' && req.method === 'GET') {
105
+ const cart = readCart(req);
106
+ if (!cart.qty) return send(res, 200, page('Checkout', '<main><h1>Checkout</h1><p data-testid="empty">Your cart is empty.</p></main>'));
107
+ const t = totals(cart);
108
+ return send(
109
+ res,
110
+ 200,
111
+ page(
112
+ 'Checkout',
113
+ `<main><h1>Checkout</h1><dl>
114
+ <dt>${cart.qty} x ${PRODUCT.name}</dt><dd data-testid="subtotal">${money(t.subtotal)}</dd>
115
+ <dt>Discount${cart.code ? ` (${cart.code})` : ''}</dt><dd data-testid="discount">-${money(t.discount)}</dd>
116
+ <dt><strong>Total</strong></dt><dd><strong data-testid="total">${money(t.total)}</strong></dd>
117
+ </dl><button type="button">Pay now</button></main>`,
118
+ ),
119
+ );
120
+ }
121
+
122
+ send(res, 404, page('Not found', '<main><h1>Not found</h1></main>'));
123
+ }
124
+
125
+ async function stop(): Promise<void> {
126
+ const r = running;
127
+ running = undefined;
128
+ if (r) await new Promise<void>((resolve) => r.server.close(() => resolve()));
129
+ }
130
+
131
+ export async function startSampleApp(port = 4320): Promise<{ url: string; close: () => Promise<void> }> {
132
+ if (running) return { url: running.url, close: stop };
133
+ const server = createServer((req, res) => {
134
+ handle(req, res).catch((err) => {
135
+ res.writeHead(500);
136
+ res.end(String(err));
137
+ });
138
+ });
139
+ await new Promise<void>((resolve, reject) => {
140
+ server.once('error', reject);
141
+ // no host: dual-stack, so both localhost (::1) and 127.0.0.1 reach it
142
+ server.listen(port, () => resolve());
143
+ });
144
+ // The shop never keeps a process alive on its own: a run or a test that started it in-process can still exit.
145
+ // The localdost server, when it runs, keeps the process up anyway.
146
+ server.unref();
147
+ running = { server, url: `http://localhost:${port}` };
148
+ return { url: running.url, close: stop };
149
+ }
150
+
151
+ export function setBug(on: boolean): void {
152
+ bugOn = on;
153
+ }
154
+
155
+ // `node server.ts` starts it standalone; the Playwright webServer uses this.
156
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
157
+ const port = Number(process.argv[2] ?? 4320);
158
+ startSampleApp(port).then(({ url }) => {
159
+ // Standalone, the shop is the whole process, so it holds the process open.
160
+ running?.server.ref();
161
+ console.log(`demo shop on ${url}`);
162
+ });
163
+ }
@@ -0,0 +1,13 @@
1
+ import { expect, test } from '@playwright/test';
2
+
3
+ test('discount applied at checkout', async ({ page }) => {
4
+ await page.goto('/');
5
+ await page.getByLabel('Quantity').fill('1');
6
+ await page.getByLabel('Discount code').fill('LOYAL10');
7
+ await page.getByRole('button', { name: 'Add to cart' }).click();
8
+
9
+ await expect(page).toHaveURL(/\/checkout$/);
10
+ await expect(page.getByTestId('subtotal')).toHaveText('$120.00');
11
+ await expect(page.getByTestId('discount')).toHaveText('-$12.00');
12
+ await expect(page.getByTestId('total')).toHaveText('$108.00');
13
+ });
@@ -0,0 +1,8 @@
1
+ import { expect, test } from '@playwright/test';
2
+
3
+ test('home page loads @smoke', async ({ page }) => {
4
+ await page.goto('/');
5
+ await expect(page.getByRole('heading', { name: 'Trail Running Shoes' })).toBeVisible();
6
+ await expect(page.getByTestId('price')).toHaveText('$120.00');
7
+ await expect(page.getByRole('button', { name: 'Add to cart' })).toBeEnabled();
8
+ });
@@ -0,0 +1,59 @@
1
+ // Sends approved drafts again when their automatic retry is due (KAT-178). The schedule is the `retry` state on the
2
+ // approval row (agent/send-retry.ts), so nothing lives only in memory: after a restart the first tick sends whatever
3
+ // came due while the server was down.
4
+ import { get, list, update } from '../db.js';
5
+ import { publish } from '../events.js';
6
+ import { log } from '../config.js';
7
+ import { approveAction } from './rules.js';
8
+ export const RETRY_TICK_MS = 15_000;
9
+ const intervalSchedule = (fn, ms) => {
10
+ const t = setInterval(fn, ms);
11
+ t.unref?.();
12
+ return () => clearInterval(t);
13
+ };
14
+ /** Pending approvals whose retry is due at `now`. */
15
+ export function dueRetries(now) {
16
+ return list('approvals', { status: 'pending' }).filter((a) => a.retry && Date.parse(a.retry.nextAt) <= now);
17
+ }
18
+ /**
19
+ * Sends every due retry once, one after the other. approveAction decides what comes next: a send that works
20
+ * ends the approval, a transient failure schedules the next retry, a permanent one puts the draft back in the Inbox.
21
+ * Returns how many it tried.
22
+ */
23
+ export async function runDueRetries(opts = {}) {
24
+ const now = opts.now ?? Date.now;
25
+ const approve = opts.approve ?? approveAction;
26
+ const due = dueRetries(now());
27
+ for (const a of due) {
28
+ try {
29
+ await approve(a.id, undefined, { now, auto: true });
30
+ }
31
+ catch (err) {
32
+ log.warn(`approval ${a.id}: retry failed: ${String(err)}`);
33
+ // A failure that left the schedule untouched (the dot is gone, say) would repeat every tick: hand it back to a person.
34
+ const cur = get('approvals', a.id);
35
+ if (cur && cur.status === 'pending' && cur.retry?.nextAt === a.retry?.nextAt) {
36
+ update('approvals', a.id, { retry: null, error: err instanceof Error ? err.message : String(err) });
37
+ publish({ type: 'approval', approval: get('approvals', a.id) });
38
+ }
39
+ }
40
+ }
41
+ return due.length;
42
+ }
43
+ /** Starts the retry loop: one pass now, then one every `intervalMs`. Returns the function that stops it. */
44
+ export function startApprovalRetries(opts = {}) {
45
+ let running = false;
46
+ const tick = () => {
47
+ if (running)
48
+ return;
49
+ running = true;
50
+ runDueRetries({ now: opts.now })
51
+ .catch((err) => log.warn(`approval retries: ${String(err)}`))
52
+ .finally(() => {
53
+ running = false;
54
+ });
55
+ };
56
+ tick();
57
+ return (opts.schedule ?? intervalSchedule)(tick, opts.intervalMs ?? RETRY_TICK_MS);
58
+ }
59
+ //# sourceMappingURL=approval-retries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-retries.js","sourceRoot":"","sources":["../../src/agent/approval-retries.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,qHAAqH;AACrH,sCAAsC;AACtC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAKpC,MAAM,gBAAgB,GAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;IAC5C,MAAM,CAAC,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;IACZ,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,qDAAqD;AACrD,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,CAAiB,WAAW,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;AAC9H,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA+D,EAAE;IACnG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,aAAa,CAAC;IAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,mBAAmB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3D,uHAAuH;YACvH,MAAM,GAAG,GAAG,GAAG,CAAiB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;gBAC7E,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpG,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAiB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAE,EAAE,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,4GAA4G;AAC5G,MAAM,UAAU,oBAAoB,CAAC,OAAyE,EAAE;IAC9G,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,aAAa,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;aAC7B,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;aAC5D,OAAO,CAAC,GAAG,EAAE;YACZ,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IACF,IAAI,EAAE,CAAC;IACP,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC;AACrF,CAAC"}
@@ -0,0 +1,390 @@
1
+ // Approval queue hygiene (KAT-94): one pending approval per (action kind, target), and drafts whose
2
+ // PR merged or closed, or whose commit is no longer the PR head, close on their own.
3
+ import { db, get, list, update } from '../db.js';
4
+ import { publish } from '../events.js';
5
+ import { watchRepos } from '../repos.js';
6
+ import { addStep, updateActionResult } from './runs.js';
7
+ /**
8
+ * Drafts made for one head of a PR besides its comment and check: the defects found at that head, the new evidence
9
+ * for an existing defect, and the design questions on its ticket (dogfood ledger: defects for an older head of a PR).
10
+ */
11
+ export function headScoped(action) {
12
+ const m = action.meta ?? {};
13
+ if (action.kind === 'file_defect' || action.kind === 'issue_create')
14
+ return typeof m.head === 'string' && !!m.head;
15
+ if (action.kind === 'ticket_comment')
16
+ return (m.defectComment === true || m.designQuestion === true || m.append === true) && typeof m.head === 'string' && !!m.head;
17
+ return false;
18
+ }
19
+ /** The PR an action belongs to: meta.pr, else the `#N` at the end of a `github:owner/repo#N` target. */
20
+ export function prOf(action) {
21
+ // Only PR artifacts: a ticket comment on a GitHub issue has a `#N` target too, and it is not a PR.
22
+ const scoped = headScoped(action);
23
+ if (action.kind !== 'pr_comment' && action.kind !== 'check_run' && !scoped)
24
+ return undefined;
25
+ const n = Number(action.meta?.pr);
26
+ if (Number.isInteger(n) && n > 0)
27
+ return n;
28
+ if (scoped)
29
+ return undefined;
30
+ const m = /^github:[^#@\s]+#(\d+)$/.exec(action.target);
31
+ return m ? Number(m[1]) : undefined;
32
+ }
33
+ /**
34
+ * The repo a PR draft belongs to, lower case: from a `github:` target, else meta.repo ("owner/name"). A defect draft and
35
+ * its evidence comment name the repo the defect is filed in, which can be a tracker repo that holds no code (KAT-355),
36
+ * so for those meta.repo (the repo of the PR) wins.
37
+ */
38
+ function repoOfAction(action) {
39
+ const metaRepo = typeof action.meta?.repo === 'string' ? action.meta.repo.toLowerCase() : undefined;
40
+ if (headScoped(action) && metaRepo)
41
+ return metaRepo;
42
+ return repoOfTarget(action.target) ?? metaRepo;
43
+ }
44
+ /**
45
+ * True when a PR-state change in `repo` may touch this draft. A PR number belongs to one repo, so in a dot with more than
46
+ * one repo a draft whose repo is unknown is left alone: it may be another repo's PR with the same number (KAT-323).
47
+ */
48
+ function inRepoOf(a, repo, multiRepo) {
49
+ const target = repoOfAction(a.action);
50
+ if (!repo)
51
+ return true;
52
+ if (!target)
53
+ return !multiRepo;
54
+ return target === repo.toLowerCase();
55
+ }
56
+ function isMultiRepo(watchId) {
57
+ const w = get('watches', watchId);
58
+ return !!w && watchRepos(w).length > 1;
59
+ }
60
+ /** "owner/repo" of a `github:owner/repo#N` or `github:owner/repo@sha` target, lower case. */
61
+ export function repoOfTarget(target) {
62
+ const m = /^github:([^#@\s]+)/.exec(target);
63
+ return m ? m[1].toLowerCase() : undefined;
64
+ }
65
+ /** A pending approval that has not passed its expiresAt. Only these count on the dot badge. */
66
+ export function isLive(a, now = Date.now()) {
67
+ return a.status === 'pending' && !(a.expiresAt && Date.parse(a.expiresAt) <= now);
68
+ }
69
+ export function liveCount(watchId, now = Date.now()) {
70
+ const row = db
71
+ .prepare(`SELECT COUNT(*) AS n FROM approvals WHERE watchId = ? AND status = 'pending' AND (json_extract(extra, '$.expiresAt') IS NULL OR json_extract(extra, '$.expiresAt') > ?)`)
72
+ .get(watchId, new Date(now).toISOString());
73
+ return Number(row.n);
74
+ }
75
+ let checkCloseHook;
76
+ /** rules.ts registers how an expired check_run draft closes its commit's check (KAT-285). */
77
+ export function setCheckCloseHook(fn) {
78
+ checkCloseHook = fn;
79
+ }
80
+ /** Closes a pending approval without a decision. Its run records the action as blocked, with a step that says why. */
81
+ export function closeApproval(a, status, closedReason, supersededBy) {
82
+ const decidedAt = new Date().toISOString();
83
+ const patch = { status, decidedAt, closedReason };
84
+ if (supersededBy)
85
+ patch.supersededBy = supersededBy;
86
+ update('approvals', a.id, patch);
87
+ const done = { ...a, status, decidedAt, closedReason, ...(supersededBy ? { supersededBy } : {}) };
88
+ publish({ type: 'approval', approval: done });
89
+ try {
90
+ updateActionResult(a.runId, a.id, 'blocked');
91
+ addStep(a.runId, `${status === 'superseded' ? 'Superseded' : 'Expired'}: ${a.action.title}`, closedReason, 'info');
92
+ }
93
+ catch {
94
+ /* run may be gone */
95
+ }
96
+ // An expired report no longer waits: its commit's check says so. A superseded one is replaced by a newer draft.
97
+ if (status === 'expired' && a.action.kind === 'check_run')
98
+ checkCloseHook?.(done, 'expired');
99
+ return done;
100
+ }
101
+ /**
102
+ * Kinds whose target names one outward artifact (the sticky PR comment, the check run for a sha, the defect
103
+ * with one signature), so a newer draft replaces an older one. An issue_create target ends in the defect
104
+ * signature, so two different failures never share a slot. Ticket comments append rather than upsert, and
105
+ * chat tool calls, Slack posts, pushes and report edits share targets across unrelated drafts, so they keep
106
+ * their own approvals.
107
+ */
108
+ const ONE_PER_TARGET = new Set(['pr_comment', 'check_run', 'issue_create']);
109
+ function sameSlot(a, b) {
110
+ // A comment a person wrote on an object card (meta.plain) is a new comment, not an edit of the sticky report: it replaces nothing.
111
+ if (a.meta?.plain === true || b.meta?.plain === true)
112
+ return false;
113
+ return ONE_PER_TARGET.has(a.kind) && a.kind === b.kind && a.target === b.target;
114
+ }
115
+ /**
116
+ * Keeps one pending draft per (action kind, target) for `fresh`. Run ids sort by start time, so the draft
117
+ * from the newer run wins even when an older run finishes later: then `fresh` itself is the one superseded.
118
+ */
119
+ export function supersedeOlder(fresh) {
120
+ if (isTicketReviewDraft(fresh.action, fresh.runId))
121
+ return supersedeOlderTicketReviews(fresh);
122
+ if (!ONE_PER_TARGET.has(fresh.action.kind))
123
+ return [];
124
+ // A row with a failed send was approved by a person; it stays until they retry or reject it.
125
+ const same = list('approvals', { watchId: fresh.watchId, status: 'pending' }).filter((a) => a.id !== fresh.id && !a.error && sameSlot(a.action, fresh.action));
126
+ const newerRun = same.filter((a) => a.runId > fresh.runId).sort((x, y) => y.runId.localeCompare(x.runId))[0];
127
+ if (newerRun)
128
+ return [closeApproval(fresh, 'superseded', `A draft from a newer run for ${fresh.action.target} is already waiting.`, newerRun.id)];
129
+ return same.map((a) => closeApproval(a, 'superseded', `A newer draft for ${fresh.action.target} replaced this one.`, fresh.id));
130
+ }
131
+ /** Metadata that marks a ticket comment as some other flow's: a defect comment, a design question, a status label, a person's comment. */
132
+ const NOT_A_REVIEW_META = ['defectComment', 'designQuestion', 'statusLabel', 'append', 'plain', 'askedBy'];
133
+ const hasText = (v) => (typeof v === 'string' || typeof v === 'number') && String(v) !== '';
134
+ /**
135
+ * The comment a ticket review run drafts on its ticket (src/flows/ticketReview.ts). Other ticket comments append and never replace.
136
+ * Drafts made before `meta.ticketReview` existed carry key, ticketId, tracker and url, and come from a ticket_review run or
137
+ * are titled "QA review for ...": those count too, so an upgrade still closes an older pending review (KAT-371).
138
+ */
139
+ function isTicketReviewDraft(action, runId) {
140
+ if (action.kind !== 'ticket_comment')
141
+ return false;
142
+ const meta = action.meta ?? {};
143
+ if (meta.ticketReview === true)
144
+ return true;
145
+ if (NOT_A_REVIEW_META.some((k) => meta[k] !== undefined && meta[k] !== false))
146
+ return false;
147
+ if (!['key', 'ticketId', 'tracker', 'url'].every((k) => hasText(meta[k])))
148
+ return false;
149
+ if (action.title.startsWith('QA review for '))
150
+ return true;
151
+ return !!runId && get('runs', runId)?.kind === 'ticket_review';
152
+ }
153
+ /**
154
+ * A newer review run of the same ticket replaces the pending review draft of an older run, and the note names the newer
155
+ * run (KAT-371). Run ids sort by start time, so when the older run finishes last, its own draft is the one closed.
156
+ */
157
+ function supersedeOlderTicketReviews(fresh) {
158
+ // A row with a failed send was approved by a person; it stays until they retry or reject it.
159
+ const same = list('approvals', { watchId: fresh.watchId, status: 'pending' }).filter((a) => a.id !== fresh.id && !a.error && a.runId !== fresh.runId && isTicketReviewDraft(a.action, a.runId) && a.action.target === fresh.action.target);
160
+ const newer = same.filter((a) => a.runId > fresh.runId).sort((x, y) => y.runId.localeCompare(x.runId))[0];
161
+ if (newer)
162
+ return [closeApproval(fresh, 'superseded', `A newer review of ${fresh.action.target} (run ${newer.runId}) is already waiting.`, newer.id)];
163
+ return same.map((a) => closeApproval(a, 'superseded', `A newer review of ${fresh.action.target} (run ${fresh.runId}) replaced this one.`, fresh.id));
164
+ }
165
+ /** A newer draft for the same slot went out without approval: the older pending drafts are stale. */
166
+ export function supersedeBySent(watchId, action, runId) {
167
+ if (isTicketReviewDraft(action, runId)) {
168
+ // A review sent at once (rule act) closes the pending review drafts of older runs for the same ticket (KAT-371).
169
+ return list('approvals', { watchId, status: 'pending' })
170
+ .filter((a) => !a.error && a.runId < runId && isTicketReviewDraft(a.action, a.runId) && a.action.target === action.target)
171
+ .map((a) => closeApproval(a, 'superseded', `A newer review of ${action.target} (run ${runId}) was sent on its own.`));
172
+ }
173
+ if (!ONE_PER_TARGET.has(action.kind))
174
+ return [];
175
+ return list('approvals', { watchId, status: 'pending' })
176
+ .filter((a) => !a.error && sameSlot(a.action, action) && a.runId <= runId)
177
+ .map((a) => closeApproval(a, 'superseded', `A newer draft for ${action.target} was sent on its own.`));
178
+ }
179
+ /** Marks pending approvals past their expiresAt as expired. Returns how many it closed. */
180
+ export function sweepTimeExpired(now = Date.now()) {
181
+ const due = list('approvals', { status: 'pending' }).filter((a) => a.expiresAt && Date.parse(a.expiresAt) <= now);
182
+ for (const a of due)
183
+ closeApproval(a, 'expired', 'Nobody decided before it expired.');
184
+ return due.length;
185
+ }
186
+ /** A defect draft (a new defect, or evidence for one): the bug outlives the PR that found it. */
187
+ function isDefectDraft(action) {
188
+ // A new defect is drafted as issue_create (src/flows/defectDraft.ts) and carries the bug signature.
189
+ if (action.kind === 'issue_create')
190
+ return typeof action.meta?.bugSig === 'string' && action.meta.bugSig !== '';
191
+ return action.kind === 'file_defect' || (action.kind === 'ticket_comment' && action.meta?.defectComment === true);
192
+ }
193
+ function sameSha(a, b) {
194
+ return !!a && !!b && (a.startsWith(b) || b.startsWith(a));
195
+ }
196
+ /**
197
+ * Applies what is known about one PR to its pending approvals: a merged or closed PR expires them all (a merged PR keeps its pending defect drafts),
198
+ * and an open PR expires check-run and comment drafts written for a sha that is no longer its head.
199
+ * `before` (ISO) limits it to drafts created before the state was read, so a draft for a head that
200
+ * arrived after the lookup is never compared against the old state.
201
+ */
202
+ export function applyPrState(watchId, pr, st, before, repo) {
203
+ const out = [];
204
+ const cutoff = before ? Date.parse(before) : NaN;
205
+ const multi = isMultiRepo(watchId);
206
+ for (const a of list('approvals', { watchId, status: 'pending' })) {
207
+ // A row with a failed send was approved by a person; it stays until they retry or reject it.
208
+ if (prOf(a.action) !== pr || a.error)
209
+ continue;
210
+ // The PR number is per repo: a draft for another repo's PR #N is not this one.
211
+ if (!inRepoOf(a, repo, multi))
212
+ continue;
213
+ // Compare as times: GitHub sends whole seconds, so a draft from that same second counts as newer.
214
+ if (Number.isFinite(cutoff) && Date.parse(a.createdAt) >= cutoff)
215
+ continue;
216
+ const meta = a.action.meta ?? {};
217
+ // A post-merge comment is written for a merged PR on purpose; only a closed PR ends it.
218
+ const afterMerge = meta.afterMerge === true;
219
+ // A merged PR keeps its pending defects: the bug now lives on the default branch (KAT-333). A closed PR expires them.
220
+ if (st.state === 'merged' && isDefectDraft(a.action)) {
221
+ if (st.mergeSha && meta.mergeSha !== st.mergeSha) {
222
+ update('approvals', a.id, { action: { ...a.action, meta: { ...meta, mergeSha: st.mergeSha } } });
223
+ }
224
+ continue;
225
+ }
226
+ if (st.state === 'closed' || (st.state === 'merged' && !afterMerge)) {
227
+ out.push(closeApproval(a, 'expired', `PR #${pr} is ${st.state}.`));
228
+ continue;
229
+ }
230
+ if (st.state !== 'open' || !st.headSha)
231
+ continue;
232
+ // A stale marker already names the new head; the other comment and check drafts name the head they reviewed.
233
+ const sha = String(a.action.kind === 'check_run' ? (meta.sha ?? '') : meta.stale === true ? '' : (meta.head ?? ''));
234
+ if (!sha || sameSha(sha, st.headSha))
235
+ continue;
236
+ if (a.action.kind === 'check_run' || a.action.kind === 'pr_comment') {
237
+ out.push(closeApproval(a, 'expired', `Commit ${sha.slice(0, 7)} is no longer the head of PR #${pr} (now ${st.headSha.slice(0, 7)}).`));
238
+ }
239
+ else if (headScoped(a.action)) {
240
+ // A defect found at an older head: the run for the new head drafts its own, if the bug is still there.
241
+ out.push(closeApproval(a, 'superseded', `It was drafted for ${sha.slice(0, 7)}, which is no longer the head of PR #${pr} (now ${st.headSha.slice(0, 7)}).`));
242
+ }
243
+ }
244
+ return out;
245
+ }
246
+ /**
247
+ * A run for a new head of a PR has started: every pending draft for an older head of that PR is superseded, defects and
248
+ * ticket comments included, without waiting for the Inbox to look the PR up. Drafts a person approved and whose send
249
+ * failed stay. Returns what it closed.
250
+ */
251
+ export function supersedeOlderHeads(watchId, pr, head, repo, byRunId) {
252
+ if (!head)
253
+ return [];
254
+ const out = [];
255
+ const multi = isMultiRepo(watchId);
256
+ for (const a of list('approvals', { watchId, status: 'pending' })) {
257
+ if (a.error || prOf(a.action) !== pr)
258
+ continue;
259
+ if (!inRepoOf(a, repo, multi))
260
+ continue;
261
+ const meta = a.action.meta ?? {};
262
+ if (meta.afterMerge === true || meta.stale === true)
263
+ continue;
264
+ const sha = String(a.action.kind === 'check_run' ? (meta.sha ?? '') : (meta.head ?? ''));
265
+ if (!sha || sameSha(sha, head))
266
+ continue;
267
+ out.push(closeApproval(a, 'superseded', `PR #${pr} moved from ${sha.slice(0, 7)} to ${head.slice(0, 7)}; the run for the new head drafts its own.`, byRunId));
268
+ }
269
+ return out;
270
+ }
271
+ /** The PRs that pending approvals of a watch point at. With `repo` ("owner/repo"), only the PRs of that repo. */
272
+ export function pendingPrs(watchId, repo) {
273
+ const prs = new Set();
274
+ for (const a of list('approvals', { watchId, status: 'pending' })) {
275
+ if (repo) {
276
+ const target = repoOfAction(a.action);
277
+ if (target && target !== repo.toLowerCase())
278
+ continue;
279
+ }
280
+ const pr = prOf(a.action);
281
+ if (pr)
282
+ prs.add(pr);
283
+ }
284
+ return [...prs];
285
+ }
286
+ /** Looks up each PR that has pending approvals and applies its state. A failed lookup leaves that PR alone. */
287
+ export async function reconcilePrApprovals(watchId, lookup,
288
+ /** When the caller read the state it passes to lookup; drafts created later are left alone. */
289
+ readAt,
290
+ /** "owner/repo" the lookup reads; drafts for other repos are left alone. */
291
+ repo) {
292
+ const out = [];
293
+ for (const pr of pendingPrs(watchId, repo)) {
294
+ const before = readAt ?? new Date().toISOString();
295
+ let st;
296
+ try {
297
+ st = await lookup(pr);
298
+ }
299
+ catch {
300
+ continue;
301
+ }
302
+ if (st)
303
+ out.push(...applyPrState(watchId, pr, st, before, repo));
304
+ }
305
+ return out;
306
+ }
307
+ const lastInboxCheck = new Map();
308
+ export const INBOX_CHECK_MS = 60_000;
309
+ /** Inbox load: reconcile a watch at most once a minute. Returns false when the throttle skipped it. */
310
+ export async function reconcileThrottled(watchId, lookup, now = Date.now(), repo) {
311
+ // The throttle is per dot and repo: a check of one repo must not skip the dot's other repos.
312
+ const key = repo ? `${watchId}|${repo.toLowerCase()}` : watchId;
313
+ const last = lastInboxCheck.get(key) ?? 0;
314
+ if (now - last < INBOX_CHECK_MS)
315
+ return false;
316
+ lastInboxCheck.set(key, now);
317
+ await reconcilePrApprovals(watchId, lookup, undefined, repo);
318
+ return true;
319
+ }
320
+ export function resetInboxThrottle() {
321
+ lastInboxCheck.clear();
322
+ }
323
+ // ---------- escalation categories and stats ----------
324
+ const CATEGORY_RULES = [
325
+ ['reviewer_unavailable', /\b(review was unavailable|returned no decision)\b/i],
326
+ [
327
+ 'secret_or_personal_data',
328
+ /\b(contains?|exposes?|includes?|leaks?|reveals?|shows?)\b[^.]*\b(credential|token|secret|password|api key|personal|username|email address)/i,
329
+ ],
330
+ ['untrusted_instruction', /\b(untrusted|injection)\b|\brepeats?\b[^.]*\binstruction/i],
331
+ ['must_not_rule', /\bmust not\b|must-not|owner's rule/i],
332
+ ['destructive', /\b(revert|force push|delet|destructive|changes the codebase)/i],
333
+ ['tone', /\b(hostile|blame|tone|rude)\b/i],
334
+ ['unsupported_claim', /\b(unsupported|evidence|substantiat|contradict|conflict|claim|exceed|inconsistent|unverified)/i],
335
+ ];
336
+ /** Sorts a reviewer's one-sentence reason into a category. */
337
+ export function classifyEscalation(reason) {
338
+ for (const [cat, re] of CATEGORY_RULES)
339
+ if (re.test(reason))
340
+ return cat;
341
+ return 'other';
342
+ }
343
+ /** The stored escalation, or one derived from the reason for rows written before KAT-94. */
344
+ export function escalationOf(a) {
345
+ if (a.escalation)
346
+ return a.escalation;
347
+ const m = /^Auto-review escalated:\s*(.*)$/s.exec(a.reason ?? '');
348
+ if (m)
349
+ return { by: 'auto_review', category: classifyEscalation(m[1]) };
350
+ return { by: 'rule', category: 'rule_ask' };
351
+ }
352
+ /** Escalation stats per action kind over approvals and run actions created since `sinceIso`. */
353
+ export function approvalStats(opts = {}) {
354
+ const since = opts.sinceIso ?? null;
355
+ const byKind = new Map();
356
+ const row = (kind) => {
357
+ let k = byKind.get(kind);
358
+ if (!k) {
359
+ k = { kind: kind, autoSent: 0, approvals: 0, byStatus: {}, escalatedByReview: 0, heldByRule: 0, escalationRate: null, categories: {} };
360
+ byKind.set(kind, k);
361
+ }
362
+ return k;
363
+ };
364
+ const inRange = (createdAt) => !since || createdAt >= since;
365
+ const approvals = list('approvals', opts.watchId ? { watchId: opts.watchId } : undefined).filter((a) => inRange(a.createdAt));
366
+ for (const a of approvals) {
367
+ const k = row(a.action.kind);
368
+ k.approvals++;
369
+ k.byStatus[a.status] = (k.byStatus[a.status] ?? 0) + 1;
370
+ const e = escalationOf(a);
371
+ if (e.by === 'auto_review')
372
+ k.escalatedByReview++;
373
+ else
374
+ k.heldByRule++;
375
+ k.categories[e.category] = (k.categories[e.category] ?? 0) + 1;
376
+ }
377
+ const runs = list('runs', opts.watchId ? { watchId: opts.watchId } : undefined).filter((r) => inRange(r.createdAt));
378
+ for (const r of runs) {
379
+ for (const x of r.actions ?? []) {
380
+ if (x.result === 'executed' && !x.approvalId)
381
+ row(x.action.kind).autoSent++;
382
+ }
383
+ }
384
+ for (const k of byKind.values()) {
385
+ const d = k.escalatedByReview + k.autoSent;
386
+ k.escalationRate = d ? Math.round((k.escalatedByReview / d) * 1000) / 1000 : null;
387
+ }
388
+ return { since, kinds: [...byKind.values()].sort((a, b) => a.kind.localeCompare(b.kind)) };
389
+ }
390
+ //# sourceMappingURL=approvals.js.map