From 8781d9c0a972068e2ee0e5597eb2f3482788355a Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 3 Nov 2026 11:39:32 -0800 Subject: [PATCH] v1.94.35.0 fix(contracts): run gstack-skill-contract through the host-resolved bin path (GST-1088 lane B follow-up) (#3957) * feat(skills): when-to-use descriptions, wider triggers and contract blocks for /investigate, /review, /qa, /verify (GST-1088 lane B) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skills): keep core trigger phrases in /review and /qa descriptions; bare gstack-skill-contract name until lane A ships it Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skills): Done-means list leaves out steps a host suppresses and allows the small-diff skip (review fix round) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: Done-means honors loadout section exclusions and the skill's own stop rules (Step 11 voices) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: the Done-means checker sentence follows an explicit CONTRACT_CHECKER_SHIPPED flag Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: cite GST-1088 gate rev 2 for the /review cap raises Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Revert "test: cite GST-1088 gate rev 2 for the /review cap raises" This reverts commit cc1539cd97b004eb8d06680121f3a7d7c77672df. * fix: trim /qa's opening sentence by 4 bytes so the branch fits main's qa parity cap Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: flip CONTRACT_CHECKER_SHIPPED now that bin/gstack-skill-contract ships, and re-pin /review by the measured 240 bytes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: the changelog fragment says lane A's routing hook and contract check have landed Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(contracts): run gstack-skill-contract through the host-resolved bin path The Done-means check/waive sentence named a bare gstack-skill-contract, which a standard install does not put on PATH (fix-check finding on #3909 at 58aeee7). Render it through ctx.paths.binDir like every other gstack bin, with a failing-first test across every host. Re-pin /review by the measured +56 skeleton bytes and +24 chars per non-Claude host render. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: changelog fragment wording for the bin-path fix Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- CHANGELOG.md | 10 +++++++++ VERSION | 2 +- agents-digest/gstack-AGENTS.md | 2 +- investigate/SKILL.md | 2 +- package.json | 2 +- review/SKILL.md | 2 +- scripts/resolvers/contract-done-means.ts | 10 ++++----- test/fixtures/skill-md-size-allowlist.json | 18 ++++++++-------- test/helpers/carve-guards.ts | 4 ++-- test/skill-descriptions.test.ts | 25 ++++++++++++++++------ 10 files changed, 50 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5850abca6..303d9ce55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [1.94.35.0] - 2026-11-03 + +**/investigate's and /review's "Done means" list now runs the contract checker through gstack's own bin path (GST-1088 lane B follow-up).** The list told the agent to run a bare `gstack-skill-contract check`, but a standard install doesn't put gstack's bin folder on PATH, so an agent that ran it, most importantly to record a waiver, got "command not found". It now names the same host-resolved path every other gstack command uses, for example `~/.claude/skills/gstack/bin/gstack-skill-contract check` on Claude Code. + +### Fixed +- **Done-means check and waive commands**: `scripts/resolvers/contract-done-means.ts` renders `check` and `waive` through each host's bin directory instead of the bare command name. The rest of the wording is unchanged. + +### Tests +- `test/skill-descriptions.test.ts`: on every host, /investigate and /review render the checker through that host's bin path and never as a bare command, and the checked-in /review SKILL.md shows the Claude path. /review's skeleton and size pins rise by the measured 56 bytes (24 chars per non-Claude host render). + ## [1.94.34.0] - 2026-11-03 ### Fixed diff --git a/VERSION b/VERSION index cbc2db0c2..9c06cd249 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.94.34.0 +1.94.35.0 diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md index 5e9c80c97..d3015ee19 100644 --- a/agents-digest/gstack-AGENTS.md +++ b/agents-digest/gstack-AGENTS.md @@ -1,4 +1,4 @@ -# gstack digest v1.94.34.0 — regenerate/re-copy after upgrading gstack +# gstack digest v1.94.35.0 — regenerate/re-copy after upgrading gstack Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed for agent hosts without a full skill install. The full skills add workflows, diff --git a/investigate/SKILL.md b/investigate/SKILL.md index 191fe7e05..81e8e62cc 100644 --- a/investigate/SKILL.md +++ b/investigate/SKILL.md @@ -88,7 +88,7 @@ Finish only when each of these exists (contract v1): - `debug-report`: a `DEBUG REPORT` with Symptom, Root cause, Fix, Evidence, Regression test and Status filled in (`none: ` where the skill's own stop rule leaves one empty). - `check-after-last-edit`: a test or repro command run after your last edit. -`gstack-skill-contract check` reads them from the transcript (docs/skill-routing-and-contracts.md). For an item that truly does not apply, run `gstack-skill-contract waive --reason ""` (this session only; it counts as a miss). +`~/.claude/skills/gstack/bin/gstack-skill-contract check` reads them from the transcript (docs/skill-routing-and-contracts.md). For an item that truly does not apply, run `~/.claude/skills/gstack/bin/gstack-skill-contract waive --reason ""` (this session only; it counts as a miss). ## Shared preamble (load first) diff --git a/package.json b/package.json index 6b1e63447..e963a1c93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.94.34", + "version": "1.94.35", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/review/SKILL.md b/review/SKILL.md index b01e94d13..4a7f65123 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -46,7 +46,7 @@ Finish only when each of these exists (contract v1): - `adversarial-pass`: an Agent dispatch for the adversarial pass, its prompt including "Think like an attacker and a chaos engineer". - `review-report`: a `Pre-Landing Review` with Gate edits filled in (`none: ` where the skill's own stop rule leaves one empty). -`gstack-skill-contract check` reads them from the transcript (docs/skill-routing-and-contracts.md). For an item that truly does not apply, run `gstack-skill-contract waive --reason ""` (this session only; it counts as a miss). +`~/.claude/skills/gstack/bin/gstack-skill-contract check` reads them from the transcript (docs/skill-routing-and-contracts.md). For an item that truly does not apply, run `~/.claude/skills/gstack/bin/gstack-skill-contract waive --reason ""` (this session only; it counts as a miss). ## Shared preamble (load first) diff --git a/scripts/resolvers/contract-done-means.ts b/scripts/resolvers/contract-done-means.ts index ef98c9b0d..d4d07a6c7 100644 --- a/scripts/resolvers/contract-done-means.ts +++ b/scripts/resolvers/contract-done-means.ts @@ -116,8 +116,8 @@ function plainWords(item: ContractItem): string { /** Whether bin/gstack-skill-contract ships. The PR that adds it flips this, regenerates and re-pins; test/skill-descriptions.test.ts fails while the two disagree. */ export const CONTRACT_CHECKER_SHIPPED = true; -/** The list; checker adds the check and waive commands, which only a tree that ships the checker may mention. */ -export function renderDoneMeans(contract: SkillContract, checker = CONTRACT_CHECKER_SHIPPED): string { +/** The list; checker adds the check and waive commands (run through the host's binDir), which only a tree that ships the checker may mention. */ +export function renderDoneMeans(contract: SkillContract, binDir: string, checker = CONTRACT_CHECKER_SHIPPED): string { if (contract.items.length === 0) return ''; return [ '## Done means', @@ -125,8 +125,8 @@ export function renderDoneMeans(contract: SkillContract, checker = CONTRACT_CHEC 'Finish only when each of these exists (contract v1):', '', ...contract.items.map(item => '- ' + code(item.id) + ': ' + plainWords(item) + '.'), - ...(checker ? ['', code('gstack-skill-contract check') + ' reads them from the transcript (docs/skill-routing-and-contracts.md). ' + - 'For an item that truly does not apply, run ' + code('gstack-skill-contract waive --reason ""') + ' (this session only; it counts as a miss).'] : []), + ...(checker ? ['', code(binDir + '/gstack-skill-contract check') + ' reads them from the transcript (docs/skill-routing-and-contracts.md). ' + + 'For an item that truly does not apply, run ' + code(binDir + '/gstack-skill-contract waive --reason ""') + ' (this session only; it counts as a miss).'] : []), ].join('\n'); } @@ -138,5 +138,5 @@ export function generateContractDoneMeans(ctx: TemplateContext): string { const backing = BACKED_BY[item.kind]; return !backing || (!suppressed.has(backing.resolver) && !ctx.modules?.excluded.has('section:' + ctx.skillName + '/' + backing.section)); }; - return renderDoneMeans({ ...contract, items: contract.items.filter(shown) }); + return renderDoneMeans({ ...contract, items: contract.items.filter(shown) }, ctx.paths.binDir); } diff --git a/test/fixtures/skill-md-size-allowlist.json b/test/fixtures/skill-md-size-allowlist.json index 45b3b889e..6212b3f5c 100644 --- a/test/fixtures/skill-md-size-allowlist.json +++ b/test/fixtures/skill-md-size-allowlist.json @@ -6,52 +6,52 @@ "agy/gstack-plan-design-review": 109107, "agy/gstack-plan-devex-review": 114948, "agy/gstack-plan-eng-review": 143581, - "agy/gstack-review": 104728, + "agy/gstack-review": 104752, "codex/gstack-autoplan": 108383, "codex/gstack-plan-design-review": 110464, "codex/gstack-plan-devex-review": 116456, "codex/gstack-plan-eng-review": 144746, - "codex/gstack-review": 104251, + "codex/gstack-review": 104275, "copilot/gstack-autoplan": 109083, "copilot/gstack-plan-design-review": 109373, "copilot/gstack-plan-devex-review": 114410, "copilot/gstack-plan-eng-review": 143746, - "copilot/gstack-review": 104309, + "copilot/gstack-review": 104333, "cursor/gstack-autoplan": 108315, "cursor/gstack-plan-design-review": 107915, "cursor/gstack-plan-devex-review": 113680, "cursor/gstack-plan-eng-review": 142336, - "cursor/gstack-review": 122781, + "cursor/gstack-review": 122805, "factory/gstack-autoplan": 110593, "factory/gstack-plan-design-review": 111013, "factory/gstack-plan-devex-review": 117043, "factory/gstack-plan-eng-review": 145444, - "factory/gstack-review": 126554, + "factory/gstack-review": 126578, "gbrain/gstack-autoplan": 108722, "gbrain/gstack-plan-eng-review": 124963, "gemini/gstack-autoplan": 108873, "gemini/gstack-plan-design-review": 109201, "gemini/gstack-plan-devex-review": 114238, "gemini/gstack-plan-eng-review": 143579, - "gemini/gstack-review": 104131, + "gemini/gstack-review": 104155, "hermes/gstack-autoplan": 108725, "hermes/gstack-plan-eng-review": 124999, "kiro/gstack-autoplan": 108089, "kiro/gstack-plan-design-review": 107761, "kiro/gstack-plan-devex-review": 113532, "kiro/gstack-plan-eng-review": 142198, - "kiro/gstack-review": 122605, + "kiro/gstack-review": 122629, "openclaw/gstack-autoplan": 108545, "openclaw/gstack-plan-eng-review": 123478, "opencode/gstack-autoplan": 109064, "opencode/gstack-plan-design-review": 109229, "opencode/gstack-plan-devex-review": 114288, "opencode/gstack-plan-eng-review": 143605, - "opencode/gstack-review": 123403, + "opencode/gstack-review": 123427, "slate/gstack-autoplan": 108202, "slate/gstack-plan-design-review": 107838, "slate/gstack-plan-devex-review": 113606, "slate/gstack-plan-eng-review": 142267, - "slate/gstack-review": 122693 + "slate/gstack-review": 122717 } } diff --git a/test/helpers/carve-guards.ts b/test/helpers/carve-guards.ts index 659255e43..b08ca0677 100644 --- a/test/helpers/carve-guards.ts +++ b/test/helpers/carve-guards.ts @@ -490,10 +490,10 @@ do not launch the downstream skill or open a browser.`, gateAfterStop: undefined, // operational multi-STOP skill, like ship }, behavioral: 'plan', - maxSkeletonBytes: 60_014, // GST-1088 lane B (#3909, raised from 59,774 to measured, no headroom; owner ruling via GStack Minder 2026-11-03): CONTRACT_CHECKER_SHIPPED=true now that bin/gstack-skill-contract ships (#3912) renders the gstack-skill-contract check/waive sentence under the Done means list (renders/GSTA-256/plan-v3.md line 74, r2-d6 "Done-means list"), +240 bytes; lane C's diet is expected to bring /review back under 59,073; measured 60,014. Before: GST-1088 lane B (raised from 59,073 to measured, no headroom): the contract: frontmatter block and the F1 "Done means" list rendered from it at the top of the body, plus widened triggers; F1 is a gate-rev-2 recommendation on the plan Garry approved with "do it" on gate rev 1 (2026-11-03), contingent on his gate-rev-2 answer, and lane C's diet is expected to bring /review back under 59,073; measured 59,774. Before: GSTA-96 hoist (2026-10-26): lowered from 80_900 by the shared preamble that moved to sections/preamble.md, keeping the pre-hoist headroom of 319 bytes; measured 58,754. Before: Shared-code identity/skip/action rules + critical-severity validation; measured 74,493 (2026-09-17). + v1.91.12.0 merge of #2999 (review clarity repairs: await reads, research alongside dispatch, /review deadline and setup authority, findings sources) with #3002 (guarded state-root lines, plan-check checkpoints); each fit alone; measured 74,881 (2026-10-01). + Oct 8 wave: shared voice directive bans "load-bearing" and adds the reply-language rule, offset by tightening the bounded closer (net +17 bytes per tier-2+ skill); measured 74,884 (2026-10-08). + gate integrity (HONEST_WORK_GATE_INTEGRITY W2): Step 3.5 Diff scans with the shared GATE_SCAN_BLOCK, the Step 4 carry, the four-option `review-gate-disposition` question in 5c, gate record fields in 5.8 and the Gate edits report line; measured 80,054 (2026-10-10). + Oct 10 multi-agent wave PR D2 (sideways review): Step 4's enum-only paragraph becomes the sideways sweep with the forced-CRITICAL list, plus the flake-fix number sentence in the Gate Integrity paragraph; measured skeleton 80,812 (2026-10-10). + maxSkeletonBytes: 60_070, // GST-1088 lane B follow-up (raised from 60,014 to measured, no headroom): the Done-means check/waive commands run through the host-resolved bin path (~/.claude/skills/gstack/bin/gstack-skill-contract) instead of a bare gstack-skill-contract that a standard install doesn't put on PATH (fix-check finding on #3909 at 58aeee7), +56 bytes; measured 60,070. Before: GST-1088 lane B (#3909, raised from 59,774 to measured, no headroom; owner ruling via GStack Minder 2026-11-03): CONTRACT_CHECKER_SHIPPED=true now that bin/gstack-skill-contract ships (#3912) renders the gstack-skill-contract check/waive sentence under the Done means list (renders/GSTA-256/plan-v3.md line 74, r2-d6 "Done-means list"), +240 bytes; lane C's diet is expected to bring /review back under 59,073; measured 60,014. Before: GST-1088 lane B (raised from 59,073 to measured, no headroom): the contract: frontmatter block and the F1 "Done means" list rendered from it at the top of the body, plus widened triggers; F1 is a gate-rev-2 recommendation on the plan Garry approved with "do it" on gate rev 1 (2026-11-03), contingent on his gate-rev-2 answer, and lane C's diet is expected to bring /review back under 59,073; measured 59,774. Before: GSTA-96 hoist (2026-10-26): lowered from 80_900 by the shared preamble that moved to sections/preamble.md, keeping the pre-hoist headroom of 319 bytes; measured 58,754. Before: Shared-code identity/skip/action rules + critical-severity validation; measured 74,493 (2026-09-17). + v1.91.12.0 merge of #2999 (review clarity repairs: await reads, research alongside dispatch, /review deadline and setup authority, findings sources) with #3002 (guarded state-root lines, plan-check checkpoints); each fit alone; measured 74,881 (2026-10-01). + Oct 8 wave: shared voice directive bans "load-bearing" and adds the reply-language rule, offset by tightening the bounded closer (net +17 bytes per tier-2+ skill); measured 74,884 (2026-10-08). + gate integrity (HONEST_WORK_GATE_INTEGRITY W2): Step 3.5 Diff scans with the shared GATE_SCAN_BLOCK, the Step 4 carry, the four-option `review-gate-disposition` question in 5c, gate record fields in 5.8 and the Gate edits report line; measured 80,054 (2026-10-10). + Oct 10 multi-agent wave PR D2 (sideways review): Step 4's enum-only paragraph becomes the sideways sweep with the forced-CRITICAL list, plus the flake-fix number sentence in the Gate Integrity paragraph; measured skeleton 80,812 (2026-10-10). minUnionBytes: 89_000, // Phase 4 wave 1; measured union 93,357 mustContain: ['confidence', 'P1', 'P2', 'Review Army', 'adversarial'], - maxSizeRatio: 1.3283, // + GST-1088 lane B (#3909, raised from 1.3261 to measured, no headroom; owner ruling via GStack Minder 2026-11-03): the gstack-skill-contract check/waive sentence that CONTRACT_CHECKER_SHIPPED=true renders (renders/GSTA-256/plan-v3.md line 74, r2-d6 "Done-means list"), +240 bytes; lane C's diet is expected to bring /review back under 1.3180; measured 144,147 / 108,523 = 1.32826, rounded up. Before: + GST-1088 lane B (raised from 1.3180 to measured, no headroom): the contract: frontmatter block and the F1 "Done means" list, contingent on Garry's gate-rev-2 answer; lane C's diet is expected to bring /review back under 1.3180; measured 143,907 / 108,523 = 1.3261. Before: + GSTA-167 variant G part 1 (plan approved by Garry 2026-10-30, autoplan-20261030161754 "Do it", which names about +0.3k prompt tokens per voice): the native adversarial and outside-voice prompts carry the blocking floor and the Severity and Blocks lines, +537 bytes; measured 1.3180 (2026-10-30). Before: 1.3136. GSTA-96 hoist merged with GSTA-92 phase 2 (2026-10-26): both owner-approved raises together, measured 142,550 / 108,523 = 1.3135. Before: Shared-code feature + critical-severity validation: 128,042 union bytes / 108,523 baseline = 1.1799; preserves content floors. + v1.91.12.0 merge of #2999 (above, plus plan-completion fallback intent and specialist checklist-by-path) with #3002; measured 1.1843 (2026-10-01). + v1.91.19.0 wave: verdict-form Codex callers with sandbox preflight (INV-1/B1), P0/P1 structured gate (B1b), bound-plan discovery and data-not-instructions guard (F1/D3), visible LEARNINGS failures (B5); measured 129,941 / 108,523 = 1.1974 (2026-10-03). + v1.91.18.0 (#3023) merged into the v1.91.19.0 wave; measured 130,025 / 108,523 = 1.1981 (2026-10-04). + Oct 6 fix wave: quota_exhausted preflight branch (#3051); measured 130,359 / 108,523 = 1.2012 (2026-10-06). + Oct 6 fix wave A3/CEO-12: free text reaches commands only through agent-written mktemp files (mktemp block, write rule, path rebuild and refusal at each posting, prompt and brief site); measured 131,314 / 108,523 = 1.2100 (2026-10-06). Combined Oct 6 wave head (A and B): measured 131,966 / 108,523 = 1.2160 (2026-10-06). + Oct 7 wave B3: the Codex probe runs as a command (select-model capture lines, check-sandbox/probe-model/run-with-timeout subcommands) instead of being sourced; measured 132,199 / 108,523 = 1.2182 (2026-10-07). + Oct 7 wave CEO-28/DX-11: review prompts ask for a severity per finding and design proposals use the proposal gate; measured 132,258 / 108,523 = 1.2187 (2026-10-07). + Oct 7 wave guard (CEO-20): conditional `run_in_background` request plus the background-run recovery at each foreground dispatch site; measured 132,233 / 108,523 = 1.2185 (2026-10-07). Merged with the guard area: measured 132,522 / 108,523 = 1.2211 (2026-10-07). + Oct 8 wave: the defensive-security framing and fixture summary mode reach the security specialist and the Red Team (stated once in the dispatch, referenced by the Red Team); measured 133,902 / 108,523 = 1.2339 (2026-10-08). + gate integrity W2 (above); measured 1.282 (2026-10-10). + Oct 10 multi-agent wave PR D2 (sideways review): sideways sweep and flake-fix number in Step 4; `Diff read` and `Undeclared behavior changes` in the review-mode Scope Check (plan-completion section); measured 140,497 / 108,523 = 1.2946 (2026-10-10). + harness lane E (2026-10-26): the lead-judgment stage in the finding merge and the `cause` anchor in the specialist prompts, shared with /ship through scripts/resolvers/review-army.ts; measured 141,949 / 108,523 = 1.3080. + maxSizeRatio: 1.3288, // + GST-1088 lane B follow-up (raised from 1.3283 to measured, no headroom): the Done-means check/waive commands run through the host-resolved bin path instead of a bare gstack-skill-contract that isn't on PATH (fix-check finding on #3909 at 58aeee7), +56 bytes; measured 144,203 / 108,523 = 1.328778, rounded up. Before: + GST-1088 lane B (#3909, raised from 1.3261 to measured, no headroom; owner ruling via GStack Minder 2026-11-03): the gstack-skill-contract check/waive sentence that CONTRACT_CHECKER_SHIPPED=true renders (renders/GSTA-256/plan-v3.md line 74, r2-d6 "Done-means list"), +240 bytes; lane C's diet is expected to bring /review back under 1.3180; measured 144,147 / 108,523 = 1.32826, rounded up. Before: + GST-1088 lane B (raised from 1.3180 to measured, no headroom): the contract: frontmatter block and the F1 "Done means" list, contingent on Garry's gate-rev-2 answer; lane C's diet is expected to bring /review back under 1.3180; measured 143,907 / 108,523 = 1.3261. Before: + GSTA-167 variant G part 1 (plan approved by Garry 2026-10-30, autoplan-20261030161754 "Do it", which names about +0.3k prompt tokens per voice): the native adversarial and outside-voice prompts carry the blocking floor and the Severity and Blocks lines, +537 bytes; measured 1.3180 (2026-10-30). Before: 1.3136. GSTA-96 hoist merged with GSTA-92 phase 2 (2026-10-26): both owner-approved raises together, measured 142,550 / 108,523 = 1.3135. Before: Shared-code feature + critical-severity validation: 128,042 union bytes / 108,523 baseline = 1.1799; preserves content floors. + v1.91.12.0 merge of #2999 (above, plus plan-completion fallback intent and specialist checklist-by-path) with #3002; measured 1.1843 (2026-10-01). + v1.91.19.0 wave: verdict-form Codex callers with sandbox preflight (INV-1/B1), P0/P1 structured gate (B1b), bound-plan discovery and data-not-instructions guard (F1/D3), visible LEARNINGS failures (B5); measured 129,941 / 108,523 = 1.1974 (2026-10-03). + v1.91.18.0 (#3023) merged into the v1.91.19.0 wave; measured 130,025 / 108,523 = 1.1981 (2026-10-04). + Oct 6 fix wave: quota_exhausted preflight branch (#3051); measured 130,359 / 108,523 = 1.2012 (2026-10-06). + Oct 6 fix wave A3/CEO-12: free text reaches commands only through agent-written mktemp files (mktemp block, write rule, path rebuild and refusal at each posting, prompt and brief site); measured 131,314 / 108,523 = 1.2100 (2026-10-06). Combined Oct 6 wave head (A and B): measured 131,966 / 108,523 = 1.2160 (2026-10-06). + Oct 7 wave B3: the Codex probe runs as a command (select-model capture lines, check-sandbox/probe-model/run-with-timeout subcommands) instead of being sourced; measured 132,199 / 108,523 = 1.2182 (2026-10-07). + Oct 7 wave CEO-28/DX-11: review prompts ask for a severity per finding and design proposals use the proposal gate; measured 132,258 / 108,523 = 1.2187 (2026-10-07). + Oct 7 wave guard (CEO-20): conditional `run_in_background` request plus the background-run recovery at each foreground dispatch site; measured 132,233 / 108,523 = 1.2185 (2026-10-07). Merged with the guard area: measured 132,522 / 108,523 = 1.2211 (2026-10-07). + Oct 8 wave: the defensive-security framing and fixture summary mode reach the security specialist and the Red Team (stated once in the dispatch, referenced by the Red Team); measured 133,902 / 108,523 = 1.2339 (2026-10-08). + gate integrity W2 (above); measured 1.282 (2026-10-10). + Oct 10 multi-agent wave PR D2 (sideways review): sideways sweep and flake-fix number in Step 4; `Diff read` and `Undeclared behavior changes` in the review-mode Scope Check (plan-completion section); measured 140,497 / 108,523 = 1.2946 (2026-10-10). + harness lane E (2026-10-26): the lead-judgment stage in the finding merge and the `cause` anchor in the specialist prompts, shared with /ship through scripts/resolvers/review-army.ts; measured 141,949 / 108,523 = 1.3080. }, codex: { skill: 'codex', diff --git a/test/skill-descriptions.test.ts b/test/skill-descriptions.test.ts index d6eff7b43..829e54bb9 100644 --- a/test/skill-descriptions.test.ts +++ b/test/skill-descriptions.test.ts @@ -121,7 +121,7 @@ describe('contract blocks (frozen v1 schema)', () => { test(skill + ': the body carries the Done-means placeholder and the render carries the list', () => { expect(body(tmpl).includes('{{CONTRACT_DONE_MEANS}}'), tmpl + ': a contract block needs {{CONTRACT_DONE_MEANS}} at the top of the body. ' + fix(skill)).toBe(true); - expect(read(skill + '/SKILL.md').includes(renderDoneMeans(contract)), skill + '/SKILL.md: the Done-means list is stale. ' + fix(skill)).toBe(true); + expect(read(skill + '/SKILL.md').includes(renderDoneMeans(contract, HOST_PATHS.claude.binDir)), skill + '/SKILL.md: the Done-means list is stale. ' + fix(skill)).toBe(true); }); test(skill + ': every contract marker appears in the skill text', () => { @@ -153,7 +153,7 @@ describe('contract-done-means renderer', () => { { id: 'adversarial-pass', kind: 'agent_dispatch', match: 'chaos engineer' }, ], }, 'fixture/SKILL.md.tmpl'); - const out = renderDoneMeans(all, true); + const out = renderDoneMeans(all, HOST_PATHS.claude.binDir, true); test('names each item kind in plain words', () => { expect(out).toContain('## Done means'); @@ -164,8 +164,8 @@ describe('contract-done-means renderer', () => { }); test('points to check and waive in the routing-and-contracts doc, never the off switch', () => { - expect(out).toContain(BT + 'gstack-skill-contract check' + BT); - expect(out).toContain(BT + 'gstack-skill-contract waive --reason ""' + BT); + expect(out).toContain(BT + HOST_PATHS.claude.binDir + '/gstack-skill-contract check' + BT); + expect(out).toContain(BT + HOST_PATHS.claude.binDir + '/gstack-skill-contract waive --reason ""' + BT); expect(out).toContain('docs/skill-routing-and-contracts.md'); expect(out).not.toContain('skill_contracts'); }); @@ -203,7 +203,20 @@ describe('contract-done-means renderer', () => { expect(read(skill + '/SKILL.md').includes('gstack-skill-contract'), skill + '/SKILL.md names gstack-skill-contract while bin/gstack-skill-contract ' + (shipped ? 'exists' : 'is missing') + '. Fix: bun run gen:skill-docs').toBe(shipped); } if (shipped) expect(existsSync(join(ROOT, 'docs', 'skill-routing-and-contracts.md')), 'docs/skill-routing-and-contracts.md is missing').toBe(true); - expect(renderDoneMeans(all, false)).not.toContain('gstack-skill-contract'); + expect(renderDoneMeans(all, HOST_PATHS.claude.binDir, false)).not.toContain('gstack-skill-contract'); + }); + + test('check and waive run the checker through the host-resolved bin path, like every other gstack bin', () => { + for (const skill of ['investigate', 'review']) { + for (const [host, paths] of Object.entries(HOST_PATHS)) { + const out = generateContractDoneMeans({ skillName: skill, tmplPath: join(ROOT, skill, 'SKILL.md.tmpl'), host, paths } as unknown as Parameters[0]); + for (const command of ['check', 'waive']) { + expect(out, skill + ' on ' + host + ': the Done-means list must run ' + paths.binDir + '/gstack-skill-contract ' + command + '. Fix: render ctx.paths.binDir in scripts/resolvers/contract-done-means.ts, then bun run gen:skill-docs').toContain(paths.binDir + '/gstack-skill-contract ' + command); + } + expect(out.match(/\u0060gstack-skill-contract /g), skill + ' on ' + host + ': a bare gstack-skill-contract is not on PATH in a standard install').toBeNull(); + } + expect(read(skill + '/SKILL.md')).toContain(HOST_PATHS.claude.binDir + '/gstack-skill-contract waive'); + } }); test('a host that suppresses, or a loadout that excludes, the step an item checks leaves that item out', () => { @@ -213,7 +226,7 @@ describe('contract-done-means renderer', () => { expect(ids('claude')).toEqual(['specialists-dispatched', 'adversarial-pass', 'review-report']); expect(ids('codex')).toEqual(['adversarial-pass', 'review-report']); expect(ids('hermes')).toEqual(['review-report']); - expect(renderDoneMeans({ version: 1, items: [] })).toBe(''); + expect(renderDoneMeans({ version: 1, items: [] }, HOST_PATHS.claude.binDir)).toBe(''); }); test('a placeholder with no contract block fails the render', () => {