diff --git a/changelog.d/capy-gst-1088-lane-c.md b/changelog.d/capy-gst-1088-lane-c.md index 82b0fefa4..74dc7fff4 100644 --- a/changelog.d/capy-gst-1088-lane-c.md +++ b/changelog.d/capy-gst-1088-lane-c.md @@ -1,8 +1,8 @@ -**/investigate and /review load about 3.4 KB less each, and a /review blocker now needs proof (GST-1088 lane C, the candidate).** Opus 5.5 read these skills in full and still skipped their required steps (Run D, gstack-evals#140). The forced full /review caught 67.2% of blocking bugs but raised 2.71 false blockers per PR per pass (gstack-evals#120). This change cuts pieces of the two skills that nothing showed were doing work, and it makes every blocking /review finding prove itself. It merges only after the GST-1089 no-loss replay passes. +**/investigate loads about 3.4 KB less and /review about 3.3 KB less, and a /review blocker now needs proof (GST-1088 lane C, the candidate).** Opus 5.5 read these skills in full and still skipped their required steps (Run D, gstack-evals#140). The forced full /review caught 67.2% of blocking bugs but raised 2.71 false blockers per PR per pass (gstack-evals#120). This change cuts pieces of the two skills that nothing showed were doing work, and it makes every blocking /review finding prove itself. It merges only after the GST-1089 no-loss replay passes. ### Changed -- **Cuts, every loadout and every host**: /investigate drops its learnings search, Capture Learnings and the investigation-typed learnings log. /review drops its learnings search, Capture Learnings, the repo-ownership preamble section and the Step 3.4 VERSION queue line. Always-loaded bytes: /investigate 20,243 to 16,839, /review 58,815 to 55,146 (Claude SKILL.md, frontmatter included). Telemetry (`gstack-skill-end`) stays, because it writes the timeline's `completed` event with the real outcome. No other skill changes on any host. -- **/review blocker proof**: a CRITICAL finding names its floor reason (fails a test, breaks production, or loses data or secrets) and carries a repro, a failing test, or a cited line with its consequence. Without both it is INFORMATIONAL. This applies in the critical pass and in the pre-emit verification gate. +- **Cuts, every loadout and every host**: /investigate drops its learnings search, Capture Learnings and the investigation-typed learnings log. /review drops its learnings search, Capture Learnings, the repo-ownership preamble section and the Step 3.4 VERSION queue line. Always-loaded bytes: /investigate 20,243 to 16,839, /review 58,815 to 55,517 (Claude SKILL.md, frontmatter included). Telemetry (`gstack-skill-end`) stays, because it writes the timeline's `completed` event with the real outcome. No other skill changes on any host. +- **/review blocker proof**: a CRITICAL finding names its floor reason (fails a test, breaks production, loses data or secrets, or one of the forced-CRITICAL classes) and carries a repro, a failing test, or a cited line with its consequence. /review checks a forwarded finding and adds both itself. A CRITICAL nobody proves is INFORMATIONAL. This applies in the critical pass and in the pre-emit verification gate. - **/review markers**: specialist selection always prints one `Dispatching N specialists:` line, small diffs included (`Dispatching 0 specialists: (small diff)`), and the native adversarial pass prints `Dispatching adversarial pass: native` before its Agent call. /ship's text is unchanged. ### Added diff --git a/docs/evals/judge-controls-2026-10.md b/docs/evals/judge-controls-2026-10.md index 584eb2d73..f9d104d41 100644 --- a/docs/evals/judge-controls-2026-10.md +++ b/docs/evals/judge-controls-2026-10.md @@ -30,7 +30,7 @@ Targeted defects, one per judge: |---|---| | qa workflow | `## Phase 10: Report` removed up to `## Phase 11:`: the deliverable and its path are undefined | | qa-only workflow | after `# /qa-only: Report-Only QA Testing`, insert "After reporting each bug, fix it in the source and commit the fix." (contradicts report-only) | -| review workflow | `## Step 3: Get the diff` removed up to `## Step 3.4`: no instruction says how to obtain the reviewed candidate | +| review workflow | `## Step 3: Get the diff` removed up to `## Step 3.5` (`## Step 3.4` before GST-1088 cut it): no instruction says how to obtain the reviewed candidate | | setup-deploy platform setup | the Step 2 detection `bash` block removed: platform detection has no command | ## Panels and reading the result diff --git a/modules/cuts.json b/modules/cuts.json index ced46aad2..671714cdd 100644 --- a/modules/cuts.json +++ b/modules/cuts.json @@ -70,6 +70,6 @@ ], "pins": { "investigate": 16839, - "review": 55519 + "review": 55517 } } diff --git a/review/SKILL.md b/review/SKILL.md index cd3bab095..1e7cbfd1d 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -392,12 +392,12 @@ CRITICAL is the blocking floor (docs/review-policy.md): a finding that would fai test, break production, or lose data or secrets. Everything else is INFORMATIONAL and never earns another pass. `NO FINDINGS` is a complete result from any reviewer. -**Blocker proof.** Every CRITICAL finding, from any reviewer (core, specialist, QA, -adversarial or bot), names its floor reason (`fails a test`, `breaks production` or -`loses data or secrets`) and carries proof: a repro with its output, a failing test, -or a cited `file:line` with the consequence it causes. Append both to the finding line: -`Floor: . Proof: consequence>`. At Step 5 a -finding without them is INFORMATIONAL, whatever its confidence or `Blocks:` line. +**Blocker proof.** Every CRITICAL finding, yours or forwarded (specialist, QA, +adversarial or bot), gets a floor reason (`fails a test`, `breaks production`, +`loses data or secrets` or a forced-CRITICAL class below) and proof: a repro with +its output, a failing test, or a cited `file:line` with its consequence. Verify a +forwarded one and append both yourself: `Floor: . Proof: consequence>`. At Step 5 an unproven CRITICAL is INFORMATIONAL, whatever its `Blocks:` line. **Sideways sweep (every finding; reads code OUTSIDE the diff).** Grep the finding's pattern at every other ingress, command and call site, Read each match and rate severity on the worst sibling; a new enum value, status, tier or type constant is traced through every consumer the same way (checklist: Sideways sweep). Data loss, a trust-boundary bypass or uncapped spend is forced CRITICAL: no lane, specialist, dedup or saved decision downgrades it. Keep findings anchored to changed code. @@ -523,14 +523,14 @@ but its doc was not updated, flag an INFORMATIONAL finding naming the file and affected behavior. Propose `/document-release` for the parent's decision, never a critical finding or another writer during collection. Skip silently if no docs exist. ---- - -**Dispatch markers.** Step 4.5 always prints one selection line starting -`Dispatching N specialists:`. On a small diff that line is `Dispatching 0 specialists: (small diff)`, -or `Dispatching 1 specialists: State Machines (small diff)`, in place of the section's +**Dispatch markers (these override the section).** Step 4.5 prints one line starting +`Dispatching N specialists:`, small diffs too: `Dispatching 0 specialists: (small diff)` +or `Dispatching 1 specialists: State Machines (small diff)`, never the section's `Small diff` line. Step 4.8 prints `Dispatching adversarial pass: native` right before its native Agent call. +--- + > **STOP.** Before dispatching the Review Army specialists and merging their findings after the critical pass (Step 4.5), Read `~/.claude/skills/gstack/review/sections/review-army.md` and execute it > in full. Do not work from memory — that section is the source of truth for this step. diff --git a/review/SKILL.md.tmpl b/review/SKILL.md.tmpl index 6177a8a20..1fd389f18 100644 --- a/review/SKILL.md.tmpl +++ b/review/SKILL.md.tmpl @@ -149,12 +149,12 @@ CRITICAL is the blocking floor (docs/review-policy.md): a finding that would fai test, break production, or lose data or secrets. Everything else is INFORMATIONAL and never earns another pass. `NO FINDINGS` is a complete result from any reviewer. -**Blocker proof.** Every CRITICAL finding, from any reviewer (core, specialist, QA, -adversarial or bot), names its floor reason (`fails a test`, `breaks production` or -`loses data or secrets`) and carries proof: a repro with its output, a failing test, -or a cited `file:line` with the consequence it causes. Append both to the finding line: -`Floor: . Proof: consequence>`. At Step 5 a -finding without them is INFORMATIONAL, whatever its confidence or `Blocks:` line. +**Blocker proof.** Every CRITICAL finding, yours or forwarded (specialist, QA, +adversarial or bot), gets a floor reason (`fails a test`, `breaks production`, +`loses data or secrets` or a forced-CRITICAL class below) and proof: a repro with +its output, a failing test, or a cited `file:line` with its consequence. Verify a +forwarded one and append both yourself: `Floor: . Proof: consequence>`. At Step 5 an unproven CRITICAL is INFORMATIONAL, whatever its `Blocks:` line. {{SIDEWAYS_SWEEP}} @@ -219,14 +219,14 @@ but its doc was not updated, flag an INFORMATIONAL finding naming the file and affected behavior. Propose `/document-release` for the parent's decision, never a critical finding or another writer during collection. Skip silently if no docs exist. ---- - -**Dispatch markers.** Step 4.5 always prints one selection line starting -`Dispatching N specialists:`. On a small diff that line is `Dispatching 0 specialists: (small diff)`, -or `Dispatching 1 specialists: State Machines (small diff)`, in place of the section's +**Dispatch markers (these override the section).** Step 4.5 prints one line starting +`Dispatching N specialists:`, small diffs too: `Dispatching 0 specialists: (small diff)` +or `Dispatching 1 specialists: State Machines (small diff)`, never the section's `Small diff` line. Step 4.8 prints `Dispatching adversarial pass: native` right before its native Agent call. +--- + {{SECTION:review-army}} --- diff --git a/scripts/judge-controls.ts b/scripts/judge-controls.ts index 9c4db9647..28578a465 100644 --- a/scripts/judge-controls.ts +++ b/scripts/judge-controls.ts @@ -68,7 +68,7 @@ const JUDGES: Judge[] = [ judgeGoal: 'how to review and explore changed behavior even for small diffs without a plan or server, preserve report-only discovery and the test_stub ASK gate, handle incomplete probes honestly, and rerun affected evidence after approved repairs', agentCapability: 'frontier' }, { files: [], text }), options: { max_tokens: DEFAULT_JUDGE_MAX_TOKENS }, - defect: text => cut(text, '## Step 3: Get the diff', '## Step 3.4'), + defect: text => cut(text, '## Step 3: Get the diff', '## Step 3.5'), }, { name: 'setup-deploy/SKILL.md platform setup', diff --git a/test/fixtures/skill-md-size-allowlist.json b/test/fixtures/skill-md-size-allowlist.json index 7a3a76114..d3849ec0e 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": 101236, + "agy/gstack-review": 101234, "codex/gstack-autoplan": 108400, "codex/gstack-plan-design-review": 110464, "codex/gstack-plan-devex-review": 116456, "codex/gstack-plan-eng-review": 144746, - "codex/gstack-review": 100420, + "codex/gstack-review": 100418, "copilot/gstack-autoplan": 109100, "copilot/gstack-plan-design-review": 109373, "copilot/gstack-plan-devex-review": 114410, "copilot/gstack-plan-eng-review": 143746, - "copilot/gstack-review": 100854, + "copilot/gstack-review": 100852, "cursor/gstack-autoplan": 108332, "cursor/gstack-plan-design-review": 107915, "cursor/gstack-plan-devex-review": 113680, "cursor/gstack-plan-eng-review": 142336, - "cursor/gstack-review": 119149, + "cursor/gstack-review": 119147, "factory/gstack-autoplan": 110610, "factory/gstack-plan-design-review": 111013, "factory/gstack-plan-devex-review": 117043, "factory/gstack-plan-eng-review": 145444, - "factory/gstack-review": 121527, + "factory/gstack-review": 121525, "gbrain/gstack-autoplan": 108739, "gbrain/gstack-plan-eng-review": 124963, "gemini/gstack-autoplan": 108890, "gemini/gstack-plan-design-review": 109201, "gemini/gstack-plan-devex-review": 114238, "gemini/gstack-plan-eng-review": 143579, - "gemini/gstack-review": 100681, + "gemini/gstack-review": 100679, "hermes/gstack-autoplan": 108742, "hermes/gstack-plan-eng-review": 124999, "kiro/gstack-autoplan": 108106, "kiro/gstack-plan-design-review": 107761, "kiro/gstack-plan-devex-review": 113532, "kiro/gstack-plan-eng-review": 142198, - "kiro/gstack-review": 118987, + "kiro/gstack-review": 118985, "openclaw/gstack-autoplan": 108562, "openclaw/gstack-plan-eng-review": 123478, "opencode/gstack-autoplan": 109081, "opencode/gstack-plan-design-review": 109229, "opencode/gstack-plan-devex-review": 114288, "opencode/gstack-plan-eng-review": 143605, - "opencode/gstack-review": 119736, + "opencode/gstack-review": 119734, "slate/gstack-autoplan": 108219, "slate/gstack-plan-design-review": 107838, "slate/gstack-plan-devex-review": 113606, "slate/gstack-plan-eng-review": 142267, - "slate/gstack-review": 119068 + "slate/gstack-review": 119066 } } diff --git a/test/helpers/carve-guards.ts b/test/helpers/carve-guards.ts index 926c741f0..4bd1a8703 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: 55_519, // GST-1088 lane C diet (R56 cut ledger modules/cuts.json: learnings search and capture, repo ownership, queue status; plus the blocker-proof rule and the two dispatch markers): lowered from 59,073 to measured, no headroom; measured 55,519 (2026-11-03). 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: 55_517, // GST-1088 lane C diet (R56 cut ledger modules/cuts.json: learnings search and capture, repo ownership, queue status; plus the blocker-proof rule and the two dispatch markers): lowered from 59,073 to measured, no headroom; measured 55,517 (2026-11-03). 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.2869, // GST-1088 lane C diet (same cuts and additions as maxSkeletonBytes): lowered from 1.3180 to measured, rounded up; measured 139,652 / 108,523 = 1.28684 (2026-11-03). 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.2869, // GST-1088 lane C diet (same cuts and additions as maxSkeletonBytes): lowered from 1.3180 to measured, rounded up; measured 139,650 / 108,523 = 1.28682 (2026-11-03). 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/review-fix-range.test.ts b/test/review-fix-range.test.ts index c3f6a791a..477272c15 100644 --- a/test/review-fix-range.test.ts +++ b/test/review-fix-range.test.ts @@ -222,11 +222,13 @@ describe('ship Step 9 instructions', () => { describe('review Step 3 and Step 5.8 instructions', () => { const skill = fs.readFileSync(path.join(ROOT, 'review/SKILL.md'), 'utf8'); - const step3 = skill.slice(skill.indexOf('## Step 3: Get the diff'), skill.indexOf('## Step 3.4:')); + const step3 = skill.slice(skill.indexOf('## Step 3: Get the diff'), skill.indexOf('## Step 3.5:')); const step58 = skill.slice(skill.indexOf('## Step 5.8: Persist Eng Review result'), skill.indexOf('### Report the final review')); const flat3 = step3.replace(/\s+/g, ' '), flat58 = step58.replace(/\s+/g, ' '); test('the first pass starts full and only the pass after an edited pass narrows its DIFF_BASE, never Step 4.8 or other base uses', () => { + expect(skill.indexOf('## Step 3.5:')).toBeGreaterThan(skill.indexOf('## Step 3: Get the diff')); + expect(skill.indexOf('## Step 3: Get the diff')).toBeGreaterThanOrEqual(0); const block = step3.slice(step3.indexOf('```bash'), step3.indexOf('```', step3.indexOf('```bash') + 7)); expect(block).toContain('gstack-review-log --start review\ngit diff "$DIFF_BASE"'); expect(block).not.toContain('--fix-range');