From f7e71b271ee11229a32ca554ba73b64520878f83 Mon Sep 17 00:00:00 2001 From: mdsmithaustin <15272014+mdsmithaustin@users.noreply.github.com> Date: Tue, 20 Oct 2026 21:35:35 -0600 Subject: [PATCH 1/5] feat(setup-pstack): pin the trail reviewer and show its step The trail reviewer steps off the work model by rule 7, and a Codex user who wrote sol got astra with no sign of it at setup. Setup now prints the stepped reviewer beside the written one, the step note names the roles that allow the target, and `trail reviewer step: off` keeps the written model and effort on a match, labeled same-model. The rules now say a stepped reviewer's effort follows the work effort. --- PORTING.md | 2 +- skills/pstack-harness/references/roles.md | 2 +- skills/setup-pstack/SKILL.md | 4 +- .../setup-pstack/references/models-config.md | 3 +- .../scripts/check-models-config.py | 50 +++++-- .../poteto-mode/scripts/orch/recovery.test.ts | 2 +- .../scripts/test_check_models_config.py | 136 ++++++++++++++++-- 7 files changed, 177 insertions(+), 22 deletions(-) diff --git a/PORTING.md b/PORTING.md index b53a22b3..5f9c41ae 100644 --- a/PORTING.md +++ b/PORTING.md @@ -72,7 +72,7 @@ Upstream is the source of truth for the workflows themselves. This file records - Babysit CI classification is a port edit. [Babysit step 7](skills/poteto-mode/playbooks/babysit.md) owns the classification and retry rules. Preserve that step on upstream sync. - PR body finalization is a port edit (2026-10, #177). [Opening a PR](skills/poteto-mode/playbooks/opening-a-pr.md) owns PR body finalization, including non-owner reports. [Babysit](skills/poteto-mode/playbooks/babysit.md) applies them after a repair push. Upstream has neither the provisional-body rule nor the Babysit body re-check. Keep both on sync. - Repository selection is a port addition (2026-10, #169). [Opening a PR, Forge](skills/poteto-mode/playbooks/opening-a-pr.md) owns the origin-resolution rule for both github.com and Enterprise. Preserve the full host, owner, and repository in every project-bound PR and issue call, and explicit `--hostname ` in API and token calls. Keep it and the watcher's `currentPr` repository, branch, and detached-HEAD handling on sync. Port-owned examples carry explicit `-R`: Opening a PR's attachment read, Babysit steps 6 and 8, Orchestrate, Code review, and deslop. Babysit, Code review, and deslop resolve the repository without Opening a PR's Forge rule, so each of their `-R` sites says `//` comes from origin's fetch URL. Upstream-owned `gh pr` commands that read or change PR state also carry it (port edit): Shipping steps 4 and 8, why step 2, and why's code-archaeology reference. In this fork, Shipping's bare `gh pr view 205` read cursor/plugins#205 as merged while this repository's #205 was open, and why never loads Opening a PR. Keep `-R`, with `//` from origin's fetch URL, at those sites on sync. Other upstream-owned examples in Opening a PR, Autopilot-stack, and Multi-phase plan remain unchanged. -- Other roles beyond upstream's roster: `trail reviewer` (the show-me-your-work reviewer and, since 2026-10, every independent verdict and review; upstream says "a different model family", which has no answer inside one vendor) and `default` (the entry for a spawn whose skill names no role, shipped as `inherit-parent`). Step 1 of the harness skill's Spawn a role sends every role-less spawn through `default`; on sync, keep these roles and the show-me-your-work wording that resolves through `trail reviewer`, and keep the resolver's `--work-model` step as defined in [models config rule 7](skills/setup-pstack/references/models-config.md#resolution). +- Other roles beyond upstream's roster: `trail reviewer` (the show-me-your-work reviewer and, since 2026-10, every independent verdict and review; upstream says "a different model family", which has no answer inside one vendor) and `default` (the entry for a spawn whose skill names no role, shipped as `inherit-parent`). Step 1 of the harness skill's Spawn a role sends every role-less spawn through `default`; on sync, keep these roles and the show-me-your-work wording that resolves through `trail reviewer`, and keep the resolver's `--work-model` step and its `trail reviewer step: off` pin as defined in [models config rule 7](skills/setup-pstack/references/models-config.md#resolution). - `routine` is a third role beyond upstream's roster (port addition, 2026-10). A read-only scan, parse, or watch subagent that returns a reduced finding runs on it. The sites are poteto-mode's subagent defaults, `automate-me` slice mining, the Worktree cleanup, Trace forensics, Runtime forensics, Session pickup, and Autonomous run playbooks, and the Guard the Context Window principle. Upstream names no role for these spawns, so before this change the port sent them through `default`, which inherits the lead's model. The shipped model and effort live in [the models config defaults](skills/setup-pstack/examples/pstack-models.md). Explorers in `recall`, `how`, and the multi-phase plan stay on `how explorer`. On sync, keep the role in `check-models-config.py`, `role-contract.json`, and the shipped examples file, and keep each site's `routine` sentence. - **Authoring or modifying a skill** sends skill steps through the STE layer of **technical-writing** (port addition, 2026-10). Skill steps are procedures an agent executes. ASD-STE100 was written for procedures. Upstream's authoring guidance names no style standard. On sync, keep the sentence. - **Opening a PR** says how to post PR evidence (port addition, 2026-09). Follow any attachment rule the repo's `AGENTS.md` or PR template sets, upload with `gh … --attach` (gh 2.99.0 or later), never through undocumented endpoints, and confirm each posted URL returns `200` with `gh auth token`. Report an upload blocker only when no gh at 2.99.0 or later is available or a retry fails. Upstream says only to attach videos or screenshots. Keep both the repo-rule clause and the **Attachments** paragraph on sync. diff --git a/skills/pstack-harness/references/roles.md b/skills/pstack-harness/references/roles.md index 49a2bab0..fc82244d 100644 --- a/skills/pstack-harness/references/roles.md +++ b/skills/pstack-harness/references/roles.md @@ -30,7 +30,7 @@ Every pstack spawn runs a role from the models config, such as `feature` or `how python3 "${PSTACK_SKILLS_ROOT:?}/setup-pstack/scripts/check-models-config.py" --resolve --harness [--work-model @] [...] ``` - Failure signal: nonzero exit. It prints one JSON line per arm with `model`, `effort`, and `source`, and a `notes` list when the resolver has a warning. Relay each note to the user in the reply. Pass the roles the skill names, or none to print every role. Run it from the project root or pass `--project `. Do not read the config files to pick values. The rules, and the grammar for editing the files, live in setup-pstack's [models config reference](../../setup-pstack/references/models-config.md). When you resolve `trail reviewer`, pass `--work-model @` with the model and effort that did the work, and use the printed arm. When the work's role resolved to `inherit-parent`, pass the session model. Pass the model the work ran on, as the role's resolved value or the CLI's own model ID. A full Claude ID such as `claude-opus-5-5` maps to its alias on a CLI that takes aliases, and stays a literal slug on Hermes. On Claude Code, a work model that is not a Claude alias or ID exits 2. On another CLI, a work model that CLI cannot use adds a note and applies no step. When the exit 2 names `--work-model`, correct a Claude value, such as dropping a `[1m]` suffix from an alias, and rerun. If the work ran on another vendor's model, rerun without the flag: every Claude Code arm is a Claude model, so the printed arm is cross-model. Otherwise rerun without the flag and disclose the execution identity per step 5. The resolver prefers a different model in the work model's family that the user's config allows, a higher tier first, and adjusts the effort. A `"step": "same-model"` field means the config allows no other model in the work model's family, so report that resolution and disclose the execution identity per step 5. Every model you pass comes from this output or an explicit request in the task. Never improvise one, and say which role each model came from. If the resolver exits nonzero or cannot run, still spawn the role. Omit the model and effort so the child inherits the session's. For `trail reviewer`, disclose the execution identity per step 5. For a panel role, keep the arm count that the panel's skill names as its default, and brief each arm the way that skill says. Report the resolver error and the values the child ran on. Never drop a spawn because the resolver failed. + Failure signal: nonzero exit. It prints one JSON line per arm with `model`, `effort`, and `source`, and a `notes` list when the resolver has a warning. Relay each note to the user in the reply. Pass the roles the skill names, or none to print every role. Run it from the project root or pass `--project `. Do not read the config files to pick values. The rules, and the grammar for editing the files, live in setup-pstack's [models config reference](../../setup-pstack/references/models-config.md). When you resolve `trail reviewer`, pass `--work-model @` with the model and effort that did the work, and use the printed arm. When the work's role resolved to `inherit-parent`, pass the session model. Pass the model the work ran on, as the role's resolved value or the CLI's own model ID. A full Claude ID such as `claude-opus-5-5` maps to its alias on a CLI that takes aliases, and stays a literal slug on Hermes. On Claude Code, a work model that is not a Claude alias or ID exits 2. On another CLI, a work model that CLI cannot use adds a note and applies no step. When the exit 2 names `--work-model`, correct a Claude value, such as dropping a `[1m]` suffix from an alias, and rerun. If the work ran on another vendor's model, rerun without the flag: every Claude Code arm is a Claude model, so the printed arm is cross-model. Otherwise rerun without the flag and disclose the execution identity per step 5. The resolver prefers a different model in the work model's family that the user's config allows, a higher tier first, and adjusts the effort. A `"step": "same-model"` field means the config allows no other model in the work model's family, or the user pinned the reviewer with `trail reviewer step: off`. Report that resolution and disclose the execution identity per step 5. Every model you pass comes from this output or an explicit request in the task. Never improvise one, and say which role each model came from. If the resolver exits nonzero or cannot run, still spawn the role. Omit the model and effort so the child inherits the session's. For `trail reviewer`, disclose the execution identity per step 5. For a panel role, keep the arm count that the panel's skill names as its default, and brief each arm the way that skill says. Report the resolver error and the values the child ran on. Never drop a spawn because the resolver failed. 3. **Build the spawn call for this CLI.** Use the current runtime adapter selected in [pstack-harness](../SKILL.md#runtime-adapters). `inherit-parent` in a field means omit that field. 4. **Brief the persona.** A persona that runs as a briefing gets its complete text from the [persona contract](named-roles.md). Never summarize it. 5. **Report execution without dropping an arm.** Apply this step to every spawn, including a `trail reviewer` that normally resolves to `inherit-parent` without a fallback or `step` marker. If the spawn rejects a model, or a spawned arm fails on model availability such as exhausted usage credits, omit the model, let the arm inherit the session model, and report the substitution. Label the verdict and reply `same-model` when the observed reviewer and work models match. When either identity is unknown, say the review may be same-model. For explicitly requested models, use the **arena** skill's [required-arm rule](../../arena/SKILL.md#required-arms). If no field or agent can carry the effort, the effort alone becomes `inherit-parent`. Keep the model and the arm. Say in the reply which role's effort was inherited and why, such as "`how explainer` ran at the session effort because `pstack-effort-xhigh` is not loaded. Run `/setup-pstack` to register it." When a persona ran as a briefing in an effort agent's prompt instead of under its native name, say that too. Delegates return resolver notes and actual or inherited model and effort observations to the parent, including substitutions, limitations, and unknown values. The parent relays them in its reply. diff --git a/skills/setup-pstack/SKILL.md b/skills/setup-pstack/SKILL.md index fdf8457d..d82141b4 100644 --- a/skills/setup-pstack/SKILL.md +++ b/skills/setup-pstack/SKILL.md @@ -109,11 +109,11 @@ On Claude Code, describe `default — keep as written` as "roles without a writt **(b) Apply it.** Build the working table from `examples/pstack-models.md`, and on a re-run keep any role the user changed by model, effort, list, alias (`inherit-parent`, `auto`), or harness section. `default` applies no budget: every written `@effort` suffix stands and unsuffixed entries keep the effort policy in [references/models-config.md](references/models-config.md), which on Claude Code is the session effort. `unlimited`, `large`, `medium`, and `small` set the `@effort` of every real entry, panel entries and harness sections included, to `max`, `xhigh`, `high`, or `medium`, adding the suffix where none was written. If the lint in step 4 rejects that effort for the model, use the model's highest supported effort at or below the target. An entry whose model the lint cannot classify keeps its written effort, or stays unsuffixed, and step (c) names it as untouched. An alias with a written suffix, such as `auto@max`, gets the same rewrite on its suffix, since Codex honors a suffix on an alias. A bare `inherit-parent` or `auto` does not change. No budget changes a model or a list length. So `small` turns `fable` into `fable@medium` and `gpt-6-sol@max` into `gpt-6-sol@medium`, and `unlimited` turns both back into `fable@max` and `gpt-6-sol@max`. On Claude Code, a written suffix applies only while the effort agents are loaded. If the live catalog lacks them, say so. The suffixes still govern Codex and Hermes reading the same file, and subagents here run at the session effort until the agents are registered and the catalog lists them. -**(c) Show the roles and confirm.** The file is shared across CLIs, so a value this harness cannot validate is not wrong — it is another harness's choice (it reads as `inherit-parent` here). Show every role with its model and effort for this harness, marking values outside the detected set as "(set for another harness — kept unless you change it)" rather than as needing a choice. On Claude Code, show a role with no written effort as `session`, and mark a written effort "(inactive until the effort agents load)" when the live catalog lacks its agent. Also list each line step 2 dropped. Ask whether to accept as-is or change specific roles, offering the detected models plus `inherit-parent` and `auto` (both mean: this role runs on the parent chat model, which is how Auto users stay on Auto) as the options. Prefer AskQuestion over free text. For panel roles (arena runners, architect runners, interrogate reviewers) the value is a list, and one subagent runs per entry, alias entries included, so the list length sets the count. `arena cross-judge pool` is also a list, but Arena selects one value from it whose model family or capability tier differs from the parent's when possible. `swarm workers` runs every swarm worker that runs something, per the **swarm** skill, unless a race or comparison assigns another model per arm. `trail reviewer` runs the show-me-your-work reviewer and every independent verdict and review, including a swarm's audit lanes. `routine` runs every read-only scan, parse, or watch subagent that returns a reduced finding, unless the calling skill names another role. For its scope, follow [the models config reference](references/models-config.md#grammar). Show its model and effort from the working table. For reviewer resolution and model opt-outs, follow [models config rule 7](references/models-config.md#resolution). For execution-identity disclosure, follow [Spawn a role](../pstack-harness/SKILL.md#spawn-a-role). `default` is the entry for any spawn whose skill names no role; keep it `inherit-parent` unless the user wants unmapped spawns on a specific model. +**(c) Show the roles and confirm.** The file is shared across CLIs, so a value this harness cannot validate is not wrong — it is another harness's choice (it reads as `inherit-parent` here). Show every role with its model and effort for this harness, marking values outside the detected set as "(set for another harness — kept unless you change it)" rather than as needing a choice. On Claude Code, show a role with no written effort as `session`, and mark a written effort "(inactive until the effort agents load)" when the live catalog lacks its agent. Also list each line step 2 dropped. Ask whether to accept as-is or change specific roles, offering the detected models plus `inherit-parent` and `auto` (both mean: this role runs on the parent chat model, which is how Auto users stay on Auto) as the options. Prefer AskQuestion over free text. For panel roles (arena runners, architect runners, interrogate reviewers) the value is a list, and one subagent runs per entry, alias entries included, so the list length sets the count. `arena cross-judge pool` is also a list, but Arena selects one value from it whose model family or capability tier differs from the parent's when possible. `swarm workers` runs every swarm worker that runs something, per the **swarm** skill, unless a race or comparison assigns another model per arm. `trail reviewer` runs the show-me-your-work reviewer and every independent verdict and review, including a swarm's audit lanes. `routine` runs every read-only scan, parse, or watch subagent that returns a reduced finding, unless the calling skill names another role. For its scope, follow [the models config reference](references/models-config.md#grammar). Show its model and effort from the working table. For reviewer resolution and model opt-outs, follow [models config rule 7](references/models-config.md#resolution). Also show the reviewer that runs when the work does. Resolve `feature` and `refactoring`, then run `python3 /scripts/check-models-config.py --resolve --harness --work-model @ "trail reviewer"` with their model and effort, once for each distinct model. When the arm has a `step`, print the written and stepped values together, such as `trail reviewer: gpt-6.1-sol@xhigh → gpt-6-astra@high when work runs on sol`, and relay its note, which names the roles that allow the stepped-to model. Say that a stepped reviewer takes its effort from the work effort, and that a `trail reviewer step: off` line keeps the written reviewer and effort and discloses the review as same-model. Offer the line only when the user wants that. For execution-identity disclosure, follow [Spawn a role](../pstack-harness/SKILL.md#spawn-a-role). `default` is the entry for any spawn whose skill names no role; keep it `inherit-parent` unless the user wants unmapped spawns on a specific model. ### 4. Validate -Run the lint on the file you are about to write, before writing it: `python3 /scripts/check-models-config.py `. Any `error:` line (unknown role, bad effort, an effort the model does not support, a duplicate role or section, `none` or `ultra` under `## claude-code`) stops the write; fix the line and re-run. `notice:` lines mark `max` and `ultra` pins, and a flat-line `none` or `ultra` that Claude Code runs at the session effort. Read each one back to the user, so an expensive tier or a Claude Code fallback is a choice. Every *newly chosen* real slug must be in the detected set. `inherit-parent` and `auto` always pass, and preserved values from another harness are exempt. If a chosen real slug is not available, stop and ask again. Once the lint passes, show the user what each role will run as here. For the user file, run `python3 /scripts/check-models-config.py --resolve --harness --user-file ` from the project root, which also applies any workspace file there. For a per-repo override, copy the draft to `/.agents/pstack-models.md` and pass `--project ` instead, so the real user file stays underneath. +Run the lint on the file you are about to write, before writing it: `python3 /scripts/check-models-config.py `. Any `error:` line (unknown role, bad effort, an effort the model does not support, a duplicate role or section, `none` or `ultra` under `## claude-code`) stops the write; fix the line and re-run. `notice:` lines mark `max` and `ultra` pins, and a flat-line `none` or `ultra` that Claude Code runs at the session effort. Read each one back to the user, so an expensive tier or a Claude Code fallback is a choice. Every *newly chosen* real slug must be in the detected set. `inherit-parent` and `auto` always pass, and preserved values from another harness are exempt. If a chosen real slug is not available, stop and ask again. Once the lint passes, show the user what each role will run as here. For the user file, run `python3 /scripts/check-models-config.py --resolve --harness --user-file ` from the project root, which also applies any workspace file there. For a per-repo override, copy the draft to `/.agents/pstack-models.md` and pass `--project ` instead, so the real user file stays underneath. Run it once more with `--work-model @` and `"trail reviewer"` for each distinct model of `feature` and `refactoring`, and show the stepped reviewer as step 3c describes, so the user sees what the line does before the write. ### 5. Write the config diff --git a/skills/setup-pstack/references/models-config.md b/skills/setup-pstack/references/models-config.md index 9fe676f6..97b0f19a 100644 --- a/skills/setup-pstack/references/models-config.md +++ b/skills/setup-pstack/references/models-config.md @@ -16,6 +16,7 @@ Failure signal: nonzero exit. It prints one JSON line per arm with `role`, `arm` - Panel roles take a comma list, one arm per entry: `arena runners`, `arena cross-judge pool`, `architect runners`, and `interrogate reviewers`. - A `## codex`, `## claude-code`, `## grok`, or `## hermes` header starts a section whose lines apply to that CLI only. Lines above any header are flat lines and apply everywhere. Put a CLI's own slug, such as `gpt-6-sol` or `grok-4.7`, under that CLI's section, because Codex, Hermes, and Grok Build each accept any model name from a flat line. - `trail reviewer` runs the show-me-your-work reviewer and every independent verdict and review, including the audit lanes the **swarm** skill gives it. Resolve it with `--work-model @` and the resolver moves the review off the model that did the work when the config allows another model in its family, per rule 7. `default` is the entry for a spawn whose skill names no role, and ships as `inherit-parent`. +- `trail reviewer step: off` pins the reviewer, per rule 7. It is a setting, not a role. It takes `on` or `off`, cannot share a line with a role, and `--resolve` never prints it. Layers read it like a role line, so a `## codex` pin leaves Claude Code stepping, and the highest layer that names it wins. - `routine` runs a read-only scan, parse, or watch subagent that returns a reduced finding, such as a bulk transcript read, a large artifact parse, or a watcher. Its shipped model and effort are defined in [the defaults file](../examples/pstack-models.md). A skill that names its own role keeps it. - `# budget: