diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e40735e..6e5c3c985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [Unreleased] + +**Capy lanes now know what gstack's review effort tiers mean on Capy.** gstack's review plan prints an effort on every reviewer it dispatches (`effort=full`, `effort=light`, the outside voice's `effort=host`) and on `AUDIT_EFFORT:`. The Capy skill never said how to honour them, so each lane guessed, and GStack Minder's crew kept its own mapping in CREW.md rule 30(c). Garry approved the mapping on 2026-10-29 ("Do it"). + +### Changed +- **capy/skill/gstack/SKILL.md** maps each tier onto Capy's subagent settings. `effort=full` and `AUDIT_EFFORT: host` leave `model` unset, so the subagent keeps the lane's model and reasoning. `effort=light` uses the lane's own model at `low` or `medium` reasoning, never a cheaper model. The outside voice stays on another model family. Each subagent's first report names the model and reasoning it ran at. +- **docs/model-policy.md** and **docs/review-policy.md** point Capy readers at that line. + +### Tests +- `test/capy-skill-wrapper.test.ts` pins the mapping and both pointers. It fails on the skill as main had it. + +### For Capy owners +- Lanes read the Drive copy of the skill. After this release, copy `capy/skill/gstack/` to the Drive skill folder, because a prose change does not trigger the installer's stale-copy warning. + ## [1.91.319.0] - 2026-10-29 **`gstack-pregate sealed` no longer prints a line that reads like a push confirmation.** On gstack-evals#29 the lane read `pushed aeb2413` in the `SEALED:` line as the push landing, while the remote stayed at 9036ab1 (#3565). `sealed` never pushes: it checks the commits a push would publish. `pushed ` was its label for the commit whose `sealed` policy it read beside the base branch's. diff --git a/capy/skill/gstack/SKILL.md b/capy/skill/gstack/SKILL.md index bb629e753..ac62de93b 100644 --- a/capy/skill/gstack/SKILL.md +++ b/capy/skill/gstack/SKILL.md @@ -76,6 +76,7 @@ In a repository with a sealed configuration (a `sealed` key in its `.gstack/preg - Use Capy's user-visible messaging and question tools for output and decisions. Plain assistant text is not a delivered message in Capy. Use Capy's task and pull-request workflows rather than unavailable Claude or Codex host tools. - Capy has no native gstack host target. Claude hooks do not become enforced Capy hooks; safety skills are advisory here, and `/autoplan` prints `autoplan guard: not enforced by this host` once to say so. Report missing capabilities instead of silently claiming equivalent enforcement. - Selecting GPT-6 Astra or Claude in Capy does not install or authenticate the Codex or Claude Code CLI. For cross-model reviews, a subagent on another model family is a full outside voice; record the model that reviewed. Do not report a missing Codex CLI as degraded coverage when another runner reviewed. +- gstack's review plan prints an effort on each `DISPATCH:` line and on `AUDIT_EFFORT:`. On Capy, `effort=full` and `AUDIT_EFFORT: host` mean start the subagent with `model` omitted, so it keeps the lane's model and reasoning (a `model_id` without `reasoning_mode` runs at that model's own default). `effort=light` and `AUDIT_EFFORT: light` mean the lane's own `model_id` with `reasoning_mode` `low` or `medium` (its lowest setting if it has neither), never a cheaper model. The outside voice's `effort=host` is the other-family subagent above. Each subagent's first report names the model and reasoning it ran at. - Preserve the user's requested scope, decisions, and consent. Do not enable telemetry or remote artifact sharing on their behalf. Installing gstack does not authorize merging, deploying, destructive operations, or bypassing approvals. ## Maintenance diff --git a/docs/model-policy.md b/docs/model-policy.md index 2c40f0ba4..3885ff237 100644 --- a/docs/model-policy.md +++ b/docs/model-policy.md @@ -166,8 +166,10 @@ plan-completion and docs audits, decision-trail reviewers and watchers (`AUDIT_EFFORT:` in the plan's output). A paid replay showed why reviewers stay at full: a medium-effort fix-check missed a fail-open in gate code that the same check at full effort caught. A host that cannot set a subagent's effort runs it -at its default. `gstack-config set review_effort_tiers off` (default `on`) -runs the audits and watchers at the host default too +at its default; Capy maps the tiers onto subagent model settings +([capy/skill/gstack/SKILL.md](../capy/skill/gstack/SKILL.md)). +`gstack-config set review_effort_tiers off` (default `on`) runs the audits and +watchers at the host default too ([review-policy.md](review-policy.md#review-depth)). ## Which workflows use the tiers? diff --git a/docs/review-policy.md b/docs/review-policy.md index bafc25869..9052d95de 100644 --- a/docs/review-policy.md +++ b/docs/review-policy.md @@ -211,7 +211,8 @@ plan-completion audit, the Step 14.5 docs audit, decision-trail reviewers, watchers) runs at `light`: the same model at a lower reasoning effort, never a cheaper model family. The outside voice keeps its own provider and effort (`codex_effort`). A host that cannot set a subagent's effort runs it at its -default. `gstack-config set review_effort_tiers off` (or `--no-tiers`) runs +default; Capy maps the tiers onto subagent model settings +([capy/skill/gstack/SKILL.md](../capy/skill/gstack/SKILL.md)). `gstack-config set review_effort_tiers off` (or `--no-tiers`) runs the audits and watchers at the host default too ([model-policy.md](model-policy.md#reasoning-effort)). diff --git a/test/capy-skill-wrapper.test.ts b/test/capy-skill-wrapper.test.ts index 9b041ba7d..88cc003d7 100644 --- a/test/capy-skill-wrapper.test.ts +++ b/test/capy-skill-wrapper.test.ts @@ -457,6 +457,19 @@ describe('capy skill: vendored text and support file', () => { expect(below(fs.readFileSync(path.join(REPO, 'VERSION'), 'utf8').trim(), min)).toBe(false); }); + test('SKILL.md maps the review effort tiers onto Capy subagent settings', () => { + const text = fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8'); + const adapt = text.slice(text.indexOf('## Adapt host-specific instructions to Capy'), text.indexOf('## Maintenance')); + const line = adapt.split('\n').find(l => l.includes('effort=light')) ?? ''; + expect(line).toMatch(/`effort=full` and `AUDIT_EFFORT: host` mean start the subagent with `model` omitted/); + expect(line).toMatch(/`effort=light` and `AUDIT_EFFORT: light` mean the lane's own `model_id` with `reasoning_mode` `low` or `medium`/); + expect(line).toContain('never a cheaper model'); + expect(line).toMatch(/outside voice's `effort=host` is the other-family subagent/); + for (const doc of ['docs/model-policy.md', 'docs/review-policy.md']) { + expect(fs.readFileSync(path.join(REPO, doc), 'utf8')).toContain('Capy maps the tiers onto subagent model settings'); + } + }); + test('SKILL.md: frontmatter, line cap, the session protocol tokens, and every command it names exists', () => { const text = fs.readFileSync(path.join(SKILL, 'SKILL.md'), 'utf8'); expect(text).toMatch(/^---\nname: gstack\ndescription: .+\n---\n/);