Editing the body of an already-released installer migration drifts its computed checksum (it hashes plan.toString()). The integrity guard then hard-aborted every prior install on upgrade with "applied migration checksum changed" — a 100% reproducible blocker (v1.3.0, all platforms). Already-applied migrations are filtered out of `pending` and never re-run, so a drifted checksum is functionally inert. ADR-0008 anticipates checksum-mismatch state as something the install-state layer must handle gracefully (plan -> apply -> recover/report), not abort on. This supersedes the published-checksum allowlist merged in #674 (per-release maintenance debt — every historical checksum hand-pinned, still throws for any unregistered value) with a general, self-healing recovery: - Replace the throwing guard with non-fatal `collectAppliedChecksumDrift`, surfaced on `plan.checksumDrift`. - Reconcile drifted stored checksums durably on the next state write (`reconcileDriftedChecksums`), idempotently (no perpetual writes). - Relocate the "shipped migration bodies are immutable" rule to a CI baseline test that locks every shipped migration's checksum and fails on body drift — where #615 should have been caught, instead of blocking users. Removes #674's legacyChecksums field, per-migration checksum pins, published-checksums.json fixture, and compat test. Fixes #670 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,6 @@ const RULES = [
|
||||
'tests/install-regressions.test.cjs',
|
||||
'tests/install-runtime-artifacts.test.cjs',
|
||||
'tests/install-path-detection.test.cjs',
|
||||
'tests/installer-migration-checksum-compat.test.cjs',
|
||||
'tests/release-tarball-smoke.install.test.cjs',
|
||||
'tests/runtime-artifact-layout.test.cjs',
|
||||
],
|
||||
@@ -255,7 +254,7 @@ function classify(files) {
|
||||
let fullMatrix = false;
|
||||
|
||||
for (const file of files) {
|
||||
if (['bin/', 'gsd-core/', 'agents/', 'commands/', 'docs/', 'hooks/', 'tests/', 'scripts/', 'src/'].some(p => file.startsWith(p)) ||
|
||||
if (['bin/', 'gsd-core/', 'agents/', 'commands/', 'docs/', 'hooks/', 'tests/', 'scripts/'].some(p => file.startsWith(p)) ||
|
||||
file === 'package.json' || file === 'package-lock.json' ||
|
||||
(file.startsWith('tsconfig') && file.endsWith('.json')) ||
|
||||
file.startsWith('.github/workflows/') ||
|
||||
|
||||
Reference in New Issue
Block a user