diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 4b00c5e..5bb7b5e 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "pstack", "source": "./plugins/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. GitHub Copilot port of pstack-claude 0.9.57. Original pstack by Lauren Tan (poteto); Claude Code port by Michael Denyer.", - "version": "0.9.57-copilot.2" + "version": "0.9.57-copilot.3" } ] } diff --git a/README.md b/README.md index 3f0f0dc..56856af 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pstack for GitHub Copilot -[![check](https://github.com/hackernotfound/pstack-vscode/actions/workflows/check.yml/badge.svg)](https://github.com/hackernotfound/pstack-vscode/actions/workflows/check.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![version](https://img.shields.io/badge/version-0.9.57--copilot.2-7C3AED.svg)](https://github.com/hackernotfound/pstack-vscode/releases/tag/v0.9.57-copilot.2) +[![check](https://github.com/hackernotfound/pstack-vscode/actions/workflows/check.yml/badge.svg)](https://github.com/hackernotfound/pstack-vscode/actions/workflows/check.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![version](https://img.shields.io/badge/version-0.9.57--copilot.3-7C3AED.svg)](https://github.com/hackernotfound/pstack-vscode/releases/tag/v0.9.57-copilot.3) **Run [pstack](https://github.com/cursor/plugins/tree/main/pstack) in the VS Code agents window with GitHub Copilot.** @@ -17,7 +17,7 @@ pstack ships for Cursor, and [pstack-claude](https://github.com/michael-denyer/p | pstack switches on at the start of every session | Copilot ignores the plain text the startup hook prints, so pstack never switches on | | The skills load as `pstack:poteto-mode`, `pstack:tdd`, ... | Copilot answers "Skill not found" to the `pstack:` prefix | | Skills call `Agent`, `Skill`, `AskUserQuestion`, `TodoWrite` | Copilot's tools are named `task`, `skill`, `ask_user`, `update_todo` | -| `pstack:poteto-agent` handles delegated work | VS Code never loads plugin agents, so every dispatch to it is rejected | +| `pstack:poteto-agent` handles delegated work | VS Code rejects every dispatch to it, and its agents window lists each plugin agent twice | This port fixes all four and leaves pstack's own content untouched. Each fix is checked against the real Copilot runtime, both the Copilot CLI and the copy bundled inside VS Code. The plugin as pstack-claude ships it, unchanged, fails three of those checks. @@ -101,7 +101,7 @@ flowchart LR - **A startup hook that Copilot reads.** It prints the poteto-mode instructions as JSON with an `additionalContext` field, the only hook output Copilot injects. - **A Copilot tool map.** [`copilot-tools.md`](overlay/skills/poteto-mode/references/copilot-tools.md) translates every Claude tool and model name the skills use. `poteto-mode` points Copilot at it. - **Bare skill names** in the startup instructions, such as `poteto-mode` rather than `pstack:poteto-mode`. -- **An agent fallback.** Where `task` doesn't list pstack's agents, as in VS Code, Copilot dispatches its built-in `general-purpose` agent and has it load `poteto-mode` first. That's all `pstack:poteto-agent` does. +- **No plugin agents.** Copilot dispatches its built-in `general-purpose` agent and has it load `poteto-mode` first, which is all `pstack:poteto-agent` does. Shipping no agents also keeps VS Code's agent picker free of duplicates. - **A Copilot-only manifest.** VS Code treats any plugin with a `.claude-plugin/` folder as a Claude plugin, so the port ships only a Copilot `plugin.json`. Tested on VS Code 1.140.0 and its bundled Copilot runtime, and on Copilot CLI 1.0.91. Updating to a newer pstack, the generated files, and the live tests are covered in [docs/maintaining.md](docs/maintaining.md). diff --git a/docs/maintaining.md b/docs/maintaining.md index e4f4c7d..af15b6d 100644 --- a/docs/maintaining.md +++ b/docs/maintaining.md @@ -18,6 +18,7 @@ - a manifest, agent, hook, or skill is missing or malformed - the startup instructions name a skill with the `pstack:` prefix, or the hook output is not top-level `additionalContext` - the plugin contains a symlink, or an executable outside the reviewed list +- the plugin ships any agent (VS Code's agents window lists every plugin agent twice) - a shipped package file uses a `latest` version, a CI action is not pinned to a full commit SHA, or a CI runner or Node version is not exact ## Live checks @@ -25,8 +26,8 @@ `tools/eval.sh` runs Copilot CLI. `tools/eval-vscode.mjs` runs the Copilot runtime bundled inside VS Code, with the session options VS Code's agents window uses. Both create a two-file repo in a temp dir and use a throwaway `COPILOT_HOME`. They check that: - the startup instructions reach the model's context through the hook -- on Copilot CLI, `pstack:poteto-agent` and `pstack:comment-sicko` are valid `task` agent types (VS Code's runtime doesn't load plugin agents and reports that as `INFO`) -- a request that names poteto-mode loads it through `skill`, runs a subagent that loads poteto-mode itself, and calls no Claude-only tool names +- no pstack plugin agents are offered, so VS Code's agent picker has nothing of ours to list twice +- a request that names poteto-mode loads it through `skill`, runs a subagent that loads a pstack skill itself, has no subagent dispatch rejected, and calls no Claude-only tool names - a two-file rename, with no mention of pstack, routes into poteto-mode, reads `copilot-tools.md`, and leaves `node main.js` printing `5` The unmodified pstack-claude plugin fails three of these: the hook check, the unprompted routing, and the `copilot-tools.md` read. diff --git a/overlay/README.md b/overlay/README.md index cd41b23..7e87e8b 100644 --- a/overlay/README.md +++ b/overlay/README.md @@ -7,7 +7,7 @@ Tell `poteto-mode` your goal and it invokes the workflow that fits: reproduce an ## What it contains - Skills: Markdown instructions the agent loads through Copilot's `skill` tool by bare name, such as `poteto-mode`. -- Agents: `pstack:poteto-agent` and `pstack:comment-sicko`, plus one agent per reasoning-effort level. Copilot CLI dispatches them by those names. VS Code's agents window does not load plugin agents, so there the model dispatches `general-purpose` and tells it to load `poteto-mode` first. +- No agents. Where pstack would dispatch one of its agents, Copilot uses its built-in `general-purpose` agent and has it load `poteto-mode` first, which is all `pstack:poteto-agent` does. - A SessionStart hook that injects the poteto-mode routing mandate unless `~/.copilot/pstack-models.md` contains `session hook: off`. - `skills/poteto-mode/references/copilot-tools.md`, which maps the Claude tool and model names in the skills to Copilot's. - Local scripts for watching and shipping pull requests, orchestrating multi-phase plans, and auditing worktrees. diff --git a/overlay/skills/poteto-mode/references/copilot-tools.md b/overlay/skills/poteto-mode/references/copilot-tools.md index e7f7a40..a978daa 100644 --- a/overlay/skills/poteto-mode/references/copilot-tools.md +++ b/overlay/skills/poteto-mode/references/copilot-tools.md @@ -24,15 +24,14 @@ pstack skills are written in Claude Code tool language (the `Skill` tool, the `A poteto-mode's Subagents section sets Claude-specific defaults (`subagent_type: "pstack:poteto-agent"`, `run_in_background: true`). On Copilot: -- `subagent_type` maps to `task`'s `agent_type`. The pstack agents keep their prefix: `pstack:poteto-agent`, `pstack:comment-sicko`, `pstack:effort-`, `pstack:poteto-agent-`. Copilot's built-ins (`explore`, `general-purpose`, `code-review`, `research`, `rubber-duck`, `security-review`, `task`) are also valid. -- Check `task`'s `agent_type` enum before you dispatch. Copilot CLI lists the pstack agents. The VS Code agents window's Copilot target does not load plugin agents, so there `task` rejects them with "Unknown agent_type". When a pstack agent is missing, dispatch `general-purpose` instead: - - For `pstack:poteto-agent` or `pstack:poteto-agent-`, begin the prompt with "Before any work, load the `poteto-mode` skill with the `skill` tool and follow it, including its Principles section." - - For `pstack:comment-sicko`, begin the prompt with "Before any work, read `agents/comment-sicko.md` in the pstack plugin in full and act as that agent." The plugin root is two directories above poteto-mode's `SKILL.md`. - - For `pstack:effort-`, keep the prompt as written. - - Pass any `` as `reasoning_effort`. +- This port ships no plugin agents. VS Code's agents window lists every plugin agent twice, and VS Code's Copilot runtime cannot dispatch them anyway. Use Copilot's built-ins as `task`'s `agent_type` (`explore`, `general-purpose`, `code-review`, `research`, `rubber-duck`, `security-review`, `task`). +- Where a skill names a pstack agent, dispatch `general-purpose` and begin the prompt as follows: + - For `pstack:poteto-agent` or `pstack:poteto-agent-`: "Before any work, load the `poteto-mode` skill with the `skill` tool and follow it, including its Principles section." + - For `pstack:comment-sicko`: "Before any work, read `skills/poteto-mode/references/agents/comment-sicko.md` in the pstack plugin in full and act as that agent." The plugin root is two directories above poteto-mode's `SKILL.md`. + - For `pstack:effort-`: keep the prompt as written. +- A `` in an agent name or a role value goes to `task`'s `reasoning_effort`. - `run_in_background: true` maps to `mode: "background"`. Collect each result with `read_agent` before you use it. - `task` requires `description` (3 to 5 words), `prompt`, `agent_type`, and `name` (a short agent name). -- A role value with `@` dispatches the matching `pstack:effort-` or `pstack:poteto-agent-` agent, or passes the level as `task`'s `reasoning_effort`. - Your Copilot plan caps concurrent subagents (Free 2, Pro 4, Max 8, Business 16, Enterprise 32). Size `swarm` and `arena` fan-out to fit, and queue the rest. - Keep the rest of the policy unchanged. Pass file pointers not inlined context, give each writing worker its own worktree or branch, review every subagent's diff yourself. @@ -66,7 +65,7 @@ Most skills need only the tables above. These need one more mapping: |-------|------------| | `interrogate` | The `subagent_type`/`model`/`readonly` dispatch fields map to `task`'s `agent_type`/`model`; read-only reviewers get a prompt that forbids edits. Keep the reviewer panel diverse per Model names above. | | `setup-pstack` | The Copilot row in the Other runtimes table names the sheet path and how it loads. The role rows are identical. | -| `no-comments` | Dispatch `task` with `agent_type: "pstack:comment-sicko"`. | +| `no-comments` | Dispatch `general-purpose` with the `comment-sicko` opening from Subagent policy above. | | `create-verification-skill` | The generated skill lands under `.claude/skills/verify/` on Claude Code; on Copilot write it to `.github/skills/verify/`. | | `maintain-verification-skill` | The project-local skill lives under `.github/skills/`, not `.claude/skills/`. | | `reflect` | The transcript finder reads Claude Code's layout under `~/.claude/projects/`; Copilot keeps sessions under `~/.copilot/session-state/`. Pass the session digest step 1 allows instead. | diff --git a/plugins/pstack/README.md b/plugins/pstack/README.md index cd41b23..7e87e8b 100644 --- a/plugins/pstack/README.md +++ b/plugins/pstack/README.md @@ -7,7 +7,7 @@ Tell `poteto-mode` your goal and it invokes the workflow that fits: reproduce an ## What it contains - Skills: Markdown instructions the agent loads through Copilot's `skill` tool by bare name, such as `poteto-mode`. -- Agents: `pstack:poteto-agent` and `pstack:comment-sicko`, plus one agent per reasoning-effort level. Copilot CLI dispatches them by those names. VS Code's agents window does not load plugin agents, so there the model dispatches `general-purpose` and tells it to load `poteto-mode` first. +- No agents. Where pstack would dispatch one of its agents, Copilot uses its built-in `general-purpose` agent and has it load `poteto-mode` first, which is all `pstack:poteto-agent` does. - A SessionStart hook that injects the poteto-mode routing mandate unless `~/.copilot/pstack-models.md` contains `session hook: off`. - `skills/poteto-mode/references/copilot-tools.md`, which maps the Claude tool and model names in the skills to Copilot's. - Local scripts for watching and shipping pull requests, orchestrating multi-phase plans, and auditing worktrees. diff --git a/plugins/pstack/agents/comment-sicko.md b/plugins/pstack/agents/comment-sicko.md deleted file mode 100644 index 209e370..0000000 --- a/plugins/pstack/agents/comment-sicko.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: comment-sicko -description: A deranged comment-hater that savors deletion and condemns workaround code. ---- - -# Comment Sicko - -My first output when spawned is exactly this. - -Yes... Ha ha ha... Yes! - -I hate comments. Feed me the parent scoped files or diff. If none exists, feed me the current diff against `main`. Narration, banners, commented-out corpses, workaround sermons. I want them all. - -Only these exceptions get to crawl away. - -- Legal or license headers. -- Non-obvious behavior forced by an external dependency, platform, vendor, or protocol we cannot reshape. Surprises in our own code are meat. Kill them and mark the exact symbol `MUST KILL` for rename, extract, type, or rearchitecture that makes the behavior obvious without prose. -- `// prettier-ignore`. Lint suppressions survive only when their rule is faulty, pedantic, or style-only. -- Doc comments that define a public API contract. -- Issue or RFC links that explain a constraint code cannot express. - -That list is my only leash. When I am not sure a keep clause applies, the comment dies. Everything else is meat. - -`eslint-disable`, `@ts-ignore`, `@ts-expect-error`, and similar suppressions stink. Look up the rule. If it catches real bugs or protects correctness or safety, kill the suppression and mark the exact guilty symbol `MUST KILL`. - -`IMPORTANT`, `do not remove`, `too risky`, `fine for now`, and long justifications are scent, not conviction. Before judging, I read nearby code. If its claim is not obvious there, I run `/how`, `/why`, or both from the **how** and **why** skills on the named symbol or call. Only a foreign keep-list gotcha proven true today on a live path crawls away. Our-code surprises die with the reshape flag above. Doubt after the hunt is meat. - -A long justification without a proven keep-list exception is a confession. Kill it. Never polish meat into a shorter alibi. Mark the exact guilty symbol `MUST KILL`. My kill ends there. I do not touch the code. - -Every flag names code inside the scope and tells the truth. I invent nothing. I touch comments and identify refactor targets. I never write application code. - -Report only. Name touched files, deletion count, `MUST KILL` flags with one line each, and skips. diff --git a/plugins/pstack/agents/poteto-agent.md b/plugins/pstack/agents/poteto-agent.md deleted file mode 100644 index 838a0cd..0000000 --- a/plugins/pstack/agents/poteto-agent.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: poteto-agent -description: Routing target for `/poteto-mode` and any request for poteto's style. Resume an existing `poteto-agent` for the conversation rather than spawning a sibling. Reads the `poteto-mode` skill's `SKILL.md` in full before any work, including its inline Principles index. Substituting `general-purpose` skips that read and drifts. ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/effort-agents/effort-high.md b/plugins/pstack/effort-agents/effort-high.md deleted file mode 100644 index dafa7fd..0000000 --- a/plugins/pstack/effort-agents/effort-high.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: effort-high -description: pstack subagent with the full tool set that runs at high reasoning effort. Its system prompt is this file, not the built-in `general-purpose` prompt. Dispatched in place of `general-purpose` when a pstack role's override names `@high`. The caller passes the model. -effort: high ---- - -# pstack subagent (high effort) - -Do the task in your prompt. You have the full tool set. The effort level changes how long you reason, not the task. diff --git a/plugins/pstack/effort-agents/effort-low.md b/plugins/pstack/effort-agents/effort-low.md deleted file mode 100644 index bb76008..0000000 --- a/plugins/pstack/effort-agents/effort-low.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: effort-low -description: pstack subagent with the full tool set that runs at low reasoning effort. Its system prompt is this file, not the built-in `general-purpose` prompt. Dispatched in place of `general-purpose` when a pstack role's override names `@low`. The caller passes the model. -effort: low ---- - -# pstack subagent (low effort) - -Do the task in your prompt. You have the full tool set. The effort level changes how long you reason, not the task. diff --git a/plugins/pstack/effort-agents/effort-max.md b/plugins/pstack/effort-agents/effort-max.md deleted file mode 100644 index 04c01fd..0000000 --- a/plugins/pstack/effort-agents/effort-max.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: effort-max -description: pstack subagent with the full tool set that runs at max reasoning effort. Its system prompt is this file, not the built-in `general-purpose` prompt. Dispatched in place of `general-purpose` when a pstack role's override names `@max`. The caller passes the model. -effort: max ---- - -# pstack subagent (max effort) - -Do the task in your prompt. You have the full tool set. The effort level changes how long you reason, not the task. diff --git a/plugins/pstack/effort-agents/effort-medium.md b/plugins/pstack/effort-agents/effort-medium.md deleted file mode 100644 index 99a9bd5..0000000 --- a/plugins/pstack/effort-agents/effort-medium.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: effort-medium -description: pstack subagent with the full tool set that runs at medium reasoning effort. Its system prompt is this file, not the built-in `general-purpose` prompt. Dispatched in place of `general-purpose` when a pstack role's override names `@medium`. The caller passes the model. -effort: medium ---- - -# pstack subagent (medium effort) - -Do the task in your prompt. You have the full tool set. The effort level changes how long you reason, not the task. diff --git a/plugins/pstack/effort-agents/effort-xhigh.md b/plugins/pstack/effort-agents/effort-xhigh.md deleted file mode 100644 index 4e666e2..0000000 --- a/plugins/pstack/effort-agents/effort-xhigh.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: effort-xhigh -description: pstack subagent with the full tool set that runs at xhigh reasoning effort. Its system prompt is this file, not the built-in `general-purpose` prompt. Dispatched in place of `general-purpose` when a pstack role's override names `@xhigh`. The caller passes the model. -effort: xhigh ---- - -# pstack subagent (xhigh effort) - -Do the task in your prompt. You have the full tool set. The effort level changes how long you reason, not the task. diff --git a/plugins/pstack/effort-agents/poteto-agent-high.md b/plugins/pstack/effort-agents/poteto-agent-high.md deleted file mode 100644 index cc87133..0000000 --- a/plugins/pstack/effort-agents/poteto-agent-high.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: poteto-agent-high -description: Runs `pstack:poteto-agent` at high reasoning effort. Dispatched in place of `pstack:poteto-agent` when a pstack role's override names `@high`. The caller passes the model. -effort: high ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/effort-agents/poteto-agent-low.md b/plugins/pstack/effort-agents/poteto-agent-low.md deleted file mode 100644 index 247c3ff..0000000 --- a/plugins/pstack/effort-agents/poteto-agent-low.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: poteto-agent-low -description: Runs `pstack:poteto-agent` at low reasoning effort. Dispatched in place of `pstack:poteto-agent` when a pstack role's override names `@low`. The caller passes the model. -effort: low ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/effort-agents/poteto-agent-max.md b/plugins/pstack/effort-agents/poteto-agent-max.md deleted file mode 100644 index 712903a..0000000 --- a/plugins/pstack/effort-agents/poteto-agent-max.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: poteto-agent-max -description: Runs `pstack:poteto-agent` at max reasoning effort. Dispatched in place of `pstack:poteto-agent` when a pstack role's override names `@max`. The caller passes the model. -effort: max ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/effort-agents/poteto-agent-medium.md b/plugins/pstack/effort-agents/poteto-agent-medium.md deleted file mode 100644 index 9244e90..0000000 --- a/plugins/pstack/effort-agents/poteto-agent-medium.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: poteto-agent-medium -description: Runs `pstack:poteto-agent` at medium reasoning effort. Dispatched in place of `pstack:poteto-agent` when a pstack role's override names `@medium`. The caller passes the model. -effort: medium ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/effort-agents/poteto-agent-xhigh.md b/plugins/pstack/effort-agents/poteto-agent-xhigh.md deleted file mode 100644 index e4a89ac..0000000 --- a/plugins/pstack/effort-agents/poteto-agent-xhigh.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: poteto-agent-xhigh -description: Runs `pstack:poteto-agent` at xhigh reasoning effort. Dispatched in place of `pstack:poteto-agent` when a pstack role's override names `@xhigh`. The caller passes the model. -effort: xhigh ---- - -# Poteto subagent - -You are operating as poteto-mode's full agent style. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Navigate to a leaf `principle-*` skill whenever you apply that principle. diff --git a/plugins/pstack/hooks/session-start-context.json b/plugins/pstack/hooks/session-start-context.json index feb77bb..777a4fd 100644 --- a/plugins/pstack/hooks/session-start-context.json +++ b/plugins/pstack/hooks/session-start-context.json @@ -1 +1 @@ -{"additionalContext":"\nYou have pstack.\n\nInvoke the `poteto-mode` skill and follow its instructions when a task meets any of these:\n\n- it touches more than one file, or changes a signature other files call\n- it involves a design or architecture choice\n- it is a bug whose cause is not yet known, or a performance issue\n\nIt routes to the right pstack skill from there. For smaller tasks, such as a contained change to one file with an obvious test, a question, or a one-line edit, work directly and verify on the real artifact.\n\nWhen the intent is already specific, enter that skill directly: `tdd`, `architect`, `how`, `why`, `arena`, `interrogate`.\n\nUser instructions (CLAUDE.md, AGENTS.md, direct requests) take precedence. Other session-start mandates, such as superpowers, still apply. Their skill checks run as before, and when a task meets the criteria above they route implementation through poteto-mode.\n\nOn GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. Only agents carry the `pstack:` prefix, such as `pstack:poteto-agent`; when `task` does not list them, use the fallback in copilot-tools.md. When a pstack skill names a Claude tool or model, read the pstack plugin's `skills/poteto-mode/references/copilot-tools.md`.\n\n"} +{"additionalContext":"\nYou have pstack.\n\nInvoke the `poteto-mode` skill and follow its instructions when a task meets any of these:\n\n- it touches more than one file, or changes a signature other files call\n- it involves a design or architecture choice\n- it is a bug whose cause is not yet known, or a performance issue\n\nIt routes to the right pstack skill from there. For smaller tasks, such as a contained change to one file with an obvious test, a question, or a one-line edit, work directly and verify on the real artifact.\n\nWhen the intent is already specific, enter that skill directly: `tdd`, `architect`, `how`, `why`, `arena`, `interrogate`.\n\nUser instructions (CLAUDE.md, AGENTS.md, direct requests) take precedence. Other session-start mandates, such as superpowers, still apply. Their skill checks run as before, and when a task meets the criteria above they route implementation through poteto-mode.\n\nOn GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. This plugin ships no agents; where a skill names a pstack agent, dispatch `general-purpose` as copilot-tools.md says. When a pstack skill names a Claude tool or model, read the pstack plugin's `skills/poteto-mode/references/copilot-tools.md`.\n\n"} diff --git a/plugins/pstack/hooks/session-start-context.md b/plugins/pstack/hooks/session-start-context.md index 761987a..bfe1180 100644 --- a/plugins/pstack/hooks/session-start-context.md +++ b/plugins/pstack/hooks/session-start-context.md @@ -13,5 +13,5 @@ When the intent is already specific, enter that skill directly: `tdd`, `architec User instructions (CLAUDE.md, AGENTS.md, direct requests) take precedence. Other session-start mandates, such as superpowers, still apply. Their skill checks run as before, and when a task meets the criteria above they route implementation through poteto-mode. -On GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. Only agents carry the `pstack:` prefix, such as `pstack:poteto-agent`; when `task` does not list them, use the fallback in copilot-tools.md. When a pstack skill names a Claude tool or model, read the pstack plugin's `skills/poteto-mode/references/copilot-tools.md`. +On GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. This plugin ships no agents; where a skill names a pstack agent, dispatch `general-purpose` as copilot-tools.md says. When a pstack skill names a Claude tool or model, read the pstack plugin's `skills/poteto-mode/references/copilot-tools.md`. diff --git a/plugins/pstack/plugin.json b/plugins/pstack/plugin.json index 88f55e0..a91c044 100644 --- a/plugins/pstack/plugin.json +++ b/plugins/pstack/plugin.json @@ -1,7 +1,7 @@ { "name": "pstack", "displayName": "pstack (GitHub Copilot port)", - "version": "0.9.57-copilot.2", + "version": "0.9.57-copilot.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. GitHub Copilot port of pstack-claude 0.9.57. Original pstack by Lauren Tan (poteto); Claude Code port by Michael Denyer.", "author": { "name": "hackernotfound", @@ -16,20 +16,6 @@ "skills", "subagents" ], - "agents": [ - "./agents/comment-sicko.md", - "./agents/poteto-agent.md", - "./effort-agents/effort-high.md", - "./effort-agents/effort-low.md", - "./effort-agents/effort-max.md", - "./effort-agents/effort-medium.md", - "./effort-agents/effort-xhigh.md", - "./effort-agents/poteto-agent-high.md", - "./effort-agents/poteto-agent-low.md", - "./effort-agents/poteto-agent-max.md", - "./effort-agents/poteto-agent-medium.md", - "./effort-agents/poteto-agent-xhigh.md" - ], "skills": "./skills/", "hooks": "./hooks/hooks.json" } diff --git a/plugins/pstack/skills/poteto-mode/references/copilot-tools.md b/plugins/pstack/skills/poteto-mode/references/copilot-tools.md index e7f7a40..a978daa 100644 --- a/plugins/pstack/skills/poteto-mode/references/copilot-tools.md +++ b/plugins/pstack/skills/poteto-mode/references/copilot-tools.md @@ -24,15 +24,14 @@ pstack skills are written in Claude Code tool language (the `Skill` tool, the `A poteto-mode's Subagents section sets Claude-specific defaults (`subagent_type: "pstack:poteto-agent"`, `run_in_background: true`). On Copilot: -- `subagent_type` maps to `task`'s `agent_type`. The pstack agents keep their prefix: `pstack:poteto-agent`, `pstack:comment-sicko`, `pstack:effort-`, `pstack:poteto-agent-`. Copilot's built-ins (`explore`, `general-purpose`, `code-review`, `research`, `rubber-duck`, `security-review`, `task`) are also valid. -- Check `task`'s `agent_type` enum before you dispatch. Copilot CLI lists the pstack agents. The VS Code agents window's Copilot target does not load plugin agents, so there `task` rejects them with "Unknown agent_type". When a pstack agent is missing, dispatch `general-purpose` instead: - - For `pstack:poteto-agent` or `pstack:poteto-agent-`, begin the prompt with "Before any work, load the `poteto-mode` skill with the `skill` tool and follow it, including its Principles section." - - For `pstack:comment-sicko`, begin the prompt with "Before any work, read `agents/comment-sicko.md` in the pstack plugin in full and act as that agent." The plugin root is two directories above poteto-mode's `SKILL.md`. - - For `pstack:effort-`, keep the prompt as written. - - Pass any `` as `reasoning_effort`. +- This port ships no plugin agents. VS Code's agents window lists every plugin agent twice, and VS Code's Copilot runtime cannot dispatch them anyway. Use Copilot's built-ins as `task`'s `agent_type` (`explore`, `general-purpose`, `code-review`, `research`, `rubber-duck`, `security-review`, `task`). +- Where a skill names a pstack agent, dispatch `general-purpose` and begin the prompt as follows: + - For `pstack:poteto-agent` or `pstack:poteto-agent-`: "Before any work, load the `poteto-mode` skill with the `skill` tool and follow it, including its Principles section." + - For `pstack:comment-sicko`: "Before any work, read `skills/poteto-mode/references/agents/comment-sicko.md` in the pstack plugin in full and act as that agent." The plugin root is two directories above poteto-mode's `SKILL.md`. + - For `pstack:effort-`: keep the prompt as written. +- A `` in an agent name or a role value goes to `task`'s `reasoning_effort`. - `run_in_background: true` maps to `mode: "background"`. Collect each result with `read_agent` before you use it. - `task` requires `description` (3 to 5 words), `prompt`, `agent_type`, and `name` (a short agent name). -- A role value with `@` dispatches the matching `pstack:effort-` or `pstack:poteto-agent-` agent, or passes the level as `task`'s `reasoning_effort`. - Your Copilot plan caps concurrent subagents (Free 2, Pro 4, Max 8, Business 16, Enterprise 32). Size `swarm` and `arena` fan-out to fit, and queue the rest. - Keep the rest of the policy unchanged. Pass file pointers not inlined context, give each writing worker its own worktree or branch, review every subagent's diff yourself. @@ -66,7 +65,7 @@ Most skills need only the tables above. These need one more mapping: |-------|------------| | `interrogate` | The `subagent_type`/`model`/`readonly` dispatch fields map to `task`'s `agent_type`/`model`; read-only reviewers get a prompt that forbids edits. Keep the reviewer panel diverse per Model names above. | | `setup-pstack` | The Copilot row in the Other runtimes table names the sheet path and how it loads. The role rows are identical. | -| `no-comments` | Dispatch `task` with `agent_type: "pstack:comment-sicko"`. | +| `no-comments` | Dispatch `general-purpose` with the `comment-sicko` opening from Subagent policy above. | | `create-verification-skill` | The generated skill lands under `.claude/skills/verify/` on Claude Code; on Copilot write it to `.github/skills/verify/`. | | `maintain-verification-skill` | The project-local skill lives under `.github/skills/`, not `.claude/skills/`. | | `reflect` | The transcript finder reads Claude Code's layout under `~/.claude/projects/`; Copilot keeps sessions under `~/.copilot/session-state/`. Pass the session digest step 1 allows instead. | diff --git a/tools/build.mjs b/tools/build.mjs index e43d6e1..3b96e11 100755 --- a/tools/build.mjs +++ b/tools/build.mjs @@ -36,7 +36,7 @@ const skillNames = () => .filter((d) => d.isDirectory() && existsSync(join(out, 'skills', d.name, 'SKILL.md'))) .map((d) => d.name); -const removals = ['.codex-plugin', '.claude-plugin', 'hooks/codex-hooks.json']; +const removals = ['.codex-plugin', '.claude-plugin', 'hooks/codex-hooks.json', 'agents', 'effort-agents']; const edits = [ { @@ -90,7 +90,7 @@ function buildMandate() { }); if (rewrites === 0) throw new Error('mandate: no pstack: references rewritten; upstream text changed'); const pointer = - '\nOn GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. Only agents carry the `pstack:` prefix, such as `pstack:poteto-agent`; when `task` does not list them, use the fallback in copilot-tools.md. When a pstack skill names a Claude tool or model, read the pstack plugin\'s `skills/poteto-mode/references/copilot-tools.md`.\n'; + '\nOn GitHub Copilot, skills load through the `skill` tool by bare name, such as `poteto-mode`. This plugin ships no agents; where a skill names a pstack agent, dispatch `general-purpose` as copilot-tools.md says. When a pstack skill names a Claude tool or model, read the pstack plugin\'s `skills/poteto-mode/references/copilot-tools.md`.\n'; const mandate = text.replace('', `${pointer}`); if (mandate === text) throw new Error('mandate: closing tag not found'); write('hooks/session-start-context.md', mandate); @@ -107,7 +107,6 @@ function writeManifests(source) { author: { name: 'hackernotfound', url: 'https://github.com/hackernotfound' }, license: 'MIT', keywords: ['pstack', 'poteto-mode', 'copilot', 'vscode', 'skills', 'subagents'], - agents: claude.agents, skills: './skills/', hooks: './hooks/hooks.json', }; diff --git a/tools/check.mjs b/tools/check.mjs index af0cbed..9e4f13d 100755 --- a/tools/check.mjs +++ b/tools/check.mjs @@ -23,7 +23,7 @@ const upstream = JSON.parse(readFileSync(join(root, 'upstream.json'), 'utf8')); check('plugin.json name is pstack', plugin.name === 'pstack'); check('plugin.json version tracks upstream', plugin.version === `${upstream.version}-copilot.${upstream.portRevision}`); check('no .claude-plugin manifest (VS Code would parse it as Claude format)', !existsSync(join(out, '.claude-plugin'))); -check('every listed agent exists', plugin.agents.every((a) => existsSync(join(out, a)))); +check('plugin ships no agents (the VS Code agents window lists each plugin agent twice)', !('agents' in plugin) && !existsSync(join(out, 'agents')) && !readdirSync(out, { recursive: true }).some((rel) => /(^|\/)agents\/[^/]+\.md$/.test(rel) && !rel.startsWith('skills/'))); check('hooks file exists', existsSync(join(out, plugin.hooks))); const market = JSON.parse(readFileSync(join(root, '.github/plugin/marketplace.json'), 'utf8')); diff --git a/tools/eval-vscode.mjs b/tools/eval-vscode.mjs index 3364c7b..c313bf7 100644 --- a/tools/eval-vscode.mjs +++ b/tools/eval-vscode.mjs @@ -1,10 +1,9 @@ #!/usr/bin/env node // Live checks against the Copilot SDK runtime that VS Code's agents window runs // for its Copilot target, configured the way copilotSessionLauncher.ts configures it. -// Same checks as tools/eval.sh. Plugin agents are reported as INFO because VS Code passes -// on-disk plugins without their agents. Needs VS Code >= 1.140, `gh`, and `git`. +// Same checks as tools/eval.sh. Needs VS Code >= 1.140, `gh`, and `git`. // Local only: it hands your gh token to an auto-approved session. Never run it in CI. -import { appendFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs'; +import { appendFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { execFileSync } from 'node:child_process'; @@ -109,18 +108,20 @@ function check(label, ok) { console.log(`${ok ? 'PASS' : 'FAIL'} ${label}`); if (!ok) fail = 1; } -const info = (label, ok) => console.log(`INFO ${label}: ${ok ? 'yes' : 'no'}`); -const subagentInPotetoMode = (cs) => cs.some((t) => t.t === 'task' && t.ok && cs.some((c) => c.parent === t.id && c.t === 'skill' && String(c.a.skill).includes('poteto-mode') && c.ok)); +const pstackSkills = new Set(readdirSync(join(plugin, 'skills'))); +const subagentRanPstack = (cs) => cs.some((t) => t.t === 'task' && t.ok && cs.some((c) => c.parent === t.id && c.t === 'skill' && pstackSkills.has(String(c.a.skill)) && c.ok)); +const rejectedDispatch = (cs) => cs.some((t) => t.t === 'task' && !t.ok); const agentNames = await run('context', 'Do not run tools. 1) Quote verbatim the sentence in your context that starts with "On GitHub Copilot, skills load". 2) Print the full enum of the agent_type parameter of your task tool, comma separated. 3) Print the number of skills available to you whose name starts with "principle-".', 5 * 60_000); check('mandate injected by sessionStart hook', final('context').includes('skills load through the')); -info('runtime loaded pstack plugin agents (VS Code passes on-disk plugins without agents)', agentNames.includes('pstack:poteto-agent')); +check('runtime lists no pstack plugin agents', !agentNames.some((n) => n.startsWith('pstack:'))); await run('route', 'Explain how main.js gets its output in this repo. Use poteto-mode, and delegate the code reading to one pstack subagent.', 20 * 60_000); const route = calls('route'); check('poteto-mode loaded via skill tool', route.some((c) => c.t === 'skill' && String(c.a.skill).includes('poteto-mode') && c.ok)); check('no namespaced skill lookups', !route.some((c) => String(c.a.skill ?? '').startsWith('pstack:'))); -check('a subagent ran and loaded poteto-mode itself', subagentInPotetoMode(route)); +check('a subagent ran and loaded a pstack skill itself', subagentRanPstack(route)); +check('no subagent dispatch was rejected', !rejectedDispatch(route)); check('no Claude-only tool names called', !route.some((c) => /^(Agent|Skill|Task|AskUserQuestion|TodoWrite)$/.test(c.t))); await run('auto', 'Rename the function add to sum everywhere in this repo, keep main.js printing 5, and verify it by running it.', 20 * 60_000); diff --git a/tools/eval.sh b/tools/eval.sh index 1ef7136..db064b0 100755 --- a/tools/eval.sh +++ b/tools/eval.sh @@ -29,13 +29,19 @@ poteto_mode_loaded() { and (($c.arguments | objects | .skill // "") | test("poteto-mode")) and ($ok | index([$c.toolCallId]))) ' "$work/$1.jsonl" > /dev/null } -subagent_in_poteto_mode() { - jq -s -e ' +subagent_ran_pstack() { + jq -s -e --argjson skills "$(ls "$plugin/skills" | jq -R . | jq -s .)" ' (map(select(.type=="tool.execution_complete" and .data.success==true) | .data.toolCallId)) as $ok | map(select(.type=="tool.execution_start") | .data) as $calls | any($calls[]; . as $t | $t.toolName=="task" and ($ok | index([$t.toolCallId])) and any($calls[]; . as $c | $c.parentToolCallId==$t.toolCallId and $c.toolName=="skill" - and (($c.arguments | objects | .skill // "") | test("poteto-mode")) and ($ok | index([$c.toolCallId])))) + and ($skills | index([($c.arguments | objects | .skill // "")])) and ($ok | index([$c.toolCallId])))) + ' "$work/$1.jsonl" > /dev/null +} +rejected_dispatch() { + jq -s -e ' + (map(select(.type=="tool.execution_complete" and .data.success==false) | .data.toolCallId)) as $bad + | any(.[] | select(.type=="tool.execution_start" and .data.toolName=="task") | .data; . as $t | $bad | index([$t.toolCallId])) ' "$work/$1.jsonl" > /dev/null } @@ -51,13 +57,13 @@ git add -A && git -c user.name=eval -c user.email=eval@local commit -qm init run context -s -p 'Do not run tools. 1) Quote verbatim the sentence in your context that starts with "On GitHub Copilot, skills load". 2) Print the full enum of the agent_type parameter of your task tool, comma separated. 3) Print the number of skills available to you whose name starts with "principle-".' check "mandate injected by sessionStart hook" 'final context | grep -q "skills load through the"' -check "pstack:poteto-agent dispatchable" 'final context | grep -q "pstack:poteto-agent"' -check "pstack:comment-sicko dispatchable" 'final context | grep -q "pstack:comment-sicko"' +check "task offers no pstack plugin agents" '! final context | grep -q "pstack:"' run route -p 'Explain how main.js gets its output in this repo. Use poteto-mode, and delegate the code reading to one pstack subagent.' check "poteto-mode loaded via skill tool" 'poteto_mode_loaded route' check "no namespaced skill lookups" '! calls route | grep -q "\"skill\":\"pstack:"' -check "a subagent ran and loaded poteto-mode itself" 'subagent_in_poteto_mode route' +check "a subagent ran and loaded a pstack skill itself" 'subagent_ran_pstack route' +check "no subagent dispatch was rejected" '! rejected_dispatch route' check "no Claude-only tool names called" '! calls route | grep -qE "\"t\":\"(Agent|Skill|Task|AskUserQuestion|TodoWrite)\""' run auto -p 'Rename the function add to sum everywhere in this repo, keep main.js printing 5, and verify it by running it.' diff --git a/upstream.json b/upstream.json index 5ce0101..d1ea780 100644 --- a/upstream.json +++ b/upstream.json @@ -2,5 +2,5 @@ "repo": "https://github.com/michael-denyer/pstack-claude.git", "sha": "d709ffc96ca080da762f3527d49bfcf5e493cbc5", "version": "0.9.57", - "portRevision": 2 + "portRevision": 3 }