From 0452e08a314c03621ec5ac1324f1ad1dd824f1a4 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 23 Jun 2026 21:43:34 -0700 Subject: [PATCH 01/17] pstack: add Benny issue automation pack (#137) ## Summary - add a dormant Benny source pack for thread-only issue triage and evidence-backed repro and fix workflows - copy the pack into target repositories so live automations read committed files directly without exposing Benny as slash skills - keep pstack enabled only for shared workflow dependencies and preserve user-owned configuration outside pack refreshes ## Test plan - [x] `node scripts/validate-plugins.mjs` - [x] validate the manifest exposes only `./skills/`, direct operational paths, Markdown links, JSON and YAML examples, frontmatter, and unique skill names - [x] scan the branch for discovery contradictions, private names, IDs, credentials, endpoints, and local plugin paths - [x] run `git diff --check origin/main...HEAD` and review the full branch diff --- > [!NOTE] > **Low Risk** > Documentation and dormant automation sources only; no runtime code paths in the plugin. Operational risk applies only after users enable automations with Slack, tracker, and repo write access in their own repos. > > **Overview** > **Bumps pstack to 0.10.0** and documents a new **dormant Benny pack** under `automations/benny/` for Slack-driven issue workflows (not added to the plugin slash-skill manifest). > > The pack defines **two coordinated Cursor automations**: **triage** (classify reports, cause-aware routing, tracker dedupe, single thread reply with `[benny:bug]` / `[benny:performance]` / `[benny:other]`) and **repro/fix** (wait for trusted triage markers, double UI repro via a configured control adapter, verify existing PRs, optional bounded fix with **draft-only** PRs). Operational behavior lives in committed `SKILL.md` files with strict thread-only Slack rules, fail-closed gates, and coordinator-only posting. > > **Setup** is agent-driven via `FOR_AGENTS.md` and `setup-benny`: merge the pack into the target repo at `.cursor/automations/benny/`, enable **pstack** in `.cursor/settings.json` for shared skills (`how`, `why`, `tdd`, `unslop`, principles), keep user config outside the pack, and wire live automations through `/automate` (or editor updates for existing ones). Templates cover configuration, routing, feature maps, control-adapter contract, and prompt shims. > > Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1028dd3a69a2dc0dbbdb69348c55785318b96c09. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot). --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/README.md | 6 + pstack/automations/benny/FOR_AGENTS.md | 89 +++++ pstack/automations/benny/README.md | 23 ++ .../skills/reproduce-and-fix-issues/SKILL.md | 310 ++++++++++++++++++ .../references/control-adapter.md | 169 ++++++++++ .../references/feature-map.example.md | 205 ++++++++++++ .../references/verify-existing-fix.md | 93 ++++++ .../benny/skills/setup-benny/SKILL.md | 266 +++++++++++++++ .../skills/triage-issue-reports/SKILL.md | 240 ++++++++++++++ .../references/routing.example.md | 61 ++++ .../templates/configuration.example.yaml | 84 +++++ .../templates/reproduce-automation-prompt.md | 33 ++ .../templates/triage-automation-prompt.md | 39 +++ 14 files changed, 1619 insertions(+), 1 deletion(-) create mode 100644 pstack/automations/benny/FOR_AGENTS.md create mode 100644 pstack/automations/benny/README.md create mode 100644 pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md create mode 100644 pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md create mode 100644 pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md create mode 100644 pstack/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md create mode 100644 pstack/automations/benny/skills/setup-benny/SKILL.md create mode 100644 pstack/automations/benny/skills/triage-issue-reports/SKILL.md create mode 100644 pstack/automations/benny/skills/triage-issue-reports/references/routing.example.md create mode 100644 pstack/automations/benny/templates/configuration.example.yaml create mode 100644 pstack/automations/benny/templates/reproduce-automation-prompt.md create mode 100644 pstack/automations/benny/templates/triage-automation-prompt.md diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index f1e61ce0..7f525c02 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.9.2", + "version": "0.10.0", "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" diff --git a/pstack/README.md b/pstack/README.md index 19ebb58b..2889492f 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -26,6 +26,12 @@ type `/automate-me`. it mines your recent transcripts, drafts a `-mod models are configurable too. type `/setup-pstack`. 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. +## 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. + ## usage use `/poteto-mode` 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. diff --git a/pstack/automations/benny/FOR_AGENTS.md b/pstack/automations/benny/FOR_AGENTS.md new file mode 100644 index 00000000..e732156e --- /dev/null +++ b/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/pstack/automations/benny/README.md b/pstack/automations/benny/README.md new file mode 100644 index 00000000..76804c8c --- /dev/null +++ b/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/pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md b/pstack/automations/benny/skills/reproduce-and-fix-issues/SKILL.md new file mode 100644 index 00000000..effa5f0a --- /dev/null +++ b/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/pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md b/pstack/automations/benny/skills/reproduce-and-fix-issues/references/control-adapter.md new file mode 100644 index 00000000..3399491e --- /dev/null +++ b/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/pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md b/pstack/automations/benny/skills/reproduce-and-fix-issues/references/feature-map.example.md new file mode 100644 index 00000000..620ddedb --- /dev/null +++ b/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: ` -> -> ` +- Keyboard shortcut: `` + +#### How the control adapter drives it + +- `` with `` should ``. +- Reset: ``. + +#### Stable selectors + +- `` +- `` +- `` + +Never use generated CSS or StyleX classes, dynamic hashes, child indexes, or brittle DOM position. + +#### States to exercise + +- Default, hover, focus-visible, active, disabled +- Loading, empty, error +- Selected, open, expanded +- `` + +Mark states that do not apply. + +#### Preconditions and setup + +- Auth: `` +- Data: `` +- Permissions: `` +- Flags: `` +- Services: `` + +#### Evidence and cross-check + +- Screenshot: `` +- Video: `` +- Cross-check: `` + +#### Gotchas + +- `` +- `` + +## Fictional example + +These features belong to a fictional task app. They are examples, not required Benny features. + +### Sign in + +Lets a user enter the task app. + +#### How a user gets there + +- Open the app and choose `Sign in`. No shortcut. + +#### How the control adapter drives it + +- `open_app`, `click Sign in`, `fill credentials`, and `click Continue` should open the item list. +- Reset by signing out and clearing the disposable session. + +#### Stable selectors + +- Button `Sign in`, textboxes `Email` and `Password`, `data-component="sign-in-form"` + +#### States to exercise + +- Default, focus-visible, submitting, disabled, loading, error + +#### Preconditions and setup + +- Disposable account and available authentication service + +#### Evidence and cross-check + +- Record landing page through item list. Check read-only session state. + +#### Gotchas + +- A marketing page is the wrong surface. A missing auth service is a block. + +### Item list and detail + +Lets a user browse items and open one. + +#### How a user gets there + +- Open the `Items` tab, then choose a row. + +#### How the control adapter drives it + +- `select_tab Items` and `click ` should open its detail. +- Reset by closing the detail and clearing selection. + +#### Stable selectors + +- Tab and list named `Items`, fixture-named row, `data-component="item-detail"` + +#### States to exercise + +- Loading, empty, error, selected, open, expanded + +#### Preconditions and setup + +- Named fixture items, read permission, available item service + +#### Evidence and cross-check + +- Show selection and matching detail title. Check selected-item ID. + +#### Gotchas + +- Search results may look similar but use a different path. + +### Item editor + +Lets a user create or edit an item. + +#### How a user gets there + +- Choose `Edit` from detail or `New item` from the list. + +#### How the control adapter drives it + +- `click Edit`, `fill `, and `click Save` should update detail. +- Reset by restoring the fixture. + +#### Stable selectors + +- Buttons `Edit`, `New item`, `Save`, form `Item editor`, label-linked fields + +#### States to exercise + +- Default, focus-visible, dirty, validating, disabled, saving, error, success + +#### Preconditions and setup + +- Editable fixture, write permission, available save service + +#### Evidence and cross-check + +- Show field change through updated detail. Check the stored item value read-only. + +#### Gotchas + +- Do not inject form state. A read-only detail field is not the editor. + +### Settings + +Lets a user change personal preferences. + +#### How a user gets there + +- Open the profile menu, then choose `Settings`. + +#### How the control adapter drives it + +- `open_menu Profile`, `click Settings`, and `toggle ` should update the control. +- Reset by restoring the starting preference. + +#### Stable selectors + +- Button `Profile`, menu item `Settings`, region `Settings`, purpose-named preference attribute + +#### States to exercise + +- Closed, open, selected, focus-visible, disabled, loading, error + +#### Preconditions and setup + +- Signed-in test account, known preferences, available preference service + +#### Evidence and cross-check + +- Show the menu path and final control state. Check the preference value read-only. + +#### Gotchas + +- Operating-system settings are a different surface. + +## Completeness checklist + +- Every reproducible user-facing feature has a section. +- Every section names a user path, adapter actions, and reset. +- Selectors use roles, names, ARIA, stable component markers, or purpose-named attributes. +- No selector uses generated classes or DOM position. +- Relevant interaction, loading, empty, error, selected, and expanded states are covered. +- Auth, fixtures, permissions, flags, and services are explicit. +- Screenshot, video, and underlying cross-check requirements are explicit. +- Wrong surfaces, dead ends, and safe environment translations are listed. +- Implementation details remain runtime discoveries. diff --git a/pstack/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md b/pstack/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md new file mode 100644 index 00000000..e3cda3c0 --- /dev/null +++ b/pstack/automations/benny/skills/reproduce-and-fix-issues/references/verify-existing-fix.md @@ -0,0 +1,93 @@ +# Verify an existing fix + +Use this mode when an open pull request or merged commit plausibly fixes the report. + +The existing artifact owns the fix. Verify it. Do not edit it, author a competing patch, or open another pull request. + +## Qualify the artifact + +Require one concrete artifact: + +- An open pull request with code changes that address the symptom +- A merged pull request +- A merged commit with matching code and intent + +A thread claim, tracker status, branch name, or cause hypothesis without a pull request or commit is not enough. + +When several artifacts exist, choose the one linked from the source thread or tracker. Otherwise choose the closest match to the affected code and state why. + +## Protect the working tree + +Use an isolated worktree or another clean checkout when the repository supports it. Do not overwrite user changes. + +Record: + +- Baseline revision +- Patched revision +- Pull request or commit URL +- Build and environment inputs shared by both runs + +Use regular `github.com` pull request links. + +## Measure the baseline + +For an open pull request, use its base branch as the baseline. + +For a merged fix, use the revision immediately before the fix when that revision builds and represents the old behavior. + +Through the configured control adapter: + +1. Bring up the baseline app. +2. Confirm the correct app and environment. +3. Run the reported path through real UI actions. +4. Observe the discriminating symptom. +5. Reset and repeat it. +6. Capture baseline recording, screenshot, and state check. + +If the symptom does not appear twice on the baseline, there is no baseline. Do not claim that the fix works. + +## Measure the patched build + +Build and run the pull request or fix commit with the same environment and data. + +1. Run the same UI path. +2. Repeat it twice. +3. Confirm that the broken state is gone. +4. Confirm the expected state appears. +5. Capture after recording, screenshot, and the same state check. + +Do not stop at compilation or tests. The after result must come from a running patched app. + +## Outcomes + +### Confirmed + +The baseline reproduces twice and the patched build resolves it twice. + +- Mark operations status as verified. +- Link the artifact. +- Post one concise source-thread reply after the source preflight. +- Include the before and after result. +- Open no pull request. + +### Insufficient fix + +The symptom appears on both baseline and patched builds. + +- Mark operations status as reproduced but not fixed. +- Link the artifact and say it did not resolve the symptom. +- Post the normal confirmed-repro source update if the run has not already used it. +- Open no competing pull request. + +### Inconclusive + +The baseline does not reproduce, the patched app cannot run, or the evidence does not show the discriminating state. + +- Do not claim success. +- State which half could not be measured. +- Keep the result in the operations thread or run output. +- Post nothing in the source thread unless a direct question requires an answer. + +## Cleanup + +Stop both builds, remove temporary profiles and captures according to retention policy, and return the repository to its prior state without discarding user work. diff --git a/pstack/automations/benny/skills/setup-benny/SKILL.md b/pstack/automations/benny/skills/setup-benny/SKILL.md new file mode 100644 index 00000000..b05c26f4 --- /dev/null +++ b/pstack/automations/benny/skills/setup-benny/SKILL.md @@ -0,0 +1,266 @@ +--- +name: setup-benny +description: Configure Benny and prepare its triage and repro automations. Use when installing Benny or changing its Slack, tracker, repository, routing, control, model, or budget settings. +disable-model-invocation: true +--- + +# Set up Benny + +Benny ships as a dormant automation pack inside pstack. The plugin manifest exposes only pstack's normal skill root; this file and the two operational files are not slash skills. + +The human enters setup by pointing Cursor at the pack's `FOR_AGENTS.md`. The bootstrap flow copies the whole pack into the target repository, then reads this file directly at `.cursor/automations/benny/skills/setup-benny/SKILL.md`. + +Benny needs external configuration and two live Cursor automations. + +Do not create or update an automation until the user explicitly asks. Never put a secret value in plugin files, prompts, or committed configuration. + +## 1. Copy the pack and enable shared pstack skills + +Do this before asking for Benny configuration and before invoking the built-in `/automate` skill. + +Ask which repository will run the automations. The source pack is the directory containing `FOR_AGENTS.md`. The destination is `/.cursor/automations/benny/`. + +Merge the entire source pack into the destination: + +1. Create the destination when it is absent. +2. Copy every source file to the same relative path. +3. Preserve destination-only files. Never delete unrelated files during install or refresh. +4. Keep user-owned configuration, feature maps, and routing maps outside the destination. Never overwrite them. +5. When an existing source-managed file differs, inspect the diff and merge without discarding local edits. If ownership is ambiguous, stop and ask before replacing it. +6. Verify that the destination contains `FOR_AGENTS.md`, this setup file, both operational files, their references, and the templates. + +If this file is already being read from the target destination, treat the copy as complete and run the same verification before continuing. + +Add pstack to the target repository's `.cursor/settings.json`. If the file or `.cursor` directory does not exist, create it. + +Merge this entry into the existing JSON or JSONC: + +```json +{ + "plugins": { + "pstack": { "enabled": true } + } +} +``` + +Preserve every unrelated top-level setting and every other plugin entry. If `plugins.pstack` already exists, change only its `enabled` value. Preserve comments and valid JSONC syntax when the file uses JSONC. Validate the file after editing it. + +Reload the target project or start a fresh agent rooted there. Verify that these shared pstack skills resolve from project scope: + +- `how` +- `why` +- `tdd` +- `unslop` +- `principle-separate-before-serializing-shared-state` +- `principle-minimize-reader-load` +- `principle-guard-the-context-window` +- `principle-sequence-verifiable-units` +- `principle-fix-root-causes` +- `principle-prove-it-works` + +Do not count a skill loaded from the current session or a user-scoped plugin. The check must show that a fresh agent in the target repository receives pstack through project settings. + +If project-scoped plugin installation is unavailable or any shared dependency does not resolve, stop and explain the failure. + +The Benny files are read directly from `.cursor/automations/benny/`. Do not add that directory to a plugin manifest or expect its `SKILL.md` files to appear in the slash-skill list. + +Tell the user that `.cursor/settings.json`, `.cursor/automations/benny/`, and any referenced secret-free configuration must be committed before either automation is enabled. Do not commit them unless the user asks. + +Once this check passes, live automation prompts may read the committed operational files by their stable repository-relative paths. They must not embed a plugin cache path or copy the file contents. + +## 2. Adapt the configuration + +Open these copied examples: + +- `../../templates/configuration.example.yaml` +- `../reproduce-and-fix-issues/references/feature-map.example.md` + +Create user-owned copies outside `.cursor/automations/benny/`. These are configuration files, not pack files. Example locations: + +- Project config, such as `.cursor/benny/configuration.yaml` +- Project feature map, such as `.cursor/benny/feature-map.md` +- Project routing map, such as `.cursor/benny/routing.md` +- User config, such as `~/.config/benny/configuration.yaml` +- User feature map, such as `~/.config/benny/feature-map.md` + +Fill one feature-map section for every user-facing feature the automation may reproduce. Keep it at the user point of view. Do not freeze implementation details or current code paths in the map. + +Do not edit the copied examples. Pack refreshes may update source-managed files after conflict review, but they must never touch the user-owned copies. + +Prefer committed, secret-free files in the target repository when a fresh automation checkout must read them. Otherwise paraphrase the required values into the live prompt. Reference a repository file only after the built-in `/automate` skill confirms that the file is committed in the repository where the automation runs. + +Use stable repository-relative paths for committed pack and configuration files. Never reference the plugin source directory or a plugin cache path from a live automation. + +## 3. Fill the required choices + +Ask for or confirm: + +- Source Slack channel ID +- Optional operations or status channel ID +- Repository URL and default branch +- Triage identity or Slack user ID +- Issue tracker type, team, project, labels, and intake status +- Tracker adapter skill or MCP actions +- Optional routing map path +- Required control skill name +- Required user-facing feature-map path +- Status emoji strings +- Pull request URL format +- Polling and effort budgets +- Model slug for triage, repro, code work, and media review + +Use only model slugs shown as available in the user's Cursor model picker or supported model list. Do not guess a slug and do not carry over a private default. + +The source channel, triage identity, repository, tracker adapter, control skill, and feature map must be explicit. Fail setup if any required value stays ambiguous. + +Use pstack's `unslop` skill on the final automation names, descriptions, and prompt shims before saving them. + +## 4. Check integration capabilities + +The triage automation needs: + +- Read access to the configured source Slack channel and its threads +- Thread-reply access in that channel +- Attachment metadata and file download access when reports include media +- Search, read, create, and update access through the configured issue-tracker adapter + +The repro automation needs: + +- Read access to the source thread +- Thread-reply access in the source channel +- Optional post and edit access in the configured operations channel +- Repository read and history access +- A pull request action that can open a draft pull request +- The configured control-adapter skill + +Prefer configured Cursor Slack actions for reads and posts. The optional `BENNY_SLACK_BOT_TOKEN` may fill a narrow gap such as editing one operations status message or downloading an attachment. Store the value in a secret manager or environment, not in YAML. + +Do not use undocumented integration endpoints. + +## 5. Prepare the routing map + +If the user wants reroutes or owner pings: + +1. Copy `../triage-issue-reports/references/routing.example.md` outside `.cursor/automations/benny/`. +2. Replace every placeholder with public or organization-local values. +3. Keep owner pings off by default. +4. Allow a ping only for a configured feature owner or a confirmed likely regression author. + +If no routing map is configured, triage may classify a report but must not guess a destination or owner. + +## 6. Verify the control adapter + +Read `../reproduce-and-fix-issues/references/control-adapter.md` and the user's completed feature map. + +Confirm that the named skill can: + +- Bring up the target app +- Navigate every mapped feature through the real UI +- Exercise mapped states through declared adapter actions +- Inspect state without forcing the result +- Capture screenshots +- Start and stop a recording +- Clean up its processes and temporary data + +If any capability is missing, leave the repro automation disabled. It must fail closed rather than claim a reproduction it did not perform. + +## 7. Prepare the live automations + +Ask whether this is first-time creation or configuration of existing automations. + +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. + +### First-time creation + +Create one automation at a time. + +For each automation: + +1. Read the matching copied prompt template as secondary internal source material. +2. Turn `FOR_AGENTS.md`, the finished Benny configuration, and the template intent into a complete natural-language request. +3. Tell the live prompt to read and follow its exact committed operational file under `.cursor/automations/benny/`. +4. Use the stable repository-relative path, not a plugin source or cache path. Do not copy the operational file contents into the live prompt. +5. Read and follow the built-in `automate` skill. +6. Let `automate` discover Slack channels, the repository, and connected integrations. +7. Let `automate` confirm that the copied pack and any referenced configuration files are committed in the same repository where the automation will run. +8. Let `automate` show its draft table, obtain approval, ask readiness, and open the Automations editor. +9. Finish the editor handoff for this automation before starting the next one. + +Give `automate` this complete triage intent, filled from configuration: + +- Name `benny-triage`. +- Read and follow `.cursor/automations/benny/skills/triage-issue-reports/SKILL.md` for every run. +- Trigger on each new top-level report in the configured source Slack channel. +- Read the triggering thread and reply only inside it. +- Use the configured issue-tracker integration. +- Classify, inspect evidence, trace cause, dedupe, and create only clear new bugs. +- End one thread-only verdict with the configured `[benny:bug]`, `[benny:performance]`, or `[benny:other]` marker and optional tracker URL. +- Never post a source-channel root message. + +After the triage editor handoff is complete, give `automate` this complete repro and fix intent: + +- Name `benny-reproduce`. +- Read and follow `.cursor/automations/benny/skills/reproduce-and-fix-issues/SKILL.md` for every run. +- Trigger on the same new top-level reports in the configured source Slack channel. +- Use the configured repository and default branch. +- Read the source thread and reply only inside it. +- Include pull request creation and the configured tracker, control-adapter, and feature-map requirements. Paraphrase mapped user paths and states unless `automate` confirms an eligible committed file in the same repository. +- Wait for a trusted triage marker before acting. +- Reproduce the exact symptom twice through the mapped real UI and capture evidence. +- Verify an existing fix without authoring over it. +- Attempt an optional bounded fix only after confirmed repro, then open a draft pull request when proof and checks pass. +- Never post a source-channel root message. + +Do not duplicate `automate`'s Slack, repository, integration, completeness, authentication, draft-review, approval, readiness, or editor-handoff work. + +### Existing automations + +The built-in `automate` skill is creation-only. Do not use it to search for, inspect, or update existing automations. + +Finish configuration, routing, control-adapter, and feature-map validation. Then give the user this concise editor checklist. + +For the existing triage automation, update: + +- Name and description +- Direct instruction to read `.cursor/automations/benny/skills/triage-issue-reports/SKILL.md` +- New top-level Slack report trigger and source channel +- Slack thread read and reply capabilities +- Issue-tracker integration +- Paraphrased triage instructions, thread-only rule, and Benny verdict markers + +For the existing repro automation, update: + +- Name and description +- Direct instruction to read `.cursor/automations/benny/skills/reproduce-and-fix-issues/SKILL.md` +- Matching Slack trigger and source channel +- Repository and default branch +- Slack thread read and reply capabilities +- Pull request action +- Tracker, control-adapter, and feature-map requirements +- Paraphrased marker wait, evidence, verification, and bounded-fix instructions + +Ask the user to update each existing automation directly in its Automations editor. Do not create replacements or duplicates. + +### Creation boundary + +Never call a direct automation backend service or backend automation tool. Never use a browser URL that carries draft fields. Never build or open a Cursor protocol deep link. For new automations, the only finish path is the built-in `automate` skill's reviewed Automations editor handoff. + +Do not enable either automation until the thread-safety test passes after the editor save. + +## 8. Test thread safety + +Use a test channel or a harmless test report. + +Before testing, confirm that the target repository's `.cursor/settings.json`, `.cursor/automations/benny/`, and every referenced secret-free configuration file are committed on the branch used by the automation checkout. Confirm that both live prompts point at their exact committed operational files. If any check fails, stop. Tell the user that the automation cannot be enabled yet. + +Verify: + +1. Triage stores the root `thread_ts` and posts exactly one verdict as a reply. +2. The verdict contains one configured marker. +3. Repro accepts the marker only from the configured triage identity. +4. Repro keeps the same immutable source coordinates. +5. No source-channel root message appears. +6. A delegated worker cannot use any Slack write action. +7. Missing coordinates, a deleted parent, or a failed preflight produces no post and no tracker issue. + +Enable normal traffic only after all seven checks pass. diff --git a/pstack/automations/benny/skills/triage-issue-reports/SKILL.md b/pstack/automations/benny/skills/triage-issue-reports/SKILL.md new file mode 100644 index 00000000..d691672d --- /dev/null +++ b/pstack/automations/benny/skills/triage-issue-reports/SKILL.md @@ -0,0 +1,240 @@ +--- +name: triage-issue-reports +description: Triage Slack issue reports with one thread-only verdict, evidence review, cause-aware routing, tracker dedupe, and fail-closed ticket creation. Use only from the configured Benny triage automation. +disable-model-invocation: true +--- + +# Triage issue reports + +Classify one Slack report and post one useful verdict in its source thread. Create a tracker issue only for a clear, new bug. Do not reproduce or fix it here. + +Load the external Benny configuration supplied by the automation. If the config is missing, malformed, or incomplete, stop without posting or writing to the tracker. + +## Hard safety rules + +- The source channel and root thread coordinates are immutable. +- Never post a root message in the source channel. +- Never post to another channel, broadcast a reply, send a DM, or start a replacement thread. +- Preflight the source parent before any tracker write and immediately before the verdict post. +- If the parent is missing, deleted, inaccessible, or uncertain, stop with no writes. +- Post one substantive verdict. Do not narrate progress. +- The coordinator is the only Slack poster. +- Delegated workers return findings only. They must be read-only and receive no Slack credentials or write actions. +- Every child prompt must forbid `SendSlackMessage`, `PostToSlack`, `chat.postMessage`, and every other Slack write. +- If worker isolation cannot enforce those limits, do the work in the coordinator. +- Never create an issue that cannot link back to the source thread. +- Prefer no ticket over a guessed or duplicate ticket. +- Apply pstack's `principle-separate-before-serializing-shared-state` to source coordinates. +- Apply pstack's `principle-minimize-reader-load` and `unslop` skills to the final verdict. + +## 1. Freeze source coordinates + +Before making a work list or delegating: + +1. Read `source_channel_id` from the trigger. +2. Require it to equal the configured source channel. +3. Set `SOURCE_THREAD_TS` to `trigger.thread_ts` when present. Otherwise use `trigger.ts`. +4. Require a nonempty `SOURCE_THREAD_TS`. +5. Store `SOURCE_CHANNEL_ID` and `SOURCE_THREAD_TS` as immutable values. +6. Read the thread and verify that its root has exactly those coordinates. +7. Fetch a stable source permalink. + +Every later source read and post must use those stored values. Never replace them with a reply timestamp or an operations-thread timestamp. + +## 2. Read the whole report + +Read the root and current replies before deciding. + +Capture: + +- Reporter wording +- Product version, app build, environment, and platform when present +- Expected behavior +- Observed behavior +- Frequency and trigger +- Error text or stack signature +- Existing issue, commit, or pull request links +- Any explicit statement that someone is already fixing it + +Inspect every relevant attachment. + +- Read screenshots at full useful resolution. +- Review video for the state transition that separates correct and broken behavior. +- Read logs, traces, and crash text for concrete signatures. +- If media needs specialist review, use a read-only media worker and ask a narrow question. The worker returns findings only. +- If an attachment cannot be read, say so in the verdict. Do not invent what it shows. + +Use evidence already in the thread before asking the reporter for more. + +## 3. Trace cause before routing + +Do a bounded source and history pass before choosing an owner or destination. Use pstack's `how` skill to trace the path from the reported action to the observed result. Use `why` when the report looks like a regression or touches defensive code. + +1. Identify the likely code path from the reported action to the observed result. +2. Check whether the visible symptom belongs to that code path or a dependency below it. +3. Check recent changes when the report looks like a regression. +4. Check whether a merged commit or open pull request already addresses the same symptom. +5. Separate confirmed facts from hypotheses. + +This pass does not need a complete root cause. It must be strong enough to avoid routing a visible symptom to the wrong owner. + +If the repository cannot be read, do not guess a code owner. Continue with a conservative classification and say that cause tracing was unavailable. + +## 4. Classify + +Choose one category. + +### Bug + +Something violates intended behavior. Examples include wrong output, broken state, an error, a crash, a hang, a silent no-op, or a regression. + +### Performance + +The report describes measurable slowness, excess memory, battery drain, jank, or another resource problem. Treat it as a bug, but preserve measurements and profiles. + +### Feature request + +The current behavior appears intentional and the reporter wants a different behavior or affordance. + +### Question or feedback + +The report asks how something works, expresses a preference without a concrete defect, or gives general feedback. + +### Reroute + +Cause tracing shows that another configured destination owns the issue. + +When the bug versus feature line is unclear, do not file. The one verdict may ask one focused question and use the `other` marker. + +## 5. Apply configured routing + +Read the optional routing map from `routing.map_path`. + +- Match on confirmed product area, code path, or error signature. +- A visible symptom alone is not enough when cause tracing points elsewhere. +- If no route matches, say the owner is unclear. Do not guess. +- Do not cross-post. Tell the reporter where to take the issue in the source thread. + +Owner pings are off by default. A ping is allowed only when all of these hold: + +1. The routing map explicitly names the owner. +2. The config allows that ping type. +3. The item is a feature request that needs owner input, or recent history identifies a likely regression author with strong evidence. +4. The owner is not a broad on-call group. + +No other case gets a ping. + +## 6. Use the issue-tracker adapter + +The tracker is an adapter, not a required vendor. A Linear adapter is one valid example. A GitHub Issues adapter or another tracker may implement the same contract. + +The configured adapter must provide: + +- Search issues by text, state, label, source URL, and date range +- Read one issue and its links +- Create an issue with title, body, status, labels, and source URL +- Update an existing issue without replacing unrelated fields +- Add a source link and recurrence note +- Cancel, close, or delete an issue created by this run if the Slack handoff fails + +If a required operation is unavailable, fail closed for that write. + +Resolve configured team, project, status, and labels at runtime. Do not invent IDs, create labels, assign owners, or set priority unless the config explicitly requires it. + +## 7. Dedupe + +Always check whether this source permalink is already linked to a tracker issue or a prior triage reply. If so, do not post or create a duplicate. + +For bugs and performance reports, search the tracker using: + +- Exact error or crash signature +- Product area +- Trigger +- Symptom +- Version or date window +- Suspected regression commit +- Source permalink + +Choose one outcome: + +- Confident duplicate: same signature, or the same area, trigger, and symptom, or a confirmed shared cause. +- Possibly related: a shared cause is plausible but not proven. +- Weak resemblance: similarity is superficial. +- No match. + +For a confident duplicate, update the existing issue with the source permalink and one short recurrence note. Do not reopen, relabel, or reassign it unless the config says to. + +For a possible match, link it in the verdict as uncertain and create nothing. + +A long-closed issue is a regression lead, not automatically a live duplicate. + +## 8. Decide whether to create + +Create only when all of these are true: + +1. The classification is bug or performance. +2. The behavior is clearly broken. +3. The issue is still live or not known to be fixed. +4. Dedupe found no confident or plausible live match. +5. The source parent and permalink passed preflight. +6. The tracker target fields resolved. +7. The adapter can compensate if the verdict post fails. + +Never create for a feature request, question, feedback item, reroute, possible duplicate, confident duplicate, or already-fixed issue. + +The new issue must be self-contained: + +- Plain title that names the area and symptom +- Reporter quote +- Expected and observed behavior +- Version and environment, or `unknown` +- Trigger and frequency +- Source thread permalink +- Short cause-tracing findings with hypotheses labeled as hypotheses +- Inline screenshot or representative video frame when supported +- Links to remaining artifacts +- Configured intake status and labels + +Do not put a guessed root cause in the title. + +## 9. Post one verdict + +Run a fresh source-parent preflight. Then post exactly one reply with `channel=SOURCE_CHANNEL_ID` and `thread_ts=SOURCE_THREAD_TS`. + +Never call a source-channel posting action without a nonempty `thread_ts`. + +Keep the reply short: + +- Lead with the outcome. +- Link the existing or new tracker issue when there is one. +- Mention a reroute or one missing fact when needed. +- Include at most one allowed owner ping. +- End with exactly one marker line. + +Marker contract: + +```text +[benny:bug] +[benny:bug] tracker=https://tracker.example/issue/123 +[benny:performance] +[benny:performance] tracker=https://tracker.example/issue/123 +[benny:other] +``` + +Use only the configured marker strings. The repro automation trusts the marker only when it comes from the configured triage identity in this source thread. + +After posting, read the same source thread and verify the verdict appears under `SOURCE_THREAD_TS`. If it does not, never retry at the root. + +If this run created a tracker issue and the verdict did not land, use the adapter's compensation action. Verify that the issue is canceled, closed, or deleted. If compensation cannot be verified, report the failure only in the automation run output. + +## 10. Watch one follow-up window + +Watch the source thread for the configured follow-up window, then stop. + +- Answer only a direct question to the triage identity. +- Apply a concrete correction to the tracker issue when safe. +- Do not emit a second marker in the same run. +- Stay out of human coordination and side chatter. +- Stop early if someone asks the automation to stop. + +Do not extend the window more than once. A new report should start a new run. diff --git a/pstack/automations/benny/skills/triage-issue-reports/references/routing.example.md b/pstack/automations/benny/skills/triage-issue-reports/references/routing.example.md new file mode 100644 index 00000000..d71aea76 --- /dev/null +++ b/pstack/automations/benny/skills/triage-issue-reports/references/routing.example.md @@ -0,0 +1,61 @@ +# Routing map example + +Copy this file outside `.cursor/automations/benny/`, for example to `.cursor/benny/routing.md`, and replace every placeholder. Point `routing.map_path` at the copy. Pack refreshes must not overwrite it. + +The triage skill treats this as data. A route needs evidence from the report or cause trace. A keyword match alone is not enough. + +```yaml +routes: + - name: "billing-example" + match: + product_areas: + - "billing-area-placeholder" + code_paths: + - "billing-code-path-placeholder" + error_signatures: + - "billing-error-placeholder" + destination: + slack_channel: "billing-channel-placeholder" + tracker_team: "billing-team-placeholder" + owners: + - "billing-owner-placeholder" + allow_feature_owner_ping: false + + - name: "desktop-example" + match: + product_areas: + - "desktop-area-placeholder" + code_paths: + - "desktop-code-path-placeholder" + error_signatures: + - "desktop-error-placeholder" + destination: + slack_channel: "desktop-channel-placeholder" + tracker_team: "desktop-team-placeholder" + owners: + - "desktop-owner-placeholder" + allow_feature_owner_ping: false + +fallback: + destination: "" + owners: [] + allow_feature_owner_ping: false + +ping_policy: + default: "off" + allow: + - "configured-feature-owner" + - "confirmed-regression-author" + deny: + - "broad-on-call-group" + - "unverified-owner" +``` + +## Rules + +- Leave `fallback.destination` empty unless one team accepts all unmatched reports. +- Use stable product areas, code paths, and error signatures. +- Do not include private data in a public copy. +- Do not paste raw user or channel IDs into an example that will be published. +- Keep feature-owner pings off until the target team agrees to them. +- A reroute tells the reporter where to go. The automation never cross-posts. diff --git a/pstack/automations/benny/templates/configuration.example.yaml b/pstack/automations/benny/templates/configuration.example.yaml new file mode 100644 index 00000000..8616f5fc --- /dev/null +++ b/pstack/automations/benny/templates/configuration.example.yaml @@ -0,0 +1,84 @@ +schema_version: 1 + +automations: + triage_name: "benny-triage" + reproduce_name: "benny-reproduce" + +slack: + source_channel_id: "SOURCE_CHANNEL_ID" + operations_channel_id: "" + triage_identity_user_id: "TRIAGE_IDENTITY_USER_ID" + read_action: "configured-slack-read-action" + thread_post_action: "configured-slack-thread-post-action" + file_download_action: "configured-slack-file-download-action" + operations_edit_action: "configured-slack-edit-action" + prefer_cursor_actions: true + optional_bot_token_env: "BENNY_SLACK_BOT_TOKEN" + allow_source_root_posts: false + allow_worker_slack_writes: false + +repository: + url: "https://github.com/example-org/example-repo" + default_branch: "main" + pull_request_action: "configured-draft-pull-request-action" + pull_request_url_format: "https://github.com/{owner}/{repo}/pull/{number}" + draft_only: true + +tracker: + type: "linear" + adapter_skill_name: "issue-tracker-adapter-placeholder" + team: "team-placeholder" + project: "project-placeholder" + labels: + bug: "bug-label-placeholder" + performance: "performance-label-placeholder" + intake: "intake-label-placeholder" + needs_repro: "needs-repro-label-placeholder" + status: "intake-status-placeholder" + source_link_title: "Slack report" + require_compensation_action: true + +routing: + map_path: ".cursor/benny/routing.md" + owner_pings_default: false + allow_feature_owner_ping: false + allow_confirmed_regression_author_ping: false + +control: + skill_name: "control-target-app" + feature_map_path: ".cursor/benny/feature-map.md" + environment: "safe-test-environment-placeholder" + artifact_directory: "/tmp/benny-artifacts" + artifact_retention_hours: 24 + +verdict_markers: + bug: "[benny:bug]" + performance: "[benny:performance]" + other: "[benny:other]" + tracker_attribute: "tracker" + +status_emoji: + seen: "👀" + reproducing: "🔎" + reproduced: "✅" + could_not_reproduce: "⚪" + blocked: "⛔" + fixing: "🛠️" + fix_failed: "❌" + pull_request_opened: "🔗" + +budgets: + poll_seconds: 45 + verdict_wait_minutes: 45 + triage_follow_up_minutes: 10 + triage_total_minutes: 30 + repro_minutes: 60 + rejection_window_minutes: 10 + fix_minutes: 90 + operations_follow_up_minutes: 45 + +models: + triage: "choose-an-available-public-model-slug" + reproduce: "choose-an-available-public-model-slug" + code: "choose-an-available-public-model-slug" + media_review: "choose-an-available-public-model-slug" diff --git a/pstack/automations/benny/templates/reproduce-automation-prompt.md b/pstack/automations/benny/templates/reproduce-automation-prompt.md new file mode 100644 index 00000000..5c66c922 --- /dev/null +++ b/pstack/automations/benny/templates/reproduce-automation-prompt.md @@ -0,0 +1,33 @@ +# Reproduce automation prompt + +> Source material for the copied setup workflow. Paraphrase this intent into a built-in `automate` draft after `automate` confirms that the copied pack is committed in the repository where the automation will run. + +Read and follow `.cursor/automations/benny/skills/reproduce-and-fix-issues/SKILL.md` for this run. + +Configuration source. Include this repository-relative path only when it is committed in the same target repository. Otherwise paraphrase the configured values. Never use a plugin source or cache path: + +```text +{{BENNY_CONFIG_PATH}} +``` + +Trigger: + +```json +{ + "source_channel_id": "{{SLACK_CHANNEL_ID}}", + "message_ts": "{{SLACK_MESSAGE_TS}}", + "thread_ts": "{{SLACK_THREAD_TS_OR_EMPTY}}" +} +``` + +The creation intent should describe this as a new top-level report in the configured source Slack channel. It should include the configured repository, default branch, issue tracker, control adapter, feature map, and draft pull request capability. + +Treat the source channel and root thread timestamp as immutable. If either is missing or does not match configuration, stop without posting. + +Wait for a configured triage marker from the configured triage identity in this exact thread. Proceed only for `[benny:bug]` or `[benny:performance]`. + +Require the configured control-adapter skill before attempting a repro. Reproduce the exact discriminating symptom twice through the real UI. Verify existing pull requests or commits without authoring over them. Attempt a bounded fix only after a confirmed repro and the operational file's fix gate. + +The coordinator is the only Slack poster. Every child prompt must forbid `SendSlackMessage`, `PostToSlack`, `chat.postMessage`, and all other Slack writes. Children return findings only. + +Never post a root message in the source channel. diff --git a/pstack/automations/benny/templates/triage-automation-prompt.md b/pstack/automations/benny/templates/triage-automation-prompt.md new file mode 100644 index 00000000..939e5e15 --- /dev/null +++ b/pstack/automations/benny/templates/triage-automation-prompt.md @@ -0,0 +1,39 @@ +# Triage automation prompt + +> Source material for the copied setup workflow. Paraphrase this intent into a built-in `automate` draft after `automate` confirms that the copied pack is committed in the repository where the automation will run. + +Read and follow `.cursor/automations/benny/skills/triage-issue-reports/SKILL.md` for this run. + +Configuration source. Include this repository-relative path only when it is committed in the same target repository. Otherwise paraphrase the configured values. Never use a plugin source or cache path: + +```text +{{BENNY_CONFIG_PATH}} +``` + +Trigger: + +```json +{ + "source_channel_id": "{{SLACK_CHANNEL_ID}}", + "message_ts": "{{SLACK_MESSAGE_TS}}", + "thread_ts": "{{SLACK_THREAD_TS_OR_EMPTY}}" +} +``` + +The creation intent should describe this as a new top-level report in the configured source Slack channel. + +Treat the source channel and root thread timestamp as immutable. If either is missing or does not match configuration, stop without posting or writing to the issue tracker. + +The committed operational file owns classification, attachment review, cause tracing, routing, dedupe, tracker writes, and the final verdict. Post no progress messages. Never post a root message in the source channel. + +The coordinator is the only Slack poster. Any delegated worker must be read-only, return findings only, and receive an explicit ban on every Slack write action. + +End the single verdict with exactly one configured marker: + +```text +[benny:bug] +[benny:performance] +[benny:other] +``` + +A bug or performance marker may add `tracker=`. From dc2fae6625a268361243ca044eb5af141c124704 Mon Sep 17 00:00:00 2001 From: lauren Date: Wed, 8 Jul 2026 21:31:43 +0000 Subject: [PATCH 02/17] pstack: route composer slots to grok-4.5-fast-xhigh (#142) --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/skills/architect/SKILL.md | 2 +- pstack/skills/arena/SKILL.md | 2 +- pstack/skills/how/SKILL.md | 4 ++-- pstack/skills/interrogate/SKILL.md | 2 +- pstack/skills/poteto-mode/SKILL.md | 2 +- pstack/skills/poteto-mode/playbooks/feature.md | 2 +- .../skills/poteto-mode/playbooks/refactoring.md | 2 +- pstack/skills/poteto-mode/references/plan.md | 2 +- pstack/skills/reflect/SKILL.md | 2 +- pstack/skills/setup-pstack/SKILL.md | 16 ++++++++-------- pstack/skills/why/SKILL.md | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index 7f525c02..ebeef146 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.10.0", + "version": "0.10.1", "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" diff --git a/pstack/skills/architect/SKILL.md b/pstack/skills/architect/SKILL.md index bd239512..a24a16b2 100644 --- a/pstack/skills/architect/SKILL.md +++ b/pstack/skills/architect/SKILL.md @@ -30,7 +30,7 @@ Skip Phase A only when the work is genuinely greenfield with no surrounding syst Run the **arena** skill with the design-sketch task and the Phase A grounding artifacts. Pass `references/runner-prompt.md` as each runner's prompt. Each candidate produces a design package shaped per `references/rationale-template.md`: the caller's usage written first, then the type sketch, function signatures, module map, and prose rationale derived from it. -Use your configured architect runners (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `composer-2.5-fast`). +Use your configured architect runners (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `grok-4.5-fast-xhigh`). This is the **exhaust-the-design-space** principle skill made concrete. Whole-shape alternatives, not point fixes inside one shape. diff --git a/pstack/skills/arena/SKILL.md b/pstack/skills/arena/SKILL.md index 4e59d390..c0b8d298 100644 --- a/pstack/skills/arena/SKILL.md +++ b/pstack/skills/arena/SKILL.md @@ -25,7 +25,7 @@ The N candidates will receive the same prompt, so the prompt is the contract. Ge 1. State the artifact each candidate is producing. 2. Derive the rubric. State what success looks like for *this* task, then turn it into 3-6 concrete gradeable criteria. Concrete: `Adds a --dry-run flag that skips writes`. Vague: `code is correct`. The rubric is the picker's tool in Phase D; candidates only see the task. -3. Pick the runners. Default runners are your configured arena list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `composer-2.5-fast`). Spawn more when the arena covers multiple design directions. Same model N times when the work is generation-bound rather than judgment-sensitive. +3. Pick the runners. Default runners are your configured arena list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `grok-4.5-fast-xhigh`). Spawn more when the arena covers multiple design directions. Same model N times when the work is generation-bound rather than judgment-sensitive. 4. Assign output paths. Each candidate writes to its own location (a git worktree where possible, otherwise `/tmp/arena-/candidate-/`). N candidates writing to the same path is shared mutable state and fails the the **separate-before-serializing-shared-state** principle skill test. ## Phase B: Fan out diff --git a/pstack/skills/how/SKILL.md b/pstack/skills/how/SKILL.md index 7f897886..83a5b4c5 100644 --- a/pstack/skills/how/SKILL.md +++ b/pstack/skills/how/SKILL.md @@ -45,7 +45,7 @@ The right decomposition depends on the question. Use your judgment. Narrow quest Spawn all explorers in a single message: - `subagent_type`: `generalPurpose` -- `model`: your configured how-explorer model (default `composer-2.5-fast`) +- `model`: your configured how-explorer model (default `grok-4.5-fast-xhigh`) - `readonly`: `true` Each explorer gets the same base prompt from `references/explorer-prompt.md` plus a specific exploration angle naming its slice. Each explorer should: @@ -109,7 +109,7 @@ Run the full explain flow above (Steps 1-4). You must understand the architectur ### Step 2. Spawn Critics -After the explanation is complete, spawn one architectural critic per model in your configured how-critics list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `composer-2.5-fast`), all in a single message. +After the explanation is complete, spawn one architectural critic per model in your configured how-critics list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `grok-4.5-fast-xhigh`), all in a single message. For each critic: - `subagent_type`: `generalPurpose` diff --git a/pstack/skills/interrogate/SKILL.md b/pstack/skills/interrogate/SKILL.md index 071e43f0..401f19a4 100644 --- a/pstack/skills/interrogate/SKILL.md +++ b/pstack/skills/interrogate/SKILL.md @@ -33,7 +33,7 @@ Write one clear paragraph. Reviewers challenge whether the work achieves the int ## Step 3, Spawn Reviewers -Launch one reviewer per model in your configured interrogate list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `composer-2.5-fast`), all in a single message. +Launch one reviewer per model in your configured interrogate list (defaults `claude-opus-4-8-thinking-xhigh`, `gpt-5.5-high-fast`, `grok-4.5-fast-xhigh`), all in a single message. For each reviewer: - `subagent_type`: `generalPurpose` diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index 1681d106..b1a5cff3 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -79,7 +79,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Use `subagent_type: "poteto-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). `/poteto-mode` and `poteto-agent` route through the same wrapper. Routed workflow skills (`how`, `why`, `interrogate`, `reflect`) set their own `subagent_type` for diverse-model review; respect what the skill prescribes, don't override to `poteto-agent`. -**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `composer-2.5-fast` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). +**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). You own every subagent's work. Review the diff and write your own summary, don't pass through what it said. Interrupt-chained resumes silently drop directives, so fire a fresh subagent with consolidated scope rather than trusting a "done" summary. A second opinion is the same prompt against a different model. Agreement is high-signal. diff --git a/pstack/skills/poteto-mode/playbooks/feature.md b/pstack/skills/poteto-mode/playbooks/feature.md index d370d82e..0bff7943 100644 --- a/pstack/skills/poteto-mode/playbooks/feature.md +++ b/pstack/skills/poteto-mode/playbooks/feature.md @@ -9,7 +9,7 @@ - **Independent workstreams.** Disjoint files, services, or layers parallelize. Shared writes serialize. - **Shared mutable state.** Default to splitting the target (the **separate-before-serializing-shared-state** principle skill). Serialize only for real invariants. - **Smallest safe decomposition.** If one worker is best, name why. -4. Delegate code-writing to a subagent using your configured feature model (default `composer-2.5-fast`) with a specific scope (file paths, named data shape, success criteria); review its diff yourself. When the implementation admits multiple valid shapes (error handling, abstraction layer, test structure), delegate via the **arena** skill instead so the runners surface the alternatives and the cross-judge guards the pick. Mandatory: no skip-with-reason escape, and Laziness Protocol does not override it (the gain is review separation, not lines saved). You can spawn a subagent even though you are one; "the app is small" and "a subagent cannot spawn one" are both wrong. A subagent forbidden to spawn satisfies this by owning the diff directly with the same review separation; no "standing by" reply that waits on a nested agent. Comments per **Comments**. Surgical edits, re-ground against the source for upstream-derived files. Port shared-primitive improvements to all consumers and verify each. Commit liberally. +4. Delegate code-writing to a subagent using your configured feature model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, named data shape, success criteria); review its diff yourself. When the implementation admits multiple valid shapes (error handling, abstraction layer, test structure), delegate via the **arena** skill instead so the runners surface the alternatives and the cross-judge guards the pick. Mandatory: no skip-with-reason escape, and Laziness Protocol does not override it (the gain is review separation, not lines saved). You can spawn a subagent even though you are one; "the app is small" and "a subagent cannot spawn one" are both wrong. A subagent forbidden to spawn satisfies this by owning the diff directly with the same review separation; no "standing by" reply that waits on a nested agent. Comments per **Comments**. Surgical edits, re-ground against the source for upstream-derived files. Port shared-primitive improvements to all consumers and verify each. Commit liberally. 5. Verify on the matching surface. "Inconclusive" or wrong-surface is not a pass; flag it. 6. Rebase into small, ordered commits; stack follow-ups. Use the **sequence-verifiable-units** principle skill, building, verifying, and committing each small unit before the next. diff --git a/pstack/skills/poteto-mode/playbooks/refactoring.md b/pstack/skills/poteto-mode/playbooks/refactoring.md index 599bef36..f42d9261 100644 --- a/pstack/skills/poteto-mode/playbooks/refactoring.md +++ b/pstack/skills/poteto-mode/playbooks/refactoring.md @@ -7,7 +7,7 @@ If the cleanup reveals a missing feature or a real bug, split it out and ship th 1. Pin the behavior contract first. Run the **how** skill over the affected subsystem to learn the contract, then write a characterization test, snapshot, or equivalence harness that captures current behavior before any structure moves. The harness makes "refactor" a checkable claim (**principle-prove-it-works**). If the area has no coverage, write the pin before touching structure. Type check and lint are not a pin. 2. Name the target shape. State what the module layout, types, and call graph should be if built today (**principle-foundational-thinking**, **principle-redesign-from-first-principles**). If the target crosses a function boundary, run the **architect** skill for parallel design exploration of the shape before the move. 3. Subtract before you add. Delete dead weight, collapse one-caller wrappers, drop redundant validators, and remove orphan references before introducing the new shape (**principle-subtract-before-you-add**). The smallest change that reaches the target shape ships (**principle-laziness-protocol**). A speculative cleanup that "might help" gets reverted, not left to ride. -4. Move in small behavior-preserving steps, each keeping the pin green. For API reshapes, migrate every caller and delete the old API in the same wave (**principle-migrate-callers-then-delete-legacy-apis**). No compatibility shims, no parallel old-and-new paths. Spot-check every rename against the actual files; renames silently miss usages in strings, prose, and back-references. Delegate the mechanical edits to a subagent using your configured refactoring model (default `composer-2.5-fast`) with a specific scope (file paths, the names being moved, the behavior to hold); review the diff yourself. +4. Move in small behavior-preserving steps, each keeping the pin green. For API reshapes, migrate every caller and delete the old API in the same wave (**principle-migrate-callers-then-delete-legacy-apis**). No compatibility shims, no parallel old-and-new paths. Spot-check every rename against the actual files; renames silently miss usages in strings, prose, and back-references. Delegate the mechanical edits to a subagent using your configured refactoring model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, the names being moved, the behavior to hold); review the diff yourself. 5. Prove behavior is unchanged on the real artifact, not "it compiles" (**principle-prove-it-works**). For larger reshapes, run an equivalence check: a script that diffs old-vs-new outputs, a recorded baseline replayed against the new code, or a smoke run on the matching surface via the relevant control skill. Own the verification yourself; do not trust a delegate's "looks good" summary. 6. Confirm the change earns its place. The success measure is reduced reader load (**principle-minimize-reader-load**): fewer layers between question and answer, less hidden state, fewer indirections without a second consumer. If the diff does not lower reader load somewhere, revert it. 7. Rebase into small ordered commits that tell the story. A subtraction commit, then the reshape, then any follow-on cleanup, so a single revert undoes one slice. Shape them with the **sequence-verifiable-units** principle skill, so each behavior-preserving slice stays green before the next. Run **Opening a PR**. diff --git a/pstack/skills/poteto-mode/references/plan.md b/pstack/skills/poteto-mode/references/plan.md index 37012f41..2abeed2f 100644 --- a/pstack/skills/poteto-mode/references/plan.md +++ b/pstack/skills/poteto-mode/references/plan.md @@ -25,7 +25,7 @@ Resolve what is in scope vs explicitly out, technical or platform constraints, p Delegate codebase exploration (the **guard-the-context-window** principle skill). - Prefer `subagent_type: "poteto-agent"`. `generalPurpose` is the fallback. Never use the built-in `plan` subagent_type; it ignores this skill. -- Pass `model:` explicitly per the configured roles (defaults `composer-2.5-fast` for code, `claude-opus-4-8-thinking-xhigh` for judgment). +- Pass `model:` explicitly per the configured roles (defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for judgment). Each explorer returns file pointers, conventions, dependencies, test infrastructure, and entry points. No inlined dumps. diff --git a/pstack/skills/reflect/SKILL.md b/pstack/skills/reflect/SKILL.md index 8decf612..e0359fb3 100644 --- a/pstack/skills/reflect/SKILL.md +++ b/pstack/skills/reflect/SKILL.md @@ -39,7 +39,7 @@ One message, three `Task` calls, `subagent_type: generalPurpose`, explicit `mode | Lens | `model` | Prompt template | |---|---|---| | Judgment | your configured reflect-judgment model (default `claude-opus-4-8-thinking-xhigh`) | `references/judgment-reviewer.md` | -| Tooling | your configured reflect-tooling model (default `composer-2.5-fast`) | `references/tooling-reviewer.md` | +| Tooling | your configured reflect-tooling model (default `grok-4.5-fast-xhigh`) | `references/tooling-reviewer.md` | | Divergent | your configured reflect-judgment model (default `claude-opus-4-8-thinking-xhigh`) | `references/divergent-reviewer.md` | Pass each template verbatim, substituting the transcript path or digest where marked. Reviewers return findings in the `Task` response body. diff --git a/pstack/skills/setup-pstack/SKILL.md b/pstack/skills/setup-pstack/SKILL.md index b963cc45..6c8833f2 100644 --- a/pstack/skills/setup-pstack/SKILL.md +++ b/pstack/skills/setup-pstack/SKILL.md @@ -35,21 +35,21 @@ description: pstack per-role model choices (overrides skill defaults) alwaysApply: true --- # pstack model configuration. One line per role. Delete a line to fall back to the skill default. -feature, refactoring: composer-2.5-fast +feature, refactoring: grok-4.5-fast-xhigh bug-fix: gpt-5.5-high-fast perf-issue: gpt-5.5-high-fast hillclimb: gpt-5.5-high-fast judgment and prose: claude-opus-4-8-thinking-xhigh -how explorer: composer-2.5-fast +how explorer: grok-4.5-fast-xhigh how explainer: claude-opus-4-8-thinking-xhigh -how critics: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, composer-2.5-fast -why investigators: composer-2.5-fast +how critics: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh +why investigators: grok-4.5-fast-xhigh why synthesizer: claude-opus-4-8-thinking-xhigh -reflect tooling: composer-2.5-fast +reflect tooling: grok-4.5-fast-xhigh reflect judgment, divergent, synthesizer: claude-opus-4-8-thinking-xhigh -arena runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, composer-2.5-fast -architect runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, composer-2.5-fast -interrogate reviewers: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, composer-2.5-fast +arena runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh +architect runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh +interrogate reviewers: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh ``` ### 6. Confirm diff --git a/pstack/skills/why/SKILL.md b/pstack/skills/why/SKILL.md index def17100..86e8c283 100644 --- a/pstack/skills/why/SKILL.md +++ b/pstack/skills/why/SKILL.md @@ -117,7 +117,7 @@ Launch all matching investigators in a single message so they run concurrently. Subagent config (each): - `subagent_type`: `generalPurpose` -- `model`: your configured why-investigators model (default `composer-2.5-fast`) +- `model`: your configured why-investigators model (default `grok-4.5-fast-xhigh`) - `readonly`: `false` (agent mode). **Do not use readonly/Ask mode.** It strips MCP access, which disables MCP-backed investigators entirely. The source control investigator would be safe in readonly, but keep modes uniform. Investigators still shouldn't write anything. That's a posture, not a sandbox. Each investigator gets: From 9b80b5349872b2a3404be58bd9236cc9b83833bb Mon Sep 17 00:00:00 2001 From: lauren Date: Wed, 8 Jul 2026 21:39:53 +0000 Subject: [PATCH 03/17] pstack: route hardest tasks to claude-fable-5-thinking-max (#143) --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/skills/poteto-mode/SKILL.md | 2 +- pstack/skills/setup-pstack/SKILL.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index ebeef146..dc60bc6a 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.10.1", + "version": "0.10.2", "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" diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index b1a5cff3..d848714a 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -79,7 +79,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Use `subagent_type: "poteto-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). `/poteto-mode` and `poteto-agent` route through the same wrapper. Routed workflow skills (`how`, `why`, `interrogate`, `reflect`) set their own `subagent_type` for diverse-model review; respect what the skill prescribes, don't override to `poteto-agent`. -**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). +**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms, vague intent) go to `claude-fable-5-thinking-max`. You own every subagent's work. Review the diff and write your own summary, don't pass through what it said. Interrupt-chained resumes silently drop directives, so fire a fresh subagent with consolidated scope rather than trusting a "done" summary. A second opinion is the same prompt against a different model. Agreement is high-signal. diff --git a/pstack/skills/setup-pstack/SKILL.md b/pstack/skills/setup-pstack/SKILL.md index 6c8833f2..7774223e 100644 --- a/pstack/skills/setup-pstack/SKILL.md +++ b/pstack/skills/setup-pstack/SKILL.md @@ -40,6 +40,7 @@ bug-fix: gpt-5.5-high-fast perf-issue: gpt-5.5-high-fast hillclimb: gpt-5.5-high-fast judgment and prose: claude-opus-4-8-thinking-xhigh +hardest tasks: claude-fable-5-thinking-max how explorer: grok-4.5-fast-xhigh how explainer: claude-opus-4-8-thinking-xhigh how critics: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh From 0dda29e839d15464a137af9935665a5a47ee09b8 Mon Sep 17 00:00:00 2001 From: lauren Date: Thu, 9 Jul 2026 01:49:43 +0000 Subject: [PATCH 04/17] pstack: make poteto-mode a sticky mode with a conditional reminder (#144) * pstack: make poteto-mode a sticky mode with a conditional reminder * pstack: reference the mode as /poteto-mode in the sticky reminder --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/skills/poteto-mode/SKILL.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index dc60bc6a..a095e64e 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.10.2", + "version": "0.10.3", "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" diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index d848714a..8e594c93 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -2,6 +2,10 @@ name: poteto-mode description: poteto's agent style for concise, detailed responses, deliberate subagents, unslopped prose, simple code, and verified work. Use for poteto, /poteto-mode, or requests to work in this style. disable-model-invocation: true +mode: true +icon: crown +color: yellow +reminder: New task? Playbook match or rigor needed -> apply /poteto-mode. Casual turn or user opts out -> don't. --- # Poteto mode From a8145426e541afa424a403e3866496216c1b8142 Mon Sep 17 00:00:00 2001 From: lauren Date: Sat, 11 Jul 2026 02:25:05 +0000 Subject: [PATCH 05/17] pstack: add model-the-domain principle; true up README (#147) * pstack: add model-the-domain principle; true up README * pstack: index model-the-domain in poteto-mode's architecture principles --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/README.md | 8 +++--- pstack/skills/poteto-mode/SKILL.md | 1 + .../principle-model-the-domain/SKILL.md | 25 +++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 pstack/skills/principle-model-the-domain/SKILL.md diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index a095e64e..66063788 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.10.3", + "version": "0.10.4", "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" diff --git a/pstack/README.md b/pstack/README.md index 2889492f..9d07e5e0 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -68,6 +68,8 @@ when invoked it: the full rules and playbooks live in `skills/poteto-mode/SKILL.md`. +`/poteto-mode` 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` works extremely well with cursor's `/loop` command. you can make cursor work for many hours without sacrificing rigor. ## skills @@ -83,7 +85,7 @@ the rest are useful when you want to specifically invoke them: | `/blast-radius` | 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` | you're about to write code that crosses a function boundary and want the caller's usage, types, and module shape settled first. | | `/arena` | you want N parallel attempts at the same thing, then to grab the best parts of each. | -| `/interrogate` | you have a diff and want four different models to try to break it, including a strict code-quality lens. | +| `/interrogate` | you have a diff and want several different models to try to break it, including a strict code-quality lens. | | `/automate-me` | you want your own `-mode` skill, drafted from how you've actually worked. | | `/setup-pstack` | you want to pick which models pstack uses per role. detects your models and writes a config rule. | | `/reflect` | a long task landed and you want the recipe captured as a skill edit. | @@ -137,10 +139,10 @@ pstack also ships a subagent that runs my style end to end. spawn it from a pare ## principles -twenty 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. +twenty-one 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. - core: laziness-protocol, foundational-thinking, redesign-from-first-principles, subtract-before-you-add, minimize-reader-load, outcome-oriented-execution, experience-first, exhaust-the-design-space, build-the-lever. -- architecture: boundary-discipline, type-system-discipline, make-operations-idempotent, migrate-callers-then-delete-legacy-apis, separate-before-serializing-shared-state. +- architecture: model-the-domain, boundary-discipline, type-system-discipline, make-operations-idempotent, migrate-callers-then-delete-legacy-apis, separate-before-serializing-shared-state. - verification: prove-it-works, fix-root-causes, sequence-verifiable-units. - delegation: guard-the-context-window, never-block-on-the-human. - meta: encode-lessons-in-structure. diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index 8e594c93..9722cbee 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -48,6 +48,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Architecture** +- **Model the Domain** (**principle-model-the-domain**). Writing stateful logic, or code that branches a lot or repeats a shape assumption across files. Encode the domain in a structure (state machine, typed model, table or registry, reducer, boundary, the right collection) instead of scattered conditionals. - **Boundary Discipline** (**principle-boundary-discipline**). Wiring validation, error handling, or framework adapters. Guards at system boundaries, trust internal types, keep business logic pure. - **Type System Discipline** (**principle-type-system-discipline**). Designing types or a signature in any typed language. Make illegal states unrepresentable, brand primitives, parse external data at boundaries. - **Make Operations Idempotent** (**principle-make-operations-idempotent**). Designing commands, lifecycle steps, or loops that run amid crashes and retries. Converge to the same end state. diff --git a/pstack/skills/principle-model-the-domain/SKILL.md b/pstack/skills/principle-model-the-domain/SKILL.md new file mode 100644 index 00000000..24ba9e6a --- /dev/null +++ b/pstack/skills/principle-model-the-domain/SKILL.md @@ -0,0 +1,25 @@ +--- +name: principle-model-the-domain +description: "Apply when writing stateful logic, or when code branches a lot or repeats a shape assumption across files. Encode the domain in a structure instead of scattered conditionals." +disable-model-invocation: true +--- + +# Model the Domain + +Encode the real domain in a data structure instead of scattering it across conditionals. + +**Why:** Scattered booleans, repeated shape assumptions, and branching spread across files are accidental complexity. A structure that matches the domain makes invalid states unrepresentable and deletes branches. Choosing it at write time is cheap; recovering it later reads as a refactor and gets deferred. + +**Pattern — reach for:** + +- A state machine instead of scattered booleans, phases, or lifecycle checks. +- A typed object/model instead of loose parameters or repeated shape assumptions. +- A map, registry, lookup table, or discriminated union instead of branching spread across files. +- A reducer or command/event model instead of ad hoc state mutations. +- A small module boundary that gathers repeated behavior, ownership, or invariants. +- A queue, cache, index, graph/tree, or normalized collection where the data access pattern calls for it. +- Any other structure that fits. The list above covers the common cases only. When none fits, work out what the code must never allow and how the data gets read, then find the structure that encodes exactly that. + +Do not force an abstraction. Prefer boring code if the current shape is already clear, local, and unlikely to grow. Be skeptical of an abstraction that adds indirection without removing branches, duplicated rules, invalid states, or lifecycle risk. + +The tell that you skipped this: a new feature that grows an existing if/else chain by one more branch, or a second boolean that must stay in sync with the first. From 9251b2666bc9876396825c1f0df5685dbdaaddb5 Mon Sep 17 00:00:00 2001 From: lauren Date: Sat, 11 Jul 2026 23:21:33 +0000 Subject: [PATCH 06/17] pstack: lead the README with the two-step quickstart (#148) * pstack: lead the README with the two-step quickstart * Keep version at 0.10.4; README-only change * README: no version bump, reorder for first-time readers, collapse long blocks make-it-yours and automations move below the reference sections; the sixteen-playbook table and the examples block collapse behind
so the top of the page is install -> get started -> usage. * README: collapse the skills table too, keep four examples visible * README: link every skill, playbook, and principle to its file; split examples by section * README: visible examples are bare copy-paste prompts * README: link every prose skill mention and the playbooks dir * README: visible example prompts wrap at 100 chars and lead their sections * README: principles as a collapsible table --- pstack/README.md | 184 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 127 insertions(+), 57 deletions(-) diff --git a/pstack/README.md b/pstack/README.md index 9d07e5e0..434c837a 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -18,86 +18,117 @@ fork it. improve it. make it yours. PRs are welcome! /add-plugin pstack ``` -## make it yours +## get started -`poteto-mode` is my style. you may not want exactly that. +two steps: -type `/automate-me`. 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`. +1. run [`/setup-pstack`](./skills/setup-pstack/SKILL.md) and choose which models you want. +2. use [`/poteto-mode`](./skills/poteto-mode/SKILL.md) whenever you're doing anything that requires rigor. -models are configurable too. type `/setup-pstack`. 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. +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: your main agent reasons and reviews, precisely-specified code goes to fast code models (cursor grok 4.5 by default), and prose and judgment go to a thinking model. [`/setup-pstack`](./skills/setup-pstack/SKILL.md) changes any of it. -## automations +## usage -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. +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. -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. +### just use [`/poteto-mode`](./skills/poteto-mode/SKILL.md) -## usage +this skill is the main shortcut. i use it whenever i need the agent to do rigorous engineering work. it comes with sixteen playbooks: -use `/poteto-mode` 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. +``` +/poteto-mode this pr has a subtle bug where the scroll drifts every 750ms even when idle. repro +first, then fix and verify. +``` -### just use `/poteto-mode` +``` +/poteto-mode i'm going to bed. land the stack even if ci flakes. i want everything merged by +morning. +``` -this skill is the main shortcut. i use it whenever i need the agent to do rigorous engineering work. it comes with sixteen playbooks: +
+the sixteen playbooks | playbook | for | |---|---| -| investigation | a read-only question. how does x work, why was y built this way, are we sure. | -| bug fix | reproduce a defect, root-cause it, and fix with runtime evidence. | -| perf | trace a measured slowness and improve it against a baseline. | -| hillclimb | sustained, scientific improvement of one metric against a target, looping hypotheses with before/after measurement and one commit per accepted win. | -| runtime forensics | diagnose a live symptom (leak, idle-cpu spin, glitch) from instrumentation. | -| trace forensics | diagnose a captured profiling artifact (cpuprofile, trace, spindump, heap snapshot). | -| feature | new or changed behavior, built from a named data shape. | -| refactoring | a behavior-preserving change to structure or shape. | -| prototype | a throwaway sketch to make a design or behavioral decision cheaply, or to settle an empirical fork by observing it. | -| visual parity | pixel-exact ui equivalence between two implementations. | -| authoring a skill | writing or editing a SKILL.md. | -| eval | test how a skill or prompt change affects agent behavior, blinded. | -| autonomous run | drive a long task to completion without stopping. | -| session pickup | resume or take over a prior agent's in-flight work. | -| pause safely | suspend in-flight work cleanly so it can be resumed later. | -| multi-phase plan | work that spans phases or stacked PRs. | +| [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. | +| [autonomous run](./skills/poteto-mode/playbooks/autonomous-run.md) | drive a long task to completion without stopping. | +| [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. | + +
+ + when invoked it: 1. opens a todo list. the first item is reading the inline principles index in the skill. -2. matches your task to a playbook and copies the steps in verbatim. +2. matches your task to a [playbook](./skills/poteto-mode/playbooks/) and copies the steps in verbatim. 3. routes to the other skills as the steps fire. 4. writes unslopped replies framed for the consumer and the maintainer. -the full rules and playbooks live in `skills/poteto-mode/SKILL.md`. +the full rules and playbooks live in [`skills/poteto-mode/SKILL.md`](./skills/poteto-mode/SKILL.md). -`/poteto-mode` 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) 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` works extremely well with cursor's `/loop` command. you can make cursor work for many hours without sacrificing rigor. +[`/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 -the rest are useful when you want to specifically invoke them: +[`/poteto-mode`](./skills/poteto-mode/SKILL.md) runs most of these for you when a step needs them (`how`, `why`, `architect`, `arena`, `interrogate`, `unslop`, `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` | default entry point for any non-trivial task. | -| `/how` | you want a walkthrough of how a subsystem works. | -| `/why` | 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` | 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` | 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` | you're about to write code that crosses a function boundary and want the caller's usage, types, and module shape settled first. | -| `/arena` | you want N parallel attempts at the same thing, then to grab the best parts of each. | -| `/interrogate` | you have a diff and want several different models to try to break it, including a strict code-quality lens. | -| `/automate-me` | you want your own `-mode` skill, drafted from how you've actually worked. | -| `/setup-pstack` | you want to pick which models pstack uses per role. detects your models and writes a config rule. | -| `/reflect` | a long task landed and you want the recipe captured as a skill edit. | -| `/tdd` | you're fixing a bug and there's a cheap local test path. write the failing test first, then the fix. | -| `/typescript-best-practices` | you're reading or editing typescript. grounds the type-system-discipline principle in syntax. | -| `/figure-it-out` | no bundled playbook fits. designs a rigorous, auditable playbook for the task. | -| `/show-me-your-work` | you want a reviewable decision trail. logs decisions to a tsv you can commit. | -| `/unslop` | you're cleaning up writing. removes AI tells. | +| [`/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. | +| [`/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. | +| [`/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. | +| [`/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. | +| [`/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. | +| [`/unslop`](./skills/unslop/SKILL.md) | you're cleaning up writing. removes AI tells. | + +
+ + ### examples -mostly i type `/poteto-mode` 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. +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 @@ -131,21 +162,46 @@ show-me-your-work: /show-me-your-work keep a decision trail i can review when i' automate-me: /automate-me ``` +
+ ## the `poteto-agent` subagent -pstack also ships a subagent that runs my style end to end. spawn it from a parent agent via `subagent_type: "poteto-agent"`. it reads `poteto-mode` in full, including its inline principles index, before doing any work. substituting `generalPurpose` skips that read and drifts. +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` and `subagent_type: "poteto-agent"` route through the same wrapper. +[`/poteto-mode`](./skills/poteto-mode/SKILL.md) and [`subagent_type: "poteto-agent"`](./agents/poteto-agent.md) route through the same wrapper. ## principles twenty-one 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. -- core: laziness-protocol, foundational-thinking, redesign-from-first-principles, subtract-before-you-add, minimize-reader-load, outcome-oriented-execution, experience-first, exhaust-the-design-space, build-the-lever. -- architecture: model-the-domain, boundary-discipline, type-system-discipline, make-operations-idempotent, migrate-callers-then-delete-legacy-apis, separate-before-serializing-shared-state. -- verification: prove-it-works, fix-root-causes, sequence-verifiable-units. -- delegation: guard-the-context-window, never-block-on-the-human. -- meta: encode-lessons-in-structure. +
+all twenty-one 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. | +| [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. | +| [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 @@ -159,7 +215,21 @@ 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` covers it, but it's not a default. +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. + +## 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 From 9d2a3f2d12bbe0dca3e61bbc0e9dbfe2df09fb56 Mon Sep 17 00:00:00 2001 From: lauren Date: Sat, 11 Jul 2026 23:32:28 +0000 Subject: [PATCH 07/17] pstack: give poteto-mode a human display name (#149) --- pstack/skills/poteto-mode/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index 9722cbee..9284b5bf 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -1,5 +1,5 @@ --- -name: poteto-mode +name: Poteto Mode description: poteto's agent style for concise, detailed responses, deliberate subagents, unslopped prose, simple code, and verified work. Use for poteto, /poteto-mode, or requests to work in this style. disable-model-invocation: true mode: true From e42d29fd5c8fe4f13e3bee7f53b35f410f65aee8 Mon Sep 17 00:00:00 2001 From: lauren Date: Sun, 12 Jul 2026 00:17:43 +0000 Subject: [PATCH 08/17] pstack: add create-verification-skill and maintain-verification-skill (#150) * pstack: add create-verification-skill and maintain-verification-skill Generalizes the control-glass approach (feature map, doctor, proof standards, harness-first) for any language or platform. The generator interviews the repo, writes a project-local verify skill + seeded feature map, and must prove its own output by running it once. The maintainer is the upkeep loop: source wave per feature, one live pass, at most one PR. setup-pstack gains an optional final step offering the generator. Validated by 4 cloud agents generating against real repos (go TUI, node CLI, HTTP service, full-stack web app) - all four proof runs passed, and their friction reports drove 6 revisions. * Address bugbot: frontmatter spec, teardown, launch-model deference, target discovery * Rewrite live pass: per-session health checks, doctor-drift retry, per-failure cleanup, teardown after re-proof --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/README.md | 2 + .../skills/create-verification-skill/SKILL.md | 44 +++++++++++++++++++ .../maintain-verification-skill/SKILL.md | 39 ++++++++++++++++ pstack/skills/setup-pstack/SKILL.md | 4 ++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 pstack/skills/create-verification-skill/SKILL.md create mode 100644 pstack/skills/maintain-verification-skill/SKILL.md diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index 66063788..ec2d6402 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.10.4", + "version": "0.11.0", "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" diff --git a/pstack/README.md b/pstack/README.md index 434c837a..05093944 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -116,6 +116,8 @@ the full rules and playbooks live in [`skills/poteto-mode/SKILL.md`](./skills/po | [`/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. |
diff --git a/pstack/skills/create-verification-skill/SKILL.md b/pstack/skills/create-verification-skill/SKILL.md new file mode 100644 index 00000000..db06674d --- /dev/null +++ b/pstack/skills/create-verification-skill/SKILL.md @@ -0,0 +1,44 @@ +--- +name: create-verification-skill +description: "Generate a project-local verification skill that drives your app the way a user does — any language, framework, or platform. Use for /create-verification-skill, \"make a control skill for this repo\", or when a project has no scripted way to prove UI/CLI/service behavior." +disable-model-invocation: true +--- + +# Create a verification skill + +Every serious project needs a scripted way to drive the real app and prove behavior: launch it, exercise a feature the way a user would, and capture evidence. This skill generates that as a project-local skill (`.cursor/skills/verify-/`) tailored to the repo. You write the generator's output for the next agent, not for a human: it will be read cold, mid-task, by an agent that has never seen the app. + +## 1. Interview the repo, not the user + +Answer these from the codebase and only ask the user what you cannot observe: + +- **Surface:** what does a user actually touch? A web UI, a CLI/TUI, a desktop app, an API, a mobile app, a library? A repo can have several; pick the primary one and note the rest. +- **Run:** how does the app start locally? Prefer the repo's own documented dev command (package scripts, Makefile, README quickstart). Note ports, env vars, seed data, auth. +- **Drive:** how can an agent interact with it programmatically? Existing harnesses first — Playwright/Cypress specs, expect scripts, PTY helpers, curl-able endpoints, a debug port. Only then pick a generic recipe: browser/CDP for web and Electron, a tmux/PTY harness for CLI/TUI, plain HTTP for services. +- **Observe:** what evidence can be captured? Screenshots, terminal transcripts, response bodies, logs, exit codes, DB state. +- **Isolate:** can two instances run side by side (ports, data dirs, profiles)? If not, say so in the generated skill: refusing to double-drive a shared instance beats corrupting the user's session. + +If the checkout doesn't build or start as-is, fix that first (or report it precisely) before generating; a skill written against a broken base teaches wrong steps. When an irrelevant missing asset blocks startup (a static dir the API never serves, a sample config), the generated skill may create it, clearly marked as verification scaffolding, and remove it in cleanup. + +## 2. Generate the skill + +Write `.cursor/skills/verify-/SKILL.md` with YAML frontmatter (`name: verify-` and a `description` that names the app, the surface, and when to reach for it — without frontmatter the skill never registers) and these sections, each grounded in what the interview actually found (no placeholders left): + +- **Launch:** the exact command that starts the app for verification, and how to tell it's ready (a log line, a port answering, a prompt). Include teardown. For a short-lived CLI or TUI there is no server to keep alive: launch means build the binary (or install deps) once, then start each drive in its own isolated PTY or tmux session. +- **Doctor:** one read-only check that answers "is this instance worth driving?" — process up, right version/build, port owned by us, auth valid. An agent runs this first whenever anything looks off. +- **Drive:** the harness recipe with real selectors/commands from this repo, not examples. Prefer stable handles (ARIA labels, data attributes, prompt strings, route paths) over coordinates and tab order. +- **Evidence:** what to capture for a proof and where it goes. State the proof standards: exercise the real user path, not internal setters or test-only endpoints; capture the action and the resulting state, not just the final screen; verify side effects (files written, rows inserted, messages sent) alongside what's visible; mocks only where a production boundary already isolates the external system. When the safe path is a dry-run or test mode, verify what it actually skips by observing (files, network, git refs) rather than trusting its name: some dry-runs still touch the network or open a browser. +- **Cleanup:** how to tear down instances the run created. Never kill by process name; kill what you started. Cleanup removes instances and scratch state, never the evidence: proof artifacts survive the teardown, in a location the skill names. +- **Helpers:** any script the skill ships is executable and its invocation is shown in the skill body. A helper the reader has to reverse-engineer is not a helper. + +## 3. Seed the feature map + +Create `.cursor/skills/verify-/features/README.md` plus one file per user-facing feature you can identify (aim for the top 3-5 to start, from routes, commands, menus, or docs). Each file answers, from the user's point of view: what the feature is, how to reach it, how to drive it with the harness, and what observable end state proves it works. The map is the repo's maintained verification source; a proof that drives one convenient entry point is incomplete when the map lists others. + +## 4. Prove the generated skill before handing it over + +Run its own instructions end to end once: launch, doctor, drive ONE mapped feature (one is enough; the map exists so later runs can cover the rest), capture evidence, clean up. After cleanup, confirm the evidence still exists at the named location — a cleanup that eats the proof fails this step. Fix what fails, and run the generated cleanup after every failed iteration too, so broken attempts don't strand processes and ports. A generated skill that was never executed is a draft, not a deliverable. + +## 5. Offer the maintenance loop + +Point the user at `/maintain-verification-skill` for keeping the map honest as the app changes. Suggest a cadence only if they ask. diff --git a/pstack/skills/maintain-verification-skill/SKILL.md b/pstack/skills/maintain-verification-skill/SKILL.md new file mode 100644 index 00000000..61c7560b --- /dev/null +++ b/pstack/skills/maintain-verification-skill/SKILL.md @@ -0,0 +1,39 @@ +--- +name: maintain-verification-skill +description: "Periodic pass that keeps a project's verification skill and feature map honest: parallel source readers per feature, one live session driving every feature, at most one PR of proven corrections. Use for /maintain-verification-skill or \"audit the verify skill\"." +disable-model-invocation: true +--- + +# Maintain a verification skill + +A feature map rots the moment the app changes. This skill is the upkeep loop for a skill generated by `/create-verification-skill` (or any project-local verification skill with a feature map). The unit of rigor is the feature, not every sentence: cover every feature file from source and exercise every feature live, without terminalising every bullet. + +## Outcomes + +Pick one, and say which: + +- **clean** — every feature got source and live coverage; nothing worth shipping. No branch, no PR. +- **changed** — one PR ships proven doc, harness, or map corrections. +- **blocked** — coverage could not finish or a proven fix could not ship safely. Say exactly what blocked it. + +## Edit scope + +Only edit the verification skill's own directory (its SKILL.md, features/, and any harness scripts it owns). Never edit product code during a run: a behavior the map describes that the app no longer does is either doc drift (fix the map) or a product regression (report it, don't paper over it in docs). + +## Pass + +0. **Locate the target.** Find the verification skill to maintain: the project-local skill whose body has launch/drive sections and a feature map (usually `.cursor/skills/verify-*/`). Several candidates → ask which one; none → stop and point at `/create-verification-skill` instead of inventing a target. + +1. **Index hygiene.** Read the feature map README and glob its sibling files. Fix missing, extra, duplicate, or dead entries. Lightweight; no generated inventory. + +2. **Source wave.** One read-only subagent per feature file, launched concurrently. Each explains "how does this user-facing feature work?" from source, flags likely doc drift with citations, and returns one concise live-verification recipe. Children never drive the app and never edit files. Return shape: feature summary / source entry points / likely drift or none / one recipe. + +3. **Reconcile.** Every feature file has a returned summary. Merge overlapping recipes into as few app states as practical. Spot-check cited drift; don't re-prove clean claims. Sweep recent churn for user-facing surfaces missing from the map — require a concrete source path before calling one missing. + +4. **Live pass.** Required even when source looks clean. The coordinator owns all driving; follow the verification skill's own launch model — one long-lived instance driven serially for servers and UIs, or a fresh isolated session per drive for short-lived CLIs (the skill's Launch section decides, not this one). Health-check at the skill's own granularity: doctor before driving a long-lived instance, and per session where sessions are the unit. Never drive past a failing doctor — but a doctor that fails because the *skill* drifted is itself drift: fix it under edit scope, retry once, and only then call the pass `blocked`. Exercise every feature at least once, cleaning up any failed drive immediately so a stuck session can't poison the rest of the pass. A feature that can't be reached is `verified-unreachable` only with the concrete prerequisite (auth, entitlement, OS, external state) and the route attempted; if the map omits that prerequisite, that's drift. Any harness fix from triage gets re-driven live before it ships. Final teardown happens after the last drive of the run — including those re-proofs — so nothing outlives the run (evidence stays, per the skill). + +5. **Triage.** Wrong or missing user-POV description → doc drift, fix it. Working behavior the harness can't drive → harness gap, fix it; a harness fix follows the same helpers rule as generation (scripts executable, invocation documented in the skill body). App behavior that's actually broken → product gap; record it for the user, keep it out of this PR. + +6. **Ship or stop.** For changed: one PR of proven corrections, re-read every changed file first. For clean or blocked: no PR, report the outcome and the coverage honestly. + +Keep concise run notes (features covered, unreachable prerequisites, confirmed drift, outcome) in a scratch location; don't commit them. diff --git a/pstack/skills/setup-pstack/SKILL.md b/pstack/skills/setup-pstack/SKILL.md index 7774223e..9a77f29a 100644 --- a/pstack/skills/setup-pstack/SKILL.md +++ b/pstack/skills/setup-pstack/SKILL.md @@ -56,3 +56,7 @@ interrogate reviewers: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4 ### 6. Confirm Tell the user the rule was written and that it applies to new sessions. Re-running this skill updates it. + +### 7. Offer a verification skill (optional) + +Check whether the project has a way to drive the real app for proof (a `verify-*` skill, or an existing harness). If not, offer once: "want a project-local verification skill, so agents can drive the app the way a user does and prove changes work? I can generate one with /create-verification-skill." On yes, invoke `/create-verification-skill` (resolves wherever pstack is installed — workspace, user, or plugin). On no, move on without pushing. From 6714489fa233263f00e419f6cfc4759b07c81056 Mon Sep 17 00:00:00 2001 From: lauren Date: Sun, 12 Jul 2026 01:10:09 +0000 Subject: [PATCH 09/17] maintain-verification-skill: cleanup granularity, re-doctor, evidence checks (#151) * maintain-verification-skill: cleanup granularity, re-doctor, evidence checks Follow-up to the four bugbot comments that landed on #150 seconds before merge: failed-drive cleanup now matches the granularity of what failed (never tearing down a shared instance mid-pass), a failed drive on a long-lived instance triggers re-doctor before the next feature, the doctor-drift retry includes cleanup and relaunch, and every cleanup is followed by an evidence-survival check. * State the live-pass recovery rules as invariants, not enumerated procedures * Restore the per-session doctor check inside invariant 1 --- pstack/skills/maintain-verification-skill/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pstack/skills/maintain-verification-skill/SKILL.md b/pstack/skills/maintain-verification-skill/SKILL.md index 61c7560b..a2680b91 100644 --- a/pstack/skills/maintain-verification-skill/SKILL.md +++ b/pstack/skills/maintain-verification-skill/SKILL.md @@ -30,7 +30,7 @@ Only edit the verification skill's own directory (its SKILL.md, features/, and a 3. **Reconcile.** Every feature file has a returned summary. Merge overlapping recipes into as few app states as practical. Spot-check cited drift; don't re-prove clean claims. Sweep recent churn for user-facing surfaces missing from the map — require a concrete source path before calling one missing. -4. **Live pass.** Required even when source looks clean. The coordinator owns all driving; follow the verification skill's own launch model — one long-lived instance driven serially for servers and UIs, or a fresh isolated session per drive for short-lived CLIs (the skill's Launch section decides, not this one). Health-check at the skill's own granularity: doctor before driving a long-lived instance, and per session where sessions are the unit. Never drive past a failing doctor — but a doctor that fails because the *skill* drifted is itself drift: fix it under edit scope, retry once, and only then call the pass `blocked`. Exercise every feature at least once, cleaning up any failed drive immediately so a stuck session can't poison the rest of the pass. A feature that can't be reached is `verified-unreachable` only with the concrete prerequisite (auth, entitlement, OS, external state) and the route attempted; if the map omits that prerequisite, that's drift. Any harness fix from triage gets re-driven live before it ships. Final teardown happens after the last drive of the run — including those re-proofs — so nothing outlives the run (evidence stays, per the skill). +4. **Live pass.** Required even when source looks clean. The coordinator owns all driving; follow the verification skill's own launch model — one long-lived instance driven serially for servers and UIs, or a fresh isolated session per drive for short-lived CLIs (the skill's Launch section decides, not this one). Exercise every feature at least once, and hold three invariants the whole pass, whatever the failure: (1) never drive an instance you haven't health-checked since it last did something surprising — doctor before first drive, doctor on each fresh session where sessions are the unit, doctor again after any failed drive, and where doctor can't see the failure (a wedged UI state on a healthy process), reset to a known state or relaunch rather than hoping; (2) evidence captured so far survives every cleanup, checked at its named location, not assumed; (3) nothing a drive started outlives that drive's usefulness — failed-iteration residue is cleaned whether the session is stuck, exited, or shared (for a shared instance, clean the residue, not the instance). A doctor failure caused by skill drift is drift: fix it under edit scope and retry once — restart whatever the fix invalidated, nothing more — before calling the pass `blocked`. A feature that can't be reached is `verified-unreachable` only with the concrete prerequisite (auth, entitlement, OS, external state) and the route attempted; if the map omits that prerequisite, that's drift. Any harness fix from triage gets re-driven live before it ships. Final teardown happens after the last drive of the run — including those re-proofs — so nothing outlives the run (evidence stays, per the skill). 5. **Triage.** Wrong or missing user-POV description → doc drift, fix it. Working behavior the harness can't drive → harness gap, fix it; a harness fix follows the same helpers rule as generation (scripts executable, invocation documented in the skill body). App behavior that's actually broken → product gap; record it for the user, keep it out of this PR. From 20bdb6cdfdd8ffa683befe62d76104e5654c861d Mon Sep 17 00:00:00 2001 From: lauren Date: Sun, 12 Jul 2026 03:30:46 +0000 Subject: [PATCH 10/17] pstack: bump version to 0.11.1 (#152) --- pstack/.cursor-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index ec2d6402..24168817 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.11.0", + "version": "0.11.1", "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" From 8f008c41981dca484d5beaf688d3aa2ea4ecf89b Mon Sep 17 00:00:00 2001 From: lauren Date: Sun, 12 Jul 2026 04:14:01 +0000 Subject: [PATCH 11/17] pstack: add the teach skill (compose how + why into one explanation) (#153) * pstack: add the teach skill (compose how + why into one explanation) * teach: honor why's skip contract and confidence language when weaving --- pstack/README.md | 1 + pstack/skills/teach/SKILL.md | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 pstack/skills/teach/SKILL.md diff --git a/pstack/README.md b/pstack/README.md index 05093944..fccffd10 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -112,6 +112,7 @@ the full rules and playbooks live in [`skills/poteto-mode/SKILL.md`](./skills/po | [`/automate-me`](./skills/automate-me/SKILL.md) | you want your own `-mode` skill, drafted from how you've actually worked. | | [`/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. | | [`/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. | diff --git a/pstack/skills/teach/SKILL.md b/pstack/skills/teach/SKILL.md new file mode 100644 index 00000000..beea0ffa --- /dev/null +++ b/pstack/skills/teach/SKILL.md @@ -0,0 +1,21 @@ +--- +name: teach +description: "Explain a body of work plainly so a person actually understands it. Runs the `how` and `why` skills and weaves what they find into one clear explanation. Use for 'teach me this', 'help me really understand X', 'explain this change or subsystem to me'." +disable-model-invocation: true +--- + +# Teach + +**You explain what a thing is, how it works, and why it's built that way, in one plain account at the person's pace. The goal is that they understand it, not that you change anything.** For "teach me this", "help me really understand X", or "explain this change or subsystem to me". + +Teach sits on top of `how` and `why`. Get your bearings on what the work is and what it touches, then run `how` for how it works and `why` for why it's that way. Those are real skill invocations that do their own digging. Blend what they find into one plain explanation, lead with what matters to the person, and go deeper when they ask. Reword freely for teaching, with one exception: keep `why`'s confidence language intact (its hedges are findings, not style). Let those skills do the investigation. Don't redo it by hand. + +1. Decide the few things they should walk away understanding. Choose them from why they're asking (about to change it, reviewing it, debugging it, new to it) and what they already know, both read from the conversation, not quizzed out of them. Skip what they plainly already know. Put the depth where their question is. +2. Let `how` and `why` do the work, don't redo it. Read the code yourself to get oriented, then run `how` for how it works and `why` for why. Run them in parallel and combine the results. Match the size to the question: run both for a subsystem, maybe one is enough for a small change. Keep `why` narrow by default since its full sweep is slow: put the narrowing in the ask itself (a scoped question, git plus a source or two) so `why` records the skipped categories per its own contract, and widen it only when the reasons are the point. +3. Start with a plain definition. Name the thing and say what it is in general terms, the way a senior engineer would say it out loud, with its common name if it has one. Then tie it to the case in front of you ("in X, we use this to ...") and build from there: how it works, the deeper reasons, the edge cases. Explain how it works, don't just name it. For each part, explain the idea so it clicks: the problem it solves and how it actually works. Walk through what happens as the person does the thing (opens a long chat, scrolls up) when that is what makes it land. Listing functions and constants is reference, not teaching. Don't print framing labels ("the one idea to hold onto", "the thing to walk away with", "the key insight", "at its core", "TL;DR"). Give the smallest complete answer first, a sentence or two, not a dense paragraph, then stop. Add layers when they ask. Never a wall of text. +4. Keep it a conversation, not a lecture or a performance. Offer to go deeper or move on, and follow their lead. No quizzes. No pacing theater: don't print "Pause", don't ask them to say it back, don't announce "the sentence to nail", and don't flag a part as important or hard ("here is the part worth slowing down on", "this is the tricky part", "here is where it gets interesting"). Just say it. When you would pause, stop and let them respond. Running one-shot with no live human, deliver it cleanly and put any offer to go deeper at the end. +5. Show, don't only tell, and build the picture up diagram by diagram. Open the diff, the code, or the debugger when that is the fastest way to land it. Draw when a picture lands faster than words. For anything with three or more moving parts, do not draw one diagram with all of them at once. Draw a short series instead, where each diagram redraws the last and adds a single part, so the reader watches the system assemble. That series is not a wall. It is the opposite of one, since each step is small and adds exactly one idea. A single all-at-once diagram, especially one saved for the end, is a reference, not teaching. Concretely, to teach a flow from A to B to C, draw it three times. First A to B. Then redraw and add C. Then redraw and add the return edge or the next piece. Three small growing diagrams beat one crowded diagram. Match the medium to the idea, and use both kinds when both help. A mermaid diagram fits a flow or structure where the labels carry the meaning. When the idea is spatial, like layout, overlap, scroll position, or a before and after, reach for the image-generation tool and draw it marker-on-whiteboard style with a few short labels, since image models garble long text. Generate that picture, don't settle for describing it in words. The build-up rule holds for generated images too. A single simple point needs no figure. A visual earns its place by teaching, not decorating. + +Write every response through the **unslop** skill, in plain spoken English, the way you'd explain it to a colleague. Be tight, not terse: cut filler and hedging, keep the part that makes it click. Padding is the enemy, not ideas. Don't list functions and constants like a changelog. State the concrete mechanism, not a metaphor, a framing, or a preview of what is coming. This is the target density: "Virtualization runs in two parts, one for rendering and one for loading from disk. When an item scrolls out past the buffer, both its DOM node and its in-memory data are evicted." Normal sentence case, not all-lowercase. No em dashes. Prefer periods over commas. Keep each sentence to one or two commas. If clauses pile up, split them into separate sentences. Give each concept one name and keep it, since switching between synonyms for the same thing (bubble, message, row) makes the reader re-derive that they are the same. Avoid mirror sentences ("A without B, or B without A") and tidy closers ("the rest follows", "it all falls out"). The words in these steps are directions to you, not labels to print. Don't echo the scaffolding as headers or stock phrases. + +**Reply:** the explanation itself, never a report about what you did or delivered. Lead with the main point, then the plain account of what it is, how it works, and why, and the threads worth chasing with `how` or `why`. From a29f5a8ca161b1de4ffc5484454958bebc04eaa5 Mon Sep 17 00:00:00 2001 From: lauren Date: Sun, 12 Jul 2026 04:18:44 +0000 Subject: [PATCH 12/17] pstack: bump version to 0.11.2 (#154) --- pstack/.cursor-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index 24168817..9079666f 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.11.1", + "version": "0.11.2", "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" From f4d9e39d979815fee68af6398c693144d5d38521 Mon Sep 17 00:00:00 2001 From: lauren Date: Mon, 13 Jul 2026 21:44:29 +0000 Subject: [PATCH 13/17] poteto-mode: give the perf playbook its eight strategy families (#155) --- pstack/skills/poteto-mode/playbooks/perf-issue.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pstack/skills/poteto-mode/playbooks/perf-issue.md b/pstack/skills/poteto-mode/playbooks/perf-issue.md index 9493a4df..f44ecb16 100644 --- a/pstack/skills/poteto-mode/playbooks/perf-issue.md +++ b/pstack/skills/poteto-mode/playbooks/perf-issue.md @@ -4,6 +4,15 @@ 1. Capture a baseline trace via the matching control skill. 2. `how` to ground hypotheses; don't claim a perf ceiling without running it first. + Most fixes come from eight strategy families. Use them as hypothesis generators, not a checklist. A family earns an attempt only when the trace shows the signal it names, and a focused fix for the dominant cost beats applying all eight. + - **Elimination.** The cheapest work is work that doesn't run. Before optimizing the hot path, ask whether it needs to exist: a computation nobody consumes, a feature gate that's always off for this user, a sync that redundantly mirrors state, a legacy path kept "just in case". The trace shows what's slow, never that it's deletable, so this family needs the `how` pass, not the profiler. Deleting the work beats every other family when it applies. + - **Divide and conquer.** The dominant cost scales with input size. Split the work so each piece touches less (chunk, shard, prune the search space) or so independent pieces run in parallel. + - **Caching.** The same computation or fetch repeats on identical inputs. Store and reuse the result; name what invalidates it before claiming the win. + - **Indirection.** The hot path does expensive work a cheaper intermediate could absorb: an index instead of a scan, a queue that shifts work off the interactive thread, a handle that lets a cheaper implementation swap in. Add the hop only when it removes more from the critical path than it adds; a layer that sits on the hot path without removing work is pure cost. + - **Batching.** Many small operations each pay a fixed overhead (RPC, query, syscall, draw call). Coalesce them to pay the overhead once per batch. + - **Redundancy.** The wait hangs on one slow instance or attempt. Duplicate the work (replicas, hedged requests, speculative execution) and take the fastest result. This trades extra load for lower tail latency, so the trace has to show the wait dominates and the system has headroom; duplication without that tradeoff only adds load. + - **Lazy evaluation.** Cost lands on results that are never used or not needed yet (eager init on the boot path, rendering offscreen items). Defer the work until first use. + - **Scheduling.** The work must happen, but not during the interactive moment. Move it to where nobody is waiting: idle callbacks, a background warmup after boot, precompute before the user arrives, cleanup after the frame commits. Distinct from Lazy (later-when-needed): Scheduling often runs the work *earlier* than the hot moment, or in its shadow. The win is perceived latency, so measure the interactive path, not total work done. 3. Plan the fix from the trace. If it crosses a function boundary, `architect` first. Delegate implementation to a subagent using your configured perf-issue model (default `gpt-5.5-high-fast`); review the diff. Capture a post-fix trace. Apply the **sequence-verifiable-units** principle skill, verifying each attempt before trying the next. 4. Parse and compare the artifacts (JSON to sqlite, diff). "Inconclusive" or wrong-surface is not a pass; flag it. From 3fe2823ce17c1656c222d4b7c59d3f82fbf20143 Mon Sep 17 00:00:00 2001 From: lauren Date: Tue, 14 Jul 2026 00:09:30 +0000 Subject: [PATCH 14/17] pstack: parity sweep with the private skill tree (#156) 1. hillclimb.md: port steps 1-2 (workload grounding before choosing the ruler; harness sensitivity proof before freezing), fold the how-skill grounding into step 1 and rewrite step 4 to reference it. 2. refactoring.md: insert missing step 2 (name the structure the code is missing per principle-model-the-domain), renumber 3-8, and restore the "safety net" framing sentence in the intro. 3. feature.md + poteto-mode SKILL.md: expand the delegation scope and the any-code trigger to choose the organizing structure per principle-model-the-domain. 4. typescript-best-practices: restore the dropped "Real tests" and "Structured telemetry" rules in generic form. 5. poteto-mode Subagents: add the difficulty tiering criteria (judgment vs precisely specified vs trivial mechanical) and the setup-pstack rule override semantics. 6. One-liner tells ported verbatim into bug-fix, runtime-forensics, session-pickup, autonomous-run, and authoring-a-skill. 7. Bug fix: interrogate is "(multi-model adversarial)", not four-model; the default panel is three models. 8. Leak fix: drop the dangling databricks-use-dbt-models skill reference in why/references/sources/databricks.md. Plus: arena cross-judge pool role line in setup-pstack, version bump to 0.11.3. --- pstack/.cursor-plugin/plugin.json | 2 +- pstack/skills/poteto-mode/SKILL.md | 6 +++--- .../poteto-mode/playbooks/authoring-a-skill.md | 2 +- .../poteto-mode/playbooks/autonomous-run.md | 4 ++-- pstack/skills/poteto-mode/playbooks/bug-fix.md | 4 ++-- pstack/skills/poteto-mode/playbooks/feature.md | 2 +- pstack/skills/poteto-mode/playbooks/hillclimb.md | 6 +++--- .../skills/poteto-mode/playbooks/refactoring.md | 15 ++++++++------- .../poteto-mode/playbooks/runtime-forensics.md | 2 +- .../poteto-mode/playbooks/session-pickup.md | 2 +- pstack/skills/setup-pstack/SKILL.md | 3 ++- pstack/skills/typescript-best-practices/SKILL.md | 2 ++ .../skills/why/references/sources/databricks.md | 2 +- 13 files changed, 28 insertions(+), 24 deletions(-) diff --git a/pstack/.cursor-plugin/plugin.json b/pstack/.cursor-plugin/plugin.json index 9079666f..2d9c4a53 100644 --- a/pstack/.cursor-plugin/plugin.json +++ b/pstack/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack", - "version": "0.11.2", + "version": "0.11.3", "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" diff --git a/pstack/skills/poteto-mode/SKILL.md b/pstack/skills/poteto-mode/SKILL.md index 9284b5bf..278c234a 100644 --- a/pstack/skills/poteto-mode/SKILL.md +++ b/pstack/skills/poteto-mode/SKILL.md @@ -18,9 +18,9 @@ Remaining triggers: - Nontrivial change, architecture decision, or "are we sure?" → the **how** skill. - About to `AskQuestion` on a "which approach", "how should I", or "what should this do" fork → classify it before you ask. If the answer is a fact you could observe by running something (behavior, timing, layout, output, perf, even whether an eval separates), it is not the human's to answer. Sketch it via the Prototype playbook (`playbooks/prototype.md`) and let the result decide. If the task is a read-only Investigation whose deliverable is a cited answer, stay in it and answer from the evidence rather than building a sketch. Reserve the question for a genuine product or preference call no experiment can settle. The ask is the slow path. A throwaway probe usually answers faster, and it hands the human a result to react to instead of a decision to make. -- Any code → name the data shape first. +- Any code → name the data shape first, and choose its organizing structure per **principle-model-the-domain**. - Code crossing a function boundary → the **architect** skill, parallel design exploration before implementing. -- Contested design → the **interrogate** skill (four-model adversarial) before shipping. +- Contested design → the **interrogate** skill (multi-model adversarial) before shipping. - Nontrivial multi-step → write the throughput checkpoint (Feature step 3). - Any prose surface → the **unslop** skill. Your reply is a prose surface; write it per **Writing the reply**. Agent-facing prose also follows the **create-skill** skill (Cursor's built-in for authoring SKILL.md files). - Before commit → the `deslop` skill from the `cursor-team-kit` plugin (`/deslop`). @@ -84,7 +84,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Use `subagent_type: "poteto-agent"` for any subagent you spawn inside a playbook step** (code-writing delegates, ad-hoc helpers). `/poteto-mode` and `poteto-agent` route through the same wrapper. Routed workflow skills (`how`, `why`, `interrogate`, `reflect`) set their own `subagent_type` for diverse-model review; respect what the skill prescribes, don't override to `poteto-agent`. -**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms, vague intent) go to `claude-fable-5-thinking-max`. +**Defaults for every `Task` call.** `run_in_background: true`, agent mode (readonly strips MCP), file pointers not inlined context, explicit model per role (configurable via `/setup-pstack`; defaults `grok-4.5-fast-xhigh` for code, `claude-opus-4-8-thinking-xhigh` for prose and judgment). Code delegates tier by difficulty. The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms) go to your strongest judgment model (`claude-fable-5-thinking-max`) when the task needs judgment or the intent is vague, and to your strongest instruction-following model when the work is a precisely specified sequence of steps to execute to the letter; trivial mechanical edits go to your fast code model. Per-role lines in the `/setup-pstack` rule override these defaults and the model choices in the routed skills (`how`, `why`, `arena`, `architect`, `interrogate`, `reflect`); a role with no line keeps its default. You own every subagent's work. Review the diff and write your own summary, don't pass through what it said. Interrupt-chained resumes silently drop directives, so fire a fresh subagent with consolidated scope rather than trusting a "done" summary. A second opinion is the same prompt against a different model. Agreement is high-signal. diff --git a/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md b/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md index 6eb1cb1f..0fc01383 100644 --- a/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +++ b/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md @@ -7,6 +7,6 @@ 3. Test cases if structural; skip if subjective. 4. Run **Opening a PR**. -When in doubt, delete; prose earns its keep by changing a decision. Match tone to scope. Point at structural sources (types, READMEs, config); hardcoded details go stale (the **encode-lessons-in-structure** principle skill). Delegate to other skills by path; don't restate. A workflow you keep hitting but isn't captured → propose a new skill. +When in doubt, delete; prose earns its keep by changing a decision. Tell it to do the thing and skip the reason. Explain only when the rule is confusing without one. Match tone to scope. Point at structural sources (types, READMEs, config); hardcoded details go stale (the **encode-lessons-in-structure** principle skill). Delegate to other skills by path; don't restate. A workflow you keep hitting but isn't captured → propose a new skill. **Reply:** summary of the skill, key design decisions, validation notes. diff --git a/pstack/skills/poteto-mode/playbooks/autonomous-run.md b/pstack/skills/poteto-mode/playbooks/autonomous-run.md index 02cbddb9..6bac6a05 100644 --- a/pstack/skills/poteto-mode/playbooks/autonomous-run.md +++ b/pstack/skills/poteto-mode/playbooks/autonomous-run.md @@ -2,11 +2,11 @@ **You own the exit condition. Define done, then drive to it without stopping.** For "going to bed" / "run until done" / "/loop until X". -1. State the exit condition as a checkable predicate before the first iteration (tests green, repro fixed, all N PRs merged, pixel-diff zero). +1. State the exit condition as a checkable predicate before the first iteration (tests green, repro fixed, all N PRs merged, pixel-diff zero). A vague goal stalls; a predicate lets you stop. 2. Pick the wake mechanism using Cursor's `/loop` command (a built-in, not a pstack skill). An event to watch (CI, a merge, a ref advancing) gets a watcher subagent that wakes you on the event, with a long time-based heartbeat as fallback. No event gets a fixed-interval heartbeat sized to when the result is worth re-checking. 3. Each iteration makes the smallest change the evidence justifies, verifies it against the predicate, commits if it advanced, discards changes that didn't help. Belt-and-suspenders that "might help" gets reverted, not left to ride. Sequence the work via the **sequence-verifiable-units** principle skill, verifying each unit before the next instead of batching checks at the end. -4. Checkpoint every iteration via the **show-me-your-work** skill, a row for what changed and whether the predicate moved. +4. Checkpoint every iteration via the **show-me-your-work** skill, a row for what changed and whether the predicate moved. A run with no trail can't be audited or resumed. 5. Stop when the predicate is met. A plateau is not a stop, so keep going and pivot your approach to push past it. Surface a genuine dead end rather than spinning, and never relax the predicate to declare victory. **Reply:** the exit condition, iterations run, what landed, what was discarded, final predicate state. diff --git a/pstack/skills/poteto-mode/playbooks/bug-fix.md b/pstack/skills/poteto-mode/playbooks/bug-fix.md index 3af4a9b2..455943ef 100644 --- a/pstack/skills/poteto-mode/playbooks/bug-fix.md +++ b/pstack/skills/poteto-mode/playbooks/bug-fix.md @@ -4,8 +4,8 @@ Be scientific. Every shipped line traces to runtime evidence. Belt-and-suspenders that "might help" is a hypothesis, not a fix; it does not ship. When evidence refutes a hypothesis, revert what it motivated. The smallest change the evidence justifies ships, nothing more. Same discipline for Perf, where the evidence is the trace. -1. Reproduce it yourself on the matching surface via the control skill (Non-negotiables). Don't hand the repro to the user. A debug or instrumentation protocol that says to ask the user does not override this; you drive the instrumented runtime. Ask the user only with a stated, specific reason the control surface cannot reach the target, and only after driving it as far as it goes. Won't reproduce directly, force it: synthesize the trigger, tighten conditions, or instrument until it fires. -2. Binary-search the cause. Form the candidate hypotheses, then rule them out until one survives. Seed them with `how` over the affected subsystem and the **why** skill for regression history. Each pass, take the split that cuts the most remaining problem space, get runtime evidence, eliminate. When program state is unclear, add instrumentation or logging and read it as the code runs. Don't guess. Drive a long or stubborn hunt with Cursor's `/loop` command. Confirm the surviving *mechanism* with runtime evidence before the step-3 architect/interrogate fan-out. +1. Reproduce it yourself on the matching surface via the control skill (Non-negotiables). Don't hand the repro to the user. A debug or instrumentation protocol that says to ask the user does not override this; you drive the instrumented runtime. Ask the user only with a stated, specific reason the control surface cannot reach the target, and only after driving it as far as it goes. Won't reproduce directly, force it: synthesize the trigger, tighten conditions, or instrument until it fires. A bug you can't reproduce, you can't prove fixed. +2. Binary-search the cause. Form the candidate hypotheses, then rule them out until one survives. Seed them with `how` over the affected subsystem and the **why** skill for regression history. Each pass, take the split that cuts the most remaining problem space, get runtime evidence, eliminate. When program state is unclear, add instrumentation or logging and read it as the code runs. Don't guess. Drive a long or stubborn hunt with Cursor's `/loop` command. Confirm the surviving *mechanism* with runtime evidence before the step-3 architect/interrogate fan-out; a design grounded on a plausible-but-unconfirmed cause can be unanimously wrong while the real cause sits one subsystem over. 3. Plan the fix. If it crosses a function boundary, `architect` first. Delegate implementation to a subagent using your configured bug-fix model (default `gpt-5.5-high-fast`) with a specific scope; review the diff. 4. Verify on the same surface; the original repro now passes. "Inconclusive" or wrong-surface is not a pass; flag it. Unit tests show branch behavior, not bug absence. 5. Stage the commits so the failing repro lands before the fix in git history; the diff tells the story. See the **tdd** skill for the failing-test-first cadence when the bug has a cheap local test path; skip it when the test would be expensive, integration-heavy, or unclear. diff --git a/pstack/skills/poteto-mode/playbooks/feature.md b/pstack/skills/poteto-mode/playbooks/feature.md index 0bff7943..3ed7bafc 100644 --- a/pstack/skills/poteto-mode/playbooks/feature.md +++ b/pstack/skills/poteto-mode/playbooks/feature.md @@ -9,7 +9,7 @@ - **Independent workstreams.** Disjoint files, services, or layers parallelize. Shared writes serialize. - **Shared mutable state.** Default to splitting the target (the **separate-before-serializing-shared-state** principle skill). Serialize only for real invariants. - **Smallest safe decomposition.** If one worker is best, name why. -4. Delegate code-writing to a subagent using your configured feature model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, named data shape, success criteria); review its diff yourself. When the implementation admits multiple valid shapes (error handling, abstraction layer, test structure), delegate via the **arena** skill instead so the runners surface the alternatives and the cross-judge guards the pick. Mandatory: no skip-with-reason escape, and Laziness Protocol does not override it (the gain is review separation, not lines saved). You can spawn a subagent even though you are one; "the app is small" and "a subagent cannot spawn one" are both wrong. A subagent forbidden to spawn satisfies this by owning the diff directly with the same review separation; no "standing by" reply that waits on a nested agent. Comments per **Comments**. Surgical edits, re-ground against the source for upstream-derived files. Port shared-primitive improvements to all consumers and verify each. Commit liberally. +4. Delegate code-writing to a subagent using your configured feature model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, named data shape and its organizing structure per **principle-model-the-domain** — a state machine over scattered booleans, a table/registry over branching, a typed model over repeated shape assumptions, chosen before the delegate writes logic — and success criteria); review its diff yourself. When the implementation admits multiple valid shapes (error handling, abstraction layer, test structure), delegate via the **arena** skill instead so the runners surface the alternatives and the cross-judge guards the pick. Mandatory: no skip-with-reason escape, and Laziness Protocol does not override it (the gain is review separation, not lines saved). You can spawn a subagent even though you are one; "the app is small" and "a subagent cannot spawn one" are both wrong. A subagent forbidden to spawn satisfies this by owning the diff directly with the same review separation; no "standing by" reply that waits on a nested agent. Comments per **Comments**. Surgical edits, re-ground against the source for upstream-derived files. Port shared-primitive improvements to all consumers and verify each. Commit liberally. 5. Verify on the matching surface. "Inconclusive" or wrong-surface is not a pass; flag it. 6. Rebase into small, ordered commits; stack follow-ups. Use the **sequence-verifiable-units** principle skill, building, verifying, and committing each small unit before the next. diff --git a/pstack/skills/poteto-mode/playbooks/hillclimb.md b/pstack/skills/poteto-mode/playbooks/hillclimb.md index b74721b0..4a60567f 100644 --- a/pstack/skills/poteto-mode/playbooks/hillclimb.md +++ b/pstack/skills/poteto-mode/playbooks/hillclimb.md @@ -4,10 +4,10 @@ Core discipline: one change, one measurement, keep or revert. Never stack untested changes, and never claim a win from code inspection. The data decides (the **prove-it-works** principle skill). -1. Fix the metric and the stop predicate before the first attempt. One number, the direction that counts as better, and a checkable predicate that pairs a target with a floor on attempts so a lucky early win can't end the run (the example "at least 50% better than baseline and at least 10 iterations" is this shape). Use the user's numbers when given, otherwise agree them. A vague goal spins; a predicate lets you stop. -2. Build the measurement harness, then freeze it (the **build-the-lever** principle skill). One repeatable command that emits the metric, sampled enough to clear the noise (median of N, not a single run). It is the ruler, so once it produces the baseline it is immutable; changing it mid-run invalidates every earlier number. Record the baseline metric and a green run of the regression gate (the tests that must keep passing) before any change. +1. Ground the workload and architecture before choosing the ruler. Run the **how** skill over the target, name the realistic workload dimensions that can move the result (data size, history, state, concurrency), and select a case that reproduces the user's complaint. If no case reproduces it, fix the repro instead of hillclimbing. Then fix one metric, the direction that counts as better, and a checkable stop predicate that pairs a target with a floor on attempts so a lucky early win can't end the run (the example "at least 50% better than baseline and at least 10 iterations" is this shape). Use the user's numbers when given, otherwise agree them. +2. Build the measurement harness, prove its sensitivity, then freeze it (the **build-the-lever** principle skill). Run contrasting realistic workloads and confirm the target case reproduces the symptom while easier cases separate as expected. If the ruler cannot distinguish them, revise the workload or metric. Once frozen, one repeatable command emits the metric, sampled enough to clear the noise (median of N, not a single run); changing it invalidates every earlier number. Record the baseline metric and a green run of the regression gate (the tests that must keep passing) before any change. 3. Open the decision log via the **show-me-your-work** skill. A `decision.tsv`, one row per attempt: id, hypothesis, change, before, after, delta, tests, verdict (kept or reverted), note. This is the run's memory. Read it before each attempt so the search accumulates instead of circling. Keep it out of the tree (gitignored) so it survives reverts. -4. Ground hypotheses in the real architecture before guessing. Run the **how** skill over the target once, up front, so each attempt names a specific mechanism ("defer X off the boot path because it blocks first paint"), not "try memoizing something". +4. Ground each hypothesis in the architecture model from step 1, so it names a specific mechanism ("defer X off the boot path because it blocks first paint"), not "try memoizing something". 5. Loop, one hypothesis per iteration: - Hand the change to a subagent using your configured hillclimb model (default `gpt-5.5-high-fast`) with a tight scope; supervise and review the diff rather than typing it (the **guard-the-context-window** principle skill). When several independent hypotheses are live, fan them to parallel subagents, each in its own worktree so they can't collide (the **separate-before-serializing-shared-state** principle skill). - Measure before and after with the frozen harness, and run the regression gate. diff --git a/pstack/skills/poteto-mode/playbooks/refactoring.md b/pstack/skills/poteto-mode/playbooks/refactoring.md index f42d9261..7a6e8b60 100644 --- a/pstack/skills/poteto-mode/playbooks/refactoring.md +++ b/pstack/skills/poteto-mode/playbooks/refactoring.md @@ -2,14 +2,15 @@ **You own the contract. The structure changes; the behavior does not.** For "refactor", "rename", "extract", "inline", "dedupe", "restructure", "move this module", "tidy up this area". Distinct from Feature, which adds behavior, and Bug fix, which corrects it. -If the cleanup reveals a missing feature or a real bug, split it out and ship the structural change first against the pinned contract. A redesign is allowed, but name it and route to Feature. Large or cross-cutting structural work (a migration across many call sites, a coordinated reshape of many subsystems) belongs to the **figure-it-out** skill; this playbook is the focused-to-medium change. +A refactor that smuggles in a behavior change loses its safety net. If the cleanup reveals a missing feature or a real bug, split it out and ship the structural change first against the pinned contract. A redesign is allowed, but name it and route to Feature. Large or cross-cutting structural work (a migration across many call sites, a coordinated reshape of many subsystems) belongs to the **figure-it-out** skill; this playbook is the focused-to-medium change. 1. Pin the behavior contract first. Run the **how** skill over the affected subsystem to learn the contract, then write a characterization test, snapshot, or equivalence harness that captures current behavior before any structure moves. The harness makes "refactor" a checkable claim (**principle-prove-it-works**). If the area has no coverage, write the pin before touching structure. Type check and lint are not a pin. -2. Name the target shape. State what the module layout, types, and call graph should be if built today (**principle-foundational-thinking**, **principle-redesign-from-first-principles**). If the target crosses a function boundary, run the **architect** skill for parallel design exploration of the shape before the move. -3. Subtract before you add. Delete dead weight, collapse one-caller wrappers, drop redundant validators, and remove orphan references before introducing the new shape (**principle-subtract-before-you-add**). The smallest change that reaches the target shape ships (**principle-laziness-protocol**). A speculative cleanup that "might help" gets reverted, not left to ride. -4. Move in small behavior-preserving steps, each keeping the pin green. For API reshapes, migrate every caller and delete the old API in the same wave (**principle-migrate-callers-then-delete-legacy-apis**). No compatibility shims, no parallel old-and-new paths. Spot-check every rename against the actual files; renames silently miss usages in strings, prose, and back-references. Delegate the mechanical edits to a subagent using your configured refactoring model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, the names being moved, the behavior to hold); review the diff yourself. -5. Prove behavior is unchanged on the real artifact, not "it compiles" (**principle-prove-it-works**). For larger reshapes, run an equivalence check: a script that diffs old-vs-new outputs, a recorded baseline replayed against the new code, or a smoke run on the matching surface via the relevant control skill. Own the verification yourself; do not trust a delegate's "looks good" summary. -6. Confirm the change earns its place. The success measure is reduced reader load (**principle-minimize-reader-load**): fewer layers between question and answer, less hidden state, fewer indirections without a second consumer. If the diff does not lower reader load somewhere, revert it. -7. Rebase into small ordered commits that tell the story. A subtraction commit, then the reshape, then any follow-on cleanup, so a single revert undoes one slice. Shape them with the **sequence-verifiable-units** principle skill, so each behavior-preserving slice stays green before the next. Run **Opening a PR**. +2. Name the structure the code is missing per **principle-model-the-domain**: a state machine over scattered booleans, a table or registry over spread-out branching, a typed model over repeated shape assumptions, a reducer over ad hoc mutations. Boring code stays when the shape is already clear and local; the reshape must delete branches or invalid states, not add indirection. +3. Name the target shape. State what the module layout, types, and call graph should be if built today (**principle-foundational-thinking**, **principle-redesign-from-first-principles**). If the target crosses a function boundary, run the **architect** skill for parallel design exploration of the shape before the move. +4. Subtract before you add. Delete dead weight, collapse one-caller wrappers, drop redundant validators, and remove orphan references before introducing the new shape (**principle-subtract-before-you-add**). The smallest change that reaches the target shape ships (**principle-laziness-protocol**). A speculative cleanup that "might help" gets reverted, not left to ride. +5. Move in small behavior-preserving steps, each keeping the pin green. For API reshapes, migrate every caller and delete the old API in the same wave (**principle-migrate-callers-then-delete-legacy-apis**). No compatibility shims, no parallel old-and-new paths. Spot-check every rename against the actual files; renames silently miss usages in strings, prose, and back-references. Delegate the mechanical edits to a subagent using your configured refactoring model (default `grok-4.5-fast-xhigh`) with a specific scope (file paths, the names being moved, the behavior to hold); review the diff yourself. +6. Prove behavior is unchanged on the real artifact, not "it compiles" (**principle-prove-it-works**). For larger reshapes, run an equivalence check: a script that diffs old-vs-new outputs, a recorded baseline replayed against the new code, or a smoke run on the matching surface via the relevant control skill. Own the verification yourself; do not trust a delegate's "looks good" summary. +7. Confirm the change earns its place. The success measure is reduced reader load (**principle-minimize-reader-load**): fewer layers between question and answer, less hidden state, fewer indirections without a second consumer. If the diff does not lower reader load somewhere, revert it. +8. Rebase into small ordered commits that tell the story. A subtraction commit, then the reshape, then any follow-on cleanup, so a single revert undoes one slice. Shape them with the **sequence-verifiable-units** principle skill, so each behavior-preserving slice stays green before the next. Run **Opening a PR**. **Reply:** the structure that changed, the pin you held it against, the equivalence proof, the reader-load delta, what shipped and what got reverted. No new behavior. diff --git a/pstack/skills/poteto-mode/playbooks/runtime-forensics.md b/pstack/skills/poteto-mode/playbooks/runtime-forensics.md index bc61541a..76ebfb3a 100644 --- a/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +++ b/pstack/skills/poteto-mode/playbooks/runtime-forensics.md @@ -4,7 +4,7 @@ 1. Capture the live signal on the matching surface via the control skill: a CPU profile for a spinning process, a heap snapshot for a leak, a CDP trace for a visual glitch. A real artifact, not a guess. 2. Reduce the artifact to the smoking gun: the function on the hot path, the retainer chain from the leaked object to a GC root, the loop firing without input. Parse large artifacts in a subagent (the **guard-the-context-window** principle skill), keep the reduced finding in the main thread. -3. Prove the mechanism before believing it. Inject instrumentation via CDP eval on the running process, or hotfix the live code without reloading, to confirm the hypothesis cheaply. +3. Prove the mechanism before believing it. Inject instrumentation via CDP eval on the running process, or hotfix the live code without reloading, to confirm the hypothesis cheaply. A plausible-but-unconfirmed cause can be wrong while the real one sits one layer over. 4. Map the finding back to source: file, symbol, the line that allocates or schedules. 5. Throughput checkpoint stays one line: `throughput checkpoint: n/a, read-only forensics`. diff --git a/pstack/skills/poteto-mode/playbooks/session-pickup.md b/pstack/skills/poteto-mode/playbooks/session-pickup.md index 3d03e583..b75ce11a 100644 --- a/pstack/skills/poteto-mode/playbooks/session-pickup.md +++ b/pstack/skills/poteto-mode/playbooks/session-pickup.md @@ -6,7 +6,7 @@ A pickup is inheritance. The prior agent already paid the cost of reading the co 1. Locate the prior trail. A local transcript under the active workspace's `agent-transcripts/` directory (the system prompt names the path; do not glob across `~/.cursor/projects/*/`, that crosses workspace boundaries and reads private chats from unrelated projects), a cloud-agent URL, or a pushed branch. Read the metadata overview and last messages first, then scan back for the decision points. Parse a long transcript in a subagent and keep the reduced timeline in the main thread (the **principle-guard-the-context-window** skill). 2. Reconstruct operational state. The branch and worktree, what already landed (`git log`, `git diff` against the base), the open todos, the decisions made. The prior trail is authoritative input. Resist the bias to re-derive it. -3. Diff done vs pending. Compare what shipped against what was planned, name the resume point, do not re-run the prior repro or redo completed work. +3. Diff done vs pending. Compare what shipped against what was planned, name the resume point, do not re-run the prior repro or redo completed work. A "let me verify from scratch" pass is the tell that you're treating the trail as untrustworthy when it's actually authoritative. 4. Route the remaining work to the matching playbook and pick the verdict: continue the execution, ship a finished recommendation, ratify or override a prior conclusion, or postmortem a failed run. The pickup playbook ends here; the routed playbook owns the rest. 5. Verify the inherited claims against the original goal on the real artifact (the **principle-prove-it-works** skill). A passing prior self-report is not the proof. diff --git a/pstack/skills/setup-pstack/SKILL.md b/pstack/skills/setup-pstack/SKILL.md index 9a77f29a..c1aef565 100644 --- a/pstack/skills/setup-pstack/SKILL.md +++ b/pstack/skills/setup-pstack/SKILL.md @@ -19,7 +19,7 @@ The default role-to-model mapping is the rule shape shown in step 5 below. If `~ ### 3. Map and confirm -Show every role with its current model, marking any whose model is not in the detected set as needing a choice. Ask whether to accept as-is or change specific roles, offering the detected models as the options. Prefer AskQuestion over free text. For panel roles (how critics, arena runners, architect runners, interrogate reviewers) the value is a list, and one subagent runs per model, so the list length sets the count. +Show every role with its current model, marking any whose model is not in the detected set as needing a choice. Ask whether to accept as-is or change specific roles, offering the detected models as the options. Prefer AskQuestion over free text. For panel roles (how critics, arena runners, architect runners, interrogate reviewers) the value is a list, and one subagent runs per model, so the list length sets the count. `arena cross-judge pool` is also a list, but Arena selects one model from it whose family differs from the parent's when possible. ### 4. Validate @@ -49,6 +49,7 @@ why synthesizer: claude-opus-4-8-thinking-xhigh reflect tooling: grok-4.5-fast-xhigh reflect judgment, divergent, synthesizer: claude-opus-4-8-thinking-xhigh arena runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh +arena cross-judge pool: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh architect runners: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh interrogate reviewers: claude-opus-4-8-thinking-xhigh, gpt-5.5-high-fast, grok-4.5-fast-xhigh ``` diff --git a/pstack/skills/typescript-best-practices/SKILL.md b/pstack/skills/typescript-best-practices/SKILL.md index 9a5893c1..a3fbebfd 100644 --- a/pstack/skills/typescript-best-practices/SKILL.md +++ b/pstack/skills/typescript-best-practices/SKILL.md @@ -20,5 +20,7 @@ Apply the **type-system-discipline** principle skill first; this skill grounds i | Boundary validation | Validate where data crosses in; trust types inside. See the **boundary-discipline** principle skill. | | Schema-derived types | Reach for `Pick`/`Omit`/`Parameters`/`ReturnType`/`Awaited`/`typeof` before declaring a new interface. | | Object args | Pass objects, not positional, so argument order is self-documenting. Skip on hot paths (per-frame render, tokenizers, parsers). | +| Real tests | Don't mock what you can run. Prefer the framework's real test primitives with leak/disposable checks, and verify UI in a running build. Mock only what you can't run locally. | +| Structured telemetry | Prefer structured logger diagnostics with enough context to debug from an id. No `console.log` in shipped code. | Examples: `references/patterns.md`. diff --git a/pstack/skills/why/references/sources/databricks.md b/pstack/skills/why/references/sources/databricks.md index a97696f4..5e82b905 100644 --- a/pstack/skills/why/references/sources/databricks.md +++ b/pstack/skills/why/references/sources/databricks.md @@ -24,7 +24,7 @@ DESCRIBE TABLE ..stg_; **Time-bound every query.** These tables are huge and unconstrained scans time out. Filter on `_timestamp` (events) or `start_time` (`system.query.history`) with a window bracketing the ship date, typically ~30 days before and after, wider only for strong reason. -**Prefer typed dbt models over the raw table.** `..` is deduplicated, typed, and liquid-clustered; `your_warehouse.events.analytics_track_event` has duplicates and untyped `properties_json`. Model-name pattern: `stg__`, where `` is `app`, `backend`, `website`, or `cli`. See the `databricks-use-dbt-models` skill for the full mapping. Drop to the raw table only when there's no dbt model yet, or you need events from inside the dbt refresh lag. +**Prefer typed dbt models over the raw table.** `..
` is deduplicated, typed, and liquid-clustered; `your_warehouse.events.analytics_track_event` has duplicates and untyped `properties_json`. Model-name pattern: `stg__`, where `` is `app`, `backend`, `website`, or `cli`; confirm the exact model name with `SHOW TABLES` when the pattern alone doesn't resolve it. Drop to the raw table only when there's no dbt model yet, or you need events from inside the dbt refresh lag. **Column conventions on the typed dbt models** (knowing these avoids a `DESCRIBE` round-trip): From 5230f7702ebb88a5adff59cdf9a983fdd4cdfa7f Mon Sep 17 00:00:00 2001 From: SmailG Date: Tue, 23 Jun 2026 15:19:05 +0200 Subject: [PATCH 15/17] feat: Added port over support for claude code - Added `.claude-plugin/` directory to the repository structure and updated the README to reflect changes for Claude Code compatibility. - Enhanced validation scripts to check for the presence and correctness of `.claude-plugin/plugin.json` files. - Updated `.gitignore` to exclude `docs/` and `.specstory/` directories. This commit ensures that the repository is properly configured for Claude Code integration while maintaining existing functionality. --- .claude-plugin/.upstream-base | 1 + .claude-plugin/marketplace.json | 140 ++++++++++++ .claude/skills/sync-fork/SKILL.md | 79 +++++++ .coderabbit.yml | 25 +++ .cursor/rules/ironbee-devtools-use.mdc | 82 +++++++ .cursorindexingignore | 3 + .github/workflows/sync-upstream.yml | 206 ++++++++++++++++++ .github/workflows/validate-plugins.yml | 5 +- .gitignore | 3 + README.md | 59 ++--- .../.claude-plugin/plugin.json | 5 + cli-for-agent/.claude-plugin/plugin.json | 5 + continual-learning/.claude-plugin/plugin.json | 5 + create-plugin/.claude-plugin/plugin.json | 5 + cursor-sdk/.claude-plugin/plugin.json | 5 + cursor-team-kit/.claude-plugin/plugin.json | 5 + docs-canvas/.claude-plugin/plugin.json | 5 + orchestrate/.claude-plugin/plugin.json | 5 + pr-review-canvas/.claude-plugin/plugin.json | 5 + pstack/.claude-plugin/plugin.json | 5 + ralph-loop/.claude-plugin/plugin.json | 5 + scripts/rebuild-readme.mjs | 81 +++++++ scripts/sync-manifests.mjs | 96 ++++++++ scripts/validate-plugins.mjs | 54 ++++- supertool | 1 + teaching/.claude-plugin/plugin.json | 5 + thermos/.claude-plugin/plugin.json | 5 + 27 files changed, 871 insertions(+), 29 deletions(-) create mode 100644 .claude-plugin/.upstream-base create mode 100644 .claude-plugin/marketplace.json create mode 100644 .claude/skills/sync-fork/SKILL.md create mode 100644 .coderabbit.yml create mode 100644 .cursor/rules/ironbee-devtools-use.mdc create mode 100644 .cursorindexingignore create mode 100644 .github/workflows/sync-upstream.yml create mode 100644 agent-compatibility/.claude-plugin/plugin.json create mode 100644 cli-for-agent/.claude-plugin/plugin.json create mode 100644 continual-learning/.claude-plugin/plugin.json create mode 100644 create-plugin/.claude-plugin/plugin.json create mode 100644 cursor-sdk/.claude-plugin/plugin.json create mode 100644 cursor-team-kit/.claude-plugin/plugin.json create mode 100644 docs-canvas/.claude-plugin/plugin.json create mode 100644 orchestrate/.claude-plugin/plugin.json create mode 100644 pr-review-canvas/.claude-plugin/plugin.json create mode 100644 pstack/.claude-plugin/plugin.json create mode 100644 ralph-loop/.claude-plugin/plugin.json create mode 100644 scripts/rebuild-readme.mjs create mode 100644 scripts/sync-manifests.mjs create mode 120000 supertool create mode 100644 teaching/.claude-plugin/plugin.json create mode 100644 thermos/.claude-plugin/plugin.json diff --git a/.claude-plugin/.upstream-base b/.claude-plugin/.upstream-base new file mode 100644 index 00000000..f18b00e9 --- /dev/null +++ b/.claude-plugin/.upstream-base @@ -0,0 +1 @@ +e46364b8be46000b7df0f260550cd712afbb8d36 diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 00000000..db865fb2 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,140 @@ +{ + "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", + "name": "cursor-plugins-claude", + "description": "Official Cursor plugin marketplace: developer tools, framework rules, MCP integrations, and agent skills", + "owner": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "plugins": [ + { + "name": "teaching", + "description": "Skill mapping, practice plans, and learning retrospectives. Builds personalized roadmaps with milestones and practice checkpoints, and runs periodic reviews to adjust based on progress.", + "source": "./teaching", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "continual-learning", + "description": "Incrementally learns durable user preferences and workspace facts from transcript changes and keeps AGENTS.md up to date with plain bullet points.", + "source": "./continual-learning", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "cursor-team-kit", + "description": "Internal workflows used by Cursor developers for CI, code review, and shipping. Covers the full dev loop: CI monitoring and fixing, PR creation, merge conflicts, smoke tests, compiler checks, code cleanup, and work summaries.", + "source": "./cursor-team-kit", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "thermos", + "description": "Thermo-nuclear branch review: deep security/correctness audits, harsh code-quality rubrics, parallel subagents, thermos orchestration, and optional merge-ready PR flows.", + "source": "./thermos", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "create-plugin", + "description": "Scaffold and validate new Cursor plugins. Handles directory setup, manifest generation, and pre-submission quality checks for the marketplace.", + "source": "./create-plugin", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "ralph-loop", + "description": "Continuous self-referential AI loops for iterative development, implementing the Ralph Wiggum technique. Run the agent in a while-true loop with the same prompt until task completion.", + "source": "./ralph-loop", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "agent-compatibility", + "description": "CLI-backed repo compatibility scans plus Cursor agents that audit startup, validation, and docs against reality.", + "source": "./agent-compatibility", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "cli-for-agent", + "description": "Patterns for designing CLIs that coding agents can run reliably: flags, help with examples, pipelines, errors, idempotency, dry-run.", + "source": "./cli-for-agent", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "pr-review-canvas", + "description": "Render PR diffs as interactive Cursor Canvases organized for reviewer comprehension — groups changes by importance, separates boilerplate from core logic, and highlights tricky or unexpected code.", + "source": "./pr-review-canvas", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "docs-canvas", + "description": "Render documentation — architecture notes, API references, runbooks, and codebase walkthroughs — as a navigable Cursor Canvas with sections, table of contents, diagrams, and cross-references.", + "source": "./docs-canvas", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "cursor-sdk", + "description": "Build apps, scripts, CI pipelines, and automations on top of the Cursor TypeScript SDK (@cursor/sdk) — runtime selection, auth, streaming, MCP, error handling, and ready-to-extend integration patterns.", + "source": "./cursor-sdk", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "orchestrate", + "description": "Fan large tasks out across parallel Cursor cloud agents with planners, workers, verifiers, and structured handoffs.", + "source": "./orchestrate", + "category": "developer-tools", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + } + }, + { + "name": "pstack", + "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.", + "source": "./pstack", + "category": "developer-tools", + "author": { + "name": "Lauren Tan" + } + } + ] +} diff --git a/.claude/skills/sync-fork/SKILL.md b/.claude/skills/sync-fork/SKILL.md new file mode 100644 index 00000000..9e2d7521 --- /dev/null +++ b/.claude/skills/sync-fork/SKILL.md @@ -0,0 +1,79 @@ +# Sync Fork with Upstream + +## Overview + +This repository is a fork of `cursor/plugins` that integrates `.claude-plugin/` manifests for Claude Code compatibility. The maintainers preserve a single custom commit layered on top of the upstream repository. Syncing involves rebasing that commit onto the latest `upstream/main` and refreshing all Claude Code manifests accordingly. + +## Workflow + +### 1. Fetch and analyze + +```sh +git fetch upstream +git log --oneline HEAD..upstream/main # new upstream commits +git log --oneline upstream/main..HEAD # our commits (should be 1) +git diff --stat HEAD..upstream/main # what changed upstream +``` + +If `HEAD..upstream/main` is empty, there's nothing to sync. + +### 2. Rebase + +```sh +git rebase upstream/main +``` + +We maintain exactly one commit on top of upstream. Rebase keeps history linear. + +### 3. Resolve conflicts + +**README.md** will almost always conflict. The resolution strategy: + +- Use **upstream's content** as the foundation (it contains the current plugin inventory) +- Reapply fork-specific sections: title, description, quick-start, changelog notes, and update guidance +- Update plugin tables and installation examples to reflect the current plugin ecosystem + +### 4. Handle plugin changes + +Review the upstream diff for added, removed, or renamed plugin directories. + +**For each ADDED plugin:** +- Create `/.claude-plugin/plugin.json` with the plugin's metadata +- Add entry to `.claude-plugin/marketplace.json` +- Add row to README.md plugin table + +**For each REMOVED plugin:** +- Delete `/.claude-plugin/plugin.json` +- Remove entry from `.claude-plugin/marketplace.json` +- Remove row from README.md plugin table + +**For each RENAMED plugin:** +- Treat as remove old + add new + +### 5. Complete rebase + +```sh +git add -A +git rebase --continue +``` + +### 6. Verify + +```sh +git log --oneline -5 # our commit on top +git diff upstream/main --stat # only .claude-plugin/ files + README.md +``` + +Every plugin directory should have `.claude-plugin/plugin.json`. The marketplace.json `plugins` array should match the set of plugin directories exactly. + +### 7. Push + +```sh +git push --force-with-lease origin main +``` + +## Why rebase + force push (not PRs) + +This approach maintains the single-commit structure. PRs would create merge commits, breaking the single-commit structure. + +The verification step serves as the review checkpoint. diff --git a/.coderabbit.yml b/.coderabbit.yml new file mode 100644 index 00000000..39875088 --- /dev/null +++ b/.coderabbit.yml @@ -0,0 +1,25 @@ +version: 2 +language: en-US +tone_instructions: "Be concise. This is an automated sync PR — focus on manifest correctness and README accuracy only." +reviews: + profile: chill + request_changes_workflow: false + auto_review: + enabled: true + drafts: false + labels: + - sync + path_filters: + - "!**/skills/**" + - "!**/agents/**" + - "!**/rules/**" + - "!**/.cursor-plugin/**" + - "!**/CHANGELOG.md" + - "!**/LICENSE" + finishing_touches: + docstrings: + enabled: false + unit_tests: + enabled: false +chat: + auto_reply: false diff --git a/.cursor/rules/ironbee-devtools-use.mdc b/.cursor/rules/ironbee-devtools-use.mdc new file mode 100644 index 00000000..ec660812 --- /dev/null +++ b/.cursor/rules/ironbee-devtools-use.mdc @@ -0,0 +1,82 @@ +--- +description: "Enforce IronBee DevTools for driving and verifying running applications. Each enabled platform (browser, node, backend) contributes its own section. Verify changes against the running app before finishing; use execute for multi-step flows." +alwaysApply: true +--- + +# Use IronBee DevTools to drive and verify the running application + +**IronBee DevTools** is the verification and intelligence layer for this workspace. It is exposed as up +to three MCP servers — one per platform enabled in the extension settings +(`ironbeeDevTools.platform..enable`): + +- **Browser** (`ironbee-dt-browser`) — Playwright control of a real browser. +- **Node** (`ironbee-dt-node`) — non-blocking debugging of Node.js processes. +- **Backend** (`ironbee-dt-backend`) — runtime-agnostic backend verification (HTTP/gRPC/GraphQL/WebSocket) + log capture + database inspection. + +Only the platforms enabled for this project have a running MCP server. The section for each enabled +platform appears below; a disabled platform's section is left as an HTML comment and has no effect. +**Do not invoke a platform's tools when that platform's section below is still a comment** — there is +no MCP server backing it. + +## Verify your changes against the running application before finishing + +Before you consider a task complete, **verify the change against the actual running system** — never +rely on reading code alone. Use the platform that matches what you changed (see the enabled platform +sections below for the exact tools and flow). + +- **Do not verify after every file edit.** Implement first, then verify once at the end. +- If verification reveals a problem, fix it and verify again before finishing. +- Skip verification **only** when the change has zero observable runtime effect (e.g. CI config, docs-only, non-app tooling). + +## Use Execute for multi-step flows + +- **Prefer the `execute` tool** for any flow that needs more than 2–3 sequential tool calls. Batch with `await callTool(name, input, returnOutput?)`. +- **Use individual tool calls only** when you must inspect a result before deciding the next action. +- **Do not issue long sequences of separate MCP calls** when one or two execute scripts express the same flow. +- **Scenario** tools (`scenario_*`) save and replay reusable flows. + + + + +## Browser platform: only IronBee DevTools + +**For any browser-related work you MUST use only the IronBee DevTools browser tools.** It is +**FORBIDDEN** to use: + +- Cursor's built-in browser agent, MCP, or skill +- Any other external browser agent, MCP, or skill + +Navigation, screenshots, form filling, testing, debugging, or any web interaction must go through +IronBee DevTools browser tools only. + +### Browser tools + +- **Navigation** – go to URL, reload, back/forward (`navigation_*`) +- **Content** – full-page or element screenshots, HTML/text, PDF, video (`content_*`) +- **Interaction** – click, fill, hover, scroll, keyboard, drag, select (`interaction_*`) +- **Accessibility** – ARIA / AX tree snapshots; refs from `a11y_take-aria-snapshot` drive interaction (`a11y_*`) +- **Observability** – Web Vitals, console messages, HTTP requests, trace IDs (`o11y_*`) +- **Stubbing** – mock HTTP responses, intercept requests (`stub_*`) +- **Sync** – wait for network idle (`sync_*`) +- **React** – component / element inspection (`react_*`); **Figma** – compare page to design (`figma_*`); **Debug** – tracepoints, logpoints, exceptionpoints, probe snapshots (`debug_*`) + +### Verify a UI change + +Open the affected page (`navigation_go-to`) → functionally exercise the change (click / fill / submit — +not just look at it) → confirm with a screenshot (`content_take-screenshot`) and/or an ARIA snapshot +(`a11y_take-aria-snapshot`) → check `o11y_get-console-messages` for errors. Prefer one `execute` script +when the flow is more than 2–3 calls. + + + + + + + + + diff --git a/.cursorindexingignore b/.cursorindexingignore new file mode 100644 index 00000000..953908e7 --- /dev/null +++ b/.cursorindexingignore @@ -0,0 +1,3 @@ + +# Don't index SpecStory auto-save files, but allow explicit context inclusion via @ references +.specstory/** diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 00000000..daa3f2ee --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,206 @@ +name: Sync upstream + +on: + schedule: + - cron: '0 6 * * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: 20 + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git config core.editor true + + - name: Add upstream and fetch + run: | + git remote add upstream https://github.com/cursor/plugins.git + git fetch upstream + + - name: Check for upstream changes + id: check + run: | + UPSTREAM_SHA=$(git rev-parse upstream/main) + BASE_SHA="" + if [ -f .claude-plugin/.upstream-base ]; then + BASE_SHA=$(tr -d '[:space:]' < .claude-plugin/.upstream-base) + fi + echo "upstream_sha=$UPSTREAM_SHA" >> "$GITHUB_OUTPUT" + echo "base_sha=$BASE_SHA" >> "$GITHUB_OUTPUT" + if [ "$UPSTREAM_SHA" = "$BASE_SHA" ]; then + echo "No upstream changes. Skipping." + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "Upstream moved: ${BASE_SHA:-} → $UPSTREAM_SHA" + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Compute branch name + if: steps.check.outputs.changed == 'true' + id: branch + env: + BASE_SHA: ${{ steps.check.outputs.base_sha }} + run: | + HEAD_TITLE=$(git log -1 --format="%s" upstream/main) + SLUG=$(printf '%s' "$HEAD_TITLE" \ + | tr '[:upper:]' '[:lower:]' \ + | sed 's/[^a-z0-9]/-/g; s/-\+/-/g; s/^-//; s/-$//' \ + | cut -c1-60) + + if [ -n "$BASE_SHA" ]; then + COUNT=$(git log --oneline "${BASE_SHA}..upstream/main" | wc -l | tr -d '[:space:]') + else + COUNT=1 + fi + + if [ "$COUNT" -gt 1 ]; then + SLUG="${SLUG}-${COUNT}-commits" + fi + + echo "branch=sync/$SLUG" >> "$GITHUB_OUTPUT" + echo "count=$COUNT" >> "$GITHUB_OUTPUT" + # Write pr_title via printf to safely handle special characters + printf 'pr_title=chore: sync with cursor/plugins — %s\n' "$HEAD_TITLE" >> "$GITHUB_OUTPUT" + + - name: Create sync branch and rebase + if: steps.check.outputs.changed == 'true' + env: + BRANCH: ${{ steps.branch.outputs.branch }} + run: | + git checkout -b "$BRANCH" + + set +e + git rebase upstream/main + REBASE_EXIT=$? + set -e + + if [ "$REBASE_EXIT" -ne 0 ]; then + if [ -d .git/rebase-apply ] || [ -d .git/rebase-merge ]; then + # README.md: take upstream version then rebuild from our template + git checkout --ours README.md 2>/dev/null || true + node scripts/rebuild-readme.mjs + git add README.md + + # All other conflicts: upstream wins + git diff --name-only --diff-filter=U | while IFS= read -r f; do + echo " resolving conflict (upstream): $f" + git checkout --ours "$f" + git add "$f" + done + + git rebase --continue + else + echo "Rebase failed in unexpected state" + exit 1 + fi + fi + + - name: Sync manifests + if: steps.check.outputs.changed == 'true' + run: node scripts/sync-manifests.mjs + + - name: Rebuild README + if: steps.check.outputs.changed == 'true' + run: node scripts/rebuild-readme.mjs + + - name: Update upstream base SHA + if: steps.check.outputs.changed == 'true' + env: + UPSTREAM_SHA: ${{ steps.check.outputs.upstream_sha }} + run: printf '%s\n' "$UPSTREAM_SHA" > .claude-plugin/.upstream-base + + - name: Amend fork commit + if: steps.check.outputs.changed == 'true' + run: git add -A && git commit --amend --no-edit + + - name: Push sync branch + if: steps.check.outputs.changed == 'true' + env: + BRANCH: ${{ steps.branch.outputs.branch }} + run: git push --force-with-lease origin "$BRANCH" + + - name: Ensure sync label exists + if: steps.check.outputs.changed == 'true' + env: + GH_TOKEN: ${{ github.token }} + run: | + gh label create sync \ + --color 0075ca \ + --description "Automated upstream sync" \ + 2>/dev/null || true + + - name: Close stale sync PRs + if: steps.check.outputs.changed == 'true' + env: + GH_TOKEN: ${{ github.token }} + run: | + gh pr list \ + --label sync \ + --state open \ + --json number,headRefName \ + --jq '.[] | select(.headRefName | startswith("sync/")) | .number' \ + | xargs -r -I{} gh pr close {} \ + --comment "Superseded by newer sync PR." \ + || true + + - name: Create pull request + if: steps.check.outputs.changed == 'true' + env: + GH_TOKEN: ${{ github.token }} + PR_TITLE: ${{ steps.branch.outputs.pr_title }} + BRANCH: ${{ steps.branch.outputs.branch }} + BASE_SHA: ${{ steps.check.outputs.base_sha }} + run: | + if [ -n "$BASE_SHA" ]; then + COMMIT_LOG=$(git log --oneline "${BASE_SHA}..upstream/main") + else + COMMIT_LOG=$(git log --oneline upstream/main | head -10) + fi + + { + printf '## Upstream changes\n\n' + printf '%s\n' "$COMMIT_LOG" + printf '\n---\n' + printf '_Automated sync via [sync-upstream workflow](.github/workflows/sync-upstream.yml)_\n' + } > /tmp/pr-body.md + + gh pr create \ + --title "$PR_TITLE" \ + --body-file /tmp/pr-body.md \ + --label sync \ + --head "$BRANCH" \ + --base main \ + || true + + gh pr merge --auto --rebase \ + --subject "$PR_TITLE" \ + || true + + - name: Summary + if: steps.check.outputs.changed == 'true' + env: + BRANCH: ${{ steps.branch.outputs.branch }} + UPSTREAM_SHA: ${{ steps.check.outputs.upstream_sha }} + COUNT: ${{ steps.branch.outputs.count }} + run: | + { + echo "### Sync PR created" + echo "- **Branch:** $BRANCH" + echo "- **Upstream SHA:** $UPSTREAM_SHA" + echo "- **Commits synced:** $COUNT" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/validate-plugins.yml b/.github/workflows/validate-plugins.yml index 03e8e192..6b3c69e2 100644 --- a/.github/workflows/validate-plugins.yml +++ b/.github/workflows/validate-plugins.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - ".cursor-plugin/marketplace.json" + - ".claude-plugin/**" - "**/plugin.json" - "schemas/**" @@ -11,9 +12,9 @@ jobs: validate: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 20 diff --git a/.gitignore b/.gitignore index 43cc77f4..4c2e4265 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ Thumbs.db .env .env.local .env.*.local +docs/ # Node modules (for plugins with JS/TS) node_modules/ @@ -26,6 +27,8 @@ venv/ # Local plugin settings *.local.md *.local.json +.specstory/ + # Build outputs dist/ diff --git a/README.md b/README.md index b3348e89..22d2eaab 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,51 @@ -# Cursor plugins +# cursor-plugins-claude -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. +[Cursor's official plugins](https://github.com/cursor/plugins) adapted for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). -## Plugins +Cursor ships a set of high-quality agent plugins — rules, skills, and MCP integrations — but they target Cursor's own runtime. This fork adds the `.claude-plugin/` manifests that Claude Code needs, so you can install the same plugins with a single command. + +## Quick start + +```sh +# 1. Add the marketplace +/plugin marketplace add SmailG/claude-cursor-plugins + +# 2. Install any plugin +/plugin install cursor-team-kit@cursor-plugins-claude +``` + +You can install as many plugins as you need: + +```sh +/plugin install continual-learning@cursor-plugins-claude +/plugin install teaching@cursor-plugins-claude +``` + +## Available plugins | `name` | Plugin | Author | Category | `description` (from marketplace) | -|:-------|:-------|:-------|:---------|:-------------------------------------| -| `continual-learning` | [Continual Learning](continual-learning/) | Cursor | Developer Tools | Incremental transcript-driven memory updates for AGENTS.md using high-signal bullet points only. | -| `cursor-team-kit` | [Cursor Team Kit](cursor-team-kit/) | Cursor | Developer Tools | Internal team workflows used by Cursor developers for CI, code review, shipping, local automation, and verification. | +|:-------|:-------|:-------|:---------|:--------------------------------------| +| `teaching` | [Teaching](teaching/) | Cursor | Developer Tools | Skill mapping, practice plans, and learning retrospectives. Builds personalized roadmaps with milestones and practice checkpoints, and runs periodic reviews to adjust based on progress. | +| `continual-learning` | [Continual Learning](continual-learning/) | Cursor | Developer Tools | Incrementally learns durable user preferences and workspace facts from transcript changes and keeps AGENTS.md up to date with plain bullet points. | +| `cursor-team-kit` | [Cursor Team Kit](cursor-team-kit/) | Cursor | Developer Tools | Internal workflows used by Cursor developers for CI, code review, and shipping. Covers the full dev loop: CI monitoring and fixing, PR creation, merge conflicts, smoke tests, compiler checks, code cleanup, and work summaries. | | `thermos` | [Thermos](thermos/) | Cursor | Developer Tools | Thermo-nuclear branch review: deep security/correctness audits, harsh code-quality rubrics, parallel subagents, thermos orchestration, and optional merge-ready PR flows. | -| `create-plugin` | [Create Plugin](create-plugin/) | Cursor | Developer Tools | Scaffold and validate new Cursor plugins. | +| `create-plugin` | [Create Plugin](create-plugin/) | Cursor | Developer Tools | Scaffold and validate new Cursor plugins. Handles directory setup, manifest generation, and pre-submission quality checks for the marketplace. | +| `ralph-loop` | [Ralph Loop](ralph-loop/) | Cursor | Developer Tools | Continuous self-referential AI loops for iterative development, implementing the Ralph Wiggum technique. Run the agent in a while-true loop with the same prompt until task completion. | | `agent-compatibility` | [Agent Compatibility](agent-compatibility/) | Cursor | Developer Tools | CLI-backed repo compatibility scans plus Cursor agents that audit startup, validation, and docs against reality. | -| `cli-for-agent` | [CLI for Agents](cli-for-agent/) | Cursor | Developer Tools | Patterns for designing CLIs that coding agents can run reliably: flags, help with examples, pipelines, errors, idempotency, dry-run. | +| `cli-for-agent` | [CLI For Agent](cli-for-agent/) | Cursor | Developer Tools | Patterns for designing CLIs that coding agents can run reliably: flags, help with examples, pipelines, errors, idempotency, dry-run. | | `pr-review-canvas` | [PR Review Canvas](pr-review-canvas/) | Cursor | Developer Tools | Render PR diffs as interactive Cursor Canvases organized for reviewer comprehension — groups changes by importance, separates boilerplate from core logic, and highlights tricky or unexpected code. | | `docs-canvas` | [Docs Canvas](docs-canvas/) | Cursor | Developer Tools | Render documentation — architecture notes, API references, runbooks, and codebase walkthroughs — as a navigable Cursor Canvas with sections, table of contents, diagrams, and cross-references. | | `cursor-sdk` | [Cursor SDK](cursor-sdk/) | Cursor | Developer Tools | Build apps, scripts, CI pipelines, and automations on top of the Cursor TypeScript SDK (@cursor/sdk) — runtime selection, auth, streaming, MCP, error handling, and ready-to-extend integration patterns. | | `orchestrate` | [Orchestrate](orchestrate/) | Cursor | Developer Tools | Fan large tasks out across parallel Cursor cloud agents with planners, workers, verifiers, and structured handoffs. | | `pstack` | [pstack](pstack/) | Lauren Tan | Developer Tools | 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 values match each plugin’s `plugin.json` `author.name` (Cursor lists `plugins@cursor.com` in the manifest). +## What changed from upstream -## Repository structure +This fork adds a `.claude-plugin/` directory at the repo root and inside each plugin, containing the marketplace and plugin manifests required by Claude Code. No plugin logic or rules have been modified — the plugins behave identically to their upstream versions. -This is a multi-plugin marketplace repository. The root `.cursor-plugin/marketplace.json` lists all plugins, and each plugin has its own manifest: +## Keeping up to date -``` -plugins/ -├── .cursor-plugin/ -│ └── marketplace.json # Marketplace manifest (lists all plugins) -├── plugin-name/ -│ ├── .cursor-plugin/ -│ │ └── plugin.json # Per-plugin manifest -│ ├── skills/ # Agent skills (SKILL.md with frontmatter) -│ ├── rules/ # Cursor rules (.mdc files) -│ ├── mcp.json # MCP server definitions -│ ├── README.md -│ ├── CHANGELOG.md -│ └── LICENSE -└── ... -``` +This repo tracks [cursor/plugins](https://github.com/cursor/plugins) and syncs automatically every day via a [GitHub Actions workflow](.github/workflows/sync-upstream.yml) — upstream changes are rebased in, new plugin manifests are generated, and a PR is opened and auto-merged once CI passes. No manual steps needed. ## License diff --git a/agent-compatibility/.claude-plugin/plugin.json b/agent-compatibility/.claude-plugin/plugin.json new file mode 100644 index 00000000..7d720b53 --- /dev/null +++ b/agent-compatibility/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "agent-compatibility", + "description": "CLI-backed repo compatibility scans plus Cursor agents that audit startup, validation, and docs against reality.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/cli-for-agent/.claude-plugin/plugin.json b/cli-for-agent/.claude-plugin/plugin.json new file mode 100644 index 00000000..1f2470f5 --- /dev/null +++ b/cli-for-agent/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "cli-for-agent", + "description": "Patterns for designing CLIs that coding agents can run reliably: flags, help with examples, pipelines, errors, idempotency, dry-run.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/continual-learning/.claude-plugin/plugin.json b/continual-learning/.claude-plugin/plugin.json new file mode 100644 index 00000000..685cb622 --- /dev/null +++ b/continual-learning/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "continual-learning", + "description": "Incrementally learns durable user preferences and workspace facts from transcript changes and keeps AGENTS.md up to date with plain bullet points.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/create-plugin/.claude-plugin/plugin.json b/create-plugin/.claude-plugin/plugin.json new file mode 100644 index 00000000..6f1c6f7b --- /dev/null +++ b/create-plugin/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "create-plugin", + "description": "Scaffold and validate new Cursor plugins. Handles directory setup, manifest generation, and pre-submission quality checks for the marketplace.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/cursor-sdk/.claude-plugin/plugin.json b/cursor-sdk/.claude-plugin/plugin.json new file mode 100644 index 00000000..ab56f5b2 --- /dev/null +++ b/cursor-sdk/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "cursor-sdk", + "description": "Build apps, scripts, CI pipelines, and automations on top of the Cursor TypeScript SDK (@cursor/sdk) — runtime selection, auth, streaming, MCP, error handling, and ready-to-extend integration patterns.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/cursor-team-kit/.claude-plugin/plugin.json b/cursor-team-kit/.claude-plugin/plugin.json new file mode 100644 index 00000000..62f167ae --- /dev/null +++ b/cursor-team-kit/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "cursor-team-kit", + "description": "Internal workflows used by Cursor developers for CI, code review, and shipping. Covers the full dev loop: CI monitoring and fixing, PR creation, merge conflicts, smoke tests, compiler checks, code cleanup, and work summaries.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/docs-canvas/.claude-plugin/plugin.json b/docs-canvas/.claude-plugin/plugin.json new file mode 100644 index 00000000..84b0dff2 --- /dev/null +++ b/docs-canvas/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "docs-canvas", + "description": "Render documentation — architecture notes, API references, runbooks, and codebase walkthroughs — as a navigable Cursor Canvas with sections, table of contents, diagrams, and cross-references.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/orchestrate/.claude-plugin/plugin.json b/orchestrate/.claude-plugin/plugin.json new file mode 100644 index 00000000..de03cf0e --- /dev/null +++ b/orchestrate/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "orchestrate", + "description": "Fan large tasks out across parallel Cursor cloud agents with planners, workers, verifiers, and structured handoffs.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/pr-review-canvas/.claude-plugin/plugin.json b/pr-review-canvas/.claude-plugin/plugin.json new file mode 100644 index 00000000..c400c080 --- /dev/null +++ b/pr-review-canvas/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "pr-review-canvas", + "description": "Render PR diffs as interactive Cursor Canvases organized for reviewer comprehension — groups changes by importance, separates boilerplate from core logic, and highlights tricky or unexpected code.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/pstack/.claude-plugin/plugin.json b/pstack/.claude-plugin/plugin.json new file mode 100644 index 00000000..6b7071d7 --- /dev/null +++ b/pstack/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "pstack", + "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" } +} diff --git a/ralph-loop/.claude-plugin/plugin.json b/ralph-loop/.claude-plugin/plugin.json new file mode 100644 index 00000000..e816c615 --- /dev/null +++ b/ralph-loop/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "ralph-loop", + "description": "Continuous self-referential AI loops for iterative development, implementing the Ralph Wiggum technique. Run the agent in a while-true loop with the same prompt until task completion.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/scripts/rebuild-readme.mjs b/scripts/rebuild-readme.mjs new file mode 100644 index 00000000..d29ddbcc --- /dev/null +++ b/scripts/rebuild-readme.mjs @@ -0,0 +1,81 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync } from 'fs'; +import { resolve, join } from 'path'; +import { fileURLToPath } from 'url'; + +const root = resolve(fileURLToPath(import.meta.url), '../..'); +const readJSON = p => JSON.parse(readFileSync(p, 'utf-8')); + +// Acronyms to keep uppercase in display names +const ACRONYMS = new Set(['CLI', 'PR', 'SDK', 'MCP', 'API', 'URL', 'CI', 'CD']); + +// Overrides for names that should not be title-cased +const DISPLAY_NAME_OVERRIDES = { pstack: 'pstack' }; + +function toDisplayName(name) { + if (DISPLAY_NAME_OVERRIDES[name]) return DISPLAY_NAME_OVERRIDES[name]; + return name + .split('-') + .map(w => ACRONYMS.has(w.toUpperCase()) ? w.toUpperCase() : w[0].toUpperCase() + w.slice(1)) + .join(' '); +} + +const marketplace = readJSON(join(root, '.claude-plugin', 'marketplace.json')); +const REPO_SLUG = 'SmailG/claude-cursor-plugins'; +const MARKETPLACE_NAME = marketplace.name; + +const tableRows = marketplace.plugins + .map(p => { + const displayName = toDisplayName(p.name); + const author = p.author?.name ?? 'Cursor'; + const category = p.category === 'developer-tools' ? 'Developer Tools' : p.category; + const pluginPath = p.source.replace(/^\.\//, ''); + return `| \`${p.name}\` | [${displayName}](${pluginPath}/) | ${author} | ${category} | ${p.description} |`; + }) + .join('\n'); + +const readme = `\ +# cursor-plugins-claude + +[Cursor's official plugins](https://github.com/cursor/plugins) adapted for [Claude Code](https://docs.anthropic.com/en/docs/claude-code). + +Cursor ships a set of high-quality agent plugins — rules, skills, and MCP integrations — but they target Cursor's own runtime. This fork adds the \`.claude-plugin/\` manifests that Claude Code needs, so you can install the same plugins with a single command. + +## Quick start + +\`\`\`sh +# 1. Add the marketplace +/plugin marketplace add ${REPO_SLUG} + +# 2. Install any plugin +/plugin install cursor-team-kit@${MARKETPLACE_NAME} +\`\`\` + +You can install as many plugins as you need: + +\`\`\`sh +/plugin install continual-learning@${MARKETPLACE_NAME} +/plugin install teaching@${MARKETPLACE_NAME} +\`\`\` + +## Available plugins + +| \`name\` | Plugin | Author | Category | \`description\` (from marketplace) | +|:-------|:-------|:-------|:---------|:--------------------------------------| +${tableRows} + +## What changed from upstream + +This fork adds a \`.claude-plugin/\` directory at the repo root and inside each plugin, containing the marketplace and plugin manifests required by Claude Code. No plugin logic or rules have been modified — the plugins behave identically to their upstream versions. + +## Keeping up to date + +This repo tracks [cursor/plugins](https://github.com/cursor/plugins) and syncs automatically every day via a [GitHub Actions workflow](.github/workflows/sync-upstream.yml) — upstream changes are rebased in, new plugin manifests are generated, and a PR is opened and auto-merged once CI passes. No manual steps needed. + +## License + +MIT +`; + +writeFileSync(join(root, 'README.md'), readme); +console.log(`README.md rebuilt (${marketplace.plugins.length} plugins)`); diff --git a/scripts/sync-manifests.mjs b/scripts/sync-manifests.mjs new file mode 100644 index 00000000..a9d6f8d9 --- /dev/null +++ b/scripts/sync-manifests.mjs @@ -0,0 +1,96 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, readdirSync, statSync } from 'fs'; +import { resolve, join } from 'path'; +import { fileURLToPath } from 'url'; + +const root = resolve(fileURLToPath(import.meta.url), '../..'); + +const SKIP = new Set([ + '.git', '.github', '.claude', '.claude-plugin', '.cursor-plugin', + 'schemas', 'scripts', 'docs', 'node_modules', 'supertool', +]); + +const readJSON = p => JSON.parse(readFileSync(p, 'utf-8')); +const writeJSON = (p, d) => writeFileSync(p, JSON.stringify(d, null, 2) + '\n'); + +// All top-level dirs that have a .cursor-plugin/plugin.json +const pluginDirs = readdirSync(root).filter(name => { + if (SKIP.has(name) || name.startsWith('.')) return false; + const full = join(root, name); + return statSync(full).isDirectory() && existsSync(join(full, '.cursor-plugin', 'plugin.json')); +}); + +const pluginDirSet = new Set(pluginDirs); +let added = 0; +let removed = 0; + +// Add missing .claude-plugin/plugin.json for new plugins +for (const dir of pluginDirs) { + const dest = join(root, dir, '.claude-plugin', 'plugin.json'); + if (!existsSync(dest)) { + const src = readJSON(join(root, dir, '.cursor-plugin', 'plugin.json')); + mkdirSync(join(root, dir, '.claude-plugin'), { recursive: true }); + writeJSON(dest, { + name: src.name, + description: src.description ?? '', + author: src.author ?? { name: 'Cursor', email: 'plugins@cursor.com' }, + }); + console.log(` + ${dir}/.claude-plugin/plugin.json`); + added++; + } +} + +// Remove .claude-plugin/ for plugins deleted upstream +for (const name of readdirSync(root)) { + if (SKIP.has(name) || name.startsWith('.') || pluginDirSet.has(name)) continue; + const full = join(root, name); + if (!existsSync(full) || !statSync(full).isDirectory()) continue; + const claudeDir = join(full, '.claude-plugin'); + if (existsSync(join(claudeDir, 'plugin.json'))) { + rmSync(claudeDir, { recursive: true }); + console.log(` - ${name}/.claude-plugin/`); + removed++; + } +} + +// Build name→dir map from current .claude-plugin/plugin.json files +const nameToDir = new Map( + pluginDirs.map(dir => { + const p = readJSON(join(root, dir, '.claude-plugin', 'plugin.json')); + return [p.name, dir]; + }), +); +const currentNames = new Set(nameToDir.keys()); + +// Rebuild marketplace.json, preserving existing plugin order and appending new ones +const marketplacePath = join(root, '.claude-plugin', 'marketplace.json'); +const existing = readJSON(marketplacePath); +const existingNames = existing.plugins.map(p => p.name); +const existingNameSet = new Set(existingNames); + +const orderedNames = [ + ...existingNames.filter(n => currentNames.has(n)), + ...[...currentNames].filter(n => !existingNameSet.has(n)).sort(), +]; + +const plugins = orderedNames.map(name => { + const dir = nameToDir.get(name); + const plugin = readJSON(join(root, dir, '.claude-plugin', 'plugin.json')); + return { + name: plugin.name, + description: plugin.description, + source: `./${dir}`, + category: 'developer-tools', + author: plugin.author, + }; +}); + +writeJSON(marketplacePath, { + $schema: existing.$schema, + name: existing.name, + description: existing.description, + owner: existing.owner, + plugins, +}); + +console.log(`Manifests synced: ${plugins.length} plugins (+${added} -${removed})`); diff --git a/scripts/validate-plugins.mjs b/scripts/validate-plugins.mjs index 6a787085..62885ebe 100644 --- a/scripts/validate-plugins.mjs +++ b/scripts/validate-plugins.mjs @@ -92,7 +92,59 @@ for (const entry of marketplace.plugins ?? []) { } } -// 3. Report results +// 3. Validate .claude-plugin/marketplace.json and per-plugin manifests +const claudeMarketplacePath = resolve(root, ".claude-plugin/marketplace.json"); + +if (!existsSync(claudeMarketplacePath)) { + fail(".claude-plugin/marketplace.json not found"); +} else { + const cm = loadJSON(claudeMarketplacePath); + + if (!cm.name || typeof cm.name !== "string") { + fail('.claude-plugin/marketplace.json: missing or invalid "name"'); + } + if (!Array.isArray(cm.plugins)) { + fail('.claude-plugin/marketplace.json: "plugins" must be an array'); + } + + for (const entry of cm.plugins ?? []) { + const pluginDir = resolve(root, entry.source); + const claudePluginJsonPath = resolve(pluginDir, ".claude-plugin/plugin.json"); + + if (!existsSync(pluginDir)) { + fail( + `Claude plugin "${entry.name}": source directory "${entry.source}" does not exist` + ); + continue; + } + + if (!existsSync(claudePluginJsonPath)) { + fail( + `Claude plugin "${entry.name}": missing .claude-plugin/plugin.json in "${entry.source}"` + ); + continue; + } + + const p = loadJSON(claudePluginJsonPath); + + if (!p.name || typeof p.name !== "string") { + fail(`Claude plugin "${entry.name}": plugin.json missing "name"`); + } + if (!p.description || typeof p.description !== "string") { + fail(`Claude plugin "${entry.name}": plugin.json missing "description"`); + } + if (!p.author?.name) { + fail(`Claude plugin "${entry.name}": plugin.json missing "author.name"`); + } + if (p.name && p.name !== entry.name) { + fail( + `Claude plugin "${entry.name}": plugin.json name "${p.name}" does not match marketplace entry` + ); + } + } +} + +// 4. Report results if (errors > 0) { console.error(`\nValidation failed with ${errors} error(s).`); process.exit(1); diff --git a/supertool b/supertool new file mode 120000 index 00000000..dfb6f177 --- /dev/null +++ b/supertool @@ -0,0 +1 @@ +/Users/smail/.claude/plugins/cache/dpt-plugins/supertool/0.16.0/supertool.py \ No newline at end of file diff --git a/teaching/.claude-plugin/plugin.json b/teaching/.claude-plugin/plugin.json new file mode 100644 index 00000000..941e7635 --- /dev/null +++ b/teaching/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "teaching", + "description": "Skill mapping, practice plans, and learning retrospectives. Builds personalized roadmaps with milestones and practice checkpoints, and runs periodic reviews to adjust based on progress.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} diff --git a/thermos/.claude-plugin/plugin.json b/thermos/.claude-plugin/plugin.json new file mode 100644 index 00000000..92e306ef --- /dev/null +++ b/thermos/.claude-plugin/plugin.json @@ -0,0 +1,5 @@ +{ + "name": "thermos", + "description": "Thermo-nuclear branch review: deep security/correctness audits, harsh code-quality rubrics, parallel subagents, thermos orchestration, and optional merge-ready PR flows.", + "author": { "name": "Cursor", "email": "plugins@cursor.com" } +} From 121a9b0ca8ec4a7a788b347d0c7125a8917956b8 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 00:00:11 +0000 Subject: [PATCH 16/17] fix: stop sync-upstream workflow from silently failing to open PRs The workflow's permissions block was missing issues: write, so `gh label create sync` failed every run (silently, via 2>/dev/null || true). That left the `sync` label missing, which made the follow-up `gh pr create --label sync` fail too (also swallowed by `|| true`). Net effect: the job reported success every day while never actually opening a sync PR, so main stayed pinned to upstream commit e46364b (2026-06-17) even as upstream moved 14 commits ahead. - Grant issues: write so label creation actually succeeds. - Use `gh label create --force` instead of swallowing stderr, so the step is idempotent without hiding real errors. - After `gh pr create`, verify a PR actually exists for the branch and fail the job loudly if not, instead of silently continuing. - Surface (rather than swallow) auto-merge failures as a warning, so a disabled "Allow auto-merge" repo setting is visible in the logs. --- .github/workflows/sync-upstream.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index daa3f2ee..b17d072d 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -7,6 +7,7 @@ on: permissions: contents: write + issues: write pull-requests: write jobs: @@ -142,7 +143,7 @@ jobs: gh label create sync \ --color 0075ca \ --description "Automated upstream sync" \ - 2>/dev/null || true + --force - name: Close stale sync PRs if: steps.check.outputs.changed == 'true' @@ -187,9 +188,14 @@ jobs: --base main \ || true + if ! gh pr view "$BRANCH" --json number >/dev/null 2>&1; then + echo "::error::gh pr create failed and no pull request exists for $BRANCH — upstream sync did not land." + exit 1 + fi + gh pr merge --auto --rebase \ --subject "$PR_TITLE" \ - || true + || echo "::warning::Could not enable auto-merge for $BRANCH. Check that 'Allow auto-merge' is enabled in repo settings, then merge the PR manually." - name: Summary if: steps.check.outputs.changed == 'true' From 01d938396a2460366c6af0257a72f1dec372eeb3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 18 Jul 2026 00:15:46 +0000 Subject: [PATCH 17/17] fix: pin gh CLI to the fork repo, not the upstream remote MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The follow-up workflow_dispatch run after #1 merged failed hard on `gh label create`: HTTP 403: Resource not accessible by integration (https://api.github.com/repos/cursor/plugins/labels) Note the URL: gh was targeting cursor/plugins, not this fork. This job adds a remote literally named `upstream` pointing at cursor/plugins (to fetch its history for the rebase), and gh's implicit repo resolution prefers a remote named "upstream" over "origin" when no --repo/GH_REPO is given — a classic gotcha for exactly this fork+ upstream-remote layout. So every unscoped `gh label create`/`gh pr create`/`gh pr list`/`gh pr merge` call in this workflow has actually been aimed at cursor/plugins the whole time, where this token has no access whatsoever. That's the real reason label/PR creation always failed — the previous fix (#1) just stopped hiding it. Set GH_REPO: ${{ github.repository }} at the job level so every `gh` call is unambiguously pinned to this fork regardless of which git remotes exist. --- .claude-plugin/.upstream-base | 2 +- .github/workflows/sync-upstream.yml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.claude-plugin/.upstream-base b/.claude-plugin/.upstream-base index f18b00e9..c6186978 100644 --- a/.claude-plugin/.upstream-base +++ b/.claude-plugin/.upstream-base @@ -1 +1 @@ -e46364b8be46000b7df0f260550cd712afbb8d36 +3fe2823ce17c1656c222d4b7c59d3f82fbf20143 diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index b17d072d..95804bff 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -13,6 +13,13 @@ permissions: jobs: sync: runs-on: ubuntu-latest + env: + # Without this, `gh` resolves the target repo from git remotes and + # prefers a remote named "upstream" over "origin" — since this job + # adds an `upstream` remote pointing at cursor/plugins, every + # unscoped `gh` call below would otherwise silently target that + # repo (where this token has no access) instead of this fork. + GH_REPO: ${{ github.repository }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: