dsh-pstack 0.2.0-beta.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/LICENSE +2 -3
  2. package/README.md +148 -84
  3. package/README.zh.md +198 -0
  4. package/assets/pstack-config-entry.png +0 -0
  5. package/cordis.patch.yml +105 -27
  6. package/dist/client.mjs +2341 -0
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/host-contract-CUPSpeNk.d.mts +22 -0
  9. package/dist/index.d.mts +49 -238
  10. package/dist/index.mjs +250 -123
  11. package/dist/models.d.mts +44 -0
  12. package/dist/models.mjs +201 -0
  13. package/dist/paths-BT77khwm.mjs +48 -0
  14. package/dist/pstack/LICENSE +21 -0
  15. package/dist/pstack/README.md +291 -0
  16. package/dist/pstack/agents/poteto-agent.md +9 -0
  17. package/{assets → dist/pstack}/docs/guide/01-setup.md +13 -11
  18. package/{assets → dist/pstack}/docs/guide/02-poteto-mode.md +4 -4
  19. package/{assets → dist/pstack}/docs/guide/04-design.md +4 -4
  20. package/{assets → dist/pstack}/docs/guide/05-build-and-clean.md +2 -2
  21. package/{assets → dist/pstack}/docs/guide/06-verify-and-ship.md +13 -3
  22. package/{assets → dist/pstack}/docs/guide/07-overnight.md +15 -13
  23. package/{assets → dist/pstack}/docs/guide/09-make-it-yours.md +6 -2
  24. package/{assets → dist/pstack}/docs/guide/10-recipes-and-pitfalls.md +7 -5
  25. package/{assets → dist/pstack}/docs/guide/README.md +1 -1
  26. package/dist/pstack/docs/harness/dsh.md +98 -0
  27. package/{assets → dist/pstack}/skills/architect/SKILL.md +12 -12
  28. package/dist/pstack/skills/arena/SKILL.md +50 -0
  29. package/{assets → dist/pstack}/skills/automate-me/SKILL.md +14 -14
  30. package/{assets → dist/pstack}/skills/benchmark-checklist/SKILL.md +1 -1
  31. package/{assets → dist/pstack}/skills/blast-radius/SKILL.md +4 -6
  32. package/{assets → dist/pstack}/skills/correct/SKILL.md +1 -1
  33. package/{assets → dist/pstack}/skills/create-formal-verification-skill/SKILL.md +4 -2
  34. package/{assets → dist/pstack}/skills/create-verification-skill/SKILL.md +5 -5
  35. package/dist/pstack/skills/figure-it-out/SKILL.md +54 -0
  36. package/dist/pstack/skills/how/SKILL.md +38 -0
  37. package/{assets → dist/pstack}/skills/in-your-own-words/SKILL.md +1 -1
  38. package/dist/pstack/skills/interrogate/SKILL.md +33 -0
  39. package/{assets → dist/pstack}/skills/ketchup/SKILL.md +3 -5
  40. package/dist/pstack/skills/ketchup-video/SKILL.md +29 -0
  41. package/{assets → dist/pstack}/skills/maintain-formal-verification-skill/SKILL.md +1 -1
  42. package/{assets → dist/pstack}/skills/maintain-verification-skill/SKILL.md +3 -3
  43. package/dist/pstack/skills/make-bot-ui/SKILL.md +117 -0
  44. package/dist/pstack/skills/no-comments/SKILL.md +26 -0
  45. package/{assets → dist/pstack}/skills/poteto-help/SKILL.md +34 -31
  46. package/{assets → dist/pstack}/skills/poteto-help/references/prompting.md +1 -1
  47. package/{assets → dist/pstack}/skills/poteto-help/references/recipes.md +3 -3
  48. package/{assets → dist/pstack}/skills/poteto-mode/SKILL.md +20 -19
  49. package/dist/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  50. package/dist/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  51. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-full.md +25 -0
  52. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  53. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/babysit.md +4 -4
  54. package/dist/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  55. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/eval.md +3 -3
  56. package/dist/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
  57. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/hillclimb.md +3 -3
  58. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/investigation.md +2 -2
  59. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/multi-phase-plan.md +23 -23
  60. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/opening-a-pr.md +6 -6
  61. package/dist/pstack/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  62. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/pause-safely.md +2 -2
  63. package/dist/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  64. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/prototype.md +4 -4
  65. package/dist/pstack/skills/poteto-mode/playbooks/refactoring.md +16 -0
  66. package/dist/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  67. package/dist/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  68. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/shipping.md +2 -2
  69. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/trace-forensics.md +2 -2
  70. package/dist/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  71. package/dist/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  72. package/{assets → dist/pstack}/skills/poteto-mode/scripts/check-plan.mjs +6 -8
  73. package/dist/pstack/skills/poteto-mode/scripts/check-plan.test.mjs +128 -0
  74. package/{assets/skills/poteto-mode/scripts/check-plan.test.mjs → dist/pstack/skills/poteto-mode/scripts/expect.mjs} +12 -101
  75. package/dist/pstack/skills/poteto-mode/scripts/support.mjs +93 -0
  76. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.mjs +123 -0
  77. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +217 -0
  78. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.mjs +119 -0
  79. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.mjs +626 -0
  80. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.test.mjs +521 -0
  81. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.mjs +657 -0
  82. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +523 -0
  83. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/render.mjs +106 -0
  84. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/types.mjs +9 -0
  85. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +5 -0
  86. package/{assets → dist/pstack}/skills/poteto-mode/scripts/worktree-audit.mjs +15 -22
  87. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.test.mjs +134 -0
  88. package/{assets → dist/pstack}/skills/principle-attack-the-premise/SKILL.md +1 -1
  89. package/{assets → dist/pstack}/skills/principle-boundary-discipline/SKILL.md +1 -1
  90. package/{assets → dist/pstack}/skills/principle-encode-lessons-in-structure/SKILL.md +1 -1
  91. package/{assets → dist/pstack}/skills/principle-exhaust-the-design-space/SKILL.md +1 -1
  92. package/{assets → dist/pstack}/skills/principle-experience-first/SKILL.md +1 -1
  93. package/{assets → dist/pstack}/skills/principle-explain-the-number/SKILL.md +3 -2
  94. package/{assets → dist/pstack}/skills/principle-fix-root-causes/SKILL.md +1 -1
  95. package/{assets → dist/pstack}/skills/principle-laziness-protocol/SKILL.md +1 -1
  96. package/{assets → dist/pstack}/skills/principle-make-operations-idempotent/SKILL.md +1 -1
  97. package/{assets → dist/pstack}/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +1 -1
  98. package/{assets → dist/pstack}/skills/principle-minimize-reader-load/SKILL.md +1 -1
  99. package/{assets → dist/pstack}/skills/principle-model-the-domain/SKILL.md +1 -1
  100. package/{assets → dist/pstack}/skills/principle-never-block-on-the-human/SKILL.md +1 -1
  101. package/{assets → dist/pstack}/skills/principle-outcome-oriented-execution/SKILL.md +1 -1
  102. package/{assets → dist/pstack}/skills/principle-prove-it-works/SKILL.md +2 -2
  103. package/{assets → dist/pstack}/skills/principle-redesign-from-first-principles/SKILL.md +1 -1
  104. package/{assets → dist/pstack}/skills/principle-separate-before-serializing-shared-state/SKILL.md +1 -1
  105. package/{assets → dist/pstack}/skills/principle-sequence-verifiable-units/SKILL.md +1 -1
  106. package/{assets → dist/pstack}/skills/principle-subtract-before-you-add/SKILL.md +1 -1
  107. package/{assets → dist/pstack}/skills/principle-test-behavior-not-implementation/SKILL.md +1 -1
  108. package/{assets → dist/pstack}/skills/principle-type-system-discipline/SKILL.md +1 -1
  109. package/dist/pstack/skills/recall/SKILL.md +37 -0
  110. package/dist/pstack/skills/reflect/SKILL.md +71 -0
  111. package/{assets → dist/pstack}/skills/reflect/references/divergent-reviewer.md +4 -4
  112. package/{assets → dist/pstack}/skills/reflect/references/judgment-reviewer.md +2 -2
  113. package/{assets → dist/pstack}/skills/reflect/references/synthesizer.md +5 -5
  114. package/{assets → dist/pstack}/skills/reflect/references/tooling-reviewer.md +2 -2
  115. package/dist/pstack/skills/setup-pstack/SKILL.md +80 -0
  116. package/{assets → dist/pstack}/skills/sharpen/SKILL.md +1 -1
  117. package/{assets → dist/pstack}/skills/show-me-your-work/SKILL.md +8 -8
  118. package/{assets → dist/pstack}/skills/show-me-your-work/scripts/log.mjs +1 -3
  119. package/dist/pstack/skills/show-me-your-work/scripts/log.test.mjs +56 -0
  120. package/dist/pstack/skills/statechart/SKILL.md +82 -0
  121. package/dist/pstack/skills/statechart/references/render.md +93 -0
  122. package/dist/pstack/skills/statechart/scripts/backends/cfg.mjs +31 -0
  123. package/dist/pstack/skills/statechart/scripts/backends/mermaid.mjs +186 -0
  124. package/dist/pstack/skills/statechart/scripts/backends/plain-text.mjs +62 -0
  125. package/dist/pstack/skills/statechart/scripts/backends/report.mjs +84 -0
  126. package/dist/pstack/skills/statechart/scripts/frontends/config.mjs +268 -0
  127. package/dist/pstack/skills/statechart/scripts/frontends/dot.mjs +67 -0
  128. package/dist/pstack/skills/statechart/scripts/frontends/marks.mjs +94 -0
  129. package/dist/pstack/skills/statechart/scripts/frontends/messages.mjs +48 -0
  130. package/dist/pstack/skills/statechart/scripts/frontends/spec.mjs +101 -0
  131. package/dist/pstack/skills/statechart/scripts/frontends/trace.mjs +39 -0
  132. package/dist/pstack/skills/statechart/scripts/frontends/value.mjs +180 -0
  133. package/dist/pstack/skills/statechart/scripts/frontends/verdict.mjs +40 -0
  134. package/dist/pstack/skills/statechart/scripts/frontends/view.mjs +99 -0
  135. package/dist/pstack/skills/statechart/scripts/ir.mjs +277 -0
  136. package/dist/pstack/skills/statechart/scripts/passes/annotate.mjs +92 -0
  137. package/dist/pstack/skills/statechart/scripts/passes/label.mjs +210 -0
  138. package/dist/pstack/skills/statechart/scripts/passes/lift.mjs +84 -0
  139. package/dist/pstack/skills/statechart/scripts/passes/loop-check.mjs +47 -0
  140. package/dist/pstack/skills/statechart/scripts/passes/paths.mjs +72 -0
  141. package/dist/pstack/skills/statechart/scripts/passes/reach.mjs +135 -0
  142. package/dist/pstack/skills/statechart/scripts/passes/region-check.mjs +82 -0
  143. package/dist/pstack/skills/statechart/scripts/passes/regions.mjs +268 -0
  144. package/dist/pstack/skills/statechart/scripts/pipeline.mjs +72 -0
  145. package/dist/pstack/skills/statechart/scripts/run.mjs +440 -0
  146. package/dist/pstack/skills/statechart/scripts/statechart.mjs +155 -0
  147. package/dist/pstack/skills/statechart/scripts/statechart.test.mjs +198 -0
  148. package/dist/pstack/skills/statechart/scripts/worker.mjs +31 -0
  149. package/dist/pstack/skills/swarm/SKILL.md +43 -0
  150. package/{assets → dist/pstack}/skills/tdd/SKILL.md +1 -1
  151. package/{assets → dist/pstack}/skills/teach/SKILL.md +2 -2
  152. package/{assets → dist/pstack}/skills/technical-writing/SKILL.md +1 -1
  153. package/{assets → dist/pstack}/skills/typescript-best-practices/SKILL.md +3 -6
  154. package/{assets → dist/pstack}/skills/why/SKILL.md +8 -8
  155. package/dist/remote.d.mts +27 -0
  156. package/dist/remote.mjs +234 -0
  157. package/dist/role-config-NNn5r1JX.mjs +415 -0
  158. package/dist/role-manifest-C3fUzjLI.d.mts +19 -0
  159. package/dist/role-wire-DZwTn2wF.d.mts +55 -0
  160. package/dist/roles.d.mts +18 -0
  161. package/dist/roles.mjs +323 -0
  162. package/dist/script.d.mts +9 -111
  163. package/dist/script.mjs +32 -329
  164. package/dist/skill.d.mts +38 -0
  165. package/dist/skill.mjs +183 -0
  166. package/dist/skills/authored/decision-audit/SKILL.md +103 -0
  167. package/dist/skills/authored/decision-audit/SKILL.zh.md +103 -0
  168. package/dist/skills/authored/decision-audit/references/recover-commit.md +17 -0
  169. package/dist/skills/authored/decision-audit/references/recover-commit.zh.md +17 -0
  170. package/dist/skills/authored/decision-write/SKILL.md +133 -0
  171. package/dist/skills/authored/decision-write/SKILL.zh.md +133 -0
  172. package/dist/skills/authored/decision-write/references/land.md +48 -0
  173. package/dist/skills/authored/decision-write/references/land.zh.md +48 -0
  174. package/dist/skills/authored/decision-write/references/scope.md +16 -0
  175. package/dist/skills/authored/decision-write/references/scope.zh.md +16 -0
  176. package/dist/skills/authored/docs-drift/SKILL.md +120 -0
  177. package/dist/skills/authored/docs-drift/SKILL.zh.md +120 -0
  178. package/dist/skills/authored/setup-project-docs/SKILL.md +63 -0
  179. package/dist/skills/authored/setup-project-docs/SKILL.zh.md +63 -0
  180. package/dist/skills/authored/setup-project-docs/references/decision-conventions.md +13 -0
  181. package/dist/skills/authored/setup-project-docs/references/decision-conventions.zh.md +13 -0
  182. package/dist/skills/vendored/retro/SKILL.md +44 -0
  183. package/dist/skills/vendored/retro/agents/openai.yaml +5 -0
  184. package/dist/skills/vendored/writing-for-agents/SKILL-MECHANICS.md +22 -0
  185. package/dist/skills/vendored/writing-for-agents/SKILL.md +81 -0
  186. package/dist/skills/vendored/writing-for-agents/agents/openai.yaml +3 -0
  187. package/dist/subagent.d.mts +54 -206
  188. package/dist/subagent.mjs +258 -963
  189. package/locale/en.json +3 -2
  190. package/locale/zh.json +3 -2
  191. package/package.json +93 -66
  192. package/assets/agents/poteto-agent.md +0 -8
  193. package/assets/docs/harness/dsh.md +0 -60
  194. package/assets/docs/pstack-models.example.md +0 -54
  195. package/assets/skills/arena/SKILL.md +0 -50
  196. package/assets/skills/figure-it-out/SKILL.md +0 -54
  197. package/assets/skills/how/SKILL.md +0 -38
  198. package/assets/skills/interrogate/SKILL.md +0 -71
  199. package/assets/skills/interrogate/references/code-quality-review.md +0 -47
  200. package/assets/skills/interrogate/references/lead-judgment.md +0 -39
  201. package/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  202. package/assets/skills/interrogate/references/rubric.md +0 -77
  203. package/assets/skills/no-comments/SKILL.md +0 -26
  204. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  205. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -15
  206. package/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  207. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  208. package/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  209. package/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  210. package/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  211. package/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  212. package/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  213. package/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  214. package/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  215. package/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  216. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -20
  217. package/assets/skills/poteto-mode/scripts/orch/orch.mjs +0 -4282
  218. package/assets/skills/poteto-mode/scripts/orch/orch.test.mjs +0 -2042
  219. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +0 -5101
  220. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.mjs +0 -1177
  221. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +0 -1441
  222. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +0 -4601
  223. package/assets/skills/recall/SKILL.md +0 -37
  224. package/assets/skills/reflect/SKILL.md +0 -69
  225. package/assets/skills/setup-pstack/SKILL.md +0 -67
  226. package/assets/skills/swarm/SKILL.md +0 -43
  227. package/dist/frontmatter-BQX3ekwP.mjs +0 -229
  228. package/dist/frontmatter-BQX3ekwP.mjs.map +0 -1
  229. package/dist/history.d.mts +0 -429
  230. package/dist/history.mjs +0 -1129
  231. package/dist/history.mjs.map +0 -1
  232. package/dist/host-contract-o47JH_r8.d.mts +0 -527
  233. package/dist/index.mjs.map +0 -1
  234. package/dist/paths-D_JlVmBk.mjs +0 -42
  235. package/dist/paths-D_JlVmBk.mjs.map +0 -1
  236. package/dist/script.mjs.map +0 -1
  237. package/dist/subagent.mjs.map +0 -1
  238. /package/{static/icon.png → assets/logo.png} +0 -0
  239. /package/{assets → dist/pstack}/agents/comment-sicko.md +0 -0
  240. /package/{assets → dist/pstack}/docs/guide/03-understand.md +0 -0
  241. /package/{assets → dist/pstack}/docs/guide/08-principles.md +0 -0
  242. /package/{assets → dist/pstack}/docs/guide/images/design.jpg +0 -0
  243. /package/{assets → dist/pstack}/docs/guide/images/overnight.jpg +0 -0
  244. /package/{assets → dist/pstack}/docs/guide/images/recipes.jpg +0 -0
  245. /package/{assets → dist/pstack}/docs/guide/images/router.jpg +0 -0
  246. /package/{assets → dist/pstack}/docs/guide/images/understanding.jpg +0 -0
  247. /package/{assets → dist/pstack}/docs/guide/images/verification.jpg +0 -0
  248. /package/{assets → dist/pstack}/skills/architect/references/design-red-flags.md +0 -0
  249. /package/{assets → dist/pstack}/skills/architect/references/rationale-template.md +0 -0
  250. /package/{assets → dist/pstack}/skills/architect/references/runner-prompt.md +0 -0
  251. /package/{assets → dist/pstack}/skills/bro/SKILL.md +0 -0
  252. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/README.md +0 -0
  253. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -0
  254. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/search.md +0 -0
  255. /package/{assets → dist/pstack}/skills/how/references/explainer-prompt.md +0 -0
  256. /package/{assets → dist/pstack}/skills/how/references/explorer-prompt.md +0 -0
  257. /package/{assets → dist/pstack}/skills/poteto-mode/references/bugbot-triage.md +0 -0
  258. /package/{assets → dist/pstack}/skills/principle-build-the-lever/SKILL.md +0 -0
  259. /package/{assets → dist/pstack}/skills/principle-foundational-thinking/SKILL.md +0 -0
  260. /package/{assets → dist/pstack}/skills/principle-guard-the-context-window/SKILL.md +0 -0
  261. /package/{assets → dist/pstack}/skills/show-me-your-work/references/decision-log-template.tsv +0 -0
  262. /package/{assets → dist/pstack}/skills/typescript-best-practices/references/patterns.md +0 -0
  263. /package/{assets → dist/pstack}/skills/unslop/SKILL.md +0 -0
  264. /package/{assets → dist/pstack}/skills/why/references/epistemics.md +0 -0
  265. /package/{assets → dist/pstack}/skills/why/references/investigator-prompt.md +0 -0
  266. /package/{assets → dist/pstack}/skills/why/references/source-playbook.md +0 -0
  267. /package/{assets → dist/pstack}/skills/why/references/sources/code-archaeology.md +0 -0
  268. /package/{assets → dist/pstack}/skills/why/references/sources/databricks.md +0 -0
  269. /package/{assets → dist/pstack}/skills/why/references/sources/datadog.md +0 -0
  270. /package/{assets → dist/pstack}/skills/why/references/sources/incident-postmortem.md +0 -0
  271. /package/{assets → dist/pstack}/skills/why/references/sources/linear.md +0 -0
  272. /package/{assets → dist/pstack}/skills/why/references/sources/notion.md +0 -0
  273. /package/{assets → dist/pstack}/skills/why/references/sources/sentry.md +0 -0
  274. /package/{assets → dist/pstack}/skills/why/references/sources/slack.md +0 -0
  275. /package/{assets → dist/pstack}/skills/why/references/synthesizer-prompt.md +0 -0
@@ -0,0 +1,657 @@
1
+ import { nonEmpty } from "./types.mjs";
2
+ import { WatcherQueryError, resolveChecks, resolveReviewThreads } from "./github.mjs";
3
+ // runtime/skills/poteto-mode/scripts/watch-pr/policy.ts
4
+ function assessGitHubMerge(args) {
5
+ if (args.mergeStateStatus === "BLOCKED") {
6
+ if (args.headRollupState === "ERROR" || args.headRollupState === "FAILURE") return {
7
+ kind: "refused",
8
+ mergeStateStatus: args.mergeStateStatus,
9
+ headRollupState: args.headRollupState
10
+ };
11
+ return {
12
+ kind: "allowed",
13
+ basis: "rollup",
14
+ mergeStateStatus: args.mergeStateStatus,
15
+ headRollupState: args.headRollupState
16
+ };
17
+ }
18
+ return {
19
+ kind: "allowed",
20
+ basis: "merge-state",
21
+ mergeStateStatus: args.mergeStateStatus,
22
+ headRollupState: args.headRollupState
23
+ };
24
+ }
25
+ async function mergeAssessment(reader, facts) {
26
+ const commits = await reader.commitRollups(facts.context);
27
+ const headRollupState = facts.headRefOid === null ? null : commits.find((commit) => commit.oid === facts.headRefOid)?.state ?? null;
28
+ return {
29
+ hadPreviousPassingCi: commits.some((commit) => commit.oid !== facts.headRefOid && commit.state === "SUCCESS"),
30
+ github: assessGitHubMerge({
31
+ mergeStateStatus: facts.mergeStateStatus,
32
+ headRollupState
33
+ })
34
+ };
35
+ }
36
+ const AUTOMATION_TOKENS = [
37
+ "bugbot",
38
+ "security review",
39
+ "pr review automation",
40
+ "review automation"
41
+ ];
42
+ async function readSnapshot(args) {
43
+ const facts = await args.reader.pullRequest(args.context);
44
+ if (facts.state === "MERGED" || facts.mergedAt !== null) return {
45
+ kind: "merged",
46
+ context: args.context,
47
+ facts
48
+ };
49
+ if (facts.state === "CLOSED") return {
50
+ kind: "closed",
51
+ context: args.context,
52
+ facts
53
+ };
54
+ const threads = await resolveReviewThreads(args.reader, args.context);
55
+ const checks = await resolveChecks(args.reader, args.context);
56
+ const failed = nonEmpty(checks.checks.filter((check) => check.kind === "failed"));
57
+ const pending = nonEmpty(checks.checks.filter((check) => check.kind === "pending"));
58
+ let ci;
59
+ if (failed === null && pending !== null && args.pendingHistory === "omit") ci = {
60
+ kind: "ci-pending",
61
+ source: checks.source,
62
+ all: checks.checks,
63
+ failed: [],
64
+ pending,
65
+ hadPreviousPassingCi: false
66
+ };
67
+ else {
68
+ const merge = await mergeAssessment(args.reader, facts);
69
+ const base = {
70
+ source: checks.source,
71
+ all: checks.checks,
72
+ hadPreviousPassingCi: merge.hadPreviousPassingCi
73
+ };
74
+ if (failed !== null) ci = {
75
+ ...base,
76
+ kind: "ci-failing",
77
+ failed,
78
+ pending: pending ?? [],
79
+ github: merge.github
80
+ };
81
+ else if (merge.github.kind === "refused") ci = {
82
+ ...base,
83
+ kind: "ci-github-rejected",
84
+ failed: [],
85
+ pending: pending ?? [],
86
+ github: merge.github
87
+ };
88
+ else if (pending !== null) ci = {
89
+ ...base,
90
+ kind: "ci-pending",
91
+ failed: [],
92
+ pending
93
+ };
94
+ else ci = {
95
+ ...base,
96
+ kind: "ci-clean",
97
+ failed: [],
98
+ pending: [],
99
+ github: merge.github
100
+ };
101
+ }
102
+ return {
103
+ kind: "open",
104
+ context: args.context,
105
+ facts,
106
+ threads,
107
+ ci,
108
+ reviewAutomationRunning: checks.checks.some((check) => check.kind === "pending" && AUTOMATION_TOKENS.some((token) => check.name.toLowerCase().includes(token)))
109
+ };
110
+ }
111
+ const conflictBlocker = (row) => row.kind === "open" && (row.facts.mergeable === "CONFLICTING" || row.facts.mergeStateStatus === "DIRTY" || row.facts.mergeStateStatus === "CONFLICTING") ? {
112
+ kind: "merge-conflicts",
113
+ pr: row.context,
114
+ facts: row.facts
115
+ } : null;
116
+ function threadBlocker(row) {
117
+ if (row.kind !== "open") return null;
118
+ const threads = nonEmpty(row.threads);
119
+ return threads === null ? null : {
120
+ kind: "review-threads",
121
+ pr: row.context,
122
+ threads
123
+ };
124
+ }
125
+ const ciBlocker = (row) => row.kind === "open" && (row.ci.kind === "ci-failing" || row.ci.kind === "ci-github-rejected") ? {
126
+ kind: "failing-checks",
127
+ pr: row.context,
128
+ ci: row.ci
129
+ } : null;
130
+ function gateReason(row, allowDraft) {
131
+ if (row.kind === "merged") return null;
132
+ if (row.kind === "closed") return "closed-without-merge";
133
+ if (row.facts.isDraft && !allowDraft) return "draft-pr";
134
+ return row.facts.reviewDecision === "CHANGES_REQUESTED" ? "changes-requested" : null;
135
+ }
136
+ function gateBlocker(row, allowDraft) {
137
+ const reason = gateReason(row, allowDraft);
138
+ return reason === null || reason === "draft-pr" && row.kind === "open" && row.ci.kind === "ci-pending" ? null : {
139
+ kind: "merge-gate",
140
+ pr: row.context,
141
+ reason
142
+ };
143
+ }
144
+ function readyContribution(row, allowDraft) {
145
+ if (row.kind === "merged") return {
146
+ kind: "merged-pr",
147
+ context: row.context,
148
+ mergedAt: row.facts.mergedAt
149
+ };
150
+ if (row.kind !== "open" || row.ci.kind !== "ci-clean" || row.threads.length !== 0 || conflictBlocker(row) !== null || gateReason(row, allowDraft) !== null) return null;
151
+ const reviewDecision = row.facts.reviewDecision;
152
+ if (reviewDecision === "CHANGES_REQUESTED") return null;
153
+ return {
154
+ kind: "ready-pr",
155
+ context: row.context,
156
+ proof: {
157
+ mergeability: "clear",
158
+ threads: [],
159
+ ci: row.ci,
160
+ gate: {
161
+ state: "OPEN",
162
+ reviewDecision,
163
+ draft: row.facts.isDraft ? "draft-allowed" : "not-draft"
164
+ }
165
+ }
166
+ };
167
+ }
168
+ function classifyPr(row, allowDraft = false) {
169
+ for (const blocker of [
170
+ conflictBlocker(row),
171
+ threadBlocker(row),
172
+ ciBlocker(row),
173
+ gateBlocker(row, allowDraft)
174
+ ]) if (blocker !== null) return {
175
+ kind: "blocker",
176
+ blocker
177
+ };
178
+ if (row.kind === "open" && row.ci.kind === "ci-pending") return {
179
+ kind: "waiting",
180
+ frontier: row.context,
181
+ pending: row.ci.pending
182
+ };
183
+ const ready = readyContribution(row, allowDraft);
184
+ if (ready === null) throw new Error("snapshot has no classified decision");
185
+ return ready.kind === "merged-pr" ? {
186
+ kind: "merged",
187
+ pr: ready
188
+ } : {
189
+ kind: "ready",
190
+ pr: ready
191
+ };
192
+ }
193
+ function selectTierMajorStackDecision(rows, allowDraft = false) {
194
+ for (const tier of [
195
+ conflictBlocker,
196
+ threadBlocker,
197
+ ciBlocker
198
+ ]) for (const row of rows) {
199
+ const blocker = tier(row);
200
+ if (blocker !== null) return {
201
+ kind: "blocker",
202
+ blocker
203
+ };
204
+ }
205
+ for (const row of rows) {
206
+ const blocker = gateBlocker(row, allowDraft);
207
+ if (blocker !== null) return {
208
+ kind: "blocker",
209
+ blocker
210
+ };
211
+ }
212
+ for (const row of rows) if (row.kind === "open" && row.ci.kind === "ci-pending") return {
213
+ kind: "waiting",
214
+ frontier: row.context,
215
+ pending: row.ci.pending
216
+ };
217
+ const prs = nonEmpty(rows.map((row) => readyContribution(row, allowDraft)).filter((row) => row !== null));
218
+ if (prs === null || prs.length !== rows.length) throw new Error("stack has no classified decision");
219
+ return {
220
+ kind: "clear",
221
+ prs
222
+ };
223
+ }
224
+ const queryBackoffSeconds = (interval, failures) => Math.min(Math.max(interval, 60) * 2 ** (failures - 1), 300);
225
+ function verdictFactory(clock, mode) {
226
+ let sequence = 0;
227
+ function stamp(payload, override) {
228
+ return {
229
+ schemaVersion: 1,
230
+ sequence: sequence += 1,
231
+ observedAt: clock.observedAt(),
232
+ mode: override ?? mode,
233
+ ...payload
234
+ };
235
+ }
236
+ return stamp;
237
+ }
238
+ function blockerVerdict(stamp, blocker) {
239
+ switch (blocker.kind) {
240
+ case "merge-conflicts": return stamp({
241
+ kind: "BLOCKER",
242
+ terminal: true,
243
+ exitCode: 2,
244
+ blocker
245
+ });
246
+ case "review-threads": return stamp({
247
+ kind: "BLOCKER",
248
+ terminal: true,
249
+ exitCode: 3,
250
+ blocker
251
+ });
252
+ case "failing-checks": return stamp({
253
+ kind: "BLOCKER",
254
+ terminal: true,
255
+ exitCode: 4,
256
+ blocker
257
+ });
258
+ case "merge-gate": return stamp({
259
+ kind: "BLOCKER",
260
+ terminal: true,
261
+ exitCode: 6,
262
+ blocker
263
+ });
264
+ default: return blocker;
265
+ }
266
+ }
267
+ function statusQueryVerdict(stamp, failures, failure) {
268
+ return stamp({
269
+ kind: "BLOCKER",
270
+ terminal: true,
271
+ exitCode: 7,
272
+ blocker: {
273
+ kind: "status-query",
274
+ failures,
275
+ failure
276
+ }
277
+ });
278
+ }
279
+ const deadlinePassed = (started, options, now) => options.timeout > 0 && now - started >= options.timeout;
280
+ async function pollUntilTerminal(args) {
281
+ let failures = 0;
282
+ const started = args.dependencies.clock.now();
283
+ const sleep = async (seconds) => {
284
+ const remaining = args.options.timeout > 0 ? Math.max(0, args.options.timeout - (args.dependencies.clock.now() - started)) : seconds;
285
+ await args.dependencies.clock.sleep(Math.min(seconds, remaining));
286
+ };
287
+ while (true) {
288
+ let result;
289
+ try {
290
+ result = await args.step();
291
+ failures = 0;
292
+ } catch (error) {
293
+ if (!(error instanceof WatcherQueryError)) throw error;
294
+ failures += 1;
295
+ if (!error.failure.retryable || failures >= args.options.maxQueryErrors) return statusQueryVerdict(args.stamp, failures, error.failure);
296
+ const retryInSeconds = queryBackoffSeconds(args.options.interval, failures);
297
+ args.dependencies.emit(args.stamp({
298
+ kind: "RETRY",
299
+ terminal: false,
300
+ failure: error.failure,
301
+ consecutiveFailures: failures,
302
+ retryInSeconds
303
+ }));
304
+ if (deadlinePassed(started, args.options, args.dependencies.clock.now())) return args.stamp({
305
+ kind: "TIMEOUT",
306
+ terminal: true,
307
+ exitCode: 5,
308
+ reason: {
309
+ kind: "status-unavailable",
310
+ failure: error.failure
311
+ }
312
+ });
313
+ await sleep(retryInSeconds);
314
+ continue;
315
+ }
316
+ if (result.kind === "terminal") return result.verdict;
317
+ if (result.kind === "sleep") {
318
+ if (result.onDeadline !== void 0 && deadlinePassed(started, args.options, args.dependencies.clock.now())) return result.onDeadline();
319
+ await sleep(result.seconds);
320
+ }
321
+ }
322
+ }
323
+ async function runSimple(args) {
324
+ const stamp = verdictFactory(args.dependencies.clock, args.mode);
325
+ const step = async () => {
326
+ const rows = [];
327
+ for (const context of args.contexts) rows.push(await readSnapshot({
328
+ reader: args.dependencies.reader,
329
+ context,
330
+ pendingHistory: "include",
331
+ allowDraft: args.options.allowDraft
332
+ }));
333
+ const complete = nonEmpty(rows);
334
+ if (complete === null) throw new Error("watch context cannot be empty");
335
+ if (args.statusOnly) return {
336
+ kind: "terminal",
337
+ verdict: stamp({
338
+ kind: "STATUS",
339
+ terminal: true,
340
+ exitCode: 0,
341
+ reason: "status-only",
342
+ rows: complete
343
+ })
344
+ };
345
+ if (args.mode === "queued-stack") throw new Error("queued-stack requires status-only in the simple runner");
346
+ if (args.mode === "stack") args.dependencies.emit(stamp({
347
+ kind: "STATUS",
348
+ terminal: false,
349
+ reason: "poll",
350
+ rows: complete
351
+ }, args.mode));
352
+ const decision = args.mode === "single" ? classifyPr(complete[0], args.options.allowDraft) : selectTierMajorStackDecision(complete, args.options.allowDraft);
353
+ if (decision.kind === "blocker") return {
354
+ kind: "terminal",
355
+ verdict: blockerVerdict(stamp, decision.blocker)
356
+ };
357
+ if (decision.kind === "ready" || decision.kind === "merged") return {
358
+ kind: "terminal",
359
+ verdict: stamp({
360
+ kind: "READY",
361
+ terminal: true,
362
+ exitCode: 0,
363
+ scope: {
364
+ kind: "single",
365
+ pr: decision.pr
366
+ }
367
+ }, args.mode)
368
+ };
369
+ if (decision.kind === "clear") return {
370
+ kind: "terminal",
371
+ verdict: stamp({
372
+ kind: "READY",
373
+ terminal: true,
374
+ exitCode: 0,
375
+ scope: {
376
+ kind: "stack",
377
+ prs: decision.prs
378
+ }
379
+ }, args.mode)
380
+ };
381
+ args.dependencies.emit(stamp({
382
+ kind: "WAITING",
383
+ terminal: false,
384
+ frontier: decision.frontier,
385
+ reason: {
386
+ kind: "pending-checks",
387
+ pending: decision.pending
388
+ }
389
+ }));
390
+ return {
391
+ kind: "sleep",
392
+ seconds: args.options.interval,
393
+ onDeadline: () => stamp({
394
+ kind: "TIMEOUT",
395
+ terminal: true,
396
+ exitCode: 5,
397
+ reason: {
398
+ kind: "pending-checks",
399
+ pending: decision.pending
400
+ }
401
+ })
402
+ };
403
+ };
404
+ return pollUntilTerminal({
405
+ dependencies: args.dependencies,
406
+ options: args.options,
407
+ stamp,
408
+ step
409
+ });
410
+ }
411
+ const createQueueState = (queue, now) => ({
412
+ queue,
413
+ snapshots: /* @__PURE__ */ new Map(),
414
+ work: {
415
+ kind: "whole-stack-sweep",
416
+ remaining: queue
417
+ },
418
+ nextSweepAt: now,
419
+ frontier: null,
420
+ lastWaitKey: null,
421
+ startedAt: now
422
+ });
423
+ const orderedRows = (state) => state.queue.flatMap((context) => {
424
+ const row = state.snapshots.get(context.number);
425
+ return row === void 0 ? [] : [row];
426
+ });
427
+ const activeRows = (state) => orderedRows(state).filter((row) => row.kind !== "merged");
428
+ function planQueue(state, now) {
429
+ if (state.work !== null) return state;
430
+ if (state.snapshots.size === 0 || now >= state.nextSweepAt) {
431
+ const remaining = nonEmpty(state.queue.filter((context) => state.snapshots.get(context.number)?.kind !== "merged"));
432
+ if (remaining !== null) return {
433
+ ...state,
434
+ work: {
435
+ kind: "whole-stack-sweep",
436
+ remaining
437
+ }
438
+ };
439
+ }
440
+ const frontier = activeRows(state)[0]?.context;
441
+ return frontier === void 0 ? state : {
442
+ ...state,
443
+ work: {
444
+ kind: "frontier-poll",
445
+ frontier
446
+ }
447
+ };
448
+ }
449
+ function applyQueueSnapshot(state, snapshot, now, options) {
450
+ if (state.work === null) throw new Error("queue has no read in flight");
451
+ const snapshots = new Map(state.snapshots);
452
+ snapshots.set(snapshot.context.number, snapshot);
453
+ const base = {
454
+ ...state,
455
+ snapshots
456
+ };
457
+ if (state.work.kind === "frontier-poll") return {
458
+ state: {
459
+ ...base,
460
+ work: null
461
+ },
462
+ completedSweepRows: null
463
+ };
464
+ const [head, ...tail] = state.work.remaining;
465
+ if (head.number !== snapshot.context.number) throw new Error("snapshot does not match sweep head");
466
+ const remaining = nonEmpty(tail);
467
+ if (remaining !== null) return {
468
+ state: {
469
+ ...base,
470
+ work: {
471
+ kind: "whole-stack-sweep",
472
+ remaining
473
+ }
474
+ },
475
+ completedSweepRows: null
476
+ };
477
+ const rows = nonEmpty(state.queue.flatMap((context) => {
478
+ const row = snapshots.get(context.number);
479
+ return row === void 0 ? [] : [row];
480
+ }));
481
+ if (rows === null || rows.length !== state.queue.length) throw new Error("sweep completed without every snapshot");
482
+ return {
483
+ state: {
484
+ ...base,
485
+ work: null,
486
+ nextSweepAt: now + options.sweepInterval
487
+ },
488
+ completedSweepRows: rows
489
+ };
490
+ }
491
+ function evaluateQueue(state, now, options) {
492
+ const active = activeRows(state);
493
+ if (active.length === 0) {
494
+ const merged = nonEmpty(orderedRows(state).flatMap((row) => row.kind === "merged" ? [{
495
+ kind: "merged-pr",
496
+ context: row.context,
497
+ mergedAt: row.facts.mergedAt
498
+ }] : []));
499
+ if (merged === null) throw new Error("empty queue cannot complete");
500
+ return {
501
+ kind: "complete",
502
+ state,
503
+ merged
504
+ };
505
+ }
506
+ const rows = nonEmpty(active);
507
+ if (rows === null) throw new Error("active queue cannot be empty");
508
+ const decision = selectTierMajorStackDecision(rows, options.allowDraft);
509
+ if (decision.kind === "blocker") return {
510
+ kind: "blocker",
511
+ state,
512
+ blocker: decision.blocker
513
+ };
514
+ const frontier = rows[0].context;
515
+ if (state.frontier !== null && state.frontier.number !== frontier.number) return {
516
+ kind: "advance",
517
+ state: {
518
+ ...state,
519
+ frontier,
520
+ lastWaitKey: null
521
+ },
522
+ merged: state.frontier,
523
+ frontier,
524
+ remaining: active.length
525
+ };
526
+ if (deadlinePassed(state.startedAt, options, now)) return {
527
+ kind: "timeout",
528
+ state: {
529
+ ...state,
530
+ frontier
531
+ },
532
+ frontier,
533
+ unmergedCount: active.length
534
+ };
535
+ const row = rows[0];
536
+ const pending = row.kind === "open" && row.ci.kind === "ci-pending" ? row.ci.pending : null;
537
+ const reason = pending === null ? {
538
+ kind: "merge-queue",
539
+ unmergedCount: active.length
540
+ } : {
541
+ kind: "pending-checks",
542
+ pending
543
+ };
544
+ const key = reason.kind === "pending-checks" ? `pending:${frontier.number}:${reason.pending.length}` : `queue:${frontier.number}:${reason.unmergedCount}`;
545
+ return {
546
+ kind: "waiting",
547
+ state: {
548
+ ...state,
549
+ frontier,
550
+ lastWaitKey: key
551
+ },
552
+ frontier,
553
+ reason,
554
+ emit: state.lastWaitKey !== key
555
+ };
556
+ }
557
+ async function runQueued(args) {
558
+ let state = createQueueState(args.contexts, args.dependencies.clock.now());
559
+ const stamp = verdictFactory(args.dependencies.clock, "queued-stack");
560
+ args.dependencies.emit(stamp({
561
+ kind: "QUEUE",
562
+ terminal: false,
563
+ queue: args.contexts
564
+ }));
565
+ const step = async () => {
566
+ state = planQueue(state, args.dependencies.clock.now());
567
+ if (state.work === null) {
568
+ const complete = evaluateQueue(state, args.dependencies.clock.now(), args.options);
569
+ if (complete.kind !== "complete") throw new Error("queue has no work while active");
570
+ return {
571
+ kind: "terminal",
572
+ verdict: stamp({
573
+ kind: "COMPLETE",
574
+ terminal: true,
575
+ exitCode: 0,
576
+ queue: state.queue,
577
+ merged: complete.merged
578
+ })
579
+ };
580
+ }
581
+ const context = state.work.kind === "whole-stack-sweep" ? state.work.remaining[0] : state.work.frontier;
582
+ const snapshot = await readSnapshot({
583
+ reader: args.dependencies.reader,
584
+ context,
585
+ pendingHistory: "omit",
586
+ allowDraft: args.options.allowDraft
587
+ });
588
+ const applied = applyQueueSnapshot(state, snapshot, args.dependencies.clock.now(), args.options);
589
+ state = applied.state;
590
+ if (applied.completedSweepRows !== null) args.dependencies.emit(stamp({
591
+ kind: "STATUS",
592
+ terminal: false,
593
+ reason: "whole-stack-sweep",
594
+ rows: applied.completedSweepRows
595
+ }));
596
+ if (state.work !== null) return { kind: "continue" };
597
+ const evaluation = evaluateQueue(state, args.dependencies.clock.now(), args.options);
598
+ state = evaluation.state;
599
+ switch (evaluation.kind) {
600
+ case "complete": return {
601
+ kind: "terminal",
602
+ verdict: stamp({
603
+ kind: "COMPLETE",
604
+ terminal: true,
605
+ exitCode: 0,
606
+ queue: state.queue,
607
+ merged: evaluation.merged
608
+ })
609
+ };
610
+ case "blocker": return {
611
+ kind: "terminal",
612
+ verdict: blockerVerdict(stamp, evaluation.blocker)
613
+ };
614
+ case "advance":
615
+ args.dependencies.emit(stamp({
616
+ kind: "ADVANCE",
617
+ terminal: false,
618
+ merged: evaluation.merged,
619
+ frontier: evaluation.frontier,
620
+ remaining: evaluation.remaining
621
+ }));
622
+ return { kind: "continue" };
623
+ case "timeout": return {
624
+ kind: "terminal",
625
+ verdict: stamp({
626
+ kind: "TIMEOUT",
627
+ terminal: true,
628
+ exitCode: 5,
629
+ reason: {
630
+ kind: "queued-stack",
631
+ frontier: evaluation.frontier,
632
+ unmergedCount: evaluation.unmergedCount
633
+ }
634
+ })
635
+ };
636
+ case "waiting":
637
+ if (evaluation.emit) args.dependencies.emit(stamp({
638
+ kind: "WAITING",
639
+ terminal: false,
640
+ frontier: evaluation.frontier,
641
+ reason: evaluation.reason
642
+ }));
643
+ return {
644
+ kind: "sleep",
645
+ seconds: args.options.interval
646
+ };
647
+ default: return evaluation;
648
+ }
649
+ };
650
+ return pollUntilTerminal({
651
+ dependencies: args.dependencies,
652
+ options: args.options,
653
+ stamp,
654
+ step
655
+ });
656
+ }
657
+ export { applyQueueSnapshot, assessGitHubMerge, classifyPr, createQueueState, evaluateQueue, planQueue, queryBackoffSeconds, readSnapshot, runQueued, runSimple, selectTierMajorStackDecision, statusQueryVerdict, verdictFactory };