A light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.
fix(3657): skip false-fail when pristine hash drifts after GSD update (#3767)
* test(3657): RED+shape-lock for verify-reapply-patches pristine-drift
Adds tests/bug-3657-verify-reapply-patches-pristine-drift.test.cjs:
- Core regression: exits 0 with reason=OK_PRISTINE_DRIFT_DETECTED when
on-disk gsd-pristine/ hash does not match backup-meta.json.pristine_hashes
- Counter-tests: real FAIL_USER_LINES_MISSING still caught when hashes match;
over-broad mode unchanged when backup-meta.json is absent; clean run
reports 0 failures when everything matches
- Multi-file: drift + real-failure handled independently per file
Updates tests/bug-2969-verify-reapply-patches.test.cjs REASON shape-lock to
include OK_PRISTINE_DRIFT_DETECTED (added by the #3657 fix).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3657): verify-reapply-patches skips pristine when hash drifts
When gsd-pristine/ is refreshed to a newer GSD version after a backup is
captured, the on-disk pristine's SHA-256 no longer matches the hash recorded
in backup-meta.json.pristine_hashes. Using the wrong-version pristine as the
diff baseline inverts the delta: every line the upstream removed between the
two versions appears as a "user-added line that must survive", producing
spurious FAIL_USER_LINES_MISSING false positives (Bug #3657).
Fix:
- Add sha256() and readPristineHashes() helpers to verify-reapply-patches.cjs
- In verifyFile(), when a pristine_hashes entry exists for the file, compare
the on-disk pristine's SHA-256 against it before accepting the baseline
- On hash mismatch, return immediately with status=ok and the new
REASON.OK_PRISTINE_DRIFT_DETECTED code, skipping the diff rather than
false-failing
- When no pristine_hashes entry exists (older installer / absent backup-meta),
fall through to the pre-fix behaviour (use on-disk pristine as-is)
- Export sha256, readPristineHashes, and OK_PRISTINE_DRIFT_DETECTED
New REASON code OK_PRISTINE_DRIFT_DETECTED is added to the frozen enum.
Exit code contract is unchanged: 0 for gate pass (including skipped-due-drift
files), 1 for real user-content failures, 2 for structural errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(3657): update changeset to reference PR #3767
* fix(3657): surface drifted_files in verify-reapply-patches JSON report
Extend the top-level JSON report shape with two additive fields:
- `drifted: N` — count of files skipped due to pristine-snapshot drift
- `drifted_files: [...]` — relative paths of those files
Per-file shape is unchanged (status:'ok' + reason:OK_PRISTINE_DRIFT_DETECTED)
for backward compat. Drift still exits 0; `failures` count is unaffected.
This gives workflow Step 5a structured data to gate on so drifted files are
no longer silently treated as a full PASS (codex adversarial-review finding 1).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3657): reapply-patches workflow halts on drifted files instead of silent pass
Insert a "Step 5a: drift check" block between the exit-code check and the
failures check in workflows/reapply-patches.md Step 5a. The new block:
1. Parses `drifted` + `drifted_files` from the JSON report (added in the
companion prod-code commit).
2. When DRIFTED_COUNT > 0, emits a formatted HALT message naming each
drifted file and instructs the user to re-baseline before re-running.
3. Sets DRIFT_DETECTED=true and exits non-zero so subsequent steps cannot
execute while drift is unresolved.
Drift is a distinct third state: it is not a failure (no missing user lines
were proven) but it is also not a clean pass (the diff was skipped entirely).
Existing pass/fail logic for VERIFY_STATUS and failures count is unchanged.
Closes the silent-skip gap identified in codex adversarial-review finding 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(3657): assert drifted_files report shape + workflow Step 5a drift check
Finding 1 (BLOCKER) — three new tests in bug-3657 test file:
- Single drifted file: drifted=1, drifted_files contains the file path,
failures=0, per-file shape unchanged (backward compat).
- Multi-file drift: drifted=2, drifted_files lists both paths, clean file
absent from array.
- No-drift baseline: drifted=0, drifted_files=[] always present in output.
Finding 2 (WARNING) — structural test on workflow source:
- Asserts Step 5a contains "Step 5a: drift check" heading.
- Asserts DRIFTED_COUNT, drifted_files, and DRIFT_DETECTED are referenced
(confirming the gate exists and uses the structured report fields).
- Asserts drift-check block appears before VERIFY_STATUS check (exit-code
is 0 for drift, so the drift check must precede the non-zero gate).
Also updates bug-2969 shape-lock to include the two new additive fields
(drifted, drifted_files) per the contract change in the prod-code commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(3657): address pr-review-toolkit + codex review + CI failures
- lint-tests: add // allow-test-rule: source-text-is-the-product at file
top of bug-3657 test file; the inline comment at line 477 was a prose
sentence, not a file-level annotation, so the lint scanner did not
recognise it as the bypass token
- Windows test failures (4 subtests): normalize relPath to forward slashes
before pristineHashes key lookup in verifyFile(); on Windows path.join
produces backslash-separated relPath values but backup-meta.json stores
keys with forward slashes, causing the hash lookup to silently return
undefined, falling through to use-as-is mode and producing the same
false FAIL_USER_LINES_MISSING that the fix was meant to prevent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): bump verify allowlist ceiling 9→10 for bug-3657 test file
Adding tests/bug-3657-verify-reapply-patches-pristine-drift.test.cjs in
the previous commit pushed the verify module from 9 to 10 test files.
The lint-test-file-count gate (added in #6313baad on main) enforces that
modules cannot exceed their allowlist ceiling, so all 6 test platforms
plus lint-tests and coverage failed with:
FAIL_EXCEEDS_ALLOWLIST: verify count=10 ceiling=9
The fix is to raise the ceiling from 9 to 10 and set issue=3767.
This file does not exist on this branch yet (introduced on main after
the branch diverged) so we add it here. The merged CI state will see
the bumped ceiling and pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> T
Tom Boucher committed
a7abc6df2fe2f46c7320da850033c90fad1433d2
Parent: 99b52a3
Committed by GitHub <noreply@github.com>
on 5/21/2026, 3:13:25 AM