From bf23d9155f667705e4b0520e4200c5a183e3d5b1 Mon Sep 17 00:00:00 2001 From: garrytan Date: Fri, 2 Oct 2026 23:48:54 +0000 Subject: [PATCH] fix(testing): shared TEST_BOOTSTRAP undoes only owned changes (s03 H1, s03 H2, s03 H3, s03 M1) The shared {{TEST_BOOTSTRAP}} (/ship, /design-review) still told the agent to 'git checkout -- package.json package-lock.json', to 'revert all bootstrap changes', to 'delete silently' a failing first test, and to stage 'all bootstrap files'. The QA copy (qa/sections/test-bootstrap.md.tmpl) already says undo only owned changes, never blanket-checkout, never silently delete a valid red regression, and stop on unrelated staged edits. The shared copy now matches it. This removes destructive behavior (UC2: lands regardless of eval). W7g: test/qa-browser-preservation.test.ts gains a check that the shared copy (ship, design-review) has no 'git checkout --', no silent deletion, no blanket revert, and keeps the owned-change and staged-edits rules (case-insensitive). Negative control: the old testing.ts turns it red. Parity cap (test/helpers/carve-guards.ts): ship maxSizeRatio 1.404 -> 1.405 (measured 1.4044 at the branch tip, with the s03 M2/M3 wording). expected red until the regeneration commit --- scripts/resolvers/testing.ts | 8 ++++---- test/helpers/carve-guards.ts | 2 +- test/qa-browser-preservation.test.ts | 12 ++++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/scripts/resolvers/testing.ts b/scripts/resolvers/testing.ts index e1aa6d70b..0fda3fb17 100644 --- a/scripts/resolvers/testing.ts +++ b/scripts/resolvers/testing.ts @@ -116,7 +116,7 @@ If multiple runtimes detected (monorepo) → ask which runtime to set up first, 3. Create directory structure (test/, spec/, etc.) 4. Create one example test matching the project's code to verify setup works -If package installation fails → debug once. If still failing → revert with \`git checkout -- package.json package-lock.json\` (or equivalent for the runtime). Warn user and continue without tests. +Record existing files and edits before installing. If package installation fails → debug once. If still failing → undo only the changes this bootstrap made and preserve the user's edits; never blanket-checkout. Warn user and continue without tests. ### B4.5. First real tests @@ -125,7 +125,7 @@ Generate 3-5 real tests for existing code: 1. **Find recently changed files:** \`git log --since=30.days --name-only --format="" | sort | uniq -c | sort -rn | head -10\` 2. **Prioritize by risk:** Error handlers > business logic with conditionals > API endpoints > pure functions 3. **For each file:** Write one test that tests real behavior with meaningful assertions. Never \`expect(x).toBeDefined()\` — test what the code DOES. -4. Run each test. Passes → keep. Fails → fix once. Still fails → delete silently. +4. Run each test. Passes → keep. Fails → fix an invalid test or fixture once. Still fails → drop it and name it, with its failure output, in the bootstrap summary; a failure in the code under test is a finding for the user, never a silent deletion. 5. Generate at least 1 test, cap at 5. Never import secrets, API keys, or credentials in test files. Use environment variables or test fixtures. @@ -137,7 +137,7 @@ Never import secrets, API keys, or credentials in test files. Use environment va {detected test command} \`\`\` -If tests fail → debug once. If still failing → revert all bootstrap changes and warn user. +If tests fail → debug once. If still failing → undo only this bootstrap's own changes, preserve the user's edits, and warn user with the failure. ### B5.5. CI/CD pipeline @@ -188,7 +188,7 @@ Append a \`## Testing\` section: git status --porcelain \`\`\` -Only commit if there are changes. Stage all bootstrap files (config, test directory, TESTING.md, CLAUDE.md, .github/workflows/test.yml if created): +Only commit if there are changes. Stage the bootstrap's own files by name (config, test directory, TESTING.md, CLAUDE.md, .github/workflows/test.yml if created); if unrelated edits are already staged, stop and ask before committing: \`git commit -m "chore: bootstrap test framework ({framework name})"\` ---`; diff --git a/test/helpers/carve-guards.ts b/test/helpers/carve-guards.ts index f0f5ec5ef..2052f7264 100644 --- a/test/helpers/carve-guards.ts +++ b/test/helpers/carve-guards.ts @@ -166,7 +166,7 @@ export const CARVE_GUARDS: Record = { // wave's headline capability) grows the union to 1.195x. Deliberate: // the section is on-demand (loads only for Apple store targets), so // per-invocation cost for non-iOS ships is one manifest line. - maxSizeRatio: 1.404, // Shared advisory identity/dedup + critical-severity validation: 248,065 union bytes / 187,706 baseline = 1.3216 (2026-09-17). + test value bar in the lazy Step 7 section (value cards, weak paths, gate table, base control, machine checks; ~13.6KB): measured 1.396 (2026-09-29). + W1 guarded state-root resolution (`eval gstack-paths; : "${GSTACK_STATE_ROOT:?…}"`) in the Context Recovery preamble, the eureka log and each state-writing bash block; measured 1.401 (2026-09-30). + the shared QA review step's plan-check timing rule (plan checks and their revalidation run on --timeout-ms after smoke expiry); measured 1.4022 (2026-09-30). + maxSizeRatio: 1.405, // Shared advisory identity/dedup + critical-severity validation: 248,065 union bytes / 187,706 baseline = 1.3216 (2026-09-17). + test value bar in the lazy Step 7 section (value cards, weak paths, gate table, base control, machine checks; ~13.6KB): measured 1.396 (2026-09-29). + W1 guarded state-root resolution (`eval gstack-paths; : "${GSTACK_STATE_ROOT:?…}"`) in the Context Recovery preamble, the eureka log and each state-writing bash block; measured 1.401 (2026-09-30). + the shared QA review step's plan-check timing rule (plan checks and their revalidation run on --timeout-ms after smoke expiry); measured 1.4022 (2026-09-30). + the shared TEST_BOOTSTRAP owned-change undo rules (s03 H1-H3, M1) and the value-bar coverage wording (s03 M2/M3); measured 1.4044 (2026-10-02). }, 'plan-ceo-review': { skill: 'plan-ceo-review', diff --git a/test/qa-browser-preservation.test.ts b/test/qa-browser-preservation.test.ts index 0cd24f262..aea4d57d2 100644 --- a/test/qa-browser-preservation.test.ts +++ b/test/qa-browser-preservation.test.ts @@ -78,6 +78,18 @@ describe('compact QA bootstrap preserves native detection', () => { expect(bootstrap).not.toContain('git checkout --'); expect(bootstrap).not.toContain('delete silently'); }); + + test('shared {{TEST_BOOTSTRAP}} copy undoes only owned changes, like the QA copy', () => { + for (const skillName of ['ship', 'design-review']) { + const shared = generateTestBootstrap({ ...ctx, skillName }); + expect(shared).not.toContain('git checkout --'); + expect(shared).not.toMatch(/delete silently/i); + expect(shared).not.toMatch(/revert all bootstrap changes/i); + expect(shared).toMatch(/undo only/i); + expect(shared).toMatch(/preserve the user's edits/i); + expect(shared).toMatch(/unrelated edits are already staged, stop/i); + } + }); }); async function runRecipe(marker: string, options: { flow?: boolean; hostname?: string; response?: string } = {}) {