@justjoshn/pi-pstack 0.15.36-pi.1 → 0.15.36-pi.12
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/CHANGELOG.md +94 -0
- package/README.md +29 -24
- package/agents/ci-watcher.md +28 -0
- package/agents/thermo-nuclear-code-quality-review.md +23 -0
- package/assets/logo.png +0 -0
- package/automations/benny/FOR_AGENTS.md +2 -1
- package/automations/benny/README.md +2 -2
- package/automations/benny/skills/setup-benny/SKILL.md +10 -9
- package/automations/benny/templates/reproduce-automation-prompt.md +1 -1
- package/automations/benny/templates/triage-automation-prompt.md +1 -1
- package/bin/pstack-routines-supervisor +9 -0
- package/docs/guide/01-setup.md +2 -2
- package/docs/guide/07-overnight.md +1 -1
- package/docs/guide/09-make-it-yours.md +1 -1
- package/docs/guide/10-recipes-and-pitfalls.md +1 -1
- package/docs/native-gaps.md +14 -8
- package/docs/parity-reverse-engineering.md +94 -0
- package/docs/parity-status.md +128 -0
- package/package.json +41 -6
- package/packaging/install-supervisor-unit.sh +164 -0
- package/packaging/launchd/com.pstack.routines-supervisor.plist.example +24 -0
- package/packaging/systemd/pstack-routines-supervisor.service.example +15 -0
- package/skills/architect/SKILL.md +1 -1
- package/skills/architect/references/runner-prompt.md +1 -1
- package/skills/arena/SKILL.md +4 -4
- package/skills/check-compiler-errors/SKILL.md +23 -0
- package/skills/create-skill/SKILL.md +515 -29
- package/skills/fix-ci/SKILL.md +29 -0
- package/skills/fix-merge-conflicts/SKILL.md +32 -0
- package/skills/get-pr-comments/SKILL.md +23 -0
- package/skills/how/SKILL.md +1 -1
- package/skills/ketchup/SKILL.md +2 -2
- package/skills/ketchup-video/SKILL.md +2 -2
- package/skills/loop-on-ci/SKILL.md +50 -0
- package/skills/make-bot-ui/SKILL.md +2 -2
- package/skills/make-pr-easy-to-review/SKILL.md +59 -0
- package/skills/new-branch-and-pr/SKILL.md +29 -0
- package/skills/no-inline-imports/SKILL.md +12 -0
- package/skills/poteto-help/SKILL.md +4 -4
- package/skills/poteto-mode/SKILL.md +2 -2
- package/skills/poteto-mode/playbooks/bug-fix.md +1 -1
- package/skills/poteto-mode/playbooks/feature.md +1 -1
- package/skills/poteto-mode/playbooks/hillclimb.md +1 -1
- package/skills/poteto-mode/playbooks/multi-phase-plan.md +2 -2
- package/skills/poteto-mode/playbooks/orchestrate.md +2 -2
- package/skills/poteto-mode/playbooks/perf-issue.md +1 -1
- package/skills/poteto-mode/playbooks/refactoring.md +1 -1
- package/skills/pr-review-canvas/SKILL.md +176 -0
- package/skills/pr-review-canvas/renderer.js +170 -0
- package/skills/pr-review-canvas/styles.css +96 -0
- package/skills/pr-review-canvas/template.html +18 -0
- package/skills/reflect/SKILL.md +2 -2
- package/skills/review-and-ship/SKILL.md +41 -0
- package/skills/run-smoke-tests/SKILL.md +42 -0
- package/skills/setup-pstack/SKILL.md +13 -13
- package/skills/statechart/scripts/test/cli.test.ts +1 -1
- package/skills/swarm/SKILL.md +2 -2
- package/skills/teach/SKILL.md +1 -1
- package/skills/thermo-nuclear-code-quality-review/SKILL.md +192 -0
- package/skills/typescript-exhaustive-switch/SKILL.md +10 -0
- package/skills/verify-this/SKILL.md +74 -0
- package/skills/weekly-review/SKILL.md +32 -0
- package/skills/what-did-i-get-done/SKILL.md +31 -0
- package/skills/why/SKILL.md +2 -2
- package/skills/workflow-from-chats/SKILL.md +50 -0
- package/src/ask.ts +24 -10
- package/src/child-env.ts +15 -2
- package/src/generate-image.ts +98 -0
- package/src/index.ts +28 -9
- package/src/loop.ts +74 -17
- package/src/mode.ts +89 -27
- package/src/paths.ts +18 -0
- package/src/pi-command.ts +12 -0
- package/src/plan.ts +285 -30
- package/src/rule.ts +4 -4
- package/src/sections.ts +27 -3
- package/src/subscriptions/durable-store.ts +531 -0
- package/src/subscriptions/durable-types.ts +69 -0
- package/src/subscriptions/ensure-supervisor.ts +67 -0
- package/src/subscriptions/index.ts +310 -282
- package/src/subscriptions/supervisor-main.ts +134 -0
- package/src/subscriptions/supervisor.ts +325 -0
- package/src/subscriptions/webhook.ts +82 -21
- package/src/task/agents.ts +39 -3
- package/src/task/card.ts +31 -0
- package/src/task/format.ts +17 -3
- package/src/task/models.ts +7 -0
- package/src/task/progress.ts +112 -0
- package/src/task/records.ts +7 -9
- package/src/task/registry.ts +9 -4
- package/src/task/runner.ts +116 -24
- package/src/task/stop.ts +3 -3
- package/src/task/tool.ts +158 -57
- package/src/task/worktree.ts +5 -3
- package/src/todo.ts +29 -4
- package/scripts/live-e2e.mjs +0 -257
- package/test/aliases.test.ts +0 -57
- package/test/ask.test.ts +0 -85
- package/test/autocomplete.test.ts +0 -39
- package/test/e2e/aliases.e2e.test.ts +0 -81
- package/test/e2e/ask.e2e.test.ts +0 -135
- package/test/e2e/harness.ts +0 -179
- package/test/e2e/host.e2e.test.ts +0 -193
- package/test/e2e/lifecycle.e2e.test.ts +0 -99
- package/test/e2e/mode.e2e.test.ts +0 -160
- package/test/e2e/package.e2e.test.ts +0 -67
- package/test/e2e/task.e2e.test.ts +0 -734
- package/test/e2e/todo.e2e.test.ts +0 -59
- package/test/fixtures/cursor-askquestion-calls.json +0 -806
- package/test/fixtures/fake-pi.mjs +0 -96
- package/test/fixtures/image-model.ts +0 -16
- package/test/fixtures/list-models.ts +0 -15
- package/test/fixtures/readonly-shell-exit.ts +0 -17
- package/test/fixtures/scripted-model.ts +0 -113
- package/test/loop.test.ts +0 -209
- package/test/mode.test.ts +0 -143
- package/test/plan.test.ts +0 -126
- package/test/readonly-shell-security.test.ts +0 -84
- package/test/readonly-shell.test.ts +0 -44
- package/test/records.test.ts +0 -143
- package/test/registry.test.ts +0 -18
- package/test/resources.test.ts +0 -162
- package/test/rule.test.ts +0 -92
- package/test/scripts.test.ts +0 -182
- package/test/sections.test.ts +0 -56
- package/test/subscriptions-cron.test.ts +0 -60
- package/test/subscriptions.test.ts +0 -598
- package/test/task-agents.test.ts +0 -49
- package/test/task-card.test.ts +0 -34
- package/test/task-fork.test.ts +0 -233
- package/test/task-format.test.ts +0 -65
- package/test/task-model.test.ts +0 -141
- package/test/task-runner.test.ts +0 -259
- package/test/task-schema.test.ts +0 -50
- package/test/task-status.test.ts +0 -155
- package/test/task-worktree.test.ts +0 -106
- package/test/todo.test.ts +0 -74
- package/test/visualize.test.ts +0 -152
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -16
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.15.36-pi.12] - 2026-11-04
|
|
4
|
+
|
|
5
|
+
Each item below was checked against Cursor CLI 2026.10.22 with pstack and cursor-team-kit loaded, through its bundle and live runs. `parity/pi-pstack-behavior-parity/` in the repository records the evidence and the decisions.
|
|
6
|
+
|
|
7
|
+
- A mode keeps its skill in context on every request until the user leaves it, as a Cursor Custom Mode does, and sends Cursor's notices: entered, the per-turn reminder, and an exit or switch notice once. The previous version sent the body on one request only, so models that replay the system prompt lost it.
|
|
8
|
+
- A background completion arrives as Cursor's system notification: its preamble, a title from the first line of the prompt (80 characters at most), and its follow-up request. The background launch text and the Agent ID line use Cursor's wording.
|
|
9
|
+
- Task, TodoWrite, and AskQuestion descriptions carry Cursor's usage rules, and AskQuestion needs two options per question. The model list adds Cursor's rules for user-requested models.
|
|
10
|
+
- Add Cursor's built-in `explore` subagent type, a file-search specialist with Pi's search tools and no Task tool. team-kit's thermo-nuclear agent text, which names it, is upstream's again.
|
|
11
|
+
- Every subagent hears Cursor's reminder that it runs under a parent and spawns no subagents unless asked.
|
|
12
|
+
- Add `GenerateImage`, Cursor's image tool, on Pi's image models. It is offered when an image model is available and saves each image to the session's artifacts folder. `teach` asks for the image tool again, as upstream does.
|
|
13
|
+
- Stop attaching `typescript-best-practices` when a `.ts` file is read. Cursor loads a skill that sets `paths` and `disable-model-invocation` only when invoked by name.
|
|
14
|
+
- Plan mode follows Cursor's: its instructions, `CreatePlan {plan, name, overview, todos}` writing Cursor's plan file, edits to markdown files only, `SwitchMode` with the user's consent, and a build-locally, build-in-a-worker, or propose-changes choice after a saved plan. `create_plan` is gone.
|
|
15
|
+
- A `/loop` wake that comes due during a run fires once when the run settles. A fixed tick was dropped before, and an agent-paced wake that landed during another run stopped the loop.
|
|
16
|
+
- `make-bot-ui` describes webhook routines as they behave: no default expiry, and `sessionStrategy: "new_session"` for webhooks.
|
|
17
|
+
|
|
18
|
+
## [0.15.36-pi.11] - 2026-11-04
|
|
19
|
+
|
|
20
|
+
- Title a background completion notice with the Task `description`, as Cursor names a subagent, instead of a slice of its prompt.
|
|
21
|
+
- Stream a foreground Task's last tool steps and latest line into its card while the child works, the way Cursor shows conversation steps.
|
|
22
|
+
- `/loop` accepts the interval first or last, in unit words (`10 minutes`, `every 10 minutes`), prints usage for a bare command, and keeps wall-clock cadence so a long run does not delay the next tick.
|
|
23
|
+
- A bare `/plan` enters plan mode as Cursor's plan command does, and plan mode keeps `stop_agent` so a launched child can be stopped.
|
|
24
|
+
- Attach a skill whose frontmatter declares `paths`/`globs` (including the shipped `typescript-best-practices`) when the session reads or edits a matching file, once per session.
|
|
25
|
+
- Inject the shipped always-applied engineering rules as their full text instead of a paraphrase.
|
|
26
|
+
- Put the current todo list in every request's system prompt so compaction and branch switches do not drop it.
|
|
27
|
+
- Start `cloud_base_branch` from `origin/<branch>` when that ref exists, falling back to a local ref.
|
|
28
|
+
- Say that a resume ignores a supplied `subagent_type` instead of dropping it silently.
|
|
29
|
+
- Record a detached `new_session` fire's own final message as its run output in `list_subscriptions`.
|
|
30
|
+
- Restore the upstream Benny commit-before-enable gate and sweep from the last successful sweep so downtime does not lose reports.
|
|
31
|
+
- Restore the architect runner prompt's independence sentence, describe `visualize` as a bar or line chart, and deliver screenshots and video the way Pi can.
|
|
32
|
+
- A webhook routine accepts `sessionStrategy: "new_session"`, so an accepted POST runs detached with no chat open, as a Cursor Automation does, and records its outcome. Older stored routines keep `wake_self`.
|
|
33
|
+
- A timer or webhook routine no longer expires after seven days. Cursor defines no automation expiry, so `expiresInHours` is the only limit; `0` means none, and a GitHub watch keeps its 7-day default.
|
|
34
|
+
- Each workspace binds its own routines port: a busy default falls back to an ephemeral port the workspace reuses and reports, while an explicit `PSTACK_ROUTINES_PORT` still reports a collision.
|
|
35
|
+
- A mode attaches its skill body on the request that enters it and sends a path-naming reminder on later requests, as Cursor's Custom Mode does, instead of re-sending the whole body every turn.
|
|
36
|
+
- Plan mode saves a `.plan.md` artifact through `create_plan`, and `/plan build` starts the work from the saved file.
|
|
37
|
+
|
|
38
|
+
## [0.15.36-pi.10] - 2026-11-03
|
|
39
|
+
|
|
40
|
+
- Resume and fork a descendant that a worktree worker started inside its worktree, from the root chat, while keeping unrelated-directory records refused.
|
|
41
|
+
- Recover a steering message stranded at settlement with its recorded images and its own message boundary instead of joining text and dropping attachments.
|
|
42
|
+
- Refuse a new subscription event with HTTP 503 and `Retry-After` when 20 events are undelivered, instead of evicting an event the sender was told was accepted.
|
|
43
|
+
- Keep accepted `new_session` work eligible after the subscription expires; expiry only stops new occurrences.
|
|
44
|
+
- Run a `new_session` timer on the model, thinking level, and project-trust decision it was created with, live or detached.
|
|
45
|
+
- Append Task settle-time notices to entries another extension proposed at the same boundary.
|
|
46
|
+
- Signal a pre-epoch supervisor lock only when its command line identifies this supervisor, so a reused pid cannot target an unrelated process.
|
|
47
|
+
- Report durable subscriptions and detached supervision in the host section instead of saying they live only in the current Pi process.
|
|
48
|
+
|
|
49
|
+
## [0.15.36-pi.9] - 2026-11-03
|
|
50
|
+
|
|
51
|
+
- Follow the repository Vitest rules in the test suite. No runtime change.
|
|
52
|
+
- Correct stale documentation against the current code, including versions, counts, paths and host requirements.
|
|
53
|
+
|
|
54
|
+
## [0.15.36-pi.8] - 2026-11-02
|
|
55
|
+
|
|
56
|
+
- Declare `cost.totalFromProvider` on the exported `Usage` type so the package typechecks again, completing the provider-reported cost provenance aggregation shipped in 0.15.36-pi.7.
|
|
57
|
+
|
|
58
|
+
## [0.15.36-pi.7] - 2026-11-02
|
|
59
|
+
|
|
60
|
+
- Update the host compatibility documentation for Pi 1.5.0. Retain the four native gaps for RPC process control, skill-block formatting, named-ID fork truncation, and workspace folder naming.
|
|
61
|
+
- Keep earlier verification records unchanged. This documentation audit does not claim new runtime-test results or complete upstream parity.
|
|
62
|
+
- Preserve string-enum argument shapes and optional literal types with TypeBox schemas under Pi 1.5.0 validation.
|
|
63
|
+
- Preserve provider-reported cost provenance when aggregating subagent usage.
|
|
64
|
+
- Ship a versioned package-root changelog entry for Pi 1.5.0's extension update notices.
|
|
65
|
+
|
|
66
|
+
## [0.15.36-pi.6]
|
|
67
|
+
|
|
68
|
+
- Implement version-2 durable subscription registry with transactional file locking, native owner continuation delivery via `pi.sendMessage`, bounded exponential retry on detached failures, per-subscription queue caps, non-blocking GitHub arming, legacy supervisor termination, and in-process fallback isolation.
|
|
69
|
+
- Decode child RPC stdout streams using `StringDecoder` to preserve split multibyte UTF-8 code points across buffer boundaries.
|
|
70
|
+
- Publish upstream pstack git commit provenance in `pstackSource` and exclude nested script dependencies from npm publication archives via `skills/.npmignore`.
|
|
71
|
+
- Canonicalize statechart symlink test fixture paths on macOS and add checksum-verified TLC statechart verification to CI.
|
|
72
|
+
|
|
73
|
+
## [0.15.36-pi.5]
|
|
74
|
+
|
|
75
|
+
- Replace hand-rolled frontmatter, attachment MIME, and session header parsers with Pi 1.4.0 exports (`stripFrontmatter`, `detectSupportedImageMimeTypeFromFile`, and `parseSessionEntries`).
|
|
76
|
+
- Register TUI message renderers for `pstack/task` and `pstack/subscription`, drain parked `runtime/inbox/` wakes on session restore, surface durable delivery state in `list_subscriptions`, and report live supervisor status in `/routines`.
|
|
77
|
+
- Declare published `files` in `package.json`, record the REA architecture reconstruction report in `docs/parity-reverse-engineering.md`, and enforce zero dependencies on an external `pstack` checkout.
|
|
78
|
+
|
|
79
|
+
## [0.15.36-pi.4]
|
|
80
|
+
|
|
81
|
+
- Add a durable routines supervisor (`pstack-routines-supervisor`) that dual-writes subscription desired state and auto-starts on `subscribe_*` so timers and webhook routines keep firing after the interactive chat exits. Optional launchd/systemd examples live under `packaging/`.
|
|
82
|
+
- Add `packaging/install-supervisor-unit.sh` for opt-in reboot survival (idempotent launchd or systemd user unit). Benny setup and the overnight guide point at it.
|
|
83
|
+
- Teach `/ketchup-video` and the host media section to open the rendered mp4 in the system player, read one frame per slide, and name the path (Pi chat does not inline-play video).
|
|
84
|
+
- Expand the vendored `create-skill` soft-dep to full interview and structure depth with Pi paths.
|
|
85
|
+
|
|
86
|
+
## [0.15.36-pi.3]
|
|
87
|
+
|
|
88
|
+
- Vendor the full soft-dependency team-kit skill and agent set into the package (CI, PR, review, verification, weekly summary, and the two engineering rules as skills), so pi-pstack no longer needs a separate team-kit install for parity.
|
|
89
|
+
- Inject the two former always-apply engineering rules into the host system prompt, and teach the thermo-nuclear agent to gather diffs with Pi tools instead of inventing `shell` / `explore` Task types.
|
|
90
|
+
- Keep Claude Code harness notes out of the package (Pi users get `docs/native-gaps.md` instead).
|
|
91
|
+
|
|
92
|
+
## [0.15.36-pi.2]
|
|
93
|
+
|
|
94
|
+
- Add repository, homepage, and bugs metadata and a changelog to the npm package.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pstack for Pi (pi-pstack)
|
|
2
2
|
|
|
3
|
-
pi-pstack is pstack 0.15.36 for Pi 1.
|
|
3
|
+
pi-pstack is pstack 0.15.36 for Pi 1.5.0: rigorous agent workflows (`/poteto-mode` and its playbooks), the principle skills, and the review, research, and verification skills, plus the full soft-dependency team-kit set (`deslop`, `control-cli`, `control-ui`, CI/PR helpers, thermo-nuclear review, and the rest) vendored in so you do not install a separate team-kit package. A small extension provides the host features the skills call by name: `/name` skill commands, `/mode`, `/plan`, the `Task` subagent tool with local worktree workers, forks, and `agent_status`, `TodoWrite`, `AskQuestion`, `GenerateImage`, `SwitchMode`, the model rule, `/loop`, subscriptions and webhook routines, and `visualize`.
|
|
4
4
|
|
|
5
5
|
## Get set up
|
|
6
6
|
|
|
@@ -13,8 +13,8 @@ pi-pstack is pstack 0.15.36 for Pi 1.4.0: rigorous agent workflows (`/poteto-mod
|
|
|
13
13
|
pi install ./extensions/pi-pstack
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
Pi does not install dependencies for a local package, so `bun install` (or `npm install` in `extensions/pi-pstack`) fetches the one runtime dependency, `@anthropic-ai/sandbox-runtime`, which the read-only shell loads (readonly subagents and `/plan`). Without it everything else works, and a read-only shell command fails instead of running unsandboxed. To try it for one session without installing, run `pi -e ./extensions/pi-pstack`. To install the published package instead, run `pi install npm:@justjoshn/pi-pstack`.
|
|
17
|
-
Installing loads pi-pstack's tools and system-prompt sections at once, but no skill runs until you invoke it.
|
|
16
|
+
Pi does not install dependencies for a local package, so `bun install` (or `npm install` in `extensions/pi-pstack`) fetches the one runtime dependency, `@anthropic-ai/sandbox-runtime`, which the read-only shell loads (readonly subagents and `/plan`). Without it everything else works, and a read-only shell command fails instead of running unsandboxed. On Linux the sandbox also needs `bubblewrap`, `socat`, and `ripgrep` (`sudo apt install bubblewrap socat ripgrep`), and Ubuntu 24.04 and later need the user-namespace change under Limits. macOS uses the built-in `sandbox-exec`. pi-pstack needs Node 22.19 or newer. To try it for one session without installing, run `pi -e ./extensions/pi-pstack`. To install the published package instead, run `pi install npm:@justjoshn/pi-pstack`.
|
|
17
|
+
Installing loads pi-pstack's tools and system-prompt sections at once, but no skill runs until you invoke it. 61 workflow skills stay out of the model's automatic skill list. Setup, create-skill, and the team-kit shipping and review skills (`deslop`, `control-cli`, `control-ui`, CI and PR helpers, and the rest of that set) can load from your words alone.
|
|
18
18
|
2. Run `/setup-pstack`. It lists the models the `Task` tool can use, asks for a reasoning budget, maps a model to each role, and writes the model rule. A new rule applies from the next request.
|
|
19
19
|
3. Start real work with `/poteto-mode`, a goal, and a check that can pass or fail.
|
|
20
20
|
|
|
@@ -27,9 +27,9 @@ Remove the package with `pi remove ./extensions/pi-pstack`. Its state lives in `
|
|
|
27
27
|
| You type | What happens |
|
|
28
28
|
|---|---|
|
|
29
29
|
| `/poteto-mode <task>` | The skill attaches to that one message. Every skill Pi loaded works this way: pstack's (`/how`, `/why`, `/arena`, `/interrogate`, `/principle-prove-it-works`, `/deslop`) and your own, such as a `/<handle>-mode` skill from `/automate-me`. `/skill:<name>` works too. |
|
|
30
|
-
| `/mode poteto-mode [task]` | Keeps the skill in context on every turn. The footer shows a badge with the skill's `icon` and `color` metadata, such as a yellow `♛ mode: poteto-mode` (other skills get `⚡`). `/mode off` exits and `/mode` reports. Any loaded skill can back a mode. |
|
|
31
|
-
| `/plan [task]` | Plan mode: the agent
|
|
32
|
-
| `/loop 30m <prompt>` | Runs the prompt now
|
|
30
|
+
| `/mode poteto-mode [task]` | Keeps the skill in context on every turn until you leave the mode: the skill rides every request in its own system-prompt section, which Pi re-sends only when it changes. The first request after entry says the user entered the mode, later requests carry a reminder that names the skill file, and the request after `/mode off` or a switch to another mode says the user left it. The footer shows a badge with the skill's `icon` and `color` metadata, such as a yellow `♛ mode: poteto-mode` (other skills get `⚡`). `/mode off` exits and `/mode` reports. Any loaded skill can back a mode. |
|
|
31
|
+
| `/plan [task]` | Plan mode: the agent researches with read-only tools (`read`, `grep`, `find`, `ls`, the sandboxed `bash_readonly`, `AskQuestion`, `TodoWrite`, `agent_status`, `Task`, whose launches run readonly: a fresh one runs here with no worktree, and a resume or fork stays where its agent ran, and `stop_agent`), asks its clarifying questions early, and presents the plan with `CreatePlan` (`plan`, `name`, `overview`, `todos`). `CreatePlan` writes the plan file under `<pstack dir>/plans/` (`<name>-<8 hex>.plan.md`: the chat id in a comment, the todos as front matter, then the plan), one file per plan name in a chat. `edit` and `write` work on markdown files only, so the agent refines the plan in its file. After a run that saved a plan, an interactive session asks `Yes, build locally`, `Yes, build in cloud` (in a git repository: a background isolated worker builds it on its own branch), or `No, propose changes`. `/plan build` builds the saved plan too, and `/plan off` restores your tools. A bare `/plan` enters plan mode. The footer shows `plan`. |
|
|
32
|
+
| `/loop 30m <prompt>` | Runs the prompt now, then again every 30 minutes from each fire, so a long run does not push the next tick out. A tick that comes due while a run is still going fires once when that run settles; several missed ticks still fire once. The interval can come first or last, written as `30m`, `10 minutes`, or `every 10 minutes`. Without an interval the agent picks each wake with the `Loop` tool, and the loop ends when it picks none and no background subagent is still running. `/loop stop` or Escape during a run ends it. The prompt can be a skill command, such as `/loop 1h /poteto-mode run the audit tick`. When a playbook says to arm `/loop`, the agent starts it with the `Loop` tool. Intervals go up to 24 days. |
|
|
33
33
|
| `/routines` | Lists webhook routines with their URL, credential file, and status. |
|
|
34
34
|
| `/setup-pstack` | Configures the per-role models. |
|
|
35
35
|
| `/poteto-help <question>` | Answers a question about pstack and hands you a prompt to send. |
|
|
@@ -40,34 +40,38 @@ Remove the package with `pi remove ./extensions/pi-pstack`. Its state lives in `
|
|
|
40
40
|
|
|
41
41
|
| Feature | Behavior |
|
|
42
42
|
|---|---|
|
|
43
|
-
| `Task` (`description`, `prompt`, `subagent_type`, `model`, `run_in_background`, `resume`, `fork`, `fork_turns`, `readonly`, `file_attachments`, `environment`, `cloud_base_branch`) | Starts a separate `pi --mode rpc` process per subagent, so this Pi process can steer and abort it. Foreground calls return the response and an agent ID. Background calls return at once, and a `<task>`
|
|
44
|
-
| `resume` | Sends a follow-up to an idle agent with its context, model, type, and directory. On an agent running in this Pi process, it delivers the prompt as a steer and returns at once. A readonly or plan-mode call cannot steer a writable agent. An agent running in another Pi process is refused. This is how a playbook "messages" a worker. Pi's own `/resume` command reopens a chat session instead. |
|
|
43
|
+
| `Task` (`description`, `prompt`, `subagent_type`, `model`, `run_in_background`, `resume`, `fork`, `fork_turns`, `readonly`, `file_attachments`, `environment`, `cloud_base_branch`) | Starts a separate `pi --mode rpc` process per subagent, so this Pi process can steer and abort it. Foreground calls return the response and an agent ID. Background calls return at once, and a `<system_notification>` with a `<task>` block arrives after your turn ends, titled by the first line of the prompt (80 characters at most) and followed by a request to do any follow-up work; the notification card shows the call's `description`. Print and JSON runs wait for pending notifications before exiting, unless aborted. Several calls in one message run in parallel. A subagent's own subagents cannot spawn more, and every subagent is told to spawn none unless asked. A run lock per agent ID keeps out a second writer, even from another Pi process (Limits notes the stale-lock race). Children inherit the parent's project-trust decision. Foreground usage counts toward the session totals. The Task card leads with the call's `description`, then the agent type and the model that ran, and while a foreground child works it shows its last few tool steps and latest line instead of a blank wait. |
|
|
44
|
+
| `resume` | Sends a follow-up to an idle agent with its context, model, type, and directory. The root chat can resume or fork a descendant that a worktree worker started inside that worktree, and the descendant still runs where it first ran. On an agent running in this Pi process, it delivers the prompt as a steer and returns at once. A readonly or plan-mode call cannot steer a writable agent. An agent running in another Pi process is refused. This is how a playbook "messages" a worker. Pi's own `/resume` command reopens a chat session instead. |
|
|
45
45
|
| `fork` | Starts a new agent whose transcript begins as a copy of an idle agent's transcript, in that agent's directory (its worktree for an isolated worker), so it sees the built checkout and uncommitted changes. Type, model, and readonly default from the source; readonly can be added, never lifted. `fork_turns: N` (only with `fork`) copies just the first N user turns. `fork` excludes `resume`, `environment`, and `cloud_base_branch`. Pi's own `/fork` command branches the chat session instead. |
|
|
46
46
|
| `stop_agent` | `agent_id`. Stops a running subagent. One this Pi process owns gets an RPC abort, then a kill after a grace period. One another of your Pi processes owns gets a signal to the live pid in its run lock. An idle or finished agent is left alone, and the result says so. |
|
|
47
47
|
| `agent_status` | Reads a subagent's state (`running` while its run lock names a live pid, `idle`, or `missing`), type, model, directory, branch, times, and last reply, without waking it. It also shows whether the agent is readonly, the agent it was forked from, its pid while running, and its transcript. Without `agent_id` it lists the workspace's 20 newest agents. In the root chat that includes every descendant, isolated workers too. |
|
|
48
|
-
| Subagent types | `generalPurpose` (default), `poteto-agent` (a background delegate that reads poteto-mode first),
|
|
49
|
-
| Models | A Pi model spec such as `claude-opus-5-5:xhigh` or `xai/grok-4.7:high`, model parameters such as `claude-opus-5-5[effort=high]` or `grok-4.7[fast=true]` (picks a listed `-fast` id of that model), or `inherit`, `inherit-parent`, `auto`, or nothing for the parent model. A model Pi does not list, or a thinking level the model does not support, fails with the allowed list. A bare model id that several providers offer resolves to the parent chat's provider when it offers that id, and otherwise fails with the choices. Older rules that wrote `claude-opus-5-5-xhigh` still resolve. The system prompt's `pstack_subagents` section lists the types, the parent model, and the models with their levels. |
|
|
50
|
-
| Isolated workers (`environment: "cloud"`) | The subagent runs in a new git worktree at `<pstack dir>/workspaces/<workspace folder>/worktrees/<agent id>` on branch `pstack/<agent id>`, from `cloud_base_branch` (
|
|
48
|
+
| Subagent types | The built-in `generalPurpose` (default) and `explore` (a file-search specialist the caller tells how thorough to be, with `grep`, `find`, and `ls` on and no `Task`), then `poteto-agent` (a background delegate that reads poteto-mode first), `ci-watcher` (a background PR check watcher), `comment-sicko`, and `thermo-nuclear-code-quality-review`, the last four read from `agents/*.md`. Unknown types fail with the list. |
|
|
49
|
+
| Models | A Pi model spec such as `claude-opus-5-5:xhigh` or `xai/grok-4.7:high`, model parameters such as `claude-opus-5-5[effort=high]` or `grok-4.7[fast=true]` (picks a listed `-fast` id of that model), `fast` for the parent model's listed `-fast` variant when it has one, else the parent model, or `inherit`, `inherit-parent`, `auto`, or nothing for the parent model. A model Pi does not list, or a thinking level the model does not support, fails with the allowed list. A bare model id that several providers offer resolves to the parent chat's provider when it offers that id, and otherwise fails with the choices. Older rules that wrote `claude-opus-5-5-xhigh` still resolve. The system prompt's `pstack_subagents` section lists the types, the parent model, and the models with their levels. |
|
|
50
|
+
| Isolated workers (`environment: "cloud"`) | The subagent runs in a new git worktree at `<pstack dir>/workspaces/<workspace folder>/worktrees/<agent id>` on branch `pstack/<agent id>`, from `cloud_base_branch` (`origin/<branch>` when that remote-tracking ref exists, else a local branch or other ref) or your HEAD commit, so uncommitted changes do not reach it. The result and the card name the branch to merge, and `resume` and `fork` run in the same worktree. It fails clearly outside a git repository, in a repository with no commits, or when the base does not resolve. The worker shares the root chat's workspace state, so it sees the same projects, stores, and subagent transcripts. It also shares this machine's ports, processes, writable caches, simulators, and credentials. Assign separate ports, output directories, and writable caches to concurrent runtime lanes. `swarm` and `orchestrate` spawn worktree workers by default. |
|
|
51
51
|
| `readonly: true` | The child gets `read`, `grep`, `find`, `ls`, `TodoWrite`, and a read-only `bash`, and no MCP. That shell runs each command in an OS sandbox ([`@anthropic-ai/sandbox-runtime`](https://github.com/anthropics/sandbox-runtime): `sandbox-exec` on macOS, bubblewrap on Linux) that blocks every file write and all network access, so `git log` works and `touch` or `curl` fail. Where no sandbox can start, the command fails rather than running unsandboxed. |
|
|
52
|
-
| `TodoWrite` | `todos` with `id`, `content`, `status`, and `merge`. The list follows the session branch
|
|
53
|
-
| `AskQuestion` | `title`, and per question `id`, `prompt`, `options` (`id`, `label`, optional `description`), and `allow_multiple`, through Pi's select dialog. Every question ends with `Other: (type to answer)`; a typed answer comes back as `other` with its text. In print and JSON runs, including subagents, each question comes back skipped. |
|
|
52
|
+
| `TodoWrite` | `todos` with `id`, `content`, `status`, and `merge`. Its description says when to keep a list, the four states, and one task in progress at a time. The list follows the session branch, shows above the editor, and rides every request's system prompt. |
|
|
53
|
+
| `AskQuestion` | `title`, and per question `id`, `prompt`, `options` (at least two, each `id`, `label`, optional `description`), and `allow_multiple`, through Pi's select dialog. It is for decisions only the user can make, and a recommended option goes first with `(Recommended)`. Every question ends with `Other: (type to answer)`; a typed answer comes back as `other` with its text. In print and JSON runs, including subagents, each question comes back skipped. |
|
|
54
|
+
| Always-applied rules | The two team-kit rules are in `pstack_host` as their shipped text on every request, alongside the same rules as hidden skills. |
|
|
54
55
|
| The model rule | `<pstack dir>/pstack-models.md`, plain Markdown with one line per role, added to every request's system prompt. A `pstack-models.mdc` from an earlier version is moved there once, without its frontmatter, and kept as `pstack-models.mdc.migrated`. |
|
|
55
|
-
| Subscriptions | `subscribe_github_pr` (`scope` `pr` with `prUrl`, `repo` with `repo`, or `author` with `author` and `repo`) polls with `gh` every 60 seconds and wakes the chat when a PR's state, head, mergeability, review decision, reviews, or comments change, or when a check concludes or its conclusion changes; the first poll is a baseline. `subscribe_timer` takes a `name`, a `prompt`, and a 5-field `cron` or `delaySeconds`, either with `once`; `sessionStrategy` `wake_self`
|
|
56
|
-
| Webhook routines | `subscribe_webhook` (`name`, `prompt`) serves `http://127.0.0.1:<port>/routines/<slug>` (port `PSTACK_ROUTINES_PORT`,
|
|
56
|
+
| Subscriptions | `subscribe_github_pr` (`scope` `pr` with `prUrl`, `repo` with `repo`, or `author` with `author` and `repo`) polls with `gh` every 60 seconds and wakes the chat when a PR's state, head, mergeability, review decision, reviews, or comments change, or when a check concludes or its conclusion changes; the first poll is a baseline. `subscribe_timer` takes a `name`, a `prompt`, and a 5-field `cron` or `delaySeconds`, either with `once`; `sessionStrategy` `wake_self` queues a wake for this owning session. With `new_session`, a live owner starts a background Task and receives its notification. An offline owner permits a detached run with a recorded outcome. Both reuse the model, thinking level, and project-trust decision the timer was created with. Re-subscribing an existing timer name returns `created: false`. `list_subscriptions` and `unsubscribe` manage them. The authoritative registry is `<pstack dir>/durable/<workspace>/subscriptions.json`. Any session in that workspace can list or cancel subscriptions. Session history does not recreate cancelled or completed subscriptions. Owner-directed events wait for the creating session rather than waking another workspace session. A detached run records its own final message, shown by `list_subscriptions`. A timer does not expire unless `expiresInHours` says so (at most 30 days); `0` means no expiry. A GitHub watch keeps a 7-day default because it is this port's own surface. |
|
|
57
|
+
| Webhook routines | `subscribe_webhook` (`name`, `prompt`, optional `sessionStrategy`) serves `http://127.0.0.1:<port>/routines/<slug>` (port `PSTACK_ROUTINES_PORT`, else the port this workspace last bound, else 47913, where `0` picks a free port) and keeps a random sender key in `<pstack dir>/routines/<slug>/credentials.json` (mode 0600). The result names the URL and the file, never the key. A JSON POST with `X-Automation-Key` or `Authorization: Bearer` returns 200 after durable acceptance, and 503 with `Retry-After` while that routine already holds 20 undelivered events. With the default `wake_self`, the owner receives a `[routine]` turn holding the prompt and a `<webhook_event>` block (`headers`, `body_digest`, `body`, `timestamp_ms`). With `new_session`, each accepted POST starts a fresh detached run, the way a hosted automation runs with no chat open, and records its outcome in `list_subscriptions`. HTTP 200 does not mean the run finished. Each authenticated POST is a separate event, including identical bodies. Storage failure returns 503 rather than acknowledging a lost event, and a full delivery queue refuses the new event instead of dropping an earlier accepted one. A wrong key gets 401, an unknown routine 404, a method other than POST 405, a body over 64 KiB 413, and a body that is not a JSON object 400. A routine does not expire unless `expiresInHours` says so. `make-bot-ui` builds a page on top of this. |
|
|
58
|
+
| Durable supervisor | Creating a subscription auto-starts `pstack-routines-supervisor --workspace <cwd>` when it is not already running. Creation waits for that subscription to arm, and webhook creation returns the bound listener's URL. The supervisor reads the durable registry, arms timers and GitHub polls, and owns the routines port. An online owner receives native Pi continuation messages. Owner-directed events accepted while the owner is offline wait for that same session to resume. A timer or webhook routine explicitly configured with `sessionStrategy: "new_session"` starts detached work while its owner is offline. You can still start the bin yourself. For reboot survival, run `packaging/install-supervisor-unit.sh --workspace <cwd>` (idempotent; installs the launchd or systemd unit from the examples under `packaging/`). Print and JSON runs still cannot *create* subscriptions. |
|
|
57
59
|
| Stores and projects | The system prompt names "the current agent's store" (per session), "the root agent's store" (the main chat's, named to every subagent however deep), and the workspace's `projects/` folder, where a program's Project is `<slug>/notes.md` (its tracker) and `<slug>/store/`. |
|
|
58
60
|
| `visualize` | `title`, `kind` (`bar` or `line`), `labels`, `series` (`name`, `values`), and `unit` render a Unicode chart in the result and write a standalone SVG to the session's artifacts folder. |
|
|
59
61
|
| Transcripts | The system prompt names this workspace's Pi session directory, the current session file, and this workspace's subagent transcripts. |
|
|
60
|
-
|
|
|
62
|
+
| `GenerateImage` | Generates an image (`description` of at least six words, `filename`, `reference_image_paths`, `aspect_ratio`) on Pi's image models through `ctx.modelRegistry.generateImages()`. It is offered when an image model is available (for example an OpenRouter image model), not to readonly subagents or in plan mode, and saves each image to the session's artifacts folder. Without an image model, the host section tells skills to draw a Mermaid diagram instead. |
|
|
63
|
+
| `SwitchMode` | `target_mode_id` (`plan` or `agent`) and `explanation`. The agent proposes entering or leaving plan mode, and the switch happens only after you confirm it. Offered in interactive and RPC sessions. |
|
|
61
64
|
|
|
62
|
-
Subagent transcripts are Pi sessions in `<pstack dir>/workspaces/<workspace folder>/subagents/`, with the agent ID in each file name, next to a small record that `resume`, `fork`, and `agent_status` read.
|
|
65
|
+
Subagent transcripts are Pi sessions in `<pstack dir>/workspaces/<workspace folder>/subagents/`, with the agent ID in each file name, next to a small record that `resume`, `fork`, and `agent_status` read. Records belong to the main chat's shared workspace state, so the root chat can act on a descendant that ran in a worktree. Children inherit your installed extensions and MCP servers, and local ones run in your working directory. Give each local subagent that writes its own git worktree, or launch it with `environment: "cloud"`, because a child process does not isolate the filesystem. A child exits on its own if its parent Pi process dies.
|
|
63
66
|
|
|
64
67
|
## Limits
|
|
65
68
|
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
+
- Worktree workers run on this machine, not remote VMs. They start from committed code only and share your installed extensions, MCP servers, and network, except that a readonly worker gets no MCP servers and no network. A worktree is not a credential boundary. Concurrent runtime lanes need separate ports, output directories, and writable caches. pi-pstack never pushes their branches, though a worker can push its own. Worktrees and branches stay until you or the worktree-cleanup playbook remove them.
|
|
70
|
+
- The supervisor can accept events after chat exit, but owner-directed events wait until the owning session resumes. Explicit `new_session` timers and webhook routines can spend tokens with no human watching. Detached runs do not supply the live owner's Task notification flow. For reboot survival, run `packaging/install-supervisor-unit.sh --workspace <cwd>`. If the supervisor cannot start, an explicitly reported in-process fallback stops when that Pi process exits. A GitHub subscription restarted after downtime takes a new baseline, so changes made while nothing was polling do not wake it. Each workspace binds its own routines port. With no explicit port, a busy default falls back to an ephemeral port that the workspace then reuses and reports, so two workspaces serve routines at once. An explicit `PSTACK_ROUTINES_PORT` is a configuration: if it is taken, the routine reports that error instead of moving. The listener binds `127.0.0.1`, so a page served to other machines forwards through a local server, as `make-bot-ui` describes.
|
|
71
|
+
- Event delivery is at-least-once. A process crash after Pi queues a message but before its durable acknowledgement can repeat a wake or a fresh run. Automation prompts must make external actions idempotent. Up to 20 undelivered events per subscription stay queued until delivery or cancellation, and a new event beyond that is refused rather than replacing an older accepted one. Expiry stops new occurrences rather than discarding accepted work. Failed detached executions retain their event for retry and expose the error in `list_subscriptions`. Cancelling a subscription drops pending undelivered events, but cannot undo work already handed to Pi.
|
|
72
|
+
- The Benny automation pack under `automations/benny/` runs on pi-pstack subscriptions. Keep its owning Pi session running for immediate handling, or resume that session to handle parked events. It needs a Slack MCP server for its Slack steps.
|
|
69
73
|
- `/plan` uses `bash_readonly` for its shell rather than replacing `bash`, so your shell settings stay as they are outside plan mode.
|
|
70
|
-
- Background subagent token usage is recorded in the child's transcript and in the `usage` field of the notification's details, but does not enter the parent session's totals: Pi 1.
|
|
74
|
+
- Background subagent token usage is recorded in the child's transcript and in the `usage` field of the notification's details, but does not enter the parent session's totals: Pi 1.5.0 has no public API for adding a background completion's usage to the parent totals. Native tool-result usage covers synchronous nested work, not later notifications.
|
|
71
75
|
- `/reload`, `/new`, and Pi's `/resume` and `/fork` commands stop running background subagents, with a warning that names how many. Continue one later with `Task` `resume` and its agent ID.
|
|
72
76
|
- A print or JSON run waits for its background subagents before it exits, with no timeout of its own, unless it is aborted.
|
|
73
77
|
- Subagents start the same Pi script that runs the parent (`process.argv[1]`), or `pi` from `PATH`. Embedding the package through the SDK in another host is not supported.
|
|
@@ -76,21 +80,22 @@ Subagent transcripts are Pi sessions in `<pstack dir>/workspaces/<workspace fold
|
|
|
76
80
|
- Subagents run headless in RPC mode, so an extension that asks for permission through a dialog cannot ask there.
|
|
77
81
|
- The read-only shell sandboxes shell subprocesses only, and is verified on macOS and on the Ubuntu CI runner. On Linux it needs `bubblewrap`, `socat`, and `ripgrep`. Ubuntu 24.04 and later restrict unprivileged user namespaces: either add an AppArmor profile that grants `userns` to `bwrap`, or run `sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0`, which lifts the restriction for every program on the machine. The policy sets `allowAllUnixSockets: true` so Linux skips `apply-seccomp`, whose nested userns fails on GitHub-hosted runners; filesystem write denial and network denial still come from bubblewrap.
|
|
78
82
|
- Whether a model follows a playbook is the model's call.
|
|
79
|
-
- Workspace folders follow Pi's session-folder naming, so two paths that differ only by `/` versus `-` share a folder
|
|
83
|
+
- Workspace folders follow Pi's session-folder naming, so two paths that differ only by `/` versus `-` share a folder. Resume and fork refuse an agent whose record names the other directory, except that a record created inside this workspace's own worktrees belongs to this workspace. Subscription reads and mutations also reject a registry owned by the other workspace.
|
|
80
84
|
- The run lock that keeps one writer per agent ID names the process writing the transcript. A lock file without a readable pid counts as held; the error names the file to delete. `agent_status` shows such an agent as `idle`. A lock whose pid is dead is taken over, and two processes that take over the same stale lock at the same moment can both succeed.
|
|
81
85
|
- `skills/poteto-mode/scripts/watch-pr` needs Bun and installs its one dependency on first run. `check-plan.mjs` needs only Node. `worktree-audit.sh` needs `rg` and `jq`, and works with BSD (macOS) or GNU `stat` and `date`.
|
|
82
86
|
- `statechart` runs `skills/statechart/scripts/statechart` on Node 22.18 to 22.x, Node 23.6 or later, Bun 1.1.5 or later, or Deno 2.0 or later. The first run installs TLC and Java through [mise](https://mise.jdx.dev/) and needs the network. Without a SPEC it prints `Give one SPEC.tla.` and its usage, then exits 2.
|
|
83
87
|
|
|
84
88
|
## Maintain it
|
|
85
89
|
|
|
86
|
-
The skills, agents, guide, and automation pack are this package's own files; edit them in place. They track pstack 0.15.36 in behavior. The record of the move to Pi-native text and the host features added for it is at the repository root, in `parity/pi-pstack-0.15.36/` (design and decisions); earlier records are in the root's `parity/pi-pstack-*`. Four mechanisms Pi 1.
|
|
90
|
+
The skills, agents, guide, and automation pack are this package's own files; edit them in place. They track pstack 0.15.36 in behavior. [`docs/parity-status.md`](docs/parity-status.md) records what was reconstructed, what each host translation uses, and which differences remain host-bound. The record of the move to Pi-native text and the host features added for it is at the repository root, in `parity/pi-pstack-0.15.36/` (design and decisions); earlier records are in the root's `parity/pi-pstack-*`. Four mechanisms Pi 1.5.0 does not export keep a hand-written implementation here: [`docs/native-gaps.md`](docs/native-gaps.md) names each one, the evidence, and the public API that would replace it.
|
|
87
91
|
|
|
88
92
|
```sh
|
|
89
93
|
bun run typecheck
|
|
90
94
|
bun run test
|
|
95
|
+
bun run test:statechart # full compiler suite; set TLA2TOOLS and JAVA for an existing verified toolchain
|
|
91
96
|
bun run live:e2e -- --model deepseek/deepseek-flash # real-model scenarios; needs credentials and gives the model under test your real auth.json (see the script header)
|
|
92
97
|
```
|
|
93
98
|
|
|
94
99
|
## Licenses
|
|
95
100
|
|
|
96
|
-
The port's own code is MIT (`LICENSE`). pstack's files keep their MIT notice in `licenses/pstack.LICENSE` (© 2026 Lauren Tan), and the
|
|
101
|
+
The port's own code is MIT (`LICENSE`). pstack's files keep their MIT notice in `licenses/pstack.LICENSE` (© 2026 Lauren Tan), and the vendored team-kit skills and agents keep theirs in `licenses/cursor-team-kit.LICENSE`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-watcher
|
|
3
|
+
description: Watch PR CI for the current branch and report pass/fail with relevant failure links. Use when waiting for CI results or CI has failed. Use proactively to monitor branch CI.
|
|
4
|
+
model: fast
|
|
5
|
+
is_background: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# CI watcher
|
|
9
|
+
|
|
10
|
+
CI monitoring specialist for PR-attached checks.
|
|
11
|
+
|
|
12
|
+
## Trigger
|
|
13
|
+
|
|
14
|
+
Use when waiting for CI results, CI has failed, or when proactively monitoring branch CI.
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
1. Determine current branch: `git branch --show-current`
|
|
19
|
+
2. Resolve the PR: `gh pr view --json number,url,headRefName`
|
|
20
|
+
3. Inspect attached checks: `gh pr checks --json name,bucket,state,workflow,link`
|
|
21
|
+
4. If checks are pending, watch: `gh pr checks --watch --fail-fast`
|
|
22
|
+
5. If a GitHub Actions check failed, fetch logs with `gh run view <run-id> --log-failed`; otherwise, return the check link and concise next step.
|
|
23
|
+
|
|
24
|
+
## Output
|
|
25
|
+
|
|
26
|
+
- CI status (passed/failed)
|
|
27
|
+
- PR and check metadata
|
|
28
|
+
- If failed: concise failure excerpt or external check link and likely next step
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thermo-nuclear-code-quality-review
|
|
3
|
+
description: Thermo-nuclear code quality audit (maintainability, structure, 1k-line rule, spaghetti, code-judo). Invoked via Task after a parent gathers diff and file contents. Loads the rubric from the `thermo-nuclear-code-quality-review` skill shipped with pi-pstack.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Thermo-Nuclear Code Quality Review
|
|
7
|
+
|
|
8
|
+
You are a **Task subagent**. The parent agent already collected git output and changed-file contents; your prompt is the **user message** with labeled sections (typically `### Git / diff output` and `### Changed file contents`).
|
|
9
|
+
|
|
10
|
+
## Rubric
|
|
11
|
+
|
|
12
|
+
1. Load the `thermo-nuclear-code-quality-review` skill (shipped with pi-pstack) and treat its `SKILL.md` as the **complete** rubric — tone, approval bar, output ordering, code-judo / 1k-line / spaghetti rules.
|
|
13
|
+
2. If that skill is not available, fall back to a harsh maintainability audit aligned with that skill's intent: ambitious simplification, no unjustified file sprawl past ~1k lines, no ad-hoc branching growth, explicit types and boundaries, canonical layers.
|
|
14
|
+
|
|
15
|
+
## Work
|
|
16
|
+
|
|
17
|
+
- Apply the rubric **only** to what the diff and contents show. Trace cross-file impact when the change touches module boundaries.
|
|
18
|
+
- Output in the **priority order** the rubric specifies. Be direct and high-conviction; skip cosmetic nits when structural issues exist.
|
|
19
|
+
- Do **not** spawn nested subagents unless the user or parent explicitly asks.
|
|
20
|
+
|
|
21
|
+
## Parent orchestration
|
|
22
|
+
|
|
23
|
+
Typical flow: in **one** message, run two `Task` calls in parallel — `subagent_type: "shell"` and `subagent_type: "explore"` — to collect `git diff <base>...HEAD` output and full contents of changed files (default base `main`). Then invoke this agent with `subagent_type: "thermo-nuclear-code-quality-review"` and a user prompt containing `### Git / diff output` and `### Changed file contents`.
|
package/assets/logo.png
ADDED
|
Binary file
|
|
@@ -31,6 +31,7 @@ i want two pi automations that work together in one slack issue channel. each on
|
|
|
31
31
|
- i want this entire pack committed at `.pi/automations/benny/` in the target repository. its `SKILL.md` files are direct automation instructions, not skills pi discovers.
|
|
32
32
|
- i want pi-pstack installed in pi for shared dependencies such as `how`, `why`, `tdd`, `unslop`, and the required principle skills.
|
|
33
33
|
- i want each subscription prompt to read its operational file directly from the target repository. i do not want pi-pstack package paths, copied excerpts, or slash-skill discovery.
|
|
34
|
+
- i want the pack and every referenced secret-free configuration file committed on the branch the owning session has checked out before either subscription is enabled, so no subscription runs instructions i have not reviewed.
|
|
34
35
|
- i keep user-owned configuration, feature maps, routing maps, memory, and secrets outside `.pi/automations/benny/` so pack refreshes cannot overwrite them.
|
|
35
36
|
- i want durable memory as files in one directory setup names, such as `~/.pi/agent/pstack/automations/benny/memories/`: a claim ledger so no report runs twice, and short operating notes.
|
|
36
37
|
- i want both automations to fail closed when channel coordinates, tracker access, the control adapter, or the feature map are missing or uncertain.
|
|
@@ -73,7 +74,7 @@ i want this setup session to run in the target repository, so a fresh subagent i
|
|
|
73
74
|
|
|
74
75
|
if pi-pstack or any shared dependency does not resolve, stop and explain what failed. do not move `.pi/automations/benny/skills/` into `.pi/skills/` or expect its files to appear in the slash-skill list.
|
|
75
76
|
|
|
76
|
-
tell me that
|
|
77
|
+
tell me that creating a subscription auto-starts `pstack-routines-supervisor`, that Benny's owner-session wakes park while this chat is offline until the same session is restored, and that a timer or webhook routine runs with no chat open only when it is created with `sessionStrategy: "new_session"`, in which case the run must do the work itself instead of handing it to a background `Task`. routines do not expire unless `expiresInHours` names a limit. for reboot survival, ask whether to run `packaging/install-supervisor-unit.sh --workspace <target-repository>` and run it when i say yes. do not create or update a subscription until i explicitly ask.
|
|
77
78
|
|
|
78
79
|
for first-time creation, create the triage subscription first, check it with `list_subscriptions`, and confirm one harmless fire before creating the repro subscription.
|
|
79
80
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
benny gives you two pi automations for slack issue reports. one triages each report. the other reproduces confirmed bugs and may prepare a small draft fix.
|
|
4
4
|
|
|
5
|
-
a pi automation is a pi-pstack subscription in
|
|
5
|
+
a pi automation is a pi-pstack subscription rooted in the target repository. creating one auto-starts `pstack-routines-supervisor`. owner-session wakes received while the setup chat is offline park until that same session is restored. a scheduled sweep is `subscribe_timer` with a cron schedule. each fire hands one report to a background subagent on the automation's model. a push trigger is `subscribe_webhook`: a slack app or relay you run posts each new report to the local routine url. slack reads and writes go through a slack mcp server configured in pi (`pi mcp list`). durable memory is plain files in a directory setup names, such as `~/.pi/agent/pstack/automations/benny/memories/`.
|
|
6
6
|
|
|
7
7
|
the files in this directory are dormant setup and automation sources. they do not appear as slash skills.
|
|
8
8
|
|
|
@@ -17,4 +17,4 @@ the files in this directory are dormant setup and automation sources. they do no
|
|
|
17
17
|
|
|
18
18
|
## what differs from hosted automations
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
creating a subscription auto-starts `pstack-routines-supervisor`. keep the owning pi session running for immediate handling, or restore it later to drain parked wakes. a timer or webhook routine explicitly configured with `sessionStrategy: "new_session"` starts detached work while its owner is offline, the way a hosted automation runs with no chat open; a detached run is one-shot, so it does the work itself instead of handing it to a background `Task`. for reboot survival, run `packaging/install-supervisor-unit.sh --workspace <target-repository>` (idempotent launchd or systemd user unit). if the supervisor cannot start, subscriptions still arm in the creating pi process and stop when that process exits, so tmux still works as a fallback. routines do not expire unless `expiresInHours` names a limit, which `list_subscriptions` reports; changing one means `unsubscribe`, then subscribing again with the same name. each workspace gets its own listener port, so two repositories can both serve routines. a webhook routine listens on `127.0.0.1` only, so slack cannot reach it directly. a push trigger needs a relay you run.
|
|
@@ -15,7 +15,7 @@ Benny needs external configuration and two live automations. Each automation is
|
|
|
15
15
|
- Timer mode (default): `subscribe_timer` with a 5-field `cron`. Each fire wakes the owning session, which sweeps the source channel, claims one report, and hands it to one background `Task` on the automation's configured model. The run's result arrives as a Task notification.
|
|
16
16
|
- Webhook mode: `subscribe_webhook`. Each POST to the local routine URL wakes the owning session with a `[routine]` turn, and the prompt hands the event to one background `Task` on the automation's configured model.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Creating a subscription auto-starts `pstack-routines-supervisor`. Benny's `wake_self` timers and webhook routines target the owning session. While it is offline, wakes park durably until that session is restored. A timer or webhook routine created with `sessionStrategy: "new_session"` instead starts a fresh detached run per fire, with no chat open, and records each outcome in `list_subscriptions`. Routines do not expire unless `expiresInHours` names a limit. Tell the user this before creating anything. For fires that survive a reboot, ask whether to run `packaging/install-supervisor-unit.sh --workspace <target-repository>` (resolve the script from the pi-pstack package root) and run it when they say yes.
|
|
19
19
|
|
|
20
20
|
Do not create or update a subscription until the user explicitly asks. Never put a secret value in pack files, prompts, memory, or committed configuration.
|
|
21
21
|
|
|
@@ -38,7 +38,7 @@ If this file is already being read from the target destination, treat the copy a
|
|
|
38
38
|
|
|
39
39
|
Confirm that pi-pstack is installed in Pi. A personal install (`pi install <path-to-pi-pstack>`) serves every repository on this machine. A project install (`pi install -l <path-to-pi-pstack>`) writes the target repository's `.pi/settings.json`; preserve every unrelated setting and package entry when that file exists, and validate it after editing.
|
|
40
40
|
|
|
41
|
-
This setup session must run in the target repository, because a `Task` subagent starts in its parent's working directory. If it does not, stop and tell the user to start Pi in the target repository and point it at `FOR_AGENTS.md` again. Start a fresh `Task` subagent with `readonly: true`. Ask it
|
|
41
|
+
This setup session must run in the target repository, because a `Task` subagent starts in its parent's working directory. If it does not, stop and tell the user to start Pi in the target repository and point it at `FOR_AGENTS.md` again. Start a fresh `Task` subagent with `readonly: true`. Ask it to resolve `<SKILLS>` from its own system prompt and read each required `<SKILLS>/<name>/SKILL.md` file below. It must report each absolute path and confirm the file's frontmatter names the required skill. Hidden skills need not appear in Pi's automatic skill catalog.
|
|
42
42
|
|
|
43
43
|
- `how`
|
|
44
44
|
- `why`
|
|
@@ -51,7 +51,7 @@ This setup session must run in the target repository, because a `Task` subagent
|
|
|
51
51
|
- `principle-fix-root-causes`
|
|
52
52
|
- `principle-prove-it-works`
|
|
53
53
|
|
|
54
|
-
Do not count a skill this session read by hand. The check must show that a fresh subagent in the target repository receives pi-pstack.
|
|
54
|
+
Do not count a skill this session read by hand or a catalog listing alone. The check must show that a fresh subagent in the target repository receives pi-pstack's host instructions and can read every required installed file.
|
|
55
55
|
|
|
56
56
|
If pi-pstack or any shared dependency does not resolve, stop and explain the failure.
|
|
57
57
|
|
|
@@ -59,7 +59,7 @@ Confirm that `pi mcp list` shows the Slack MCP server the user names, and that i
|
|
|
59
59
|
|
|
60
60
|
The Benny files are read directly from `<target-repository>/.pi/automations/benny/`. Do not move that directory into `.pi/skills/` or expect its `SKILL.md` files to appear in the slash-skill list.
|
|
61
61
|
|
|
62
|
-
Tell the user
|
|
62
|
+
Tell the user that `.pi/automations/benny/`, any referenced secret-free configuration, and, for a project install, the target repository's `.pi/settings.json` must be committed on the branch the owning session has checked out before either subscription is enabled. A subscription reads the working tree, so an uncommitted instruction would run unreviewed. Do not commit them unless the user asks.
|
|
63
63
|
|
|
64
64
|
Once this check passes, subscription prompts read the operational files by their absolute paths in the target checkout. They must not embed a pi-pstack package path or copy the file contents.
|
|
65
65
|
|
|
@@ -169,7 +169,7 @@ Ask whether this is first-time creation or configuration of existing subscriptio
|
|
|
169
169
|
|
|
170
170
|
Read `../../FOR_AGENTS.md` from the copied pack as the primary user-intent source for either path. Use it to understand the two triggers, tools, instructions, outcomes, and shared rules.
|
|
171
171
|
|
|
172
|
-
The owning session must be interactive or RPC
|
|
172
|
+
The owning session must be interactive or RPC and rooted in the target repository. A print or JSON run cannot create a subscription. Creating the subscription auto-starts `pstack-routines-supervisor`. Keep the owning session available for prompt handling, or restore it later to drain parked wakes. In both trigger modes, each delivered fire hands its report to one background `Task` with the automation's configured `model`. After both subscriptions exist, ask whether to install the reboot unit with `packaging/install-supervisor-unit.sh --workspace <target-repository>`, and run it only when the user says yes.
|
|
173
173
|
|
|
174
174
|
### First-time creation
|
|
175
175
|
|
|
@@ -183,7 +183,8 @@ For each automation:
|
|
|
183
183
|
4. Show the user the subscription name, mode, schedule, and full prompt, and get approval.
|
|
184
184
|
5. Create the subscription:
|
|
185
185
|
- Timer mode: `subscribe_timer` with `name`, `prompt`, and `cron`. Keep the default `sessionStrategy`, `wake_self`, so each fire reaches the owning session, which starts the `Task` on the configured model.
|
|
186
|
-
- Webhook mode: `subscribe_webhook` with `name` and `prompt`. It returns the local URL (`http://127.0.0.1:<port>/routines/<slug>`, where the slug is the kebab-case form of the name) and the credential file path. The key stays in that file. Never print it, paste it into chat, or copy it into the configuration.
|
|
186
|
+
- Webhook mode: `subscribe_webhook` with `name` and `prompt`. Keep the default `sessionStrategy`, `wake_self`, for the same handoff. It returns the local URL (`http://127.0.0.1:<port>/routines/<slug>`, where the slug is the kebab-case form of the name) and the credential file path. The key stays in that file. Never print it, paste it into chat, or copy it into the configuration.
|
|
187
|
+
- Only when the user asks for the automations to run with no chat open, pass `sessionStrategy: "new_session"` and replace the background `Task` handoff in the prompt with the same work performed in that run, because a detached run ends when it settles and takes any background child with it. State that tradeoff before switching.
|
|
187
188
|
6. Run `list_subscriptions`. Confirm the subscription appears with the expected name, schedule or URL, and `expiresAt`. A result of `created: false` means a subscription with that name already exists and kept its old prompt; follow the existing-subscription path instead.
|
|
188
189
|
7. Finish the thread-safety checks that apply to this automation before creating the next one.
|
|
189
190
|
|
|
@@ -225,11 +226,11 @@ Finish configuration, routing, control-adapter, and feature-map validation. Then
|
|
|
225
226
|
3. Create it again with the same name and the new prompt. A webhook routine keeps its slug, so check whether its URL or credential file changed and tell the user to update the relay.
|
|
226
227
|
4. Run `list_subscriptions` and confirm exactly one subscription per name.
|
|
227
228
|
|
|
228
|
-
To renew
|
|
229
|
+
To renew a subscription created with `expiresInHours`, do the same with the unchanged prompt. Do not create replacements under new names.
|
|
229
230
|
|
|
230
231
|
### Creation boundary
|
|
231
232
|
|
|
232
|
-
Create Benny's automations only with pi-pstack's `subscribe_timer` and `subscribe_webhook` tools in the owning session.
|
|
233
|
+
Create Benny's automations only with pi-pstack's `subscribe_timer` and `subscribe_webhook` tools in the owning session. Do not invent a separate `cron` or `launchd` schedule for Benny. The opt-in `packaging/install-supervisor-unit.sh` install is the reboot path for the durable supervisor, not a Benny schedule. Never expose the routine listener beyond `127.0.0.1` from this setup.
|
|
233
234
|
|
|
234
235
|
Do not let either automation handle normal traffic until the thread-safety test passes.
|
|
235
236
|
|
|
@@ -237,7 +238,7 @@ Do not let either automation handle normal traffic until the thread-safety test
|
|
|
237
238
|
|
|
238
239
|
Create both subscriptions with a test channel as the source channel, or test with a harmless report.
|
|
239
240
|
|
|
240
|
-
Before testing, confirm that both subscription prompts point at their exact operational files in the target checkout, that the memory directory exists, and that `list_subscriptions` shows both subscriptions. If any check fails, stop. Tell the user that the automation cannot handle traffic yet.
|
|
241
|
+
Before testing, confirm that the target repository's `.pi/automations/benny/`, every referenced secret-free configuration file, and, for a project install, its `.pi/settings.json` are committed on the branch the owning session has checked out. Confirm that both subscription prompts point at their exact committed operational files in the target checkout, that the memory directory exists, and that `list_subscriptions` shows both subscriptions. If any check fails, stop. Tell the user that the automation cannot handle traffic yet.
|
|
241
242
|
|
|
242
243
|
Verify:
|
|
243
244
|
|
|
@@ -17,7 +17,7 @@ Memory: `{{BENNY_MEMORY_DIR}}`. Read `MEMORIES.md` first. Record claims only in
|
|
|
17
17
|
Trigger, timer mode (this session woke from a `subscribe_timer` fire):
|
|
18
18
|
|
|
19
19
|
1. If `ledger.tsv` has a `benny-reproduce` claim with no `done` line from the last `{{REPRO_PLUS_FIX_MINUTES}}` minutes, another repro run owns the app. End the turn and post nothing.
|
|
20
|
-
2. Read top-level messages in the configured source Slack channel
|
|
20
|
+
2. Read top-level messages in the configured source Slack channel, starting `{{SWEEP_LOOKBACK_MINUTES}}` minutes ago or from the last successful sweep time recorded in `MEMORIES.md` when that is earlier, so reports posted while the session was offline are still seen. Skip every message `ledger.tsv` lists as `done` for `benny-reproduce`. A `claimed` line older than `{{REPRO_PLUS_FIX_MINUTES}}` minutes with no `done` line belongs to a run that died, so retry that message. Record this sweep's start time in `MEMORIES.md` when the sweep ends.
|
|
21
21
|
3. Take the oldest remaining message whose thread holds a triage marker from the configured triage identity, or whose age exceeds the verdict wait. If none remain, end the turn with `no report ready` and post nothing. A newer message without a marker waits for a later fire.
|
|
22
22
|
4. Append a `claimed` line for it to `ledger.tsv` before any other work. Handle only this one report.
|
|
23
23
|
5. Start one background `Task` with `model: "{{REPRODUCE_MODEL}}"` whose prompt is this prompt with this trigger block replaced by this trigger JSON, and do no other work in this session:
|
|
@@ -16,7 +16,7 @@ Memory: `{{BENNY_MEMORY_DIR}}`. Read `MEMORIES.md` first. Record claims only in
|
|
|
16
16
|
|
|
17
17
|
Trigger, timer mode (this session woke from a `subscribe_timer` fire):
|
|
18
18
|
|
|
19
|
-
1. Read top-level messages in the configured source Slack channel
|
|
19
|
+
1. Read top-level messages in the configured source Slack channel with the configured Slack read tool, starting `{{SWEEP_LOOKBACK_MINUTES}}` minutes ago or from the last successful sweep time recorded in `MEMORIES.md` when that is earlier, so reports posted while the session was offline are still seen. Record this sweep's start time in `MEMORIES.md` when the sweep ends.
|
|
20
20
|
2. Skip every message that `ledger.tsv` lists as `done` for `benny-triage`, and every message with a `claimed` line from the last `{{TRIAGE_TOTAL_MINUTES}}` minutes. A `claimed` line older than that with no `done` line belongs to a run that died, so retry that message.
|
|
21
21
|
3. Take the oldest remaining message. If none remain, end the turn with `no new report` and post nothing.
|
|
22
22
|
4. Append a `claimed` line for it to `ledger.tsv` before any other work. Handle only this one report. The next fire takes the next one.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Starts the durable routines supervisor for one workspace.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
entry="$here/../src/subscriptions/supervisor-main.ts"
|
|
6
|
+
if command -v bun >/dev/null 2>&1; then
|
|
7
|
+
exec bun "$entry" "$@"
|
|
8
|
+
fi
|
|
9
|
+
exec node --experimental-strip-types "$entry" "$@"
|
package/docs/guide/01-setup.md
CHANGED
|
@@ -13,7 +13,7 @@ bun install
|
|
|
13
13
|
pi install ./extensions/pi-pstack
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
`pi install <path-to-pi-pstack>` loads the package in place, so keep the checkout where it is. To install the published package instead, run `pi install npm:@justjoshn/pi-pstack`. Start Pi, and the pstack commands appear in the `/` menu.
|
|
16
|
+
`pi install <path-to-pi-pstack>` loads the package in place, so keep the checkout where it is. To install the published package instead, run `pi install npm:@justjoshn/pi-pstack`. On Linux, the read-only shell also needs `bubblewrap`, `socat`, and `ripgrep`, as the package README explains. Start Pi, and the pstack commands appear in the `/` menu.
|
|
17
17
|
|
|
18
18
|
## Pick your models
|
|
19
19
|
|
|
@@ -23,7 +23,7 @@ Run:
|
|
|
23
23
|
/setup-pstack
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
[`/setup-pstack`](../../skills/setup-pstack/SKILL.md) detects the models you have access to, asks for a reasoning budget, shows you each role (code delegates, judgment, the review panels), and asks what you want. Answer the questions. It writes `~/.pi/agent/pstack/pstack-models.md
|
|
26
|
+
[`/setup-pstack`](../../skills/setup-pstack/SKILL.md) detects the models you have access to, asks for a reasoning budget, shows you each role (code delegates, judgment, the review panels), and asks what you want. Answer the questions. It writes `~/.pi/agent/pstack/pstack-models.md` (`$PI_CODING_AGENT_DIR/pstack/pstack-models.md` when that variable is set), the model rule. pi-pstack adds it to every request, so every pstack skill reads it.
|
|
27
27
|
|
|
28
28
|
The defaults run at `xhigh` reasoning, the same as the `large` budget. `unlimited` lifts each model to its highest tier, up to `max`. Opus goes to `max`. Grok tops out at `xhigh`, so it stays there. `medium` and `small` lower the reasoning and spend fewer tokens.
|
|
29
29
|
|
|
@@ -115,7 +115,7 @@ Every loop above still waits for you to start it. A scheduled or event-driven au
|
|
|
115
115
|
- Every stage can stop the line. Triage can decide the report is expected behavior, repro can fail to reproduce it, and the fixer can judge the change too risky. Each of those outcomes is useful, because it keeps bad work from reaching the next stage, where it costs more to undo.
|
|
116
116
|
- Every stage hands over evidence. Repro attaches screenshots and video of the broken state, and the fix attaches before-and-after proof. A human can then check that the agent fixed the right thing before reading a line of code.
|
|
117
117
|
|
|
118
|
-
pstack ships this as a dormant [automation pack](../../automations/benny/README.md) for Slack issue reports. It runs as subscriptions
|
|
118
|
+
pstack ships this as a dormant [automation pack](../../automations/benny/README.md) for Slack issue reports. It runs as pi-pstack subscriptions. Creating a subscription auto-starts `pstack-routines-supervisor` for the workspace. Benny's timers and webhook routines target their owning Pi session. Keep it running for immediate handling, or resume it later to drain parked events. Only timers explicitly configured with `sessionStrategy: "new_session"` start detached work while their owner is offline. For reboot survival, run [`packaging/install-supervisor-unit.sh`](../../packaging/install-supervisor-unit.sh) `--workspace <repo>` (it writes the launchd or systemd unit from the examples under `packaging/`). One automation triages each report. The other reproduces confirmed bugs and may prepare a small draft fix. Point an agent at its [`FOR_AGENTS.md`](../../automations/benny/FOR_AGENTS.md) and name the target repository to set it up.
|
|
119
119
|
|
|
120
120
|
**Pitfall:** a duration is not a finish condition. "work on this for 4 hours" gives the agent nothing to check, and you'll wake up to four hours of motion instead of a result. Give `/loop` a predicate that can pass or fail.
|
|
121
121
|
|
|
@@ -93,7 +93,7 @@ Read every output yourself before accepting the verdict. If you disagree with th
|
|
|
93
93
|
|
|
94
94
|
## Build a bot UI with `/make-bot-ui`
|
|
95
95
|
|
|
96
|
-
One situational skill is for driving
|
|
96
|
+
One situational skill is for driving agent work from a page. [`/make-bot-ui`](../../skills/make-bot-ui/SKILL.md) builds a small page whose buttons POST to a pi-pstack webhook routine (`subscribe_webhook`). For example, you could swipe through a review queue and have each swipe ask an agent to act on that item. Creating the subscription auto-starts `pstack-routines-supervisor`. Keep the owning Pi session running for immediate handling. Events accepted while it is offline wait until that same session resumes. For reboot survival, run `packaging/install-supervisor-unit.sh --workspace <repo>`. A server on your machine holds the webhook's sender key, so the key never reaches the browser or the chat. The skill also covers exposing the page on Tailscale.
|
|
97
97
|
|
|
98
98
|
**Pitfall:** don't edit a skill mid-task because it's misbehaving. Fix it in its own PR and keep the task moving. A skill edit that ships tangled into feature work is invisible to review and impossible to evaluate.
|
|
99
99
|
|
|
@@ -158,7 +158,7 @@ That's the whole prompt. [`/bro`](../../skills/bro/SKILL.md) restates the last m
|
|
|
158
158
|
|
|
159
159
|
[`/ketchup`](../../skills/ketchup/SKILL.md) tells you in plain words what changed since your last message, then lists each call waiting on you with its pick, evidence, and risk. It changes nothing while it reports.
|
|
160
160
|
|
|
161
|
-
To watch the catch-up instead, run [`/ketchup-video`](../../skills/ketchup-video/SKILL.md). It
|
|
161
|
+
To watch the catch-up instead, run [`/ketchup-video`](../../skills/ketchup-video/SKILL.md). It opens a short subtitled video of slides in the system player, shows one frame per slide in chat, and lists the calls waiting on you as text under it.
|
|
162
162
|
|
|
163
163
|
## The pitfalls
|
|
164
164
|
|