From 2bfae38fc0520cebcd9c9c6ee9d6141aaf919285 Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:18:11 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat(roles):=20=E9=AA=8C=E8=AF=81=20worker?= =?UTF-8?q?=20=E4=B8=8E=E6=94=B6=E5=B0=BE=E5=A4=8D=E6=A0=B8=E6=94=B9?= =?UTF-8?q?=E8=AF=BB=E7=8B=AC=E7=AB=8B=E7=9A=84=20verification=20workers?= =?UTF-8?q?=20=E8=A7=92=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上游要求 orchestrate 的 verifier 和 show-me-your-work 的收尾复核换一个 模型家族来做。fork 之前让验证 worker 读 swarm workers,而这个角色同时管 swarm 的分片与竞速 worker,想让验证在某个 host 上换成另一家,就得连 swarm 的实现一起换掉。 新增 verification workers:poteto-mode 的验证 worker、swarm 里验证别人 工作的 lane(如 autopilot 的 swarm-verify)和收尾复核都读它;T3 的候选 角色传入没写这份工作的那个 provider。setup-pstack 写明按 host 指向另一家, ADAPTATION 记录这条本地决定,check-fork 加三条正向守卫。 Co-Authored-By: Claude Opus 5.5 --- ADAPTATION.md | 4 +++- scripts/check-fork.mjs | 21 +++++++++++++++++++++ scripts/check-fork.test.mjs | 3 +++ skills/poteto-mode/SKILL.md | 4 ++-- skills/poteto-mode/playbooks/orchestrate.md | 2 +- skills/setup-pstack/SKILL.md | 2 +- skills/show-me-your-work/SKILL.md | 2 +- skills/swarm/SKILL.md | 2 +- 8 files changed, 33 insertions(+), 7 deletions(-) diff --git a/ADAPTATION.md b/ADAPTATION.md index cad9a0c..9b98007 100644 --- a/ADAPTATION.md +++ b/ADAPTATION.md @@ -39,7 +39,9 @@ The 0.15.21 sync (upstream 0.15.16–0.15.21, #484, #486, #536, #538, #539, #570 The 0.15.25 sync (upstream 0.15.22–0.15.25, #633 and #634: #595, #597, #602, #604, #606, #609, #613, #615, #616, #628, #633) takes the `in-your-own-words` and `sharpen` skills with the local frontmatter and runtime-contract line, the shorter visual `ketchup` reply (host-rendered charts instead of `/visualize`), ketchup catch-ups at the end of autopilot ticks and replies, the restated attack-the-premise, fix-root-causes, make-operations-idempotent, and test-behavior principles, the cut marginal sections in interrogate's lead-judgment reference, swarm, and the migrate-callers and type-system-discipline principles, the always-on signal after a deep dig, the full-swarm-once review cadence in autopilot-full and multi-phase-plan, the principle-first rewrites of autopilot-full, autopilot-stack, and shipping, and Graphite's removal from `orch frontier set`. The per-job effort rule ("match the model to the job") becomes "match effort to the job" in poteto-mode's Subagents section: workers start from the resolved role and `reasoning_effort`, rise one step for the hardest work and drop one step for judgment or two or more for routine work, and pass the value only through each host's separate effort control (Codex `reasoning_effort`, the Claude Agent `effort` field, T3 `target.options`). It never changes a role's model, T3 target, or `xagent:` entry, so panels stay diverse. xagent workers originally kept their CLI's own setting; they now get the adjusted value through `bin/xagent --effort`. Upstream's urgency-based fast mode is skipped: fast mode and priority tiers cost more and stay off unless the user asks, which also matches the T3 overlay. The autopilot and shipping rewrites keep this fork's isolated host workers instead of Cursor cloud agents, the project harness instead of `control-ui`/`control-cli`, the selected state directory instead of the root agent's system-prompt store, an authorized host scheduler instead of `/loop 1h`, the installed playbook instead of `origin/main`, merges only under explicit merge authorization, `--auto` only on request, and replacement of a stuck agent only after its ownership is resolved. `orch frontier set` takes upstream's base-chain discovery through `gh` or `--forge origin` in place of the optional Graphite path, but keeps this fork's authoritative `--prs` list, which reads each PR's state and head SHA with `gh pr view` and so works from a detached worker worktree; `--prs` with `--forge origin` fails because Origin's list output carries no head SHA. The discovery path also carries local fixes for defects in upstream's version, found in independent review: `gh` queries pin `--repo` to the GitHub origin and drop PRs whose head repository is another fork, so a same-named fork branch never gets the local SHA; every list passes `--limit 1000` and fails when the result may be truncated, since `gh pr list` returns 30 rows by default; trunk comes from `origin/HEAD`, else from whichever of `main` and `master` exists, remote refs first, and fails when both or neither exist instead of assuming `main`; and `ssh://git@github.com/` origins are accepted alongside HTTPS and scp-style ones, here and in `worktree-audit.sh`. Recovery hints offer `--prs` only where it works, on GitHub. Origin's list output has no head repository, so `--forge origin` cannot drop same-named fork PRs; prefer `gh` or `--prs` where forks exist. Shipping reads and fixes the bottom PR's base before every merge, the first after a restart included, because a PR still targeting its merged parent merges into that branch. The T3 overlay treats a queued `WAITING`/`merge-queue` as a wait in Shipping, which stops only at `COMPLETE` or a blocker. The multi-phase-plan skeleton makes its rebase items depend on the execution playbook, because Autopilot-stack owners never rebase. `worktree-audit.sh` keeps its GitHub-only PR query, because Origin's list output has no head repository and the audit must not match a same-named fork branch. `poteto-agent.md` resolves poteto-mode from the Claude install record or the Codex plugin cache instead of `~/.cursor/plugins/`. The T3 overlay's no-polling watch-pr rule now covers Shipping as well as Babysit. The Cursor `/` menu note in the README is skipped. -Model tiering by role follows upstream again. Poteto-mode's Subagents section restores upstream's "Code delegates tier by difficulty" routing that earlier adaptations dropped: each code playbook's delegate reads its role, the hardest changes read `hardest tasks`, prose and judgment read `judgment and prose`, and verification workers read `swarm workers`. The models come from `config.json`, where every role still inherits the parent by default, instead of upstream's Cursor slug defaults, and effort still moves per job within the role's model. `how`, `why` and `reflect` name their role keys, such as `how explorer` and `reflect judgment`, so a configured role is the one they read. +Model tiering by role follows upstream again. Poteto-mode's Subagents section restores upstream's "Code delegates tier by difficulty" routing that earlier adaptations dropped: each code playbook's delegate reads its role, the hardest changes read `hardest tasks`, prose and judgment read `judgment and prose`, and verification workers read `verification workers`. The models come from `config.json`, where every role still inherits the parent by default, instead of upstream's Cursor slug defaults, and effort still moves per job within the role's model. `how`, `why` and `reflect` name their role keys, such as `how explorer` and `reflect judgment`, so a configured role is the one they read. + +`verification workers` is a local role with no upstream line. Upstream runs orchestrate's verifier and show-me-your-work's handback review on a different model family than the work. On Codex or Claude Code another family needs an `xagent:` entry, so verification takes its own role instead of sharing `swarm workers` with fan-out workers, and each host can point it at the other vendor while swarms keep their own worker. A swarm's verify lanes, as in autopilot's swarm-verify, and the handback review read it too. On T3 a candidate role passes the provider that did not produce the checked work. The orch store lock carries a local fix for three races that upstream still has at `e5136d82`: a writer killed between the exclusive open and its pid write left an empty lock that only `--force` could pass, two writers that saw the same dead holder could both take the lock, and a release could unlink the lock a `--force` writer had just put in its place. `acquireLock` now writes the pid to a private file and hard-links it into place, falling back to the exclusive open where hard links are unsupported. Every read-then-unlink of the lock, in a takeover or a release, runs behind a `.orch.lock.takeover` claim, and a takeover re-reads the holder before it unlinks. A writer that meets a live claim is refused with `is being released or replaced; retry`; a release that meets one retries every 10 ms, so `close` waits while a live claimant, even a stopped one, holds it. The fix and its multi-process race tests are adapted from michael-denyer/pstack-claude #219 (`eef8f7c6`) and #238 (`de804764`), MIT, Copyright (c) 2026 Michael Denyer, whose notice is added to `LICENSE`. That fork's TLA+ model and its retry when a lock vanishes before its holder is read are not taken. The lock lives in `skills/poteto-mode/scripts/orch/lock.ts`, with `UserError` and `errorCode` in `orch/errors.ts`, because this fork replaced upstream's lock wholesale and `store.ts` was already past 1,000 lines; its race tests live in `orch/lock.test.ts`, sharing `orch/store.test-helper.ts` with `orch.test.ts`. Each acquire also removes the private pid files and staged claims that a writer killed mid-claim leaves behind, judged by the pid in their names, which the kill-at-every-step test now checks. The frontier code stays in `store.ts` even though it is large, so upstream's edits there still merge file by file. Its GitHub remote parsing is `skills/poteto-mode/scripts/github-remote.ts`, moved out of upstream's `watch-pr/github.ts` so `orch` and `watch-pr` share one parser. diff --git a/scripts/check-fork.mjs b/scripts/check-fork.mjs index 21e1073..aa8c67d 100644 --- a/scripts/check-fork.mjs +++ b/scripts/check-fork.mjs @@ -167,6 +167,27 @@ export const REQUIRED = [ hint: "fast mode stays off unless the user asks; urgency does not turn it on", section: "upstream-behavior-retained", }, + { + id: "verification-workers-role", + file: "skills/poteto-mode/SKILL.md", + pattern: /Verification workers, including a swarm's verify lanes and the \*\*show-me-your-work\*\* handback review, read `verification workers`\./, + hint: "verifiers read their own role so each host can point it at another vendor", + section: "upstream-behavior-retained", + }, + { + id: "swarm-verify-role", + file: "skills/swarm/SKILL.md", + pattern: /Workers that verify another agent's work, as in a swarm-verify, read `verification workers` instead\./, + hint: "a swarm's verify lanes read verification workers, not swarm workers", + section: "upstream-behavior-retained", + }, + { + id: "handback-review-role", + file: "skills/show-me-your-work/SKILL.md", + pattern: /spawn a subagent on the `verification workers` role from the effective policy/, + hint: "the handback review runs on the verification workers role", + section: "upstream-behavior-retained", + }, { id: "t3-no-service-tier", file: "references/t3-runtime.md", diff --git a/scripts/check-fork.test.mjs b/scripts/check-fork.test.mjs index 61835e6..a6d6011 100644 --- a/scripts/check-fork.test.mjs +++ b/scripts/check-fork.test.mjs @@ -166,6 +166,9 @@ const DROPPED = [ ["autopilot-push-authorization", "skills/poteto-mode/playbooks/autopilot-full.md", "Within the program's push authorization, force-push", "Force-push"], ["autopilot-merge-authorization", "skills/poteto-mode/playbooks/autopilot-full.md", "Only the operator's explicit authorization to merge this queue, together with your clean verdict, permits the merge.", "Green CI alone never authorizes a merge."], ["fast-mode-on-request", "skills/poteto-mode/SKILL.md", "Fast mode and priority service tiers cost more, so use them only when the user asked.", "Use fast mode only when the job is urgent, meaning CI or trunk is red or a person is blocked on the result right now."], + ["verification-workers-role", "skills/poteto-mode/SKILL.md", "Verification workers, including a swarm's verify lanes and the **show-me-your-work** handback review, read `verification workers`.", ""], + ["swarm-verify-role", "skills/swarm/SKILL.md", "Workers that verify another agent's work, as in a swarm-verify, read `verification workers` instead.", ""], + ["handback-review-role", "skills/show-me-your-work/SKILL.md", "on the `verification workers` role from the effective policy, on a different available model family", "on a different model family"], ["t3-no-service-tier", "references/t3-runtime.md", "The preview adds no speed or service-tier option; do not add one unless the user asked.", ""], ["t3-catalog-preview", "references/t3-runtime.md", "config.mjs resolve --host t3", "removed-by-sync"], ["t3-worktree-isolation", "references/t3-runtime.md", 'isolation: "worktree"', "removed-by-sync"], diff --git a/skills/poteto-mode/SKILL.md b/skills/poteto-mode/SKILL.md index 3c63e09..6520a02 100644 --- a/skills/poteto-mode/SKILL.md +++ b/skills/poteto-mode/SKILL.md @@ -91,11 +91,11 @@ The chat that receives `$poteto-mode` runs the playbook. Never spawn a `poteto-a For a worker using the full pstack workflow, include a pointer to this plugin's `agents/poteto-agent.md` prompt template. Review workflows use their own narrower templates. Read the effective policy from `node /bin/config.mjs show --host `; absent values inherit the parent, and model/effort overrides must be supported by the current role. -**Match the model to the role.** Code delegates tier by difficulty. Each code playbook's delegate, trivial mechanical edits included, reads its role (`feature`, `refactoring`, `bug-fix`, `perf-issue`, or `hillclimb`). The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms) read `hardest tasks`, whether the task needs judgment on vague intent or is a precisely specified sequence of steps to execute to the letter. Prose and judgment read `judgment and prose`. Verification workers read `swarm workers`. The routed skills (`how`, `why`, `reflect`, `swarm`, `arena`, `architect`, `interrogate`) read the roles and panels they name. A role absent from the effective policy inherits the parent. +**Match the model to the role.** Code delegates tier by difficulty. Each code playbook's delegate, trivial mechanical edits included, reads its role (`feature`, `refactoring`, `bug-fix`, `perf-issue`, or `hillclimb`). The hardest changes (cross-cutting design, gnarly concurrency, subtle algorithms) read `hardest tasks`, whether the task needs judgment on vague intent or is a precisely specified sequence of steps to execute to the letter. Prose and judgment read `judgment and prose`. Verification workers, including a swarm's verify lanes and the **show-me-your-work** handback review, read `verification workers`. The routed skills (`how`, `why`, `reflect`, `swarm`, `arena`, `architect`, `interrogate`) read the roles and panels they name. A role absent from the effective policy inherits the parent. Classify the current delegate's work, not the whole project's difficulty. After a hard design is settled, routine implementation returns to its ordinary code-playbook role. Keep `hardest tasks` only for implementation that still requires difficult reasoning. Complex architecture exploration uses `hardest architect runners` when that panel is configured, otherwise the existing `architect runners` panel. An already running worker keeps its model; start a fresh worker for a new phase under the fresh-worker rule below. In each brief record the phase, difficulty and one-sentence reason for the selected role or panel. -On T3, a role may declare `candidates`. Resolve exactly one through the T3 helper: prefer the parent provider when listed, otherwise the first configured candidate. To request another configured provider for a different model perspective, pass `--provider` and record the reason. Do not spawn every candidate or retry a failed selection on another candidate. Explicit `@latest` family selectors use the task's live catalog and resolve to exact model IDs before dispatch; reuse those resolved IDs throughout this task. Native host policy and exact pinned targets keep their existing meaning. +On T3, a role may declare `candidates`. Resolve exactly one through the T3 helper: prefer the parent provider when listed, otherwise the first configured candidate. To request another configured provider for a different model perspective, pass `--provider` and record the reason. A `verification workers` candidate role passes the configured provider that did not produce the checked work, so the check stays cross-family. Do not spawn every candidate or retry a failed selection on another candidate. Explicit `@latest` family selectors use the task's live catalog and resolve to exact model IDs before dispatch; reuse those resolved IDs throughout this task. Native host policy and exact pinned targets keep their existing meaning. **Match effort to the job.** Before each spawn, start from the role's resolved policy and the effective `reasoning_effort`, then pick the effort the job needs. The policy order is `low`, `medium`, `high`, `xhigh`, `max`; one step above `high` is `xhigh`. Raise it one step, up to `max`, for the hardest or subtlest work. Lower it one step for judgment and two or more steps, down to `low`, for routine work. Verification workers keep the resolved effort. Change only the effort, never the role's model, T3 target, or `xagent:` entry, so a diverse panel stays diverse. Pass it only through the separate effort control the host adapter names, never inside a model ID. With no effective value or no such control, the worker inherits and the reply says so. An `xagent:` worker gets the adjusted value through `bin/xagent --effort`, and with no effective value runs at its CLI's own setting. If the host rejects the adjusted value, do not try another one. Use the resolved value and say so. Fast mode and priority service tiers cost more, so use them only when the user asked. diff --git a/skills/poteto-mode/playbooks/orchestrate.md b/skills/poteto-mode/playbooks/orchestrate.md index 0c2e88f..21f4995 100644 --- a/skills/poteto-mode/playbooks/orchestrate.md +++ b/skills/poteto-mode/playbooks/orchestrate.md @@ -86,7 +86,7 @@ A dependency is a context relay, not just ordering. Undeclared upstream context #### Verification -Scale verification to the unit. When VERIFY is a single cheap command, the worker runs it and reports the output, and the coordinator spot-checks receipts. A dedicated verifier agent (on a different available model family (or explicitly labeled same-family independent review) than the worker) is for units whose verification is expensive, judgment-laden, or high-blast-radius. A verifier agent whose entire product would be rerunning one command is ceremony, not verification. +Scale verification to the unit. When VERIFY is a single cheap command, the worker runs it and reports the output, and the coordinator spot-checks receipts. A dedicated verifier agent (on the `verification workers` role, a different available model family (or explicitly labeled same-family independent review) than the worker) is for units whose verification is expensive, judgment-laden, or high-blast-radius. A verifier agent whose entire product would be rerunning one command is ceremony, not verification. Write ledger rows with `orch ledger record`. Check the current PR and head SHA with `orch ledger check`. `ledger.tsv`, one row per verdict, keyed by PR number plus head SHA: `live-ui-verified | unit-test-verified | type-check-only | verifier-blocked | verifier-failed`. CI green is an input to a verdict, not a verdict. Behavioral work needs better than `type-check-only`. `verifier-blocked` is not a pass. Respawn when the environment heals. `verifier-failed` gets a fix unit, not a re-verify. A worker may self-report. A verifier overrides it on the same key. A new head SHA voids the row, so re-verify after restack. The ledger answers "was this verified", not memory and not the transcript. diff --git a/skills/setup-pstack/SKILL.md b/skills/setup-pstack/SKILL.md index 6a1754e..e3c32f9 100644 --- a/skills/setup-pstack/SKILL.md +++ b/skills/setup-pstack/SKILL.md @@ -34,6 +34,6 @@ Example shared patch, usable on both hosts: } ``` -Role names follow the bundled workflow: the code playbook roles `feature`, `refactoring`, `bug-fix`, `perf-issue`, and `hillclimb`; `hardest tasks` for the hardest changes; `judgment and prose`; `how explorer`, `how explainer`, `why investigators`, `why synthesizer`, `reflect judgment`, and `reflect tooling`; and `swarm workers`, which verification workers also read. Panels include `arena runners`, `arena cross-judge pool`, `architect runners`, optional `hardest architect runners`, and `interrogate reviewers`. Use the role a workflow actually requests; do not populate unused choices. +Role names follow the bundled workflow: the code playbook roles `feature`, `refactoring`, `bug-fix`, `perf-issue`, and `hillclimb`; `hardest tasks` for the hardest changes; `judgment and prose`; `how explorer`, `how explainer`, `why investigators`, `why synthesizer`, `reflect judgment`, and `reflect tooling`; `swarm workers` for swarm fan-out; and `verification workers` for verifier agents, a swarm's verify lanes, and the show-me-your-work handback review. Set `verification workers` per host to a model family other than that host's writers, for example `xagent:claude` under `hosts.codex`; on T3, list one candidate per provider. Panels include `arena runners`, `arena cross-judge pool`, `architect runners`, optional `hardest architect runners`, and `interrogate reviewers`. Use the role a workflow actually requests; do not populate unused choices. Shared `required_panel_members`, for example `["xagent:grok", "xagent:gemini"]`, adds those external agents to every panel and the default panel on both hosts. It is rejected in a host override; `null` removes it. diff --git a/skills/show-me-your-work/SKILL.md b/skills/show-me-your-work/SKILL.md index 51ef9cc..4201128 100644 --- a/skills/show-me-your-work/SKILL.md +++ b/skills/show-me-your-work/SKILL.md @@ -65,7 +65,7 @@ Correct the log, not the story. The audit never edits or removes a row, even an ## Cross-model review of the trail -Before handing back, spawn a subagent on a different available model family (or explicitly labeled same-family independent review) from the one that did the work. Self-review is not a substitute. The subagent reads the audit trail and the run's transcript, then flags what the user should pay attention to. Not a redo of the work, a scan for what's suboptimal or risky. Set each worker's reasoning effort for the job, per the Subagents section of the **poteto-mode** skill. +Before handing back, spawn a subagent on the `verification workers` role from the effective policy, on a different available model family (or explicitly labeled same-family independent review) from the one that did the work. Self-review is not a substitute. The subagent reads the audit trail and the run's transcript, then flags what the user should pay attention to. Not a redo of the work, a scan for what's suboptimal or risky. Set each worker's reasoning effort for the job, per the Subagents section of the **poteto-mode** skill. - Decisions logged with weak or absent evidence. - Verification steps skipped or claimed without proof in the transcript. diff --git a/skills/swarm/SKILL.md b/skills/swarm/SKILL.md index 2e458af..5f20c8d 100644 --- a/skills/swarm/SKILL.md +++ b/skills/swarm/SKILL.md @@ -20,7 +20,7 @@ Open a todolist with one entry per phase before launching anything. 1. State the done predicate and the artifact or report the swarm must return. 2. Choose the shape. Partition into slices, race N workers on identical briefs, or mix both. For a race or mixed shape, declare `first pass`, `rank all`, or `best-of` before spawning. -3. Pick the worker model from `swarm workers` in the effective policy from `node /bin/config.mjs show --host ` when present. Otherwise use `inherit-parent`. For a model race, name each arm's model up front. Set each worker's reasoning effort for the job, per the Subagents section of the **poteto-mode** skill. +3. Pick the worker model from `swarm workers` in the effective policy from `node /bin/config.mjs show --host ` when present. Otherwise use `inherit-parent`. Workers that verify another agent's work, as in a swarm-verify, read `verification workers` instead. For a model race, name each arm's model up front. Set each worker's reasoning effort for the job, per the Subagents section of the **poteto-mode** skill. 4. Give each worker its own writable output when it writes. When workers verify or measure commits, name the exact SHAs in each brief. Measurement briefs also name the sample count, what constitutes a sample, and execution order. Require the worker to record those SHAs and the method in its result. ## Phase B: Fan out From 1b4be5fdb2b2890da6021647e484f00809cb6961 Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:18:11 +0800 Subject: [PATCH 2/6] =?UTF-8?q?chore(release):=20=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8D=87=E5=88=B0=200.15.25-shared.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 发布 verification workers 角色拆分,两个 manifest 按 docs/guide/01-setup.md 的要求一起升级。 Co-Authored-By: Claude Opus 5.5 --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index bffe736..23d2abc 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "pstack", - "version": "0.15.25-shared.6", + "version": "0.15.25-shared.7", "description": "Shared pstack engineering workflows for Claude Code and Codex, with one configuration and host-specific runtime adapters.", "author": { "name": "Local adaptation; upstream Lauren Tan" diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 990901f..ad41835 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "pstack-codex", - "version": "0.15.25-shared.6", + "version": "0.15.25-shared.7", "description": "Shared pstack engineering workflows for Codex and Claude Code, with one configuration and native host adapters.", "author": { "name": "Lauren Tan; local Codex adaptation" From ac146e266b3d366ddc25fd6486ff28c12a579f7f Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:28:50 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix(roles):=20T3=20=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E6=8C=89=E8=A7=A3=E6=9E=90=E5=87=BA=E7=9A=84=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=AE=B6=E6=97=8F=E9=80=89=E5=80=99=E9=80=89=EF=BC=8C=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=E6=8C=89=20provider?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit references/t3-runtime.md 写明 provider 名称本身不能确定模型家族,同一个 provider 可能代理别家的模型。原措辞让 verification workers 选"没写这份 工作的 provider"并当作跨家,两个 provider 背后是同一家时会误报。现在按 候选解析出的模型家族挑选;所有候选都和被检工作同家时,标为同家族复核。 setup-pstack 也改成按模型家族列候选。 Co-Authored-By: Claude Opus 5.5 --- ADAPTATION.md | 2 +- skills/poteto-mode/SKILL.md | 2 +- skills/setup-pstack/SKILL.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ADAPTATION.md b/ADAPTATION.md index 9b98007..79c8417 100644 --- a/ADAPTATION.md +++ b/ADAPTATION.md @@ -41,7 +41,7 @@ The 0.15.25 sync (upstream 0.15.22–0.15.25, #633 and #634: #595, #597, #602, # Model tiering by role follows upstream again. Poteto-mode's Subagents section restores upstream's "Code delegates tier by difficulty" routing that earlier adaptations dropped: each code playbook's delegate reads its role, the hardest changes read `hardest tasks`, prose and judgment read `judgment and prose`, and verification workers read `verification workers`. The models come from `config.json`, where every role still inherits the parent by default, instead of upstream's Cursor slug defaults, and effort still moves per job within the role's model. `how`, `why` and `reflect` name their role keys, such as `how explorer` and `reflect judgment`, so a configured role is the one they read. -`verification workers` is a local role with no upstream line. Upstream runs orchestrate's verifier and show-me-your-work's handback review on a different model family than the work. On Codex or Claude Code another family needs an `xagent:` entry, so verification takes its own role instead of sharing `swarm workers` with fan-out workers, and each host can point it at the other vendor while swarms keep their own worker. A swarm's verify lanes, as in autopilot's swarm-verify, and the handback review read it too. On T3 a candidate role passes the provider that did not produce the checked work. +`verification workers` is a local role with no upstream line. Upstream runs orchestrate's verifier and show-me-your-work's handback review on a different model family than the work. On Codex or Claude Code another family needs an `xagent:` entry, so verification takes its own role instead of sharing `swarm workers` with fan-out workers, and each host can point it at the other vendor while swarms keep their own worker. A swarm's verify lanes, as in autopilot's swarm-verify, and the handback review read it too. On T3 a candidate role picks the candidate whose resolved model family differs from the checked work's, because a provider name alone does not identify the family. The orch store lock carries a local fix for three races that upstream still has at `e5136d82`: a writer killed between the exclusive open and its pid write left an empty lock that only `--force` could pass, two writers that saw the same dead holder could both take the lock, and a release could unlink the lock a `--force` writer had just put in its place. `acquireLock` now writes the pid to a private file and hard-links it into place, falling back to the exclusive open where hard links are unsupported. Every read-then-unlink of the lock, in a takeover or a release, runs behind a `.orch.lock.takeover` claim, and a takeover re-reads the holder before it unlinks. A writer that meets a live claim is refused with `is being released or replaced; retry`; a release that meets one retries every 10 ms, so `close` waits while a live claimant, even a stopped one, holds it. The fix and its multi-process race tests are adapted from michael-denyer/pstack-claude #219 (`eef8f7c6`) and #238 (`de804764`), MIT, Copyright (c) 2026 Michael Denyer, whose notice is added to `LICENSE`. That fork's TLA+ model and its retry when a lock vanishes before its holder is read are not taken. The lock lives in `skills/poteto-mode/scripts/orch/lock.ts`, with `UserError` and `errorCode` in `orch/errors.ts`, because this fork replaced upstream's lock wholesale and `store.ts` was already past 1,000 lines; its race tests live in `orch/lock.test.ts`, sharing `orch/store.test-helper.ts` with `orch.test.ts`. Each acquire also removes the private pid files and staged claims that a writer killed mid-claim leaves behind, judged by the pid in their names, which the kill-at-every-step test now checks. The frontier code stays in `store.ts` even though it is large, so upstream's edits there still merge file by file. Its GitHub remote parsing is `skills/poteto-mode/scripts/github-remote.ts`, moved out of upstream's `watch-pr/github.ts` so `orch` and `watch-pr` share one parser. diff --git a/skills/poteto-mode/SKILL.md b/skills/poteto-mode/SKILL.md index 6520a02..645e85a 100644 --- a/skills/poteto-mode/SKILL.md +++ b/skills/poteto-mode/SKILL.md @@ -95,7 +95,7 @@ For a worker using the full pstack workflow, include a pointer to this plugin's Classify the current delegate's work, not the whole project's difficulty. After a hard design is settled, routine implementation returns to its ordinary code-playbook role. Keep `hardest tasks` only for implementation that still requires difficult reasoning. Complex architecture exploration uses `hardest architect runners` when that panel is configured, otherwise the existing `architect runners` panel. An already running worker keeps its model; start a fresh worker for a new phase under the fresh-worker rule below. In each brief record the phase, difficulty and one-sentence reason for the selected role or panel. -On T3, a role may declare `candidates`. Resolve exactly one through the T3 helper: prefer the parent provider when listed, otherwise the first configured candidate. To request another configured provider for a different model perspective, pass `--provider` and record the reason. A `verification workers` candidate role passes the configured provider that did not produce the checked work, so the check stays cross-family. Do not spawn every candidate or retry a failed selection on another candidate. Explicit `@latest` family selectors use the task's live catalog and resolve to exact model IDs before dispatch; reuse those resolved IDs throughout this task. Native host policy and exact pinned targets keep their existing meaning. +On T3, a role may declare `candidates`. Resolve exactly one through the T3 helper: prefer the parent provider when listed, otherwise the first configured candidate. To request another configured provider for a different model perspective, pass `--provider` and record the reason. A `verification workers` candidate role selects, with `--provider`, a candidate whose resolved model is a different family from the checked work's. A provider name alone does not identify the family; when every candidate resolves to that family, label the review same-family. Do not spawn every candidate or retry a failed selection on another candidate. Explicit `@latest` family selectors use the task's live catalog and resolve to exact model IDs before dispatch; reuse those resolved IDs throughout this task. Native host policy and exact pinned targets keep their existing meaning. **Match effort to the job.** Before each spawn, start from the role's resolved policy and the effective `reasoning_effort`, then pick the effort the job needs. The policy order is `low`, `medium`, `high`, `xhigh`, `max`; one step above `high` is `xhigh`. Raise it one step, up to `max`, for the hardest or subtlest work. Lower it one step for judgment and two or more steps, down to `low`, for routine work. Verification workers keep the resolved effort. Change only the effort, never the role's model, T3 target, or `xagent:` entry, so a diverse panel stays diverse. Pass it only through the separate effort control the host adapter names, never inside a model ID. With no effective value or no such control, the worker inherits and the reply says so. An `xagent:` worker gets the adjusted value through `bin/xagent --effort`, and with no effective value runs at its CLI's own setting. If the host rejects the adjusted value, do not try another one. Use the resolved value and say so. Fast mode and priority service tiers cost more, so use them only when the user asked. diff --git a/skills/setup-pstack/SKILL.md b/skills/setup-pstack/SKILL.md index e3c32f9..ed73fa8 100644 --- a/skills/setup-pstack/SKILL.md +++ b/skills/setup-pstack/SKILL.md @@ -34,6 +34,6 @@ Example shared patch, usable on both hosts: } ``` -Role names follow the bundled workflow: the code playbook roles `feature`, `refactoring`, `bug-fix`, `perf-issue`, and `hillclimb`; `hardest tasks` for the hardest changes; `judgment and prose`; `how explorer`, `how explainer`, `why investigators`, `why synthesizer`, `reflect judgment`, and `reflect tooling`; `swarm workers` for swarm fan-out; and `verification workers` for verifier agents, a swarm's verify lanes, and the show-me-your-work handback review. Set `verification workers` per host to a model family other than that host's writers, for example `xagent:claude` under `hosts.codex`; on T3, list one candidate per provider. Panels include `arena runners`, `arena cross-judge pool`, `architect runners`, optional `hardest architect runners`, and `interrogate reviewers`. Use the role a workflow actually requests; do not populate unused choices. +Role names follow the bundled workflow: the code playbook roles `feature`, `refactoring`, `bug-fix`, `perf-issue`, and `hillclimb`; `hardest tasks` for the hardest changes; `judgment and prose`; `how explorer`, `how explainer`, `why investigators`, `why synthesizer`, `reflect judgment`, and `reflect tooling`; `swarm workers` for swarm fan-out; and `verification workers` for verifier agents, a swarm's verify lanes, and the show-me-your-work handback review. Set `verification workers` per host to a model family other than that host's writers, for example `xagent:claude` under `hosts.codex`; on T3, list candidates from different model families. Panels include `arena runners`, `arena cross-judge pool`, `architect runners`, optional `hardest architect runners`, and `interrogate reviewers`. Use the role a workflow actually requests; do not populate unused choices. Shared `required_panel_members`, for example `["xagent:grok", "xagent:gemini"]`, adds those external agents to every panel and the default panel on both hosts. It is rejected in a host override; `null` removes it. From 2d63bb9483faa804b34037fadd4ba6a5e8611b5f Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:41:16 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat(config):=20=E6=96=B0=E5=A2=9E=20auxili?= =?UTF-8?q?ary=5Fpanel=5Fmembers=EF=BC=8C=E8=BE=85=E5=8A=A9=E6=88=90?= =?UTF-8?q?=E5=91=98=E5=A4=B1=E8=B4=A5=E8=AE=B0=E4=B8=BA=E7=BC=BA=E5=8F=A3?= =?UTF-8?q?=E4=B8=8D=E9=98=BB=E5=A1=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xagent 席位从不替换、也不允许少一席收尾,所以作为辅助的外部 agent (如 gemini)一旦连续失败,整组评审就卡住,要用户放弃那一席才能收尾。 上游靠"同家族退回默认模型"保住可用性,xagent 席位走不了这条路。 新增共享字段 auxiliary_panel_members:列出的外部成员按同样规则重试一次, 仍失败就记为覆盖缺口,不计入覆盖与共识结论,也不阻塞其余成员已完成的 评审组;它不会被替换,也不会让角色或其他成员变成可选。它不往评审组里加人, 校验规则与 required_panel_members 相同(只能写在共享层,null 删除), 两份名单共用一个校验函数。 Co-Authored-By: Claude Opus 5.5 --- bin/config.mjs | 34 ++++++++++++++---------- references/runtime.md | 4 +-- scripts/config.test.mjs | 58 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/bin/config.mjs b/bin/config.mjs index 789ec58..2f99053 100755 --- a/bin/config.mjs +++ b/bin/config.mjs @@ -22,6 +22,9 @@ const REASONING_EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]); const DEFAULT_PANEL = ["inherit-parent", "inherit-parent"]; // External agents that must join every panel, so a per-panel or per-host list cannot leave them out. const REQUIRED_MEMBERS = "required_panel_members"; +// External agents whose unresolved outcome is reported as a gap instead of blocking their panel. +const AUXILIARY_MEMBERS = "auxiliary_panel_members"; +const MEMBER_LISTS = [REQUIRED_MEMBERS, AUXILIARY_MEMBERS]; export function getDefaultConfigPath(homeDir = homedir()) { return path.join(homeDir, ".config", "pstack", "config.json"); @@ -121,17 +124,19 @@ function validateEffort(policy, label) { } // null means unset, in a stored config as in a patch. -function validateRequiredMembers(policy, scope, label) { - if (!Object.hasOwn(policy, REQUIRED_MEMBERS)) return; - const field = `${label}.${REQUIRED_MEMBERS}`; - if (scope !== "common") throw new Error(`${field} is shared policy and cannot be set per host`); - const members = policy[REQUIRED_MEMBERS]; - if (members === null) return; - if (!Array.isArray(members) || members.length === 0) throw new Error(`${field} must be a nonempty array or null`); - for (const member of members) { - if (typeof member !== "string" || !XAGENT_VALUE.test(member)) throw new Error(`${field} entries must be xagent:[/]`); +function validateMemberLists(policy, scope, label) { + for (const key of MEMBER_LISTS) { + if (!Object.hasOwn(policy, key)) continue; + const field = `${label}.${key}`; + if (scope !== "common") throw new Error(`${field} is shared policy and cannot be set per host`); + const members = policy[key]; + if (members === null) continue; + if (!Array.isArray(members) || members.length === 0) throw new Error(`${field} must be a nonempty array or null`); + for (const member of members) { + if (typeof member !== "string" || !XAGENT_VALUE.test(member)) throw new Error(`${field} entries must be xagent:[/]`); + } + if (new Set(members).size !== members.length) throw new Error(`${field} entries must be unique`); } - if (new Set(members).size !== members.length) throw new Error(`${field} entries must be unique`); } function validatePolicy(policy, scope, label) { @@ -142,7 +147,7 @@ function validatePolicy(policy, scope, label) { validateRoles(policy.roles, scope, label); validatePanels(policy.panels, scope, label); validateEffort(policy, label); - validateRequiredMembers(policy, scope, label); + validateMemberLists(policy, scope, label); } function validateConfig(config) { @@ -157,7 +162,7 @@ function validateConfig(config) { function validatePatch(patch, scope, label) { requireObject(patch, label); - const allowed = new Set(["roles", "panels", "reasoning_effort", REQUIRED_MEMBERS]); + const allowed = new Set(["roles", "panels", "reasoning_effort", ...MEMBER_LISTS]); for (const key of Object.keys(patch)) { if (!allowed.has(key)) throw new Error(`${label}.${key} is not a supported update field`); } @@ -181,7 +186,7 @@ function validatePatch(patch, scope, label) { } } } - validateRequiredMembers(patch, scope, label); + validateMemberLists(patch, scope, label); if (Object.hasOwn(patch, "reasoning_effort") && patch.reasoning_effort !== null && !REASONING_EFFORTS.has(patch.reasoning_effort)) { throw new Error(`${label}.reasoning_effort must be one of ${[...REASONING_EFFORTS].join(", ")} or null`); } @@ -288,7 +293,7 @@ function applyPatch(policy, patch) { }); } } - for (const key of ["reasoning_effort", REQUIRED_MEMBERS]) { + for (const key of ["reasoning_effort", ...MEMBER_LISTS]) { if (!Object.hasOwn(patch, key)) continue; if (patch[key] === null) delete policy[key]; else policy[key] = cloneJson(patch[key]); @@ -328,6 +333,7 @@ export function showConfig({ configPath = getDefaultConfigPath(), host } = {}) { roles: { ...config.roles, ...hostPolicy.roles }, panels: Object.fromEntries(Object.entries(panels).map(([name, panel]) => [name, withRequired(panel)])), [REQUIRED_MEMBERS]: [...required], + [AUXILIARY_MEMBERS]: [...(config[AUXILIARY_MEMBERS] ?? [])], reasoning_effort: hostPolicy.reasoning_effort ?? config.reasoning_effort ?? null, defaultModel: "inherit-parent", defaultPanel: withRequired(DEFAULT_PANEL), diff --git a/references/runtime.md b/references/runtime.md index 8de8035..47cb1ff 100644 --- a/references/runtime.md +++ b/references/runtime.md @@ -27,11 +27,11 @@ node /bin/config.mjs show --host codex Resolve `` from this skill's installed path. The canonical configuration is `~/.config/pstack/config.json`, outside host plugin caches. If the file is absent, the helper returns inherited defaults without writing anything. Only setup or an explicit configuration request writes preferences. Do not ask every worker to run setup. -Shared `roles`, `panels`, `reasoning_effort`, and `required_panel_members` define policy. Codex and Claude Code apply their respective host overrides from `hosts.codex` and `hosts.claude`; Antigravity's `show` view ignores both and returns only common policy. A T3 session applies the optional `hosts.t3` section instead, and ignores `hosts.codex` and `hosts.claude` whichever host runs it. Shared model choices are `inherit-parent`, `auto`, or an `xagent:[/]` entry (below); other concrete model IDs belong only in `hosts.codex` or `hosts.claude`, and T3 targets `/` only in `hosts.t3`. Missing roles inherit the main conversation; a missing panel uses the helper's `defaultPanel`, two independent inherited-model attempts plus any required panel members. Model availability is validated against the running host, not against upstream names or this JSON schema. A requested unavailable model is an unresolved choice, not permission to silently substitute. Never splice reasoning effort into a model ID. In Antigravity, `reasoning_effort` is a displayed shared preference only; use it only if the current host exposes compatible support. +Shared `roles`, `panels`, `reasoning_effort`, `required_panel_members`, and `auxiliary_panel_members` define policy. Codex and Claude Code apply their respective host overrides from `hosts.codex` and `hosts.claude`; Antigravity's `show` view ignores both and returns only common policy. A T3 session applies the optional `hosts.t3` section instead, and ignores `hosts.codex` and `hosts.claude` whichever host runs it. Shared model choices are `inherit-parent`, `auto`, or an `xagent:[/]` entry (below); other concrete model IDs belong only in `hosts.codex` or `hosts.claude`, and T3 targets `/` only in `hosts.t3`. Missing roles inherit the main conversation; a missing panel uses the helper's `defaultPanel`, two independent inherited-model attempts plus any required panel members. Model availability is validated against the running host, not against upstream names or this JSON schema. A requested unavailable model is an unresolved choice, not permission to silently substitute. Never splice reasoning effort into a model ID. In Antigravity, `reasoning_effort` is a displayed shared preference only; use it only if the current host exposes compatible support. A value `xagent:` (for example `xagent:grok`) names an external agent CLI, not a host model, so it is valid in shared policy. `xagent:/` (for example `xagent:claude/claude-opus-5-5`) also pins that CLI's own model; the model belongs to the agent, not the host, so it is shared policy too. Never pass either as a subagent `model`. Run that worker with `/bin/xagent [/] [--effort ]`, passing everything after `xagent:` as the first argument and the worker's effort as `--effort` (omitted when there is no effective value), only when the selected host exposes the required process execution capability and the task authorizes delegation, as specified in the bundled [xagent skill](../skills/xagent/SKILL.md): `ro` for reviewers, judges, and explorers; `rw` for writers. The parent gives every external worker, including readers, an exclusively owned worktree at the intended revision and every attempt a new output directory. Give it the same standalone brief a native worker would get. Its evidence is process completion, `meta.json` completed/status, its recorded `model`, `effort` and `resolved_models`, and `result.md`, held to the same standard as a native worker's result; a `PASS` still needs the parent's own check. Reject read-only violations and unavailable snapshots without resetting a shared checkout. -Shared `required_panel_members` lists `xagent:` entries that Codex and Claude Code `show` append to every effective panel and to `defaultPanel`, so no per-panel or host override can leave them out. Antigravity's read-only view also displays these common entries, but does not start them; apply the delegation rules above only when the host's actual tools and the task authorization support it. On hosts that execute a panel, run every entry of the effective panel; a pool such as `arena cross-judge pool` still selects one. An `xagent:` entry is never replaced by an inherited model or another agent and never dropped to finish with N-1. Unless the user set a time limit, give an external worker at least xagent's 900-second default. A pinned model that the CLI reports it did not run is `DROPOUT` with reason `model_mismatch`, never a quiet substitute. On `DROPOUT`, inspect partial changes and rerun once into a new output directory; without a user-set limit, double the timeout when the first attempt timed out. A second `DROPOUT`, `BLOCKED`, a missing CLI, or an agent xagent rejects is an unresolved required outcome: report it by agent name, keep it out of coverage and consensus claims, and do not call the panel or task complete unless the user waives it. +Shared `required_panel_members` lists `xagent:` entries that Codex and Claude Code `show` append to every effective panel and to `defaultPanel`, so no per-panel or host override can leave them out. Antigravity's read-only view also displays these common entries, but does not start them; apply the delegation rules above only when the host's actual tools and the task authorization support it. On hosts that execute a panel, run every entry of the effective panel; a pool such as `arena cross-judge pool` still selects one. An `xagent:` entry is never replaced by an inherited model or another agent and never dropped to finish with N-1. Unless the user set a time limit, give an external worker at least xagent's 900-second default. A pinned model that the CLI reports it did not run is `DROPOUT` with reason `model_mismatch`, never a quiet substitute. On `DROPOUT`, inspect partial changes and rerun once into a new output directory; without a user-set limit, double the timeout when the first attempt timed out. A second `DROPOUT`, `BLOCKED`, a missing CLI, or an agent xagent rejects is an unresolved required outcome: report it by agent name, keep it out of coverage and consensus claims, and do not call the panel or task complete unless the user waives it. The one exception is a panel entry also listed in shared `auxiliary_panel_members`: it gets the same retry, but its unresolved outcome is a reported gap that does not block a panel whose other members completed. Name it as a gap, keep it out of coverage and consensus claims, and never replace it with another model or agent. The listing never makes a role or any other panel member optional. Each worker brief carries the selected host, plugin root, configuration path, resolved role/panel policy, scope, and verification predicate. A read-only child without command execution uses this supplied snapshot. If none was supplied, it may read the single shared JSON file and apply the host-over-common precedence; an absent file means inherited defaults. It must not invent a Bash tool or run setup. Use the same policy snapshot throughout one task unless the user changes it. A worker inherits this policy; it does not edit shared preferences. Same-family reviewers are independent attempts, not cross-family evidence. diff --git a/scripts/config.test.mjs b/scripts/config.test.mjs index 20ad158..9796a8e 100644 --- a/scripts/config.test.mjs +++ b/scripts/config.test.mjs @@ -428,6 +428,64 @@ test("Given malformed or host-scoped required panel members, When update or show assert.match(shown.stderr, /required_panel_members/); }); +test("Given auxiliary panel members, When every host view runs show, Then each lists them and panels keep their configured entries", (t) => { + const dir = tempDir(); + t.after(() => rmSync(dir, { recursive: true, force: true })); + const configPath = path.join(dir, "config.json"); + const inputPath = path.join(dir, "patch.json"); + const config = validConfig(); + config.hosts.codex.panels["interrogate reviewers"] = ["inherit-parent", "xagent:claude", "xagent:gemini"]; + config.hosts.codex.panels["arena cross-judge pool"] = ["xagent:claude"]; + writeJson(configPath, config); + writeJson(inputPath, { auxiliary_panel_members: ["xagent:gemini"] }); + + const update = runCli(["update", "--input", inputPath, "--config", configPath]); + assert.equal(update.status, 0, update.stderr); + for (const host of ["codex", "claude", "t3", "antigravity"]) { + const effective = JSON.parse(runCli(["show", "--host", host, "--config", configPath]).stdout).effective; + assert.deepEqual(effective.auxiliary_panel_members, ["xagent:gemini"], host); + assert.deepEqual(effective.required_panel_members, [], host); + assert.deepEqual(effective.defaultPanel, ["inherit-parent", "inherit-parent"], host); + } + const codex = JSON.parse(runCli(["show", "--host", "codex", "--config", configPath]).stdout).effective; + assert.deepEqual(codex.panels["interrogate reviewers"], ["inherit-parent", "xagent:claude", "xagent:gemini"]); + assert.deepEqual(codex.panels["arena cross-judge pool"], ["xagent:claude"]); + + writeJson(inputPath, { auxiliary_panel_members: null }); + assert.equal(runCli(["update", "--input", inputPath, "--config", configPath]).status, 0); + assert.deepEqual(JSON.parse(runCli(["show", "--host", "codex", "--config", configPath]).stdout).effective.auxiliary_panel_members, []); + assert.equal(Object.hasOwn(JSON.parse(readFileSync(configPath, "utf8")), "auxiliary_panel_members"), false); +}); + +test("Given malformed or host-scoped auxiliary panel members, When update or show runs, Then they are rejected without writing", (t) => { + const dir = tempDir(); + t.after(() => rmSync(dir, { recursive: true, force: true })); + const configPath = path.join(dir, "config.json"); + const inputPath = path.join(dir, "patch.json"); + writeJson(configPath, validConfig()); + const original = readFileSync(configPath, "utf8"); + + for (const value of [[], "xagent:gemini", ["inherit-parent"], ["xagent:gemini", "xagent:gemini"], ["xagent:Gemini Pro"]]) { + writeJson(inputPath, { auxiliary_panel_members: value }); + const result = runCli(["update", "--input", inputPath, "--config", configPath]); + assert.notEqual(result.status, 0, JSON.stringify(value)); + assert.equal(readFileSync(configPath, "utf8"), original); + } + writeJson(inputPath, { auxiliary_panel_members: ["xagent:gemini"] }); + for (const host of ["codex", "claude", "t3"]) { + const hostUpdate = runCli(["update", "--host", host, "--input", inputPath, "--config", configPath]); + assert.notEqual(hostUpdate.status, 0, host); + assert.equal(readFileSync(configPath, "utf8"), original); + } + + const handWritten = validConfig(); + handWritten.hosts.codex.auxiliary_panel_members = ["xagent:gemini"]; + writeJson(configPath, handWritten); + const shown = runCli(["show", "--host", "codex", "--config", configPath]); + assert.notEqual(shown.status, 0); + assert.match(shown.stderr, /auxiliary_panel_members/); +}); + test("Given a malformed xagent entry in common policy, When update runs, Then it is rejected without writing", (t) => { const dir = tempDir(); t.after(() => rmSync(dir, { recursive: true, force: true })); From 8f61f5d3530110e0e6cb11924d04f65215267c91 Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:41:16 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(policy):=20=E6=8E=A8=E7=90=86=E5=BC=BA?= =?UTF-8?q?=E5=BA=A6=E4=BB=A5=E8=87=AA=E5=AE=B6=20agent=20=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E4=B8=BA=E5=87=86=EF=BC=8Csetup=20=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=8E=A8=E8=8D=90=E8=B7=A8=E5=8E=82=E5=95=86=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原契约在设了 reasoning_effort 时把强度传给每个原生子 agent,会盖掉 ~/.claude/agents、~/.codex/agents 里各自配的推理强度。现在 agent 定义 自己设了强度的就保持定义里的值,共享强度只作用于 xagent 外部 worker 和定义里没设强度的子 agent;外部 CLI 不传强度时会沿用用户交互用的默认值, 例如 codex 的 low。真实 host E2E 的 prompt 改为把原生 worker 派成 没有自带强度的 agent 类型,继续覆盖"强度传到原生 worker"这条路径。 fork 的 inherit-parent 默认值在多方环节只有一家,上游默认是两家。 setup-pstack 现在在另一家 CLI 已登录时提出跨厂商布局:每个评审组是 本 host 模型加另一家,裁判池只放另一家,辅助厂商标为 auxiliary; 写入前先跟用户确认。README、ADAPTATION 同步记录这些决定。 Co-Authored-By: Claude Opus 5.5 --- ADAPTATION.md | 2 ++ README.md | 2 +- README.zh-CN.md | 2 ++ references/claude-runtime.md | 2 +- references/codex-runtime.md | 2 +- scripts/pstack-host-e2e-native.test.py | 3 ++- scripts/pstack-host-e2e.py | 3 ++- skills/setup-pstack/SKILL.md | 8 +++++++- 8 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ADAPTATION.md b/ADAPTATION.md index 79c8417..fdcc04b 100644 --- a/ADAPTATION.md +++ b/ADAPTATION.md @@ -43,6 +43,8 @@ Model tiering by role follows upstream again. Poteto-mode's Subagents section re `verification workers` is a local role with no upstream line. Upstream runs orchestrate's verifier and show-me-your-work's handback review on a different model family than the work. On Codex or Claude Code another family needs an `xagent:` entry, so verification takes its own role instead of sharing `swarm workers` with fan-out workers, and each host can point it at the other vendor while swarms keep their own worker. A swarm's verify lanes, as in autopilot's swarm-verify, and the handback review read it too. On T3 a candidate role picks the candidate whose resolved model family differs from the checked work's, because a provider name alone does not identify the family. +Two local rules keep cross-vendor panels usable. Shared `auxiliary_panel_members` names external members whose unresolved outcome is a reported gap rather than a blocker, so a supporting vendor's outage does not stop a review its primary members finished; upstream reaches the same availability by falling back within a family, which xagent entries never do. Native agent definitions own their effort: on Codex and Claude Code a worker's effort goes to a native agent type only when its definition sets none, so `reasoning_effort` mainly reaches `xagent:` workers, whose CLIs otherwise run at the user's interactive default. setup-pstack proposes a cross-vendor layout for multi-party steps when another vendor's CLI is signed in, because this fork's `inherit-parent` defaults stay one family where upstream's defaults pair two. + The orch store lock carries a local fix for three races that upstream still has at `e5136d82`: a writer killed between the exclusive open and its pid write left an empty lock that only `--force` could pass, two writers that saw the same dead holder could both take the lock, and a release could unlink the lock a `--force` writer had just put in its place. `acquireLock` now writes the pid to a private file and hard-links it into place, falling back to the exclusive open where hard links are unsupported. Every read-then-unlink of the lock, in a takeover or a release, runs behind a `.orch.lock.takeover` claim, and a takeover re-reads the holder before it unlinks. A writer that meets a live claim is refused with `is being released or replaced; retry`; a release that meets one retries every 10 ms, so `close` waits while a live claimant, even a stopped one, holds it. The fix and its multi-process race tests are adapted from michael-denyer/pstack-claude #219 (`eef8f7c6`) and #238 (`de804764`), MIT, Copyright (c) 2026 Michael Denyer, whose notice is added to `LICENSE`. That fork's TLA+ model and its retry when a lock vanishes before its holder is read are not taken. The lock lives in `skills/poteto-mode/scripts/orch/lock.ts`, with `UserError` and `errorCode` in `orch/errors.ts`, because this fork replaced upstream's lock wholesale and `store.ts` was already past 1,000 lines; its race tests live in `orch/lock.test.ts`, sharing `orch/store.test-helper.ts` with `orch.test.ts`. Each acquire also removes the private pid files and staged claims that a writer killed mid-claim leaves behind, judged by the pid in their names, which the kill-at-every-step test now checks. The frontier code stays in `store.ts` even though it is large, so upstream's edits there still merge file by file. Its GitHub remote parsing is `skills/poteto-mode/scripts/github-remote.ts`, moved out of upstream's `watch-pr/github.ts` so `orch` and `watch-pr` share one parser. ## Antigravity integration diff --git a/README.md b/README.md index 457d799..a33be8d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Marketplace registration is needed only once per host. Host caches are generated - Claude Code entry: `/pstack:poteto-mode`. - Optional setup: `$pstack-codex:setup-pstack` or `/pstack:setup-pstack`. -Preferences are shared in `~/.config/pstack/config.json`. Roles inherit the main conversation unless configured; workers receive the resolved policy and do not need setup. Concrete model choices are host-scoped so one vendor's model ID never leaks into another host. The exception is an external agent's own model, such as `xagent:claude/claude-opus-5-5`: xagent hands it to that agent's CLI from either host, so it can be shared. Shared reasoning and panel-size preferences apply to both when the actual runtime supports them. Shared `required_panel_members` adds external agents such as `xagent:grok` to every panel on both hosts, and those entries are never silently skipped. See [the runtime contract](./references/runtime.md). +Preferences are shared in `~/.config/pstack/config.json`. Roles inherit the main conversation unless configured; workers receive the resolved policy and do not need setup. Concrete model choices are host-scoped so one vendor's model ID never leaks into another host. The exception is an external agent's own model, such as `xagent:claude/claude-opus-5-5`: xagent hands it to that agent's CLI from either host, so it can be shared. Shared reasoning and panel-size preferences apply to both when the actual runtime supports them. Shared `required_panel_members` adds external agents such as `xagent:grok` to every panel on both hosts, and those entries are never silently skipped. Shared `auxiliary_panel_members` marks external members, such as `xagent:gemini`, whose failure after a retry is reported as a gap instead of blocking a panel the other members finished. On Codex and Claude Code, an agent type whose definition sets its own effort keeps it; shared reasoning reaches the rest, including external agents. See [the runtime contract](./references/runtime.md). Examples below use `$skill` as a short reference to the bundled skill; in Claude Code invoke `/pstack:skill` or read its file through the host's skill interface. diff --git a/README.zh-CN.md b/README.zh-CN.md index f1e8510..6102218 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -192,6 +192,8 @@ pstack 本身不安装定时器;长任务流程也不保证会话退出或主 共享配置中的 `required_panel_members`(例如 `["xagent:grok", "xagent:gemini"]`)会把这些外部 Agent 追加到两个主控的每个评审组和默认评审组,单个评审组或主控覆盖都无法遗漏它们。评审组里的 `xagent:` 不会被替换成继承模型,也不会以 N-1 静默跳过;重试和失败报告规则见[运行时契约](./references/runtime.md)。 +共享配置中的 `auxiliary_panel_members`(例如 `["xagent:gemini"]`)把这些外部 Agent 标为辅助成员:重试一次后仍失败,只记为覆盖缺口,不阻塞其余成员已完成的评审组;它们仍不会被替换成别的模型。在 Codex 和 Claude Code 上,agent 定义里自己设了推理强度的子 Agent 保持定义里的值,共享的 `reasoning_effort` 作用于其余 worker,包括外部 Agent。 + | 配置值 | 本机执行入口 | |---|---| | `xagent:claude` | `claude` | diff --git a/references/claude-runtime.md b/references/claude-runtime.md index e474121..03fc1ff 100644 --- a/references/claude-runtime.md +++ b/references/claude-runtime.md @@ -3,7 +3,7 @@ Read [the shared runtime](./runtime.md) first. This file defines only Claude Code behavior. Use the current tool schemas even when an installed CLI version differs from the version used to validate this package. - Entry points are `/pstack:poteto-mode`, `/pstack:setup-pstack`, and other `/pstack:` names. The same `skills/` files are used by Codex. Do not call `$pstack-codex:*` as Claude commands. -- Resolve preferences with `node /bin/config.mjs show --host claude`. Default to the main conversation's model. For shared agents, frontmatter `model: inherit` preserves inheritance. Use a concrete per-call model only when the actual Agent schema and account support it. Claude aliases/model IDs are not Cursor slugs or Codex IDs; GPT/Grok models require a separately configured, authorized provider/bridge and must not be assumed available; `xagent:` policy entries are that bridge for local agent CLIs (see the shared runtime). Pass a worker's effort, including poteto-mode's per-job adjustment, through the Agent tool's separate `effort` field when its schema exposes one; otherwise inherit session effort. +- Resolve preferences with `node /bin/config.mjs show --host claude`. Default to the main conversation's model. For shared agents, frontmatter `model: inherit` preserves inheritance. Use a concrete per-call model only when the actual Agent schema and account support it. Claude aliases/model IDs are not Cursor slugs or Codex IDs; GPT/Grok models require a separately configured, authorized provider/bridge and must not be assumed available; `xagent:` policy entries are that bridge for local agent CLIs (see the shared runtime). Pass a worker's effort, including poteto-mode's per-job adjustment, through the Agent tool's separate `effort` field when its schema exposes one, except to an agent type whose definition sets its own `effort`: that definition owns the worker's effort, as it owns the model when the role is `inherit-parent`. Without the field, the worker inherits session effort. - Use Claude's actual `Agent` tool with its supported `subagent_type`; available types can include `general-purpose`, `Explore`, `pstack:poteto-agent`, and `pstack:comment-sicko`. The two plugin agent files are native Claude definitions. The comment reviewer has only Read/Grep/Glob and returns proposals, not edits. The general workflow agent reads the same poteto-mode and shared configuration as the parent. - Respect the current nesting and concurrency limits. Select background execution only when the tool supports it. Track returned IDs and actual completion notifications/output, and inspect artifacts before accepting results. Do not call Codex `collaboration.*`, assume an empty output means success, or interrupt merely to tidy the agent list. If a role cannot delegate, it performs feasible scoped work and returns evidence. - In a one-shot/headless parent (`claude -p`), join external workers before the final reply. Run parallel xagent commands with `&` inside one foreground Bash call and `wait` for every returned PID; give that call a timeout longer than the worker deadlines and termination grace. Use a native blocking wait only when its current schema actually provides one. Ending with a promise to receive background notifications can exit the parent and cancel those workers; a Monitor or shell sentinel is not a substitute for collecting their terminal results. diff --git a/references/codex-runtime.md b/references/codex-runtime.md index 4d40d51..631774b 100644 --- a/references/codex-runtime.md +++ b/references/codex-runtime.md @@ -3,7 +3,7 @@ Read [the shared runtime](./runtime.md) first. This file defines only Codex-specific behavior. - Entry points keep the existing namespace, such as `$pstack-codex:poteto-mode` and `$pstack-codex:setup-pstack`. -- Resolve preferences with `node /bin/config.mjs show --host codex`. Validate concrete IDs and effort against the current collaboration schema. Fixed-model roles cannot be overridden. `inherit-parent`/`auto` omit the model field. Pass `reasoning_effort`, including poteto-mode's per-job adjustment, only if the selected role and actual schema accept it. +- Resolve preferences with `node /bin/config.mjs show --host codex`. Validate concrete IDs and effort against the current collaboration schema. Fixed-model roles cannot be overridden. `inherit-parent`/`auto` omit the model field. Pass `reasoning_effort`, including poteto-mode's per-job adjustment, only if the selected role and actual schema accept it and the role's definition sets no `model_reasoning_effort`; a definition that sets one owns the worker's effort. - Use exposed collaboration tools, which may include `spawn_agent`, `send_message`, `followup_task`, `list_agents`, `wait_agent`, and `interrupt_agent`. Use the real `agent_type` and available role names. Do not send Claude/Cursor-only fields such as `subagent_type`, `run_in_background`, `readonly`, `environment`, or `cloud_base_branch`. - `agents/poteto-agent.md` and `agents/comment-sicko.md` are prompt templates here, not registered Codex roles. Pass the file pointer to an appropriate supported role. Claude frontmatter in those shared files does not register a Codex role or enforce its tools; enforce scope through the selected host role and brief. - Close children only after a final answer, explicit completion event, or confirmed completed/failed/canceled status. Preserve host-specific cancellation and progress rules. diff --git a/scripts/pstack-host-e2e-native.test.py b/scripts/pstack-host-e2e-native.test.py index bfdc1c6..3fad5d1 100644 --- a/scripts/pstack-host-e2e-native.test.py +++ b/scripts/pstack-host-e2e-native.test.py @@ -621,7 +621,8 @@ def test_given_stub_hosts_when_exercised_then_launch_settings_prompt_rules_and_n self.assertIn(f"exclusive worktree at fixture base {report['base']} and have it leave its change uncommitted", prompt) self.assertIn(f"a native reviewer changes no files and runs python3 -B {ROOT / 'scripts/e2e-snapshot.py'} " "as its first and as its last shell command", prompt) - self.assertIn("pass an effort to every worker, native or xagent", prompt) + self.assertIn("pass an effort to every worker, native or xagent; dispatch each native worker as an agent type " + "whose definition sets no effort of its own", prompt) if host == "claude": self.assertIn("-p", launch["argv"]) self.assertIn("--no-session-persistence", launch["argv"]) diff --git a/scripts/pstack-host-e2e.py b/scripts/pstack-host-e2e.py index ef179fd..0d48f18 100644 --- a/scripts/pstack-host-e2e.py +++ b/scripts/pstack-host-e2e.py @@ -614,7 +614,8 @@ def exercise(host, run, host_timeout, check_timeout=30): host's file-edit tool (Write or Edit in Claude Code, apply_patch in Codex); a native reviewer changes no files and runs python3 -B {SNAPSHOT_TOOL} as its first and as its last shell command in that worktree, each as a command of its own. -When the effective policy sets reasoning_effort, pass an effort to every worker, native or xagent. +When the effective policy sets reasoning_effort, pass an effort to every worker, native or xagent; dispatch each native +worker as an agent type whose definition sets no effort of its own, so that effort applies. Report the resolved routes, actual worker receipt paths, findings, your own test output, and any gaps. End with PSTACK_E2E: PASS only if the repair, all configured reviews and your independent tests are complete, with no unresolved reproduced violation of the stated contract; otherwise PSTACK_E2E: FAIL. diff --git a/skills/setup-pstack/SKILL.md b/skills/setup-pstack/SKILL.md index ed73fa8..3137b6d 100644 --- a/skills/setup-pstack/SKILL.md +++ b/skills/setup-pstack/SKILL.md @@ -20,7 +20,7 @@ In Antigravity, run `node /bin/config.mjs show --host antigravity` 1. Identify the current host from its actual tools and read the effective configuration with `node /bin/config.mjs show --host `. Missing configuration means all roles inherit and panels use two independent attempts; setup is optional. 2. For a setup request, run `node /bin/config.mjs init`. It creates `~/.config/pstack/config.json` only when absent and imports any legacy `~/.codex/pstack/models.json` or `~/.claude/pstack/models.json` into that host's overrides. Existing shared configuration is authoritative. Legacy files remain untouched and are no longer runtime sources. 3. Honor preferences already given. Shared roles and panel entries can use only `inherit-parent`, `auto`, or `xagent:` (an external agent CLI dispatched through xagent, for example `xagent:grok`), optionally with that CLI's own model as `xagent:/`, for example `xagent:claude/claude-opus-5-5`; check the model with that CLI, such as `grok models` or `pi --list-models`, before saving it. Any other concrete model goes into the current host's override after checking actual availability and role constraints. Keep reasoning separate. Do not infer IDs from upstream brand names or silently substitute for an unavailable explicit choice. Preserve the other host's choices. -4. Write a small JSON patch containing only the requested `roles`, `panels`, `reasoning_effort`, and/or `required_panel_members`. Apply shared preferences with `node /bin/config.mjs update --input `; add `--host codex`, `--host claude`, or `--host t3` for host-specific overrides. The helper merges per-role changes atomically. A null role/panel or null effort removes that override and restores inheritance from the next layer. Delete the scratch patch after readback, not the evidence. Concurrent edits fail visibly rather than overwriting each other. +4. Write a small JSON patch containing only the requested `roles`, `panels`, `reasoning_effort`, `required_panel_members`, and/or `auxiliary_panel_members`. Apply shared preferences with `node /bin/config.mjs update --input `; add `--host codex`, `--host claude`, or `--host t3` for host-specific overrides. The helper merges per-role changes atomically. A null role/panel or null effort removes that override and restores inheritance from the next layer. Delete the scratch patch after readback, not the evidence. Concurrent edits fail visibly rather than overwriting each other. 5. Read back both hosts with `show --host codex` and `show --host claude`, plus `show --host t3` when a T3 section exists. Report the shared path and effective choices. Validation of JSON/model names is not proof of model execution. Workers inherit the resolved policy from the parent; do not configure each worker separately. 6. Inspect the current project's existing verify skill or harness. If neither exists, mention `create-verification-skill` once; generate and exercise one only when requested. @@ -37,3 +37,9 @@ Example shared patch, usable on both hosts: Role names follow the bundled workflow: the code playbook roles `feature`, `refactoring`, `bug-fix`, `perf-issue`, and `hillclimb`; `hardest tasks` for the hardest changes; `judgment and prose`; `how explorer`, `how explainer`, `why investigators`, `why synthesizer`, `reflect judgment`, and `reflect tooling`; `swarm workers` for swarm fan-out; and `verification workers` for verifier agents, a swarm's verify lanes, and the show-me-your-work handback review. Set `verification workers` per host to a model family other than that host's writers, for example `xagent:claude` under `hosts.codex`; on T3, list candidates from different model families. Panels include `arena runners`, `arena cross-judge pool`, `architect runners`, optional `hardest architect runners`, and `interrogate reviewers`. Use the role a workflow actually requests; do not populate unused choices. Shared `required_panel_members`, for example `["xagent:grok", "xagent:gemini"]`, adds those external agents to every panel and the default panel on both hosts. It is rejected in a host override; `null` removes it. + +Shared `auxiliary_panel_members`, for example `["xagent:gemini"]`, marks external panel members whose failure after the retry is a reported gap instead of a blocker. It adds no member to any panel, so list the agent in the panels it should join. It is rejected in a host override; `null` removes it. + +Multi-party steps are the panels above, `reflect judgment` with `reflect tooling`, and `verification workers`. Upstream gives each of them two model families by default; this fork's `inherit-parent` defaults stay one family until configured. When another vendor's CLI is installed and signed in, propose a cross-vendor layout for them: the host's own model plus the other vendor through `xagent:` in each panel, and only the other vendor in `arena cross-judge pool`, since arena picks a single judge from it. Mark a supporting vendor auxiliary rather than required when it should not hold up a review. Confirm the proposal with the user before writing it. + +On Codex and Claude Code, `reasoning_effort` reaches `xagent:` workers and native agent types whose definition sets no effort; a definition that sets its own effort keeps it. Without a value, an external CLI runs at its own default, which may be the user's interactive setting. From d5593d561c904d89d3709d0d1431d20174534404 Mon Sep 17 00:00:00 2001 From: Martin <60476606+mtmtian@users.noreply.github.com> Date: Sun, 18 Oct 2026 14:43:06 +0800 Subject: [PATCH 6/6] =?UTF-8?q?docs(runtime):=20agent=20=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=8B=A5=E6=9C=89=E6=8E=A8=E7=90=86=E5=BC=BA=E5=BA=A6=E7=9A=84?= =?UTF-8?q?=E5=8E=9F=E5=88=99=E5=86=99=E8=BF=9B=E5=85=B1=E4=BA=AB=E5=A5=91?= =?UTF-8?q?=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这条规则是 reasoning_effort 的跨 host 语义,之前只写在 claude、codex 两个适配文件里,共享契约仍暗示强度会传给每个 worker。现在 runtime.md 写一次原则,适配文件只保留各自的字段名。claude-runtime 开头"默认用主 会话模型"补上"除非 agent 定义自己设了模型",和同一行的新规则不再矛盾。 Co-Authored-By: Claude Opus 5.5 --- references/claude-runtime.md | 2 +- references/runtime.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/references/claude-runtime.md b/references/claude-runtime.md index 03fc1ff..b32db44 100644 --- a/references/claude-runtime.md +++ b/references/claude-runtime.md @@ -3,7 +3,7 @@ Read [the shared runtime](./runtime.md) first. This file defines only Claude Code behavior. Use the current tool schemas even when an installed CLI version differs from the version used to validate this package. - Entry points are `/pstack:poteto-mode`, `/pstack:setup-pstack`, and other `/pstack:` names. The same `skills/` files are used by Codex. Do not call `$pstack-codex:*` as Claude commands. -- Resolve preferences with `node /bin/config.mjs show --host claude`. Default to the main conversation's model. For shared agents, frontmatter `model: inherit` preserves inheritance. Use a concrete per-call model only when the actual Agent schema and account support it. Claude aliases/model IDs are not Cursor slugs or Codex IDs; GPT/Grok models require a separately configured, authorized provider/bridge and must not be assumed available; `xagent:` policy entries are that bridge for local agent CLIs (see the shared runtime). Pass a worker's effort, including poteto-mode's per-job adjustment, through the Agent tool's separate `effort` field when its schema exposes one, except to an agent type whose definition sets its own `effort`: that definition owns the worker's effort, as it owns the model when the role is `inherit-parent`. Without the field, the worker inherits session effort. +- Resolve preferences with `node /bin/config.mjs show --host claude`. Default to the main conversation's model unless the selected agent type's definition sets one. For shared agents, frontmatter `model: inherit` preserves inheritance. Use a concrete per-call model only when the actual Agent schema and account support it. Claude aliases/model IDs are not Cursor slugs or Codex IDs; GPT/Grok models require a separately configured, authorized provider/bridge and must not be assumed available; `xagent:` policy entries are that bridge for local agent CLIs (see the shared runtime). Pass a worker's effort, including poteto-mode's per-job adjustment, through the Agent tool's separate `effort` field when its schema exposes one, except to an agent type whose definition sets its own `effort`: that definition owns the worker's effort, as it owns the model when the role is `inherit-parent`. Without the field, the worker inherits session effort. - Use Claude's actual `Agent` tool with its supported `subagent_type`; available types can include `general-purpose`, `Explore`, `pstack:poteto-agent`, and `pstack:comment-sicko`. The two plugin agent files are native Claude definitions. The comment reviewer has only Read/Grep/Glob and returns proposals, not edits. The general workflow agent reads the same poteto-mode and shared configuration as the parent. - Respect the current nesting and concurrency limits. Select background execution only when the tool supports it. Track returned IDs and actual completion notifications/output, and inspect artifacts before accepting results. Do not call Codex `collaboration.*`, assume an empty output means success, or interrupt merely to tidy the agent list. If a role cannot delegate, it performs feasible scoped work and returns evidence. - In a one-shot/headless parent (`claude -p`), join external workers before the final reply. Run parallel xagent commands with `&` inside one foreground Bash call and `wait` for every returned PID; give that call a timeout longer than the worker deadlines and termination grace. Use a native blocking wait only when its current schema actually provides one. Ending with a promise to receive background notifications can exit the parent and cancel those workers; a Monitor or shell sentinel is not a substitute for collecting their terminal results. diff --git a/references/runtime.md b/references/runtime.md index 47cb1ff..4c0e41f 100644 --- a/references/runtime.md +++ b/references/runtime.md @@ -27,7 +27,7 @@ node /bin/config.mjs show --host codex Resolve `` from this skill's installed path. The canonical configuration is `~/.config/pstack/config.json`, outside host plugin caches. If the file is absent, the helper returns inherited defaults without writing anything. Only setup or an explicit configuration request writes preferences. Do not ask every worker to run setup. -Shared `roles`, `panels`, `reasoning_effort`, `required_panel_members`, and `auxiliary_panel_members` define policy. Codex and Claude Code apply their respective host overrides from `hosts.codex` and `hosts.claude`; Antigravity's `show` view ignores both and returns only common policy. A T3 session applies the optional `hosts.t3` section instead, and ignores `hosts.codex` and `hosts.claude` whichever host runs it. Shared model choices are `inherit-parent`, `auto`, or an `xagent:[/]` entry (below); other concrete model IDs belong only in `hosts.codex` or `hosts.claude`, and T3 targets `/` only in `hosts.t3`. Missing roles inherit the main conversation; a missing panel uses the helper's `defaultPanel`, two independent inherited-model attempts plus any required panel members. Model availability is validated against the running host, not against upstream names or this JSON schema. A requested unavailable model is an unresolved choice, not permission to silently substitute. Never splice reasoning effort into a model ID. In Antigravity, `reasoning_effort` is a displayed shared preference only; use it only if the current host exposes compatible support. +Shared `roles`, `panels`, `reasoning_effort`, `required_panel_members`, and `auxiliary_panel_members` define policy. Codex and Claude Code apply their respective host overrides from `hosts.codex` and `hosts.claude`; Antigravity's `show` view ignores both and returns only common policy. A T3 session applies the optional `hosts.t3` section instead, and ignores `hosts.codex` and `hosts.claude` whichever host runs it. Shared model choices are `inherit-parent`, `auto`, or an `xagent:[/]` entry (below); other concrete model IDs belong only in `hosts.codex` or `hosts.claude`, and T3 targets `/` only in `hosts.t3`. Missing roles inherit the main conversation; a missing panel uses the helper's `defaultPanel`, two independent inherited-model attempts plus any required panel members. Model availability is validated against the running host, not against upstream names or this JSON schema. A requested unavailable model is an unresolved choice, not permission to silently substitute. Never splice reasoning effort into a model ID. On Codex and Claude Code, a native agent type's own definition owns its effort when it sets one, and its model when the role is `inherit-parent`; the effective `reasoning_effort` reaches every other worker, including `xagent:` workers through `--effort`. The host adapter names the definition fields. In Antigravity, `reasoning_effort` is a displayed shared preference only; use it only if the current host exposes compatible support. A value `xagent:` (for example `xagent:grok`) names an external agent CLI, not a host model, so it is valid in shared policy. `xagent:/` (for example `xagent:claude/claude-opus-5-5`) also pins that CLI's own model; the model belongs to the agent, not the host, so it is shared policy too. Never pass either as a subagent `model`. Run that worker with `/bin/xagent [/] [--effort ]`, passing everything after `xagent:` as the first argument and the worker's effort as `--effort` (omitted when there is no effective value), only when the selected host exposes the required process execution capability and the task authorizes delegation, as specified in the bundled [xagent skill](../skills/xagent/SKILL.md): `ro` for reviewers, judges, and explorers; `rw` for writers. The parent gives every external worker, including readers, an exclusively owned worktree at the intended revision and every attempt a new output directory. Give it the same standalone brief a native worker would get. Its evidence is process completion, `meta.json` completed/status, its recorded `model`, `effort` and `resolved_models`, and `result.md`, held to the same standard as a native worker's result; a `PASS` still needs the parent's own check. Reject read-only violations and unavailable snapshots without resetting a shared checkout.