fix: v1.40.0.0 migration done-marker leaves privacy-map half-patched on jq-less machines (#1581)#1589
Open
stedfn wants to merge 2 commits into
Open
fix: v1.40.0.0 migration done-marker leaves privacy-map half-patched on jq-less machines (#1581)#1589stedfn wants to merge 2 commits into
stedfn wants to merge 2 commits into
Conversation
added 2 commits
May 18, 2026 18:23
…ds (garrytan#1581) The v1.40.0.0 migration unconditionally `touch`ed its done-marker, even when the jq-gated `.brain-privacy-map.json` patch was skipped because jq was missing on the user's machine. On subsequent runs, the script short-circuited on the marker so the privacy-map repair never landed. Federation sync then silently dropped `/plan-eng-review` test plans. Track every failure mode via a single `incomplete` flag: jq missing, malformed JSON, jq mutation failure, tempfile creation failure, `mv` failure, allowlist append failure, gitattributes append failure. The marker is written only when `incomplete=0`, so the migration runner retries on the next /gstack-upgrade once the prerequisites are met.
…arrytan#1581) 8 cases pinning the fix: - Case 1 (happy path): jq present, fresh privacy-map → all three files patched, marker written. - Case 2 (regression for garrytan#1581): jq missing, privacy-map present → marker must NOT be written. Fails against the buggy script, passes against the fix. - Case 3 (recovery): jq missing, then jq restored → patch lands on second run. - Case 4 (idempotency): privacy-map already has correct entry → no mutation, marker written. - Case 5 (fresh-init): privacy-map file absent → allowlist + gitattrs patched, marker written. - Case 6 (malformed JSON): broken privacy-map JSON → no marker, no mutation. - Case 7 (jq mutation failure): fake jq returning 1 → no marker, tempfile cleaned up. - Case 8 (allowlist append failure): read-only allowlist → no marker. Tests use spawnSync('bash', [MIGRATION], …) with isolated tmpHomes. "jq missing" sets PATH to a curated dir of symlinks to standard utils, omitting jq; "jq mutation fails" uses an `exit 1` shim. Avoids blanket-clearing PATH (which would hide bash/grep/etc).
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix v1.40.0.0 migration done-marker (#1581)
Fixes #1581.
What this fixes
gstack-upgrade/migrations/v1.40.0.0.shused to unconditionallytouchits done-marker (~/.gstack/.migrations/v1.40.0.0.done) at the end of the script, even when the.brain-privacy-map.jsonpatch was skipped becausejqis missing from the user's PATH. On subsequent runs the script short-circuits at[ -f "${DONE}" ] && exit 0, so the privacy-map repair never lands unless the user spots the buried WARN, installs jq, manually removes the marker, and re-runs.The silent failure path:
.brain-allowlistand.gitattributesget patched on the first pass (they don't need jq), so/gstack-upgradelooks successful — but federation sync silently drops/plan-eng-reviewtest plans because the privacy-map entry forprojects/*/*-eng-review-test-plan-*.mdwas never added.The fix
Defer
touch "${DONE}"until every required repair either succeeded or was provably unnecessary. Track every failure mode via a singleincompleteflag:mktempfailuremvfailure on the rewriteprintf >>writing to a read-only file, etc.)The marker is written only when
incomplete=0, so the migration runner retries on the next/gstack-upgradeonce the prerequisites are met. No manual marker-removal required.Tests
8 cases in
test/gstack-upgrade-migration-v1_40_0_0.test.ts:Case 2 fails against the unmodified script (verified before applying the fix) and passes against the fix.
Proposed remediation migration (for the next wave)
The in-place fix above helps fresh installs and users who haven't yet upgraded to v1.40.0.0. It does NOT help users who already ran the buggy version — their
v1.40.0.0.donemarker is set, and the migration runner's version check (gstack-upgrade/SKILL.md:206) won't re-invokev1.40.0.0.shfor users whose installed version is already>= 1.40.0.0.To remediate stuck users automatically, a new migration script needs to ship in the next wave. The script below is idempotent, well-tested (9 cases, all green locally), and ready to drop in at whatever version your next wave assigns. The filename and the
DONEpath inside need to match the wave version you pick (e.g. rename tov1.41.0.0.shand updateDONE="${MIGRATION_DIR}/v1.41.0.0.done").I'm holding the remediation back from this PR because pre-claiming a migration version slot conflicts with how you batch community PRs into release waves. If you'd prefer I add it to this PR at a specific version, happy to push a follow-up commit — just tell me which slot you want.
Proposed
gstack-upgrade/migrations/v1.40.0.1.sh(rename + update DONE name)Proposed
test/gstack-upgrade-migration-v1_40_0_1.test.ts(9 cases)Available on request — full file is 200 lines. Cases:
v1.40.0.0.done+ missing entry (the user-visible field flow) → entry added, new marker written.Test plan
bun test test/gstack-upgrade-migration-v1_40_0_0.test.ts— 8/8 passv1.40.0.0.sh(regression test catches the bug)bun test) still greenOut of scope
mark_done()helper across migrations..brain-privacy-map.jsoncontent — out of scope; we log an error and bail rather than mutate corrupt JSON.