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
@@ -0,0 +1,523 @@
1
+ import { expect } from "../expect.mjs";
2
+ import "../support.mjs";
3
+ import { parsePrNumber } from "./types.mjs";
4
+ import { WatcherQueryError } from "./github.mjs";
5
+ import { applyQueueSnapshot, assessGitHubMerge, classifyPr, createQueueState, evaluateQueue, planQueue, queryBackoffSeconds, readSnapshot, runQueued, runSimple, selectTierMajorStackDecision } from "./policy.mjs";
6
+ import { failedCheck, fakeReader, passingCheck, pendingCheck } from "./fakes.test-helper.mjs";
7
+ import { describe, it } from "node:test";
8
+ // runtime/skills/poteto-mode/scripts/watch-pr/policy.test.ts
9
+ const context = (number) => ({
10
+ owner: "owner",
11
+ repo: "repo",
12
+ number: parsePrNumber(number)
13
+ });
14
+ const options = {
15
+ interval: 10,
16
+ sweepInterval: 300,
17
+ timeout: 0,
18
+ maxQueryErrors: 5,
19
+ allowDraft: false
20
+ };
21
+ describe("readiness truth table", () => {
22
+ it("covers every specified row and every UNKNOWN rollup value", () => {
23
+ for (const [mergeStateStatus, headRollupState, expected] of [
24
+ [
25
+ "BLOCKED",
26
+ "FAILURE",
27
+ "refused"
28
+ ],
29
+ [
30
+ "BLOCKED",
31
+ "ERROR",
32
+ "refused"
33
+ ],
34
+ [
35
+ "BLOCKED",
36
+ "PENDING",
37
+ "allowed"
38
+ ],
39
+ [
40
+ "UNSTABLE",
41
+ "FAILURE",
42
+ "allowed"
43
+ ],
44
+ [
45
+ "UNKNOWN",
46
+ "ERROR",
47
+ "allowed"
48
+ ],
49
+ [
50
+ "UNKNOWN",
51
+ "EXPECTED",
52
+ "allowed"
53
+ ],
54
+ [
55
+ "UNKNOWN",
56
+ "FAILURE",
57
+ "allowed"
58
+ ],
59
+ [
60
+ "UNKNOWN",
61
+ "PENDING",
62
+ "allowed"
63
+ ],
64
+ [
65
+ "UNKNOWN",
66
+ "SUCCESS",
67
+ "allowed"
68
+ ],
69
+ [
70
+ "UNKNOWN",
71
+ null,
72
+ "allowed"
73
+ ],
74
+ [
75
+ "CLEAN",
76
+ "SUCCESS",
77
+ "allowed"
78
+ ]
79
+ ]) expect(assessGitHubMerge({
80
+ mergeStateStatus,
81
+ headRollupState
82
+ }).kind).toBe(expected);
83
+ });
84
+ it("turns a clean visible list plus GitHub refusal into an explicit CI blocker", async () => {
85
+ const reader = fakeReader({
86
+ facts: { mergeStateStatus: "BLOCKED" },
87
+ fastPath: {
88
+ kind: "checks",
89
+ checks: [passingCheck()]
90
+ },
91
+ commitRollups: [{
92
+ oid: "head",
93
+ state: "FAILURE"
94
+ }]
95
+ });
96
+ const snapshot = await readSnapshot({
97
+ reader,
98
+ context: context(1),
99
+ pendingHistory: "include",
100
+ allowDraft: false
101
+ });
102
+ expect(snapshot.kind).toBe("open");
103
+ if (snapshot.kind !== "open") throw new Error("expected open snapshot");
104
+ expect(snapshot.ci.kind).toBe("ci-github-rejected");
105
+ expect(classifyPr(snapshot)).toMatchObject({
106
+ kind: "blocker",
107
+ blocker: { kind: "failing-checks" }
108
+ });
109
+ });
110
+ });
111
+ describe("snapshot query planning", () => {
112
+ it("does not query commit rollups while queued checks are pending", async () => {
113
+ const reader = fakeReader({ fastPath: {
114
+ kind: "checks",
115
+ checks: [pendingCheck()]
116
+ } });
117
+ const snapshot = await readSnapshot({
118
+ reader,
119
+ context: context(2),
120
+ pendingHistory: "omit",
121
+ allowDraft: false
122
+ });
123
+ expect(snapshot.kind).toBe("open");
124
+ if (snapshot.kind !== "open") throw new Error("expected open snapshot");
125
+ expect(snapshot.ci.kind).toBe("ci-pending");
126
+ expect(reader.calls).toEqual([
127
+ "pullRequest",
128
+ "reviewThreadPage:null",
129
+ "checksFastPath"
130
+ ]);
131
+ });
132
+ it("queries rollups for settled and failed lists", async () => {
133
+ const settled = fakeReader();
134
+ await readSnapshot({
135
+ reader: settled,
136
+ context: context(3),
137
+ pendingHistory: "omit",
138
+ allowDraft: false
139
+ });
140
+ expect(settled.calls).toContain("commitRollups");
141
+ const failed = fakeReader({ fastPath: {
142
+ kind: "checks",
143
+ checks: [failedCheck()]
144
+ } });
145
+ await readSnapshot({
146
+ reader: failed,
147
+ context: context(4),
148
+ pendingHistory: "omit",
149
+ allowDraft: false
150
+ });
151
+ expect(failed.calls).toContain("commitRollups");
152
+ });
153
+ it("short-circuits merged rows before threads and checks", async () => {
154
+ const reader = fakeReader({ facts: {
155
+ state: "MERGED",
156
+ mergedAt: "2026-07-26T00:00:00Z"
157
+ } });
158
+ expect((await readSnapshot({
159
+ reader,
160
+ context: context(5),
161
+ pendingHistory: "include",
162
+ allowDraft: false
163
+ })).kind).toBe("merged");
164
+ expect(reader.calls).toEqual(["pullRequest"]);
165
+ });
166
+ });
167
+ it("scans stacks tier-major so an upstack conflict outranks frontier CI", async () => {
168
+ const frontier = await readSnapshot({
169
+ reader: fakeReader({
170
+ fastPath: {
171
+ kind: "checks",
172
+ checks: [failedCheck()]
173
+ },
174
+ commitRollups: [{
175
+ oid: "head",
176
+ state: "FAILURE"
177
+ }]
178
+ }),
179
+ context: context(10),
180
+ pendingHistory: "omit",
181
+ allowDraft: false
182
+ });
183
+ const upstack = await readSnapshot({
184
+ reader: fakeReader({ facts: { mergeable: "CONFLICTING" } }),
185
+ context: context(11),
186
+ pendingHistory: "omit",
187
+ allowDraft: false
188
+ });
189
+ const decision = selectTierMajorStackDecision([frontier, upstack]);
190
+ expect(decision).toMatchObject({
191
+ kind: "blocker",
192
+ blocker: {
193
+ kind: "merge-conflicts",
194
+ pr: { number: 11 }
195
+ }
196
+ });
197
+ });
198
+ it("attributes a stack wait to the PR whose checks are pending, not the bottom", async () => {
199
+ const readyBottom = await readSnapshot({
200
+ reader: fakeReader(),
201
+ context: context(20),
202
+ pendingHistory: "omit",
203
+ allowDraft: false
204
+ });
205
+ const pendingUpstack = await readSnapshot({
206
+ reader: fakeReader({ fastPath: {
207
+ kind: "checks",
208
+ checks: [pendingCheck("upstack-build")]
209
+ } }),
210
+ context: context(21),
211
+ pendingHistory: "omit",
212
+ allowDraft: false
213
+ });
214
+ const decision = selectTierMajorStackDecision([readyBottom, pendingUpstack]);
215
+ expect(decision).toMatchObject({
216
+ kind: "waiting",
217
+ frontier: { number: 21 },
218
+ pending: [{ name: "upstack-build" }]
219
+ });
220
+ });
221
+ it("waits on a draft while checks are pending, then reports the draft gate", async () => {
222
+ const pending = await readSnapshot({
223
+ reader: fakeReader({
224
+ facts: { isDraft: true },
225
+ fastPath: {
226
+ kind: "checks",
227
+ checks: [pendingCheck()]
228
+ }
229
+ }),
230
+ context: context(12),
231
+ pendingHistory: "omit",
232
+ allowDraft: false
233
+ });
234
+ expect(classifyPr(pending).kind).toBe("waiting");
235
+ const settled = await readSnapshot({
236
+ reader: fakeReader({ facts: { isDraft: true } }),
237
+ context: context(12),
238
+ pendingHistory: "omit",
239
+ allowDraft: false
240
+ });
241
+ expect(classifyPr(settled)).toMatchObject({
242
+ kind: "blocker",
243
+ blocker: {
244
+ kind: "merge-gate",
245
+ reason: "draft-pr"
246
+ }
247
+ });
248
+ });
249
+ describe("queued-stack cadence", () => {
250
+ async function openSnapshot(pr) {
251
+ return readSnapshot({
252
+ reader: fakeReader(),
253
+ context: pr,
254
+ pendingHistory: "omit",
255
+ allowDraft: false
256
+ });
257
+ }
258
+ it("drops a sweep head only after its snapshot succeeds", async () => {
259
+ const queue = [
260
+ context(20),
261
+ context(21),
262
+ context(22)
263
+ ];
264
+ let state = createQueueState(queue, 0);
265
+ const first = await openSnapshot(queue[0]);
266
+ state = applyQueueSnapshot(state, first, 0, options).state;
267
+ expect(state.work).toMatchObject({
268
+ kind: "whole-stack-sweep",
269
+ remaining: [{ number: 21 }, { number: 22 }]
270
+ });
271
+ const second = await openSnapshot(queue[1]);
272
+ state = applyQueueSnapshot(state, second, 60, options).state;
273
+ expect(state.work).toMatchObject({
274
+ kind: "whole-stack-sweep",
275
+ remaining: [{ number: 22 }]
276
+ });
277
+ });
278
+ it("resumes the sweep at the PR whose read failed", async () => {
279
+ const middle = context(21);
280
+ const base = fakeReader();
281
+ let failNext = true;
282
+ const timeline = [];
283
+ const reader = {
284
+ ...base,
285
+ async pullRequest(pr) {
286
+ if (pr.number === middle.number && failNext) {
287
+ failNext = false;
288
+ timeline.push(`fail:${pr.number}`);
289
+ throw new WatcherQueryError({
290
+ kind: "command-exit",
291
+ retryable: true,
292
+ detail: "rate limited",
293
+ code: 1
294
+ });
295
+ }
296
+ timeline.push(`read:${pr.number}`);
297
+ return base.pullRequest(pr);
298
+ }
299
+ };
300
+ let now = 0;
301
+ let sleeps = 0;
302
+ const running = runQueued({
303
+ dependencies: {
304
+ reader,
305
+ clock: {
306
+ now: () => now,
307
+ observedAt: () => "2026-07-26T00:00:00.000Z",
308
+ async sleep(seconds) {
309
+ timeline.push("sleep");
310
+ now += seconds;
311
+ sleeps += 1;
312
+ if (sleeps === 2) throw new Error("stop after resume proof");
313
+ }
314
+ },
315
+ emit(verdict) {
316
+ timeline.push(`emit:${verdict.kind}`);
317
+ }
318
+ },
319
+ contexts: [
320
+ context(20),
321
+ middle,
322
+ context(22)
323
+ ],
324
+ options
325
+ });
326
+ await expect(running).rejects.toThrow("stop after resume proof");
327
+ expect(timeline).toEqual([
328
+ "emit:QUEUE",
329
+ "read:20",
330
+ "fail:21",
331
+ "emit:RETRY",
332
+ "sleep",
333
+ "read:21",
334
+ "read:22",
335
+ "emit:STATUS",
336
+ "emit:WAITING",
337
+ "sleep"
338
+ ]);
339
+ });
340
+ it("emits a completed sweep only after its final successful snapshot", async () => {
341
+ const queue = [context(30), context(31)];
342
+ let state = createQueueState(queue, 0);
343
+ const first = applyQueueSnapshot(state, await openSnapshot(queue[0]), 0, options);
344
+ expect(first.completedSweepRows).toBeNull();
345
+ state = first.state;
346
+ const second = applyQueueSnapshot(state, await openSnapshot(queue[1]), 5, options);
347
+ expect(second.completedSweepRows?.map((row) => Number(row.context.number))).toEqual([30, 31]);
348
+ expect(second.state.nextSweepAt).toBe(305);
349
+ });
350
+ it("ADVANCE continues directly to the new frontier without sleeping", async () => {
351
+ const one = context(40);
352
+ const two = context(41);
353
+ const base = fakeReader();
354
+ const reads = /* @__PURE__ */ new Map();
355
+ const timeline = [];
356
+ const reader = {
357
+ ...base,
358
+ async pullRequest(pr) {
359
+ timeline.push(`read:${pr.number}`);
360
+ const facts = await base.pullRequest(pr);
361
+ const count = (reads.get(pr.number) ?? 0) + 1;
362
+ reads.set(pr.number, count);
363
+ return pr.number === one.number && count > 1 ? {
364
+ ...facts,
365
+ state: "MERGED",
366
+ mergedAt: "2026-07-26T00:00:00Z"
367
+ } : facts;
368
+ }
369
+ };
370
+ let now = 0;
371
+ let sleeps = 0;
372
+ const emitted = [];
373
+ const running = runQueued({
374
+ dependencies: {
375
+ reader,
376
+ clock: {
377
+ now: () => now,
378
+ observedAt: () => "2026-07-26T00:00:00.000Z",
379
+ async sleep(seconds) {
380
+ timeline.push("sleep");
381
+ now += seconds;
382
+ sleeps += 1;
383
+ if (sleeps === 2) throw new Error("stop after advance proof");
384
+ }
385
+ },
386
+ emit(verdict) {
387
+ emitted.push(verdict);
388
+ timeline.push(`emit:${verdict.kind}`);
389
+ }
390
+ },
391
+ contexts: [one, two],
392
+ options
393
+ });
394
+ await expect(running).rejects.toThrow("stop after advance proof");
395
+ expect(emitted.some((event) => event.kind === "ADVANCE")).toBe(true);
396
+ const firstSleep = timeline.indexOf("sleep");
397
+ expect(timeline.slice(firstSleep, firstSleep + 5)).toEqual([
398
+ "sleep",
399
+ "read:40",
400
+ "emit:ADVANCE",
401
+ "read:41",
402
+ "emit:WAITING"
403
+ ]);
404
+ });
405
+ it("deduplicates identical waits and schedules the next due sweep", async () => {
406
+ const queue = [context(50)];
407
+ let state = createQueueState(queue, 0);
408
+ state = applyQueueSnapshot(state, await openSnapshot(queue[0]), 0, options).state;
409
+ const first = evaluateQueue(state, 0, options);
410
+ expect(first.kind).toBe("waiting");
411
+ if (first.kind !== "waiting") throw new Error("expected waiting");
412
+ expect(first.emit).toBe(true);
413
+ const second = evaluateQueue(first.state, 10, options);
414
+ expect(second.kind).toBe("waiting");
415
+ if (second.kind !== "waiting") throw new Error("expected waiting");
416
+ expect(second.emit).toBe(false);
417
+ expect(planQueue(second.state, 300).work?.kind).toBe("whole-stack-sweep");
418
+ });
419
+ });
420
+ it("uses the specified retry floor and cap", () => {
421
+ expect(queryBackoffSeconds(1, 1)).toBe(60);
422
+ expect(queryBackoffSeconds(1, 2)).toBe(120);
423
+ expect(queryBackoffSeconds(60, 4)).toBe(300);
424
+ });
425
+ describe("polling deadline sleeps", () => {
426
+ for (const mode of [
427
+ "single",
428
+ "queued-stack",
429
+ "query-retry"
430
+ ]) it(`caps ${mode} sleeps at the configured deadline`, async () => {
431
+ let now = 0;
432
+ const sleeps = [];
433
+ const pending = fakeReader({ fastPath: {
434
+ kind: "checks",
435
+ checks: [pendingCheck()]
436
+ } });
437
+ const dependencies = {
438
+ reader: mode === "query-retry" ? {
439
+ ...pending,
440
+ async pullRequest() {
441
+ throw new WatcherQueryError({
442
+ kind: "command-exit",
443
+ retryable: true,
444
+ code: 1,
445
+ detail: "temporary failure"
446
+ });
447
+ }
448
+ } : pending,
449
+ clock: {
450
+ now: () => now,
451
+ observedAt: () => "2026-07-26T00:00:00.000Z",
452
+ async sleep(seconds) {
453
+ sleeps.push(seconds);
454
+ now += seconds;
455
+ }
456
+ },
457
+ emit() {}
458
+ };
459
+ const polling = {
460
+ ...options,
461
+ interval: 60,
462
+ timeout: 5
463
+ };
464
+ const result = mode === "queued-stack" ? await runQueued({
465
+ dependencies,
466
+ contexts: [context(1)],
467
+ options: polling
468
+ }) : await runSimple({
469
+ dependencies,
470
+ contexts: [context(1)],
471
+ mode: "single",
472
+ statusOnly: false,
473
+ options: polling
474
+ });
475
+ expect(result.kind).toBe("TIMEOUT");
476
+ expect(sleeps).toEqual([5]);
477
+ expect(now).toBe(5);
478
+ });
479
+ it("preserves the polling interval when the deadline is disabled", async () => {
480
+ let now = 0;
481
+ let reads = 0;
482
+ const sleeps = [];
483
+ const pending = fakeReader({ fastPath: {
484
+ kind: "checks",
485
+ checks: [pendingCheck()]
486
+ } });
487
+ const passed = fakeReader({ fastPath: {
488
+ kind: "checks",
489
+ checks: [passingCheck()]
490
+ } });
491
+ const result = await runSimple({
492
+ dependencies: {
493
+ reader: {
494
+ ...pending,
495
+ async checksFastPath(pr) {
496
+ reads += 1;
497
+ return reads === 1 ? pending.checksFastPath(pr) : passed.checksFastPath(pr);
498
+ }
499
+ },
500
+ clock: {
501
+ now: () => now,
502
+ observedAt: () => "2026-07-26T00:00:00.000Z",
503
+ async sleep(seconds) {
504
+ sleeps.push(seconds);
505
+ now += seconds;
506
+ }
507
+ },
508
+ emit() {}
509
+ },
510
+ contexts: [context(1)],
511
+ mode: "single",
512
+ statusOnly: false,
513
+ options: {
514
+ ...options,
515
+ interval: 60,
516
+ timeout: 0
517
+ }
518
+ });
519
+ expect(result.kind).toBe("READY");
520
+ expect(sleeps).toEqual([60]);
521
+ });
522
+ });
523
+ export {};
@@ -0,0 +1,106 @@
1
+ // runtime/skills/poteto-mode/scripts/watch-pr/render.ts
2
+ const renderJson = (verdict) => `${JSON.stringify(verdict)}\n`;
3
+ function ciCell(row) {
4
+ if (row.kind !== "open") return "—";
5
+ const was = row.ci.hadPreviousPassingCi ? ", was ✅" : "";
6
+ switch (row.ci.kind) {
7
+ case "ci-clean": return "✅";
8
+ case "ci-pending": return `⏳ ${row.ci.pending.length} pending${was}`;
9
+ case "ci-failing": return `❌ ${row.ci.failed.length} failed${row.ci.pending.length ? `, ${row.ci.pending.length} pending` : ""}${was}`;
10
+ case "ci-github-rejected": return `❌ GitHub reports failing checks${was}`;
11
+ default: return row.ci;
12
+ }
13
+ }
14
+ function reviewCell(row) {
15
+ if (row.kind !== "open") return "—";
16
+ const open = row.threads.length;
17
+ return row.reviewAutomationRunning ? open ? `🤖 running, ${open} open` : "🤖 running" : open ? `📝 ${open} open` : "✅";
18
+ }
19
+ function mergeCell(row) {
20
+ if (row.kind === "merged") return "✅ merged";
21
+ if (row.kind === "closed") return "❌ closed";
22
+ if (row.facts.isDraft) return "⏸ draft";
23
+ if (row.facts.reviewDecision === "CHANGES_REQUESTED") return "⚠️ changes requested";
24
+ return row.facts.mergeable === "CONFLICTING" || row.facts.mergeStateStatus === "DIRTY" || row.facts.mergeStateStatus === "CONFLICTING" ? "⚠️ conflict" : "✅";
25
+ }
26
+ function renderStatusTable(rows) {
27
+ const lines = ["| PR | CI | Review | Merge |", "| --- | --- | --- | --- |"];
28
+ for (const row of rows) {
29
+ const url = `https://github.com/${row.context.owner}/${row.context.repo}/pull/${row.context.number}`;
30
+ lines.push(`| [#${row.context.number}](${url}) | ${ciCell(row)} | ${reviewCell(row)} | ${mergeCell(row)} |`);
31
+ }
32
+ return `${lines.join("\n")}\n`;
33
+ }
34
+ function threadLine(thread) {
35
+ const comment = thread.firstComment;
36
+ return [
37
+ thread.id,
38
+ comment?.path ?? "None",
39
+ comment?.line ?? "None",
40
+ comment?.authorLogin ?? "None",
41
+ `isBugBot=${thread.isBugbot}`,
42
+ `bugbotReviewPasses=${thread.bugbotReviewPasses}`,
43
+ (comment?.body ?? "").split(/\r?\n/, 1)[0]?.slice(0, 180) ?? ""
44
+ ].join(" ");
45
+ }
46
+ function renderBlocker(blocker) {
47
+ switch (blocker.kind) {
48
+ case "merge-conflicts": return [
49
+ "BLOCKER: merge-conflicts",
50
+ `pr=${blocker.pr.number}`,
51
+ `mergeable=${blocker.facts.mergeable}`,
52
+ `mergeStateStatus=${blocker.facts.mergeStateStatus}`,
53
+ "action=resolve merge conflicts before waiting for CI"
54
+ ].join("\n");
55
+ case "review-threads": return [
56
+ "BLOCKER: review-threads",
57
+ `pr=${blocker.pr.number}`,
58
+ `unresolved=${blocker.threads.length}`,
59
+ ...blocker.threads.map(threadLine)
60
+ ].join("\n");
61
+ case "failing-checks": {
62
+ const failed = blocker.ci.kind === "ci-failing" ? blocker.ci.failed : [];
63
+ const details = failed.map((check) => `${check.name} ${check.reportedState} ${check.description} ${check.link}`);
64
+ if (blocker.ci.kind === "ci-github-rejected") details.push(`mergeStateStatus=${blocker.ci.github.mergeStateStatus}`, `headRollupState=${blocker.ci.github.headRollupState}`);
65
+ return [
66
+ "BLOCKER: failing-checks",
67
+ `pr=${blocker.pr.number}`,
68
+ `failed=${failed.length}`,
69
+ ...details
70
+ ].join("\n");
71
+ }
72
+ case "merge-gate": {
73
+ const action = blocker.reason === "closed-without-merge" ? "restore or remove the closed PR from the queued stack" : blocker.reason === "draft-pr" ? "mark the PR ready for review before waiting for the merge queue" : "resolve the changes-requested review before waiting for the merge queue";
74
+ return [
75
+ `BLOCKER: ${blocker.reason}`,
76
+ `pr=${blocker.pr.number}`,
77
+ `action=${action}`
78
+ ].join("\n");
79
+ }
80
+ case "status-query": return [
81
+ "BLOCKER: status-query",
82
+ `failures=${blocker.failures}`,
83
+ `detail=${blocker.failure.detail}`,
84
+ "action=verify current PR context, GitHub authentication, and API availability, then rearm"
85
+ ].join("\n");
86
+ default: return blocker;
87
+ }
88
+ }
89
+ function renderPretty(verdict) {
90
+ switch (verdict.kind) {
91
+ case "QUEUE": return `QUEUE: captured ${verdict.queue.length} PR${verdict.queue.length === 1 ? "" : "s"} bottom-to-top: ${verdict.queue.map((pr) => `#${pr.number}`).join(",")}\n`;
92
+ case "STATUS": return renderStatusTable(verdict.rows);
93
+ case "WAITING": return verdict.reason.kind === "pending-checks" ? `WAITING: frontier=#${verdict.frontier.number}; ${verdict.reason.pending.length} check${verdict.reason.pending.length === 1 ? "" : "s"} pending\n` : `WAITING: frontier=#${verdict.frontier.number} is blocker-free; waiting for merge queue (${verdict.reason.unmergedCount} PR${verdict.reason.unmergedCount === 1 ? "" : "s"} unmerged)\n`;
94
+ case "ADVANCE": return `ADVANCE: merged #${verdict.merged.number}; next=#${verdict.frontier.number}; remaining=${verdict.remaining}\n`;
95
+ case "RETRY": return `RETRY: GitHub status query failed; retrying in ${verdict.retryInSeconds}s\ndetail=${verdict.failure.detail}\n`;
96
+ case "BLOCKER": return `${renderBlocker(verdict.blocker)}\n`;
97
+ case "READY": return `READY: no merge conflicts, no unresolved review threads, no failing or pending checks${verdict.scope.kind === "single" && verdict.scope.pr.kind === "ready-pr" ? `\nmergeStateStatus=${verdict.scope.pr.proof.ci.github.mergeStateStatus}\nreviewDecision=${verdict.scope.pr.proof.gate.reviewDecision}\nisDraft=${verdict.scope.pr.proof.gate.draft === "draft-allowed"}${verdict.scope.pr.proof.gate.draft === "draft-allowed" ? "\nnote=draft allowed (--allow-draft); leave draft — do not mark ready" : ""}` : ""}\n`;
98
+ case "COMPLETE": return `COMPLETE: queued stack merged (${verdict.queue.length} PR${verdict.queue.length === 1 ? "" : "s"})\n`;
99
+ case "TIMEOUT":
100
+ if (verdict.reason.kind === "pending-checks") return "TIMEOUT: checks still pending\n";
101
+ if (verdict.reason.kind === "status-unavailable") return "TIMEOUT: GitHub status remained unavailable\n";
102
+ return `TIMEOUT: queued stack still has ${verdict.reason.unmergedCount} PR${verdict.reason.unmergedCount === 1 ? "" : "s"} unmerged; frontier=#${verdict.reason.frontier.number}\n`;
103
+ default: return verdict;
104
+ }
105
+ }
106
+ export { renderJson, renderPretty, renderStatusTable };
@@ -0,0 +1,9 @@
1
+ // runtime/skills/poteto-mode/scripts/watch-pr/types.ts
2
+ function nonEmpty(items) {
3
+ return items.length === 0 ? null : [items[0], ...items.slice(1)];
4
+ }
5
+ function parsePrNumber(value, label = "PR number") {
6
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) throw new Error(`${label} must be a positive integer`);
7
+ return value;
8
+ }
9
+ export { nonEmpty, parsePrNumber };
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ // runtime/skills/poteto-mode/scripts/watch-pr/watch-pr
3
+ const { main } = await import("./cli.mjs");
4
+ process.exitCode = await main(process.argv.slice(2));
5
+ export {};