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

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