Summary
gstack-upgrade/migrations/v1.40.0.0.sh unconditionally touches its done-marker (~/.gstack/.migrations/v1.40.0.0.done) at the end of the script — even when the .brain-privacy-map.json patch was skipped because jq is missing. The migration logs only a WARN: line during a noisy ./setup, and subsequent /gstack-upgrade invocations no-op against the done-marker without re-checking, so the privacy-map repair never actually lands unless the user spots the warning, installs jq, manually removes the marker, and re-runs.
Repro
- Box without
jq installed (e.g., Debian 12 without jq from apt).
- Upgrade from any pre-1.40 gstack to v1.40.0.0.
./setup runs the migration and emits:
[v1.40.0.0] WARN: jq not found; skipping privacy-map repair. Install jq and re-run gstack-upgrade, or run gstack-artifacts-init manually.
- Then unconditionally touches
~/.gstack/.migrations/v1.40.0.0.done.
- Install
jq and re-run /gstack-upgrade (or the migration script directly) — the script short-circuits at [ -f "${DONE}" ] && exit 0 and never patches the privacy-map.
.brain-allowlist and .gitattributes were patched on the first pass (no jq needed there), so the inconsistency is silent: federation sync still drops /plan-eng-review test plans because the privacy-map class is missing, but allowlist/gitattributes look fine.
Workaround
sudo apt install jq
rm ~/.gstack/.migrations/v1.40.0.0.done
bash ~/.claude/skills/gstack/gstack-upgrade/migrations/v1.40.0.0.sh
After this, jq '[.[] | select(.pattern | test("eng-review-test-plan"))]' ~/.gstack/.brain-privacy-map.json returns the artifact-class entry.
Suggested fix
Two options, pick one:
-
Defer touch "${DONE}" until all three target files are either patched or confirmed up to date. Track per-file success; only mark done when nothing was skipped. The "fresh-init user with nothing to patch" path stays a no-op because all three if ! grep -Fq ... / if ! jq -e ... gates report "already present."
-
Use a per-prerequisite marker. When jq is missing, write v1.40.0.0.jq-missing instead of v1.40.0.0.done. The migration runner treats .jq-missing as "retry on next run" and only promotes it to .done once jq is found and the patch lands.
Option 1 is simpler and matches the existing single-marker scheme; Option 2 is more general and would help future migrations with optional-tool dependencies.
Either way, the WARN: line should probably also surface louder — ./setup output is long enough that a single warning line scrolls past easily.
Environment
- gstack v1.40.0.0 (upgraded from v1.39.1.0)
- Debian 12 / Linux 6.1, install_type=global-git
- jq not installed at upgrade time; installed after the fact
Summary
gstack-upgrade/migrations/v1.40.0.0.shunconditionallytouches its 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. The migration logs only aWARN:line during a noisy./setup, and subsequent/gstack-upgradeinvocations no-op against the done-marker without re-checking, so the privacy-map repair never actually lands unless the user spots the warning, installs jq, manually removes the marker, and re-runs.Repro
jqinstalled (e.g., Debian 12 withoutjqfrom apt)../setupruns the migration and emits:~/.gstack/.migrations/v1.40.0.0.done.jqand re-run/gstack-upgrade(or the migration script directly) — the script short-circuits at[ -f "${DONE}" ] && exit 0and never patches the privacy-map..brain-allowlistand.gitattributeswere patched on the first pass (no jq needed there), so the inconsistency is silent: federation sync still drops/plan-eng-reviewtest plans because the privacy-map class is missing, but allowlist/gitattributes look fine.Workaround
After this,
jq '[.[] | select(.pattern | test("eng-review-test-plan"))]' ~/.gstack/.brain-privacy-map.jsonreturns theartifact-class entry.Suggested fix
Two options, pick one:
Defer
touch "${DONE}"until all three target files are either patched or confirmed up to date. Track per-file success; only mark done when nothing was skipped. The "fresh-init user with nothing to patch" path stays a no-op because all threeif ! grep -Fq .../if ! jq -e ...gates report "already present."Use a per-prerequisite marker. When jq is missing, write
v1.40.0.0.jq-missinginstead ofv1.40.0.0.done. The migration runner treats.jq-missingas "retry on next run" and only promotes it to.doneonce jq is found and the patch lands.Option 1 is simpler and matches the existing single-marker scheme; Option 2 is more general and would help future migrations with optional-tool dependencies.
Either way, the
WARN:line should probably also surface louder —./setupoutput is long enough that a single warning line scrolls past easily.Environment