From c620de38e19fe63e8a6e361e11d706b5ed432b93 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Thu, 2 Apr 2026 21:38:06 -0700 Subject: [PATCH] fix: setup runs pending migrations so git pull + ./setup works (#774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: setup runs pending migrations so git pull + ./setup works Previously, version migrations only ran during /gstack-upgrade (Step 4.75). Users who updated via git pull + ./setup never got migrations applied, leaving stale skill directory structures in place. Now setup tracks the last-run version in ~/.gstack/.last-setup-version and runs any pending migrations automatically. Idempotent — safe to run multiple times. Co-Authored-By: Claude Opus 4.6 (1M context) * fix: setup runs pending migrations so git pull + ./setup works Previously, version migrations only ran during /gstack-upgrade (Step 4.75). Users who updated via git pull + ./setup never got migrations applied, leaving stale skill directory structures in place. Now setup tracks the last-run version in ~/.gstack/.last-setup-version and runs any pending migrations automatically. Addresses adversarial review findings: space-safe while-read loop, fresh install guard, upper-bound version check, missing VERSION guard. * chore: bump version and changelog (v0.15.2.1) Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 12 ++++++++++++ VERSION | 2 +- setup | 29 ++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 615dbf91..a7239b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.15.2.1] - 2026-04-02 — Setup Runs Migrations + +`git pull && ./setup` now applies version migrations automatically. Previously, migrations only ran during `/gstack-upgrade`, so users who updated via git pull never got state fixes (like the skill directory restructure from v0.15.1.0). Now `./setup` tracks the last version it ran at and applies any pending migrations on every run. + +### Fixed + +- **Setup runs pending migrations.** `./setup` now checks `~/.gstack/.last-setup-version` and runs any migration scripts newer than that version. No more broken skill directories after `git pull`. +- **Space-safe migration loop.** Uses `while read` instead of `for` loop to handle paths with spaces correctly. +- **Fresh installs skip migrations.** New installs write the version marker without running historical migrations that don't apply to them. +- **Future migration guard.** Migrations for versions newer than the current VERSION are skipped, preventing premature execution from development branches. +- **Missing VERSION guard.** If the VERSION file is absent, the version marker isn't written, preventing permanent migration poisoning. + ## [0.15.2.0] - 2026-04-02 — Voice-Friendly Skill Triggers Say "run a security check" instead of remembering `/cso`. Skills now have voice-friendly trigger phrases that work with AquaVoice, Whisper, and other speech-to-text tools. No more fighting with acronyms that get transcribed wrong ("CSO" -> "CEO" -> wrong skill). diff --git a/VERSION b/VERSION index 3654b689..edfc413f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.15.2.0 +0.15.2.1 diff --git a/setup b/setup index 2fdd2892..af23d2af 100755 --- a/setup +++ b/setup @@ -703,7 +703,34 @@ if [ "$INSTALL_CODEX" -eq 1 ]; then create_agents_sidecar "$SOURCE_GSTACK_DIR" fi -# 8. First-time welcome + legacy cleanup +# 8. Run pending version migrations +# Migrations handle state fixes that ./setup alone can't cover (stale config, +# orphaned files, directory structure changes). Each migration is idempotent. +MIGRATIONS_DIR="$SOURCE_GSTACK_DIR/gstack-upgrade/migrations" +CURRENT_VERSION=$(cat "$SOURCE_GSTACK_DIR/VERSION" 2>/dev/null || echo "unknown") +LAST_SETUP_VERSION=$(cat "$HOME/.gstack/.last-setup-version" 2>/dev/null || echo "0.0.0.0") +if [ -d "$MIGRATIONS_DIR" ] && [ "$CURRENT_VERSION" != "unknown" ] && [ "$LAST_SETUP_VERSION" != "$CURRENT_VERSION" ]; then + # Fresh install (no marker file) — skip migrations, just write marker + if [ ! -f "$HOME/.gstack/.last-setup-version" ]; then + : # fall through to marker write below + else + find "$MIGRATIONS_DIR" -maxdepth 1 -name 'v*.sh' -type f 2>/dev/null | sort -V | while IFS= read -r migration; do + m_ver="$(basename "$migration" .sh | sed 's/^v//')" + # Run if migration is newer than last setup version AND not newer than current version + if [ "$(printf '%s\n%s' "$LAST_SETUP_VERSION" "$m_ver" | sort -V | head -1)" = "$LAST_SETUP_VERSION" ] && [ "$LAST_SETUP_VERSION" != "$m_ver" ] \ + && [ "$(printf '%s\n%s' "$m_ver" "$CURRENT_VERSION" | sort -V | tail -1)" = "$CURRENT_VERSION" ]; then + echo " running migration $m_ver..." + bash "$migration" || echo " warning: migration $m_ver had errors (non-fatal)" + fi + done + fi +fi +mkdir -p "$HOME/.gstack" +if [ "$CURRENT_VERSION" != "unknown" ]; then + echo "$CURRENT_VERSION" > "$HOME/.gstack/.last-setup-version" +fi + +# 9. First-time welcome + legacy cleanup if [ ! -f "$HOME/.gstack/.welcome-seen" ]; then echo " Welcome! Run /gstack-upgrade anytime to stay current." touch "$HOME/.gstack/.welcome-seen"