Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

This port applies the Cursor → Claude Code substitutions in skill bodies. Earlier drafts left them flagged; this revision resolves them. A later pass added a Codex build that shares the same skills; see [Codex port](#codex-port) below.

## Unreleased: optional Devin workers

Adds `devin` to the external runner for both Claude Code and Codex parents. SWE-2 supports medium/high/max through exact model UIDs; SWE-1.6 uses a fixed `default` effort token. Setup probes opted-in Devin families while preserving existing default panels. Arena uses the shared completion contract, which accepts matching Codex and Devin pinned-argv evidence. The upstream sync point is unchanged.

The adapter extracts the final response from a private conversation export, records pinned-argv evidence without claiming a provider model report, and leaves unreported usage/cost/session fields null. Per-run configuration disables nested subagents and imported tool settings. Read-only workers deny shell and writes; writers use sandboxed shell commands for edits and tests in the assigned worktree, with direct unsandboxed file tools denied and explicit shell-only guidance prepended in a private prompt copy. Per-run shell onboarding is suppressed; a private conversation export must end with a final agent message without tool calls, preventing banner-only output, progress messages, and denied headless tools from counting as completed answers. Only final response text is retained; the export is removed on every outcome. Devin project settings and startup hooks remain a live-verification concern. Account restrictions fail without fallback.

## 1.4.1 syncs to Cursor pstack 0.15.1

Open Pstack 1.4.1 tracks Cursor pstack 0.15.1 at `f8abeddd1862dc73704e3d719dd73df0d51b8c71`. Poteto-mode now requires each claim to include its evidence or a measured, inferred, or guess label in the same sentence. Agents also run any check they can run themselves instead of handing that check to the user. No playbook, model, runtime, or dependency changed.
Expand Down
2 changes: 2 additions & 0 deletions NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Summary of structural changes:
- Claude-native Fable and Opus lanes are port-authored agent definitions. They select the rolling family alias plus requested effort for every selectable Claude-native pair in the provider-dispatch model matrix.
- A Codex build shares the same `skills/` tree. It adds `plugins/pstack/.codex-plugin/plugin.json`, a root `.agents/plugins/marketplace.json`, and `plugins/pstack/skills/poteto-mode/references/codex-tools.md` (the Claude-to-Codex tool, model, and built-in map), plus a one-line Platform note in the skills that name a Claude primitive. The skill content itself is unchanged. See [CHANGES.md](CHANGES.md#codex-port).

The external runner also includes an independently authored Devin CLI adapter for optional SWE-2 and SWE-1.6 workers. It does not import Cognition source code.

## Modifications

Per the MIT license, modifications are permitted. Skill bodies have been edited to substitute Cursor-specific primitives with their Claude Code equivalents (the full substitution table is in [CHANGES.md](CHANGES.md)). All upstream copyright notices in source files (where present) are preserved.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ That is the main workflow. The other skills are there when poteto-mode needs the

Plugin skills include `pstack:` in their name. In Claude Code, invoke a native skill such as `/pstack:architect`. In Codex, ask for the skill, such as `Use pstack:architect for this design.` See the [technical reference](docs/reference.md) for the full list.

## Optional Devin workers

Codex or Claude Code can delegate selected roles to SWE-2 or SWE-1.6 through an authenticated [Devin CLI](https://docs.devin.ai/cli). Ask `setup-pstack` to use `devin:swe-2@high` (medium/high/max) or `devin:swe-1.6@default` for named roles. Devin remains an external worker; the default four-model panel stays unchanged.

This adapter captures print output and pins the CLI model UID. It does not report provider-verified model identity, tokens, or cost. Read-only workers cannot execute shell commands. See the [Devin dispatch contract](plugins/pstack/skills/poteto-mode/references/provider-dispatch.md#optional-devin-models) for permissions and live verification requirements.

## Models and token use

Some pstack workflows use one model. Skills such as `architect`, `arena`, and `interrogate` can run several models in parallel. Each model run uses the subscription and token allowance of its own command-line tool.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ The port is editorial, not mechanical. Anywhere upstream pstack assumed Cursor-s
| Cursor's `/goal` (standing objective across turns) | The program objective written into the run's standing orders and restated in the todolist |
| The Cursor agent store (path in the system prompt) | `~/.claude/orchestrate/<project-slug>/`, which survives the session restarts a multi-day program expects |
| Model rule `~/.cursor/rules/pstack-models.mdc` | Override sheet `~/.claude/pstack-models.md`, included from `CLAUDE.md` |
| Multi-model panels (arena, architect, interrogate) | Provider dispatch restores the upstream frontier quad: `claude:fable@max`, `codex:gpt-5.6-sol@max`, `grok:grok-4.6@xhigh`, `claude:opus@xhigh`. Same-provider lanes stay native; external lanes use the bundled runner. |
| Multi-model panels (arena, architect, interrogate) | Provider dispatch restores the upstream frontier quad: `claude:fable@max`, `codex:gpt-5.6-sol@max`, `grok:grok-4.6@xhigh`, `claude:opus@xhigh`. Same-provider lanes stay native; external lanes use the bundled runner. Optional Devin workers use `devin:swe-2@high` or `devin:swe-1.6@default`; see the [dispatch contract](../plugins/pstack/skills/poteto-mode/references/provider-dispatch.md#optional-devin-models). |

### Cross-vendor dispatch

Expand Down
2 changes: 1 addition & 1 deletion plugins/pstack/skills/arena/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Start all N lanes in one fan-out phase through the provider-dispatch contract. N

Each rationale names the alternatives the candidate considered and what it rejected.

An external lane counts only when its receipt says `complete` and carries either a matching `provider-report` or Codex's exact `pinned-argv` evidence; a native lane counts when its tool transcript returns the assigned model's result. If a candidate fails, proceed with N-1 and note the exact dropout in the synthesis record. Never replace it with another provider silently.
An external lane counts only when it satisfies [Completion and dropouts](../poteto-mode/references/provider-dispatch.md#completion-and-dropouts), including the assignment and model-argument checks for Codex or Devin `pinned-argv` evidence; a native lane counts when its tool transcript returns the assigned model's result. If a candidate fails, proceed with N-1 and note the exact dropout in the synthesis record. Never replace it with another provider silently.

## Phase C: Cross-judge

Expand Down
4 changes: 2 additions & 2 deletions plugins/pstack/skills/poteto-mode/references/codex-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ poteto-mode's Subagents section sets Claude-specific defaults (`subagent_type: "

## Models and providers

Do not replace every configured entry with a Codex model. `/setup-pstack` writes portable descriptors such as `claude:fable@max`, `codex:gpt-5.6-sol@max`, and `grok:grok-4.6@xhigh`. In a Codex parent, only `codex:*` is native. Route Claude and Grok descriptors through the external launcher exactly as `provider-dispatch.md` specifies. The current default panel intentionally keeps four-provider frontier diversity and contains no older GPT or Claude substitute.
Do not replace every configured entry with a Codex model. `/setup-pstack` writes portable descriptors such as `claude:fable@max`, `codex:gpt-5.6-sol@max`, and `grok:grok-4.6@xhigh`. In a Codex parent, only `codex:*` is native. Route Claude, Grok, and optional Devin descriptors through the external launcher exactly as `provider-dispatch.md` specifies. The current default panel intentionally keeps four-provider frontier diversity and contains no older GPT or Claude substitute.

## Claude built-in skills pstack references

Expand All @@ -57,7 +57,7 @@ Some triggers name skills that ship with Claude Code, not pstack. They do not ex

## Vendored scripts

`skills/poteto-mode/scripts/` ships the `watch-pr` PR watcher, the `orch` store CLI, `worktree-audit.sh`, and `runner/pstack-runner`. They are plain bun and bash, so they run the same on Codex; invoke them through `shell`. The external runner additionally needs the assigned `claude`, `codex`, or `grok` executable already authenticated. It rejects a Codex provider when Codex is the parent because that lane belongs on native `spawn_agent`. The other scripts need `bun`, `gh`, (for stack work) `gt`, and (for `worktree-audit.sh`) `jq` and `rg`. `worktree-audit.sh` reads Claude Code transcripts under `~/.claude/projects/`; point it at your runtime's transcript directory instead when you run it elsewhere.
`skills/poteto-mode/scripts/` ships the `watch-pr` PR watcher, the `orch` store CLI, `worktree-audit.sh`, and `runner/pstack-runner`. They are plain bun and bash, so they run the same on Codex; invoke them through `shell`. The external runner additionally needs the assigned `claude`, `codex`, `grok`, or `devin` executable already authenticated. It rejects a Codex provider when Codex is the parent because that lane belongs on native `spawn_agent`. The other scripts need `bun`, `gh`, (for stack work) `gt`, and (for `worktree-audit.sh`) `jq` and `rg`. `worktree-audit.sh` reads Claude Code transcripts under `~/.claude/projects/`; point it at your runtime's transcript directory instead when you run it elsewhere.

## Instructions file

Expand Down
33 changes: 25 additions & 8 deletions plugins/pstack/skills/poteto-mode/references/provider-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,27 @@ pstack model choices are provider-qualified descriptors:
| grok | grok-4.6-fast-xhigh | grok | grok-4.6 | xhigh | low medium high xhigh max | - |
| opus | opus | claude | opus | xhigh | low medium high xhigh max | opus |

The allowed effort universe is exactly `low`, `medium`, `high`, `xhigh`, `max`. First-run requested efforts are the Default effort cell of each row. A Claude-native agent stem of `-` means the family has no Claude-native agent. Otherwise the shipped agent name is `pstack-<stem>-<effort>`.
For the default matrix, the allowed effort universe is exactly `low`, `medium`, `high`, `xhigh`, `max`. First-run requested efforts are the Default effort cell of each row. A Claude-native agent stem of `-` means the family has no Claude-native agent. Otherwise the shipped agent name is `pstack-<stem>-<effort>`.

`fable` and `opus` are Claude Code's rolling aliases. Claude resolves each alias to the latest available family revision. A runner receipt keeps the requested alias in `model` and the concrete provider-reported revision in `reportedModel`; verification accepts only a numeric `claude-fable-*` or `claude-opus-*` revision from the matching family.

## Optional Devin models

Devin is an external provider from either parent, not a parent harness. These opt-in families do not change the four-model default panel.

| Family | Provider | Model | Default effort | Selectable efforts | CLI model UID |
|---|---|---|---|---|---|
| swe-2 | devin | swe-2 | high | medium high max | swe-2-<effort> |
| swe-1.6 | devin | swe-1.6 | default | default | swe-1-6 |

Use descriptors such as `devin:swe-2@high` or `devin:swe-1.6@default`. `default` records that SWE-1.6 has no selectable effort; it is rejected for other providers. Never clamp SWE-2's unsupported `low` or `xhigh` to another level. The runner pins the exact CLI UID instead of a rolling family alias or Fusion pairing.

Install and sign in to [Devin CLI](https://docs.devin.ai/cli). Inspect `devin models list --format json` and probe each selected pair: listing a model does not prove the account can execute it. An upgrade-required response is an unavailable-model failure, never permission to substitute another model.

The runner uses `--print` and a private temporary `--config` file, deleted after completion or failure. It disables recursive subagents and imports from other tools, and denies MCP and fetch calls. Read-only lanes deny edit, write, and shell execution; use them for file inspection, not test execution. Writer lanes use `--sandbox` in the dedicated worktree and perform edits and tests through sandboxed `exec`. Direct `edit`/`write` tools are denied in both modes: they run outside Devin's OS sandbox and can require interactive confirmation even with scoped write grants. The adapter prefixes each writer task with these execution constraints in a private prompt copy, preserving the assigned prompt and its receipt path. File-tool-only prompts are unsupported. Devin's own project configuration, rules, plugins, and hooks can still load; this is not a clean-room execution environment. Do not assign an untrusted checkout or rely on this adapter to isolate startup hooks. Verify effective permission behavior in the target CLI before release.

The temporary config marks shell onboarding complete. The runner requests a private ATIF-v1.7 conversation export and accepts only a final agent step with a nonempty message and no tool calls. A progress message followed by denied or pending tools cannot count as completion, even if Devin exits zero without stderr. Only the final message is returned; system context, reasoning, and tool observations are never copied into output or receipts. The export directory is private and removed after every outcome. The adapter continues to use `pinned-argv` model evidence rather than treating the export's display model name as verified identity; model-report, session, usage, and cost fields remain null.

## Read-time normalization

Normalize configured descriptors before matching them to the matrix or choosing a route. If a provider-qualified Claude model starts with `claude-fable-` or `claude-opus-` and its remaining revision contains only digits and hyphens, replace that model component in memory with `fable` or `opus`. Preserve provider, effort, role, and lane order. Use only the normalized descriptor for native dispatch or runner argv. Never pass the versioned predecessor to Claude.
Expand All @@ -31,10 +48,10 @@ This read-time rule makes an older installed sheet use the latest family revisio

The top-level harness resolves the route once. A child receives an assigned provider, model, effort, access mode, prompt, working directory, and output path. A child never detects the harness, chooses a provider, or launches another model. Environment markers may corroborate the top-level harness before fan-out, but nested processes inherit parent markers and must not use them for routing.

| Parent | `claude:*` | `codex:*` | `grok:*` |
|---|---|---|---|
| Claude Code | native `Agent` | external runner | external runner |
| Codex | external runner | native `spawn_agent` | external runner |
| Parent | `claude:*` | `codex:*` | `grok:*` | `devin:*` |
|---|---|---|---|---|
| Claude Code | native `Agent` | external runner | external runner | external runner |
| Codex | external runner | native `spawn_agent` | external runner | external runner |

`inherit-parent` and `auto` remain aliases. They use the parent's current model and effort through its native subagent primitive. In a panel they still consume one lane, but they reduce provider diversity; say so in the synthesis record.

Expand All @@ -54,9 +71,9 @@ The launcher lives at `skills/poteto-mode/scripts/runner/pstack-runner` under th
```text
pstack-runner \
--parent <claude|codex> \
--provider <claude|codex|grok> \
--provider <claude|codex|grok|devin> \
--model <real CLI model> \
--effort <low|medium|high|xhigh|max> \
--effort <low|medium|high|xhigh|max|default> \
--mode <read-only|isolated-write> \
--prompt <unique prompt file> \
--cwd <repository or dedicated worktree> \
Expand Down Expand Up @@ -90,7 +107,7 @@ Success requires all of these:

1. Exit status `0`.
2. Receipt status `complete`.
3. Either `modelVerified: true` with `modelEvidence: "provider-report"`, or a Codex receipt with `reportedModel: null`, `modelVerified: false`, and `modelEvidence: "pinned-argv"`. For Claude's `fable` and `opus` aliases, the concrete provider report must belong to the requested family. Codex 0.149.0 accepts the exact `--model` argument but does not report the served model in its JSONL stream.
3. Either `modelVerified: true` with `modelEvidence: "provider-report"`, or a Codex or Devin receipt with `reportedModel: null`, `modelVerified: false`, and `modelEvidence: "pinned-argv"`. For Claude's `fable` and `opus` aliases, the concrete provider report must belong to the requested family. For pinned-argv evidence, verify the receipt provider, model, and effort match the assignment and its argv pins the expected CLI model. Codex pins the assigned model directly; Devin uses the exact UID mapping in Optional Devin models (for example, `swe-2@high` pins `--model swe-2-high`). Neither Codex JSONL nor Devin print output supplies a provider model report; do not describe pinned argv as provider-verified identity.
4. A non-empty output file.

The receipt also carries elapsed time, token usage when the CLI exposes it, and cost when available. Keep it with the arena or review artifacts so parent-harness comparisons are evidence-based.
Expand Down
4 changes: 2 additions & 2 deletions plugins/pstack/skills/poteto-mode/scripts/runner/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
UsageError,
} from "./types.ts";

const HELP = `Usage: pstack-runner --parent <claude|codex> --provider <claude|codex|grok> \\
const HELP = `Usage: pstack-runner --parent <claude|codex> --provider <claude|codex|grok|devin> \\
--model <slug> --effort <level> --mode <read-only|isolated-write> \\
--prompt <file> --cwd <dir> --output <file> --receipt <file> [--timeout <seconds>]

Expand Down Expand Up @@ -98,7 +98,7 @@ export function parseArgs(argv: readonly string[]): RunnerOptions | null {
parent: oneOf("parent", stringValue(parsed.values.parent), PARENTS) as Parent,
provider: oneOf("provider", stringValue(parsed.values.provider), PROVIDERS) as Provider,
model: required("model", stringValue(parsed.values.model)),
effort: oneOf("effort", stringValue(parsed.values.effort), EFFORTS) as Effort,
effort: oneOf("effort", stringValue(parsed.values.effort), [...EFFORTS, "default"]) as Effort,
mode,
promptPath: required("prompt", stringValue(parsed.values.prompt)),
cwd: required("cwd", stringValue(parsed.values.cwd)),
Expand Down
25 changes: 25 additions & 0 deletions plugins/pstack/skills/poteto-mode/scripts/runner/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type {
RunnerOptions,
} from "./types.ts";

import { devinConfigPath, devinExportPath, devinModel, devinPromptPath } from "./devin.ts";

export interface CommandSpec {
readonly command: string;
readonly args: readonly string[];
Expand All @@ -13,6 +15,8 @@ export interface CommandSpec {

export function preflightCommand(provider: Provider): CommandSpec {
switch (provider) {
case "devin":
return { command: "devin", args: ["auth", "status"], stdin: "none" };
case "claude":
return {
command: "claude",
Expand Down Expand Up @@ -65,6 +69,27 @@ function effortOverride(effort: Effort): string {

export function invocationCommand(options: RunnerOptions): CommandSpec {
switch (options.provider) {
case "devin":
return {
command: "devin",
args: [
"--config",
devinConfigPath(options),
"--model",
devinModel(options.model, options.effort),
...(options.mode === "isolated-write"
? ["--sandbox"]
: ["--permission-mode", "auto"]),
"--respect-workspace-trust",
"false",
"--prompt-file",
devinPromptPath(options),
"--export",
devinExportPath(options),
"--print",
],
stdin: "none",
};
case "claude":
return {
command: "claude",
Expand Down
Loading