dsh-pstack 0.1.0 → 0.2.0-beta.3

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 (406) hide show
  1. package/LICENSE +2 -3
  2. package/README.md +174 -148
  3. package/README.zh.md +185 -0
  4. package/assets/logo.png +0 -0
  5. package/cordis.patch.yml +103 -14
  6. package/dist/host-contract-CUPSpeNk.d.mts +22 -0
  7. package/dist/index.d.mts +87 -14
  8. package/dist/index.mjs +370 -143
  9. package/dist/models.d.mts +44 -0
  10. package/dist/models.mjs +201 -0
  11. package/dist/paths-BT77khwm.mjs +48 -0
  12. package/dist/{LICENSE → pstack/LICENSE} +1 -2
  13. package/dist/pstack/README.md +291 -0
  14. package/{assets → dist/pstack}/agents/comment-sicko.md +1 -1
  15. package/dist/pstack/agents/poteto-agent.md +9 -0
  16. package/{assets → dist/pstack}/docs/guide/01-setup.md +11 -9
  17. package/dist/{assets → pstack}/docs/guide/02-poteto-mode.md +2 -2
  18. package/{assets → dist/pstack}/docs/guide/04-design.md +4 -4
  19. package/dist/{assets → pstack}/docs/guide/05-build-and-clean.md +3 -3
  20. package/dist/{assets → pstack}/docs/guide/06-verify-and-ship.md +11 -1
  21. package/{assets → dist/pstack}/docs/guide/07-overnight.md +10 -10
  22. package/dist/{assets → pstack}/docs/guide/09-make-it-yours.md +4 -4
  23. package/{assets → dist/pstack}/docs/guide/10-recipes-and-pitfalls.md +6 -4
  24. package/dist/pstack/docs/guide/images/design.jpg +0 -0
  25. package/dist/pstack/docs/guide/images/overnight.jpg +0 -0
  26. package/dist/pstack/docs/guide/images/recipes.jpg +0 -0
  27. package/dist/pstack/docs/guide/images/router.jpg +0 -0
  28. package/dist/pstack/docs/guide/images/understanding.jpg +0 -0
  29. package/dist/pstack/docs/guide/images/verification.jpg +0 -0
  30. package/dist/pstack/docs/harness/dsh.md +98 -0
  31. package/{assets → dist/pstack}/skills/architect/SKILL.md +5 -5
  32. package/dist/pstack/skills/arena/SKILL.md +50 -0
  33. package/{assets → dist/pstack}/skills/automate-me/SKILL.md +14 -13
  34. package/dist/{assets → pstack}/skills/benchmark-checklist/SKILL.md +1 -3
  35. package/dist/{assets → pstack}/skills/blast-radius/SKILL.md +1 -3
  36. package/{assets → dist/pstack}/skills/bro/SKILL.md +0 -2
  37. package/dist/{assets → pstack}/skills/correct/SKILL.md +1 -3
  38. package/{assets → dist/pstack}/skills/create-formal-verification-skill/SKILL.md +5 -3
  39. package/{assets → dist/pstack}/skills/create-verification-skill/SKILL.md +6 -6
  40. package/{assets → dist/pstack}/skills/figure-it-out/SKILL.md +4 -4
  41. package/dist/{assets → pstack}/skills/how/SKILL.md +4 -4
  42. package/{assets → dist/pstack}/skills/how/references/explainer-prompt.md +1 -1
  43. package/dist/pstack/skills/in-your-own-words/SKILL.md +7 -0
  44. package/dist/pstack/skills/interrogate/SKILL.md +33 -0
  45. package/{assets → dist/pstack}/skills/ketchup/SKILL.md +1 -3
  46. package/dist/pstack/skills/ketchup-video/SKILL.md +29 -0
  47. package/{assets → dist/pstack}/skills/maintain-formal-verification-skill/SKILL.md +2 -2
  48. package/dist/{assets → pstack}/skills/maintain-verification-skill/SKILL.md +3 -3
  49. package/dist/pstack/skills/make-bot-ui/SKILL.md +117 -0
  50. package/{assets → dist/pstack}/skills/no-comments/SKILL.md +4 -4
  51. package/{assets → dist/pstack}/skills/poteto-help/SKILL.md +21 -17
  52. package/dist/{assets → pstack}/skills/poteto-help/references/prompting.md +1 -1
  53. package/dist/{assets → pstack}/skills/poteto-help/references/recipes.md +3 -3
  54. package/{assets → dist/pstack}/skills/poteto-mode/SKILL.md +20 -21
  55. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/authoring-a-skill.md +1 -1
  56. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/autonomous-run.md +2 -2
  57. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/autopilot-full.md +7 -7
  58. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  59. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/babysit.md +3 -3
  60. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/bug-fix.md +3 -3
  61. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/eval.md +1 -1
  62. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/feature.md +1 -1
  63. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/hillclimb.md +1 -1
  64. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/multi-phase-plan.md +13 -13
  65. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/opening-a-pr.md +3 -3
  66. package/dist/pstack/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  67. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/perf-issue.md +2 -2
  68. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/prototype.md +1 -1
  69. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/refactoring.md +2 -2
  70. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/runtime-forensics.md +1 -1
  71. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/session-pickup.md +1 -1
  72. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/shipping.md +2 -2
  73. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/visual-parity.md +1 -1
  74. package/dist/{assets → pstack}/skills/poteto-mode/playbooks/worktree-cleanup.md +2 -2
  75. package/{assets → dist/pstack}/skills/poteto-mode/scripts/check-plan.mjs +83 -70
  76. package/dist/{assets/skills/poteto-mode/scripts/check-plan.test.ts → pstack/skills/poteto-mode/scripts/check-plan.test.mjs} +53 -21
  77. package/dist/pstack/skills/poteto-mode/scripts/expect.mjs +254 -0
  78. package/dist/pstack/skills/poteto-mode/scripts/support.mjs +93 -0
  79. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.mjs +123 -0
  80. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +217 -0
  81. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.mjs +119 -0
  82. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.mjs +626 -0
  83. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.test.mjs +521 -0
  84. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.mjs +657 -0
  85. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +523 -0
  86. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/render.mjs +106 -0
  87. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/types.mjs +9 -0
  88. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +5 -0
  89. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.mjs +668 -0
  90. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.test.mjs +134 -0
  91. package/{assets → dist/pstack}/skills/principle-attack-the-premise/SKILL.md +1 -3
  92. package/{assets → dist/pstack}/skills/principle-boundary-discipline/SKILL.md +1 -3
  93. package/{assets → dist/pstack}/skills/principle-build-the-lever/SKILL.md +0 -3
  94. package/dist/pstack/skills/principle-encode-lessons-in-structure/SKILL.md +11 -0
  95. package/dist/pstack/skills/principle-exhaust-the-design-space/SKILL.md +9 -0
  96. package/{assets → dist/pstack}/skills/principle-experience-first/SKILL.md +1 -3
  97. package/dist/{assets → pstack}/skills/principle-explain-the-number/SKILL.md +3 -4
  98. package/dist/{assets → pstack}/skills/principle-fix-root-causes/SKILL.md +1 -3
  99. package/{assets → dist/pstack}/skills/principle-foundational-thinking/SKILL.md +0 -2
  100. package/dist/{assets → pstack}/skills/principle-guard-the-context-window/SKILL.md +0 -2
  101. package/dist/{assets → pstack}/skills/principle-laziness-protocol/SKILL.md +1 -3
  102. package/dist/{assets → pstack}/skills/principle-make-operations-idempotent/SKILL.md +1 -3
  103. package/dist/{assets → pstack}/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +1 -3
  104. package/{assets → dist/pstack}/skills/principle-minimize-reader-load/SKILL.md +1 -3
  105. package/{assets → dist/pstack}/skills/principle-model-the-domain/SKILL.md +1 -3
  106. package/{assets → dist/pstack}/skills/principle-never-block-on-the-human/SKILL.md +1 -3
  107. package/dist/{assets → pstack}/skills/principle-outcome-oriented-execution/SKILL.md +1 -3
  108. package/{assets → dist/pstack}/skills/principle-prove-it-works/SKILL.md +3 -3
  109. package/dist/{assets → pstack}/skills/principle-redesign-from-first-principles/SKILL.md +1 -3
  110. package/{assets → dist/pstack}/skills/principle-separate-before-serializing-shared-state/SKILL.md +1 -3
  111. package/dist/{assets → pstack}/skills/principle-sequence-verifiable-units/SKILL.md +1 -3
  112. package/dist/{assets → pstack}/skills/principle-subtract-before-you-add/SKILL.md +1 -3
  113. package/{assets → dist/pstack}/skills/principle-test-behavior-not-implementation/SKILL.md +1 -3
  114. package/{assets → dist/pstack}/skills/principle-type-system-discipline/SKILL.md +1 -3
  115. package/dist/{assets → pstack}/skills/recall/SKILL.md +4 -4
  116. package/dist/pstack/skills/reflect/SKILL.md +71 -0
  117. package/{assets → dist/pstack}/skills/reflect/references/divergent-reviewer.md +1 -1
  118. package/{assets → dist/pstack}/skills/reflect/references/judgment-reviewer.md +1 -1
  119. package/{assets → dist/pstack}/skills/reflect/references/synthesizer.md +3 -3
  120. package/dist/{assets → pstack}/skills/reflect/references/tooling-reviewer.md +1 -1
  121. package/dist/pstack/skills/setup-pstack/SKILL.md +80 -0
  122. package/{assets → dist/pstack}/skills/sharpen/SKILL.md +1 -3
  123. package/{assets → dist/pstack}/skills/show-me-your-work/SKILL.md +3 -3
  124. package/dist/pstack/skills/show-me-your-work/scripts/log.mjs +106 -0
  125. package/dist/pstack/skills/show-me-your-work/scripts/log.test.mjs +56 -0
  126. package/dist/pstack/skills/statechart/SKILL.md +82 -0
  127. package/dist/pstack/skills/statechart/references/render.md +93 -0
  128. package/dist/pstack/skills/statechart/scripts/backends/cfg.mjs +31 -0
  129. package/dist/pstack/skills/statechart/scripts/backends/mermaid.mjs +186 -0
  130. package/dist/pstack/skills/statechart/scripts/backends/plain-text.mjs +62 -0
  131. package/dist/pstack/skills/statechart/scripts/backends/report.mjs +84 -0
  132. package/dist/pstack/skills/statechart/scripts/frontends/config.mjs +268 -0
  133. package/dist/pstack/skills/statechart/scripts/frontends/dot.mjs +67 -0
  134. package/dist/pstack/skills/statechart/scripts/frontends/marks.mjs +94 -0
  135. package/dist/pstack/skills/statechart/scripts/frontends/messages.mjs +48 -0
  136. package/dist/pstack/skills/statechart/scripts/frontends/spec.mjs +101 -0
  137. package/dist/pstack/skills/statechart/scripts/frontends/trace.mjs +39 -0
  138. package/dist/pstack/skills/statechart/scripts/frontends/value.mjs +180 -0
  139. package/dist/pstack/skills/statechart/scripts/frontends/verdict.mjs +40 -0
  140. package/dist/pstack/skills/statechart/scripts/frontends/view.mjs +99 -0
  141. package/dist/pstack/skills/statechart/scripts/ir.mjs +277 -0
  142. package/dist/pstack/skills/statechart/scripts/passes/annotate.mjs +92 -0
  143. package/dist/pstack/skills/statechart/scripts/passes/label.mjs +210 -0
  144. package/dist/pstack/skills/statechart/scripts/passes/lift.mjs +84 -0
  145. package/dist/pstack/skills/statechart/scripts/passes/loop-check.mjs +47 -0
  146. package/dist/pstack/skills/statechart/scripts/passes/paths.mjs +72 -0
  147. package/dist/pstack/skills/statechart/scripts/passes/reach.mjs +135 -0
  148. package/dist/pstack/skills/statechart/scripts/passes/region-check.mjs +82 -0
  149. package/dist/pstack/skills/statechart/scripts/passes/regions.mjs +268 -0
  150. package/dist/pstack/skills/statechart/scripts/pipeline.mjs +72 -0
  151. package/dist/pstack/skills/statechart/scripts/run.mjs +440 -0
  152. package/dist/pstack/skills/statechart/scripts/statechart.mjs +155 -0
  153. package/dist/pstack/skills/statechart/scripts/statechart.test.mjs +198 -0
  154. package/dist/pstack/skills/statechart/scripts/worker.mjs +31 -0
  155. package/dist/pstack/skills/swarm/SKILL.md +43 -0
  156. package/{assets → dist/pstack}/skills/tdd/SKILL.md +1 -3
  157. package/{assets → dist/pstack}/skills/teach/SKILL.md +3 -3
  158. package/{assets → dist/pstack}/skills/technical-writing/SKILL.md +2 -2
  159. package/{assets → dist/pstack}/skills/typescript-best-practices/SKILL.md +1 -2
  160. package/{assets → dist/pstack}/skills/unslop/SKILL.md +0 -2
  161. package/dist/{assets → pstack}/skills/why/SKILL.md +9 -9
  162. package/dist/script.d.mts +91 -0
  163. package/dist/script.mjs +485 -0
  164. package/dist/skill.d.mts +38 -0
  165. package/dist/skill.mjs +183 -0
  166. package/dist/skills/authored/decision-audit/SKILL.md +99 -0
  167. package/dist/skills/authored/decision-audit/SKILL.zh.md +99 -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 +131 -0
  171. package/dist/skills/authored/decision-write/SKILL.zh.md +131 -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/setup-project-docs/SKILL.md +58 -0
  175. package/dist/skills/authored/setup-project-docs/SKILL.zh.md +58 -0
  176. package/dist/skills/authored/setup-project-docs/references/decision-conventions.md +11 -0
  177. package/dist/skills/authored/setup-project-docs/references/decision-conventions.zh.md +11 -0
  178. package/dist/skills/vendored/retro/SKILL.md +44 -0
  179. package/dist/skills/vendored/retro/agents/openai.yaml +5 -0
  180. package/dist/skills/vendored/writing-for-agents/SKILL-MECHANICS.md +22 -0
  181. package/dist/skills/vendored/writing-for-agents/SKILL.md +81 -0
  182. package/dist/skills/vendored/writing-for-agents/agents/openai.yaml +3 -0
  183. package/dist/subagent.d.mts +175 -106
  184. package/dist/subagent.mjs +1012 -344
  185. package/locale/en.json +7 -0
  186. package/locale/zh.json +7 -0
  187. package/package.json +61 -50
  188. package/assets/agents/poteto-agent.md +0 -8
  189. package/assets/docs/guide/02-poteto-mode.md +0 -139
  190. package/assets/docs/guide/05-build-and-clean.md +0 -83
  191. package/assets/docs/guide/06-verify-and-ship.md +0 -152
  192. package/assets/docs/guide/09-make-it-yours.md +0 -100
  193. package/assets/docs/harness/dsh.md +0 -65
  194. package/assets/docs/pstack-models.example.md +0 -23
  195. package/assets/skills/arena/SKILL.md +0 -50
  196. package/assets/skills/benchmark-checklist/SKILL.md +0 -41
  197. package/assets/skills/blast-radius/SKILL.md +0 -52
  198. package/assets/skills/correct/SKILL.md +0 -34
  199. package/assets/skills/how/SKILL.md +0 -38
  200. package/assets/skills/in-your-own-words/SKILL.md +0 -9
  201. package/assets/skills/interrogate/SKILL.md +0 -69
  202. package/assets/skills/interrogate/references/code-quality-review.md +0 -47
  203. package/assets/skills/interrogate/references/lead-judgment.md +0 -39
  204. package/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  205. package/assets/skills/interrogate/references/rubric.md +0 -77
  206. package/assets/skills/maintain-verification-skill/SKILL.md +0 -41
  207. package/assets/skills/poteto-help/references/prompting.md +0 -51
  208. package/assets/skills/poteto-help/references/recipes.md +0 -51
  209. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  210. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -13
  211. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  212. package/assets/skills/poteto-mode/playbooks/eval.md +0 -25
  213. package/assets/skills/poteto-mode/playbooks/opening-a-pr.md +0 -34
  214. package/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  215. package/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  216. package/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  217. package/assets/skills/poteto-mode/playbooks/shipping.md +0 -12
  218. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -12
  219. package/assets/skills/poteto-mode/scripts/bootstrap.ts +0 -62
  220. package/assets/skills/poteto-mode/scripts/bun.lock +0 -67
  221. package/assets/skills/poteto-mode/scripts/check-plan.test.ts +0 -96
  222. package/assets/skills/poteto-mode/scripts/orch/orch.test.ts +0 -761
  223. package/assets/skills/poteto-mode/scripts/orch/orch.ts +0 -590
  224. package/assets/skills/poteto-mode/scripts/orch/store.ts +0 -1677
  225. package/assets/skills/poteto-mode/scripts/package.json +0 -16
  226. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.ts +0 -224
  227. package/assets/skills/poteto-mode/scripts/watch-pr/cli.ts +0 -223
  228. package/assets/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +0 -129
  229. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.ts +0 -436
  230. package/assets/skills/poteto-mode/scripts/watch-pr/github.ts +0 -718
  231. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.ts +0 -420
  232. package/assets/skills/poteto-mode/scripts/watch-pr/policy.ts +0 -836
  233. package/assets/skills/poteto-mode/scripts/watch-pr/render.ts +0 -169
  234. package/assets/skills/poteto-mode/scripts/watch-pr/tsconfig.json +0 -13
  235. package/assets/skills/poteto-mode/scripts/watch-pr/types.compile.ts +0 -93
  236. package/assets/skills/poteto-mode/scripts/watch-pr/types.ts +0 -413
  237. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr +0 -6
  238. package/assets/skills/poteto-mode/scripts/worktree-audit.sh +0 -127
  239. package/assets/skills/principle-encode-lessons-in-structure/SKILL.md +0 -13
  240. package/assets/skills/principle-exhaust-the-design-space/SKILL.md +0 -11
  241. package/assets/skills/principle-explain-the-number/SKILL.md +0 -19
  242. package/assets/skills/principle-fix-root-causes/SKILL.md +0 -23
  243. package/assets/skills/principle-guard-the-context-window/SKILL.md +0 -14
  244. package/assets/skills/principle-laziness-protocol/SKILL.md +0 -12
  245. package/assets/skills/principle-make-operations-idempotent/SKILL.md +0 -24
  246. package/assets/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +0 -16
  247. package/assets/skills/principle-outcome-oriented-execution/SKILL.md +0 -23
  248. package/assets/skills/principle-redesign-from-first-principles/SKILL.md +0 -18
  249. package/assets/skills/principle-sequence-verifiable-units/SKILL.md +0 -19
  250. package/assets/skills/principle-subtract-before-you-add/SKILL.md +0 -20
  251. package/assets/skills/recall/SKILL.md +0 -37
  252. package/assets/skills/reflect/SKILL.md +0 -70
  253. package/assets/skills/reflect/references/tooling-reviewer.md +0 -48
  254. package/assets/skills/setup-pstack/SKILL.md +0 -76
  255. package/assets/skills/show-me-your-work/scripts/log.sh +0 -42
  256. package/assets/skills/swarm/SKILL.md +0 -41
  257. package/assets/skills/why/SKILL.md +0 -100
  258. package/dist/README.md +0 -159
  259. package/dist/assets/agents/comment-sicko.md +0 -32
  260. package/dist/assets/agents/poteto-agent.md +0 -8
  261. package/dist/assets/docs/guide/01-setup.md +0 -64
  262. package/dist/assets/docs/guide/03-understand.md +0 -79
  263. package/dist/assets/docs/guide/04-design.md +0 -133
  264. package/dist/assets/docs/guide/07-overnight.md +0 -122
  265. package/dist/assets/docs/guide/08-principles.md +0 -72
  266. package/dist/assets/docs/guide/10-recipes-and-pitfalls.md +0 -180
  267. package/dist/assets/docs/guide/README.md +0 -38
  268. package/dist/assets/docs/harness/dsh.md +0 -65
  269. package/dist/assets/docs/pstack-models.example.md +0 -23
  270. package/dist/assets/skills/architect/SKILL.md +0 -81
  271. package/dist/assets/skills/architect/references/design-red-flags.md +0 -57
  272. package/dist/assets/skills/architect/references/rationale-template.md +0 -35
  273. package/dist/assets/skills/architect/references/runner-prompt.md +0 -20
  274. package/dist/assets/skills/arena/SKILL.md +0 -50
  275. package/dist/assets/skills/automate-me/SKILL.md +0 -105
  276. package/dist/assets/skills/bro/SKILL.md +0 -9
  277. package/dist/assets/skills/create-formal-verification-skill/SKILL.md +0 -43
  278. package/dist/assets/skills/create-verification-skill/SKILL.md +0 -46
  279. package/dist/assets/skills/create-verification-skill/references/feature-map-example/README.md +0 -47
  280. package/dist/assets/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -39
  281. package/dist/assets/skills/create-verification-skill/references/feature-map-example/search.md +0 -45
  282. package/dist/assets/skills/figure-it-out/SKILL.md +0 -54
  283. package/dist/assets/skills/how/references/explainer-prompt.md +0 -55
  284. package/dist/assets/skills/how/references/explorer-prompt.md +0 -35
  285. package/dist/assets/skills/in-your-own-words/SKILL.md +0 -9
  286. package/dist/assets/skills/interrogate/SKILL.md +0 -69
  287. package/dist/assets/skills/interrogate/references/code-quality-review.md +0 -47
  288. package/dist/assets/skills/interrogate/references/lead-judgment.md +0 -39
  289. package/dist/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  290. package/dist/assets/skills/interrogate/references/rubric.md +0 -77
  291. package/dist/assets/skills/ketchup/SKILL.md +0 -45
  292. package/dist/assets/skills/maintain-formal-verification-skill/SKILL.md +0 -60
  293. package/dist/assets/skills/no-comments/SKILL.md +0 -26
  294. package/dist/assets/skills/poteto-help/SKILL.md +0 -161
  295. package/dist/assets/skills/poteto-mode/SKILL.md +0 -153
  296. package/dist/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  297. package/dist/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  298. package/dist/assets/skills/poteto-mode/playbooks/babysit.md +0 -23
  299. package/dist/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  300. package/dist/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  301. package/dist/assets/skills/poteto-mode/playbooks/hillclimb.md +0 -21
  302. package/dist/assets/skills/poteto-mode/playbooks/investigation.md +0 -14
  303. package/dist/assets/skills/poteto-mode/playbooks/multi-phase-plan.md +0 -155
  304. package/dist/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  305. package/dist/assets/skills/poteto-mode/playbooks/pause-safely.md +0 -10
  306. package/dist/assets/skills/poteto-mode/playbooks/prototype.md +0 -14
  307. package/dist/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  308. package/dist/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  309. package/dist/assets/skills/poteto-mode/playbooks/trace-forensics.md +0 -14
  310. package/dist/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  311. package/dist/assets/skills/poteto-mode/references/bugbot-triage.md +0 -142
  312. package/dist/assets/skills/poteto-mode/scripts/bootstrap.ts +0 -62
  313. package/dist/assets/skills/poteto-mode/scripts/bun.lock +0 -67
  314. package/dist/assets/skills/poteto-mode/scripts/check-plan.mjs +0 -205
  315. package/dist/assets/skills/poteto-mode/scripts/orch/orch.test.ts +0 -761
  316. package/dist/assets/skills/poteto-mode/scripts/orch/orch.ts +0 -590
  317. package/dist/assets/skills/poteto-mode/scripts/orch/store.ts +0 -1677
  318. package/dist/assets/skills/poteto-mode/scripts/package.json +0 -16
  319. package/dist/assets/skills/poteto-mode/scripts/watch-pr/cli.test.ts +0 -224
  320. package/dist/assets/skills/poteto-mode/scripts/watch-pr/cli.ts +0 -223
  321. package/dist/assets/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +0 -129
  322. package/dist/assets/skills/poteto-mode/scripts/watch-pr/github.test.ts +0 -436
  323. package/dist/assets/skills/poteto-mode/scripts/watch-pr/github.ts +0 -718
  324. package/dist/assets/skills/poteto-mode/scripts/watch-pr/policy.test.ts +0 -420
  325. package/dist/assets/skills/poteto-mode/scripts/watch-pr/policy.ts +0 -836
  326. package/dist/assets/skills/poteto-mode/scripts/watch-pr/render.ts +0 -169
  327. package/dist/assets/skills/poteto-mode/scripts/watch-pr/tsconfig.json +0 -13
  328. package/dist/assets/skills/poteto-mode/scripts/watch-pr/types.compile.ts +0 -93
  329. package/dist/assets/skills/poteto-mode/scripts/watch-pr/types.ts +0 -413
  330. package/dist/assets/skills/poteto-mode/scripts/watch-pr/watch-pr +0 -6
  331. package/dist/assets/skills/poteto-mode/scripts/worktree-audit.sh +0 -127
  332. package/dist/assets/skills/principle-attack-the-premise/SKILL.md +0 -23
  333. package/dist/assets/skills/principle-boundary-discipline/SKILL.md +0 -36
  334. package/dist/assets/skills/principle-build-the-lever/SKILL.md +0 -26
  335. package/dist/assets/skills/principle-encode-lessons-in-structure/SKILL.md +0 -13
  336. package/dist/assets/skills/principle-exhaust-the-design-space/SKILL.md +0 -11
  337. package/dist/assets/skills/principle-experience-first/SKILL.md +0 -21
  338. package/dist/assets/skills/principle-foundational-thinking/SKILL.md +0 -23
  339. package/dist/assets/skills/principle-minimize-reader-load/SKILL.md +0 -20
  340. package/dist/assets/skills/principle-model-the-domain/SKILL.md +0 -26
  341. package/dist/assets/skills/principle-never-block-on-the-human/SKILL.md +0 -17
  342. package/dist/assets/skills/principle-prove-it-works/SKILL.md +0 -24
  343. package/dist/assets/skills/principle-separate-before-serializing-shared-state/SKILL.md +0 -18
  344. package/dist/assets/skills/principle-test-behavior-not-implementation/SKILL.md +0 -22
  345. package/dist/assets/skills/principle-type-system-discipline/SKILL.md +0 -15
  346. package/dist/assets/skills/reflect/SKILL.md +0 -70
  347. package/dist/assets/skills/reflect/references/divergent-reviewer.md +0 -38
  348. package/dist/assets/skills/reflect/references/judgment-reviewer.md +0 -37
  349. package/dist/assets/skills/reflect/references/synthesizer.md +0 -56
  350. package/dist/assets/skills/setup-pstack/SKILL.md +0 -76
  351. package/dist/assets/skills/sharpen/SKILL.md +0 -18
  352. package/dist/assets/skills/show-me-your-work/SKILL.md +0 -84
  353. package/dist/assets/skills/show-me-your-work/references/decision-log-template.tsv +0 -1
  354. package/dist/assets/skills/show-me-your-work/scripts/log.sh +0 -42
  355. package/dist/assets/skills/swarm/SKILL.md +0 -41
  356. package/dist/assets/skills/tdd/SKILL.md +0 -44
  357. package/dist/assets/skills/teach/SKILL.md +0 -23
  358. package/dist/assets/skills/technical-writing/SKILL.md +0 -108
  359. package/dist/assets/skills/typescript-best-practices/SKILL.md +0 -32
  360. package/dist/assets/skills/typescript-best-practices/references/patterns.md +0 -328
  361. package/dist/assets/skills/unslop/SKILL.md +0 -64
  362. package/dist/assets/skills/why/references/epistemics.md +0 -71
  363. package/dist/assets/skills/why/references/investigator-prompt.md +0 -84
  364. package/dist/assets/skills/why/references/source-playbook.md +0 -17
  365. package/dist/assets/skills/why/references/sources/code-archaeology.md +0 -51
  366. package/dist/assets/skills/why/references/sources/databricks.md +0 -70
  367. package/dist/assets/skills/why/references/sources/datadog.md +0 -97
  368. package/dist/assets/skills/why/references/sources/incident-postmortem.md +0 -5
  369. package/dist/assets/skills/why/references/sources/linear.md +0 -48
  370. package/dist/assets/skills/why/references/sources/notion.md +0 -55
  371. package/dist/assets/skills/why/references/sources/sentry.md +0 -66
  372. package/dist/assets/skills/why/references/sources/slack.md +0 -17
  373. package/dist/assets/skills/why/references/synthesizer-prompt.md +0 -129
  374. package/dist/cordis.patch.yml +0 -20
  375. package/dist/index.mjs.map +0 -1
  376. package/dist/paths-Bbai4CaT.mjs +0 -16
  377. package/dist/paths-Bbai4CaT.mjs.map +0 -1
  378. package/dist/subagent.mjs.map +0 -1
  379. /package/{assets → dist/pstack}/docs/guide/03-understand.md +0 -0
  380. /package/{assets → dist/pstack}/docs/guide/08-principles.md +0 -0
  381. /package/{assets → dist/pstack}/docs/guide/README.md +0 -0
  382. /package/{assets → dist/pstack}/skills/architect/references/design-red-flags.md +0 -0
  383. /package/{assets → dist/pstack}/skills/architect/references/rationale-template.md +0 -0
  384. /package/{assets → dist/pstack}/skills/architect/references/runner-prompt.md +0 -0
  385. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/README.md +0 -0
  386. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -0
  387. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/search.md +0 -0
  388. /package/{assets → dist/pstack}/skills/how/references/explorer-prompt.md +0 -0
  389. /package/{assets → dist/pstack}/skills/poteto-mode/playbooks/investigation.md +0 -0
  390. /package/{assets → dist/pstack}/skills/poteto-mode/playbooks/pause-safely.md +0 -0
  391. /package/{assets → dist/pstack}/skills/poteto-mode/playbooks/trace-forensics.md +0 -0
  392. /package/{assets → dist/pstack}/skills/poteto-mode/references/bugbot-triage.md +0 -0
  393. /package/{assets → dist/pstack}/skills/show-me-your-work/references/decision-log-template.tsv +0 -0
  394. /package/{assets → dist/pstack}/skills/typescript-best-practices/references/patterns.md +0 -0
  395. /package/{assets → dist/pstack}/skills/why/references/epistemics.md +0 -0
  396. /package/{assets → dist/pstack}/skills/why/references/investigator-prompt.md +0 -0
  397. /package/{assets → dist/pstack}/skills/why/references/source-playbook.md +0 -0
  398. /package/{assets → dist/pstack}/skills/why/references/sources/code-archaeology.md +0 -0
  399. /package/{assets → dist/pstack}/skills/why/references/sources/databricks.md +0 -0
  400. /package/{assets → dist/pstack}/skills/why/references/sources/datadog.md +0 -0
  401. /package/{assets → dist/pstack}/skills/why/references/sources/incident-postmortem.md +0 -0
  402. /package/{assets → dist/pstack}/skills/why/references/sources/linear.md +0 -0
  403. /package/{assets → dist/pstack}/skills/why/references/sources/notion.md +0 -0
  404. /package/{assets → dist/pstack}/skills/why/references/sources/sentry.md +0 -0
  405. /package/{assets → dist/pstack}/skills/why/references/sources/slack.md +0 -0
  406. /package/{assets → dist/pstack}/skills/why/references/synthesizer-prompt.md +0 -0
@@ -1,836 +0,0 @@
1
- import {
2
- WatcherQueryError,
3
- resolveChecks,
4
- resolveReviewThreads,
5
- } from "./github.ts";
6
- import type * as T from "./types.ts";
7
- import { nonEmpty } from "./types.ts";
8
- export function assessGitHubMerge(args: {
9
- readonly mergeStateStatus: T.MergeStateStatus;
10
- readonly headRollupState: T.RollupState;
11
- }): T.GitHubMergeAssessment {
12
- if (args.mergeStateStatus === "BLOCKED") {
13
- if (args.headRollupState === "ERROR" || args.headRollupState === "FAILURE")
14
- return {
15
- kind: "refused",
16
- mergeStateStatus: args.mergeStateStatus,
17
- headRollupState: args.headRollupState,
18
- };
19
- return {
20
- kind: "allowed",
21
- basis: "rollup",
22
- mergeStateStatus: args.mergeStateStatus,
23
- headRollupState: args.headRollupState,
24
- };
25
- }
26
- return {
27
- kind: "allowed",
28
- basis: "merge-state",
29
- mergeStateStatus: args.mergeStateStatus,
30
- headRollupState: args.headRollupState,
31
- };
32
- }
33
- async function mergeAssessment(
34
- reader: T.GitHubReader,
35
- facts: T.PullRequestFacts
36
- ) {
37
- const commits = await reader.commitRollups(facts.context);
38
- const headRollupState =
39
- facts.headRefOid === null
40
- ? null
41
- : (commits.find((commit) => commit.oid === facts.headRefOid)?.state ??
42
- null);
43
- return {
44
- hadPreviousPassingCi: commits.some(
45
- (commit) => commit.oid !== facts.headRefOid && commit.state === "SUCCESS"
46
- ),
47
- github: assessGitHubMerge({
48
- mergeStateStatus: facts.mergeStateStatus,
49
- headRollupState,
50
- }),
51
- };
52
- }
53
- const AUTOMATION_TOKENS = [
54
- "bugbot",
55
- "security review",
56
- "pr review automation",
57
- "review automation",
58
- ] as const;
59
- export async function readSnapshot(args: {
60
- readonly reader: T.GitHubReader;
61
- readonly context: T.PrContext;
62
- readonly pendingHistory: "include" | "omit";
63
- readonly allowDraft: boolean;
64
- }): Promise<T.PrSnapshot> {
65
- const facts = await args.reader.pullRequest(args.context);
66
- if (facts.state === "MERGED" || facts.mergedAt !== null)
67
- return { kind: "merged", context: args.context, facts };
68
- if (facts.state === "CLOSED")
69
- return { kind: "closed", context: args.context, facts };
70
- const threads = await resolveReviewThreads(args.reader, args.context);
71
- const checks = await resolveChecks(args.reader, args.context);
72
- const failed = nonEmpty(
73
- checks.checks.filter(
74
- (check): check is T.FailedCheck => check.kind === "failed"
75
- )
76
- );
77
- const pending = nonEmpty(
78
- checks.checks.filter(
79
- (check): check is T.PendingCheck => check.kind === "pending"
80
- )
81
- );
82
- let ci: T.CiState;
83
- if (failed === null && pending !== null && args.pendingHistory === "omit")
84
- ci = {
85
- kind: "ci-pending",
86
- source: checks.source,
87
- all: checks.checks,
88
- failed: [],
89
- pending,
90
- hadPreviousPassingCi: false,
91
- };
92
- else {
93
- const merge = await mergeAssessment(args.reader, facts);
94
- const base = {
95
- source: checks.source,
96
- all: checks.checks,
97
- hadPreviousPassingCi: merge.hadPreviousPassingCi,
98
- };
99
- if (failed !== null)
100
- ci = {
101
- ...base,
102
- kind: "ci-failing",
103
- failed,
104
- pending: pending ?? [],
105
- github: merge.github,
106
- };
107
- else if (merge.github.kind === "refused")
108
- ci = {
109
- ...base,
110
- kind: "ci-github-rejected",
111
- failed: [],
112
- pending: pending ?? [],
113
- github: merge.github,
114
- };
115
- else if (pending !== null)
116
- ci = { ...base, kind: "ci-pending", failed: [], pending };
117
- else
118
- ci = {
119
- ...base,
120
- kind: "ci-clean",
121
- failed: [],
122
- pending: [],
123
- github: merge.github,
124
- };
125
- }
126
- return {
127
- kind: "open",
128
- context: args.context,
129
- facts,
130
- threads,
131
- ci,
132
- reviewAutomationRunning: checks.checks.some(
133
- (check) =>
134
- check.kind === "pending" &&
135
- AUTOMATION_TOKENS.some((token) =>
136
- check.name.toLowerCase().includes(token)
137
- )
138
- ),
139
- };
140
- }
141
- const conflictBlocker = (row: T.PrSnapshot): T.MergeBlocker | null =>
142
- row.kind === "open" &&
143
- (row.facts.mergeable === "CONFLICTING" ||
144
- row.facts.mergeStateStatus === "DIRTY" ||
145
- row.facts.mergeStateStatus === "CONFLICTING")
146
- ? { kind: "merge-conflicts", pr: row.context, facts: row.facts }
147
- : null;
148
- function threadBlocker(row: T.PrSnapshot): T.MergeBlocker | null {
149
- if (row.kind !== "open") return null;
150
- const threads = nonEmpty(row.threads);
151
- return threads === null
152
- ? null
153
- : { kind: "review-threads", pr: row.context, threads };
154
- }
155
- const ciBlocker = (row: T.PrSnapshot): T.MergeBlocker | null =>
156
- row.kind === "open" &&
157
- (row.ci.kind === "ci-failing" || row.ci.kind === "ci-github-rejected")
158
- ? { kind: "failing-checks", pr: row.context, ci: row.ci }
159
- : null;
160
- function gateReason(
161
- row: T.PrSnapshot,
162
- allowDraft: boolean
163
- ): T.MergeGateReason | null {
164
- if (row.kind === "merged") return null;
165
- if (row.kind === "closed") return "closed-without-merge";
166
- if (row.facts.isDraft && !allowDraft) return "draft-pr";
167
- return row.facts.reviewDecision === "CHANGES_REQUESTED"
168
- ? "changes-requested"
169
- : null;
170
- }
171
- function gateBlocker(
172
- row: T.PrSnapshot,
173
- allowDraft: boolean
174
- ): T.MergeBlocker | null {
175
- const reason = gateReason(row, allowDraft);
176
- return reason === null ||
177
- (reason === "draft-pr" &&
178
- row.kind === "open" &&
179
- row.ci.kind === "ci-pending")
180
- ? null
181
- : { kind: "merge-gate", pr: row.context, reason };
182
- }
183
- function readyContribution(
184
- row: T.PrSnapshot,
185
- allowDraft: boolean
186
- ): T.ReadyPr | T.MergedPr | null {
187
- if (row.kind === "merged")
188
- return {
189
- kind: "merged-pr",
190
- context: row.context,
191
- mergedAt: row.facts.mergedAt,
192
- };
193
- if (
194
- row.kind !== "open" ||
195
- row.ci.kind !== "ci-clean" ||
196
- row.threads.length !== 0 ||
197
- conflictBlocker(row) !== null ||
198
- gateReason(row, allowDraft) !== null
199
- )
200
- return null;
201
- const reviewDecision = row.facts.reviewDecision;
202
- if (reviewDecision === "CHANGES_REQUESTED") return null;
203
- return {
204
- kind: "ready-pr",
205
- context: row.context,
206
- proof: {
207
- mergeability: "clear",
208
- threads: [],
209
- ci: row.ci,
210
- gate: {
211
- state: "OPEN",
212
- reviewDecision,
213
- draft: row.facts.isDraft ? "draft-allowed" : "not-draft",
214
- },
215
- },
216
- };
217
- }
218
- export function classifyPr(
219
- row: T.PrSnapshot,
220
- allowDraft = false
221
- ): T.PrDecision {
222
- for (const blocker of [
223
- conflictBlocker(row),
224
- threadBlocker(row),
225
- ciBlocker(row),
226
- gateBlocker(row, allowDraft),
227
- ])
228
- if (blocker !== null) return { kind: "blocker", blocker };
229
- if (row.kind === "open" && row.ci.kind === "ci-pending")
230
- return { kind: "waiting", frontier: row.context, pending: row.ci.pending };
231
- const ready = readyContribution(row, allowDraft);
232
- if (ready === null) throw new Error("snapshot has no classified decision");
233
- return ready.kind === "merged-pr"
234
- ? { kind: "merged", pr: ready }
235
- : { kind: "ready", pr: ready };
236
- }
237
- export function selectTierMajorStackDecision(
238
- rows: T.NonEmpty<T.PrSnapshot>,
239
- allowDraft = false
240
- ): T.StackDecision {
241
- for (const tier of [conflictBlocker, threadBlocker, ciBlocker])
242
- for (const row of rows) {
243
- const blocker = tier(row);
244
- if (blocker !== null) return { kind: "blocker", blocker };
245
- }
246
- for (const row of rows) {
247
- const blocker = gateBlocker(row, allowDraft);
248
- if (blocker !== null) return { kind: "blocker", blocker };
249
- }
250
- for (const row of rows)
251
- if (row.kind === "open" && row.ci.kind === "ci-pending")
252
- return {
253
- kind: "waiting",
254
- frontier: row.context,
255
- pending: row.ci.pending,
256
- };
257
- const prs = nonEmpty(
258
- rows
259
- .map((row) => readyContribution(row, allowDraft))
260
- .filter((row): row is T.ReadyPr | T.MergedPr => row !== null)
261
- );
262
- if (prs === null || prs.length !== rows.length)
263
- throw new Error("stack has no classified decision");
264
- return { kind: "clear", prs };
265
- }
266
- export const queryBackoffSeconds = (
267
- interval: number,
268
- failures: number
269
- ): number => Math.min(Math.max(interval, 60) * 2 ** (failures - 1), 300);
270
- interface Envelope<M extends T.WatchMode> {
271
- readonly schemaVersion: 1;
272
- readonly sequence: number;
273
- readonly observedAt: string;
274
- readonly mode: M;
275
- }
276
- type Payload<V> = V extends unknown
277
- ? Omit<V, keyof Envelope<T.WatchMode>>
278
- : never;
279
- type VerdictPayload = Payload<T.WatcherVerdict>;
280
- export interface VerdictStamp<M extends T.WatchMode = T.WatchMode> {
281
- <const P extends VerdictPayload>(payload: P): Envelope<M> & P;
282
- <const P extends VerdictPayload, M2 extends T.WatchMode>(
283
- payload: P,
284
- mode: M2
285
- ): Envelope<M2> & P;
286
- }
287
- export function verdictFactory<M extends T.WatchMode>(
288
- clock: WatchClock,
289
- mode: M
290
- ): VerdictStamp<M> {
291
- let sequence = 0;
292
- function stamp<const P extends VerdictPayload>(payload: P): Envelope<M> & P;
293
- function stamp<const P extends VerdictPayload, M2 extends T.WatchMode>(
294
- payload: P,
295
- mode: M2
296
- ): Envelope<M2> & P;
297
- function stamp<const P extends VerdictPayload>(
298
- payload: P,
299
- override?: T.WatchMode
300
- ): Envelope<T.WatchMode> & P {
301
- return {
302
- schemaVersion: 1,
303
- sequence: (sequence += 1),
304
- observedAt: clock.observedAt(),
305
- mode: override ?? mode,
306
- ...payload,
307
- };
308
- }
309
- return stamp;
310
- }
311
- function blockerVerdict(
312
- stamp: VerdictStamp,
313
- blocker: T.MergeBlocker
314
- ): T.BlockerVerdict {
315
- switch (blocker.kind) {
316
- case "merge-conflicts":
317
- return stamp({ kind: "BLOCKER", terminal: true, exitCode: 2, blocker });
318
- case "review-threads":
319
- return stamp({ kind: "BLOCKER", terminal: true, exitCode: 3, blocker });
320
- case "failing-checks":
321
- return stamp({ kind: "BLOCKER", terminal: true, exitCode: 4, blocker });
322
- case "merge-gate":
323
- return stamp({ kind: "BLOCKER", terminal: true, exitCode: 6, blocker });
324
- default: {
325
- const exhaustive: never = blocker;
326
- return exhaustive;
327
- }
328
- }
329
- }
330
- export function statusQueryVerdict(
331
- stamp: VerdictStamp,
332
- failures: number,
333
- failure: T.QueryFailure
334
- ): T.BlockerVerdict {
335
- return stamp({
336
- kind: "BLOCKER",
337
- terminal: true,
338
- exitCode: 7,
339
- blocker: { kind: "status-query", failures, failure },
340
- });
341
- }
342
- export interface WatchClock {
343
- now(): number;
344
- observedAt(): string;
345
- sleep(seconds: number): Promise<void>;
346
- }
347
- export interface RunDependencies {
348
- readonly reader: T.GitHubReader;
349
- readonly clock: WatchClock;
350
- readonly emit: (verdict: T.ProgressVerdict) => void;
351
- }
352
- const deadlinePassed = (
353
- started: number,
354
- options: T.PollingOptions,
355
- now: number
356
- ): boolean => options.timeout > 0 && now - started >= options.timeout;
357
- type StepResult<V> =
358
- | { readonly kind: "terminal"; readonly verdict: V }
359
- | {
360
- readonly kind: "sleep";
361
- readonly seconds: number;
362
- readonly onDeadline?: () => V;
363
- }
364
- | { readonly kind: "continue" };
365
- async function pollUntilTerminal<V>(args: {
366
- readonly dependencies: RunDependencies;
367
- readonly options: T.PollingOptions;
368
- readonly stamp: VerdictStamp;
369
- readonly step: () => Promise<StepResult<V>>;
370
- }): Promise<V | T.BlockerVerdict | T.TimeoutVerdict> {
371
- let failures = 0;
372
- const started = args.dependencies.clock.now();
373
- while (true) {
374
- let result: StepResult<V>;
375
- try {
376
- result = await args.step();
377
- failures = 0;
378
- } catch (error) {
379
- if (!(error instanceof WatcherQueryError)) throw error;
380
- failures += 1;
381
- if (!error.failure.retryable || failures >= args.options.maxQueryErrors)
382
- return statusQueryVerdict(args.stamp, failures, error.failure);
383
- const retryInSeconds = queryBackoffSeconds(
384
- args.options.interval,
385
- failures
386
- );
387
- args.dependencies.emit(
388
- args.stamp({
389
- kind: "RETRY",
390
- terminal: false,
391
- failure: error.failure,
392
- consecutiveFailures: failures,
393
- retryInSeconds,
394
- })
395
- );
396
- if (deadlinePassed(started, args.options, args.dependencies.clock.now()))
397
- return args.stamp({
398
- kind: "TIMEOUT",
399
- terminal: true,
400
- exitCode: 5,
401
- reason: { kind: "status-unavailable", failure: error.failure },
402
- });
403
- await args.dependencies.clock.sleep(retryInSeconds);
404
- continue;
405
- }
406
- if (result.kind === "terminal") return result.verdict;
407
- if (result.kind === "sleep") {
408
- if (
409
- result.onDeadline !== undefined &&
410
- deadlinePassed(started, args.options, args.dependencies.clock.now())
411
- )
412
- return result.onDeadline();
413
- await args.dependencies.clock.sleep(result.seconds);
414
- }
415
- }
416
- }
417
- export async function runSimple(args: {
418
- readonly dependencies: RunDependencies;
419
- readonly contexts: T.NonEmpty<T.PrContext>;
420
- readonly mode: T.WatchMode;
421
- readonly statusOnly: boolean;
422
- readonly options: T.PollingOptions;
423
- }): Promise<T.TerminalVerdict> {
424
- const stamp = verdictFactory(args.dependencies.clock, args.mode);
425
- const step = async (): Promise<StepResult<T.TerminalVerdict>> => {
426
- const rows: T.PrSnapshot[] = [];
427
- for (const context of args.contexts)
428
- rows.push(
429
- await readSnapshot({
430
- reader: args.dependencies.reader,
431
- context,
432
- pendingHistory: "include",
433
- allowDraft: args.options.allowDraft,
434
- })
435
- );
436
- const complete = nonEmpty(rows);
437
- if (complete === null) throw new Error("watch context cannot be empty");
438
- if (args.statusOnly)
439
- return {
440
- kind: "terminal",
441
- verdict: stamp({
442
- kind: "STATUS",
443
- terminal: true,
444
- exitCode: 0,
445
- reason: "status-only",
446
- rows: complete,
447
- }),
448
- };
449
- if (args.mode === "queued-stack")
450
- throw new Error("queued-stack requires status-only in the simple runner");
451
- if (args.mode === "stack")
452
- args.dependencies.emit(
453
- stamp(
454
- { kind: "STATUS", terminal: false, reason: "poll", rows: complete },
455
- args.mode
456
- )
457
- );
458
- const decision =
459
- args.mode === "single"
460
- ? classifyPr(complete[0], args.options.allowDraft)
461
- : selectTierMajorStackDecision(complete, args.options.allowDraft);
462
- if (decision.kind === "blocker")
463
- return {
464
- kind: "terminal",
465
- verdict: blockerVerdict(stamp, decision.blocker),
466
- };
467
- if (decision.kind === "ready" || decision.kind === "merged")
468
- return {
469
- kind: "terminal",
470
- verdict: stamp(
471
- {
472
- kind: "READY",
473
- terminal: true,
474
- exitCode: 0,
475
- scope: { kind: "single", pr: decision.pr },
476
- },
477
- args.mode
478
- ),
479
- };
480
- if (decision.kind === "clear")
481
- return {
482
- kind: "terminal",
483
- verdict: stamp(
484
- {
485
- kind: "READY",
486
- terminal: true,
487
- exitCode: 0,
488
- scope: { kind: "stack", prs: decision.prs },
489
- },
490
- args.mode
491
- ),
492
- };
493
- args.dependencies.emit(
494
- stamp({
495
- kind: "WAITING",
496
- terminal: false,
497
- frontier: decision.frontier,
498
- reason: { kind: "pending-checks", pending: decision.pending },
499
- })
500
- );
501
- return {
502
- kind: "sleep",
503
- seconds: args.options.interval,
504
- onDeadline: () =>
505
- stamp({
506
- kind: "TIMEOUT",
507
- terminal: true,
508
- exitCode: 5,
509
- reason: { kind: "pending-checks", pending: decision.pending },
510
- }),
511
- };
512
- };
513
- return pollUntilTerminal({
514
- dependencies: args.dependencies,
515
- options: args.options,
516
- stamp,
517
- step,
518
- });
519
- }
520
- export type QueueWork =
521
- | {
522
- readonly kind: "whole-stack-sweep";
523
- readonly remaining: T.NonEmpty<T.PrContext>;
524
- }
525
- | { readonly kind: "frontier-poll"; readonly frontier: T.PrContext };
526
- export interface QueueState {
527
- readonly queue: T.NonEmpty<T.PrContext>;
528
- readonly snapshots: ReadonlyMap<T.PrNumber, T.PrSnapshot>;
529
- readonly work: QueueWork | null;
530
- readonly nextSweepAt: number;
531
- readonly frontier: T.PrContext | null;
532
- readonly lastWaitKey: string | null;
533
- readonly startedAt: number;
534
- }
535
- export const createQueueState = (
536
- queue: T.NonEmpty<T.PrContext>,
537
- now: number
538
- ): QueueState => ({
539
- queue,
540
- snapshots: new Map(),
541
- work: { kind: "whole-stack-sweep", remaining: queue },
542
- nextSweepAt: now,
543
- frontier: null,
544
- lastWaitKey: null,
545
- startedAt: now,
546
- });
547
- const orderedRows = (state: QueueState): T.PrSnapshot[] =>
548
- state.queue.flatMap((context) => {
549
- const row = state.snapshots.get(context.number);
550
- return row === undefined ? [] : [row];
551
- });
552
- const activeRows = (state: QueueState): T.PrSnapshot[] =>
553
- orderedRows(state).filter((row) => row.kind !== "merged");
554
- export function planQueue(state: QueueState, now: number): QueueState {
555
- if (state.work !== null) return state;
556
- if (state.snapshots.size === 0 || now >= state.nextSweepAt) {
557
- const remaining = nonEmpty(
558
- state.queue.filter(
559
- (context) => state.snapshots.get(context.number)?.kind !== "merged"
560
- )
561
- );
562
- if (remaining !== null)
563
- return { ...state, work: { kind: "whole-stack-sweep", remaining } };
564
- }
565
- const frontier = activeRows(state)[0]?.context;
566
- return frontier === undefined
567
- ? state
568
- : { ...state, work: { kind: "frontier-poll", frontier } };
569
- }
570
- export interface QueueSnapshotResult {
571
- readonly state: QueueState;
572
- readonly completedSweepRows: T.NonEmpty<T.PrSnapshot> | null;
573
- }
574
- export function applyQueueSnapshot(
575
- state: QueueState,
576
- snapshot: T.PrSnapshot,
577
- now: number,
578
- options: T.PollingOptions
579
- ): QueueSnapshotResult {
580
- if (state.work === null) throw new Error("queue has no read in flight");
581
- const snapshots = new Map(state.snapshots);
582
- snapshots.set(snapshot.context.number, snapshot);
583
- const base = { ...state, snapshots };
584
- if (state.work.kind === "frontier-poll")
585
- return { state: { ...base, work: null }, completedSweepRows: null };
586
- const [head, ...tail] = state.work.remaining;
587
- if (head.number !== snapshot.context.number)
588
- throw new Error("snapshot does not match sweep head");
589
- const remaining = nonEmpty(tail);
590
- if (remaining !== null)
591
- return {
592
- state: { ...base, work: { kind: "whole-stack-sweep", remaining } },
593
- completedSweepRows: null,
594
- };
595
- const rows = nonEmpty(
596
- state.queue.flatMap((context) => {
597
- const row = snapshots.get(context.number);
598
- return row === undefined ? [] : [row];
599
- })
600
- );
601
- if (rows === null || rows.length !== state.queue.length)
602
- throw new Error("sweep completed without every snapshot");
603
- return {
604
- state: { ...base, work: null, nextSweepAt: now + options.sweepInterval },
605
- completedSweepRows: rows,
606
- };
607
- }
608
- export type QueueEvaluation =
609
- | {
610
- readonly kind: "complete";
611
- readonly state: QueueState;
612
- readonly merged: T.NonEmpty<T.MergedPr>;
613
- }
614
- | {
615
- readonly kind: "blocker";
616
- readonly state: QueueState;
617
- readonly blocker: T.MergeBlocker;
618
- }
619
- | {
620
- readonly kind: "advance";
621
- readonly state: QueueState;
622
- readonly merged: T.PrContext;
623
- readonly frontier: T.PrContext;
624
- readonly remaining: number;
625
- }
626
- | {
627
- readonly kind: "timeout";
628
- readonly state: QueueState;
629
- readonly frontier: T.PrContext;
630
- readonly unmergedCount: number;
631
- }
632
- | {
633
- readonly kind: "waiting";
634
- readonly state: QueueState;
635
- readonly frontier: T.PrContext;
636
- readonly reason:
637
- | {
638
- readonly kind: "pending-checks";
639
- readonly pending: T.NonEmpty<T.PendingCheck>;
640
- }
641
- | { readonly kind: "merge-queue"; readonly unmergedCount: number };
642
- readonly emit: boolean;
643
- };
644
- export function evaluateQueue(
645
- state: QueueState,
646
- now: number,
647
- options: T.PollingOptions
648
- ): QueueEvaluation {
649
- const active = activeRows(state);
650
- if (active.length === 0) {
651
- const merged = nonEmpty(
652
- orderedRows(state).flatMap((row) =>
653
- row.kind === "merged"
654
- ? [
655
- {
656
- kind: "merged-pr" as const,
657
- context: row.context,
658
- mergedAt: row.facts.mergedAt,
659
- },
660
- ]
661
- : []
662
- )
663
- );
664
- if (merged === null) throw new Error("empty queue cannot complete");
665
- return { kind: "complete", state, merged };
666
- }
667
- const rows = nonEmpty(active);
668
- if (rows === null) throw new Error("active queue cannot be empty");
669
- const decision = selectTierMajorStackDecision(rows, options.allowDraft);
670
- if (decision.kind === "blocker")
671
- return { kind: "blocker", state, blocker: decision.blocker };
672
- const frontier = rows[0].context;
673
- if (state.frontier !== null && state.frontier.number !== frontier.number)
674
- return {
675
- kind: "advance",
676
- state: { ...state, frontier, lastWaitKey: null },
677
- merged: state.frontier,
678
- frontier,
679
- remaining: active.length,
680
- };
681
- if (deadlinePassed(state.startedAt, options, now))
682
- return {
683
- kind: "timeout",
684
- state: { ...state, frontier },
685
- frontier,
686
- unmergedCount: active.length,
687
- };
688
- const row = rows[0];
689
- const pending =
690
- row.kind === "open" && row.ci.kind === "ci-pending" ? row.ci.pending : null;
691
- const reason =
692
- pending === null
693
- ? ({ kind: "merge-queue", unmergedCount: active.length } as const)
694
- : ({ kind: "pending-checks", pending } as const);
695
- const key =
696
- reason.kind === "pending-checks"
697
- ? `pending:${frontier.number}:${reason.pending.length}`
698
- : `queue:${frontier.number}:${reason.unmergedCount}`;
699
- return {
700
- kind: "waiting",
701
- state: { ...state, frontier, lastWaitKey: key },
702
- frontier,
703
- reason,
704
- emit: state.lastWaitKey !== key,
705
- };
706
- }
707
- export async function runQueued(args: {
708
- readonly dependencies: RunDependencies;
709
- readonly contexts: T.NonEmpty<T.PrContext>;
710
- readonly options: T.PollingOptions;
711
- }): Promise<T.QueueTerminalVerdict> {
712
- let state = createQueueState(args.contexts, args.dependencies.clock.now());
713
- const stamp = verdictFactory(args.dependencies.clock, "queued-stack");
714
- args.dependencies.emit(
715
- stamp({ kind: "QUEUE", terminal: false, queue: args.contexts })
716
- );
717
- const step = async (): Promise<StepResult<T.QueueTerminalVerdict>> => {
718
- state = planQueue(state, args.dependencies.clock.now());
719
- if (state.work === null) {
720
- const complete = evaluateQueue(
721
- state,
722
- args.dependencies.clock.now(),
723
- args.options
724
- );
725
- if (complete.kind !== "complete")
726
- throw new Error("queue has no work while active");
727
- return {
728
- kind: "terminal",
729
- verdict: stamp({
730
- kind: "COMPLETE",
731
- terminal: true,
732
- exitCode: 0,
733
- queue: state.queue,
734
- merged: complete.merged,
735
- }),
736
- };
737
- }
738
- const context =
739
- state.work.kind === "whole-stack-sweep"
740
- ? state.work.remaining[0]
741
- : state.work.frontier;
742
- const snapshot = await readSnapshot({
743
- reader: args.dependencies.reader,
744
- context,
745
- pendingHistory: "omit",
746
- allowDraft: args.options.allowDraft,
747
- });
748
- const applied = applyQueueSnapshot(
749
- state,
750
- snapshot,
751
- args.dependencies.clock.now(),
752
- args.options
753
- );
754
- state = applied.state;
755
- if (applied.completedSweepRows !== null)
756
- args.dependencies.emit(
757
- stamp({
758
- kind: "STATUS",
759
- terminal: false,
760
- reason: "whole-stack-sweep",
761
- rows: applied.completedSweepRows,
762
- })
763
- );
764
- if (state.work !== null) return { kind: "continue" };
765
- const evaluation = evaluateQueue(
766
- state,
767
- args.dependencies.clock.now(),
768
- args.options
769
- );
770
- state = evaluation.state;
771
- switch (evaluation.kind) {
772
- case "complete":
773
- return {
774
- kind: "terminal",
775
- verdict: stamp({
776
- kind: "COMPLETE",
777
- terminal: true,
778
- exitCode: 0,
779
- queue: state.queue,
780
- merged: evaluation.merged,
781
- }),
782
- };
783
- case "blocker":
784
- return {
785
- kind: "terminal",
786
- verdict: blockerVerdict(stamp, evaluation.blocker),
787
- };
788
- case "advance":
789
- args.dependencies.emit(
790
- stamp({
791
- kind: "ADVANCE",
792
- terminal: false,
793
- merged: evaluation.merged,
794
- frontier: evaluation.frontier,
795
- remaining: evaluation.remaining,
796
- })
797
- );
798
- return { kind: "continue" };
799
- case "timeout":
800
- return {
801
- kind: "terminal",
802
- verdict: stamp({
803
- kind: "TIMEOUT",
804
- terminal: true,
805
- exitCode: 5,
806
- reason: {
807
- kind: "queued-stack",
808
- frontier: evaluation.frontier,
809
- unmergedCount: evaluation.unmergedCount,
810
- },
811
- }),
812
- };
813
- case "waiting":
814
- if (evaluation.emit)
815
- args.dependencies.emit(
816
- stamp({
817
- kind: "WAITING",
818
- terminal: false,
819
- frontier: evaluation.frontier,
820
- reason: evaluation.reason,
821
- })
822
- );
823
- return { kind: "sleep", seconds: args.options.interval };
824
- default: {
825
- const exhaustive: never = evaluation;
826
- return exhaustive;
827
- }
828
- }
829
- };
830
- return pollUntilTerminal({
831
- dependencies: args.dependencies,
832
- options: args.options,
833
- stamp,
834
- step,
835
- });
836
- }