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,286 @@
1
+ // The release call of a lead (KAT-405): "Can we release 2026.11?" answered with Ready, Ready with risk or Not ready, and the reasons, built by
2
+ // code from rows the members already store. No model call and no tracker call; it posts nothing and files nothing. The words are
3
+ // readiness words only, so the rule of docs/STAGES.md (the release guard "never says release or hold") still holds.
4
+ //
5
+ // The rows are the team trace (buildAll over the members, src/reports/traceability.ts): a ticket from Ticket Reviewer, a PR link from PR
6
+ // Reviewer and a post-merge result from Regression Runner join into one row with the right status.
7
+ import { isLive } from './agent/approvals.js';
8
+ import { get, list } from './db.js';
9
+ import { FLAKY_SUGGEST_AT, foundBug, isBugDraft, milestoneDate, nearestOpenMilestone, testStats } from './dot-health.js';
10
+ import { subscribe } from './events.js';
11
+ import { healthFor } from './routes/health.js';
12
+ import { membersOf, teamIds } from './lead.js';
13
+ import { casesForTicket } from './flows/testDesign.js';
14
+ import { parseIssueRef } from './integrations/github-issues.js';
15
+ import { linksFor } from './links.js';
16
+ import { buildAll, issueUrl, readinessOf, readinessSummary } from './reports/traceability.js';
17
+ import { stageOn } from './stages/config.js';
18
+ import { prTitle } from './updates/words.js';
19
+ /** How long one answer is reused. */
20
+ export const RELEASE_TTL_MS = 30_000;
21
+ const WEEK_MS = 7 * 86_400_000;
22
+ const norm = (s) => (s ?? '').trim().toLowerCase();
23
+ const natural = (a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
24
+ const NBSP = ' ';
25
+ const plural = (n, one, many = `${one}s`) => `${n}${NBSP}${n === 1 ? one : many}`;
26
+ /** The words of an answer, as the lead page, the digest and the chat say them. */
27
+ export const ANSWER_WORD = {
28
+ ready: 'Ready',
29
+ ready_with_risk: 'Ready with risk',
30
+ not_ready: 'Not ready',
31
+ no_tickets: 'No tickets',
32
+ };
33
+ /** The rule that set each answer, for the Details fold. */
34
+ export const ANSWER_RULE = {
35
+ no_tickets: 'No requirement of the members has this milestone.',
36
+ not_ready: 'Not ready: a requirement of the milestone is failing, a bug is open against one, or the last after-merge check found a bug.',
37
+ ready_with_risk: 'Ready with risk: a requirement is not tested, partly tested or out of date, a bug report waits in an Inbox, a test was flaky 3 or more times this week, or a member is not watching so its data may be old.',
38
+ ready: 'Ready: every requirement of the milestone passes, no bug is open, nothing waits in an Inbox and every member is watching.',
39
+ };
40
+ /** "#4301 Export results to CSV", or "SHOP-12 Title" for a key of Jira or Linear. */
41
+ export function ticketLabel(row) {
42
+ const gh = parseIssueRef(row.key);
43
+ const head = gh ? `#${gh.number}` : row.key;
44
+ const title = row.title?.trim();
45
+ return title ? `${head} ${title}` : head;
46
+ }
47
+ /** "#4318" for a GitHub ref, else the ref as it is. */
48
+ export function shortRef(ref) {
49
+ const gh = parseIssueRef(ref);
50
+ return gh ? `#${gh.number}` : ref;
51
+ }
52
+ const appLink = (leadId, more) => `#/trace?${new URLSearchParams({ dot: leadId, ...more }).toString()}`;
53
+ /** Pending bug reports of the members, each with the requirement refs it names. */
54
+ function waitingBugReports(ids, now) {
55
+ const out = [];
56
+ for (const a of list('approvals', { watchId: [...ids], status: 'pending' })) {
57
+ if (!isLive(a, now) || !isBugDraft(a.action))
58
+ continue;
59
+ const relates = a.action.meta?.relates;
60
+ const refs = Array.isArray(relates) ? relates.filter((r) => typeof r === 'string').map((r) => r.toLowerCase()) : [];
61
+ out.push({ watchId: a.watchId, refs });
62
+ }
63
+ return out;
64
+ }
65
+ /** The runs of the last 7 days of the members, for the flaky count. */
66
+ function weekRuns(ids, now) {
67
+ const since = new Date(now - WEEK_MS).toISOString();
68
+ return list('runs', { watchId: [...ids] }, { orderBy: 'createdAt DESC', limit: 800 }).filter((r) => r.createdAt >= since);
69
+ }
70
+ const sameSpec = (a, b) => a === b || a.endsWith(`/${b}`) || b.endsWith(`/${a}`);
71
+ /** The milestone titles of the members' trackers and of the team's rows, for the picker. */
72
+ function milestonesOf(members, rows) {
73
+ const out = new Set(rows.map((r) => r.milestone).filter(Boolean));
74
+ for (const m of members)
75
+ if (m.tracker?.kind === 'github')
76
+ for (const t of m.tracker.milestones ?? [])
77
+ if (t.trim())
78
+ out.add(t.trim());
79
+ return [...out].sort(natural);
80
+ }
81
+ /** The scope of milestones a lead's trackers limit the nearest-milestone pick to, or undefined when none is limited. */
82
+ function scopeOf(members) {
83
+ const scope = members.flatMap((m) => (m.tracker?.kind === 'github' ? (m.tracker.milestones ?? []) : []));
84
+ return scope.length ? scope : undefined;
85
+ }
86
+ /**
87
+ * The newest milestone of the team's rows, for a team whose every requirement passes: no milestone is open, so the call answers for the
88
+ * latest one and reads Ready, not "No tickets". The latest dated milestone wins, else the last in natural order.
89
+ */
90
+ export function latestMilestone(rows, scope) {
91
+ const allowed = scope?.length ? new Set(scope.map((s) => s.toLowerCase())) : null;
92
+ const titles = [...new Set(rows.map((r) => r.milestone).filter((m) => !!m && (!allowed || allowed.has(m.toLowerCase()))))];
93
+ if (!titles.length)
94
+ return null;
95
+ const dated = titles.map((m) => ({ m, d: milestoneDate(m) })).filter((x) => x.d !== null);
96
+ if (dated.length)
97
+ return dated.sort((a, b) => b.d - a.d || natural(b.m, a.m))[0].m;
98
+ return titles.sort(natural).at(-1);
99
+ }
100
+ /**
101
+ * The release call for a milestone, or for the nearest open one when none is named. When no milestone is open (every requirement passes)
102
+ * the newest one answers, unless `openOnly` asks for the open one alone (the daily digest, which stays quiet about a milestone that is done).
103
+ * Pure over the stored rows and a clock: the same rows give the same answer. First match wins: No tickets, then Not ready, then Ready with
104
+ * risk, then Ready.
105
+ */
106
+ export function releaseCall(lead, milestone, now = Date.now(), o = {}) {
107
+ const members = membersOf(lead);
108
+ const ids = members.map((m) => m.id);
109
+ const built = buildAll(lead);
110
+ const rows = built.all;
111
+ const scope = scopeOf(members);
112
+ const chosen = milestone?.trim() || nearestOpenMilestone(rows, now, scope) || (o.openOnly ? '' : latestMilestone(rows, scope)) || '';
113
+ const inMilestone = rows.filter((r) => !!chosen && norm(r.milestone) === norm(chosen));
114
+ const readiness = readinessOf(inMilestone, chosen || null);
115
+ const counts = {
116
+ total: readiness.total,
117
+ passing: readiness.passing,
118
+ failing: readiness.failing,
119
+ notTested: readiness.notTested,
120
+ partlyTested: readiness.partlyTested,
121
+ outOfDate: readiness.outOfDate,
122
+ };
123
+ const base = { milestone: chosen, counts, milestones: milestonesOf(members, rows), builtAt: new Date(now).toISOString() };
124
+ if (!inMilestone.length)
125
+ return { ...base, answer: 'no_tickets', summary: readinessSummary(counts), reasons: [], rule: ANSWER_RULE.no_tickets };
126
+ const memberOf = (watchId) => (watchId && ids.includes(watchId) ? watchId : (ids[0] ?? lead.id));
127
+ const nameOfMember = (id) => members.find((m) => m.id === id)?.name;
128
+ const reasons = [];
129
+ const blocker = (r) => reasons.push({ level: 'blocker', ...r, ...(nameOfMember(r.memberId) ? { memberName: nameOfMember(r.memberId) } : {}) });
130
+ const risk = (r) => reasons.push({ level: 'risk', ...r, ...(nameOfMember(r.memberId) ? { memberName: nameOfMember(r.memberId) } : {}) });
131
+ // ---- blockers
132
+ const rowLink = (row) => row.url ?? appLink(lead.id, { milestone: chosen, issue: row.ref });
133
+ for (const row of inMilestone) {
134
+ const status = built.statuses.get(row.ref);
135
+ if (!status)
136
+ continue;
137
+ const info = built.catalog.get(row.ref);
138
+ if (row.statusCode === 'failing') {
139
+ const failed = status.prs.find((p) => p.result === 'failed' && !p.outdated);
140
+ const failedRun = failed?.runId ? get('runs', failed.runId) : undefined;
141
+ if (failed || status.specs.some((s) => s.result === 'failed')) {
142
+ const how = failedRun?.kind === 'post_merge' ? 'fails after merge' : failed ? 'fails in its PR check' : 'has a failing test';
143
+ blocker({ text: `${ticketLabel(row)} ${how}.`, ref: row.ref, href: rowLink(row), memberId: memberOf(failedRun?.watchId ?? info?.watchId) });
144
+ }
145
+ }
146
+ for (const d of status.defects.filter((x) => x.state === 'open')) {
147
+ const src = linksFor(d.ref).find((l) => l.source === 'defect' && l.watchId && ids.includes(l.watchId));
148
+ const gh = parseIssueRef(d.ref);
149
+ blocker({
150
+ text: `Bug ${shortRef(d.ref)} is open against ${ticketLabel(row)}.`,
151
+ ref: d.ref,
152
+ ...(gh ? { href: issueUrl(gh.full, gh.number) } : { href: rowLink(row) }),
153
+ memberId: memberOf(src?.watchId),
154
+ });
155
+ }
156
+ }
157
+ // Main is broken when the latest after-merge check of a member that runs them found a bug.
158
+ for (const m of members) {
159
+ if (m.archived || !stageOn(m, 'regression'))
160
+ continue;
161
+ const last = list('runs', { watchId: m.id, kind: 'post_merge' }, { orderBy: 'createdAt DESC', limit: 1 })[0];
162
+ if (last && foundBug(last)) {
163
+ const pr = last.trigger?.pr;
164
+ const title = prTitle(last.trigger?.title);
165
+ const where = pr ? ` (PR #${pr.number}${title ? ` ${title}` : ''})` : '';
166
+ blocker({
167
+ text: `The last after-merge check of ${m.name} found a bug${where}.`,
168
+ ...(pr ? { ref: `#${pr.number}` } : {}),
169
+ href: `#/runs/${last.id}`,
170
+ memberId: m.id,
171
+ });
172
+ }
173
+ }
174
+ // ---- risks: each kind of risk is one line that names its tickets
175
+ const named = (rs) => rs.map((r) => shortRef(r.key)).join(', ');
176
+ const group = (code, one, many, status) => {
177
+ const rs = inMilestone.filter((r) => r.statusCode === code);
178
+ if (!rs.length)
179
+ return;
180
+ risk({
181
+ text: `${plural(rs.length, 'requirement')} ${rs.length === 1 ? one : many}: ${named(rs)}.`,
182
+ href: appLink(lead.id, { milestone: chosen, status }),
183
+ memberId: memberOf(built.catalog.get(rs[0].ref)?.watchId),
184
+ openLabel: 'See them',
185
+ });
186
+ };
187
+ group('not_tested', 'has no test result yet', 'have no test result yet', 'not_tested');
188
+ group('partly_tested', 'is partly tested', 'are partly tested', 'partly_tested');
189
+ group('out_of_date', 'has a newer change than its last result', 'have a newer change than their last result', 'out_of_date');
190
+ // A bug report that waits in an Inbox: the bug is found, and nobody has filed it yet.
191
+ const refs = new Set(inMilestone.map((r) => r.ref));
192
+ const waiting = waitingBugReports(ids, now);
193
+ for (const m of members) {
194
+ const mine = waiting.filter((w) => w.watchId === m.id && w.refs.some((r) => refs.has(r)));
195
+ if (!mine.length)
196
+ continue;
197
+ const named2 = [...new Set(mine.flatMap((w) => w.refs.filter((r) => refs.has(r))))]
198
+ .map((r) => inMilestone.find((x) => x.ref === r))
199
+ .sort((a, b) => natural(a.key, b.key));
200
+ risk({
201
+ text: `${plural(mine.length, 'bug report')} for ${named(named2)} ${mine.length === 1 ? 'waits' : 'wait'} in the Inbox of ${m.name}.`,
202
+ href: '#/inbox',
203
+ memberId: m.id,
204
+ openLabel: 'Review',
205
+ });
206
+ }
207
+ // A test of the milestone's tickets that was flaky 3 or more times this week.
208
+ const specs = new Set();
209
+ for (const row of inMilestone) {
210
+ for (const s of built.statuses.get(row.ref)?.specs ?? [])
211
+ specs.add(s.path);
212
+ for (const c of casesForTicket(teamIds(lead.id), row.ref))
213
+ if (c.specPath && c.status !== 'retired')
214
+ specs.add(c.specPath);
215
+ }
216
+ if (specs.size) {
217
+ const flaky = testStats(weekRuns(ids, now), now)
218
+ .filter((s) => s.flaky > 0 && s.flaky + s.failed >= FLAKY_SUGGEST_AT && [...specs].some((p) => sameSpec(s.file, p)))
219
+ .sort((a, b) => b.flaky + b.failed - (a.flaky + a.failed) || a.title.localeCompare(b.title))[0];
220
+ if (flaky) {
221
+ const run = get('runs', flaky.badRunId || flaky.latestRunId);
222
+ risk({
223
+ text: `The test "${flaky.title}" was flaky ${flaky.flaky + flaky.failed} times this week.`,
224
+ href: `#/runs/${flaky.badRunId || flaky.latestRunId}`,
225
+ memberId: memberOf(run?.watchId),
226
+ });
227
+ }
228
+ }
229
+ // A member that is Not watching for a reason it did not choose: what it knows may be old. A paused or archived member is a person's choice
230
+ // and the team page shows it as such, so it does not turn a release into a risk.
231
+ for (const m of members) {
232
+ if (m.archived || m.paused)
233
+ continue;
234
+ const h = healthFor(m, now);
235
+ if (h.status === 'not_watching')
236
+ risk({
237
+ text: `${m.name} is not watching, so its data may be old: ${h.statusReason.replace(/[.\s]+$/, '').replace(/^./, (c) => c.toLowerCase())}.`,
238
+ href: `#/dots/${m.id}`,
239
+ memberId: m.id,
240
+ });
241
+ }
242
+ const blockers = reasons.filter((r) => r.level === 'blocker');
243
+ const answer = blockers.length ? 'not_ready' : reasons.length ? 'ready_with_risk' : 'ready';
244
+ return {
245
+ ...base,
246
+ answer,
247
+ summary: readinessSummary(counts),
248
+ reasons: [...blockers, ...reasons.filter((r) => r.level === 'risk')],
249
+ rule: ANSWER_RULE[answer],
250
+ };
251
+ }
252
+ // ---------- the kept answer ----------
253
+ const kept = new Map();
254
+ let wired = false;
255
+ /** The answer kept for 30 s per lead and milestone. A run, an approval or a save of a member drops it, so a fresh bug shows at once. */
256
+ export function releaseCallFor(lead, milestone, now = Date.now(), o = {}) {
257
+ if (!wired) {
258
+ wired = true;
259
+ // A new run, a run that changes status, an approval and a save of a dot change the answer. The steps of a running check do not.
260
+ const seen = new Map();
261
+ subscribe((e) => {
262
+ if (e.type === 'run') {
263
+ if (seen.get(e.run.id) === e.run.status)
264
+ return;
265
+ seen.set(e.run.id, e.run.status);
266
+ if (seen.size > 2000)
267
+ seen.delete(seen.keys().next().value);
268
+ kept.clear();
269
+ }
270
+ else if (e.type === 'approval' || e.type === 'dot')
271
+ kept.clear();
272
+ });
273
+ }
274
+ const k = `${lead.id}|${norm(milestone)}|${o.openOnly ? 'open' : 'any'}`;
275
+ const hit = kept.get(k);
276
+ if (hit && now - hit.at < RELEASE_TTL_MS)
277
+ return hit.call;
278
+ const call = releaseCall(lead, milestone, now, o);
279
+ kept.set(k, { at: now, call });
280
+ return call;
281
+ }
282
+ /** Drops every kept answer. Tests call it between cases. */
283
+ export function forgetReleaseCalls() {
284
+ kept.clear();
285
+ }
286
+ //# sourceMappingURL=lead-release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lead-release.js","sourceRoot":"","sources":["../src/lead-release.ts"],"names":[],"mappings":"AAAA,+IAA+I;AAC/I,iIAAiI;AACjI,oHAAoH;AACpH,EAAE;AACF,yIAAyI;AACzI,mGAAmG;AACnG,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACzH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,qCAAqC;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AAErC,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,CAAC;AAC/B,MAAM,IAAI,GAAG,CAAC,CAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACvE,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;AAChH,MAAM,IAAI,GAAG,GAAG,CAAC;AACjB,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,GAAW,EAAE,IAAI,GAAG,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAElG,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GAAkC;IACxD,KAAK,EAAE,OAAO;IACd,eAAe,EAAE,iBAAiB;IAClC,SAAS,EAAE,WAAW;IACtB,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAkC;IACxD,UAAU,EAAE,mDAAmD;IAC/D,SAAS,EAAE,6HAA6H;IACxI,eAAe,EACb,6MAA6M;IAC/M,KAAK,EAAE,2HAA2H;CACnI,CAAC;AAEF,qFAAqF;AACrF,MAAM,UAAU,WAAW,CAAC,GAAoC;IAC9D,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IAChC,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AACpC,CAAC;AAED,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,IAA4B,EAAE,EAAE,CAAC,WAAW,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;AAExI,mFAAmF;AACnF,SAAS,iBAAiB,CAAC,GAAsB,EAAE,GAAW;IAC5D,MAAM,GAAG,GAA0C,EAAE,CAAC;IACtD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAiB,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAC5F,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,SAAS;QACvD,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjI,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uEAAuE;AACvE,SAAS,QAAQ,CAAC,GAAsB,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,OAAO,IAAI,CAAY,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC;AACvI,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAEjG,4FAA4F;AAC5F,SAAS,YAAY,CAAC,OAAyB,EAAE,IAAyB;IACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAS,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1E,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,KAAK,QAAQ;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE;gBAAE,IAAI,CAAC,CAAC,IAAI,EAAE;oBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACvI,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,wHAAwH;AACxH,SAAS,OAAO,CAAC,OAAyB;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzG,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,IAAyB,EAAE,KAAyB;IAClF,MAAM,OAAO,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3H,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAiC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACzH,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;IACpF,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAW,EAAE,SAAkB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,IAA4B,EAAE;IAC3G,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,oBAAoB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACrI,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACvF,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,SAAS,EAAE,SAAS,CAAC,SAAS;KAC/B,CAAC;IACF,MAAM,IAAI,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IAC1H,IAAI,CAAC,WAAW,CAAC,MAAM;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC;IAEhJ,MAAM,QAAQ,GAAG,CAAC,OAA2B,EAAU,EAAE,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7H,MAAM,YAAY,GAAG,CAAC,EAAU,EAAsB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC;IAChG,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,CAA8C,EAAE,EAAE,CACjE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3H,MAAM,IAAI,GAAG,CAAC,CAA8C,EAAE,EAAE,CAC9D,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAExH,gBAAgB;IAChB,MAAM,OAAO,GAAG,CAAC,GAAa,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACtG,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC5E,MAAM,SAAS,GAAG,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAY,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACnF,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC9D,MAAM,GAAG,GAAG,SAAS,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,oBAAoB,CAAC;gBAC7H,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,IAAI,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9I,CAAC;QACH,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC;YACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACvG,MAAM,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAChC,OAAO,CAAC;gBACN,IAAI,EAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,oBAAoB,WAAW,CAAC,GAAG,CAAC,GAAG;gBACnE,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzE,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,2FAA2F;IAC3F,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC;YAAE,SAAS;QACtD,MAAM,IAAI,GAAG,IAAI,CAAY,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxH,IAAI,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC3C,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,OAAO,CAAC;gBACN,IAAI,EAAE,iCAAiC,CAAC,CAAC,IAAI,eAAe,KAAK,GAAG;gBACpE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvC,IAAI,EAAE,UAAU,IAAI,CAAC,EAAE,EAAE;gBACzB,QAAQ,EAAE,CAAC,CAAC,EAAE;aACf,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM,KAAK,GAAG,CAAC,EAAuB,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,CAAC,IAA4B,EAAE,GAAW,EAAE,IAAY,EAAE,MAAc,EAAE,EAAE;QACxF,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,EAAE,CAAC,MAAM;YAAE,OAAO;QACvB,IAAI,CAAC;YACH,IAAI,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,GAAG;YAC1F,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YACrD,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;YAC1D,SAAS,EAAE,UAAU;SACtB,CAAC,CAAC;IACL,CAAC,CAAC;IACF,KAAK,CAAC,YAAY,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,YAAY,CAAC,CAAC;IACvF,KAAK,CAAC,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACjF,KAAK,CAAC,aAAa,EAAE,yCAAyC,EAAE,4CAA4C,EAAE,aAAa,CAAC,CAAC;IAE7H,sFAAsF;IACtF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,SAAS;QAC3B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAChF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAE,CAAC;aACjD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,oBAAoB,CAAC,CAAC,IAAI,GAAG;YACpI,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,CAAC,CAAC,EAAE;YACd,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;IACL,CAAC;IAED,8EAA8E;IAC9E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,EAAE;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5E,KAAK,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC7H,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC;aAC7C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,IAAI,gBAAgB,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;aACnH,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClG,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,GAAG,CAAY,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;YACxE,IAAI,CAAC;gBACH,IAAI,EAAE,aAAa,KAAK,CAAC,KAAK,eAAe,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,mBAAmB;gBAC1F,IAAI,EAAE,UAAU,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,WAAW,EAAE;gBACrD,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,2IAA2I;IAC3I,iFAAiF;IACjF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM;YAAE,SAAS;QACrC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC,MAAM,KAAK,cAAc;YAC7B,IAAI,CAAC;gBACH,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,6CAA6C,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,GAAG;gBAC1I,IAAI,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE;gBACtB,QAAQ,EAAE,CAAC,CAAC,EAAE;aACf,CAAC,CAAC;IACP,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAkB,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3G,OAAO;QACL,GAAG,IAAI;QACP,MAAM;QACN,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC;QACjC,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;QACpE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;KAC1B,CAAC;AACJ,CAAC;AAED,wCAAwC;AAExC,MAAM,IAAI,GAAG,IAAI,GAAG,EAA6C,CAAC;AAClE,IAAI,KAAK,GAAG,KAAK,CAAC;AAElB,wIAAwI;AACxI,MAAM,UAAU,cAAc,CAAC,IAAW,EAAE,SAAkB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,IAA4B,EAAE;IAC9G,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,CAAC;QACb,gIAAgI;QAChI,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE;YACd,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBACrB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM;oBAAE,OAAO;gBAChD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;oBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAC;gBAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK;gBAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACrE,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IACzE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,cAAc;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC1D,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;AACf,CAAC"}
package/dist/lead.js ADDED
@@ -0,0 +1,328 @@
1
+ // The Lead QA dot (KAT-405, docs/STAGES.md section 1.1). A lead holds no repos, tracker, site checks or runner. It names member dots
2
+ // and reads the rows they store: team health here, the team digest in src/lead-digest.ts, the release call in src/lead-release.ts,
3
+ // the merged bug draft in src/lead-defects.ts. This file holds the lead index, the checks a save of a lead runs, and team health.
4
+ import { liveCount } from './agent/approvals.js';
5
+ import { get, list } from './db.js';
6
+ import { subscribe } from './events.js';
7
+ import { stageOn } from './stages/config.js';
8
+ import { STAGE_JOB, STAGE_KEYS } from './stages/index.js';
9
+ /** A lead names 1 to 8 dots. */
10
+ export const MAX_MEMBERS = 8;
11
+ export const isLead = (w) => w?.kind === 'lead';
12
+ // ---------- the index ----------
13
+ /** Member dot id to the id of the live lead that names it. Rebuilt on a dot event and at boot; archived leads are not in it. */
14
+ let index = null;
15
+ /** Drops the index so the next read rebuilds it. Every code path that writes `kind` or `memberIds` calls it, and so do tests. */
16
+ export function forgetLeadIndex() {
17
+ index = null;
18
+ }
19
+ function leadIndex() {
20
+ if (index)
21
+ return index;
22
+ const next = new Map();
23
+ for (const lead of list('watches', { kind: 'lead' })) {
24
+ if (lead.archived)
25
+ continue;
26
+ for (const id of lead.memberIds ?? [])
27
+ if (!next.has(id))
28
+ next.set(id, lead.id);
29
+ }
30
+ index = next;
31
+ return next;
32
+ }
33
+ let wired = false;
34
+ /** Starts keeping the index fresh. A `dot` event comes with every save of a dot, a lead included. Safe to call again. */
35
+ export function watchLeadIndex() {
36
+ if (wired)
37
+ return;
38
+ wired = true;
39
+ subscribe((e) => {
40
+ if (e.type === 'dot')
41
+ forgetLeadIndex();
42
+ });
43
+ }
44
+ watchLeadIndex();
45
+ /** The live lead whose `memberIds` holds the dot, or undefined. */
46
+ export function leadOf(dotId) {
47
+ const id = leadIndex().get(dotId);
48
+ return id ? get('watches', id) : undefined;
49
+ }
50
+ /**
51
+ * The dots whose rows one dot's work shares: the lead's `memberIds` when the dot has a lead or is one, else the dot alone. Shared case
52
+ * lookup, ticket scope, the bug target and the defect merge use it.
53
+ */
54
+ export function teamIds(dotId) {
55
+ const self = get('watches', dotId);
56
+ if (isLead(self))
57
+ return [...(self.memberIds ?? [])];
58
+ const lead = leadOf(dotId);
59
+ return lead?.memberIds?.length ? [...lead.memberIds] : [dotId];
60
+ }
61
+ /** The live member rows of a lead, in `memberIds` order. Ids of deleted dots drop out. */
62
+ export function membersOf(lead) {
63
+ const out = [];
64
+ for (const id of lead.memberIds ?? []) {
65
+ const w = get('watches', id);
66
+ if (w)
67
+ out.push(w);
68
+ }
69
+ return out;
70
+ }
71
+ /** The first member, in `memberIds` order, that has a tracker. Undefined for a dot with no lead. */
72
+ export function teamTracker(dotId) {
73
+ const lead = leadOf(dotId);
74
+ if (!lead)
75
+ return undefined;
76
+ return membersOf(lead).find((m) => !!m.tracker);
77
+ }
78
+ /**
79
+ * The dot whose tracker a dot files into and reads tickets through: itself when it has a tracker, else the first member of its lead that
80
+ * has one (KAT-405). A dot with no tracker and no lead stays itself.
81
+ */
82
+ export function trackerOwner(w) {
83
+ if (w.tracker)
84
+ return w;
85
+ return teamTracker(w.id) ?? w;
86
+ }
87
+ /** The dots whose rows a dot's trace and release call read: a lead reads its members, any other dot reads itself. */
88
+ export function scopeMembers(w) {
89
+ return isLead(w) ? membersOf(w) : [w];
90
+ }
91
+ /** The dot that reads a ticket for the scope of `w`: itself, or for a lead the first member with a tracker, else the first member. */
92
+ export function trackerWatch(w) {
93
+ if (!isLead(w))
94
+ return w;
95
+ const members = membersOf(w);
96
+ return members.find((m) => !!m.tracker) ?? members[0] ?? w;
97
+ }
98
+ /** The dot ids of a lead's members that are not archived, for work that has no use for an archived dot. */
99
+ export function liveMemberIds(lead) {
100
+ return membersOf(lead)
101
+ .filter((m) => !m.archived)
102
+ .map((m) => m.id);
103
+ }
104
+ // ---------- words ----------
105
+ /** The jobs a dot does, in a manual tester's words: "Ticket review, Test cases". "No jobs on" when every stage is off. */
106
+ export function jobWords(w) {
107
+ const on = STAGE_KEYS.filter((k) => stageOn(w, k)).map((k) => STAGE_JOB[k]);
108
+ return on.length ? on.join(', ') : 'No jobs on';
109
+ }
110
+ /** The first letter lowered when the sentence opens with a plain word, so "The last merge found a bug." reads after a colon. "GitHub" and "QA" stay. */
111
+ export function lowerFirst(text) {
112
+ const first = /^\S+/.exec(text)?.[0] ?? '';
113
+ return /^[A-Z][a-z]+$/.test(first.replace(/[^A-Za-z]+$/, '')) ? `${text[0].toLowerCase()}${text.slice(1)}` : text;
114
+ }
115
+ /** The refusal of a route that needs a repo, tracker, site or runner when the dot is a lead. */
116
+ export function leadRefusal(w) {
117
+ return `${w.name} is a lead. Ask a member for this.`;
118
+ }
119
+ // ---------- validation ----------
120
+ const OWN_FIELDS_ERROR = 'A lead has no repos, tracker or site checks of its own. Set them on a member.';
121
+ const present = (v) => {
122
+ if (v === undefined || v === null || v === false)
123
+ return false;
124
+ if (Array.isArray(v))
125
+ return v.length > 0;
126
+ if (typeof v === 'string')
127
+ return v.trim() !== '';
128
+ if (typeof v === 'object')
129
+ return Object.keys(v).length > 0;
130
+ return true;
131
+ };
132
+ /** A runner that only says its mode holds no command, setup or image of its own. */
133
+ const runnerIsEmpty = (runner) => {
134
+ if (!runner || typeof runner !== 'object' || Array.isArray(runner))
135
+ return true;
136
+ return Object.keys(runner).every((k) => k === 'mode');
137
+ };
138
+ /**
139
+ * The checks a save of `kind` and `memberIds` runs, in the chain beside stagesError and modelCapError. `current` is the dot on a PATCH,
140
+ * undefined on a POST. Returns the first refusal, or null.
141
+ */
142
+ export function leadError(fields, current) {
143
+ const bad = (code, error) => ({ code, error });
144
+ if (fields.kind !== undefined && fields.kind !== 'dot' && fields.kind !== 'lead')
145
+ return bad(400, 'kind must be dot or lead.');
146
+ const was = current?.kind === 'lead' ? 'lead' : 'dot';
147
+ if (current && fields.kind !== undefined && fields.kind !== was)
148
+ return bad(400, 'A dot cannot change kind. Make a new lead.');
149
+ const kind = current ? was : fields.kind === 'lead' ? 'lead' : 'dot';
150
+ if (kind !== 'lead') {
151
+ if (fields.memberIds !== undefined && fields.memberIds !== null)
152
+ return bad(400, 'Only a lead has members.');
153
+ return null;
154
+ }
155
+ // A lead holds none of what a member holds.
156
+ const own = present(fields.repo) ||
157
+ present(fields.repos) ||
158
+ present(fields.tracker) ||
159
+ present(fields.probes) ||
160
+ present(fields.statusPages) ||
161
+ present(fields.baseUrl) ||
162
+ !runnerIsEmpty(fields.runner) ||
163
+ present(fields.review) ||
164
+ present(fields.stages);
165
+ if (own)
166
+ return bad(400, OWN_FIELDS_ERROR);
167
+ // A new lead needs its members; a save that leaves them out keeps the ones it has.
168
+ const sent = fields.memberIds;
169
+ if (sent === undefined && current)
170
+ return null;
171
+ if (!Array.isArray(sent) || sent.length < 1 || sent.length > MAX_MEMBERS || sent.some((id) => typeof id !== 'string' || !id.trim()))
172
+ return bad(400, `A lead names 1 to ${MAX_MEMBERS} dots.`);
173
+ const ids = sent;
174
+ if (new Set(ids).size !== ids.length)
175
+ return bad(400, `A lead names 1 to ${MAX_MEMBERS} dots.`);
176
+ const keeping = new Set(current?.memberIds ?? []);
177
+ const leads = list('watches', { kind: 'lead' });
178
+ for (const id of ids) {
179
+ const m = get('watches', id);
180
+ if (!m)
181
+ return bad(400, `No dot with id ${id}.`);
182
+ if (isLead(m) || (current && id === current.id))
183
+ return bad(400, `${m.name} is a lead. A lead cannot be a member of another lead.`);
184
+ // An archived dot is refused when it is added, not when it stays: a member that was archived later keeps its place.
185
+ if (m.archived && !keeping.has(id))
186
+ return bad(400, `${m.name} is archived. Restore it first.`);
187
+ // At most one lead per member, archived leads included, so a restore never gives a member two leads.
188
+ const other = leads.find((l) => l.id !== current?.id && (l.memberIds ?? []).includes(id));
189
+ if (other)
190
+ return bad(409, `${m.name} is already in ${other.name}. Remove it there first.`);
191
+ }
192
+ return null;
193
+ }
194
+ /** The stages of a new lead: every one off, because a lead has nothing to derive them from. */
195
+ export function leadStages() {
196
+ return Object.fromEntries(STAGE_KEYS.map((k) => [k, { on: false }]));
197
+ }
198
+ /** The ids a save of `memberIds` added or removed, so each gets a `dot` event and drops its kept health answer. */
199
+ export function memberChanges(before, after) {
200
+ const a = new Set(before ?? []);
201
+ const b = new Set(after ?? []);
202
+ return [...a].filter((id) => !b.has(id)).concat([...b].filter((id) => !a.has(id)));
203
+ }
204
+ /**
205
+ * The refusal for deleting a member that is the only dot of its lead, or null. A lead always keeps 1 to 8 members, so the last one
206
+ * cannot go until the lead has another dot or is deleted.
207
+ */
208
+ export function onlyMemberRefusal(w) {
209
+ for (const lead of list('watches', { kind: 'lead' })) {
210
+ const ids = lead.memberIds ?? [];
211
+ if (ids.length === 1 && ids[0] === w.id)
212
+ return `${w.name} is the only dot of ${lead.name}. Add another dot to the lead, or delete the lead first.`;
213
+ }
214
+ return null;
215
+ }
216
+ // ---------- team health ----------
217
+ /** Failing first, then Needs you, then Not watching, then Healthy. A member that is Not watching for an expired sign-in never hides a Failing one. */
218
+ const TEAM_ORDER = ['failing', 'needs_you', 'not_watching', 'healthy'];
219
+ /** The words of the four status words, as the dot health panel says them. */
220
+ export const STATUS_WORDS = { failing: 'Failing', needs_you: 'Needs you', healthy: 'Healthy', not_watching: 'Not watching' };
221
+ export const NO_LIVE_MEMBER = 'The team has no dots. Add one in the lead settings.';
222
+ export const ALL_AWAY = 'Every dot of the team is paused or archived.';
223
+ /** One row of the team panel from a member and its health answer. */
224
+ export function memberRow(m) {
225
+ const away = m.watch.archived ? 'archived' : m.watch.paused ? 'paused' : undefined;
226
+ const h = m.health;
227
+ let need;
228
+ let action;
229
+ if (away) {
230
+ need = away === 'archived' ? 'Archived' : 'Paused';
231
+ action = null;
232
+ }
233
+ else if (h.status !== 'healthy') {
234
+ need = h.statusReason;
235
+ action = h.statusFix ?? h.suggestion?.action ?? null;
236
+ }
237
+ else if (h.suggestion) {
238
+ need = h.suggestion.text;
239
+ action = h.suggestion.action;
240
+ }
241
+ else {
242
+ need = 'Nothing needs you.';
243
+ action = null;
244
+ }
245
+ return { id: m.watch.id, name: m.watch.name, job: jobWords(m.watch), status: h.status, ...(away ? { away } : {}), need, action };
246
+ }
247
+ /** The team answer from the members' answers. Pure over its inputs, so every rule has a unit test with a fixed clock. */
248
+ export function teamHealthFrom(members, inbox, now) {
249
+ const rows = members.map(memberRow);
250
+ const builtAt = new Date(now).toISOString();
251
+ if (!rows.length)
252
+ return { status: 'not_watching', statusReason: NO_LIVE_MEMBER, members: rows, inbox, builtAt };
253
+ const counted = rows.filter((r) => !r.away);
254
+ if (!counted.length)
255
+ return { status: 'not_watching', statusReason: ALL_AWAY, members: rows, inbox, builtAt };
256
+ const status = TEAM_ORDER.find((s) => counted.some((r) => r.status === s));
257
+ if (status === 'healthy')
258
+ return { status, statusReason: 'Nothing needs you.', members: rows, inbox, builtAt };
259
+ const holders = counted.filter((r) => r.status === status);
260
+ const first = holders[0];
261
+ const more = holders.length - 1;
262
+ const reason = lowerFirst(first.need).replace(/[.\s]+$/, '');
263
+ return {
264
+ status,
265
+ statusReason: `${first.name}: ${reason}${more > 0 ? ` (and ${more} more)` : ''}.`,
266
+ members: rows,
267
+ inbox,
268
+ builtAt,
269
+ };
270
+ }
271
+ /** The team answer of a lead. `read` gives the health answer of one member: the kept one on the route, a fresh one in a test. */
272
+ export function teamHealth(lead, now, read) {
273
+ const members = membersOf(lead).map((watch) => ({ watch, health: read(watch) }));
274
+ const inbox = members.reduce((n, m) => n + liveCount(m.watch.id), 0);
275
+ return teamHealthFrom(members, inbox, now);
276
+ }
277
+ const TILE_TITLES = {
278
+ review: 'To review',
279
+ bugs: 'Bugs',
280
+ checks: 'Checks this week',
281
+ release: 'Release',
282
+ site: 'QA site',
283
+ tests: 'Tests',
284
+ tickets: 'Tickets',
285
+ ai: 'AI use today',
286
+ };
287
+ /**
288
+ * The `DotHealth` of a lead: the team word and reason, the lead's own pause or archive state, `team` set, no suggestion, and eight
289
+ * tiles that read Not set up. The dot list and the sidebar read one status word for every dot from it.
290
+ */
291
+ export function leadHealth(lead, now, read) {
292
+ const team = teamHealth(lead, now, read);
293
+ const own = lead.archived
294
+ ? { text: 'This dot is archived. Restore it to start watching again.', state: 'archived' }
295
+ : lead.paused
296
+ ? { text: 'This dot is paused. Resume it to start watching again.', state: 'paused' }
297
+ : null;
298
+ const tiles = Object.fromEntries(Object.keys(TILE_TITLES).map((k) => [
299
+ k,
300
+ { title: TILE_TITLES[k], state: 'not_set_up', line: 'Not set up', action: null, facts: {} },
301
+ ]));
302
+ const on = !own && team.status !== 'not_watching';
303
+ return {
304
+ status: own ? 'not_watching' : team.status,
305
+ statusReason: own ? own.text : team.statusReason,
306
+ watching: { on, state: own ? own.state : on ? 'on' : 'nothing', note: null, lastCheck: null, trial: null, postsWait: false },
307
+ tiles,
308
+ suggestion: null,
309
+ team,
310
+ builtAt: team.builtAt,
311
+ };
312
+ }
313
+ /**
314
+ * The cases of AI-Vision cases that another dot of the team owns, grouped by the owner's name: "Test cases from Ticket Reviewer" in a PR report
315
+ * (KAT-405). A case of the dot itself, and a case outside the team, are not listed.
316
+ */
317
+ export function teamCasesIn(dotId, cases) {
318
+ const out = new Map();
319
+ for (const c of cases) {
320
+ const row = get('test_cases', c.id);
321
+ if (!row || row.dotId === dotId)
322
+ continue;
323
+ const owner = get('watches', row.dotId)?.name ?? 'another dot';
324
+ out.set(owner, [...(out.get(owner) ?? []), { key: row.key, title: row.title }]);
325
+ }
326
+ return [...out];
327
+ }
328
+ //# sourceMappingURL=lead.js.map