pstack-claude-mirror 0.0.0-stage → 0.9.133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +16 -0
- package/CHANGES.md +1110 -0
- package/LICENSE +22 -0
- package/LICENSE-cursor-team-kit +21 -0
- package/LICENSE-mirror +27 -0
- package/LICENSE-thermos +21 -0
- package/NOTICE-skills.md +13 -0
- package/NOTICE.md +62 -0
- package/README.md +84 -2
- package/UPSTREAM-README.md +243 -0
- package/bin/pstack-claude.mjs +183 -0
- package/docs/reference.md +247 -0
- package/package.json +88 -4
- package/plugins/pstack/.antigravity-plugin/plugin.json +8 -0
- package/plugins/pstack/.claude-plugin/icon.png +0 -0
- package/plugins/pstack/.claude-plugin/plugin.json +31 -0
- package/plugins/pstack/.codex-plugin/plugin.json +52 -0
- package/plugins/pstack/.github/plugin/plugin.json +15 -0
- package/plugins/pstack/.grok-plugin/plugin.json +9 -0
- package/plugins/pstack/.muse-plugin/plugin.json +381 -0
- package/plugins/pstack/README.md +27 -0
- package/plugins/pstack/agents/comment-sicko.md +34 -0
- package/plugins/pstack/agents/poteto-agent.md +8 -0
- package/plugins/pstack/agents/thermo-nuclear-code-quality-review-subagent.md +23 -0
- package/plugins/pstack/agents/thermo-nuclear-review-subagent.md +28 -0
- package/plugins/pstack/assets/pstack-icon.png +0 -0
- package/plugins/pstack/assets/pstack-icon.prompt.txt +8 -0
- package/plugins/pstack/grok/skills/pstack-routing/SKILL.md +8 -0
- package/plugins/pstack/hooks/agy-context.awk +9 -0
- package/plugins/pstack/hooks/codex-hooks.json +17 -0
- package/plugins/pstack/hooks/copilot-context.awk +44 -0
- package/plugins/pstack/hooks/copilot-hooks.json +27 -0
- package/plugins/pstack/hooks/hooks.json +16 -0
- package/plugins/pstack/hooks/json.awk +164 -0
- package/plugins/pstack/hooks/kimi-instructions.md +17 -0
- package/plugins/pstack/hooks/muse-context.awk +31 -0
- package/plugins/pstack/hooks/pre-tool-use.awk +152 -0
- package/plugins/pstack/hooks/pre-tool-use.sh +16 -0
- package/plugins/pstack/hooks/script-contracts.awk +55 -0
- package/plugins/pstack/hooks/session-start-agy.md +17 -0
- package/plugins/pstack/hooks/session-start-context.md +15 -0
- package/plugins/pstack/hooks/session-start-copilot-setup.md +1 -0
- package/plugins/pstack/hooks/session-start-copilot-sheet.md +1 -0
- package/plugins/pstack/hooks/session-start-copilot.md +3 -0
- package/plugins/pstack/hooks/session-start-minimax.md +17 -0
- package/plugins/pstack/hooks/session-start-muse-sheet.md +1 -0
- package/plugins/pstack/hooks/session-start-muse.md +17 -0
- package/plugins/pstack/hooks/session-start-opencode.md +17 -0
- package/plugins/pstack/hooks/session-start.ps1 +105 -0
- package/plugins/pstack/hooks/session-start.sh +95 -0
- package/plugins/pstack/hooks.json +10 -0
- package/plugins/pstack/models.json +67 -0
- package/plugins/pstack/omp/index.mjs +34 -0
- package/plugins/pstack/opencode/index.js +49 -0
- package/plugins/pstack/package.json +8 -0
- package/plugins/pstack/pi/agent-files.ts +117 -0
- package/plugins/pstack/pi/agent-text.ts +99 -0
- package/plugins/pstack/pi/agent-tools.ts +148 -0
- package/plugins/pstack/pi/agents.ts +486 -0
- package/plugins/pstack/pi/ask.ts +87 -0
- package/plugins/pstack/pi/child.ts +310 -0
- package/plugins/pstack/pi/config.ts +178 -0
- package/plugins/pstack/pi/index.ts +44 -0
- package/plugins/pstack/pi/one-shot.ts +90 -0
- package/plugins/pstack/pi/path-skills.ts +54 -0
- package/plugins/pstack/pi/prompt.ts +39 -0
- package/plugins/pstack/pi/schedule.ts +254 -0
- package/plugins/pstack/pi/slash.ts +92 -0
- package/plugins/pstack/pi/sleep-wait.ts +76 -0
- package/plugins/pstack/pi/worktree.ts +74 -0
- package/plugins/pstack/skills/architect/SKILL.md +100 -0
- package/plugins/pstack/skills/architect/references/design-red-flags.md +57 -0
- package/plugins/pstack/skills/architect/references/rationale-template.md +39 -0
- package/plugins/pstack/skills/architect/references/runner-prompt.md +20 -0
- package/plugins/pstack/skills/arena/SKILL.md +66 -0
- package/plugins/pstack/skills/automate-me/SKILL.md +111 -0
- package/plugins/pstack/skills/babysit/SKILL.md +68 -0
- package/plugins/pstack/skills/benchmark-checklist/SKILL.md +38 -0
- package/plugins/pstack/skills/blast-radius/SKILL.md +49 -0
- package/plugins/pstack/skills/bro/SKILL.md +6 -0
- package/plugins/pstack/skills/correct/SKILL.md +31 -0
- package/plugins/pstack/skills/create-formal-verification-skill/SKILL.md +50 -0
- package/plugins/pstack/skills/create-verification-skill/SKILL.md +51 -0
- package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/README.md +47 -0
- package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/create-note.md +39 -0
- package/plugins/pstack/skills/create-verification-skill/references/feature-map-example/search.md +45 -0
- package/plugins/pstack/skills/deslop/SKILL.md +24 -0
- package/plugins/pstack/skills/figure-it-out/SKILL.md +51 -0
- package/plugins/pstack/skills/fix-ci/SKILL.md +29 -0
- package/plugins/pstack/skills/fix-merge-conflicts/SKILL.md +32 -0
- package/plugins/pstack/skills/get-pr-comments/SKILL.md +23 -0
- package/plugins/pstack/skills/how/SKILL.md +54 -0
- package/plugins/pstack/skills/how/references/explainer-prompt.md +55 -0
- package/plugins/pstack/skills/how/references/explorer-prompt.md +35 -0
- package/plugins/pstack/skills/in-your-own-words/SKILL.md +6 -0
- package/plugins/pstack/skills/interrogate/SKILL.md +48 -0
- package/plugins/pstack/skills/ketchup/SKILL.md +42 -0
- package/plugins/pstack/skills/ketchup-video/SKILL.md +28 -0
- package/plugins/pstack/skills/maintain-formal-verification-skill/SKILL.md +65 -0
- package/plugins/pstack/skills/maintain-verification-skill/SKILL.md +46 -0
- package/plugins/pstack/skills/make-pr-easy-to-review/SKILL.md +59 -0
- package/plugins/pstack/skills/no-comments/SKILL.md +45 -0
- package/plugins/pstack/skills/poteto-help/SKILL.md +149 -0
- package/plugins/pstack/skills/poteto-help/references/prompting.md +51 -0
- package/plugins/pstack/skills/poteto-help/references/recipes.md +51 -0
- package/plugins/pstack/skills/poteto-mode/SKILL.md +174 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/autopilot-full.md +31 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/babysit.md +23 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/eval.md +25 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/hillclimb.md +21 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/investigation.md +14 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/multi-phase-plan.md +158 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/opening-a-pr.md +34 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/orchestrate.md +27 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/pause-safely.md +11 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/prototype.md +14 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/refactoring.md +18 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/shipping.md +16 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/trace-forensics.md +14 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
- package/plugins/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
- package/plugins/pstack/skills/poteto-mode/references/agents/comment-sicko.md +34 -0
- package/plugins/pstack/skills/poteto-mode/references/agy-tools.md +99 -0
- package/plugins/pstack/skills/poteto-mode/references/bugbot-triage.md +142 -0
- package/plugins/pstack/skills/poteto-mode/references/codex-tools.md +109 -0
- package/plugins/pstack/skills/poteto-mode/references/copilot-tools.md +143 -0
- package/plugins/pstack/skills/poteto-mode/references/grok.md +50 -0
- package/plugins/pstack/skills/poteto-mode/references/kimi-tools.md +40 -0
- package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE +22 -0
- package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE-cursor-team-kit +21 -0
- package/plugins/pstack/skills/poteto-mode/references/licenses/LICENSE-thermos +21 -0
- package/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md +13 -0
- package/plugins/pstack/skills/poteto-mode/references/merge-safety.md +43 -0
- package/plugins/pstack/skills/poteto-mode/references/minimax-tools.md +93 -0
- package/plugins/pstack/skills/poteto-mode/references/muse-tools.md +105 -0
- package/plugins/pstack/skills/poteto-mode/references/omp-tools.md +39 -0
- package/plugins/pstack/skills/poteto-mode/references/opencode-tools.md +29 -0
- package/plugins/pstack/skills/poteto-mode/references/pi-tools.md +117 -0
- package/plugins/pstack/skills/poteto-mode/references/resume-storage.md +20 -0
- package/plugins/pstack/skills/poteto-mode/scripts/.prettierignore +23 -0
- package/plugins/pstack/skills/poteto-mode/scripts/.prettierrc.json +3 -0
- package/plugins/pstack/skills/poteto-mode/scripts/bootstrap.ts +71 -0
- package/plugins/pstack/skills/poteto-mode/scripts/bun.lock +67 -0
- package/plugins/pstack/skills/poteto-mode/scripts/check-plan.mjs +214 -0
- package/plugins/pstack/skills/poteto-mode/scripts/check-plan.test.ts +115 -0
- package/plugins/pstack/skills/poteto-mode/scripts/check-playbooks.mjs +71 -0
- package/plugins/pstack/skills/poteto-mode/scripts/codex-session-effort.mjs +66 -0
- package/plugins/pstack/skills/poteto-mode/scripts/package.json +16 -0
- package/plugins/pstack/skills/poteto-mode/scripts/resume.mjs +139 -0
- package/plugins/pstack/skills/poteto-mode/scripts/tsconfig.json +14 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.ts +383 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/cli.ts +266 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/deadline.ts +20 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +157 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/fresh-install.test.ts +35 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.test.ts +902 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/github.ts +922 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/integrity.test.ts +887 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/landing.ts +92 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/live-merge-safety.mjs +142 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.ts +1151 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/policy.ts +956 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/render.ts +200 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/ship-pr +6 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping-cli.test.ts +159 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping-cli.ts +65 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.test-helper.ts +48 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.test.ts +360 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/shipping.ts +235 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/transport.test.ts +211 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/tsconfig.json +13 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/types.compile.ts +108 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/types.ts +474 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr +6 -0
- package/plugins/pstack/skills/poteto-mode/scripts/watch-pr/wrapper.test.ts +20 -0
- package/plugins/pstack/skills/poteto-mode/scripts/worktree-audit.mjs +434 -0
- package/plugins/pstack/skills/principle-attack-the-premise/SKILL.md +21 -0
- package/plugins/pstack/skills/principle-boundary-discipline/SKILL.md +34 -0
- package/plugins/pstack/skills/principle-build-the-lever/SKILL.md +24 -0
- package/plugins/pstack/skills/principle-encode-lessons-in-structure/SKILL.md +11 -0
- package/plugins/pstack/skills/principle-exhaust-the-design-space/SKILL.md +9 -0
- package/plugins/pstack/skills/principle-experience-first/SKILL.md +19 -0
- package/plugins/pstack/skills/principle-explain-the-number/SKILL.md +18 -0
- package/plugins/pstack/skills/principle-fix-root-causes/SKILL.md +21 -0
- package/plugins/pstack/skills/principle-foundational-thinking/SKILL.md +21 -0
- package/plugins/pstack/skills/principle-guard-the-context-window/SKILL.md +12 -0
- package/plugins/pstack/skills/principle-laziness-protocol/SKILL.md +10 -0
- package/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md +22 -0
- package/plugins/pstack/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +14 -0
- package/plugins/pstack/skills/principle-minimize-reader-load/SKILL.md +18 -0
- package/plugins/pstack/skills/principle-model-the-domain/SKILL.md +24 -0
- package/plugins/pstack/skills/principle-never-block-on-the-human/SKILL.md +15 -0
- package/plugins/pstack/skills/principle-outcome-oriented-execution/SKILL.md +21 -0
- package/plugins/pstack/skills/principle-prove-it-works/SKILL.md +27 -0
- package/plugins/pstack/skills/principle-redesign-from-first-principles/SKILL.md +16 -0
- package/plugins/pstack/skills/principle-separate-before-serializing-shared-state/SKILL.md +16 -0
- package/plugins/pstack/skills/principle-sequence-verifiable-units/SKILL.md +17 -0
- package/plugins/pstack/skills/principle-subtract-before-you-add/SKILL.md +18 -0
- package/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md +20 -0
- package/plugins/pstack/skills/principle-type-system-discipline/SKILL.md +13 -0
- package/plugins/pstack/skills/recall/SKILL.md +43 -0
- package/plugins/pstack/skills/reflect/SKILL.md +89 -0
- package/plugins/pstack/skills/reflect/references/divergent-reviewer.md +38 -0
- package/plugins/pstack/skills/reflect/references/judgment-reviewer.md +37 -0
- package/plugins/pstack/skills/reflect/references/synthesizer.md +56 -0
- package/plugins/pstack/skills/reflect/references/tooling-reviewer.md +48 -0
- package/plugins/pstack/skills/reflect/scripts/claude-project-dir.mjs +121 -0
- package/plugins/pstack/skills/reflect/scripts/find-transcript.mjs +218 -0
- package/plugins/pstack/skills/setup-pstack/SKILL.md +109 -0
- package/plugins/pstack/skills/setup-pstack/copilot.md +88 -0
- package/plugins/pstack/skills/setup-pstack/references/runtimes.md +75 -0
- package/plugins/pstack/skills/setup-pstack/scripts/check-sheet.awk +10 -0
- package/plugins/pstack/skills/setup-pstack/scripts/check-sheet.sh +20 -0
- package/plugins/pstack/skills/setup-pstack/scripts/read-sheet.sh +24 -0
- package/plugins/pstack/skills/setup-pstack/scripts/sheet.awk +160 -0
- package/plugins/pstack/skills/sharpen/SKILL.md +15 -0
- package/plugins/pstack/skills/show-me-your-work/SKILL.md +89 -0
- package/plugins/pstack/skills/show-me-your-work/references/decision-log-template.tsv +1 -0
- package/plugins/pstack/skills/show-me-your-work/scripts/log.sh +58 -0
- package/plugins/pstack/skills/statechart/SKILL.md +81 -0
- package/plugins/pstack/skills/statechart/references/render.md +93 -0
- package/plugins/pstack/skills/statechart/scripts/backends/cfg.ts +33 -0
- package/plugins/pstack/skills/statechart/scripts/backends/mermaid.ts +201 -0
- package/plugins/pstack/skills/statechart/scripts/backends/plain-text.ts +72 -0
- package/plugins/pstack/skills/statechart/scripts/backends/report.ts +177 -0
- package/plugins/pstack/skills/statechart/scripts/bun.lock +17 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/config.ts +276 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/dot.ts +74 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/marks.ts +93 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/messages.ts +52 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/spec.ts +114 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/trace.ts +24 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/value.ts +166 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/verdict.ts +40 -0
- package/plugins/pstack/skills/statechart/scripts/frontends/view.ts +119 -0
- package/plugins/pstack/skills/statechart/scripts/ir.ts +547 -0
- package/plugins/pstack/skills/statechart/scripts/janitor.ts +12 -0
- package/plugins/pstack/skills/statechart/scripts/package.json +11 -0
- package/plugins/pstack/skills/statechart/scripts/passes/annotate.ts +128 -0
- package/plugins/pstack/skills/statechart/scripts/passes/label.ts +269 -0
- package/plugins/pstack/skills/statechart/scripts/passes/lift.ts +85 -0
- package/plugins/pstack/skills/statechart/scripts/passes/loop-check.ts +68 -0
- package/plugins/pstack/skills/statechart/scripts/passes/paths.ts +60 -0
- package/plugins/pstack/skills/statechart/scripts/passes/reach.ts +135 -0
- package/plugins/pstack/skills/statechart/scripts/passes/region-check.ts +97 -0
- package/plugins/pstack/skills/statechart/scripts/passes/regions.ts +295 -0
- package/plugins/pstack/skills/statechart/scripts/pipeline.ts +76 -0
- package/plugins/pstack/skills/statechart/scripts/run.ts +526 -0
- package/plugins/pstack/skills/statechart/scripts/statechart +29 -0
- package/plugins/pstack/skills/statechart/scripts/statechart.ts +171 -0
- package/plugins/pstack/skills/statechart/scripts/test/ConfigOracle.java +63 -0
- package/plugins/pstack/skills/statechart/scripts/test/chart.test.ts +1210 -0
- package/plugins/pstack/skills/statechart/scripts/test/charts/Braces.mmd +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/charts/Escapes.mmd +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/charts/Phases.mmd +29 -0
- package/plugins/pstack/skills/statechart/scripts/test/child-env.test.ts +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/cli.test.ts +1323 -0
- package/plugins/pstack/skills/statechart/scripts/test/config-fuzz.test.ts +263 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/Counter.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/Counter.tla +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/chart.mmd +9 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/graph.dot +16 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/report.md +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Counter/verdict-1.out +49 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/ChartRun.out +60 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/CounterAction.tla +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/chart.mmd +26 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/graph.dot +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/report.md +20 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-2.out +82 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterAction/verdict-3.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/CounterDeadlock.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/chart.mmd +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/graph.dot +16 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/report.md +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterDeadlock/verdict-2.out +77 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/ChartRun.out +69 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/CounterFan.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/chart.mmd +85 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/graph.dot +70 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/report.md +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-1.out +67 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterFan/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/ChartRun.out +85 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.cfg +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/CounterGuard.tla +13 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/chart.mmd +5 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/graph.dot +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/report.md +31 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-1.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterGuard/verdict-2.out +77 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/ChartRun.out +55 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/CounterInitPast.tla +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/chart.mmd +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/graph.dot +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/report.md +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-1.out +33 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPast/verdict-2.out +54 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/ChartRun.out +54 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/CounterInitPastHolds.tla +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/chart.mmd +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/graph.dot +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/report.md +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInitPastHolds/verdict-1.out +46 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterInstance.tla +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/CounterSteps.tla +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/chart.mmd +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/graph.dot +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/report.md +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/sany.out +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterInstance/verdict-1.out +78 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/CounterJump.tla +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/chart.mmd +26 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/graph.dot +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/report.md +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-1.out +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterJump/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/CounterLoop.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/chart.mmd +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/graph.dot +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/report.md +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterLoop/verdict-1.out +76 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/CounterOrder.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/chart.mmd +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/graph.dot +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/report.md +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterOrder/verdict-2.out +67 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/ChartRun.out +62 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.cfg +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/CounterRules.tla +24 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/Moves.tla +5 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/chart.mmd +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/graph.dot +10 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/report.md +23 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/sany.out +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-1.out +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-2.out +66 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-3.out +74 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterRules/verdict-4.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/ChartRun.out +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/CounterStart.tla +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/chart.mmd +18 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/graph.dot +13 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/report.md +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-1.out +33 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStart/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/CounterStop.tla +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/chart.mmd +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/graph.dot +13 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/report.md +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterStop/verdict-1.out +49 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/ChartRun.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/CounterTie.tla +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/chart.mmd +30 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/graph.dot +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/report.md +27 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-2.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-3.out +87 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTie/verdict-4.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/ChartRun.out +60 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/CounterTieInGraph.tla +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/chart.mmd +23 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/graph.dot +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/report.md +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterTieInGraph/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/ChartRun.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/CounterView.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/CounterView.tla +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/chart.mmd +23 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/graph.dot +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/report.md +27 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-2.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-3.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-3.out +87 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/verdict-4.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/CounterView/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/DieHard.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/DieHard.tla +38 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/chart.mmd +92 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/graph.dot +126 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/report.md +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-1.out +91 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/DieHard/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/ChartRun.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.cfg +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/FirstRule.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/chart.mmd +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/graph.dot +16 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/report.md +25 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-2.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-3.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/FirstRule/verdict-4.out +77 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/HiddenClock.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/chart.mmd +13 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/graph.dot +12 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/report.md +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/HiddenClock/verdict-1.out +72 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/Login.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/Login.tla +62 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/chart.mmd +27 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/graph.dot +40 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/report.md +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/verdict-1.out +47 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Login/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/LoginGuarded.tla +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/chart.mmd +28 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/graph.dot +37 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/report.md +8 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/verdict-1.out +47 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginGuarded/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/ChartRun.out +60 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/LoginParallel.tla +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/chart.mmd +44 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/graph.dot +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/report.md +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-1.out +83 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/LoginParallel/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/ChartRun.out +60 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/MediaPlayer.tla +103 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/chart.mmd +43 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/graph.dot +93 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/report.md +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-1.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/verdict-2.out +72 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayer/view.mjs +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/MediaPlayerFixed.tla +100 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/chart.mmd +31 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/graph.dot +85 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/report.md +9 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/verdict-1.out +47 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerFixed/view.mjs +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayer.tla +103 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/MediaPlayerProps.tla +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/chart.mmd +42 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/graph.dot +93 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/report.md +19 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-1.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-2.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-3.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-4.out +66 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-5.out +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/verdict-6.out +49 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/MediaPlayerProps/view.mjs +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.cfg +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/PickWorker.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/chart.mmd +5 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/graph.dot +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/report.md +7 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/sany.out +5 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/PickWorker/verdict-1.out +70 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ChartRun.out +61 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/Shadow.cfg +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/Shadow.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ShadowLib.tla +6 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/ShadowSub.tla +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/chart.mmd +9 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/graph.dot +16 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/report.md +8 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/sany.out +4 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/Shadow/verdict-1.out +65 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/ChartRun.out +59 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/SpacedNames.tla +9 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/chart.mmd +23 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/graph.dot +17 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/report.md +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-1.out +65 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/SpacedNames/verdict-2.out +75 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/ChartRun.out +69 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/TwoPhase.tla +75 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/chart.mmd +60 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/graph.dot +297 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/report.md +20 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-1.out +95 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/verdict-2.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhase/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/ChartRun.out +57 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.cfg +3 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/TwoPhaseFixed.tla +75 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/chart.mmd +37 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/graph.dot +223 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/report.md +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/sany.out +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/verdict-1.out +47 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TwoPhaseFixed/view.mjs +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/ChartRun.out +75 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.cfg +5 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/TypeGuard.tla +11 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/chart.mmd +18 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/graph.dot +14 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/report.md +29 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-1.out +64 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/TypeGuard/verdict-2.out +75 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/ChartRun.out +58 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/UserNoDeadlock.tla +8 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/chart.mmd +22 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/graph.dot +16 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/report.md +15 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-1.out +56 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.exit +1 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus/UserNoDeadlock/verdict-2.out +77 -0
- package/plugins/pstack/skills/statechart/scripts/test/corpus.test.ts +415 -0
- package/plugins/pstack/skills/statechart/scripts/test/differential.test.ts +565 -0
- package/plugins/pstack/skills/statechart/scripts/test/grid/Grid.cfg +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/grid/Grid.tla +9 -0
- package/plugins/pstack/skills/statechart/scripts/test/grid/sany.out +2 -0
- package/plugins/pstack/skills/statechart/scripts/test/java.ts +63 -0
- package/plugins/pstack/skills/statechart/scripts/test/labels.ts +643 -0
- package/plugins/pstack/skills/statechart/scripts/test/messages.test.ts +227 -0
- package/plugins/pstack/skills/statechart/scripts/test/pipeline.test.ts +270 -0
- package/plugins/pstack/skills/statechart/scripts/test/plain-tlc.test.ts +255 -0
- package/plugins/pstack/skills/statechart/scripts/test/render.test.ts +81 -0
- package/plugins/pstack/skills/statechart/scripts/test/tlc-out.test.ts +90 -0
- package/plugins/pstack/skills/statechart/scripts/test/tlc.ts +158 -0
- package/plugins/pstack/skills/statechart/scripts/tsconfig.json +11 -0
- package/plugins/pstack/skills/statechart/scripts/worker.ts +35 -0
- package/plugins/pstack/skills/swarm/SKILL.md +58 -0
- package/plugins/pstack/skills/tdd/SKILL.md +41 -0
- package/plugins/pstack/skills/teach/SKILL.md +28 -0
- package/plugins/pstack/skills/technical-writing/SKILL.md +105 -0
- package/plugins/pstack/skills/thermo-nuclear-code-quality-review/SKILL.md +201 -0
- package/plugins/pstack/skills/thermo-nuclear-review/SKILL.md +50 -0
- package/plugins/pstack/skills/thermos/SKILL.md +40 -0
- package/plugins/pstack/skills/typescript-best-practices/SKILL.md +32 -0
- package/plugins/pstack/skills/typescript-best-practices/references/patterns.md +328 -0
- package/plugins/pstack/skills/unslop/SKILL.md +61 -0
- package/plugins/pstack/skills/what-did-i-get-done/SKILL.md +31 -0
- package/plugins/pstack/skills/why/SKILL.md +116 -0
- package/plugins/pstack/skills/why/references/epistemics.md +79 -0
- package/plugins/pstack/skills/why/references/investigator-prompt.md +86 -0
- package/plugins/pstack/skills/why/references/source-playbook.md +17 -0
- package/plugins/pstack/skills/why/references/sources/code-archaeology.md +51 -0
- package/plugins/pstack/skills/why/references/sources/databricks.md +70 -0
- package/plugins/pstack/skills/why/references/sources/datadog.md +97 -0
- package/plugins/pstack/skills/why/references/sources/incident-postmortem.md +5 -0
- package/plugins/pstack/skills/why/references/sources/linear.md +48 -0
- package/plugins/pstack/skills/why/references/sources/notion.md +55 -0
- package/plugins/pstack/skills/why/references/sources/sentry.md +66 -0
- package/plugins/pstack/skills/why/references/sources/slack.md +17 -0
- package/plugins/pstack/skills/why/references/synthesizer-prompt.md +130 -0
- package/tools/forks.json +398 -0
- package/tools/substitutions.json +646 -0
- package/tools/upstream.json +53 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type Static, Type } from "typebox";
|
|
3
|
+
|
|
4
|
+
import { agentsReport, listing, resultText } from "./agent-text.ts";
|
|
5
|
+
import { type AgentRunner, sessionFile } from "./agents.ts";
|
|
6
|
+
import { loadAgentTypes } from "./agent-files.ts";
|
|
7
|
+
import { type AgentDefinition, GENERAL_PURPOSE, type Settings } from "./config.ts";
|
|
8
|
+
import { isForegroundWait } from "./sleep-wait.ts";
|
|
9
|
+
|
|
10
|
+
// Claude Code's Agent tool lists every agent type, the user's included, with its description.
|
|
11
|
+
const typeLine = ([type, { description }]: [string, AgentDefinition]) => `- ${type === GENERAL_PURPOSE ? `${type} (default)` : type}${description ? `: ${description}` : ""}`;
|
|
12
|
+
|
|
13
|
+
const agentParams = (types: Map<string, AgentDefinition>) => Type.Object(
|
|
14
|
+
{
|
|
15
|
+
description: Type.String({ description: "A short (3-5 word) description of the task" }),
|
|
16
|
+
prompt: Type.String({ description: "The task for the agent to perform" }),
|
|
17
|
+
subagent_type: Type.Optional(
|
|
18
|
+
Type.String({
|
|
19
|
+
description: `Agent definition to run, one of:\n${[...types].map(typeLine).join("\n")}\nA name without the pstack: prefix, other than general-purpose, is an agent file in pstack-agents in the Pi agent directory, whose tools:, disallowedTools:, and isolation: fields are not applied.`,
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
model: Type.Optional(
|
|
23
|
+
Type.String({
|
|
24
|
+
description:
|
|
25
|
+
"Optional model for this agent: a family name (opus, fable, sonnet, haiku) or a full provider/id. If omitted, the agent runs on its agent file's model, else on the parent's model.",
|
|
26
|
+
}),
|
|
27
|
+
),
|
|
28
|
+
effort: Type.Optional(
|
|
29
|
+
Type.String({
|
|
30
|
+
description:
|
|
31
|
+
"Reasoning effort for this agent, one of the levels in models.json (low, medium, high, xhigh, max). If omitted, the agent runs at its agent file's effort, else at the parent's thinking level.",
|
|
32
|
+
}),
|
|
33
|
+
),
|
|
34
|
+
run_in_background: Type.Optional(Type.Boolean({ description: "Return at once; a completion notice arrives when the agent exits." })),
|
|
35
|
+
isolation: Type.Optional(Type.Unsafe<"worktree">({ type: "string", enum: ["worktree"], description: "Run the agent in its own git worktree." })),
|
|
36
|
+
readonly: Type.Optional(Type.Boolean({ description: "Run the agent without the edit and write tools." })),
|
|
37
|
+
},
|
|
38
|
+
{ additionalProperties: false },
|
|
39
|
+
);
|
|
40
|
+
export type AgentParams = Static<ReturnType<typeof agentParams>>;
|
|
41
|
+
|
|
42
|
+
const sendParams = Type.Object(
|
|
43
|
+
{
|
|
44
|
+
to: Type.String({ description: "agentId or the agent's description" }),
|
|
45
|
+
message: Type.String({ description: "The message to send" }),
|
|
46
|
+
},
|
|
47
|
+
{ additionalProperties: false },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const stopParams = Type.Object({ id: Type.String({ description: "agentId (or description) of the agent to stop" }) }, { additionalProperties: false });
|
|
51
|
+
|
|
52
|
+
// Claude Code's background launch result, word for word.
|
|
53
|
+
const BACKGROUND_NOTE =
|
|
54
|
+
"The agent is working in the background. You will be notified automatically when it completes. You know nothing about its results until that notification arrives — do not report, assume, or predict them; continue other work or respond to the user in the meantime.\nDo not duplicate this agent's work — avoid working with the same files or topics it is using.";
|
|
55
|
+
|
|
56
|
+
const SLEEP_BLOCKED =
|
|
57
|
+
"Blocked: a background agent is still running, and its completion notice arrives on its own. Do not sleep or poll for it. Continue other work, or end your turn. The notice starts your next one.";
|
|
58
|
+
|
|
59
|
+
// model-only exposure keeps every tool declared to the model even under
|
|
60
|
+
// codemode.mode "only", which would otherwise reach them only through scripts.
|
|
61
|
+
export function registerAgentTools(pi: ExtensionAPI, runner: AgentRunner, settings: Settings): void {
|
|
62
|
+
const lookups = { transcriptOf: sessionFile, activityOf: runner.activityOf.bind(runner) };
|
|
63
|
+
// The user's own view: shown, never sent to the model.
|
|
64
|
+
pi.registerCommand("pstack-agents", {
|
|
65
|
+
description: "Show each pstack agent's status, what a running one is doing, and its transcript",
|
|
66
|
+
async handler(_args, ctx) {
|
|
67
|
+
ctx.ui.notify(agentsReport(runner.list(), lookups), "info");
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
// Wording alone did not stop models from polling a background agent with
|
|
71
|
+
// sleep, which spends turns and leads them to cut the agent short.
|
|
72
|
+
pi.on("tool_call", (event) => {
|
|
73
|
+
if (!runner.busy || event.toolName !== "bash") return;
|
|
74
|
+
const { command } = event.input;
|
|
75
|
+
if (typeof command === "string" && isForegroundWait(command)) return { block: true, reason: SLEEP_BLOCKED };
|
|
76
|
+
});
|
|
77
|
+
pi.registerTool({
|
|
78
|
+
name: "agent",
|
|
79
|
+
label: "Agent",
|
|
80
|
+
exposure: "model-only",
|
|
81
|
+
description:
|
|
82
|
+
"Launch a subagent: a separate pi process with its own context. Foreground (default) waits and returns its final text; run_in_background returns an agentId at once and a completion notice arrives when it exits. Use send_message to steer a running agent or continue a finished one, stop_agent to stop one, list_agents to see them.",
|
|
83
|
+
promptSnippet: "Launch a subagent (foreground or background, optional worktree isolation)",
|
|
84
|
+
parameters: agentParams(loadAgentTypes(settings)),
|
|
85
|
+
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
86
|
+
const started = runner.start(params, ctx);
|
|
87
|
+
if (params.run_in_background) {
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: `${JSON.stringify({ agentId: started.agent.id, status: "running" })}\n\n${BACKGROUND_NOTE}` }],
|
|
90
|
+
details: { agentId: started.agent.id, status: "running" },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const onAbort = () => void runner.stop(started.agent.id);
|
|
94
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
95
|
+
const record = await runner.wait(started.agent.id).finally(() => signal?.removeEventListener("abort", onAbort));
|
|
96
|
+
return {
|
|
97
|
+
content: [{ type: "text", text: resultText(record, sessionFile(record.agent)) }],
|
|
98
|
+
details: { agentId: record.agent.id, status: record.status },
|
|
99
|
+
isError: record.status !== "completed",
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
pi.registerTool({
|
|
105
|
+
name: "send_message",
|
|
106
|
+
label: "Send message",
|
|
107
|
+
exposure: "model-only",
|
|
108
|
+
description:
|
|
109
|
+
"Send a message to an agent this session started, by agentId or description. A running agent reads it after its current tool calls and carries on in the same run, so one completion notice follows. A finished agent resumes in the background with its earlier context and sends a completion notice.",
|
|
110
|
+
parameters: sendParams,
|
|
111
|
+
async execute(_id, params) {
|
|
112
|
+
const { record, running } = await runner.send(params.to, params.message);
|
|
113
|
+
const text = running
|
|
114
|
+
? `Agent ${record.agent.id} is running; it reads the message after its current tool calls.`
|
|
115
|
+
: JSON.stringify({ agentId: record.agent.id, status: "running" });
|
|
116
|
+
return { content: [{ type: "text", text }], details: { agentId: record.agent.id, running } };
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
pi.registerTool({
|
|
121
|
+
name: "list_agents",
|
|
122
|
+
label: "List agents",
|
|
123
|
+
exposure: "model-only",
|
|
124
|
+
description:
|
|
125
|
+
"List every agent this session started with its status. running means the process is alive; completed, failed, and stopped are reported only after the process exited. sessionFile is the agent's transcript, once its first message is written: the user can follow it with tail -f, or render a finished one with pi --export. A running agent also lists activity: its current or latest tool call and its latest message. The user sees the same with /pstack-agents.",
|
|
126
|
+
parameters: Type.Object({}, { additionalProperties: false }),
|
|
127
|
+
async execute() {
|
|
128
|
+
const agents = listing(runner.list(), lookups);
|
|
129
|
+
return { content: [{ type: "text", text: JSON.stringify(agents, null, 2) }], details: { agents } };
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
pi.registerTool({
|
|
134
|
+
name: "stop_agent",
|
|
135
|
+
label: "Stop agent",
|
|
136
|
+
exposure: "model-only",
|
|
137
|
+
description:
|
|
138
|
+
"Stop a running agent: ends its pi process and the bash command it has running, and returns once the process has exited. A process a finished bash command left in the background is not stopped. Stopping a finished agent reports its final status unchanged.",
|
|
139
|
+
parameters: stopParams,
|
|
140
|
+
async execute(_id, params) {
|
|
141
|
+
const record = await runner.stop(params.id);
|
|
142
|
+
return {
|
|
143
|
+
content: [{ type: "text", text: JSON.stringify({ agentId: record.agent.id, status: record.status, exitCode: record.exitCode }) }],
|
|
144
|
+
details: { agentId: record.agent.id, status: record.status },
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import type { ExtensionAPI, ExtensionContext, SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { type Static, Type } from "typebox";
|
|
7
|
+
import { Value } from "typebox/value";
|
|
8
|
+
|
|
9
|
+
import { noticeOf, OUTPUT_CAP_BYTES, statusText, truncateUtf8 } from "./agent-text.ts";
|
|
10
|
+
import type { AgentParams } from "./agent-tools.ts";
|
|
11
|
+
import { type Activity, alive, type ChildExit, PiChild, terminateGroup } from "./child.ts";
|
|
12
|
+
import { loadAgentTypes } from "./agent-files.ts";
|
|
13
|
+
import { checkEffort, DEPTH_FLAG, GENERAL_PURPOSE, InvalidValueError, PSTACK_STATE_DIR, readSheet, resolveModel, type Settings } from "./config.ts";
|
|
14
|
+
import { ensureWorktree, planWorktree, settleWorktree, type Worktree, worktreeSchema } from "./worktree.ts";
|
|
15
|
+
|
|
16
|
+
const ENTRY_TYPE = "pstack-agents";
|
|
17
|
+
const STATUS_KEY = "pstack-agents";
|
|
18
|
+
// Claude Code lets agents nest three layers below the main session and withholds
|
|
19
|
+
// the Agent tool at the third.
|
|
20
|
+
const MAX_SPAWN_DEPTH = 3;
|
|
21
|
+
// Names the session a child's permission asks go to. @gotgenes/pi-permission-system
|
|
22
|
+
// relays them there while that session has a UI; without it a child answers them itself.
|
|
23
|
+
const PARENT_SESSION_ENV = "PI_SUBAGENT_PARENT_SESSION";
|
|
24
|
+
|
|
25
|
+
const endedStatus = Type.Union([Type.Literal("completed"), Type.Literal("failed"), Type.Literal("stopped")]);
|
|
26
|
+
type EndedStatus = Static<typeof endedStatus>;
|
|
27
|
+
|
|
28
|
+
// Fixed when the agent starts and reused by every launch of it, so a resume
|
|
29
|
+
// runs the same session, model, thinking, system prompt, and worktree.
|
|
30
|
+
const identitySchema = Type.Object({
|
|
31
|
+
id: Type.String(),
|
|
32
|
+
description: Type.String(),
|
|
33
|
+
subagentType: Type.String(),
|
|
34
|
+
model: Type.Optional(Type.String()),
|
|
35
|
+
thinking: Type.Optional(Type.String()),
|
|
36
|
+
readonly: Type.Optional(Type.Literal(true)),
|
|
37
|
+
// Pi's own rule for a session id (assertValidSessionId): a resume passes it
|
|
38
|
+
// to pi as an argument, so an empty or odd value must not load.
|
|
39
|
+
sessionId: Type.String({ pattern: "^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$" }),
|
|
40
|
+
sessionDir: Type.String(),
|
|
41
|
+
systemPromptFile: Type.Optional(Type.String()),
|
|
42
|
+
cwd: Type.String(),
|
|
43
|
+
worktree: Type.Optional(worktreeSchema),
|
|
44
|
+
startedAt: Type.String(),
|
|
45
|
+
});
|
|
46
|
+
const runningSchema = Type.Object({
|
|
47
|
+
agent: identitySchema,
|
|
48
|
+
status: Type.Literal("running"),
|
|
49
|
+
pid: Type.Optional(Type.Number()),
|
|
50
|
+
// When that pid started, as the system reports it. A pid can be reused; a
|
|
51
|
+
// pid with its start time names one process. Absent when it could not be
|
|
52
|
+
// read, and on a record an earlier version wrote.
|
|
53
|
+
pidStart: Type.Optional(Type.String()),
|
|
54
|
+
// The pi process that launched it. Only that process may reap it.
|
|
55
|
+
parentPid: Type.Number(),
|
|
56
|
+
});
|
|
57
|
+
const endedSchema = Type.Object({
|
|
58
|
+
agent: identitySchema,
|
|
59
|
+
status: endedStatus,
|
|
60
|
+
pid: Type.Optional(Type.Number()),
|
|
61
|
+
exitCode: Type.Union([Type.Number(), Type.Null()]),
|
|
62
|
+
endedAt: Type.String(),
|
|
63
|
+
finalText: Type.String(),
|
|
64
|
+
outputFile: Type.Optional(Type.String()),
|
|
65
|
+
worktreeKept: Type.Optional(Type.Boolean()),
|
|
66
|
+
});
|
|
67
|
+
// Persisted as a session entry, last write per agent id wins.
|
|
68
|
+
const recordSchema = Type.Union([runningSchema, endedSchema]);
|
|
69
|
+
|
|
70
|
+
type AgentIdentity = Static<typeof identitySchema>;
|
|
71
|
+
type RunningRecord = Static<typeof runningSchema>;
|
|
72
|
+
export type EndedRecord = Static<typeof endedSchema>;
|
|
73
|
+
export type AgentRecord = Static<typeof recordSchema>;
|
|
74
|
+
|
|
75
|
+
interface Run {
|
|
76
|
+
child: PiChild;
|
|
77
|
+
background: boolean;
|
|
78
|
+
// Set once the run is told to end: the exit code no longer decides the
|
|
79
|
+
// status. teardown means the session is going away, so no notice follows.
|
|
80
|
+
ending?: "stopped" | "teardown";
|
|
81
|
+
done: Promise<EndedRecord>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// A remote agent runs under the live pi process that restore left it to.
|
|
85
|
+
type LocalAgent = { kind: "local"; record: RunningRecord; run: Run };
|
|
86
|
+
// Unverified restores retry identity checks; interrupted ones await termination.
|
|
87
|
+
type AgentState = LocalAgent
|
|
88
|
+
| { kind: "remote"; record: RunningRecord }
|
|
89
|
+
| { kind: "unverified"; record: RunningRecord }
|
|
90
|
+
| { kind: "interrupted"; record: RunningRecord }
|
|
91
|
+
| { kind: "ended"; record: EndedRecord };
|
|
92
|
+
|
|
93
|
+
// How a run ended, from what its process left behind. A run that settled on a
|
|
94
|
+
// reply completed, whatever the exit code of the shutdown after it. Stderr
|
|
95
|
+
// diagnoses a failure; a stopped child's stderr is not its output (pi warns
|
|
96
|
+
// there on every first run of a --session-id).
|
|
97
|
+
function outcomeOf(exit: ChildExit, stopped: boolean): { status: EndedStatus; finalText: string } {
|
|
98
|
+
if (stopped) return { status: "stopped", finalText: exit.finalText || "(stopped before it replied)" };
|
|
99
|
+
if (exit.settled && exit.finalText && !exit.errorMessage) return { status: "completed", finalText: exit.finalText };
|
|
100
|
+
const diagnostics = exit.errorMessage || exit.stderr.trim();
|
|
101
|
+
const finalText = exit.finalText && diagnostics ? `${exit.finalText}\n\n${diagnostics}` : exit.finalText || diagnostics || "(no output)";
|
|
102
|
+
return { status: "failed", finalText };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// The text a record keeps: capped, with the full copy on disk when it was cut.
|
|
106
|
+
function saveOutput(identity: AgentIdentity, text: string): Pick<EndedRecord, "finalText" | "outputFile"> {
|
|
107
|
+
const capped = truncateUtf8(text, OUTPUT_CAP_BYTES);
|
|
108
|
+
if (capped === text) return { finalText: text };
|
|
109
|
+
const outputFile = join(identity.sessionDir, `${identity.id}.${Date.now()}.out.md`);
|
|
110
|
+
try {
|
|
111
|
+
writeFileSync(outputFile, text);
|
|
112
|
+
return { finalText: capped, outputFile };
|
|
113
|
+
} catch (e) {
|
|
114
|
+
return { finalText: `${capped}\n\n(full output not saved: ${(e as Error).message})` };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Pi names the file <timestamp>_<session id>.jsonl, reopens it on a resume,
|
|
119
|
+
// and writes it only once the first message is in.
|
|
120
|
+
export function sessionFile({ sessionDir, sessionId }: AgentIdentity): string | undefined {
|
|
121
|
+
try {
|
|
122
|
+
const name = readdirSync(sessionDir).find((n) => n.endsWith(`_${sessionId}.jsonl`));
|
|
123
|
+
return name && join(sessionDir, name);
|
|
124
|
+
} catch {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function settle(worktree: Worktree): { kept: boolean; note: string } {
|
|
130
|
+
try {
|
|
131
|
+
return { kept: settleWorktree(worktree), note: "" };
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return { kept: true, note: `\n\n(worktree cleanup failed: ${(e as Error).message})` };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function childArgs(identity: AgentIdentity, depth: number): string[] {
|
|
138
|
+
const args = ["--mode", "rpc", "--session-id", identity.sessionId, "--session-dir", identity.sessionDir];
|
|
139
|
+
if (identity.model) args.push("--model", identity.model);
|
|
140
|
+
if (identity.thinking) args.push("--thinking", identity.thinking);
|
|
141
|
+
if (identity.systemPromptFile) args.push("--append-system-prompt", identity.systemPromptFile);
|
|
142
|
+
// @gotgenes/pi-permission-system 42.0.0 names a forwarded ask's agent from this tag in the child's
|
|
143
|
+
// system prompt, and picks its per-agent permission policy by that name; without it the parent's
|
|
144
|
+
// dialog says "unknown".
|
|
145
|
+
args.push("--append-system-prompt", `<active_agent name="${identity.subagentType}" />`);
|
|
146
|
+
args.push(`--${DEPTH_FLAG}`, String(depth + 1));
|
|
147
|
+
const excluded = [...(identity.readonly ? ["edit", "write"] : []), ...(depth + 1 >= MAX_SPAWN_DEPTH ? ["agent"] : [])];
|
|
148
|
+
if (excluded.length) args.push("--exclude-tools", excluded.join(","));
|
|
149
|
+
return args;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// What the system records about a live process, or undefined when it cannot
|
|
153
|
+
// say. Neither value is the process's to change, unlike its arguments: pi sets
|
|
154
|
+
// its title, and ps then shows that in their place. Linux keeps both in /proc,
|
|
155
|
+
// the start as clock ticks since boot. ps works its start time out from the
|
|
156
|
+
// wall clock there, so a clock change moves it, and ps is asked only where
|
|
157
|
+
// /proc is missing, with the locale and time zone pinned so the text is the
|
|
158
|
+
// same on every read.
|
|
159
|
+
function inspect(pid: number): { parentPid: number; start: string } | undefined {
|
|
160
|
+
let stat = "";
|
|
161
|
+
try {
|
|
162
|
+
stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
163
|
+
} catch {}
|
|
164
|
+
// State, parent pid, and 17 more fields up to the start time. They follow
|
|
165
|
+
// the command name, which is in parentheses and may hold any character.
|
|
166
|
+
const proc = /^ \S (\d+)(?: \S+){17} (\d+) /.exec(stat.slice(stat.lastIndexOf(")") + 1));
|
|
167
|
+
if (proc) return { parentPid: Number(proc[1]), start: proc[2] };
|
|
168
|
+
const ps = spawnSync("ps", ["-o", "ppid=", "-o", "lstart=", "-p", String(pid)], { encoding: "utf8", env: { ...process.env, LC_ALL: "C", TZ: "UTC" } });
|
|
169
|
+
const m = ps.status === 0 ? /^\s*(\d+)\s+(\S.*\S)\s*$/.exec(ps.stdout) : null;
|
|
170
|
+
return m ? { parentPid: Number(m[1]), start: m[2] } : undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// What became of the process a running record names:
|
|
174
|
+
// - kept: it is still a child of the live pi process that launched it;
|
|
175
|
+
// - orphan: it is the process the record was written for, its launcher gone;
|
|
176
|
+
// - unknown: a process is there, and nothing says whether it is the agent's;
|
|
177
|
+
// - gone: no process is there, or another one is.
|
|
178
|
+
type Fate = "kept" | "orphan" | "unknown" | "gone";
|
|
179
|
+
|
|
180
|
+
function fateOf(record: RunningRecord): Fate {
|
|
181
|
+
const { pid, pidStart, parentPid } = record;
|
|
182
|
+
if (pid === undefined || !alive(pid)) return "gone";
|
|
183
|
+
const info = inspect(pid);
|
|
184
|
+
if (info && pidStart !== undefined && info.start !== pidStart) return "gone";
|
|
185
|
+
// With no word from the system, two live pids keep the record: calling a
|
|
186
|
+
// live agent stopped would let a message start a second process on its session.
|
|
187
|
+
const launcherHasIt = info ? info.parentPid === parentPid : alive(parentPid);
|
|
188
|
+
if (parentPid !== process.pid && launcherHasIt) return "kept";
|
|
189
|
+
return info && info.start === pidStart ? "orphan" : "unknown";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Stops an orphan, by its group so the bash command it has running goes too.
|
|
193
|
+
// No other fate is signalled: a pid that may have been reused is not ours to hit.
|
|
194
|
+
function reapOrphan(record: RunningRecord, killGraceMs: number): Promise<void> {
|
|
195
|
+
return record.pid === undefined ? Promise.resolve() : terminateGroup(record.pid, () => fateOf(record) === "orphan", killGraceMs);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const now = () => new Date().toISOString();
|
|
199
|
+
|
|
200
|
+
// A value the call left out came from the agent file, which the caller never
|
|
201
|
+
// saw, so an error over the value names that file.
|
|
202
|
+
function fromAgentFile<T>(file: string | undefined, passed: string | undefined, resolve: () => T): T {
|
|
203
|
+
try {
|
|
204
|
+
return resolve();
|
|
205
|
+
} catch (e) {
|
|
206
|
+
if (passed !== undefined || file === undefined || !(e instanceof InvalidValueError)) throw e;
|
|
207
|
+
throw new Error(`${file}: ${(e as Error).message}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export class AgentRunner {
|
|
212
|
+
private readonly agents = new Map<string, AgentState>();
|
|
213
|
+
// Set once the session tears its agents down; a launch after that would
|
|
214
|
+
// start a child nothing stops.
|
|
215
|
+
private closed = false;
|
|
216
|
+
// The footer of the top-level session only: a child's status would go to its
|
|
217
|
+
// parent's stdout, which the reader ignores.
|
|
218
|
+
private ui?: ExtensionContext["ui"];
|
|
219
|
+
private ownSessionId?: string;
|
|
220
|
+
|
|
221
|
+
constructor(
|
|
222
|
+
private readonly pi: ExtensionAPI,
|
|
223
|
+
private readonly settings: Settings,
|
|
224
|
+
) {}
|
|
225
|
+
|
|
226
|
+
start(params: AgentParams, ctx: ExtensionContext): RunningRecord {
|
|
227
|
+
const type = params.subagent_type || GENERAL_PURPOSE;
|
|
228
|
+
const types = loadAgentTypes(this.settings);
|
|
229
|
+
const def = types.get(type);
|
|
230
|
+
if (!def) throw new Error(`Unknown subagent_type "${type}". Valid types: ${[...types.keys()].join(", ")}.`);
|
|
231
|
+
const parentModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
232
|
+
const model = fromAgentFile(def.file, params.model, () => resolveModel(params.model ?? def.model, this.settings, readSheet(this.settings.agentDir), parentModel));
|
|
233
|
+
// Claude Code subagents without an effort run at their definition's effort, else the session's.
|
|
234
|
+
const effort = params.effort ?? def.effort;
|
|
235
|
+
const thinking = effort === undefined ? this.pi.getThinkingLevel() : fromAgentFile(def.file, params.effort, () => checkEffort(effort, this.settings));
|
|
236
|
+
|
|
237
|
+
const id = `a${randomBytes(8).toString("hex")}`;
|
|
238
|
+
const state = join(this.settings.agentDir, PSTACK_STATE_DIR, ctx.sessionManager.getSessionId());
|
|
239
|
+
const sessionDir = join(state, "agents");
|
|
240
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
241
|
+
const systemPromptFile = def.body ? join(state, "prompts", `${id}.md`) : undefined;
|
|
242
|
+
const worktree = params.isolation === "worktree" ? planWorktree(ctx.cwd, id) : undefined;
|
|
243
|
+
const identity: AgentIdentity = {
|
|
244
|
+
id,
|
|
245
|
+
description: params.description,
|
|
246
|
+
subagentType: type,
|
|
247
|
+
model,
|
|
248
|
+
thinking,
|
|
249
|
+
readonly: params.readonly || undefined,
|
|
250
|
+
sessionId: randomUUID(),
|
|
251
|
+
sessionDir,
|
|
252
|
+
systemPromptFile,
|
|
253
|
+
cwd: worktree?.path ?? ctx.cwd,
|
|
254
|
+
worktree,
|
|
255
|
+
startedAt: now(),
|
|
256
|
+
};
|
|
257
|
+
this.attachSession(ctx);
|
|
258
|
+
return this.launch(identity, params.prompt, params.run_in_background === true);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private launch(identity: AgentIdentity, prompt: string, background: boolean): RunningRecord {
|
|
262
|
+
if (this.closed) throw new Error("This session is shutting down; no agent can start.");
|
|
263
|
+
try {
|
|
264
|
+
// First, so a failure here leaves no worktree or branch behind.
|
|
265
|
+
this.ensureSystemPrompt(identity);
|
|
266
|
+
if (identity.worktree) ensureWorktree(identity.worktree);
|
|
267
|
+
} catch (e) {
|
|
268
|
+
// A resume that cannot launch leaves the agent's record as its last run ended.
|
|
269
|
+
if (!this.agents.has(identity.id)) {
|
|
270
|
+
const failed: EndedRecord = { agent: identity, status: "failed", exitCode: null, endedAt: now(), finalText: (e as Error).message };
|
|
271
|
+
this.agents.set(identity.id, { kind: "ended", record: failed });
|
|
272
|
+
this.persist(failed);
|
|
273
|
+
}
|
|
274
|
+
throw e;
|
|
275
|
+
}
|
|
276
|
+
const { command, args } = this.settings.pi;
|
|
277
|
+
const child = new PiChild(
|
|
278
|
+
command,
|
|
279
|
+
[...args, "--extension", join(this.settings.pluginRoot, "pi", "index.ts"), "--skill", join(this.settings.pluginRoot, "skills"), ...childArgs(identity, this.settings.depth)],
|
|
280
|
+
{ cwd: identity.cwd, env: { [PARENT_SESSION_ENV]: this.ownSessionId }, exitGraceMs: this.settings.exitGraceMs, onActivity: () => this.showStatus() },
|
|
281
|
+
prompt,
|
|
282
|
+
);
|
|
283
|
+
const pidStart = child.pid === undefined ? undefined : inspect(child.pid)?.start;
|
|
284
|
+
const record: RunningRecord = { agent: identity, status: "running", pid: child.pid, pidStart, parentPid: process.pid };
|
|
285
|
+
const run: Run = { child, background, done: child.exited.then((exit) => this.finish(identity, run, exit)) };
|
|
286
|
+
this.agents.set(identity.id, { kind: "local", record, run });
|
|
287
|
+
this.persist(record);
|
|
288
|
+
this.showStatus();
|
|
289
|
+
return record;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// From session_start too: a reloaded session can resume an agent with
|
|
293
|
+
// send_message before any agent call.
|
|
294
|
+
attachSession(ctx: ExtensionContext): void {
|
|
295
|
+
this.ownSessionId = ctx.sessionManager.getSessionId();
|
|
296
|
+
if (ctx.hasUI && this.settings.depth === 0) this.ui = ctx.ui;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private showStatus(): void {
|
|
300
|
+
const running = this.locals().map(({ record, run }) => ({ id: record.agent.id, at: run.child.activity?.at ?? record.agent.startedAt, activity: run.child.activity }));
|
|
301
|
+
this.ui?.setStatus(STATUS_KEY, statusText(running));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// A running agent's live activity, which only a local one has.
|
|
305
|
+
activityOf(agent: AgentIdentity): Activity | undefined {
|
|
306
|
+
const state = this.agents.get(agent.id);
|
|
307
|
+
return state?.kind === "local" ? state.run.child.activity : undefined;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Pi appends a path it cannot find as the prompt text itself.
|
|
311
|
+
private ensureSystemPrompt(identity: AgentIdentity): void {
|
|
312
|
+
const file = identity.systemPromptFile;
|
|
313
|
+
if (!file || existsSync(file)) return;
|
|
314
|
+
const body = loadAgentTypes(this.settings).get(identity.subagentType)?.body;
|
|
315
|
+
if (!body) throw new Error(`Agent ${identity.id} has lost its system prompt file, and its type "${identity.subagentType}" no longer provides one.`);
|
|
316
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
317
|
+
writeFileSync(file, body, { mode: 0o600 });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private finish(identity: AgentIdentity, run: Run, exit: ChildExit): EndedRecord {
|
|
321
|
+
const { status, finalText } = outcomeOf(exit, run.ending !== undefined);
|
|
322
|
+
const worktree = identity.worktree && settle(identity.worktree);
|
|
323
|
+
const record: EndedRecord = {
|
|
324
|
+
agent: identity,
|
|
325
|
+
status,
|
|
326
|
+
pid: run.child.pid,
|
|
327
|
+
exitCode: exit.exitCode,
|
|
328
|
+
endedAt: now(),
|
|
329
|
+
worktreeKept: worktree?.kept,
|
|
330
|
+
...saveOutput(identity, finalText + (worktree?.note ?? "")),
|
|
331
|
+
};
|
|
332
|
+
this.agents.set(identity.id, { kind: "ended", record });
|
|
333
|
+
this.persist(record);
|
|
334
|
+
this.showStatus();
|
|
335
|
+
// The model that called stop_agent already has the result, so a stop's
|
|
336
|
+
// notice joins the context without starting another turn.
|
|
337
|
+
if (run.background && run.ending !== "teardown") {
|
|
338
|
+
this.pi.sendMessage(noticeOf(record, sessionFile(identity)), status !== "stopped" ? { triggerTurn: true, deliverAs: "steer" } : { triggerTurn: false });
|
|
339
|
+
}
|
|
340
|
+
return record;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// The end of the agent's run in flight, or its record when it has ended.
|
|
344
|
+
async wait(id: string): Promise<EndedRecord> {
|
|
345
|
+
const state = this.owned(id);
|
|
346
|
+
return state.kind === "local" ? state.run.done : state.record;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private locals(): LocalAgent[] {
|
|
350
|
+
return [...this.agents.values()].filter((state): state is LocalAgent => state.kind === "local");
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
get busy(): boolean {
|
|
354
|
+
return this.locals().length > 0;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Resolves once the first running agent exits, at once when none is running.
|
|
358
|
+
async nextExit(): Promise<void> {
|
|
359
|
+
const locals = this.locals();
|
|
360
|
+
if (locals.length) await Promise.race(locals.map((state) => state.run.done));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private find(to: string): AgentState {
|
|
364
|
+
const byId = this.agents.get(to);
|
|
365
|
+
if (byId) return this.refreshRestored(byId);
|
|
366
|
+
const states = [...this.agents.values()];
|
|
367
|
+
const matches = states.filter((state) => state.record.agent.description === to);
|
|
368
|
+
if (matches.length === 1) return this.refreshRestored(matches[0]);
|
|
369
|
+
if (matches.length > 1) {
|
|
370
|
+
throw new Error(`"${to}" matches several agents (${matches.map((state) => state.record.agent.id).join(", ")}); pass an agentId.`);
|
|
371
|
+
}
|
|
372
|
+
const known = states.map(({ record }) => `${record.agent.id} (${record.agent.description})`);
|
|
373
|
+
throw new Error(`No agent "${to}". Known agents: ${known.join(", ") || "none"}.`);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// An agent this process can act on. One running under another pi process is
|
|
377
|
+
// not: only that process holds its stdin and can message or stop it.
|
|
378
|
+
private owned(to: string): Exclude<AgentState, { kind: "remote" | "unverified" | "interrupted" }> {
|
|
379
|
+
const state = this.find(to);
|
|
380
|
+
if (state.kind === "remote") {
|
|
381
|
+
throw new Error(`Agent ${state.record.agent.id} is running under another pi process (pid ${state.record.parentPid}); only that process can message or stop it.`);
|
|
382
|
+
}
|
|
383
|
+
if (state.kind === "unverified" || state.kind === "interrupted") {
|
|
384
|
+
throw new Error(`Agent ${state.record.agent.id}'s previous process (pid ${state.record.pid}) has not exited; it cannot resume or be stopped here until its exit is confirmed.`);
|
|
385
|
+
}
|
|
386
|
+
return state;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// A running agent takes the message as a steer, after its current tool calls.
|
|
390
|
+
// A finished one, or one that has settled and is exiting, resumes with it,
|
|
391
|
+
// including one that settled just before the steer reached it.
|
|
392
|
+
async send(to: string, message: string): Promise<{ record: AgentRecord; running: boolean }> {
|
|
393
|
+
const { id } = this.owned(to).record.agent;
|
|
394
|
+
// Another send may have launched a run while this one awaited, so the state
|
|
395
|
+
// is read again after every wait and the launch follows the last read.
|
|
396
|
+
for (let state = this.agents.get(id); state?.kind === "local"; state = this.agents.get(id)) {
|
|
397
|
+
const { run } = state;
|
|
398
|
+
const { response, taken } = await run.child.steer(message);
|
|
399
|
+
if (taken) return { record: this.find(id).record, running: true };
|
|
400
|
+
if (response && !response.success) throw new Error(`Agent ${id} did not take the message: ${response.error}`);
|
|
401
|
+
await run.done;
|
|
402
|
+
if (run.ending) throw new Error(`Agent ${id} was stopped before it read the message; it was not delivered.`);
|
|
403
|
+
}
|
|
404
|
+
return { record: this.launch(this.find(id).record.agent, message, true), running: false };
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
async stop(to: string, ending: NonNullable<Run["ending"]> = "stopped"): Promise<EndedRecord> {
|
|
408
|
+
const state = this.owned(to);
|
|
409
|
+
if (state.kind === "ended") return state.record;
|
|
410
|
+
const { run } = state;
|
|
411
|
+
if (run.ending !== "teardown") run.ending = ending;
|
|
412
|
+
void run.child.command({ type: "abort" });
|
|
413
|
+
run.child.end(this.settings.killGraceMs);
|
|
414
|
+
return run.done;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async stopAll(): Promise<void> {
|
|
418
|
+
this.closed = true;
|
|
419
|
+
await Promise.all(this.locals().map((state) => this.stop(state.record.agent.id, "teardown")));
|
|
420
|
+
this.ui?.setStatus(STATUS_KEY, undefined);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// For an exit that cannot wait: SIGTERM lets each child pi stop its own agents.
|
|
424
|
+
signalAll(): void {
|
|
425
|
+
this.closed = true;
|
|
426
|
+
for (const { run } of this.locals()) {
|
|
427
|
+
run.ending = "teardown";
|
|
428
|
+
run.child.signal("SIGTERM");
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
list(): AgentRecord[] {
|
|
433
|
+
return [...this.agents.values()].map((state) => this.refreshRestored(state).record);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
private persist(record: AgentRecord): void {
|
|
437
|
+
this.pi.appendEntry(ENTRY_TYPE, record);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
private refreshRestored(state: AgentState): AgentState {
|
|
441
|
+
if (state.kind === "local" || state.kind === "ended") return state;
|
|
442
|
+
const { record } = state;
|
|
443
|
+
const fate = fateOf(record);
|
|
444
|
+
if (fate === "kept" && state.kind === "remote") return state;
|
|
445
|
+
if (fate !== "gone") {
|
|
446
|
+
if (state.kind === "interrupted") return state;
|
|
447
|
+
const restored: AgentState = {
|
|
448
|
+
kind: fate === "orphan" ? "interrupted" : "unverified",
|
|
449
|
+
record,
|
|
450
|
+
};
|
|
451
|
+
this.agents.set(record.agent.id, restored);
|
|
452
|
+
if (restored.kind === "interrupted") {
|
|
453
|
+
void reapOrphan(record, this.settings.killGraceMs).then(() => {
|
|
454
|
+
if (this.agents.get(record.agent.id) === restored) {
|
|
455
|
+
this.agents.set(record.agent.id, { kind: "unverified", record });
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return restored;
|
|
460
|
+
}
|
|
461
|
+
const stopped: EndedRecord = {
|
|
462
|
+
agent: record.agent,
|
|
463
|
+
status: "stopped",
|
|
464
|
+
pid: record.pid,
|
|
465
|
+
exitCode: null,
|
|
466
|
+
endedAt: now(),
|
|
467
|
+
finalText: "(interrupted: the session that started it ended)",
|
|
468
|
+
};
|
|
469
|
+
const ended: AgentState = { kind: "ended", record: stopped };
|
|
470
|
+
this.agents.set(record.agent.id, ended);
|
|
471
|
+
this.persist(stopped);
|
|
472
|
+
return ended;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// A restored process stays unavailable until its exit is confirmed. Only a
|
|
476
|
+
// process whose identity matches the record can be signalled.
|
|
477
|
+
restore(entries: readonly SessionEntry[]): void {
|
|
478
|
+
for (const entry of entries) {
|
|
479
|
+
if (entry.type !== "custom" || entry.customType !== ENTRY_TYPE || !Value.Check(recordSchema, entry.data)) continue;
|
|
480
|
+
const { id } = entry.data.agent;
|
|
481
|
+
if (this.agents.get(id)?.kind === "local") continue;
|
|
482
|
+
this.agents.set(id, entry.data.status === "running" ? { kind: "remote", record: entry.data } : { kind: "ended", record: entry.data });
|
|
483
|
+
}
|
|
484
|
+
for (const state of this.agents.values()) this.refreshRestored(state);
|
|
485
|
+
}
|
|
486
|
+
}
|