pstack-claude-mirror 0.0.0-stage → 0.9.133

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 (664) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/CHANGES.md +1110 -0
  3. package/LICENSE +22 -0
  4. package/LICENSE-cursor-team-kit +21 -0
  5. package/LICENSE-mirror +27 -0
  6. package/LICENSE-thermos +21 -0
  7. package/NOTICE-skills.md +13 -0
  8. package/NOTICE.md +62 -0
  9. package/README.md +84 -2
  10. package/UPSTREAM-README.md +243 -0
  11. package/bin/pstack-claude.mjs +183 -0
  12. package/docs/reference.md +247 -0
  13. package/package.json +88 -4
  14. package/plugins/pstack/.antigravity-plugin/plugin.json +8 -0
  15. package/plugins/pstack/.claude-plugin/icon.png +0 -0
  16. package/plugins/pstack/.claude-plugin/plugin.json +31 -0
  17. package/plugins/pstack/.codex-plugin/plugin.json +52 -0
  18. package/plugins/pstack/.github/plugin/plugin.json +15 -0
  19. package/plugins/pstack/.grok-plugin/plugin.json +9 -0
  20. package/plugins/pstack/.muse-plugin/plugin.json +381 -0
  21. package/plugins/pstack/README.md +27 -0
  22. package/plugins/pstack/agents/comment-sicko.md +34 -0
  23. package/plugins/pstack/agents/poteto-agent.md +8 -0
  24. package/plugins/pstack/agents/thermo-nuclear-code-quality-review-subagent.md +23 -0
  25. package/plugins/pstack/agents/thermo-nuclear-review-subagent.md +28 -0
  26. package/plugins/pstack/assets/pstack-icon.png +0 -0
  27. package/plugins/pstack/assets/pstack-icon.prompt.txt +8 -0
  28. package/plugins/pstack/grok/skills/pstack-routing/SKILL.md +8 -0
  29. package/plugins/pstack/hooks/agy-context.awk +9 -0
  30. package/plugins/pstack/hooks/codex-hooks.json +17 -0
  31. package/plugins/pstack/hooks/copilot-context.awk +44 -0
  32. package/plugins/pstack/hooks/copilot-hooks.json +27 -0
  33. package/plugins/pstack/hooks/hooks.json +16 -0
  34. package/plugins/pstack/hooks/json.awk +164 -0
  35. package/plugins/pstack/hooks/kimi-instructions.md +17 -0
  36. package/plugins/pstack/hooks/muse-context.awk +31 -0
  37. package/plugins/pstack/hooks/pre-tool-use.awk +152 -0
  38. package/plugins/pstack/hooks/pre-tool-use.sh +16 -0
  39. package/plugins/pstack/hooks/script-contracts.awk +55 -0
  40. package/plugins/pstack/hooks/session-start-agy.md +17 -0
  41. package/plugins/pstack/hooks/session-start-context.md +15 -0
  42. package/plugins/pstack/hooks/session-start-copilot-setup.md +1 -0
  43. package/plugins/pstack/hooks/session-start-copilot-sheet.md +1 -0
  44. package/plugins/pstack/hooks/session-start-copilot.md +3 -0
  45. package/plugins/pstack/hooks/session-start-minimax.md +17 -0
  46. package/plugins/pstack/hooks/session-start-muse-sheet.md +1 -0
  47. package/plugins/pstack/hooks/session-start-muse.md +17 -0
  48. package/plugins/pstack/hooks/session-start-opencode.md +17 -0
  49. package/plugins/pstack/hooks/session-start.ps1 +105 -0
  50. package/plugins/pstack/hooks/session-start.sh +95 -0
  51. package/plugins/pstack/hooks.json +10 -0
  52. package/plugins/pstack/models.json +67 -0
  53. package/plugins/pstack/omp/index.mjs +34 -0
  54. package/plugins/pstack/opencode/index.js +49 -0
  55. package/plugins/pstack/package.json +8 -0
  56. package/plugins/pstack/pi/agent-files.ts +117 -0
  57. package/plugins/pstack/pi/agent-text.ts +99 -0
  58. package/plugins/pstack/pi/agent-tools.ts +148 -0
  59. package/plugins/pstack/pi/agents.ts +486 -0
  60. package/plugins/pstack/pi/ask.ts +87 -0
  61. package/plugins/pstack/pi/child.ts +310 -0
  62. package/plugins/pstack/pi/config.ts +178 -0
  63. package/plugins/pstack/pi/index.ts +44 -0
  64. package/plugins/pstack/pi/one-shot.ts +90 -0
  65. package/plugins/pstack/pi/path-skills.ts +54 -0
  66. package/plugins/pstack/pi/prompt.ts +39 -0
  67. package/plugins/pstack/pi/schedule.ts +254 -0
  68. package/plugins/pstack/pi/slash.ts +92 -0
  69. package/plugins/pstack/pi/sleep-wait.ts +76 -0
  70. package/plugins/pstack/pi/worktree.ts +74 -0
  71. package/plugins/pstack/skills/architect/SKILL.md +100 -0
  72. package/plugins/pstack/skills/architect/references/design-red-flags.md +57 -0
  73. package/plugins/pstack/skills/architect/references/rationale-template.md +39 -0
  74. package/plugins/pstack/skills/architect/references/runner-prompt.md +20 -0
  75. package/plugins/pstack/skills/arena/SKILL.md +66 -0
  76. package/plugins/pstack/skills/automate-me/SKILL.md +111 -0
  77. package/plugins/pstack/skills/babysit/SKILL.md +68 -0
  78. package/plugins/pstack/skills/benchmark-checklist/SKILL.md +38 -0
  79. package/plugins/pstack/skills/blast-radius/SKILL.md +49 -0
  80. package/plugins/pstack/skills/bro/SKILL.md +6 -0
  81. package/plugins/pstack/skills/correct/SKILL.md +31 -0
  82. package/plugins/pstack/skills/create-formal-verification-skill/SKILL.md +50 -0
  83. package/plugins/pstack/skills/create-verification-skill/SKILL.md +51 -0
  84. package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
  85. package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
  86. package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
  87. package/plugins/pstack/skills/deslop/SKILL.md +24 -0
  88. package/plugins/pstack/skills/figure-it-out/SKILL.md +51 -0
  89. package/plugins/pstack/skills/fix-ci/SKILL.md +29 -0
  90. package/plugins/pstack/skills/fix-merge-conflicts/SKILL.md +32 -0
  91. package/plugins/pstack/skills/get-pr-comments/SKILL.md +23 -0
  92. package/plugins/pstack/skills/how/SKILL.md +54 -0
  93. package/plugins/pstack/skills/how/references/explainer-prompt.md +55 -0
  94. package/plugins/pstack/skills/how/references/explorer-prompt.md +35 -0
  95. package/plugins/pstack/skills/in-your-own-words/SKILL.md +6 -0
  96. package/plugins/pstack/skills/interrogate/SKILL.md +48 -0
  97. package/plugins/pstack/skills/ketchup/SKILL.md +42 -0
  98. package/plugins/pstack/skills/ketchup-video/SKILL.md +28 -0
  99. package/plugins/pstack/skills/maintain-formal-verification-skill/SKILL.md +65 -0
  100. package/plugins/pstack/skills/maintain-verification-skill/SKILL.md +46 -0
  101. package/plugins/pstack/skills/make-pr-easy-to-review/SKILL.md +59 -0
  102. package/plugins/pstack/skills/no-comments/SKILL.md +45 -0
  103. package/plugins/pstack/skills/poteto-help/SKILL.md +149 -0
  104. package/plugins/pstack/skills/poteto-help/references/prompting.md +51 -0
  105. package/plugins/pstack/skills/poteto-help/references/recipes.md +51 -0
  106. package/plugins/pstack/skills/poteto-mode/SKILL.md +174 -0
  107. package/plugins/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  108. package/plugins/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  109. package/plugins/pstack/skills/poteto-mode/playbooks/autopilot-full.md +31 -0
  110. package/plugins/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  111. package/plugins/pstack/skills/poteto-mode/playbooks/babysit.md +23 -0
  112. package/plugins/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  113. package/plugins/pstack/skills/poteto-mode/playbooks/eval.md +25 -0
  114. package/plugins/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
  115. package/plugins/pstack/skills/poteto-mode/playbooks/hillclimb.md +21 -0
  116. package/plugins/pstack/skills/poteto-mode/playbooks/investigation.md +14 -0
  117. package/plugins/pstack/skills/poteto-mode/playbooks/multi-phase-plan.md +158 -0
  118. package/plugins/pstack/skills/poteto-mode/playbooks/opening-a-pr.md +34 -0
  119. package/plugins/pstack/skills/poteto-mode/playbooks/orchestrate.md +27 -0
  120. package/plugins/pstack/skills/poteto-mode/playbooks/pause-safely.md +11 -0
  121. package/plugins/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  122. package/plugins/pstack/skills/poteto-mode/playbooks/prototype.md +14 -0
  123. package/plugins/pstack/skills/poteto-mode/playbooks/refactoring.md +18 -0
  124. package/plugins/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  125. package/plugins/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  126. package/plugins/pstack/skills/poteto-mode/playbooks/shipping.md +16 -0
  127. package/plugins/pstack/skills/poteto-mode/playbooks/trace-forensics.md +14 -0
  128. package/plugins/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  129. package/plugins/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  130. package/plugins/pstack/skills/poteto-mode/references/agents/comment-sicko.md +34 -0
  131. package/plugins/pstack/skills/poteto-mode/references/agy-tools.md +99 -0
  132. package/plugins/pstack/skills/poteto-mode/references/bugbot-triage.md +142 -0
  133. package/plugins/pstack/skills/poteto-mode/references/codex-tools.md +109 -0
  134. package/plugins/pstack/skills/poteto-mode/references/copilot-tools.md +143 -0
  135. package/plugins/pstack/skills/poteto-mode/references/grok.md +50 -0
  136. package/plugins/pstack/skills/poteto-mode/references/kimi-tools.md +40 -0
  137. package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE +22 -0
  138. package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE-cursor-team-kit +21 -0
  139. package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE-thermos +21 -0
  140. package/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md +13 -0
  141. package/plugins/pstack/skills/poteto-mode/references/merge-safety.md +43 -0
  142. package/plugins/pstack/skills/poteto-mode/references/minimax-tools.md +93 -0
  143. package/plugins/pstack/skills/poteto-mode/references/muse-tools.md +105 -0
  144. package/plugins/pstack/skills/poteto-mode/references/omp-tools.md +39 -0
  145. package/plugins/pstack/skills/poteto-mode/references/opencode-tools.md +29 -0
  146. package/plugins/pstack/skills/poteto-mode/references/pi-tools.md +117 -0
  147. package/plugins/pstack/skills/poteto-mode/references/resume-storage.md +20 -0
  148. package/plugins/pstack/skills/poteto-mode/scripts/.prettierignore +23 -0
  149. package/plugins/pstack/skills/poteto-mode/scripts/.prettierrc.json +3 -0
  150. package/plugins/pstack/skills/poteto-mode/scripts/bootstrap.ts +71 -0
  151. package/plugins/pstack/skills/poteto-mode/scripts/bun.lock +67 -0
  152. package/plugins/pstack/skills/poteto-mode/scripts/check-plan.mjs +214 -0
  153. package/plugins/pstack/skills/poteto-mode/scripts/check-plan.test.ts +115 -0
  154. package/plugins/pstack/skills/poteto-mode/scripts/check-playbooks.mjs +71 -0
  155. package/plugins/pstack/skills/poteto-mode/scripts/codex-session-effort.mjs +66 -0
  156. package/plugins/pstack/skills/poteto-mode/scripts/package.json +16 -0
  157. package/plugins/pstack/skills/poteto-mode/scripts/resume.mjs +139 -0
  158. package/plugins/pstack/skills/poteto-mode/scripts/tsconfig.json +14 -0
  159. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.ts +383 -0
  160. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/cli.ts +266 -0
  161. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/deadline.ts +20 -0
  162. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +157 -0
  163. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/fresh-install.test.ts +35 -0
  164. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.test.ts +902 -0
  165. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.ts +922 -0
  166. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/integrity.test.ts +887 -0
  167. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/landing.ts +92 -0
  168. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/live-merge-safety.mjs +142 -0
  169. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.ts +1151 -0
  170. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.ts +956 -0
  171. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/render.ts +200 -0
  172. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/ship-pr +6 -0
  173. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping-cli.test.ts +159 -0
  174. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping-cli.ts +65 -0
  175. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.test-helper.ts +48 -0
  176. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.test.ts +360 -0
  177. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.ts +235 -0
  178. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/transport.test.ts +211 -0
  179. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/tsconfig.json +13 -0
  180. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/types.compile.ts +108 -0
  181. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/types.ts +474 -0
  182. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr +6 -0
  183. package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/wrapper.test.ts +20 -0
  184. package/plugins/pstack/skills/poteto-mode/scripts/worktree-audit.mjs +434 -0
  185. package/plugins/pstack/skills/principle-attack-the-premise/SKILL.md +21 -0
  186. package/plugins/pstack/skills/principle-boundary-discipline/SKILL.md +34 -0
  187. package/plugins/pstack/skills/principle-build-the-lever/SKILL.md +24 -0
  188. package/plugins/pstack/skills/principle-encode-lessons-in-structure/SKILL.md +11 -0
  189. package/plugins/pstack/skills/principle-exhaust-the-design-space/SKILL.md +9 -0
  190. package/plugins/pstack/skills/principle-experience-first/SKILL.md +19 -0
  191. package/plugins/pstack/skills/principle-explain-the-number/SKILL.md +18 -0
  192. package/plugins/pstack/skills/principle-fix-root-causes/SKILL.md +21 -0
  193. package/plugins/pstack/skills/principle-foundational-thinking/SKILL.md +21 -0
  194. package/plugins/pstack/skills/principle-guard-the-context-window/SKILL.md +12 -0
  195. package/plugins/pstack/skills/principle-laziness-protocol/SKILL.md +10 -0
  196. package/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md +22 -0
  197. package/plugins/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +14 -0
  198. package/plugins/pstack/skills/principle-minimize-reader-load/SKILL.md +18 -0
  199. package/plugins/pstack/skills/principle-model-the-domain/SKILL.md +24 -0
  200. package/plugins/pstack/skills/principle-never-block-on-the-human/SKILL.md +15 -0
  201. package/plugins/pstack/skills/principle-outcome-oriented-execution/SKILL.md +21 -0
  202. package/plugins/pstack/skills/principle-prove-it-works/SKILL.md +27 -0
  203. package/plugins/pstack/skills/principle-redesign-from-first-principles/SKILL.md +16 -0
  204. package/plugins/pstack/skills/principle-separate-before-serializing-shared-state/SKILL.md +16 -0
  205. package/plugins/pstack/skills/principle-sequence-verifiable-units/SKILL.md +17 -0
  206. package/plugins/pstack/skills/principle-subtract-before-you-add/SKILL.md +18 -0
  207. package/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md +20 -0
  208. package/plugins/pstack/skills/principle-type-system-discipline/SKILL.md +13 -0
  209. package/plugins/pstack/skills/recall/SKILL.md +43 -0
  210. package/plugins/pstack/skills/reflect/SKILL.md +89 -0
  211. package/plugins/pstack/skills/reflect/references/divergent-reviewer.md +38 -0
  212. package/plugins/pstack/skills/reflect/references/judgment-reviewer.md +37 -0
  213. package/plugins/pstack/skills/reflect/references/synthesizer.md +56 -0
  214. package/plugins/pstack/skills/reflect/references/tooling-reviewer.md +48 -0
  215. package/plugins/pstack/skills/reflect/scripts/claude-project-dir.mjs +121 -0
  216. package/plugins/pstack/skills/reflect/scripts/find-transcript.mjs +218 -0
  217. package/plugins/pstack/skills/setup-pstack/SKILL.md +109 -0
  218. package/plugins/pstack/skills/setup-pstack/copilot.md +88 -0
  219. package/plugins/pstack/skills/setup-pstack/references/runtimes.md +75 -0
  220. package/plugins/pstack/skills/setup-pstack/scripts/check-sheet.awk +10 -0
  221. package/plugins/pstack/skills/setup-pstack/scripts/check-sheet.sh +20 -0
  222. package/plugins/pstack/skills/setup-pstack/scripts/read-sheet.sh +24 -0
  223. package/plugins/pstack/skills/setup-pstack/scripts/sheet.awk +160 -0
  224. package/plugins/pstack/skills/sharpen/SKILL.md +15 -0
  225. package/plugins/pstack/skills/show-me-your-work/SKILL.md +89 -0
  226. package/plugins/pstack/skills/show-me-your-work/references/decision-log-template.tsv +1 -0
  227. package/plugins/pstack/skills/show-me-your-work/scripts/log.sh +58 -0
  228. package/plugins/pstack/skills/statechart/SKILL.md +81 -0
  229. package/plugins/pstack/skills/statechart/references/render.md +93 -0
  230. package/plugins/pstack/skills/statechart/scripts/backends/cfg.ts +33 -0
  231. package/plugins/pstack/skills/statechart/scripts/backends/mermaid.ts +201 -0
  232. package/plugins/pstack/skills/statechart/scripts/backends/plain-text.ts +72 -0
  233. package/plugins/pstack/skills/statechart/scripts/backends/report.ts +177 -0
  234. package/plugins/pstack/skills/statechart/scripts/bun.lock +17 -0
  235. package/plugins/pstack/skills/statechart/scripts/frontends/config.ts +276 -0
  236. package/plugins/pstack/skills/statechart/scripts/frontends/dot.ts +74 -0
  237. package/plugins/pstack/skills/statechart/scripts/frontends/marks.ts +93 -0
  238. package/plugins/pstack/skills/statechart/scripts/frontends/messages.ts +52 -0
  239. package/plugins/pstack/skills/statechart/scripts/frontends/spec.ts +114 -0
  240. package/plugins/pstack/skills/statechart/scripts/frontends/trace.ts +24 -0
  241. package/plugins/pstack/skills/statechart/scripts/frontends/value.ts +166 -0
  242. package/plugins/pstack/skills/statechart/scripts/frontends/verdict.ts +40 -0
  243. package/plugins/pstack/skills/statechart/scripts/frontends/view.ts +119 -0
  244. package/plugins/pstack/skills/statechart/scripts/ir.ts +547 -0
  245. package/plugins/pstack/skills/statechart/scripts/janitor.ts +12 -0
  246. package/plugins/pstack/skills/statechart/scripts/package.json +11 -0
  247. package/plugins/pstack/skills/statechart/scripts/passes/annotate.ts +128 -0
  248. package/plugins/pstack/skills/statechart/scripts/passes/label.ts +269 -0
  249. package/plugins/pstack/skills/statechart/scripts/passes/lift.ts +85 -0
  250. package/plugins/pstack/skills/statechart/scripts/passes/loop-check.ts +68 -0
  251. package/plugins/pstack/skills/statechart/scripts/passes/paths.ts +60 -0
  252. package/plugins/pstack/skills/statechart/scripts/passes/reach.ts +135 -0
  253. package/plugins/pstack/skills/statechart/scripts/passes/region-check.ts +97 -0
  254. package/plugins/pstack/skills/statechart/scripts/passes/regions.ts +295 -0
  255. package/plugins/pstack/skills/statechart/scripts/pipeline.ts +76 -0
  256. package/plugins/pstack/skills/statechart/scripts/run.ts +526 -0
  257. package/plugins/pstack/skills/statechart/scripts/statechart +29 -0
  258. package/plugins/pstack/skills/statechart/scripts/statechart.ts +171 -0
  259. package/plugins/pstack/skills/statechart/scripts/test/ConfigOracle.java +63 -0
  260. package/plugins/pstack/skills/statechart/scripts/test/chart.test.ts +1210 -0
  261. package/plugins/pstack/skills/statechart/scripts/test/charts/Braces.mmd +7 -0
  262. package/plugins/pstack/skills/statechart/scripts/test/charts/Escapes.mmd +11 -0
  263. package/plugins/pstack/skills/statechart/scripts/test/charts/Phases.mmd +29 -0
  264. package/plugins/pstack/skills/statechart/scripts/test/child-env.test.ts +15 -0
  265. package/plugins/pstack/skills/statechart/scripts/test/cli.test.ts +1323 -0
  266. package/plugins/pstack/skills/statechart/scripts/test/config-fuzz.test.ts +263 -0
  267. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/ChartRun.out +57 -0
  268. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/Counter.cfg +3 -0
  269. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/Counter.tla +10 -0
  270. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/chart.mmd +9 -0
  271. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/graph.dot +16 -0
  272. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/report.md +7 -0
  273. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/sany.out +2 -0
  274. package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/verdict-1.out +49 -0
  275. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/ChartRun.out +60 -0
  276. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.cfg +4 -0
  277. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.tla +22 -0
  278. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/chart.mmd +26 -0
  279. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/graph.dot +19 -0
  280. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/report.md +20 -0
  281. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/sany.out +2 -0
  282. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.exit +1 -0
  283. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.out +56 -0
  284. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.exit +1 -0
  285. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.out +82 -0
  286. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-3.out +57 -0
  287. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/ChartRun.out +59 -0
  288. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.cfg +3 -0
  289. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.tla +11 -0
  290. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/chart.mmd +22 -0
  291. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/graph.dot +16 -0
  292. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/report.md +17 -0
  293. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/sany.out +2 -0
  294. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.exit +1 -0
  295. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.out +56 -0
  296. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.exit +1 -0
  297. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.out +77 -0
  298. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/ChartRun.out +69 -0
  299. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.cfg +2 -0
  300. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.tla +11 -0
  301. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/chart.mmd +85 -0
  302. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/graph.dot +70 -0
  303. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/report.md +12 -0
  304. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/sany.out +2 -0
  305. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.exit +1 -0
  306. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.out +67 -0
  307. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-2.out +57 -0
  308. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.exit +1 -0
  309. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.out +85 -0
  310. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.cfg +6 -0
  311. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.tla +13 -0
  312. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/chart.mmd +5 -0
  313. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/graph.dot +10 -0
  314. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/report.md +31 -0
  315. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/sany.out +2 -0
  316. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.exit +1 -0
  317. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.out +64 -0
  318. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.exit +1 -0
  319. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.out +77 -0
  320. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/ChartRun.out +55 -0
  321. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.cfg +3 -0
  322. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.tla +10 -0
  323. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/chart.mmd +12 -0
  324. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/graph.dot +6 -0
  325. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/report.md +12 -0
  326. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/sany.out +2 -0
  327. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.exit +1 -0
  328. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.out +33 -0
  329. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-2.out +54 -0
  330. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/ChartRun.out +54 -0
  331. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.cfg +3 -0
  332. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.tla +10 -0
  333. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/chart.mmd +1 -0
  334. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/graph.dot +6 -0
  335. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/report.md +7 -0
  336. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/sany.out +2 -0
  337. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/verdict-1.out +46 -0
  338. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/ChartRun.out +59 -0
  339. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.cfg +2 -0
  340. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.tla +10 -0
  341. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterSteps.tla +6 -0
  342. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/chart.mmd +17 -0
  343. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/graph.dot +15 -0
  344. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/report.md +14 -0
  345. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/sany.out +3 -0
  346. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.exit +1 -0
  347. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.out +78 -0
  348. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/ChartRun.out +59 -0
  349. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.cfg +3 -0
  350. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.tla +19 -0
  351. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/chart.mmd +26 -0
  352. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/graph.dot +22 -0
  353. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/report.md +12 -0
  354. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/sany.out +2 -0
  355. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.exit +1 -0
  356. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.out +58 -0
  357. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-2.out +57 -0
  358. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/ChartRun.out +57 -0
  359. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.cfg +2 -0
  360. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.tla +11 -0
  361. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/chart.mmd +17 -0
  362. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/graph.dot +15 -0
  363. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/report.md +14 -0
  364. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/sany.out +2 -0
  365. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.exit +1 -0
  366. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.out +76 -0
  367. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/ChartRun.out +59 -0
  368. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.cfg +3 -0
  369. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.tla +11 -0
  370. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/chart.mmd +19 -0
  371. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/graph.dot +10 -0
  372. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/report.md +15 -0
  373. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/sany.out +2 -0
  374. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.exit +1 -0
  375. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.out +56 -0
  376. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.exit +1 -0
  377. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.out +67 -0
  378. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/ChartRun.out +62 -0
  379. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.cfg +6 -0
  380. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.tla +24 -0
  381. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/Moves.tla +5 -0
  382. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/chart.mmd +22 -0
  383. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/graph.dot +10 -0
  384. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/report.md +23 -0
  385. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/sany.out +3 -0
  386. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.exit +1 -0
  387. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.out +58 -0
  388. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.exit +1 -0
  389. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.out +66 -0
  390. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.exit +1 -0
  391. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.out +74 -0
  392. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-4.out +59 -0
  393. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/ChartRun.out +58 -0
  394. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.cfg +3 -0
  395. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.tla +15 -0
  396. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/chart.mmd +18 -0
  397. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/graph.dot +13 -0
  398. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/report.md +11 -0
  399. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/sany.out +2 -0
  400. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.exit +1 -0
  401. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.out +33 -0
  402. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-2.out +57 -0
  403. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/ChartRun.out +57 -0
  404. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.cfg +3 -0
  405. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.tla +15 -0
  406. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/chart.mmd +7 -0
  407. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/graph.dot +13 -0
  408. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/report.md +6 -0
  409. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/sany.out +2 -0
  410. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/verdict-1.out +49 -0
  411. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/ChartRun.out +61 -0
  412. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.cfg +4 -0
  413. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.tla +14 -0
  414. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/chart.mmd +30 -0
  415. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/graph.dot +19 -0
  416. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/report.md +27 -0
  417. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/sany.out +2 -0
  418. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.exit +1 -0
  419. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.out +56 -0
  420. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.exit +1 -0
  421. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.out +64 -0
  422. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.exit +1 -0
  423. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.out +87 -0
  424. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-4.out +57 -0
  425. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/ChartRun.out +60 -0
  426. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.cfg +3 -0
  427. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.tla +12 -0
  428. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/chart.mmd +23 -0
  429. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/graph.dot +19 -0
  430. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/report.md +11 -0
  431. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/sany.out +2 -0
  432. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.exit +1 -0
  433. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.out +56 -0
  434. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-2.out +57 -0
  435. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/ChartRun.out +61 -0
  436. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/CounterView.cfg +4 -0
  437. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/CounterView.tla +14 -0
  438. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/chart.mmd +23 -0
  439. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/graph.dot +19 -0
  440. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/report.md +27 -0
  441. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/sany.out +2 -0
  442. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-1.exit +1 -0
  443. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-1.out +56 -0
  444. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-2.exit +1 -0
  445. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-2.out +64 -0
  446. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-3.exit +1 -0
  447. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-3.out +87 -0
  448. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-4.out +57 -0
  449. package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/view.mjs +1 -0
  450. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/ChartRun.out +59 -0
  451. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/DieHard.cfg +4 -0
  452. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/DieHard.tla +38 -0
  453. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/chart.mmd +92 -0
  454. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/graph.dot +126 -0
  455. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/report.md +17 -0
  456. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/sany.out +2 -0
  457. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-1.exit +1 -0
  458. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-1.out +91 -0
  459. package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-2.out +57 -0
  460. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/ChartRun.out +61 -0
  461. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.cfg +6 -0
  462. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.tla +11 -0
  463. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/chart.mmd +22 -0
  464. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/graph.dot +16 -0
  465. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/report.md +25 -0
  466. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/sany.out +2 -0
  467. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.exit +1 -0
  468. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.out +56 -0
  469. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.exit +1 -0
  470. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.out +64 -0
  471. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.exit +1 -0
  472. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.out +64 -0
  473. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.exit +1 -0
  474. package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.out +77 -0
  475. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/ChartRun.out +57 -0
  476. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.cfg +4 -0
  477. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.tla +11 -0
  478. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/chart.mmd +13 -0
  479. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/graph.dot +12 -0
  480. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/report.md +11 -0
  481. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/sany.out +2 -0
  482. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.exit +1 -0
  483. package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.out +72 -0
  484. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/ChartRun.out +57 -0
  485. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/Login.cfg +3 -0
  486. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/Login.tla +62 -0
  487. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/chart.mmd +27 -0
  488. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/graph.dot +40 -0
  489. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/report.md +7 -0
  490. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/sany.out +1 -0
  491. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/verdict-1.out +47 -0
  492. package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/view.mjs +1 -0
  493. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/ChartRun.out +57 -0
  494. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.cfg +2 -0
  495. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.tla +64 -0
  496. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/chart.mmd +28 -0
  497. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/graph.dot +37 -0
  498. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/report.md +8 -0
  499. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/sany.out +1 -0
  500. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/verdict-1.out +47 -0
  501. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/view.mjs +1 -0
  502. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/ChartRun.out +60 -0
  503. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.cfg +3 -0
  504. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.tla +64 -0
  505. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/chart.mmd +44 -0
  506. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/graph.dot +58 -0
  507. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/report.md +17 -0
  508. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/sany.out +1 -0
  509. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.exit +1 -0
  510. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.out +83 -0
  511. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-2.out +57 -0
  512. package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/view.mjs +1 -0
  513. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/ChartRun.out +60 -0
  514. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.cfg +3 -0
  515. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.tla +103 -0
  516. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/chart.mmd +43 -0
  517. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/graph.dot +93 -0
  518. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/report.md +14 -0
  519. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/sany.out +1 -0
  520. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.exit +1 -0
  521. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.out +59 -0
  522. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-2.out +72 -0
  523. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/view.mjs +3 -0
  524. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/ChartRun.out +57 -0
  525. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.cfg +2 -0
  526. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.tla +100 -0
  527. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/chart.mmd +31 -0
  528. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/graph.dot +85 -0
  529. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/report.md +9 -0
  530. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/sany.out +1 -0
  531. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/verdict-1.out +47 -0
  532. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/view.mjs +3 -0
  533. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/ChartRun.out +59 -0
  534. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayer.tla +103 -0
  535. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.cfg +3 -0
  536. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.tla +6 -0
  537. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/chart.mmd +42 -0
  538. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/graph.dot +93 -0
  539. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/report.md +19 -0
  540. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/sany.out +2 -0
  541. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.exit +1 -0
  542. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.out +61 -0
  543. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-2.out +59 -0
  544. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-3.out +61 -0
  545. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.exit +1 -0
  546. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.out +66 -0
  547. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.exit +1 -0
  548. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.out +58 -0
  549. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-6.out +49 -0
  550. package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/view.mjs +3 -0
  551. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/ChartRun.out +57 -0
  552. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.cfg +6 -0
  553. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.tla +11 -0
  554. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/chart.mmd +5 -0
  555. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/graph.dot +11 -0
  556. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/report.md +7 -0
  557. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/sany.out +5 -0
  558. package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/verdict-1.out +70 -0
  559. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ChartRun.out +61 -0
  560. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/Shadow.cfg +4 -0
  561. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/Shadow.tla +11 -0
  562. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ShadowLib.tla +6 -0
  563. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ShadowSub.tla +3 -0
  564. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/chart.mmd +9 -0
  565. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/graph.dot +16 -0
  566. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/report.md +8 -0
  567. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/sany.out +4 -0
  568. package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/verdict-1.out +65 -0
  569. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/ChartRun.out +59 -0
  570. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.cfg +2 -0
  571. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.tla +9 -0
  572. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/chart.mmd +23 -0
  573. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/graph.dot +17 -0
  574. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/report.md +15 -0
  575. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/sany.out +1 -0
  576. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.exit +1 -0
  577. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.out +65 -0
  578. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.exit +1 -0
  579. package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.out +75 -0
  580. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/ChartRun.out +69 -0
  581. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.cfg +3 -0
  582. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.tla +75 -0
  583. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/chart.mmd +60 -0
  584. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/graph.dot +297 -0
  585. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/report.md +20 -0
  586. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/sany.out +1 -0
  587. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.exit +1 -0
  588. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.out +95 -0
  589. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-2.out +57 -0
  590. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/view.mjs +1 -0
  591. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/ChartRun.out +57 -0
  592. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.cfg +3 -0
  593. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.tla +75 -0
  594. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/chart.mmd +37 -0
  595. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/graph.dot +223 -0
  596. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/report.md +11 -0
  597. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/sany.out +1 -0
  598. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/verdict-1.out +47 -0
  599. package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/view.mjs +1 -0
  600. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.exit +1 -0
  601. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.out +75 -0
  602. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.cfg +5 -0
  603. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.tla +11 -0
  604. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/chart.mmd +18 -0
  605. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/graph.dot +14 -0
  606. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/report.md +29 -0
  607. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/sany.out +2 -0
  608. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.exit +1 -0
  609. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.out +64 -0
  610. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.exit +1 -0
  611. package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.out +75 -0
  612. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/ChartRun.out +58 -0
  613. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.cfg +2 -0
  614. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.tla +8 -0
  615. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/chart.mmd +22 -0
  616. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/graph.dot +16 -0
  617. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/report.md +15 -0
  618. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/sany.out +2 -0
  619. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.exit +1 -0
  620. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.out +56 -0
  621. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.exit +1 -0
  622. package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.out +77 -0
  623. package/plugins/pstack/skills/statechart/scripts/test/corpus.test.ts +415 -0
  624. package/plugins/pstack/skills/statechart/scripts/test/differential.test.ts +565 -0
  625. package/plugins/pstack/skills/statechart/scripts/test/grid/Grid.cfg +2 -0
  626. package/plugins/pstack/skills/statechart/scripts/test/grid/Grid.tla +9 -0
  627. package/plugins/pstack/skills/statechart/scripts/test/grid/sany.out +2 -0
  628. package/plugins/pstack/skills/statechart/scripts/test/java.ts +63 -0
  629. package/plugins/pstack/skills/statechart/scripts/test/labels.ts +643 -0
  630. package/plugins/pstack/skills/statechart/scripts/test/messages.test.ts +227 -0
  631. package/plugins/pstack/skills/statechart/scripts/test/pipeline.test.ts +270 -0
  632. package/plugins/pstack/skills/statechart/scripts/test/plain-tlc.test.ts +255 -0
  633. package/plugins/pstack/skills/statechart/scripts/test/render.test.ts +81 -0
  634. package/plugins/pstack/skills/statechart/scripts/test/tlc-out.test.ts +90 -0
  635. package/plugins/pstack/skills/statechart/scripts/test/tlc.ts +158 -0
  636. package/plugins/pstack/skills/statechart/scripts/tsconfig.json +11 -0
  637. package/plugins/pstack/skills/statechart/scripts/worker.ts +35 -0
  638. package/plugins/pstack/skills/swarm/SKILL.md +58 -0
  639. package/plugins/pstack/skills/tdd/SKILL.md +41 -0
  640. package/plugins/pstack/skills/teach/SKILL.md +28 -0
  641. package/plugins/pstack/skills/technical-writing/SKILL.md +105 -0
  642. package/plugins/pstack/skills/thermo-nuclear-code-quality-review/SKILL.md +201 -0
  643. package/plugins/pstack/skills/thermo-nuclear-review/SKILL.md +50 -0
  644. package/plugins/pstack/skills/thermos/SKILL.md +40 -0
  645. package/plugins/pstack/skills/typescript-best-practices/SKILL.md +32 -0
  646. package/plugins/pstack/skills/typescript-best-practices/references/patterns.md +328 -0
  647. package/plugins/pstack/skills/unslop/SKILL.md +61 -0
  648. package/plugins/pstack/skills/what-did-i-get-done/SKILL.md +31 -0
  649. package/plugins/pstack/skills/why/SKILL.md +116 -0
  650. package/plugins/pstack/skills/why/references/epistemics.md +79 -0
  651. package/plugins/pstack/skills/why/references/investigator-prompt.md +86 -0
  652. package/plugins/pstack/skills/why/references/source-playbook.md +17 -0
  653. package/plugins/pstack/skills/why/references/sources/code-archaeology.md +51 -0
  654. package/plugins/pstack/skills/why/references/sources/databricks.md +70 -0
  655. package/plugins/pstack/skills/why/references/sources/datadog.md +97 -0
  656. package/plugins/pstack/skills/why/references/sources/incident-postmortem.md +5 -0
  657. package/plugins/pstack/skills/why/references/sources/linear.md +48 -0
  658. package/plugins/pstack/skills/why/references/sources/notion.md +55 -0
  659. package/plugins/pstack/skills/why/references/sources/sentry.md +66 -0
  660. package/plugins/pstack/skills/why/references/sources/slack.md +17 -0
  661. package/plugins/pstack/skills/why/references/synthesizer-prompt.md +130 -0
  662. package/tools/forks.json +398 -0
  663. package/tools/substitutions.json +646 -0
  664. package/tools/upstream.json +53 -0
@@ -0,0 +1,90 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+
3
+ import type { AgentRunner } from "./agents.ts";
4
+ import type { Settings } from "./config.ts";
5
+
6
+ const PENDING_POLL_MS = 50;
7
+
8
+ export interface OneShot {
9
+ exits(ctx: Pick<ExtensionContext, "mode">): boolean;
10
+ untilSettled(): Promise<void>;
11
+ assertStartsRun(prompt: string, ctx: ExtensionContext): Promise<void>;
12
+ dispose(): void;
13
+ }
14
+
15
+ // Why Pi would start no run for a prompt this extension sends, by the checks
16
+ // its prompt() makes first: an extension command runs in place, and a prompt
17
+ // without a model or credentials is refused. No settle follows either, and Pi
18
+ // reports a refusal only to its own error listeners, so a one-shot /loop
19
+ // waiting on the settle would never return. It cannot see an input handler
20
+ // that consumes the prompt.
21
+ async function noRunReason(pi: ExtensionAPI, prompt: string, ctx: ExtensionContext): Promise<string | undefined> {
22
+ if (prompt.startsWith("/")) {
23
+ const space = prompt.indexOf(" ");
24
+ const name = prompt.slice(1, space === -1 ? undefined : space);
25
+ if (pi.getCommands().some((command) => command.source === "extension" && command.name === name)) {
26
+ return `/${name} is an extension command, not a prompt`;
27
+ }
28
+ }
29
+ const model = ctx.model;
30
+ if (!model) return "no model is selected";
31
+ if (ctx.modelRegistry.hasConfiguredAuth(model)) return undefined;
32
+ const available = await ctx.modelRegistry.getAvailableOfType("chat", model.provider);
33
+ return available.length ? undefined : "the selected model has no credentials";
34
+ }
35
+
36
+ // Resolves once Pi has a queued message, which is the same condition Pi checks
37
+ // after agent_before_settle returns to decide whether the run continues.
38
+ function pendingMessage(ctx: ExtensionContext, signal: { done: boolean }): Promise<void> {
39
+ return new Promise((resolve) => {
40
+ const timer = setInterval(() => {
41
+ if (!signal.done && !ctx.hasPendingMessages()) return;
42
+ clearInterval(timer);
43
+ resolve();
44
+ }, PENDING_POLL_MS);
45
+ timer.unref();
46
+ });
47
+ }
48
+
49
+ // Everything that follows from "this process ends when the run settles":
50
+ // a background agent's notice would be lost, so the settle is held until one
51
+ // exits or a message arrives; /loop must wait for the run it started; a wakeup
52
+ // could never fire; Ctrl-C must take the children along, since pi's one SIGINT
53
+ // listener outside interactive mode is signal-exit's, which re-raises the signal
54
+ // and so skips the exit hook.
55
+ export function registerOneShot(pi: ExtensionAPI, settings: Settings, runner: Pick<AgentRunner, "nextExit">): OneShot {
56
+ // Print and json runs exit once the agent settles. A pstack child is an rpc
57
+ // process whose parent closes its stdin at the same moment, so it is one-shot too.
58
+ const exits = (ctx: Pick<ExtensionContext, "mode">) => ctx.mode === "print" || ctx.mode === "json" || settings.depth > 0;
59
+ const settleWaiters: (() => void)[] = [];
60
+ const settle = () => {
61
+ for (const resolve of settleWaiters.splice(0)) resolve();
62
+ };
63
+ // The exit hook in index.ts signals the children.
64
+ const onSigint = () => process.exit(130);
65
+ pi.on("session_start", (_event, ctx) => {
66
+ if (exits(ctx) && !process.listeners("SIGINT").includes(onSigint)) process.on("SIGINT", onSigint);
67
+ });
68
+ pi.on("agent_before_settle", async (_event, ctx) => {
69
+ if (!exits(ctx) || ctx.hasPendingMessages()) return;
70
+ const signal = { done: false };
71
+ await Promise.race([runner.nextExit(), pendingMessage(ctx, signal)]);
72
+ signal.done = true;
73
+ });
74
+ pi.on("agent_settled", settle);
75
+ return {
76
+ exits,
77
+ untilSettled: () => new Promise<void>((resolve) => settleWaiters.push(resolve)),
78
+ assertStartsRun: async (prompt, ctx) => {
79
+ const reason = await noRunReason(pi, prompt, ctx);
80
+ if (reason === undefined) return;
81
+ // Pi prints a command handler's throw and still exits 0.
82
+ process.exitCode = 1;
83
+ throw new Error(`No run would start: ${reason}`);
84
+ },
85
+ dispose: () => {
86
+ process.off("SIGINT", onSigint);
87
+ settle();
88
+ },
89
+ };
90
+ }
@@ -0,0 +1,54 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { isAbsolute, join, matchesGlob, relative, resolve } from "node:path";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
+
5
+ import { frontmatter } from "./agent-files.ts";
6
+ import type { Settings } from "./config.ts";
7
+
8
+ const FILE_TOOLS = new Set(["read", "edit", "write"]);
9
+
10
+ interface PathSkill {
11
+ name: string;
12
+ file: string;
13
+ globs: string[];
14
+ }
15
+
16
+ function parsePaths(file: string, globs: unknown): string[] {
17
+ if (Array.isArray(globs) && globs.every((g): g is string => typeof g === "string")) return globs;
18
+ throw new Error(`${file}: paths must be a JSON array of globs`);
19
+ }
20
+
21
+ // Skills whose frontmatter names `paths:` globs, the files that should load them.
22
+ function pathSkills(pluginRoot: string): PathSkill[] {
23
+ const dir = join(pluginRoot, "skills");
24
+ if (!existsSync(dir)) return [];
25
+ const skills: PathSkill[] = [];
26
+ for (const name of readdirSync(dir).sort()) {
27
+ const file = join(dir, name, "SKILL.md");
28
+ if (!existsSync(file)) continue;
29
+ const globs = frontmatter(readFileSync(file, "utf8")).fields.paths;
30
+ if (globs != null) skills.push({ name, file, globs: parsePaths(file, globs) });
31
+ }
32
+ return skills;
33
+ }
34
+
35
+ // Claude Code loads a skill with `paths:` when a matching file is touched; Pi
36
+ // has no such hook, so the first matching tool result carries a note instead.
37
+ export function registerPathSkills(pi: ExtensionAPI, settings: Settings): void {
38
+ const skills = pathSkills(settings.pluginRoot);
39
+ const noted = new Set<string>();
40
+ pi.on("tool_result", (event, ctx) => {
41
+ if (!FILE_TOOLS.has(event.toolName) || event.isError) return;
42
+ const raw = event.input.path;
43
+ if (typeof raw !== "string") return;
44
+ const rel = relative(ctx.cwd, isAbsolute(raw) ? raw : resolve(ctx.cwd, raw)).split("\\").join("/");
45
+ const skill = skills.find((s) => !noted.has(s.name) && s.globs.some((g) => matchesGlob(rel, g)));
46
+ if (!skill) return;
47
+ noted.add(skill.name);
48
+ const note = `pstack: ${rel} matches the ${skill.name} skill's paths. Load that skill now (read ${skill.file}) and follow it while you work on this file.`;
49
+ return {
50
+ content: [...event.content, { type: "text", text: note }],
51
+ structuredContent: event.structuredContent,
52
+ };
53
+ });
54
+ }
@@ -0,0 +1,39 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
+
5
+ import { readSheet, type Settings } from "./config.ts";
6
+
7
+ const MANDATE_SECTION = "pstack-session-start";
8
+ const SHEET_SECTION = "pstack-models";
9
+ const PARALLEL_SECTION = "pstack-parallel-calls";
10
+ const TOOLS_SECTION = "pstack-pi-tools";
11
+
12
+ // pstack skills name Claude Code tools and models. A session with the hook off,
13
+ // a child agent, or a skill invoked directly may never see the pointer in
14
+ // poteto-mode/SKILL.md, so every session gets it here.
15
+ function piToolsNote(pluginRoot: string): string {
16
+ const file = join(pluginRoot, "skills", "poteto-mode", "references", "pi-tools.md");
17
+ return `pstack skills are written for Claude Code. When one names a Claude Code tool (Agent, Skill, AskUserQuestion, Bash), a bundled skill, or a Claude model, read ${file} for the Pi equivalent before following it.`;
18
+ }
19
+ // Claude Code's system prompt, word for word but for its function_calls block.
20
+ // pstack skills that say "one message, N Agent calls" rely on it.
21
+ const PARALLEL_CALLS =
22
+ "If you intend to call multiple tools and there are no dependencies between the calls, make all of the independent calls in the same response, otherwise you MUST wait for previous calls to finish first to determine the dependent values.";
23
+
24
+ // Claude Code runs the session hook and loads the sheet through a CLAUDE.md
25
+ // include; Pi has neither, so both ride as system prompt sections, set again
26
+ // on every agent start so compaction cannot drop them.
27
+ // A child gets the sheet, as a Claude Code subagent sees CLAUDE.md, but not
28
+ // the mandate: SessionStart does not run for subagents.
29
+ export function registerPromptSections(pi: ExtensionAPI, settings: Settings): void {
30
+ const mandateFile = join(settings.pluginRoot, "hooks", "session-start-context.md");
31
+ pi.on("before_agent_start", (event) => {
32
+ const sheet = readSheet(settings.agentDir);
33
+ const sections = event.systemPromptOptions.sections;
34
+ sections[PARALLEL_SECTION] = PARALLEL_CALLS;
35
+ sections[TOOLS_SECTION] = piToolsNote(settings.pluginRoot);
36
+ if (settings.depth === 0 && !sheet?.hookOff) sections[MANDATE_SECTION] = readFileSync(mandateFile, "utf8");
37
+ if (sheet) sections[SHEET_SECTION] = sheet.text;
38
+ });
39
+ }
@@ -0,0 +1,254 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { Type } from "typebox";
3
+
4
+ import type { OneShot } from "./one-shot.ts";
5
+ import { expandSlash } from "./slash.ts";
6
+
7
+ const MIN_DELAY_S = 60;
8
+ const MAX_DELAY_S = 3600;
9
+ // setInterval treats a delay above 2^31-1 ms as 1 ms.
10
+ const MAX_LOOP_S = 24 * 86400;
11
+ const IDLE_RETRY_MS = 1000;
12
+ // Text the agent chose (a schedule_wakeup prompt, and what a loop it re-arms sends) goes in as a custom
13
+ // message, not a user message. The permission classifier reads user-role messages as what the user asked
14
+ // for, so a user message here would let the agent write its own permission.
15
+ const AGENT_PROMPT_TYPE = "pstack-wakeup";
16
+ const LOOP_COMMAND = /^\/loop(?:\s+([\s\S]*))?$/;
17
+ type Send = (prompt: string) => void;
18
+
19
+ const errorText = (e: unknown) => (e instanceof Error ? e.message : String(e));
20
+
21
+ const wakeupParams = Type.Object({
22
+ delaySeconds: Type.Optional(Type.Number({ description: `Seconds until the wakeup (${MIN_DELAY_S}-${MAX_DELAY_S})` })),
23
+ prompt: Type.Optional(Type.String({ description: "The prompt to run when the wakeup fires" })),
24
+ reason: Type.Optional(Type.String({ description: "Why this delay, in one short sentence" })),
25
+ noop: Type.Optional(Type.Boolean({ description: "Mark this wakeup as a routine check; it is scheduled all the same" })),
26
+ stop: Type.Optional(Type.Boolean({ description: "Cancel the pending wakeup; no other field is needed" })),
27
+ });
28
+
29
+ // One pending wakeup, one fixed-interval loop, and one live self-paced loop per
30
+ // session. A due wakeup or loop tick runs the delivery its caller chose, at
31
+ // once when the agent is idle.
32
+ export class Scheduler {
33
+ private wakeup?: NodeJS.Timeout;
34
+ private loop?: NodeJS.Timeout;
35
+ // A self-paced loop has no timer of its own while its iteration runs, so
36
+ // this is what /loop stop finds then.
37
+ private selfPaced = false;
38
+ // Set by a /loop command that ends or replaces the loop while a run is in
39
+ // flight, until that run settles. A schedule_wakeup call names no loop, so
40
+ // nothing tells that run's re-arm of the old loop from any other wakeup. It
41
+ // is refused them all, or the loop the user just ended would come back.
42
+ sealed = false;
43
+ // A run is in flight: set by agent_start, cleared by agent_settled. Not
44
+ // ctx.isIdle(), which is also false during a manual compaction.
45
+ running = false;
46
+
47
+ scheduleWakeup(seconds: number, deliver: () => void, ctx: ExtensionContext): void {
48
+ this.cancelWakeup();
49
+ const due = () => {
50
+ // Pi rejects prompts during manual compaction. Keep the wakeup pending
51
+ // until idle, including while a run or compaction is still finishing.
52
+ if (!ctx.isIdle()) {
53
+ this.wakeup = setTimeout(due, IDLE_RETRY_MS).unref();
54
+ return;
55
+ }
56
+ this.wakeup = undefined;
57
+ deliver();
58
+ };
59
+ this.wakeup = setTimeout(due, seconds * 1000);
60
+ this.wakeup.unref();
61
+ }
62
+
63
+ cancelWakeup(): boolean {
64
+ const had = this.wakeup !== undefined;
65
+ clearTimeout(this.wakeup);
66
+ this.wakeup = undefined;
67
+ return had;
68
+ }
69
+
70
+ startLoop(seconds: number, tick: () => void, ctx: ExtensionContext): void {
71
+ // A tick that lands mid-run is dropped, so a slow iteration cannot pile up a backlog.
72
+ this.loop = setInterval(() => ctx.isIdle() && tick(), seconds * 1000);
73
+ this.loop.unref();
74
+ }
75
+
76
+ private stopLoop(): boolean {
77
+ const had = this.loop !== undefined;
78
+ clearInterval(this.loop);
79
+ this.loop = undefined;
80
+ return had;
81
+ }
82
+
83
+ startSelfPaced(): void {
84
+ this.selfPaced = true;
85
+ }
86
+
87
+ // Ends the loop and the pending wakeup. midRun says a run is in flight,
88
+ // which seals the wakeup slot against it.
89
+ stopAll(midRun = false): boolean {
90
+ const wakeup = this.cancelWakeup();
91
+ const selfPaced = this.selfPaced;
92
+ this.selfPaced = false;
93
+ if (midRun) this.sealed = true;
94
+ return this.stopLoop() || wakeup || selfPaced;
95
+ }
96
+ }
97
+
98
+ function clampDelay(seconds: number): number {
99
+ return Math.min(MAX_DELAY_S, Math.max(MIN_DELAY_S, Math.round(seconds)));
100
+ }
101
+
102
+ const UNIT_SECONDS: Record<string, number> = { s: 1, m: 60, h: 3600, d: 86400 };
103
+
104
+ type LoopCommand =
105
+ | { kind: "stop" }
106
+ | { kind: "usage"; reason?: string }
107
+ | { kind: "fixed"; seconds: number; prompt: string }
108
+ | { kind: "dynamic"; prompt: string };
109
+
110
+ function parseLoop(args: string): LoopCommand {
111
+ const text = args.trim();
112
+ if (!text) return { kind: "usage" };
113
+ if (text === "stop") return { kind: "stop" };
114
+ const m = /^(\d+)([smhd])(?:\s+([\s\S]+))?$/.exec(text);
115
+ if (m) {
116
+ const seconds = Number(m[1]) * UNIT_SECONDS[m[2]];
117
+ if (!m[3]) return { kind: "usage" };
118
+ if (seconds > MAX_LOOP_S) return { kind: "usage", reason: "Intervals over 24 days are not supported." };
119
+ return { kind: "fixed", seconds, prompt: m[3].trim() };
120
+ }
121
+ return { kind: "dynamic", prompt: text };
122
+ }
123
+
124
+ function dynamicPrompt(prompt: string): string {
125
+ return (
126
+ `${prompt}\n\n` +
127
+ `[/loop, self-paced] When this iteration is done, call schedule_wakeup with prompt "/loop ${prompt}" ` +
128
+ `and a delay that fits what you are waiting for (${MIN_DELAY_S} to ${MAX_DELAY_S} seconds) to run it again. ` +
129
+ `Skip the call to end the loop.`
130
+ );
131
+ }
132
+
133
+ // model-only exposure keeps the tool declared under codemode.mode "only".
134
+ export function registerSchedule(pi: ExtensionAPI, scheduler: Scheduler, oneShot: OneShot): void {
135
+ // The prompt's author picks the role: the user's /loop sends user messages, and text the agent chose
136
+ // goes in as a custom message, which the permission classifier does not read as the user's ask. Pi
137
+ // expands slash text only in a user message, so the agent's is expanded before it is sent.
138
+ const sendAsUser: Send = (prompt) => pi.sendUserMessage(prompt, { deliverAs: "followUp", expandPromptTemplates: true });
139
+ const sendAsAgent =
140
+ (ctx: ExtensionContext): Send =>
141
+ (prompt) => {
142
+ let content = prompt;
143
+ try {
144
+ content = expandSlash(pi.getCommands(), prompt);
145
+ } catch (e) {
146
+ ctx.ui.notify(`A wakeup's command could not be expanded and was sent as written: ${errorText(e)}`, "error");
147
+ }
148
+ pi.sendMessage({ customType: AGENT_PROMPT_TYPE, content, display: true }, { triggerTurn: true, deliverAs: "followUp" });
149
+ };
150
+
151
+ pi.registerTool({
152
+ name: "schedule_wakeup",
153
+ label: "Schedule wakeup",
154
+ exposure: "model-only",
155
+ description: `Schedule this session to be re-invoked with a prompt after delaySeconds (clamped to ${MIN_DELAY_S}-${MAX_DELAY_S}), once the session is idle. One wakeup is pending at a time: a new call replaces it, and stop: true cancels it. Used by /loop's self-paced mode.`,
156
+ parameters: wakeupParams,
157
+ async execute(_id, params, _signal, _onUpdate, ctx) {
158
+ if (params.stop) {
159
+ // What is pending in a sealed slot is a loop start the user asked for, not this run's.
160
+ const had = !scheduler.sealed && scheduler.cancelWakeup();
161
+ const text = had ? "Pending wakeup cancelled." : "No wakeup was pending.";
162
+ return { content: [{ type: "text", text }], details: { cancelled: had } };
163
+ }
164
+ if (params.delaySeconds === undefined || !params.prompt) {
165
+ throw new Error("schedule_wakeup needs delaySeconds and prompt unless stop is true.");
166
+ }
167
+ if (scheduler.sealed) {
168
+ ctx.ui.notify("A wakeup this run asked for was not scheduled: /loop ended or replaced the loop while it ran.", "warning");
169
+ return {
170
+ content: [{ type: "text", text: "Not scheduled: the user ended or replaced the loop with a /loop command during this run. Do not schedule another wakeup in this run." }],
171
+ details: { refused: true },
172
+ };
173
+ }
174
+ if (oneShot.exits(ctx)) {
175
+ throw new Error(`schedule_wakeup cannot fire in a ${ctx.mode} run: pi exits when this run ends. Finish the work in this run instead.`);
176
+ }
177
+ const seconds = clampDelay(params.delaySeconds);
178
+ // A custom message runs no command, so the agent's "/loop ..." re-arm runs the loop here.
179
+ const prompt = params.prompt;
180
+ const send = sendAsAgent(ctx);
181
+ const loop = LOOP_COMMAND.exec(prompt);
182
+ const deliver = loop
183
+ ? () => void runLoop(loop[1] ?? "", ctx, send).catch((e) => ctx.ui.notify(`/loop from a wakeup failed: ${errorText(e)}`, "error"))
184
+ : () => send(prompt);
185
+ scheduler.scheduleWakeup(seconds, deliver, ctx);
186
+ const fireAt = new Date(Date.now() + seconds * 1000).toISOString();
187
+ const clamped = seconds !== params.delaySeconds ? ` (clamped from ${params.delaySeconds})` : "";
188
+ return {
189
+ content: [{ type: "text", text: `Wakeup scheduled in ${seconds}s${clamped}, at ${fireAt}. It replaces any earlier pending wakeup.` }],
190
+ details: { delaySeconds: seconds, fireAt, noop: params.noop === true },
191
+ };
192
+ },
193
+ });
194
+
195
+ pi.on("agent_start", () => {
196
+ scheduler.running = true;
197
+ });
198
+ pi.on("agent_settled", () => {
199
+ scheduler.running = false;
200
+ scheduler.sealed = false;
201
+ });
202
+
203
+ async function runLoop(args: string, ctx: ExtensionContext, send: Send): Promise<void> {
204
+ const cmd = parseLoop(args);
205
+ // Also true during a manual compaction, which no run is behind: the first
206
+ // prompt then waits for idle, but only a run in flight seals the slot.
207
+ const midRun = !ctx.isIdle();
208
+ // sendUserMessage only starts the run, and a one-shot run disposes the
209
+ // session as soon as the command returns, so there the command waits it out.
210
+ const fire = async (prompt: string) => {
211
+ // The slot is sealed against the run in flight, so the loop's first
212
+ // prompt takes the slot and runs once that run has settled. Its own
213
+ // re-arm then comes from a later run and is not refused.
214
+ if (midRun) {
215
+ scheduler.scheduleWakeup(0, () => send(prompt), ctx);
216
+ ctx.ui.notify("The loop starts once the session is idle.", "info");
217
+ return;
218
+ }
219
+ if (!oneShot.exits(ctx)) {
220
+ send(prompt);
221
+ return;
222
+ }
223
+ await oneShot.assertStartsRun(prompt, ctx);
224
+ const settled = oneShot.untilSettled();
225
+ send(prompt);
226
+ await settled;
227
+ };
228
+ switch (cmd.kind) {
229
+ case "usage":
230
+ ctx.ui.notify(`${cmd.reason ? `${cmd.reason} ` : ""}Usage: /loop [interval like 5m or 1h] <prompt>, or /loop stop`, "info");
231
+ return;
232
+ case "stop":
233
+ ctx.ui.notify(scheduler.stopAll(scheduler.running) ? "Loop stopped." : "No loop was running.", "info");
234
+ return;
235
+ case "fixed": {
236
+ const seconds = Math.max(MIN_DELAY_S, cmd.seconds);
237
+ scheduler.stopAll(scheduler.running);
238
+ scheduler.startLoop(seconds, () => send(cmd.prompt), ctx);
239
+ ctx.ui.notify(`Looping every ${seconds}s. /loop stop ends it.`, "info");
240
+ await fire(cmd.prompt);
241
+ return;
242
+ }
243
+ case "dynamic":
244
+ scheduler.stopAll(scheduler.running);
245
+ scheduler.startSelfPaced();
246
+ await fire(dynamicPrompt(cmd.prompt));
247
+ }
248
+ }
249
+
250
+ pi.registerCommand("loop", {
251
+ description: "Run a prompt on an interval (/loop 5m <prompt>), self-paced (/loop <prompt>), or stop (/loop stop)",
252
+ handler: (args, ctx) => runLoop(args, ctx, sendAsUser),
253
+ });
254
+ }
@@ -0,0 +1,92 @@
1
+ import type { SlashCommandInfo } from "@earendil-works/pi-coding-agent";
2
+ import { readFileSync } from "node:fs";
3
+
4
+ // Pi expands "/skill:name args" and "/template args" only inside sendUserMessage, and its package exports
5
+ // none of the code that does it. This is that code from pi 1.4.0 (AgentSession._expandSkillCommand,
6
+ // dist/core/prompt-templates.js, and dist/utils/frontmatter.js), reading the files pi.getCommands() names,
7
+ // for text the extension sends as a custom message. tests/pi/slash.test.mjs checks it against the installed pi.
8
+
9
+ export function stripFrontmatter(content: string): string {
10
+ const normalized = content.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
11
+ if (!normalized.startsWith("---")) return normalized;
12
+ const endIndex = normalized.indexOf("\n---", 3);
13
+ return endIndex === -1 ? normalized : normalized.slice(endIndex + 4).trim();
14
+ }
15
+
16
+ // Splits on whitespace outside quotes; a quote ends at the next quote of the same kind, and "" is an argument.
17
+ export function parseCommandArgs(argsString: string): string[] {
18
+ const args: string[] = [];
19
+ let current = "";
20
+ let hasToken = false;
21
+ let inQuote: string | null = null;
22
+ for (const char of argsString) {
23
+ if (inQuote) {
24
+ if (char === inQuote) inQuote = null;
25
+ else current += char;
26
+ } else if (char === '"' || char === "'") {
27
+ inQuote = char;
28
+ hasToken = true;
29
+ } else if (/\s/.test(char)) {
30
+ if (hasToken) {
31
+ args.push(current);
32
+ current = "";
33
+ hasToken = false;
34
+ }
35
+ } else {
36
+ current += char;
37
+ hasToken = true;
38
+ }
39
+ }
40
+ if (hasToken) args.push(current);
41
+ return args;
42
+ }
43
+
44
+ // $1, $@, $ARGUMENTS, ${N:-default}, ${@:-default}, ${@:N} and ${@:N:L}. A value is not substituted again.
45
+ export function substituteArgs(content: string, args: string[]): string {
46
+ const allArgs = args.join(" ");
47
+ return content.replace(
48
+ /\$\{(\d+|ARGUMENTS|@):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g,
49
+ (_match, defaultTarget, defaultValue, sliceStart, sliceLength, simple) => {
50
+ if (defaultTarget) {
51
+ const value = defaultTarget === "@" || defaultTarget === "ARGUMENTS" ? allArgs : args[parseInt(defaultTarget, 10) - 1];
52
+ return value ? value : defaultValue;
53
+ }
54
+ if (sliceStart) {
55
+ const start = Math.max(0, parseInt(sliceStart, 10) - 1);
56
+ return (sliceLength ? args.slice(start, start + parseInt(sliceLength, 10)) : args.slice(start)).join(" ");
57
+ }
58
+ if (simple === "ARGUMENTS" || simple === "@") return allArgs;
59
+ return args[parseInt(simple, 10) - 1] ?? "";
60
+ },
61
+ );
62
+ }
63
+
64
+ function expandSkillCommand(commands: readonly SlashCommandInfo[], text: string): string {
65
+ if (!text.startsWith("/skill:")) return text;
66
+ const spaceIndex = text.indexOf(" ");
67
+ const name = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
68
+ const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
69
+ const skill = commands.find((c) => c.source === "skill" && c.name === name);
70
+ if (!skill) return text;
71
+ const { path, baseDir } = skill.sourceInfo;
72
+ const body = stripFrontmatter(readFileSync(path, "utf8")).trim();
73
+ const block = `<skill name="${name.slice("skill:".length)}" location="${path}">\nReferences are relative to ${baseDir}.\n\n${body}\n</skill>`;
74
+ return args ? `${block}\n\n${args}` : block;
75
+ }
76
+
77
+ function expandPromptTemplate(commands: readonly SlashCommandInfo[], text: string): string {
78
+ const match = /^\/([^\s]+)(?:\s+([\s\S]*))?$/.exec(text);
79
+ const template = match && commands.find((c) => c.source === "prompt" && c.name === match[1]);
80
+ if (!template) return text;
81
+ return substituteArgs(stripFrontmatter(readFileSync(template.sourceInfo.path, "utf8")), parseCommandArgs(match[2] ?? ""));
82
+ }
83
+
84
+ // The text a user message with this text would carry. A name pi has no skill or template for stays as written,
85
+ // and so does an extension command: pi runs one only from a user message, and the agent must not run one as the
86
+ // user. Throws when a command's file cannot be read, where pi reports the error and sends the text as written.
87
+ export function expandSlash(commands: readonly SlashCommandInfo[], text: string): string {
88
+ const spaceIndex = text.indexOf(" ");
89
+ const name = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
90
+ if (text.startsWith("/") && commands.some((c) => c.source === "extension" && c.name === name)) return text;
91
+ return expandPromptTemplate(commands, expandSkillCommand(commands, text));
92
+ }
@@ -0,0 +1,76 @@
1
+ // Whether a bash command line waits on a foreground `sleep`, the way a model
2
+ // polls for a background agent it should leave alone.
3
+ //
4
+ // A token rule, not a shell parser. After heredoc bodies, quoted strings, and
5
+ // comments are removed, the word `sleep` followed by a literal duration of
6
+ // MIN_WAIT_S or more blocks, anywhere in the line, unless that sleep itself is
7
+ // directly backgrounded (`sleep 30 &`, never `&&` or `&>`). It errs toward
8
+ // blocking: a wrongly blocked command costs one rephrased turn, a missed poll
9
+ // loop costs minutes. Known misses: a sleep inside a quoted script such as
10
+ // `bash -c 'sleep 30'`, a quoted duration (`sleep "30"`), a variable duration
11
+ // (`sleep $N`), and a poll loop of sleeps under two seconds. Known over-blocks:
12
+ // a sleep inside a backgrounded group (`(sleep 30; echo done) &`), a
13
+ // backgrounded sleep with a redirection before the `&`, and
14
+ // `timeout 5 sleep 30`. tests/pi/sleep-wait.test.mjs lists each, so changing
15
+ // one is a visible decision.
16
+ const MIN_WAIT_S = 2;
17
+ const SLEEP_UNITS: Record<string, number> = { "": 1, s: 1, m: 60, h: 3600, d: 86400 };
18
+
19
+ // Seconds a literal sleep argument asks for (30, 2.5, 1m, 1m30s, infinity);
20
+ // 0 when it is not a literal.
21
+ function sleepSeconds(arg: string): number {
22
+ if (/^inf(inity)?$/.test(arg)) return Infinity;
23
+ const parts = arg.match(/\d*\.?\d+[smhd]?/g);
24
+ if (!parts || parts.join("") !== arg) return 0;
25
+ return parts.reduce((sum, part) => {
26
+ const unit = /[smhd]$/.exec(part)?.[0] ?? "";
27
+ return sum + Number(part.slice(0, part.length - unit.length)) * SLEEP_UNITS[unit];
28
+ }, 0);
29
+ }
30
+
31
+ // One line with its quoted strings replaced by "" and a comment cut off, in a
32
+ // single left-to-right pass. An unterminated quote drops the rest of the line.
33
+ function stripQuotesAndComment(line: string): string {
34
+ let out = "";
35
+ let quote: string | undefined;
36
+ for (let i = 0; i < line.length; i++) {
37
+ const c = line[i];
38
+ if (quote) {
39
+ if (c === "\\" && quote === '"') i++;
40
+ else if (c === quote) {
41
+ quote = undefined;
42
+ out += '""';
43
+ }
44
+ } else if (c === "\\") {
45
+ out += c + (line[i + 1] ?? "");
46
+ i++;
47
+ } else if (c === '"' || c === "'") quote = c;
48
+ else if (c === "#" && (i === 0 || /\s/.test(line[i - 1]))) break;
49
+ else out += c;
50
+ }
51
+ return out;
52
+ }
53
+
54
+ // The command text the shell would run: heredoc bodies, quoted strings, and
55
+ // comments removed, one pass over the lines so the cost stays linear. The
56
+ // line that opens a heredoc is kept, since commands can follow the `<<`.
57
+ function shellText(command: string): string {
58
+ const kept: string[] = [];
59
+ let terminator: string | undefined;
60
+ for (const line of command.split("\n")) {
61
+ if (terminator !== undefined) {
62
+ if (line.trim() === terminator) terminator = undefined;
63
+ continue;
64
+ }
65
+ kept.push(stripQuotesAndComment(line));
66
+ terminator = /<<-?\s*(["']?)(\w+)\1/.exec(line)?.[2];
67
+ }
68
+ return kept.join("\n");
69
+ }
70
+
71
+ export function isForegroundWait(command: string): boolean {
72
+ for (const m of shellText(command).matchAll(/\bsleep\s+([^\s;|&()<>]+)\s*(&(?![&>]))?/g)) {
73
+ if (m[2] === undefined && sleepSeconds(m[1]) >= MIN_WAIT_S) return true;
74
+ }
75
+ return false;
76
+ }