@justjoshn/pi-pstack 0.0.0-stage → 0.15.36-pi.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (651) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -2
  3. package/agents/comment-sicko.md +32 -0
  4. package/agents/poteto-agent.md +9 -0
  5. package/automations/benny/FOR_AGENTS.md +82 -0
  6. package/automations/benny/README.md +20 -0
  7. package/automations/benny/skills/reproduce-and-fix-issues/SKILL.md +310 -0
  8. package/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md +169 -0
  9. package/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md +205 -0
  10. package/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md +93 -0
  11. package/automations/benny/skills/setup-benny/SKILL.md +253 -0
  12. package/automations/benny/skills/triage-issue-reports/SKILL.md +240 -0
  13. package/automations/benny/skills/triage-issue-reports/references/routing.example.md +61 -0
  14. package/automations/benny/templates/configuration.example.yaml +113 -0
  15. package/automations/benny/templates/reproduce-automation-prompt.md +49 -0
  16. package/automations/benny/templates/triage-automation-prompt.md +53 -0
  17. package/docs/guide/01-setup.md +67 -0
  18. package/docs/guide/02-poteto-mode.md +139 -0
  19. package/docs/guide/03-understand.md +79 -0
  20. package/docs/guide/04-design.md +133 -0
  21. package/docs/guide/05-build-and-clean.md +83 -0
  22. package/docs/guide/06-verify-and-ship.md +162 -0
  23. package/docs/guide/07-overnight.md +122 -0
  24. package/docs/guide/08-principles.md +72 -0
  25. package/docs/guide/09-make-it-yours.md +100 -0
  26. package/docs/guide/10-recipes-and-pitfalls.md +182 -0
  27. package/docs/guide/README.md +38 -0
  28. package/docs/guide/images/design.jpg +0 -0
  29. package/docs/guide/images/overnight.jpg +0 -0
  30. package/docs/guide/images/recipes.jpg +0 -0
  31. package/docs/guide/images/router.jpg +0 -0
  32. package/docs/guide/images/understanding.jpg +0 -0
  33. package/docs/guide/images/verification.jpg +0 -0
  34. package/docs/native-gaps.md +67 -0
  35. package/licenses/cursor-team-kit.LICENSE +21 -0
  36. package/licenses/pstack.LICENSE +21 -0
  37. package/package.json +51 -4
  38. package/scripts/live-e2e.mjs +257 -0
  39. package/skills/architect/SKILL.md +79 -0
  40. package/skills/architect/references/design-red-flags.md +57 -0
  41. package/skills/architect/references/rationale-template.md +35 -0
  42. package/skills/architect/references/runner-prompt.md +20 -0
  43. package/skills/arena/SKILL.md +48 -0
  44. package/skills/automate-me/SKILL.md +104 -0
  45. package/skills/benchmark-checklist/SKILL.md +39 -0
  46. package/skills/blast-radius/SKILL.md +50 -0
  47. package/skills/bro/SKILL.md +7 -0
  48. package/skills/control-cli/SKILL.md +109 -0
  49. package/skills/control-ui/SKILL.md +109 -0
  50. package/skills/correct/SKILL.md +32 -0
  51. package/skills/create-formal-verification-skill/SKILL.md +43 -0
  52. package/skills/create-skill/SKILL.md +62 -0
  53. package/skills/create-verification-skill/SKILL.md +44 -0
  54. package/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
  55. package/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
  56. package/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
  57. package/skills/deslop/SKILL.md +22 -0
  58. package/skills/figure-it-out/SKILL.md +52 -0
  59. package/skills/how/SKILL.md +36 -0
  60. package/skills/how/references/explainer-prompt.md +55 -0
  61. package/skills/how/references/explorer-prompt.md +35 -0
  62. package/skills/in-your-own-words/SKILL.md +7 -0
  63. package/skills/interrogate/SKILL.md +31 -0
  64. package/skills/ketchup/SKILL.md +43 -0
  65. package/skills/ketchup-video/SKILL.md +29 -0
  66. package/skills/maintain-formal-verification-skill/SKILL.md +58 -0
  67. package/skills/maintain-verification-skill/SKILL.md +39 -0
  68. package/skills/make-bot-ui/SKILL.md +104 -0
  69. package/skills/no-comments/SKILL.md +24 -0
  70. package/skills/poteto-help/SKILL.md +161 -0
  71. package/skills/poteto-help/references/prompting.md +51 -0
  72. package/skills/poteto-help/references/recipes.md +51 -0
  73. package/skills/poteto-mode/SKILL.md +151 -0
  74. package/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  75. package/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  76. package/skills/poteto-mode/playbooks/autopilot-full.md +25 -0
  77. package/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  78. package/skills/poteto-mode/playbooks/babysit.md +23 -0
  79. package/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  80. package/skills/poteto-mode/playbooks/eval.md +25 -0
  81. package/skills/poteto-mode/playbooks/feature.md +21 -0
  82. package/skills/poteto-mode/playbooks/hillclimb.md +21 -0
  83. package/skills/poteto-mode/playbooks/investigation.md +14 -0
  84. package/skills/poteto-mode/playbooks/multi-phase-plan.md +155 -0
  85. package/skills/poteto-mode/playbooks/opening-a-pr.md +34 -0
  86. package/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  87. package/skills/poteto-mode/playbooks/pause-safely.md +10 -0
  88. package/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  89. package/skills/poteto-mode/playbooks/prototype.md +14 -0
  90. package/skills/poteto-mode/playbooks/refactoring.md +16 -0
  91. package/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  92. package/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  93. package/skills/poteto-mode/playbooks/shipping.md +12 -0
  94. package/skills/poteto-mode/playbooks/trace-forensics.md +14 -0
  95. package/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  96. package/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  97. package/skills/poteto-mode/references/bugbot-triage.md +142 -0
  98. package/skills/poteto-mode/scripts/bootstrap.ts +62 -0
  99. package/skills/poteto-mode/scripts/bun.lock +67 -0
  100. package/skills/poteto-mode/scripts/check-plan.mjs +205 -0
  101. package/skills/poteto-mode/scripts/check-plan.test.ts +110 -0
  102. package/skills/poteto-mode/scripts/package.json +16 -0
  103. package/skills/poteto-mode/scripts/watch-pr/cli.test.ts +224 -0
  104. package/skills/poteto-mode/scripts/watch-pr/cli.ts +223 -0
  105. package/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +129 -0
  106. package/skills/poteto-mode/scripts/watch-pr/github.test.ts +498 -0
  107. package/skills/poteto-mode/scripts/watch-pr/github.ts +726 -0
  108. package/skills/poteto-mode/scripts/watch-pr/policy.test.ts +482 -0
  109. package/skills/poteto-mode/scripts/watch-pr/policy.ts +842 -0
  110. package/skills/poteto-mode/scripts/watch-pr/render.ts +169 -0
  111. package/skills/poteto-mode/scripts/watch-pr/tsconfig.json +13 -0
  112. package/skills/poteto-mode/scripts/watch-pr/types.compile.ts +93 -0
  113. package/skills/poteto-mode/scripts/watch-pr/types.ts +414 -0
  114. package/skills/poteto-mode/scripts/watch-pr/watch-pr +6 -0
  115. package/skills/poteto-mode/scripts/worktree-audit.sh +156 -0
  116. package/skills/principle-attack-the-premise/SKILL.md +21 -0
  117. package/skills/principle-boundary-discipline/SKILL.md +34 -0
  118. package/skills/principle-build-the-lever/SKILL.md +23 -0
  119. package/skills/principle-encode-lessons-in-structure/SKILL.md +11 -0
  120. package/skills/principle-exhaust-the-design-space/SKILL.md +9 -0
  121. package/skills/principle-experience-first/SKILL.md +19 -0
  122. package/skills/principle-explain-the-number/SKILL.md +18 -0
  123. package/skills/principle-fix-root-causes/SKILL.md +21 -0
  124. package/skills/principle-foundational-thinking/SKILL.md +21 -0
  125. package/skills/principle-guard-the-context-window/SKILL.md +12 -0
  126. package/skills/principle-laziness-protocol/SKILL.md +10 -0
  127. package/skills/principle-make-operations-idempotent/SKILL.md +22 -0
  128. package/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +14 -0
  129. package/skills/principle-minimize-reader-load/SKILL.md +18 -0
  130. package/skills/principle-model-the-domain/SKILL.md +24 -0
  131. package/skills/principle-never-block-on-the-human/SKILL.md +15 -0
  132. package/skills/principle-outcome-oriented-execution/SKILL.md +21 -0
  133. package/skills/principle-prove-it-works/SKILL.md +22 -0
  134. package/skills/principle-redesign-from-first-principles/SKILL.md +16 -0
  135. package/skills/principle-separate-before-serializing-shared-state/SKILL.md +16 -0
  136. package/skills/principle-sequence-verifiable-units/SKILL.md +17 -0
  137. package/skills/principle-subtract-before-you-add/SKILL.md +18 -0
  138. package/skills/principle-test-behavior-not-implementation/SKILL.md +20 -0
  139. package/skills/principle-type-system-discipline/SKILL.md +13 -0
  140. package/skills/recall/SKILL.md +35 -0
  141. package/skills/reflect/SKILL.md +69 -0
  142. package/skills/reflect/references/divergent-reviewer.md +38 -0
  143. package/skills/reflect/references/judgment-reviewer.md +37 -0
  144. package/skills/reflect/references/synthesizer.md +56 -0
  145. package/skills/reflect/references/tooling-reviewer.md +48 -0
  146. package/skills/setup-pstack/SKILL.md +74 -0
  147. package/skills/sharpen/SKILL.md +16 -0
  148. package/skills/show-me-your-work/SKILL.md +82 -0
  149. package/skills/show-me-your-work/references/decision-log-template.tsv +1 -0
  150. package/skills/show-me-your-work/scripts/log.sh +42 -0
  151. package/skills/statechart/SKILL.md +82 -0
  152. package/skills/statechart/references/render.md +93 -0
  153. package/skills/statechart/scripts/backends/cfg.ts +33 -0
  154. package/skills/statechart/scripts/backends/mermaid.ts +201 -0
  155. package/skills/statechart/scripts/backends/plain-text.ts +72 -0
  156. package/skills/statechart/scripts/backends/report.ts +177 -0
  157. package/skills/statechart/scripts/frontends/config.ts +276 -0
  158. package/skills/statechart/scripts/frontends/dot.ts +74 -0
  159. package/skills/statechart/scripts/frontends/marks.ts +93 -0
  160. package/skills/statechart/scripts/frontends/messages.ts +52 -0
  161. package/skills/statechart/scripts/frontends/spec.ts +114 -0
  162. package/skills/statechart/scripts/frontends/trace.ts +24 -0
  163. package/skills/statechart/scripts/frontends/value.ts +166 -0
  164. package/skills/statechart/scripts/frontends/verdict.ts +40 -0
  165. package/skills/statechart/scripts/frontends/view.ts +119 -0
  166. package/skills/statechart/scripts/ir.ts +547 -0
  167. package/skills/statechart/scripts/package.json +11 -0
  168. package/skills/statechart/scripts/passes/annotate.ts +128 -0
  169. package/skills/statechart/scripts/passes/label.ts +269 -0
  170. package/skills/statechart/scripts/passes/lift.ts +85 -0
  171. package/skills/statechart/scripts/passes/loop-check.ts +68 -0
  172. package/skills/statechart/scripts/passes/paths.ts +60 -0
  173. package/skills/statechart/scripts/passes/reach.ts +135 -0
  174. package/skills/statechart/scripts/passes/region-check.ts +97 -0
  175. package/skills/statechart/scripts/passes/regions.ts +295 -0
  176. package/skills/statechart/scripts/pipeline.ts +76 -0
  177. package/skills/statechart/scripts/run.ts +481 -0
  178. package/skills/statechart/scripts/statechart +29 -0
  179. package/skills/statechart/scripts/statechart.ts +164 -0
  180. package/skills/statechart/scripts/test/ConfigOracle.java +63 -0
  181. package/skills/statechart/scripts/test/chart.test.ts +1210 -0
  182. package/skills/statechart/scripts/test/charts/Braces.mmd +7 -0
  183. package/skills/statechart/scripts/test/charts/Escapes.mmd +11 -0
  184. package/skills/statechart/scripts/test/charts/Phases.mmd +29 -0
  185. package/skills/statechart/scripts/test/cli.test.ts +1314 -0
  186. package/skills/statechart/scripts/test/config-fuzz.test.ts +263 -0
  187. package/skills/statechart/scripts/test/corpus/Counter/ChartRun.out +57 -0
  188. package/skills/statechart/scripts/test/corpus/Counter/Counter.cfg +3 -0
  189. package/skills/statechart/scripts/test/corpus/Counter/Counter.tla +10 -0
  190. package/skills/statechart/scripts/test/corpus/Counter/chart.mmd +9 -0
  191. package/skills/statechart/scripts/test/corpus/Counter/graph.dot +16 -0
  192. package/skills/statechart/scripts/test/corpus/Counter/report.md +7 -0
  193. package/skills/statechart/scripts/test/corpus/Counter/sany.out +2 -0
  194. package/skills/statechart/scripts/test/corpus/Counter/verdict-1.out +49 -0
  195. package/skills/statechart/scripts/test/corpus/CounterAction/ChartRun.out +60 -0
  196. package/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.cfg +4 -0
  197. package/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.tla +22 -0
  198. package/skills/statechart/scripts/test/corpus/CounterAction/chart.mmd +26 -0
  199. package/skills/statechart/scripts/test/corpus/CounterAction/graph.dot +19 -0
  200. package/skills/statechart/scripts/test/corpus/CounterAction/report.md +20 -0
  201. package/skills/statechart/scripts/test/corpus/CounterAction/sany.out +2 -0
  202. package/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.exit +1 -0
  203. package/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.out +56 -0
  204. package/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.exit +1 -0
  205. package/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.out +82 -0
  206. package/skills/statechart/scripts/test/corpus/CounterAction/verdict-3.out +57 -0
  207. package/skills/statechart/scripts/test/corpus/CounterDeadlock/ChartRun.out +59 -0
  208. package/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.cfg +3 -0
  209. package/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.tla +11 -0
  210. package/skills/statechart/scripts/test/corpus/CounterDeadlock/chart.mmd +22 -0
  211. package/skills/statechart/scripts/test/corpus/CounterDeadlock/graph.dot +16 -0
  212. package/skills/statechart/scripts/test/corpus/CounterDeadlock/report.md +17 -0
  213. package/skills/statechart/scripts/test/corpus/CounterDeadlock/sany.out +2 -0
  214. package/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.exit +1 -0
  215. package/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.out +56 -0
  216. package/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.exit +1 -0
  217. package/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.out +77 -0
  218. package/skills/statechart/scripts/test/corpus/CounterFan/ChartRun.out +69 -0
  219. package/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.cfg +2 -0
  220. package/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.tla +11 -0
  221. package/skills/statechart/scripts/test/corpus/CounterFan/chart.mmd +85 -0
  222. package/skills/statechart/scripts/test/corpus/CounterFan/graph.dot +70 -0
  223. package/skills/statechart/scripts/test/corpus/CounterFan/report.md +12 -0
  224. package/skills/statechart/scripts/test/corpus/CounterFan/sany.out +2 -0
  225. package/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.exit +1 -0
  226. package/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.out +67 -0
  227. package/skills/statechart/scripts/test/corpus/CounterFan/verdict-2.out +57 -0
  228. package/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.exit +1 -0
  229. package/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.out +85 -0
  230. package/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.cfg +6 -0
  231. package/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.tla +13 -0
  232. package/skills/statechart/scripts/test/corpus/CounterGuard/chart.mmd +5 -0
  233. package/skills/statechart/scripts/test/corpus/CounterGuard/graph.dot +10 -0
  234. package/skills/statechart/scripts/test/corpus/CounterGuard/report.md +31 -0
  235. package/skills/statechart/scripts/test/corpus/CounterGuard/sany.out +2 -0
  236. package/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.exit +1 -0
  237. package/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.out +64 -0
  238. package/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.exit +1 -0
  239. package/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.out +77 -0
  240. package/skills/statechart/scripts/test/corpus/CounterInitPast/ChartRun.out +55 -0
  241. package/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.cfg +3 -0
  242. package/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.tla +10 -0
  243. package/skills/statechart/scripts/test/corpus/CounterInitPast/chart.mmd +12 -0
  244. package/skills/statechart/scripts/test/corpus/CounterInitPast/graph.dot +6 -0
  245. package/skills/statechart/scripts/test/corpus/CounterInitPast/report.md +12 -0
  246. package/skills/statechart/scripts/test/corpus/CounterInitPast/sany.out +2 -0
  247. package/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.exit +1 -0
  248. package/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.out +33 -0
  249. package/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-2.out +54 -0
  250. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/ChartRun.out +54 -0
  251. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.cfg +3 -0
  252. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.tla +10 -0
  253. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/chart.mmd +1 -0
  254. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/graph.dot +6 -0
  255. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/report.md +7 -0
  256. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/sany.out +2 -0
  257. package/skills/statechart/scripts/test/corpus/CounterInitPastHolds/verdict-1.out +46 -0
  258. package/skills/statechart/scripts/test/corpus/CounterInstance/ChartRun.out +59 -0
  259. package/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.cfg +2 -0
  260. package/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.tla +10 -0
  261. package/skills/statechart/scripts/test/corpus/CounterInstance/CounterSteps.tla +6 -0
  262. package/skills/statechart/scripts/test/corpus/CounterInstance/chart.mmd +17 -0
  263. package/skills/statechart/scripts/test/corpus/CounterInstance/graph.dot +15 -0
  264. package/skills/statechart/scripts/test/corpus/CounterInstance/report.md +14 -0
  265. package/skills/statechart/scripts/test/corpus/CounterInstance/sany.out +3 -0
  266. package/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.exit +1 -0
  267. package/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.out +78 -0
  268. package/skills/statechart/scripts/test/corpus/CounterJump/ChartRun.out +59 -0
  269. package/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.cfg +3 -0
  270. package/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.tla +19 -0
  271. package/skills/statechart/scripts/test/corpus/CounterJump/chart.mmd +26 -0
  272. package/skills/statechart/scripts/test/corpus/CounterJump/graph.dot +22 -0
  273. package/skills/statechart/scripts/test/corpus/CounterJump/report.md +12 -0
  274. package/skills/statechart/scripts/test/corpus/CounterJump/sany.out +2 -0
  275. package/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.exit +1 -0
  276. package/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.out +58 -0
  277. package/skills/statechart/scripts/test/corpus/CounterJump/verdict-2.out +57 -0
  278. package/skills/statechart/scripts/test/corpus/CounterLoop/ChartRun.out +57 -0
  279. package/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.cfg +2 -0
  280. package/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.tla +11 -0
  281. package/skills/statechart/scripts/test/corpus/CounterLoop/chart.mmd +17 -0
  282. package/skills/statechart/scripts/test/corpus/CounterLoop/graph.dot +15 -0
  283. package/skills/statechart/scripts/test/corpus/CounterLoop/report.md +14 -0
  284. package/skills/statechart/scripts/test/corpus/CounterLoop/sany.out +2 -0
  285. package/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.exit +1 -0
  286. package/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.out +76 -0
  287. package/skills/statechart/scripts/test/corpus/CounterOrder/ChartRun.out +59 -0
  288. package/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.cfg +3 -0
  289. package/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.tla +11 -0
  290. package/skills/statechart/scripts/test/corpus/CounterOrder/chart.mmd +19 -0
  291. package/skills/statechart/scripts/test/corpus/CounterOrder/graph.dot +10 -0
  292. package/skills/statechart/scripts/test/corpus/CounterOrder/report.md +15 -0
  293. package/skills/statechart/scripts/test/corpus/CounterOrder/sany.out +2 -0
  294. package/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.exit +1 -0
  295. package/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.out +56 -0
  296. package/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.exit +1 -0
  297. package/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.out +67 -0
  298. package/skills/statechart/scripts/test/corpus/CounterRules/ChartRun.out +62 -0
  299. package/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.cfg +6 -0
  300. package/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.tla +24 -0
  301. package/skills/statechart/scripts/test/corpus/CounterRules/Moves.tla +5 -0
  302. package/skills/statechart/scripts/test/corpus/CounterRules/chart.mmd +22 -0
  303. package/skills/statechart/scripts/test/corpus/CounterRules/graph.dot +10 -0
  304. package/skills/statechart/scripts/test/corpus/CounterRules/report.md +23 -0
  305. package/skills/statechart/scripts/test/corpus/CounterRules/sany.out +3 -0
  306. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.exit +1 -0
  307. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.out +58 -0
  308. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.exit +1 -0
  309. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.out +66 -0
  310. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.exit +1 -0
  311. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.out +74 -0
  312. package/skills/statechart/scripts/test/corpus/CounterRules/verdict-4.out +59 -0
  313. package/skills/statechart/scripts/test/corpus/CounterStart/ChartRun.out +58 -0
  314. package/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.cfg +3 -0
  315. package/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.tla +15 -0
  316. package/skills/statechart/scripts/test/corpus/CounterStart/chart.mmd +18 -0
  317. package/skills/statechart/scripts/test/corpus/CounterStart/graph.dot +13 -0
  318. package/skills/statechart/scripts/test/corpus/CounterStart/report.md +11 -0
  319. package/skills/statechart/scripts/test/corpus/CounterStart/sany.out +2 -0
  320. package/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.exit +1 -0
  321. package/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.out +33 -0
  322. package/skills/statechart/scripts/test/corpus/CounterStart/verdict-2.out +57 -0
  323. package/skills/statechart/scripts/test/corpus/CounterStop/ChartRun.out +57 -0
  324. package/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.cfg +3 -0
  325. package/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.tla +15 -0
  326. package/skills/statechart/scripts/test/corpus/CounterStop/chart.mmd +7 -0
  327. package/skills/statechart/scripts/test/corpus/CounterStop/graph.dot +13 -0
  328. package/skills/statechart/scripts/test/corpus/CounterStop/report.md +6 -0
  329. package/skills/statechart/scripts/test/corpus/CounterStop/sany.out +2 -0
  330. package/skills/statechart/scripts/test/corpus/CounterStop/verdict-1.out +49 -0
  331. package/skills/statechart/scripts/test/corpus/CounterTie/ChartRun.out +61 -0
  332. package/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.cfg +4 -0
  333. package/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.tla +14 -0
  334. package/skills/statechart/scripts/test/corpus/CounterTie/chart.mmd +30 -0
  335. package/skills/statechart/scripts/test/corpus/CounterTie/graph.dot +19 -0
  336. package/skills/statechart/scripts/test/corpus/CounterTie/report.md +27 -0
  337. package/skills/statechart/scripts/test/corpus/CounterTie/sany.out +2 -0
  338. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.exit +1 -0
  339. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.out +56 -0
  340. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.exit +1 -0
  341. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.out +64 -0
  342. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.exit +1 -0
  343. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.out +87 -0
  344. package/skills/statechart/scripts/test/corpus/CounterTie/verdict-4.out +57 -0
  345. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/ChartRun.out +60 -0
  346. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.cfg +3 -0
  347. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.tla +12 -0
  348. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/chart.mmd +23 -0
  349. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/graph.dot +19 -0
  350. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/report.md +11 -0
  351. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/sany.out +2 -0
  352. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.exit +1 -0
  353. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.out +56 -0
  354. package/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-2.out +57 -0
  355. package/skills/statechart/scripts/test/corpus/CounterView/ChartRun.out +61 -0
  356. package/skills/statechart/scripts/test/corpus/CounterView/CounterView.cfg +4 -0
  357. package/skills/statechart/scripts/test/corpus/CounterView/CounterView.tla +14 -0
  358. package/skills/statechart/scripts/test/corpus/CounterView/chart.mmd +23 -0
  359. package/skills/statechart/scripts/test/corpus/CounterView/graph.dot +19 -0
  360. package/skills/statechart/scripts/test/corpus/CounterView/report.md +27 -0
  361. package/skills/statechart/scripts/test/corpus/CounterView/sany.out +2 -0
  362. package/skills/statechart/scripts/test/corpus/CounterView/verdict-1.exit +1 -0
  363. package/skills/statechart/scripts/test/corpus/CounterView/verdict-1.out +56 -0
  364. package/skills/statechart/scripts/test/corpus/CounterView/verdict-2.exit +1 -0
  365. package/skills/statechart/scripts/test/corpus/CounterView/verdict-2.out +64 -0
  366. package/skills/statechart/scripts/test/corpus/CounterView/verdict-3.exit +1 -0
  367. package/skills/statechart/scripts/test/corpus/CounterView/verdict-3.out +87 -0
  368. package/skills/statechart/scripts/test/corpus/CounterView/verdict-4.out +57 -0
  369. package/skills/statechart/scripts/test/corpus/CounterView/view.mjs +1 -0
  370. package/skills/statechart/scripts/test/corpus/DieHard/ChartRun.out +59 -0
  371. package/skills/statechart/scripts/test/corpus/DieHard/DieHard.cfg +4 -0
  372. package/skills/statechart/scripts/test/corpus/DieHard/DieHard.tla +38 -0
  373. package/skills/statechart/scripts/test/corpus/DieHard/chart.mmd +92 -0
  374. package/skills/statechart/scripts/test/corpus/DieHard/graph.dot +126 -0
  375. package/skills/statechart/scripts/test/corpus/DieHard/report.md +17 -0
  376. package/skills/statechart/scripts/test/corpus/DieHard/sany.out +2 -0
  377. package/skills/statechart/scripts/test/corpus/DieHard/verdict-1.exit +1 -0
  378. package/skills/statechart/scripts/test/corpus/DieHard/verdict-1.out +91 -0
  379. package/skills/statechart/scripts/test/corpus/DieHard/verdict-2.out +57 -0
  380. package/skills/statechart/scripts/test/corpus/FirstRule/ChartRun.out +61 -0
  381. package/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.cfg +6 -0
  382. package/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.tla +11 -0
  383. package/skills/statechart/scripts/test/corpus/FirstRule/chart.mmd +22 -0
  384. package/skills/statechart/scripts/test/corpus/FirstRule/graph.dot +16 -0
  385. package/skills/statechart/scripts/test/corpus/FirstRule/report.md +25 -0
  386. package/skills/statechart/scripts/test/corpus/FirstRule/sany.out +2 -0
  387. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.exit +1 -0
  388. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.out +56 -0
  389. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.exit +1 -0
  390. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.out +64 -0
  391. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.exit +1 -0
  392. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.out +64 -0
  393. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.exit +1 -0
  394. package/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.out +77 -0
  395. package/skills/statechart/scripts/test/corpus/HiddenClock/ChartRun.out +57 -0
  396. package/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.cfg +4 -0
  397. package/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.tla +11 -0
  398. package/skills/statechart/scripts/test/corpus/HiddenClock/chart.mmd +13 -0
  399. package/skills/statechart/scripts/test/corpus/HiddenClock/graph.dot +12 -0
  400. package/skills/statechart/scripts/test/corpus/HiddenClock/report.md +11 -0
  401. package/skills/statechart/scripts/test/corpus/HiddenClock/sany.out +2 -0
  402. package/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.exit +1 -0
  403. package/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.out +72 -0
  404. package/skills/statechart/scripts/test/corpus/Login/ChartRun.out +57 -0
  405. package/skills/statechart/scripts/test/corpus/Login/Login.cfg +3 -0
  406. package/skills/statechart/scripts/test/corpus/Login/Login.tla +62 -0
  407. package/skills/statechart/scripts/test/corpus/Login/chart.mmd +27 -0
  408. package/skills/statechart/scripts/test/corpus/Login/graph.dot +40 -0
  409. package/skills/statechart/scripts/test/corpus/Login/report.md +7 -0
  410. package/skills/statechart/scripts/test/corpus/Login/sany.out +1 -0
  411. package/skills/statechart/scripts/test/corpus/Login/verdict-1.out +47 -0
  412. package/skills/statechart/scripts/test/corpus/Login/view.mjs +1 -0
  413. package/skills/statechart/scripts/test/corpus/LoginGuarded/ChartRun.out +57 -0
  414. package/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.cfg +2 -0
  415. package/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.tla +64 -0
  416. package/skills/statechart/scripts/test/corpus/LoginGuarded/chart.mmd +28 -0
  417. package/skills/statechart/scripts/test/corpus/LoginGuarded/graph.dot +37 -0
  418. package/skills/statechart/scripts/test/corpus/LoginGuarded/report.md +8 -0
  419. package/skills/statechart/scripts/test/corpus/LoginGuarded/sany.out +1 -0
  420. package/skills/statechart/scripts/test/corpus/LoginGuarded/verdict-1.out +47 -0
  421. package/skills/statechart/scripts/test/corpus/LoginGuarded/view.mjs +1 -0
  422. package/skills/statechart/scripts/test/corpus/LoginParallel/ChartRun.out +60 -0
  423. package/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.cfg +3 -0
  424. package/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.tla +64 -0
  425. package/skills/statechart/scripts/test/corpus/LoginParallel/chart.mmd +44 -0
  426. package/skills/statechart/scripts/test/corpus/LoginParallel/graph.dot +58 -0
  427. package/skills/statechart/scripts/test/corpus/LoginParallel/report.md +17 -0
  428. package/skills/statechart/scripts/test/corpus/LoginParallel/sany.out +1 -0
  429. package/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.exit +1 -0
  430. package/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.out +83 -0
  431. package/skills/statechart/scripts/test/corpus/LoginParallel/verdict-2.out +57 -0
  432. package/skills/statechart/scripts/test/corpus/LoginParallel/view.mjs +1 -0
  433. package/skills/statechart/scripts/test/corpus/MediaPlayer/ChartRun.out +60 -0
  434. package/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.cfg +3 -0
  435. package/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.tla +103 -0
  436. package/skills/statechart/scripts/test/corpus/MediaPlayer/chart.mmd +43 -0
  437. package/skills/statechart/scripts/test/corpus/MediaPlayer/graph.dot +93 -0
  438. package/skills/statechart/scripts/test/corpus/MediaPlayer/report.md +14 -0
  439. package/skills/statechart/scripts/test/corpus/MediaPlayer/sany.out +1 -0
  440. package/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.exit +1 -0
  441. package/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.out +59 -0
  442. package/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-2.out +72 -0
  443. package/skills/statechart/scripts/test/corpus/MediaPlayer/view.mjs +3 -0
  444. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/ChartRun.out +57 -0
  445. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.cfg +2 -0
  446. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.tla +100 -0
  447. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/chart.mmd +31 -0
  448. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/graph.dot +85 -0
  449. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/report.md +9 -0
  450. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/sany.out +1 -0
  451. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/verdict-1.out +47 -0
  452. package/skills/statechart/scripts/test/corpus/MediaPlayerFixed/view.mjs +3 -0
  453. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/ChartRun.out +59 -0
  454. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayer.tla +103 -0
  455. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.cfg +3 -0
  456. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.tla +6 -0
  457. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/chart.mmd +42 -0
  458. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/graph.dot +93 -0
  459. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/report.md +19 -0
  460. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/sany.out +2 -0
  461. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.exit +1 -0
  462. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.out +61 -0
  463. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-2.out +59 -0
  464. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-3.out +61 -0
  465. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.exit +1 -0
  466. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.out +66 -0
  467. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.exit +1 -0
  468. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.out +58 -0
  469. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-6.out +49 -0
  470. package/skills/statechart/scripts/test/corpus/MediaPlayerProps/view.mjs +3 -0
  471. package/skills/statechart/scripts/test/corpus/PickWorker/ChartRun.out +57 -0
  472. package/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.cfg +6 -0
  473. package/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.tla +11 -0
  474. package/skills/statechart/scripts/test/corpus/PickWorker/chart.mmd +5 -0
  475. package/skills/statechart/scripts/test/corpus/PickWorker/graph.dot +11 -0
  476. package/skills/statechart/scripts/test/corpus/PickWorker/report.md +7 -0
  477. package/skills/statechart/scripts/test/corpus/PickWorker/sany.out +5 -0
  478. package/skills/statechart/scripts/test/corpus/PickWorker/verdict-1.out +70 -0
  479. package/skills/statechart/scripts/test/corpus/Shadow/ChartRun.out +61 -0
  480. package/skills/statechart/scripts/test/corpus/Shadow/Shadow.cfg +4 -0
  481. package/skills/statechart/scripts/test/corpus/Shadow/Shadow.tla +11 -0
  482. package/skills/statechart/scripts/test/corpus/Shadow/ShadowLib.tla +6 -0
  483. package/skills/statechart/scripts/test/corpus/Shadow/ShadowSub.tla +3 -0
  484. package/skills/statechart/scripts/test/corpus/Shadow/chart.mmd +9 -0
  485. package/skills/statechart/scripts/test/corpus/Shadow/graph.dot +16 -0
  486. package/skills/statechart/scripts/test/corpus/Shadow/report.md +8 -0
  487. package/skills/statechart/scripts/test/corpus/Shadow/sany.out +4 -0
  488. package/skills/statechart/scripts/test/corpus/Shadow/verdict-1.out +65 -0
  489. package/skills/statechart/scripts/test/corpus/SpacedNames/ChartRun.out +59 -0
  490. package/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.cfg +2 -0
  491. package/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.tla +9 -0
  492. package/skills/statechart/scripts/test/corpus/SpacedNames/chart.mmd +23 -0
  493. package/skills/statechart/scripts/test/corpus/SpacedNames/graph.dot +17 -0
  494. package/skills/statechart/scripts/test/corpus/SpacedNames/report.md +15 -0
  495. package/skills/statechart/scripts/test/corpus/SpacedNames/sany.out +1 -0
  496. package/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.exit +1 -0
  497. package/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.out +65 -0
  498. package/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.exit +1 -0
  499. package/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.out +75 -0
  500. package/skills/statechart/scripts/test/corpus/TwoPhase/ChartRun.out +69 -0
  501. package/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.cfg +3 -0
  502. package/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.tla +75 -0
  503. package/skills/statechart/scripts/test/corpus/TwoPhase/chart.mmd +60 -0
  504. package/skills/statechart/scripts/test/corpus/TwoPhase/graph.dot +297 -0
  505. package/skills/statechart/scripts/test/corpus/TwoPhase/report.md +20 -0
  506. package/skills/statechart/scripts/test/corpus/TwoPhase/sany.out +1 -0
  507. package/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.exit +1 -0
  508. package/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.out +95 -0
  509. package/skills/statechart/scripts/test/corpus/TwoPhase/verdict-2.out +57 -0
  510. package/skills/statechart/scripts/test/corpus/TwoPhase/view.mjs +1 -0
  511. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/ChartRun.out +57 -0
  512. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.cfg +3 -0
  513. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.tla +75 -0
  514. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/chart.mmd +37 -0
  515. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/graph.dot +223 -0
  516. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/report.md +11 -0
  517. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/sany.out +1 -0
  518. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/verdict-1.out +47 -0
  519. package/skills/statechart/scripts/test/corpus/TwoPhaseFixed/view.mjs +1 -0
  520. package/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.exit +1 -0
  521. package/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.out +75 -0
  522. package/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.cfg +5 -0
  523. package/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.tla +11 -0
  524. package/skills/statechart/scripts/test/corpus/TypeGuard/chart.mmd +18 -0
  525. package/skills/statechart/scripts/test/corpus/TypeGuard/graph.dot +14 -0
  526. package/skills/statechart/scripts/test/corpus/TypeGuard/report.md +29 -0
  527. package/skills/statechart/scripts/test/corpus/TypeGuard/sany.out +2 -0
  528. package/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.exit +1 -0
  529. package/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.out +64 -0
  530. package/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.exit +1 -0
  531. package/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.out +75 -0
  532. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/ChartRun.out +58 -0
  533. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.cfg +2 -0
  534. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.tla +8 -0
  535. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/chart.mmd +22 -0
  536. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/graph.dot +16 -0
  537. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/report.md +15 -0
  538. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/sany.out +2 -0
  539. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.exit +1 -0
  540. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.out +56 -0
  541. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.exit +1 -0
  542. package/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.out +77 -0
  543. package/skills/statechart/scripts/test/corpus.test.ts +403 -0
  544. package/skills/statechart/scripts/test/differential.test.ts +565 -0
  545. package/skills/statechart/scripts/test/grid/Grid.cfg +2 -0
  546. package/skills/statechart/scripts/test/grid/Grid.tla +9 -0
  547. package/skills/statechart/scripts/test/grid/sany.out +2 -0
  548. package/skills/statechart/scripts/test/java.ts +63 -0
  549. package/skills/statechart/scripts/test/labels.ts +643 -0
  550. package/skills/statechart/scripts/test/messages.test.ts +212 -0
  551. package/skills/statechart/scripts/test/pipeline.test.ts +270 -0
  552. package/skills/statechart/scripts/test/plain-tlc.test.ts +255 -0
  553. package/skills/statechart/scripts/test/render.test.ts +81 -0
  554. package/skills/statechart/scripts/test/tlc-out.test.ts +90 -0
  555. package/skills/statechart/scripts/test/tlc.ts +158 -0
  556. package/skills/statechart/scripts/tsconfig.json +11 -0
  557. package/skills/statechart/scripts/worker.ts +35 -0
  558. package/skills/swarm/SKILL.md +41 -0
  559. package/skills/tdd/SKILL.md +42 -0
  560. package/skills/teach/SKILL.md +21 -0
  561. package/skills/technical-writing/SKILL.md +106 -0
  562. package/skills/typescript-best-practices/SKILL.md +32 -0
  563. package/skills/typescript-best-practices/references/patterns.md +328 -0
  564. package/skills/unslop/SKILL.md +62 -0
  565. package/skills/why/SKILL.md +98 -0
  566. package/skills/why/references/epistemics.md +71 -0
  567. package/skills/why/references/investigator-prompt.md +84 -0
  568. package/skills/why/references/source-playbook.md +17 -0
  569. package/skills/why/references/sources/code-archaeology.md +51 -0
  570. package/skills/why/references/sources/databricks.md +70 -0
  571. package/skills/why/references/sources/datadog.md +97 -0
  572. package/skills/why/references/sources/incident-postmortem.md +5 -0
  573. package/skills/why/references/sources/linear.md +48 -0
  574. package/skills/why/references/sources/notion.md +55 -0
  575. package/skills/why/references/sources/sentry.md +66 -0
  576. package/skills/why/references/sources/slack.md +17 -0
  577. package/skills/why/references/synthesizer-prompt.md +129 -0
  578. package/src/aliases.ts +64 -0
  579. package/src/ask.ts +131 -0
  580. package/src/autocomplete.ts +21 -0
  581. package/src/child-env.ts +44 -0
  582. package/src/index.ts +123 -0
  583. package/src/loop.ts +189 -0
  584. package/src/mode.ts +156 -0
  585. package/src/modes.ts +8 -0
  586. package/src/paths.ts +72 -0
  587. package/src/plan.ts +141 -0
  588. package/src/readonly-shell.ts +107 -0
  589. package/src/rule.ts +56 -0
  590. package/src/sections.ts +117 -0
  591. package/src/subscriptions/cron.ts +75 -0
  592. package/src/subscriptions/github.ts +149 -0
  593. package/src/subscriptions/index.ts +547 -0
  594. package/src/subscriptions/webhook.ts +209 -0
  595. package/src/task/agents.ts +55 -0
  596. package/src/task/card.ts +32 -0
  597. package/src/task/format.ts +88 -0
  598. package/src/task/models.ts +140 -0
  599. package/src/task/records.ts +232 -0
  600. package/src/task/registry.ts +77 -0
  601. package/src/task/runner.ts +370 -0
  602. package/src/task/status.ts +170 -0
  603. package/src/task/stop.ts +100 -0
  604. package/src/task/tool.ts +491 -0
  605. package/src/task/worktree.ts +67 -0
  606. package/src/todo.ts +122 -0
  607. package/src/visualize.ts +244 -0
  608. package/test/aliases.test.ts +57 -0
  609. package/test/ask.test.ts +85 -0
  610. package/test/autocomplete.test.ts +39 -0
  611. package/test/e2e/aliases.e2e.test.ts +81 -0
  612. package/test/e2e/ask.e2e.test.ts +135 -0
  613. package/test/e2e/harness.ts +179 -0
  614. package/test/e2e/host.e2e.test.ts +193 -0
  615. package/test/e2e/lifecycle.e2e.test.ts +99 -0
  616. package/test/e2e/mode.e2e.test.ts +160 -0
  617. package/test/e2e/package.e2e.test.ts +67 -0
  618. package/test/e2e/task.e2e.test.ts +734 -0
  619. package/test/e2e/todo.e2e.test.ts +59 -0
  620. package/test/fixtures/cursor-askquestion-calls.json +806 -0
  621. package/test/fixtures/fake-pi.mjs +96 -0
  622. package/test/fixtures/image-model.ts +16 -0
  623. package/test/fixtures/list-models.ts +15 -0
  624. package/test/fixtures/readonly-shell-exit.ts +17 -0
  625. package/test/fixtures/scripted-model.ts +113 -0
  626. package/test/loop.test.ts +209 -0
  627. package/test/mode.test.ts +143 -0
  628. package/test/plan.test.ts +126 -0
  629. package/test/readonly-shell-security.test.ts +84 -0
  630. package/test/readonly-shell.test.ts +44 -0
  631. package/test/records.test.ts +143 -0
  632. package/test/registry.test.ts +18 -0
  633. package/test/resources.test.ts +162 -0
  634. package/test/rule.test.ts +92 -0
  635. package/test/scripts.test.ts +182 -0
  636. package/test/sections.test.ts +56 -0
  637. package/test/subscriptions-cron.test.ts +60 -0
  638. package/test/subscriptions.test.ts +598 -0
  639. package/test/task-agents.test.ts +49 -0
  640. package/test/task-card.test.ts +34 -0
  641. package/test/task-fork.test.ts +233 -0
  642. package/test/task-format.test.ts +65 -0
  643. package/test/task-model.test.ts +141 -0
  644. package/test/task-runner.test.ts +259 -0
  645. package/test/task-schema.test.ts +50 -0
  646. package/test/task-status.test.ts +155 -0
  647. package/test/task-worktree.test.ts +106 -0
  648. package/test/todo.test.ts +74 -0
  649. package/test/visualize.test.ts +152 -0
  650. package/tsconfig.json +5 -0
  651. package/vitest.config.ts +16 -0
@@ -0,0 +1,491 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { existsSync, rmSync } from 'node:fs';
3
+ import { basename, join } from 'node:path';
4
+
5
+ import { getSupportedThinkingLevels, StringEnum } from '@earendil-works/pi-ai';
6
+ import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';
7
+ import { type Static, Type } from 'typebox';
8
+ import { childIdentity, childVariables } from '../child-env.ts';
9
+ import { rootStoreDir, subagentDir, workspaceStateDir, worktreesDir } from '../paths.ts';
10
+ import { type AgentDefinition, findAgent } from './agents.ts';
11
+ import { renderTaskCard } from './card.ts';
12
+ import { backgroundText, bounded, foregroundText, steerText, worktreeLine, worktreePreface } from './format.ts';
13
+ import { type AvailableModel, type ModelSpec, resolveSubagentModel } from './models.ts';
14
+ import { type AgentRecord, acquireRunLock, forkTranscript, type RunLock, readonlyLaunchRestores, readRecord, transcriptFor, writeRecord } from './records.ts';
15
+ import { type BackgroundNotice, createSubagentRegistry } from './registry.ts';
16
+ import { type ChildHandle, type ChildOutcome, childArgs, resolveAttachments, startChild, validateAgentId, withAttachments } from './runner.ts';
17
+ import { registerStopAgent } from './stop.ts';
18
+ import { addWorktree, planWorktree, type Worktree } from './worktree.ts';
19
+
20
+ const TITLE_LIMIT = 200;
21
+
22
+ export const TaskParams = Type.Object({
23
+ description: Type.String({ description: 'A short (3-5 word) title for the subagent, shown in the UI.' }),
24
+ prompt: Type.String({ description: 'The task for the agent to perform. The subagent sees nothing of this conversation, so include every detail and say what to report back.' }),
25
+ subagent_type: Type.Optional(Type.String({ description: 'Subagent type from the pstack_subagents section. Defaults to generalPurpose.' })),
26
+ model: Type.Optional(
27
+ Type.String({
28
+ description:
29
+ 'Optional model for this agent, from the pstack_subagents section: inherit (default), a Pi model such as claude-opus-5-5:xhigh or provider/model:high, or claude-opus-5-5[effort=high]. An invalid value fails with the allowed list; pick a listed value or omit it. Ignored with resume; with fork, defaults to the source agent model.',
30
+ }),
31
+ ),
32
+ resume: Type.Optional(
33
+ Type.String({
34
+ description:
35
+ 'Agent ID from an earlier Task call in this workspace. Sends this prompt as a follow-up with the agent context preserved. While the agent is still running in this chat, the prompt is steered into its current run and Task returns at once; while another Pi process runs it, Task fails.',
36
+ }),
37
+ ),
38
+ fork: Type.Optional(
39
+ Type.String({
40
+ description:
41
+ 'Agent ID from an earlier Task call in this workspace. Starts a new agent (new ID) whose context begins as a copy of that agent transcript and that runs in the same directory (its git worktree when it had one), so it sees that checkout and its uncommitted changes. The prompt is the new task. subagent_type, model, and readonly default to the source agent; readonly can be added, never lifted. Fails while the source is running. Cannot be combined with resume, environment, or cloud_base_branch.',
42
+ }),
43
+ ),
44
+ fork_turns: Type.Optional(Type.Integer({ minimum: 1, description: 'With fork: copy only the first N user turns of the source agent, so the fork starts from that point in its conversation. Defaults to the whole transcript.' })),
45
+ run_in_background: Type.Optional(
46
+ Type.Boolean({ description: 'Return at once with the agent ID; the final response arrives as a notification after your turn ends. When false, block until the agent finishes. Defaults to the subagent type setting, else false.' }),
47
+ ),
48
+ readonly: Type.Optional(
49
+ Type.Boolean({ description: 'Limit the agent to read, grep, find, ls, and a read-only shell that can neither write files nor reach the network, with no edits and no MCP tools. A readonly subagent type stays readonly.' }),
50
+ ),
51
+ file_attachments: Type.Optional(Type.Array(Type.String(), { description: 'Paths of files or images to attach to the agent first message.' })),
52
+ environment: Type.Optional(
53
+ StringEnum(['local', 'cloud'] as const, {
54
+ description:
55
+ 'local (default) runs the agent in this working directory. cloud runs it on this machine in its own git worktree on a new branch pstack/<agent id>, created from cloud_base_branch or the current HEAD commit, so uncommitted changes do not reach it. The result names the worktree and branch; merge the branch to take its commits. Ignored with resume; not allowed with fork.',
56
+ }),
57
+ ),
58
+ cloud_base_branch: Type.Optional(Type.String({ description: 'With environment cloud, the branch the worktree starts from: a local branch or ref, else origin/<branch>. Defaults to the current HEAD commit. Needs environment cloud.' })),
59
+ });
60
+ type TaskInput = Static<typeof TaskParams>;
61
+
62
+ export function taskPreflight(params: TaskInput, depth: number): undefined {
63
+ if (params.fork !== undefined) {
64
+ if (params.resume !== undefined) throw new Error('fork and resume cannot be combined: resume continues an agent, fork starts a new agent from a copy of one.');
65
+ if (params.environment !== undefined || params.cloud_base_branch !== undefined) throw new Error('fork runs where the source agent ran, so it takes no environment or cloud_base_branch.');
66
+ }
67
+ if (params.fork_turns !== undefined && params.fork === undefined) throw new Error('fork_turns needs fork: it says how many user turns of the source agent to copy.');
68
+ if (params.cloud_base_branch !== undefined && params.environment !== 'cloud') throw new Error('cloud_base_branch needs environment "cloud": it names the branch the subagent\'s worktree starts from.');
69
+ if (depth >= 2) throw new Error('A subagent launched by another subagent cannot launch further subagents.');
70
+ return undefined;
71
+ }
72
+
73
+ /** A readonly agent type restricts its subagents; a call can add the restriction but never lift it. */
74
+ export function effectiveReadonly(agentReadonly: boolean, requested: boolean | undefined): boolean {
75
+ return agentReadonly || requested === true;
76
+ }
77
+
78
+ export interface Launch {
79
+ /** fresh: a new agent; resume: an earlier agent continued; fork: a new agent started from a copy of `forkedFrom`. */
80
+ kind: 'fresh' | 'resume' | 'fork';
81
+ agentId: string;
82
+ forkedFrom?: string;
83
+ agent: AgentDefinition;
84
+ model: ModelSpec | undefined;
85
+ /** What the agent's record keeps. */
86
+ readonly: boolean;
87
+ /** Plan mode runs this launch readonly and here, without touching the record. */
88
+ planMode: boolean;
89
+ /** The parent workspace: records, transcripts, and run locks live under its state folder. */
90
+ workspace: string;
91
+ /** Set for a cloud agent, which runs here instead of in the workspace. */
92
+ worktree: Worktree | undefined;
93
+ rootStore: string;
94
+ /** 1 for a subagent of the main chat; an agent keeps its depth when resumed. */
95
+ depth: number;
96
+ trusted: boolean;
97
+ attachments: string[];
98
+ notes: string[];
99
+ description: string;
100
+ }
101
+
102
+ const runsReadonly = (plan: Launch) => plan.readonly || plan.planMode;
103
+
104
+ /** The running pi script, so children match the parent's Pi version; falls back to `pi` on PATH. */
105
+ function piCommand(): string[] {
106
+ const script = process.argv[1];
107
+ if (script !== undefined && !script.startsWith('/$bunfs/') && existsSync(script)) return [process.execPath, script];
108
+ return /^(node|bun)(\.exe)?$/.test(basename(process.execPath).toLowerCase()) ? ['pi'] : [process.execPath];
109
+ }
110
+
111
+ export function availableModels(ctx: ExtensionContext): AvailableModel[] {
112
+ return ctx.modelRegistry.getAvailable().map((model) => ({ provider: model.provider, id: model.id, reasoning: model.reasoning, levels: getSupportedThinkingLevels(model) }));
113
+ }
114
+
115
+ export function parentModel(ctx: ExtensionContext): ModelSpec | undefined {
116
+ if (ctx.model === undefined) return undefined;
117
+ return ctx.thinkingLevel === undefined ? { provider: ctx.model.provider, id: ctx.model.id } : { provider: ctx.model.provider, id: ctx.model.id, thinking: ctx.thinkingLevel };
118
+ }
119
+
120
+ const rootStoreOf = (ctx: ExtensionContext) => rootStoreDir(ctx.cwd, ctx.sessionManager.getSessionId(), childIdentity.rootStore);
121
+
122
+ function planFresh(params: TaskInput, ctx: ExtensionContext, agents: readonly AgentDefinition[], depth: number, planMode: boolean): Launch {
123
+ const agent = findAgent(agents, params.subagent_type);
124
+ const model = resolveSubagentModel(params.model ?? agent.model, availableModels(ctx), parentModel(ctx));
125
+ const attachments = resolveAttachments(params.file_attachments ?? [], ctx.cwd);
126
+ const readonly = effectiveReadonly(agent.readonly, params.readonly);
127
+ const agentId = randomUUID();
128
+ const cloud = params.environment === 'cloud';
129
+ const worktree = cloud && !planMode ? planWorktree(ctx.cwd, worktreesDir(ctx.cwd), agentId, params.cloud_base_branch) : undefined;
130
+ const notes = worktree === undefined ? (cloud ? ['Note: environment "cloud" was ignored; plan mode runs subagents here, readonly.'] : []) : [worktreeLine(worktree)];
131
+ return { kind: 'fresh', agentId, agent, model, readonly, planMode, workspace: ctx.cwd, worktree, rootStore: rootStoreOf(ctx), depth: depth + 1, trusted: ctx.isProjectTrusted(), attachments, notes, description: params.description };
132
+ }
133
+
134
+ function recordedAgent(agents: readonly AgentDefinition[], agentId: string, type: string): AgentDefinition {
135
+ const agent = agents.find((candidate) => candidate.type === type);
136
+ if (agent === undefined) throw new Error(`Agent ${agentId} was a "${type}" subagent, a type this version no longer has. Start a new agent instead.`);
137
+ return agent;
138
+ }
139
+
140
+ function planResume(params: TaskInput, ctx: ExtensionContext, agents: readonly AgentDefinition[], isRunning: (agentId: string) => boolean, depth: number, planMode: boolean): Launch {
141
+ const agentId = validateAgentId(params.resume ?? '');
142
+ if (isRunning(agentId)) throw new Error(`Agent ${agentId} is still running. Wait for its completion notification before resuming it.`);
143
+ const dir = subagentDir(ctx.cwd);
144
+ const record = readRecord(dir, agentId);
145
+ if (record === undefined) throw new Error(`Unknown agent ID ${agentId}. Resume needs an agent ID returned by an earlier Task call in this workspace.`);
146
+ // Two directories can share a workspace folder name (as they share Pi's session folder); trust and files belong to this one.
147
+ if (record.cwd !== ctx.cwd) throw new Error(`Agent ${agentId} belongs to ${record.cwd}, not this workspace. Start a new agent instead.`);
148
+ // Without its transcript, --session-id would start an empty session under the old ID.
149
+ if (transcriptFor(dir, agentId) === undefined) throw new Error(`Agent ${agentId} has no transcript to resume, so its earlier context is gone. Start a new agent instead.`);
150
+ const { worktree } = record;
151
+ if (worktree !== undefined && !existsSync(worktree.cwd)) throw new Error(`Agent ${agentId} ran in the git worktree ${worktree.path}, which no longer exists. Start a new agent instead.`);
152
+ const agent = recordedAgent(agents, agentId, record.type);
153
+ const attachments = resolveAttachments(params.file_attachments ?? [], ctx.cwd);
154
+ const notes = [
155
+ ...(worktree === undefined ? [] : [worktreeLine(worktree)]),
156
+ ...(params.model === undefined ? [] : [`Note: model "${params.model}" was ignored; a resumed agent keeps its earlier model.`]),
157
+ ...(params.environment === undefined ? [] : [`Note: environment "${params.environment}" was ignored; a resumed agent runs where it first ran.`]),
158
+ ];
159
+ const readonly = effectiveReadonly(effectiveReadonly(record.readonly, agent.readonly), params.readonly);
160
+ // An agent never runs shallower than it was created or than its caller allows: a grandchild resumed from the main chat
161
+ // and a main-chat agent resumed from a subagent both run at depth 2. A call can add readonly but not lift it, and a
162
+ // type that has since become readonly restricts an older writable record too.
163
+ return {
164
+ kind: 'resume',
165
+ agentId,
166
+ agent,
167
+ model: record.model,
168
+ readonly,
169
+ planMode,
170
+ workspace: record.cwd,
171
+ worktree,
172
+ rootStore: rootStoreOf(ctx),
173
+ depth: Math.max(record.depth ?? 0, depth + 1),
174
+ trusted: ctx.isProjectTrusted(),
175
+ attachments,
176
+ notes,
177
+ description: params.description,
178
+ };
179
+ }
180
+
181
+ /**
182
+ * A fork starts as the source's state: its type, model, and readonly unless the call says otherwise (readonly only
183
+ * tightens), its directory or worktree, and its depth rule. `agentId` is the new agent's ID, fixed across the
184
+ * plan made before and after the locks.
185
+ */
186
+ export function planFork(params: TaskInput, ctx: ExtensionContext, agents: readonly AgentDefinition[], isRunning: (agentId: string) => boolean, depth: number, agentId: string, planMode = false): Launch {
187
+ const sourceId = validateAgentId(params.fork ?? '');
188
+ if (isRunning(sourceId)) throw new Error(`Agent ${sourceId} is still running. Wait for its completion notification before forking it.`);
189
+ const dir = subagentDir(ctx.cwd);
190
+ const record = readRecord(dir, sourceId);
191
+ if (record === undefined) throw new Error(`Unknown agent ID ${sourceId}. Fork needs an agent ID returned by an earlier Task call in this workspace.`);
192
+ if (record.cwd !== ctx.cwd) throw new Error(`Agent ${sourceId} belongs to ${record.cwd}, not this workspace. Start a new agent instead.`);
193
+ if (transcriptFor(dir, sourceId) === undefined) throw new Error(`Agent ${sourceId} has no transcript to fork, so its context is gone. Start a new agent instead.`);
194
+ const { worktree } = record;
195
+ if (worktree !== undefined && !existsSync(worktree.cwd)) throw new Error(`Agent ${sourceId} ran in the git worktree ${worktree.path}, which no longer exists. Start a new agent instead.`);
196
+ const sourceType = agents.find((candidate) => candidate.type === record.type);
197
+ const agent = params.subagent_type === undefined ? recordedAgent(agents, sourceId, record.type) : findAgent(agents, params.subagent_type);
198
+ const model = params.model === undefined ? record.model : resolveSubagentModel(params.model, availableModels(ctx), parentModel(ctx));
199
+ const readonly = effectiveReadonly(record.readonly || sourceType?.readonly === true || agent.readonly, params.readonly);
200
+ const attachments = resolveAttachments(params.file_attachments ?? [], ctx.cwd);
201
+ const turns = params.fork_turns === undefined ? '' : `, keeping its first ${params.fork_turns} user turn${params.fork_turns === 1 ? '' : 's'}`;
202
+ const notes = [`Forked from agent ${sourceId}${turns}.`, ...(worktree === undefined ? [] : [worktreeLine(worktree)])];
203
+ return {
204
+ kind: 'fork',
205
+ agentId,
206
+ forkedFrom: sourceId,
207
+ agent,
208
+ model,
209
+ readonly,
210
+ planMode,
211
+ workspace: record.cwd,
212
+ worktree,
213
+ rootStore: rootStoreOf(ctx),
214
+ depth: Math.max(record.depth ?? 0, depth + 1),
215
+ trusted: ctx.isProjectTrusted(),
216
+ attachments,
217
+ notes,
218
+ description: params.description,
219
+ };
220
+ }
221
+
222
+ function launchChild(plan: Launch, prompt: string, signal: AbortSignal | undefined) {
223
+ const readonly = runsReadonly(plan);
224
+ const env = { ...process.env, ...childVariables(plan.agent.type, plan.depth, readonly, plan.rootStore, workspaceStateDir(plan.workspace)) };
225
+ const transcript = plan.kind === 'fresh' || readonly ? undefined : transcriptFor(subagentDir(plan.workspace), plan.agentId);
226
+ const restoreTools = transcript === undefined ? [] : readonlyLaunchRestores(transcript);
227
+ const args = childArgs({ sessionDir: subagentDir(plan.workspace), agentId: plan.agentId, readonly, restoreTools, trusted: plan.trusted, ...(plan.model === undefined ? {} : { model: plan.model }) });
228
+ const input = withAttachments(prompt, plan.attachments);
229
+ return startChild({ command: piCommand(), args, prompt: input.text, images: input.images, cwd: plan.worktree?.cwd ?? plan.workspace, env, ...(signal === undefined ? {} : { signal }) });
230
+ }
231
+
232
+ function recordFresh(plan: Launch): void {
233
+ const record: AgentRecord = {
234
+ agentId: plan.agentId,
235
+ type: plan.agent.type,
236
+ readonly: plan.readonly,
237
+ cwd: plan.workspace,
238
+ createdAt: new Date().toISOString(),
239
+ depth: plan.depth,
240
+ ...(plan.model === undefined ? {} : { model: plan.model }),
241
+ ...(plan.worktree === undefined ? {} : { worktree: plan.worktree }),
242
+ ...(plan.forkedFrom === undefined ? {} : { forkedFrom: plan.forkedFrom }),
243
+ };
244
+ writeRecord(subagentDir(plan.workspace), record);
245
+ }
246
+
247
+ /** A resume keeps a raised readonly floor; plan mode's restriction is never written, since it holds for one launch. */
248
+ function recordResume(plan: Launch): void {
249
+ const dir = subagentDir(plan.workspace);
250
+ const record = readRecord(dir, plan.agentId);
251
+ if (record === undefined) throw new Error(`Unknown agent ID ${plan.agentId}. Resume needs an agent ID returned by an earlier Task call in this workspace.`);
252
+ writeRecord(dir, { ...record, readonly: plan.readonly });
253
+ }
254
+
255
+ /**
256
+ * Starts the child, then points the run lock at it and records the agent. A child that never started (no pid) has no
257
+ * transcript and changes no record, so a new agent's ID never becomes resumable; a fork's copied transcript is removed with it.
258
+ */
259
+ function start(plan: Launch, prompt: string, signal: AbortSignal | undefined, lock: RunLock): ChildHandle {
260
+ let handle: ChildHandle | undefined;
261
+ try {
262
+ handle = launchChild(plan, plan.kind === 'fresh' && plan.worktree !== undefined ? worktreePreface(plan.worktree, prompt) : prompt, signal);
263
+ if (handle.pid !== undefined) {
264
+ lock.holdFor(handle.pid);
265
+ if (plan.kind === 'resume') recordResume(plan);
266
+ else recordFresh(plan);
267
+ } else removeForkTranscript(plan);
268
+ return handle;
269
+ } catch (error) {
270
+ handle?.kill();
271
+ lock.release();
272
+ if (handle?.pid === undefined) removeForkTranscript(plan);
273
+ throw error;
274
+ }
275
+ }
276
+
277
+ function removeForkTranscript(plan: Launch): void {
278
+ if (plan.kind !== 'fork') return;
279
+ const transcript = transcriptFor(subagentDir(plan.workspace), plan.agentId);
280
+ if (transcript !== undefined) rmSync(transcript, { force: true });
281
+ }
282
+
283
+ /** The transcript file, or before Pi has created it, the pattern it will match. */
284
+ function transcriptOf(plan: Launch): string {
285
+ return transcriptFor(subagentDir(plan.workspace), plan.agentId) ?? join(subagentDir(plan.workspace), `*_${plan.agentId}.jsonl`);
286
+ }
287
+
288
+ function details(plan: Launch, background: boolean, status: string, pid?: number) {
289
+ return {
290
+ agentId: plan.agentId,
291
+ forkedFrom: plan.forkedFrom ?? null,
292
+ subagentType: plan.agent.type,
293
+ model: plan.model ?? null,
294
+ readonly: runsReadonly(plan),
295
+ background,
296
+ status,
297
+ transcript: transcriptOf(plan),
298
+ pid: pid ?? null,
299
+ worktree: plan.worktree ?? null,
300
+ description: plan.description,
301
+ };
302
+ }
303
+
304
+ function foregroundResult(plan: Launch, outcome: ChildOutcome) {
305
+ const transcript = transcriptOf(plan);
306
+ if (outcome.failure === undefined) return { content: [{ type: 'text' as const, text: foregroundText(plan.agentId, outcome.finalText, transcript, plan.notes) }], details: details(plan, false, 'success'), usage: outcome.usage };
307
+ const partial = outcome.finalText === '' ? [] : ['', 'Partial output:', bounded(outcome.finalText, transcript)];
308
+ const text = [`Subagent failed: ${outcome.failure}`, ...partial, '', `Agent ID: ${plan.agentId}`, ...plan.notes].join('\n');
309
+ return { content: [{ type: 'text' as const, text }], details: details(plan, false, 'error'), usage: outcome.usage, isError: true };
310
+ }
311
+
312
+ function backgroundNotice(plan: Launch, prompt: string, ctx: ExtensionContext, toolCallId: string): BackgroundNotice {
313
+ const flat = prompt.replace(/\s+/g, ' ').trim();
314
+ return {
315
+ title: flat.length > TITLE_LIMIT ? `${flat.slice(0, TITLE_LIMIT)}…` : flat,
316
+ toolCallId,
317
+ mode: ctx.mode,
318
+ detailFor: (outcome) => {
319
+ const transcript = transcriptOf(plan);
320
+ if (outcome.failure === undefined) return { status: 'success', detail: bounded(outcome.finalText, transcript), usage: outcome.usage };
321
+ return { status: 'error', detail: outcome.finalText === '' ? outcome.failure : `${outcome.failure}\n${bounded(outcome.finalText, transcript)}`, usage: outcome.usage };
322
+ },
323
+ };
324
+ }
325
+
326
+ /**
327
+ * A fork takes the new agent's run lock, then the source's only while it copies the transcript, so the source cannot
328
+ * start writing mid-copy and the two never share a writer lock. The plan is made again under the locks.
329
+ */
330
+ export function prepareFork(params: TaskInput, ctx: ExtensionContext, options: TaskToolOptions, isRunning: (agentId: string) => boolean): { plan: Launch; lock: RunLock } {
331
+ const planMode = options.planMode?.() === true;
332
+ const initialPlan = planFork(params, ctx, options.agents, isRunning, options.depth, randomUUID(), planMode);
333
+ const dir = subagentDir(initialPlan.workspace);
334
+ const lock = acquireRunLock(dir, initialPlan.agentId);
335
+ try {
336
+ const sourceId = initialPlan.forkedFrom ?? '';
337
+ let sourceLock: RunLock;
338
+ try {
339
+ sourceLock = acquireRunLock(dir, sourceId);
340
+ } catch (error) {
341
+ throw new Error(`Agent ${sourceId} is still running. Wait for its completion before forking it. (${(error as Error).message})`);
342
+ }
343
+ try {
344
+ const plan = planFork(params, ctx, options.agents, isRunning, options.depth, initialPlan.agentId, planMode);
345
+ forkTranscript(dir, sourceId, plan.agentId, params.fork_turns);
346
+ return { plan, lock };
347
+ } finally {
348
+ sourceLock.release();
349
+ }
350
+ } catch (error) {
351
+ lock.release();
352
+ throw error;
353
+ }
354
+ }
355
+
356
+ /** Plans the launch and takes the agent's run lock; a resume is planned again under the lock, since the agent may have started in between. */
357
+ function prepare(params: TaskInput, ctx: ExtensionContext, options: TaskToolOptions, isRunning: (agentId: string) => boolean): { plan: Launch; lock: RunLock } {
358
+ if (params.fork !== undefined) return prepareFork(params, ctx, options, isRunning);
359
+ const fresh = params.resume === undefined;
360
+ const planMode = options.planMode?.() === true;
361
+ const initialPlan = fresh ? planFresh(params, ctx, options.agents, options.depth, planMode) : planResume(params, ctx, options.agents, isRunning, options.depth, planMode);
362
+ const lock = acquireRunLock(subagentDir(initialPlan.workspace), initialPlan.agentId);
363
+ try {
364
+ return { plan: fresh ? initialPlan : planResume(params, ctx, options.agents, isRunning, options.depth, planMode), lock };
365
+ } catch (error) {
366
+ lock.release();
367
+ throw error;
368
+ }
369
+ }
370
+
371
+ /** Only a fresh cloud agent awaits here, so a resume or fork keeps taking its lock and starting in one synchronous step. */
372
+ async function createWorktree(plan: Launch, lock: RunLock, signal: AbortSignal | undefined): Promise<void> {
373
+ if (plan.kind !== 'fresh' || plan.worktree === undefined) return;
374
+ try {
375
+ await addWorktree(plan.workspace, plan.worktree, signal);
376
+ } catch (error) {
377
+ lock.release();
378
+ throw error;
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Task resume on an agent this process runs: the prompt joins its current run as a steer, and its result still arrives
384
+ * the way its launch said. A readonly call, or any call in plan mode, cannot steer an agent that has write access.
385
+ */
386
+ async function steerRunning(params: TaskInput, running: { handle: ChildHandle; readonly: boolean }, ctx: ExtensionContext, planMode: boolean) {
387
+ const agentId = params.resume ?? '';
388
+ if ((params.readonly === true || planMode) && !running.readonly)
389
+ throw new Error(`Agent ${agentId} is running with write access, so a readonly call cannot message it${planMode ? ' (plan mode makes every Task call readonly)' : ''}. Wait for its completion notification, or stop it with stop_agent.`);
390
+ const input = withAttachments(params.prompt, resolveAttachments(params.file_attachments ?? [], ctx.cwd));
391
+ await running.handle.steer(input.text, input.images).catch((error: Error) => {
392
+ throw new Error(`Agent ${agentId} finished before the message reached it (${error.message}). Resume it once its result arrives.`);
393
+ });
394
+ const notes = [
395
+ ...(params.model === undefined ? [] : [`Note: model "${params.model}" was ignored; a resumed agent keeps its earlier model.`]),
396
+ ...(params.environment === undefined ? [] : [`Note: environment "${params.environment}" was ignored; a resumed agent runs where it first ran.`]),
397
+ ];
398
+ return { content: [{ type: 'text' as const, text: steerText(agentId, notes) }], details: { agentId, status: 'steered', pid: running.handle.pid ?? null, description: params.description } };
399
+ }
400
+
401
+ const TASK_DESCRIPTION =
402
+ 'Launch a subagent: a separate Pi process with its own context that works autonomously and returns one final message. It sees nothing of this conversation, so give it a self-contained prompt and say what to report back. Put several Task calls in one message to run them in parallel. Subagent types and model values are listed in the pstack_subagents section of the system prompt.';
403
+
404
+ // Interactive Pi redraws the chat between a replaced session's shutdown and the next session's start, which erases a
405
+ // warning sent at shutdown. The next runtime shows it instead, so it rides on globalThis across the reload.
406
+ const STOPPED_NOTICE = Symbol.for('pi-pstack/stopped-subagents');
407
+ const carrier = globalThis as { [STOPPED_NOTICE]?: string };
408
+
409
+ /** Pi restores a resumed session's active tools, so an agent created at depth 1 and resumed at depth 2 would get Task back. */
410
+ function dropTask(pi: ExtensionAPI): void {
411
+ const active = pi.getActiveTools();
412
+ if (active.includes('Task') || active.includes('stop_agent')) pi.setActiveTools(active.filter((name) => name !== 'Task' && name !== 'stop_agent'));
413
+ }
414
+
415
+ export interface TaskToolOptions {
416
+ agents: readonly AgentDefinition[];
417
+ depth: number;
418
+ /** Whether plan mode is on: its Task launches run readonly and here, and record nothing of that. */
419
+ planMode?: () => boolean;
420
+ }
421
+
422
+ export interface TaskHandle {
423
+ hasBackgroundWork: () => boolean;
424
+ /** Starts a fresh background generalPurpose subagent, as a Task call would; its result arrives as a Task notification. */
425
+ startBackground: (description: string, prompt: string) => Promise<string>;
426
+ }
427
+
428
+ export function registerTask(pi: ExtensionAPI, options: TaskToolOptions): TaskHandle {
429
+ const registry = createSubagentRegistry(pi);
430
+ let sessionCtx: ExtensionContext | undefined;
431
+ pi.on('agent_before_settle', (event, ctx) => registry.beforeSettle(ctx, event.outcome));
432
+ pi.on('session_shutdown', (event, ctx) => {
433
+ const stopped = registry.shutdown();
434
+ if (stopped === 0) return;
435
+ const message = `Stopped ${stopped} background subagent${stopped === 1 ? '' : 's'} (session ${event.reason}). Resume one with its agent ID.`;
436
+ if (event.reason === 'quit') {
437
+ if (ctx.hasUI) ctx.ui.notify(message, 'warning');
438
+ } else carrier[STOPPED_NOTICE] = message;
439
+ });
440
+ pi.on('session_start', (_event, ctx) => {
441
+ sessionCtx = ctx;
442
+ if (options.depth >= 2) dropTask(pi);
443
+ const message = carrier[STOPPED_NOTICE];
444
+ delete carrier[STOPPED_NOTICE];
445
+ if (message !== undefined && ctx.hasUI) ctx.ui.notify(message, 'warning');
446
+ });
447
+
448
+ pi.registerTool({
449
+ name: 'Task',
450
+ label: 'Task',
451
+ description: TASK_DESCRIPTION,
452
+ promptSnippet: 'Launch subagents (foreground, background with completion notifications, resume by agent ID)',
453
+ parameters: TaskParams,
454
+ // Nesting stops at the subagent of a subagent, so that depth never sees the tool.
455
+ defaultActive: options.depth < 2,
456
+ renderResult: (result, renderOptions) => renderTaskCard(result, renderOptions),
457
+ async execute(toolCallId, params, signal, onUpdate, ctx) {
458
+ taskPreflight(params, options.depth);
459
+ const running = params.resume === undefined ? undefined : registry.get(validateAgentId(params.resume));
460
+ if (running !== undefined) return steerRunning(params, running, ctx, options.planMode?.() === true);
461
+ const { plan, lock } = prepare(params, ctx, options, registry.isRunning);
462
+ // Awaiting yields to a parallel Task call, so only a fresh isolated agent awaits before it is tracked.
463
+ if (plan.kind === 'fresh' && plan.worktree !== undefined) await createWorktree(plan, lock, signal);
464
+ const background = params.run_in_background ?? plan.agent.background;
465
+ const handle = start(plan, params.prompt, background ? undefined : signal, lock);
466
+ if (background) {
467
+ registry.track(plan.agentId, handle, lock.release, runsReadonly(plan), backgroundNotice(plan, params.prompt, ctx, toolCallId));
468
+ return { content: [{ type: 'text', text: backgroundText(plan.agentId, transcriptOf(plan), plan.notes) }], details: details(plan, true, 'running', handle.pid) };
469
+ }
470
+ registry.track(plan.agentId, handle, lock.release, runsReadonly(plan));
471
+ onUpdate?.({ content: [{ type: 'text', text: `Subagent ${plan.agent.type} is running (${plan.agentId}).` }], details: details(plan, false, 'running', handle.pid) });
472
+ return foregroundResult(plan, await handle.done);
473
+ },
474
+ });
475
+
476
+ registerStopAgent(pi, { running: registry.get, depth: options.depth });
477
+
478
+ async function startBackground(description: string, prompt: string): Promise<string> {
479
+ const ctx = sessionCtx;
480
+ if (ctx === undefined) throw new Error('No session is active, so no subagent can start.');
481
+ const params: TaskInput = { description, prompt, run_in_background: true };
482
+ taskPreflight(params, options.depth);
483
+ const { plan, lock } = prepare(params, ctx, options, registry.isRunning);
484
+ await createWorktree(plan, lock, undefined);
485
+ const handle = start(plan, prompt, undefined, lock);
486
+ registry.track(plan.agentId, handle, lock.release, runsReadonly(plan), backgroundNotice(plan, prompt, ctx, `pstack-${plan.agentId}`));
487
+ return plan.agentId;
488
+ }
489
+
490
+ return { hasBackgroundWork: registry.hasBackgroundWork, startBackground };
491
+ }
@@ -0,0 +1,67 @@
1
+ // An environment "cloud" subagent is an isolated worker: a child process in its own git worktree on a new branch.
2
+ import { execFile, execFileSync } from 'node:child_process';
3
+ import { join } from 'node:path';
4
+
5
+ /** Where a cloud subagent runs. Records and transcripts stay keyed on the parent workspace, never on this. */
6
+ export interface Worktree {
7
+ /** The worktree root. */
8
+ path: string;
9
+ /** The child's working directory: the parent's place in the repository, mapped into the worktree. */
10
+ cwd: string;
11
+ branch: string;
12
+ /** The ref the branch starts from: cloud_base_branch, origin/<cloud_base_branch>, or HEAD. */
13
+ base: string;
14
+ commit: string;
15
+ }
16
+
17
+ function git(dir: string, args: readonly string[]): string {
18
+ return execFileSync('git', ['-C', dir, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
19
+ }
20
+
21
+ /** undefined when git ran and exited non-zero; a git that cannot start still throws. */
22
+ function tryGit(dir: string, args: readonly string[]): string | undefined {
23
+ try {
24
+ return git(dir, args);
25
+ } catch (error) {
26
+ if (typeof (error as { status?: unknown }).status === 'number') return undefined;
27
+ throw error;
28
+ }
29
+ }
30
+
31
+ const commitOf = (dir: string, ref: string) => tryGit(dir, ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`]);
32
+
33
+ function resolveBase(cwd: string, baseBranch: string | undefined): { base: string; commit: string } {
34
+ if (baseBranch === undefined) {
35
+ const commit = commitOf(cwd, 'HEAD');
36
+ if (commit === undefined) throw new Error(`environment "cloud" branches the subagent's worktree from HEAD, but ${cwd} has no commits yet.`);
37
+ return { base: 'HEAD', commit };
38
+ }
39
+ for (const base of [baseBranch, `origin/${baseBranch}`]) {
40
+ const commit = commitOf(cwd, base);
41
+ if (commit !== undefined) return { base, commit };
42
+ }
43
+ throw new Error(`cloud_base_branch "${baseBranch}" names no commit in ${cwd}: neither ${baseBranch} nor origin/${baseBranch} exists. Pass an existing branch or omit cloud_base_branch to start from HEAD.`);
44
+ }
45
+
46
+ /** Resolves where a cloud agent will run without changing anything, so a bad base fails before any side effect. */
47
+ export function planWorktree(cwd: string, worktreesDir: string, agentId: string, baseBranch?: string): Worktree {
48
+ const prefix = tryGit(cwd, ['rev-parse', '--show-prefix'])?.replace(/\/$/, '');
49
+ if (prefix === undefined) throw new Error(`environment "cloud" runs the subagent in its own git worktree, but ${cwd} is not inside a git repository. Omit environment to run the subagent here.`);
50
+ const { base, commit } = resolveBase(cwd, baseBranch);
51
+ const path = join(worktreesDir, agentId);
52
+ const inBase = prefix !== '' && tryGit(cwd, ['cat-file', '-e', `${commit}:${prefix}`]) !== undefined;
53
+ return { path, cwd: inBase ? join(path, prefix) : path, branch: `pstack/${agentId}`, base, commit };
54
+ }
55
+
56
+ /** Creates the worktree and its branch. Nothing here removes them: the parent merges the branch, and worktree-cleanup prunes. */
57
+ export function addWorktree(repoDir: string, worktree: Worktree, signal: AbortSignal | undefined): Promise<void> {
58
+ // A checkout can run hooks and filters for a long time, so it runs off the event loop and stops with the Task call.
59
+ const args = ['-C', repoDir, 'worktree', 'add', '--quiet', '-b', worktree.branch, worktree.path, worktree.commit];
60
+ return new Promise((resolve, reject) => {
61
+ execFile('git', args, { encoding: 'utf8', ...(signal === undefined ? {} : { signal }) }, (error, _stdout, stderr) => {
62
+ if (error === null) resolve();
63
+ else if (signal?.aborted === true) reject(new Error(`Stopped creating the subagent's worktree at ${worktree.path}.`));
64
+ else reject(new Error(`Could not create the subagent's worktree at ${worktree.path}: ${(stderr || error.message).trim()}`));
65
+ });
66
+ });
67
+ }