diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json
index 2f8c2c6bf..e8b86f770 100644
--- a/.agents/plugins/marketplace.json
+++ b/.agents/plugins/marketplace.json
@@ -8,7 +8,7 @@
"name": "pstack",
"source": {
"source": "local",
- "path": "./pstack"
+ "path": "./portable/pstack"
},
"policy": {
"installation": "AVAILABLE",
diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 8ad066388..5737c604f 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -7,7 +7,7 @@
"plugins": [
{
"name": "pstack",
- "source": "./pstack",
+ "source": "./portable/pstack",
"description": "Upstream pstack workflows adapted for Claude Code and Codex."
}
]
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..dc35f108a
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+pstack/** -whitespace
+README.md -whitespace
+portable/pstack/** -whitespace linguist-generated=true
diff --git a/.github/workflows/validate-pstack-portable.yml b/.github/workflows/validate-pstack-portable.yml
index 1de2e2b39..cc8994dfe 100644
--- a/.github/workflows/validate-pstack-portable.yml
+++ b/.github/workflows/validate-pstack-portable.yml
@@ -4,6 +4,10 @@ on:
push:
paths:
- 'pstack/**'
+ - 'portable/**'
+ - 'README.md'
+ - 'README_PORTABLE.md'
+ - '.gitattributes'
- 'tools/portable/**'
- '.claude-plugin/**'
- '.agents/plugins/**'
@@ -11,6 +15,10 @@ on:
pull_request:
paths:
- 'pstack/**'
+ - 'portable/**'
+ - 'README.md'
+ - 'README_PORTABLE.md'
+ - '.gitattributes'
- 'tools/portable/**'
- '.claude-plugin/**'
- '.agents/plugins/**'
@@ -24,6 +32,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.12'
diff --git a/README.md b/README.md
index 744ca6236..a0a7acd5e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-> **yxhta/pstack:** Claude Code・Codexでの導入と上流同期は [README_PORTABLE.md](README_PORTABLE.md) を参照してください。以下は本家のREADMEです。
-
# Cursor plugins
Official Cursor plugins for popular developer tools, frameworks, and SaaS products. Each plugin is a standalone directory at the repository root with its own `.cursor-plugin/plugin.json` manifest.
diff --git a/README_PORTABLE.md b/README_PORTABLE.md
index d3889d7e2..95801b07c 100644
--- a/README_PORTABLE.md
+++ b/README_PORTABLE.md
@@ -36,24 +36,34 @@ codex plugin add pstack@yxhta-pstack
Start with `/pstack:poteto-mode` on Claude Code. On Codex, select the installed `pstack:poteto-mode` skill or ask to use poteto-mode. Run setup-pstack to configure roles. Missing roles inherit the session model; multi-model diversity needs models that your runtime actually exposes. No startup hook or automatic routing is installed.
-For a skills-only installation, clone this repository and keep it in place, then link each directory under `pstack/skills/` into your runtime's user skill directory. Install all skill directories together so the shared runtime adaptation and other relative references stay reachable. Existing skill names such as `swarm` and `architect` may collide: inspect existing installations before replacing them.
+For a skills-only installation, clone this repository and keep it in place, then link each directory under `portable/pstack/skills/` into your runtime's user skill directory. Install all skill directories together so the shared runtime adaptation and other relative references stay reachable. Existing skill names such as `swarm` and `architect` may collide: inspect existing installations before replacing them.
-Read [compatibility.md](pstack/compatibility.md) for the tool mappings, paths, and limitations. Cursor-only `make-bot-ui`, Benny automations, cloud workers, and transcript parsers are not ported. Optional cursor-team-kit dependencies are not included. Installation and structural validation do not establish that every workflow runs correctly; check a real task in each runtime.
+Read [runtime adaptation](tools/portable/assets/skills/poteto-mode/references/runtime-adaptation.md) for the tool mappings, paths, and limitations. Cursor-only `make-bot-ui`, Benny automations, cloud workers, and transcript parsers are not ported. Optional cursor-team-kit dependencies are not included. Installation and structural validation do not establish that every workflow runs correctly; check a real task in each runtime.
## Upstream updates
-The **Sync pstack upstream** GitHub Actions workflow checks daily and can be run manually. It merges upstream main into a dedicated branch, reapplies the small entry-point adaptation, records the upstream SHA, validates it, and opens a PR. It never merges into main automatically. The complete repository history is retained because this is a GitHub fork, but the PR body distinguishes pstack changes from unrelated upstream plugin changes.
+The **Sync pstack upstream** GitHub Actions workflow checks daily and can be run manually. It merges upstream main into a dedicated branch, records the upstream SHA, regenerates the portable package, validates it, and opens a PR. It never merges into main automatically. The complete repository history is retained because this is a GitHub fork. The PR body separates raw pstack paths from other changed paths, which include generated output, fork tooling, and other upstream plugins.
Enable GitHub Actions in this fork and allow Actions to create pull requests under **Settings → Actions → General**. Scheduled workflows may be disabled by GitHub after prolonged inactivity; run or re-enable the workflow when needed. If Actions is not allowed to create PRs, supply a suitably scoped repository secret `UPSTREAM_SYNC_TOKEN`; do not commit credentials. A PR opened with the default GITHUB_TOKEN does not trigger other PR workflows, so the sync job runs validation itself.
-Only one sync PR is kept open. Review and merge or close it before the next update. A merge conflict or validation failure fails the workflow with logs instead of overwriting the local adaptation. Resolve the conflicting upstream change on a branch and run the checks below. New upstream skills receive the same adaptation automatically.
+The sync script requires a clean dedicated checkout at the latest `origin` default branch. Only one sync PR is kept open. Review and merge or close it before the next update. A merge conflict or validation failure fails the workflow with logs instead of overwriting the local adaptation. Resolve the conflicting upstream change on a branch and run the checks below. New upstream skills receive the same adaptation automatically.
```sh
python3 tools/portable/prepare.py
python3 tools/portable/validate.py
python3 -m unittest discover -s tools/portable -p 'test_*.py'
git diff --check
-claude plugin validate ./pstack
+claude plugin validate ./portable/pstack
```
-Upstream-owned files receive only a runtime-adaptation link after their frontmatter and normalized skill names. Runtime-specific manifests, agents, scripts, this guide, and the runtime adaptation are maintained separately. The compatibility.md file links to the canonical adaptation inside poteto-mode; portable agent references are refreshed from upstream by prepare.py. Change behavior in runtime-adaptation.md only to adapt the runtime; keep policy changes explicit and separate. Preserve the upstream MIT license and attribution.
+The raw `pstack/` tree and root `README.md` match `tools/portable/upstream.json` byte for byte, including executable modes. Do not edit these source paths. The generator copies the complete upstream package to `portable/pstack/`, adds runtime mappings, and normalizes skill names there. It copies agents, licenses, scripts, and references. It rejects input symlinks and overlay collisions instead of overwriting unfamiliar upstream files.
+
+Edit fork-owned inputs under `tools/portable/assets/` and rerun `python3 tools/portable/prepare.py`. Never edit `portable/pstack/` by hand. The generated package is committed intentionally so every installation works without a build. `python3 tools/portable/prepare.py --check` detects missing, stale, modified, or mode-changed output. Root marketplaces point to this single package. Source files remain unpatched when upstream changes a skill header.
+
+Native plugin versions include the upstream pin and a digest of the package contents and executable modes. Adapter-only changes receive a new version without a manual bump. Template version fields are excluded from the digest.
+
+Git whitespace checks apply to fork-owned inputs. `.gitattributes` exempts the upstream source paths and generated package so upstream whitespace remains intact. Source integrity and generation checks cover those paths.
+
+Use `$sync-pstack-upstream` on Codex or `/sync-pstack-upstream` on Claude Code to review and integrate upstream changes from a source checkout. A native Claude plugin exposes `/pstack:sync-pstack-upstream`. The skill reads the recorded pin and full upstream diff, reviews changed runtime assumptions, regenerates, verifies, and prepares a PR. It does not merge automatically. Consumer installation updates still use `npx skills update`.
+
+Mechanical merge conflicts in raw `pstack/` are avoided by keeping it pristine. Conflicts in root marketplaces or fork-owned automation can still occur. Semantic changes to upstream workflows still require review and actual execution on the affected runtime. Automated sync PRs report this review gap rather than claiming complete runtime compatibility.
diff --git a/portable/pstack/.claude-plugin/plugin.json b/portable/pstack/.claude-plugin/plugin.json
new file mode 100644
index 000000000..5af356a16
--- /dev/null
+++ b/portable/pstack/.claude-plugin/plugin.json
@@ -0,0 +1,16 @@
+{
+ "name": "pstack",
+ "version": "0.15.6-portable.g23e4138daa01.a3051c49fe822",
+ "description": "Upstream pstack workflows adapted for Claude Code and Codex.",
+ "author": {
+ "name": "yxhta"
+ },
+ "homepage": "https://github.com/yxhta/pstack",
+ "repository": "https://github.com/yxhta/pstack",
+ "license": "MIT",
+ "skills": "./skills/",
+ "agents": [
+ "./runtime-agents/poteto-agent.md",
+ "./runtime-agents/comment-sicko.md"
+ ]
+}
diff --git a/portable/pstack/.codex-plugin/plugin.json b/portable/pstack/.codex-plugin/plugin.json
new file mode 100644
index 000000000..81556ddd8
--- /dev/null
+++ b/portable/pstack/.codex-plugin/plugin.json
@@ -0,0 +1,19 @@
+{
+ "name": "pstack",
+ "version": "0.15.6-portable.g23e4138daa01.a3051c49fe822",
+ "description": "Upstream pstack workflows adapted for Claude Code and Codex.",
+ "author": {
+ "name": "yxhta"
+ },
+ "homepage": "https://github.com/yxhta/pstack",
+ "repository": "https://github.com/yxhta/pstack",
+ "license": "MIT",
+ "skills": "./skills/",
+ "interface": {
+ "displayName": "pstack",
+ "shortDescription": "Upstream pstack for Claude Code and Codex",
+ "defaultPrompt": [
+ "Use poteto-mode for this task."
+ ]
+ }
+}
diff --git a/portable/pstack/.cursor-plugin/plugin.json b/portable/pstack/.cursor-plugin/plugin.json
new file mode 100644
index 000000000..a9a1d13a1
--- /dev/null
+++ b/portable/pstack/.cursor-plugin/plugin.json
@@ -0,0 +1,31 @@
+{
+ "name": "pstack",
+ "displayName": "pstack",
+ "version": "0.15.6",
+ "description": "if you want to go fast, go deep first. pstack helps you write less, but higher quality code. rigorous agent workflows you can parallelize with confidence.",
+ "author": {
+ "name": "Lauren Tan"
+ },
+ "homepage": "https://github.com/cursor/plugins/tree/main/pstack",
+ "repository": "https://github.com/cursor/plugins",
+ "license": "MIT",
+ "logo": "assets/logo.png",
+ "keywords": [
+ "pstack",
+ "poteto-mode",
+ "workflow",
+ "principles",
+ "agent-style",
+ "subagents",
+ "unslop"
+ ],
+ "category": "developer-tools",
+ "tags": [
+ "workflow",
+ "principles",
+ "review",
+ "planning"
+ ],
+ "skills": "./skills/",
+ "agents": "./agents/"
+}
diff --git a/portable/pstack/.gitignore b/portable/pstack/.gitignore
new file mode 100644
index 000000000..aafcb3456
--- /dev/null
+++ b/portable/pstack/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+.DS_Store
+*.log
diff --git a/portable/pstack/LICENSE b/portable/pstack/LICENSE
new file mode 100644
index 000000000..6b5400237
--- /dev/null
+++ b/portable/pstack/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Lauren Tan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/portable/pstack/README.md b/portable/pstack/README.md
new file mode 100644
index 000000000..a01d2d168
--- /dev/null
+++ b/portable/pstack/README.md
@@ -0,0 +1,263 @@
+# pstack
+
+i'm [poteto](https://x.com/poteto). i'm not a president or ceo, but i've worked with millions of lines of code at Meta, Netflix, and Cursor. i'm also on the react core team where i help build and maintain react compiler.
+
+there's a growing sense that ai writes too much slop code. i agree. i don't want to ship like a team of twenty slop artists. throughput without quality is not a goal i aspire to. if you want to go fast, go deep first.
+
+**pstack is my answer.** these are the same skills i use everyday to ship high quality code at Cursor. this turns cursor into a real engineering team. the goal is not to maximize loc, in fact it's the opposite. pstack helps you write less, but higher quality code.
+
+**pstack gives you fearless parallelism.** when you can go deep on one agent and trust it to write good, verifiable code, you can truly parallelize with confidence. start multiple agents up with `poteto-mode` and trust that they'll apply rigorous engineering principles to their work.
+
+**cursor gives you the best of all worlds.** every frontier model has its strengths and weaknesses. use any model with pstack. in fact, many of my skills use multi-model workflows to take advantage of each model's unique strengths.
+
+fork it. improve it. make it yours. PRs are welcome!
+
+## install
+
+```bash
+/add-plugin pstack
+```
+
+## get started
+
+two steps:
+
+1. run [`/setup-pstack`](./skills/setup-pstack/SKILL.md), pick a reasoning budget, and choose which models you want.
+2. use [`/poteto-mode`](./skills/poteto-mode/SKILL.md) whenever you're doing anything that requires rigor.
+
+new here? the [pstack guide](./docs/guide/README.md) walks you through a first real task, from setup and prompting through verification and overnight runs.
+
+that's it. the other skills are situational; the mode skill uses them for you as needed. out of the box the mode splits work by model strength: code delegates (feature, refactoring, bug fix, perf, hillclimb) go to grok, while the hardest changes, prose, and judgment go to opus 5.5. the default panel is opus 5.5 / sol / grok. [`/setup-pstack`](./skills/setup-pstack/SKILL.md) changes any of it.
+
+## usage
+
+use [`/poteto-mode`](./skills/poteto-mode/SKILL.md) at the start of a task. it reads your request, picks from a set of playbooks, and runs the other skills as the steps need them.
+
+### just use [`/poteto-mode`](./skills/poteto-mode/SKILL.md)
+
+this skill is the main shortcut. i use it whenever i need the agent to do rigorous engineering work. it comes with twenty-three playbooks:
+
+```
+/poteto-mode this pr has a subtle bug where the scroll drifts every 750ms even when idle. repro
+first, then fix and verify.
+```
+
+```
+/poteto-mode i'm going to bed. land the stack even if ci flakes. i want everything merged by
+morning.
+```
+
+
+the twenty-three playbooks
+
+| playbook | for |
+|---|---|
+| [investigation](./skills/poteto-mode/playbooks/investigation.md) | a read-only question. how does x work, why was y built this way, are we sure. |
+| [bug fix](./skills/poteto-mode/playbooks/bug-fix.md) | reproduce a defect, root-cause it, and fix with runtime evidence. |
+| [perf](./skills/poteto-mode/playbooks/perf-issue.md) | trace a measured slowness and improve it against a baseline. |
+| [hillclimb](./skills/poteto-mode/playbooks/hillclimb.md) | sustained, scientific improvement of one metric against a target, looping hypotheses with before/after measurement and one commit per accepted win. |
+| [runtime forensics](./skills/poteto-mode/playbooks/runtime-forensics.md) | diagnose a live symptom (leak, idle-cpu spin, glitch) from instrumentation. |
+| [trace forensics](./skills/poteto-mode/playbooks/trace-forensics.md) | diagnose a captured profiling artifact (cpuprofile, trace, spindump, heap snapshot). |
+| [feature](./skills/poteto-mode/playbooks/feature.md) | new or changed behavior, built from a named data shape. |
+| [refactoring](./skills/poteto-mode/playbooks/refactoring.md) | a behavior-preserving change to structure or shape. |
+| [prototype](./skills/poteto-mode/playbooks/prototype.md) | a throwaway sketch to make a design or behavioral decision cheaply, or to settle an empirical fork by observing it. |
+| [visual parity](./skills/poteto-mode/playbooks/visual-parity.md) | pixel-exact ui equivalence between two implementations. |
+| [authoring a skill](./skills/poteto-mode/playbooks/authoring-a-skill.md) | writing or editing a SKILL.md. |
+| [eval](./skills/poteto-mode/playbooks/eval.md) | test how a skill or prompt change affects agent behavior, blinded. |
+| [babysit](./skills/poteto-mode/playbooks/babysit.md) | drive a pr or a stack to merge-ready: conflicts, review threads, ci. |
+| [shipping](./skills/poteto-mode/playbooks/shipping.md) | independently verify a green stack, then land the contiguous verified run bottom-up through github by default or origin when available. |
+| [autonomous run](./skills/poteto-mode/playbooks/autonomous-run.md) | drive a long task to completion without stopping. |
+| [orchestrate](./skills/poteto-mode/playbooks/orchestrate.md) | a standing project handed to one coordinator chat: multi-day, many stacked prs, fleets of subagents. |
+| [autopilot-full](./skills/poteto-mode/playbooks/autopilot-full.md) | run independent prs to merged with one owner per pr and a root swarm verdict on each round, from the code-ready head on. |
+| [autopilot-stack](./skills/poteto-mode/playbooks/autopilot-stack.md) | build and verify one linear base-branch stack for the operator to review and land. |
+| [session pickup](./skills/poteto-mode/playbooks/session-pickup.md) | resume or take over a prior agent's in-flight work. |
+| [pause safely](./skills/poteto-mode/playbooks/pause-safely.md) | suspend in-flight work cleanly so it can be resumed later. |
+| [multi-phase plan](./skills/poteto-mode/playbooks/multi-phase-plan.md) | work that spans phases or stacked PRs. |
+| [worktree cleanup](./skills/poteto-mode/playbooks/worktree-cleanup.md) | reclaim disk by pruning merged or abandoned worktrees and stale ios simulators, safety-gated. |
+| [opening a pr](./skills/poteto-mode/playbooks/opening-a-pr.md) | open a ready pr from small ordered commits with a conventional commits title and a briefing-style body. invoked at the end of every other playbook. |
+
+
+
+
+
+when invoked it:
+
+1. matches your task to a [playbook](./skills/poteto-mode/playbooks/) and opens a todo list whose first items are its steps, copied in verbatim.
+2. routes to the other skills as the steps fire.
+3. writes unslopped replies framed for the consumer and the maintainer.
+
+the full rules and playbooks live in [`skills/poteto-mode/SKILL.md`](./skills/poteto-mode/SKILL.md).
+
+[`/poteto-mode`](./skills/poteto-mode/SKILL.md) is also a sticky mode: once entered it stays on across turns, applying itself when a playbook matches or the task needs rigor and staying out of the way otherwise. opt out any time by saying so.
+
+[`/poteto-mode`](./skills/poteto-mode/SKILL.md) works extremely well with cursor's `/loop` command. you can make cursor work for many hours without sacrificing rigor.
+
+## skills
+
+[`/poteto-mode`](./skills/poteto-mode/SKILL.md) runs most of these for you when a step needs them (`how`, `why`, `architect`, `arena`, `swarm`, `interrogate`, `unslop`, `no-comments`, `technical-writing`, `tdd`, and the principles). the table below is for when you want one directly:
+
+```
+/how do we cancel runs? do we have an n+1 when we look up every run to cancel?
+```
+
+```
+/interrogate review this pr.
+```
+
+
+all skills
+
+| skill | use it when |
+|---|---|
+| [`/poteto-mode`](./skills/poteto-mode/SKILL.md) | default entry point for any non-trivial task. |
+| [`/how`](./skills/how/SKILL.md) | you want a walkthrough of how a subsystem works. |
+| [`/why`](./skills/why/SKILL.md) | you want to know why something was built this way. discovers available MCPs at run time and queries each evidence category in parallel (source control, issue tracker, long-form docs, real-time chat, infra observability, error tracking, analytics warehouse). |
+| [`/recall`](./skills/recall/SKILL.md) | you're starting or resuming work and want your recent context on a topic rebuilt from your own chat history and the shared record, handed back as a tight current-state brief. |
+| [`/blast-radius`](./skills/blast-radius/SKILL.md) | you have a small-looking change and want to know what else it could break, with the one fact it's safe because of proven by running code, not asserted. |
+| [`/architect`](./skills/architect/SKILL.md) | you're about to write code that crosses a function boundary and want the caller's usage, types, and module shape settled first. |
+| [`/arena`](./skills/arena/SKILL.md) | you want N parallel attempts at the same thing, then to grab the best parts of each. |
+| [`/swarm`](./skills/swarm/SKILL.md) | you want N parallel workers across different slices or races, then one aggregated report. |
+| [`/interrogate`](./skills/interrogate/SKILL.md) | you have a diff and want several different models to try to break it, including a strict code-quality lens. |
+| [`/automate-me`](./skills/automate-me/SKILL.md) | you want your own `-mode` skill, drafted from how you've actually worked. |
+| [`/make-bot-ui`](./skills/make-bot-ui/SKILL.md) | you want a page or dashboard whose buttons wake a Grok Bot over a webhook, including the sender-key handoff and Tailscale. |
+| [`/setup-pstack`](./skills/setup-pstack/SKILL.md) | you want to pick which models pstack uses per role. detects your models and writes a config rule. |
+| [`/reflect`](./skills/reflect/SKILL.md) | a long task landed and you want the recipe captured as a skill edit. |
+| [`/teach`](./skills/teach/SKILL.md) | you want to actually understand a change or subsystem, not just have it summarized. runs how + why and weaves one plain explanation, built up diagram by diagram. |
+| [`/tdd`](./skills/tdd/SKILL.md) | you're fixing a bug and there's a cheap local test path. write the failing test first, then the fix. |
+| [`/benchmark-checklist`](./skills/benchmark-checklist/SKILL.md) | you ran a benchmark or measured a speedup or regression. vets the number (limiter, tuning, errors, repeat runs, end-to-end relevance) before you report or act on it. |
+| [`/no-comments`](./skills/no-comments/SKILL.md) | strip comments before review; spawns Comment Sicko, fixes accepted findings, offers encodings for claimed constraints. |
+| [`/typescript-best-practices`](./skills/typescript-best-practices/SKILL.md) | you're reading or editing typescript. grounds the type-system-discipline principle in syntax. |
+| [`/figure-it-out`](./skills/figure-it-out/SKILL.md) | no bundled playbook fits. designs a rigorous, auditable playbook for the task. |
+| [`/show-me-your-work`](./skills/show-me-your-work/SKILL.md) | you want a reviewable decision trail. logs decisions to a tsv you can commit. |
+| [`/create-verification-skill`](./skills/create-verification-skill/SKILL.md) | your project has no scripted way to prove app behavior. generates a project-local verify skill with a feature map, for any language or platform. |
+| [`/maintain-verification-skill`](./skills/maintain-verification-skill/SKILL.md) | your verify skill's feature map has drifted from the app. source wave + one live pass, at most one PR of proven corrections. |
+| [`/unslop`](./skills/unslop/SKILL.md) | you're cleaning up writing. removes AI tells. |
+| [`/bro`](./skills/bro/SKILL.md) | you want the last message restated in plain human language, no jargon. |
+| [`/technical-writing`](./skills/technical-writing/SKILL.md) | layered doc standard (Diátaxis + Google developer style + STE + Global English) for docs, RFCs, readmes, PR descriptions, commit messages. |
+
+
+
+
+
+### examples
+
+mostly i type [`/poteto-mode`](./skills/poteto-mode/SKILL.md) at the start of a task and let it route to a playbook. the other skills fire as the steps need them. a few i reach for directly.
+
+
+
+all the examples
+
+```
+bug fix: /poteto-mode this pr has a subtle bug where the scroll drifts every 750ms even
+ when idle. repro first, then fix and verify.
+perf: /poteto-mode a big list takes a second or two to load even though we virtualize.
+ run a cpu trace and tell me why.
+feature: /poteto-mode build a small feature behind a feature flag. verify it really works.
+prototype: /poteto-mode build two prototypes of the markdown renderer so we can compare.
+ spawn an agent for each.
+multi-phase: /poteto-mode open source these skills as a plugin. nothing internal leaks, work
+ in a temp dir, show me the dependency graph first.
+overnight run: /poteto-mode i'm going to bed. land the stack even if ci flakes. i want
+ everything merged by morning.
+babysit: /poteto-mode check on pr 123. anything outstanding?
+visual parity: /poteto-mode the row spacing is too tall when this flag is on. the second image
+ is correct. repro and fix until it matches.
+figure it out: /poteto-mode i'm stepping away. migrate every caller from the synchronous store
+ to the new async one, keeping behavior identical. i want to trust it was done
+ right when i'm back.
+how: /how do we cancel runs? do we have an n+1 when we look up every run to cancel?
+why: /why is this feature flag not on yet?
+architect: design this instrumentation to be high signal with no false positives. /architect
+ this first.
+arena: /arena take my prompt to the arena verbatim. i want to compare their proposals
+ with yours.
+swarm: /swarm check every package under packages/ against its check.sh. one worker per
+ package. one report.
+interrogate: /interrogate review this pr.
+tdd: /tdd implement
+unslop: can we unslop and tighten the new changes?
+reflect: /reflect that took too long. capture what we learned so the next run doesn't
+ repeat it.
+show-me-your-work: /show-me-your-work keep a decision trail i can review when i'm back.
+automate-me: /automate-me
+```
+
+
+
+## the `poteto-agent` and Comment Sicko subagents
+
+pstack also ships a subagent that runs my style end to end. spawn it from a parent agent via [`subagent_type: "poteto-agent"`](./agents/poteto-agent.md). it reads `poteto-mode` in full, including its inline principles index, before doing any work. substituting `generalPurpose` skips that read and drifts.
+
+[`/poteto-mode`](./skills/poteto-mode/SKILL.md) and [`subagent_type: "poteto-agent"`](./agents/poteto-agent.md) route through the same wrapper.
+
+pstack also ships [Comment Sicko](./agents/comment-sicko.md), a read-only comment reviewer available as `subagent_type: "Comment Sicko"`. usually invoke it through [`/no-comments`](./skills/no-comments/SKILL.md), not directly.
+
+## principles
+
+twenty-four short skills, one principle each. `poteto-mode` indexes them inline and reads that index at task start. the standalone files are there so other skills can reference a principle by name, and so the index can point at the full rule for each.
+
+
+all twenty-four principles
+
+| principle | group | rule |
+|---|---|---|
+| [laziness-protocol](./skills/principle-laziness-protocol/SKILL.md) | core | Bias toward deletion and the smallest change that solves the problem. |
+| [foundational-thinking](./skills/principle-foundational-thinking/SKILL.md) | core | Apply before writing logic: choosing core types and data structures, sequencing scaffold-vs-feature work, asking what concurrent actors share. Get the data structures right so downstream code becomes obvious. |
+| [redesign-from-first-principles](./skills/principle-redesign-from-first-principles/SKILL.md) | core | Redesign as if the requirement had been a foundational assumption from day one, instead of bolting it on. |
+| [attack-the-premise](./skills/principle-attack-the-premise/SKILL.md) | core | Apply when two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it. |
+| [subtract-before-you-add](./skills/principle-subtract-before-you-add/SKILL.md) | core | Remove dead weight, redundant validators, and stub references first, then build on the simpler base. |
+| [minimize-reader-load](./skills/principle-minimize-reader-load/SKILL.md) | core | Count layers between question and answer, and hidden state in the reader's head; collapse one-caller wrappers and shrink mutable scope. |
+| [outcome-oriented-execution](./skills/principle-outcome-oriented-execution/SKILL.md) | core | Apply during planned rewrites and migrations with explicit phase boundaries. Converge on the target architecture; don't preserve smooth intermediate states with throwaway compatibility code. |
+| [experience-first](./skills/principle-experience-first/SKILL.md) | core | Choose user delight over implementation convenience; ship fewer polished features over more rough ones. |
+| [exhaust-the-design-space](./skills/principle-exhaust-the-design-space/SKILL.md) | core | Build 2-3 competing prototypes and compare side by side before committing. |
+| [build-the-lever](./skills/principle-build-the-lever/SKILL.md) | core | Apply to any non-trivial work, not just bulk work: edits, migrations, analyses, checks. Build the tool that does it or proves it (codemod, script, generator, or a skill your subagents follow) instead of working by hand. The tool is the artifact a reviewer can rerun. |
+| [model-the-domain](./skills/principle-model-the-domain/SKILL.md) | architecture | Encode the domain in a structure instead of scattered conditionals. |
+| [boundary-discipline](./skills/principle-boundary-discipline/SKILL.md) | architecture | Concentrate guards at system boundaries (CLI, config, network, external APIs); trust internal types and keep business logic in pure functions. |
+| [type-system-discipline](./skills/principle-type-system-discipline/SKILL.md) | architecture | Make illegal states unrepresentable, brand semantic primitives, parse external data at boundaries, refuse to lie to the compiler, exhaust variants, derive from authoritative schemas. |
+| [make-operations-idempotent](./skills/principle-make-operations-idempotent/SKILL.md) | architecture | Converge to the same end state regardless of partial prior runs. |
+| [migrate-callers-then-delete-legacy-apis](./skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md) | architecture | Migrate callers and delete the old API in the same wave instead of preserving compatibility layers. |
+| [separate-before-serializing-shared-state](./skills/principle-separate-before-serializing-shared-state/SKILL.md) | architecture | Eliminate the sharing first; serialize structurally only when one shared writer is a real invariant. |
+| [prove-it-works](./skills/principle-prove-it-works/SKILL.md) | verification | Apply after completing a task, before declaring done. Verify against the real artifact (run the feature, read the actual value, inspect the diff), not a proxy, self-report, or 'it compiles.'. |
+| [fix-root-causes](./skills/principle-fix-root-causes/SKILL.md) | verification | Trace each symptom to its root cause and fix it there; reproduce first, ask why until you reach it, resist nil-check guards that silence crashes. |
+| [sequence-verifiable-units](./skills/principle-sequence-verifiable-units/SKILL.md) | verification | Apply to multi-step work (sweeps, migrations, runs of similar edits) and to how you stack commits and PRs. Break work into small units that each end in a verifiable state, check each before the next, and order delivery so the sequence proves itself to a reviewer. |
+| [test-behavior-not-implementation](./skills/principle-test-behavior-not-implementation/SKILL.md) | verification | Apply when you write, change, or keep a test. Call the code the way its users do and assert the result they observe against a literal expected value. If the test would still pass when every imported function returns undefined, rewrite the assertion or delete the test. |
+| [explain-the-number](./skills/principle-explain-the-number/SKILL.md) | verification | Apply before you trust, report, or act on a number you measured: a speedup, a regression, a throughput, a latency, or an eval result. Find what limits it, and rule out that it measured something other than the work you think. |
+| [guard-the-context-window](./skills/principle-guard-the-context-window/SKILL.md) | delegation | Route bulk to subagents; keep summaries in the main thread, not raw payloads. |
+| [never-block-on-the-human](./skills/principle-never-block-on-the-human/SKILL.md) | delegation | Proceed, present the result, let the human course-correct after the fact; reserve confirmation for irreversible actions. |
+| [encode-lessons-in-structure](./skills/principle-encode-lessons-in-structure/SKILL.md) | meta | Encode the rule as a lint, metadata flag, runtime check, or script instead of more text. |
+
+
+
+## not shipped here
+
+a few things `poteto-mode` references but doesn't bundle:
+
+- `/deslop` and the `deslop` skill ship in the `cursor-team-kit` plugin.
+- `control-cli` (for CLIs and TUIs) and `control-ui` (for browser, Electron, web) ship in `cursor-team-kit` too.
+- `/create-skill` is a cursor built-in. cursor also ships a built-in `/babysit`; inside `poteto-mode`, the [babysit playbook](./skills/poteto-mode/playbooks/babysit.md) supersedes it for pr-status requests.
+
+install `cursor-team-kit` alongside pstack if you want the full set.
+
+## why are there no planning skills?
+
+cursor already has a great plan mode which works great with pstack. but personally, i don't believe in planning. the best spec is code. if you do want to make a plan, [`/poteto-mode`](./skills/poteto-mode/SKILL.md) covers it, but it's not a default.
+
+## make it yours
+
+`poteto-mode` is my style. you may not want exactly that.
+
+type [`/automate-me`](./skills/automate-me/SKILL.md). it mines your recent transcripts, drafts a `-mode` skill from how you've actually worked, and routes through pstack underneath. you keep pstack as the base and end up with your own routing skill alongside `poteto-mode`.
+
+models are configurable too. type [`/setup-pstack`](./skills/setup-pstack/SKILL.md). it detects the models you have access to and writes a small always-applied rule mapping each role (code, judgment, the review panels) to a model. every skill reads it and falls back to sensible defaults when the rule is absent, so you override only what you want.
+
+a rule written before 0.15.3 pins the old default models. delete those role lines, or delete the file, then run `/setup-pstack` again. a rerun keeps any role whose model differs from the default.
+
+## automations
+
+pstack also ships a dormant [benny automation pack](./automations/benny/). benny triages slack issue reports, then reproduces and fixes confirmed bugs with real ui evidence. its files are not registered as slash skills.
+
+to set it up, point cursor at [`FOR_AGENTS.md`](./automations/benny/FOR_AGENTS.md). setup copies the pack into the target repository at `.cursor/automations/benny/`, enables pstack there for shared skills, and keeps user configuration outside the copied pack.
+
+## license
+
+MIT
diff --git a/pstack/skills/poteto-mode/references/portable-agents/comment-sicko.md b/portable/pstack/agents/comment-sicko.md
similarity index 100%
rename from pstack/skills/poteto-mode/references/portable-agents/comment-sicko.md
rename to portable/pstack/agents/comment-sicko.md
diff --git a/pstack/skills/poteto-mode/references/portable-agents/poteto-agent.md b/portable/pstack/agents/poteto-agent.md
similarity index 100%
rename from pstack/skills/poteto-mode/references/portable-agents/poteto-agent.md
rename to portable/pstack/agents/poteto-agent.md
diff --git a/portable/pstack/assets/logo.png b/portable/pstack/assets/logo.png
new file mode 100644
index 000000000..3754e87cb
Binary files /dev/null and b/portable/pstack/assets/logo.png differ
diff --git a/portable/pstack/automations/benny/FOR_AGENTS.md b/portable/pstack/automations/benny/FOR_AGENTS.md
new file mode 100644
index 000000000..e732156e9
--- /dev/null
+++ b/portable/pstack/automations/benny/FOR_AGENTS.md
@@ -0,0 +1,89 @@
+# benny automation intent
+
+## what i want to automate
+
+i want two cursor automations that work together in one slack issue channel.
+
+### automation 1: triage issue reports
+
+- trigger: when someone posts a new top-level report in my configured source slack channel, i want this automation to start on that report and keep its original thread coordinates.
+- behavior: i want it to read the thread and attachments, classify the report as a bug or performance issue, feature request, question or feedback, or reroute, and trace the likely owning layer before routing.
+- tracker: i want it to search my configured tracker for duplicates, update a confident duplicate, and create a ticket only for a clear net-new bug.
+- tools: i want slack thread read and reply access, my configured tracker integration, and my optional routing map.
+- outcome: i want exactly one reply in the source thread with a short verdict and `[benny:bug]`, `[benny:performance]`, or `[benny:other]`. a bug or performance marker may include the tracker url.
+- boundary: i never want this automation to post a root message in the source channel.
+
+### automation 2: reproduce and fix confirmed bugs
+
+- trigger: i want this automation to start from the same new top-level report, or another supported trigger chosen during setup, then wait for the trusted triage marker in the original thread.
+- gates: i want it to stop when someone clearly owns the fix. if an existing pull request or merged commit may fix the report, i want verification instead of a competing change.
+- behavior: i want it to use my configured control adapter and feature map, reproduce the exact symptom twice through the real ui, and capture screenshots, video, and a read-only state cross-check.
+- fix: i want it to verify existing pull requests without authoring over them. after a confirmed repro, it may attempt one bounded root-cause fix, use tdd when the test is cheap, smoke the blast radius, and open a draft pull request only when before-and-after proof passes.
+- tools: i want slack thread read and reply access, repository and history access, draft pull request creation, my configured tracker, and my control adapter.
+- outcome: i want evidence and a verified result in the source or optional operations threads, plus an optional draft pull request. updates should be concise.
+- boundary: i never want this automation to post a root message in the source channel.
+
+### shared rules
+
+- i want the source channel and root thread coordinates to stay immutable for the whole run.
+- i treat utility and debug bots as evidence, not delegation or fix ownership.
+- i allow subagents to help, but they cannot post to slack or receive slack credentials.
+- i want this entire pack committed at `.cursor/automations/benny/` in the target repository. its `SKILL.md` files are direct automation instructions, not registered plugin skills.
+- i want pstack enabled through the target repository's committed `.cursor/settings.json` only for shared dependencies such as `how`, `why`, `tdd`, `unslop`, and the required principle skills.
+- i want each live automation prompt to read its committed operational file directly. i do not want plugin cache paths, copied excerpts, or slash-skill discovery.
+- i keep user-owned configuration, feature maps, routing maps, and secrets outside `.cursor/automations/benny/` so pack refreshes cannot overwrite them.
+- i want both automations to fail closed when channel coordinates, tracker access, the control adapter, or the feature map are missing or uncertain.
+- i want draft pull requests only. do not merge or deploy.
+
+### my configuration
+
+- source slack channel: ``
+- optional operations channel: ``
+- repository and default branch: ``, ``
+- tracker: ``
+- routing map: ``
+- triage identity: ``
+- control skill: ``
+- feature map: ``
+- models: ``
+- status emoji strings: ``
+- budgets: ``
+- optional bot token capability: ``
+
+start from [`configuration.example.yaml`](./templates/configuration.example.yaml) and [`feature-map.example.md`](./skills/reproduce-and-fix-issues/references/feature-map.example.md). copy and fill them outside this pack, for example under `.cursor/benny/`. keep secret values in a secret manager or environment.
+
+## for the agent
+
+the human enters setup by pointing cursor at this file. do not look for or invoke a discovered benny slash skill.
+
+1. ask which repository will run the automations.
+2. treat the directory containing this `FOR_AGENTS.md` as the source pack.
+3. merge the entire source pack into `/.cursor/automations/benny/`.
+4. preserve every destination-only file. never delete unrelated files or overwrite user-owned configuration, feature maps, or routing maps.
+5. when an existing destination file at a source-managed path differs, review the diff and merge without discarding local edits. if ownership is ambiguous, stop and ask before replacing it.
+6. verify that the copied `FOR_AGENTS.md` and `skills/setup-benny/SKILL.md` exist in the target repository.
+7. read and follow `.cursor/automations/benny/skills/setup-benny/SKILL.md` directly from the target repository.
+
+i want you to merge this entry into the target repository's `.cursor/settings.json`:
+
+```json
+{
+ "plugins": {
+ "pstack": { "enabled": true }
+ }
+}
+```
+
+preserve every unrelated setting and plugin. preserve comments and valid jsonc syntax when the existing file uses jsonc.
+
+i want verification from a fresh agent rooted in the target repository. confirm that pstack's `how`, `why`, `tdd`, `unslop`, and the principle skills used by benny resolve in project scope. do not count skills loaded from the current session or a user-scoped install.
+
+if project-scoped plugins are unavailable or any shared dependency does not resolve, stop and explain what failed. do not add `.cursor/automations/benny/skills/` to a plugin manifest or expect its files to appear in the slash-skill list.
+
+tell me that `.cursor/settings.json`, `.cursor/automations/benny/`, and any referenced secret-free configuration must be committed before either automation is enabled. do not create or update an automation until i explicitly ask.
+
+for first-time creation, use built-in `/automate` once for triage and once for repro and fix. complete the draft review, approval, readiness check, and Automations editor handoff for the first automation before starting the second.
+
+paraphrase this intent and the finished configuration into each draft. the triage prompt must read and follow `.cursor/automations/benny/skills/triage-issue-reports/SKILL.md`. the repro prompt must read and follow `.cursor/automations/benny/skills/reproduce-and-fix-issues/SKILL.md`. use these repo-relative paths only after `/automate` confirms they are committed in the repository where the automation will run.
+
+for existing automations, do not use `/automate` to inspect or update them. validate the configuration, then use the concise field checklist in the copied setup file so i can edit each automation directly in its editor. do not create duplicates.
diff --git a/portable/pstack/automations/benny/README.md b/portable/pstack/automations/benny/README.md
new file mode 100644
index 000000000..76804c8c5
--- /dev/null
+++ b/portable/pstack/automations/benny/README.md
@@ -0,0 +1,23 @@
+# benny
+
+benny gives you two cursor automations for slack issue reports. one triages each report. the other reproduces confirmed bugs and may prepare a small draft fix.
+
+the files in this directory are dormant setup and automation sources. they do not appear as slash skills.
+
+## set it up
+
+1. point cursor at [`FOR_AGENTS.md`](./FOR_AGENTS.md) and name the target repository.
+2. let setup merge this whole directory into the target at `.cursor/automations/benny/`. it must preserve destination-only files and review conflicts instead of overwriting local edits.
+3. let setup enable pstack in the target repository's `.cursor/settings.json` for shared dependencies:
+
+```json
+{
+ "plugins": {
+ "pstack": { "enabled": true }
+ }
+}
+```
+
+4. keep user-owned configuration outside the copied pack, for example in `.cursor/benny/`. adapt [`configuration.example.yaml`](./templates/configuration.example.yaml) and [`feature-map.example.md`](./skills/reproduce-and-fix-issues/references/feature-map.example.md).
+5. commit `.cursor/settings.json`, `.cursor/automations/benny/`, and any secret-free configuration before enabling either automation.
+6. review each new automation draft or update existing automations in their editors. then send a harmless test report and verify every source-channel post stays in the original thread.
diff --git a/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md
new file mode 100644
index 000000000..effa5f0a3
--- /dev/null
+++ b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md
@@ -0,0 +1,310 @@
+---
+name: reproduce-and-fix-issues
+description: Reproduce triaged Slack bugs through a configured app-control adapter, verify existing fixes, and open a bounded draft pull request only after before-and-after proof. Use only from the configured Benny repro automation.
+disable-model-invocation: true
+---
+
+# Reproduce and fix issues
+
+Wait for a trusted triage marker in the source thread. Reproduce the exact symptom through the target app's real UI. Verify an existing fix when one exists. Attempt a bounded fix only after a confirmed repro.
+
+Load the external Benny configuration supplied by the automation. If the config, required actions, control adapter, or completed feature map is missing, fail closed.
+
+## Hard safety rules
+
+- Freeze the source channel and root thread coordinates before doing any work.
+- Never post a root message in the source channel.
+- Preflight the source parent before every source-thread post.
+- The coordinator is the only Slack poster.
+- Delegated analysis workers are read-only and return findings or media notes.
+- A fix-phase code worker may edit only when its environment provably excludes Slack credentials and every Slack write action. Otherwise the coordinator edits.
+- Every child prompt must explicitly forbid `SendSlackMessage`, `PostToSlack`, `chat.postMessage`, and all other Slack writes.
+- Never give a child a Slack token, posting instructions, source coordinates for posting, or permission to report externally.
+- If a child needs Slack write access to run, do not launch it.
+- Utility bots are evidence sources. They do not own the fix unless a person explicitly delegated the fix to them.
+- The exact discriminating symptom must appear twice through real UI interaction.
+- State inspection may confirm an observation. It must not inject or force the symptom.
+- No confirmed repro means no authored fix.
+- Existing pull requests or commits switch the run to verify mode. Do not author over them.
+- Use `github.com` pull request links.
+- Keep captures, recordings, logs, and tokens out of source control.
+- Use pstack's `principle-guard-the-context-window` for delegated analysis.
+- Apply pstack's `principle-sequence-verifiable-units`, `principle-fix-root-causes`, and `principle-prove-it-works` through repro, fix, and verification.
+
+## 1. Freeze source coordinates
+
+Before making a work list or delegating:
+
+1. Require the trigger channel to equal the configured source channel.
+2. Set `SOURCE_THREAD_TS` to `trigger.thread_ts` when present. Otherwise use `trigger.ts`.
+3. Require a nonempty `SOURCE_THREAD_TS`.
+4. Store `SOURCE_CHANNEL_ID` and `SOURCE_THREAD_TS` as immutable values.
+5. Read the source thread and verify its root has those exact coordinates.
+6. Fetch the source permalink.
+
+Never replace these values with a reply timestamp, operations timestamp, or status-message timestamp.
+
+Before every source-channel post:
+
+1. Read the thread by the immutable coordinates.
+2. Confirm the parent exists, is not deleted, and still belongs to the source channel.
+3. Send only with `channel=SOURCE_CHANNEL_ID` and `thread_ts=SOURCE_THREAD_TS`.
+4. Read the thread again and verify the new message is a reply.
+
+If any check fails, post nothing. Never retry at the root or in a fallback channel.
+
+## 2. Wait for the triage contract
+
+Watch the source thread for the configured verdict budget. Stay silent while waiting.
+
+Accept a verdict only when:
+
+- Its author matches `slack.triage_identity_user_id`.
+- It is a reply under `SOURCE_THREAD_TS`.
+- It contains exactly one configured marker.
+
+Public marker forms:
+
+```text
+[benny:bug]
+[benny:bug] tracker=https://tracker.example/issue/123
+[benny:performance]
+[benny:performance] tracker=https://tracker.example/issue/123
+[benny:other]
+```
+
+Proceed only for `bug` or `performance`. Capture the optional tracker URL. Stop silently for `other`, a missing verdict, an untrusted author, conflicting markers, or a timeout.
+
+This marker replaces private bot identities and free-form verdict matching.
+
+## 3. Apply ownership and fix-artifact gates
+
+Re-read the thread immediately before starting work.
+
+### Someone is explicitly fixing it
+
+Stop when a person clearly claims the fix, gives a concrete implementation plan, or asks another agent to implement, patch, fix, or open a pull request.
+
+Do not treat these as fix ownership:
+
+- A bot summarizes evidence.
+- A tool looks up logs or tickets.
+- Someone asks a bot to diagnose, explain, inspect, or reproduce.
+- A bot posts a cause hypothesis without agreeing to implement it.
+
+Judge the requested action, not the presence of a bot.
+
+### A fix artifact already exists
+
+If an open pull request or merged commit plausibly fixes this report, switch to `references/verify-existing-fix.md`.
+
+An artifact may come from the thread, tracker issue, repository history, or pull request search. A claim without a commit or pull request is not a fix artifact.
+
+If a person owns the work but has not produced an artifact, stop. Do not race them.
+
+## 4. Open an optional operations thread
+
+If `slack.operations_channel_id` is configured, the coordinator may create one root status message there. This is the only allowed root post in the repro workflow.
+
+Store its coordinates as `OPERATIONS_CHANNEL_ID` and `OPERATIONS_THREAD_TS`. Never confuse them with the source coordinates.
+
+Use the configured plain Unicode status strings. Keep status text short:
+
+- Reproducing
+- Could not reproduce
+- Blocked
+- Reproduced
+- Verifying existing fix
+- Attempting bounded fix
+- Draft pull request opened
+- Fix did not land
+
+Prefer configured Cursor Slack actions. Use `BENNY_SLACK_BOT_TOKEN` only when the user configured it for a narrow missing capability such as editing this one status message. Never expose the token to a worker.
+
+If no operations channel is configured, keep detailed status in the automation run output. Do not substitute a source-channel root message.
+
+## 5. Load and check the control adapter
+
+Read `references/control-adapter.md` and the completed map at `control.feature_map_path`, then invoke the skill named by `control.skill_name`.
+
+Find the feature-map section that matches the reported user path. Read it before driving the app. If no section covers the feature, mark the run blocked instead of inventing a path or selector.
+
+Require all seven capabilities:
+
+1. Bring up the configured target app and test environment.
+2. Navigate the mapped feature and exercise its documented states.
+3. Drive the real UI with clicks, typing, keys, scrolling, drag, resize, or navigation.
+4. Inspect state without mutating it.
+5. Capture screenshots.
+6. Start and stop a screen recording.
+7. Clean up processes, sessions, profiles, and temporary data.
+
+If the adapter is absent or any required capability is missing, mark the operations status as blocked and stop. Do not pretend a screenshot, unit test, state mutation, or source reading is a UI repro.
+
+## 6. Study the report
+
+Read the full source thread and tracker issue when present.
+
+Collect:
+
+- Exact action path
+- Expected behavior
+- Observed behavior
+- Discriminating state where they diverge
+- Frequency
+- Version, environment, and platform
+- Attachments and error signatures
+- Candidate code area
+
+Inspect screenshots and video. Use read-only parallel workers for code history, test ideas, blast-radius mapping, and media review when useful. Each worker gets a narrow question and the Slack-write prohibition.
+
+Use pstack's `how` skill to trace the action through the repository. Use `why` for regression history and defensive code. Form competing cause hypotheses and identify evidence that would separate them.
+
+## 7. Reproduce
+
+Bring up the target app through the control adapter.
+
+Confirm the correct app, workspace, account, data set, and feature state before acting. Use stable app markers. Do not rely on window order or a familiar title alone.
+
+Drive the reported path through real UI actions.
+
+Before calling it reproduced:
+
+1. Name the correct final state.
+2. Name the broken final state.
+3. Reach the point where they diverge.
+4. Observe the broken state.
+5. Reset enough state to make the second attempt independent.
+6. Repeat the same path and observe the same broken state again.
+7. Cross-check a real state value when possible.
+
+An expected dialog, loading state, or setup step is not the bug. Capture the final state that distinguishes correct from broken behavior.
+
+Use the configured repro budget. If the symptom does not reproduce within it, report a clean `Could not reproduce` outcome. If the environment cannot provide a required capability, report `Blocked` and state what was missing.
+
+## 8. Capture and review evidence
+
+For a successful repro:
+
+- Record the full path through the symptom.
+- Capture a screenshot of the broken final state.
+- Save a short note with the exact steps and observed state.
+- Keep artifacts in the configured temporary artifact directory.
+
+Have a read-only media reviewer answer one question: does the evidence visibly show the discriminating broken state?
+
+If the answer is no or uncertain, the repro is not confirmed. Capture better evidence or use `Could not reproduce`.
+
+Post detailed evidence only in the operations thread when configured. Keep the source update concise.
+
+## 9. Report the repro outcome
+
+Update the operations status first.
+
+For `Could not reproduce` or `Blocked`, post nothing in the source thread. The operations thread or run output carries the result.
+
+For a confirmed repro, run the source preflight and post at most one unprompted source reply:
+
+- Say the issue reproduced.
+- Link the operations evidence thread when one exists.
+- Include at most three short findings.
+- Link the tracker issue when one exists.
+- Do not ping an owner by default.
+
+Attach evidence only when the configured Slack action keeps it inside the same source thread and the organization's retention policy allows it.
+
+Wait for the configured rejection window. If a person shows that the setup or interpretation was wrong, correct the repro once. Do not start the fix phase until the window closes without a valid rejection.
+
+## 10. Verify an existing fix
+
+When a fix artifact exists, follow `references/verify-existing-fix.md`.
+
+Verification must show the symptom on the baseline and its absence on the patched build. Both paths use the real UI twice.
+
+Do not edit the existing fix, add a competing patch, or open a replacement pull request.
+
+## 11. Qualify a bounded fix
+
+Attempt a fix only when all of these hold:
+
+- The outcome is a plain confirmed repro.
+- Media review confirmed the broken final state.
+- No existing fix artifact appeared.
+- No person claimed the fix during the rejection window.
+- Runtime evidence identifies the root cause.
+- The likely change fits the configured fix budget and repository scope.
+- The control adapter can run both baseline and patched builds.
+
+If any condition fails, keep the repro report and stop without a pull request.
+
+When the gate passes, update operations status to `Attempting bounded fix`.
+
+## 12. Root-cause and implement
+
+The coordinator owns every Slack post, the final diff review, commits, and the pull request.
+
+Read-only workers may:
+
+- Trace code and history
+- Propose tests
+- Map blast radius
+- Review a diff
+- Review media
+
+They do not edit, run external writes, post status, or own the fix.
+
+A tightly scoped code edit may be delegated during this phase only when tool isolation removes Slack credentials and every Slack write action from that worker. Its prompt must still carry the explicit Slack-write ban. The coordinator reviews the edit and runs or verifies the required tests. If tool isolation is uncertain, keep the edit in the coordinator.
+
+Confirm the mechanism with runtime evidence. Eliminate competing hypotheses before editing.
+
+Fix the root cause with the smallest justified change.
+
+- Invoke pstack's `tdd` skill when there is a cheap local test target, and write the failing test before the fix.
+- State why TDD was skipped when the path is expensive, unclear, or integration-heavy.
+- Keep unrelated cleanup out.
+- Stop if the change grows beyond the configured effort or risk budget.
+
+## 13. Prove the fix
+
+Keep the original baseline evidence.
+
+On the patched build:
+
+1. Run the same real UI path.
+2. Repeat it twice.
+3. Show that the broken state is gone.
+4. Show the expected state in its place.
+5. Capture an after recording and screenshot.
+6. Cross-check the same real state value used for the baseline.
+
+A compile, unit test, code review, or plausible diff is not after evidence.
+
+Run focused tests, then smoke the blast radius around the changed behavior. Cover nearby states, inputs, permissions, platforms, and failure paths that the change could affect. Stop without a pull request if a regression remains.
+
+## 14. Open a draft pull request
+
+Only after before-and-after proof:
+
+- Review the final diff for unrelated changes and secrets.
+- Run the repository's required checks.
+- Create small ordered commits when the repository workflow allows it.
+- Open a draft pull request. Never merge or deploy from this workflow.
+- Link the configured tracker issue using the tracker's supported pull request syntax.
+- Use the configured public URL form, normally `https://github.com/{owner}/{repo}/pull/{number}`.
+- Include the repro steps, root cause, test result, before and after evidence, and blast-radius checks.
+- Run the pull request text and all Slack updates through pstack's `unslop` skill.
+
+If pull request creation fails, do not claim success. Keep the commit or branch state in the run output and mark operations status `Fix did not land`.
+
+On success, mark operations status `Draft pull request opened` and post one concise reply in the operations thread with the linked pull request. Do not create a second source-channel root or unprompted source reply.
+
+## 15. Follow-ups and cleanup
+
+Watch the configured operations thread for one follow-up window.
+
+- Answer a direct question from evidence already gathered.
+- Apply one concrete correction and rerun the repro once when it invalidates the setup.
+- Stay out of human coordination and side chatter.
+- Stop when asked.
+
+Always call the control adapter's cleanup capability. Keep artifacts only as long as the configured retention policy allows.
diff --git a/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md
new file mode 100644
index 000000000..3399491ed
--- /dev/null
+++ b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md
@@ -0,0 +1,169 @@
+# Control-adapter contract
+
+Benny does not know how to start or drive every app. The user must configure one control skill or adapter that implements this contract for the target app.
+
+Set its skill name in `control.skill_name`.
+
+Set the completed user-facing feature map path in `control.feature_map_path`. Copy and fill [`feature-map.example.md`](./feature-map.example.md) outside `.cursor/automations/benny/` instead of editing the copied example.
+
+If the skill, feature map, or a required capability is absent, ambiguous, or incomplete, repro and fix work must fail closed.
+
+## Required capabilities
+
+### Bring up
+
+Start the requested app revision in the requested test environment.
+
+Input:
+
+- Repository and revision
+- Build or start mode
+- Workspace, account, fixture, and feature-state requirements
+- Artifact directory
+- Completed feature-map path
+
+Return:
+
+- Session identifier
+- How the adapter confirmed the correct app and environment
+- Stable app markers
+- Running process or target details needed by later calls
+- Any missing capability
+
+The adapter must distinguish the target app from a similar window, shell, or production instance.
+
+### Drive UI
+
+Perform real user actions:
+
+- Click
+- Type
+- Press keys
+- Scroll
+- Drag
+- Resize
+- Navigate through app controls
+
+Prefer roles, labels, and stable selectors. Use coordinates only after a fresh screenshot.
+
+Return each action and the observed state change.
+
+Do not set internal state, call hidden app methods, write directly to storage, or inject DOM changes to create the symptom.
+
+### Drive mapped features and states
+
+Read the relevant feature-map section before driving the app.
+
+The adapter must expose ways to:
+
+- Navigate every mapped feature through the user-visible path.
+- Invoke the adapter action names listed for that feature.
+- Interact with default, hover, focus-visible, active, disabled, loading, empty, error, selected, open, expanded, and feature-specific states when they apply.
+- Arrange a state through safe fixture data, permissions, flags, service responses, or supported test controls.
+- Reset the feature for a second independent repro attempt.
+- Capture the screenshot, video, and read-only cross-check named by the feature map.
+
+Use roles, accessible names, ARIA relationships, stable component markers, and purpose-named data attributes. Never use generated CSS or StyleX classes, dynamic hashes, child indexes, or brittle DOM position.
+
+Arranging a precondition is not permission to inject the reported symptom. The repro itself must still come from real user interaction.
+
+### Inspect state
+
+Read state to confirm what the UI shows.
+
+Examples:
+
+- Accessibility tree
+- DOM or view hierarchy
+- Process state
+- Local logs
+- Network request status
+- App-exposed debug state
+
+Inspection is read-only. If a query changes state, it belongs in `drive UI` and must represent a real user action.
+
+### Screenshot
+
+Capture the current app state to a requested path.
+
+Return:
+
+- File path
+- Capture time
+- App marker or window title
+- Short description of what should be visible
+
+The screenshot must show enough app chrome to prove that the correct app is under test.
+
+### Recording
+
+Start and stop a screen recording around the full repro path.
+
+Return:
+
+- File path
+- Start and stop times
+- Captured window or region
+- Whether audio or sensitive overlays were omitted
+
+The recording must show the discriminating final state, not only setup or a loading screen.
+
+### Cleanup
+
+Stop processes and sessions created by the adapter.
+
+Remove disposable:
+
+- Browser or app profiles
+- Temporary workspaces
+- Test accounts or fixtures when the adapter created them
+- Debug ports and tunnels
+- Captures past their retention window
+
+Return what was stopped, removed, retained, or left for a person.
+
+Cleanup must not delete user work.
+
+## Adapter behavior
+
+The adapter must:
+
+- Report capabilities before the repro starts.
+- Report which feature-map sections it can drive and which are blocked.
+- Use the same environment inputs for baseline and patched builds.
+- Surface startup failures as failures.
+- Bound retries.
+- Keep secrets out of logs and artifacts.
+- Keep captures outside the repository.
+- Support a fresh or reset state between the two repro attempts.
+- Avoid production changes unless the user explicitly configured a safe test action.
+
+## Environment translation
+
+Before declaring an environment block, restate the defect without platform-specific nouns and ask whether the same behavior can be tested safely in the available environment.
+
+Examples:
+
+- A named browser may mean any external browser.
+- A named key may mean the configured shortcut.
+- A named remote host may mean a delayed or disconnected remote target.
+
+Use a translated attempt only when it tests the same underlying behavior. Label it as translated evidence. Do not call it an exact repro when the missing environment is part of the defect.
+
+Hardware prompts, operating-system permission dialogs, device-only APIs, and unavailable account states may be real blocks.
+
+## Setup check
+
+Before enabling the repro automation, run one harmless adapter check:
+
+1. Bring up the app.
+2. Confirm the stable app marker.
+3. Load one completed feature-map section.
+4. Navigate to that feature through its user path.
+5. Exercise one disposable state through mapped adapter actions.
+6. Inspect the resulting state.
+7. Capture a screenshot.
+8. Record a short clip.
+9. Clean up.
+
+Enable repro work only when all nine steps succeed and no source-channel Slack post is involved.
diff --git a/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md
new file mode 100644
index 000000000..620ddedba
--- /dev/null
+++ b/portable/pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md
@@ -0,0 +1,205 @@
+# Feature-map example
+
+Map every user-facing feature Benny may reproduce. Read the relevant section before driving the app. Keep this map at the user point of view. Discover internals and current code paths at runtime instead of freezing them here.
+
+Copy this file outside `.cursor/automations/benny/`, for example to `.cursor/benny/feature-map.md`, and set `control.feature_map_path` to the copy. Pack refreshes must not overwrite it.
+
+## Per-feature template
+
+### ``
+
+``
+
+#### How a user gets there
+
+- Click path: ` ->