fix(migrations): v1.27 remediation prints a real command instead of a fictional flag

Every skip/failure path referenced '/setup-gbrain --rerun-migration',
which is implemented nowhere, and promised the migration 'will ask
again next upgrade', which the version-window runners make false. All
five sites now print the direct GSTACK_MIGRATE_ASSUME_YES=1 bash
invocation. Runner-side re-offer tracking is filed in TODOS.
This commit is contained in:
Garry Tan 2026-08-14 17:11:48 -07:00
parent fb20ada4ac
commit 800716e9a4
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
2 changed files with 31 additions and 9 deletions

View File

@ -45,6 +45,13 @@ JOURNAL="${MIGRATION_DIR}/v1.27.0.0.journal"
DONE="${MIGRATION_DIR}/v1.27.0.0.done"
SKIPPED="${MIGRATION_DIR}/v1.27.0.0.skipped-by-user"
# Real, copy-pasteable re-run command for every remediation message below.
# There is no runner re-ask: the upgrade runners' version windows never
# re-select an already-passed migration, so the only honest remediation is
# a direct invocation of this script ($0-derived so it survives any cwd).
SELF_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
RERUN_CMD="GSTACK_MIGRATE_ASSUME_YES=1 bash ${SELF_PATH}"
USER_NAME="${USER:-$(whoami 2>/dev/null || echo unknown)}"
OLD_REPO_NAME="gstack-brain-${USER_NAME}"
NEW_REPO_NAME="gstack-artifacts-${USER_NAME}"
@ -61,8 +68,8 @@ mkdir -p "$MIGRATION_DIR"
# Already done? exit silently.
[ -f "$DONE" ] && exit 0
# User opted out previously? exit silently. (Re-invoke via
# `/setup-gbrain --rerun-migration` removes this marker.)
# User opted out previously? exit silently. (To re-run after an opt-out:
# rm the skipped-by-user marker, then invoke this script directly.)
[ -f "$SKIPPED" ] && exit 0
journal_done() {
@ -119,13 +126,16 @@ EOF
read -r REPLY || REPLY=""
case "$REPLY" in
n|N|no|No|NO)
echo " Skipping migration. Re-run via /setup-gbrain --rerun-migration." >&2
echo " Skipping migration. To re-run later:" >&2
echo " rm ${SKIPPED} && ${RERUN_CMD}" >&2
touch "$SKIPPED"
exit 0
;;
skip|skip-for-now|s)
echo " Skipping for now. Will ask again next upgrade." >&2
# Don't write SKIPPED — leave both old + new state untouched, ask again next time.
echo " Skipping for now. Re-run manually with: ${RERUN_CMD}" >&2
# Don't write SKIPPED — leave both old + new state untouched. The
# upgrade runner will NOT re-select this migration, so re-running is
# manual via the command above.
exit 0
;;
esac
@ -138,9 +148,9 @@ EOF
if [ "${GSTACK_MIGRATE_ASSUME_YES:-0}" = "1" ]; then
echo " (non-interactive: proceeding — GSTACK_MIGRATE_ASSUME_YES=1)" >&2
else
echo " Non-interactive session: skipping for now (will ask again next upgrade)." >&2
echo " To proceed unattended: GSTACK_MIGRATE_ASSUME_YES=1 ./setup" >&2
echo " To run interactively: /setup-gbrain --rerun-migration" >&2
echo " Non-interactive session: skipping for now." >&2
echo " Re-run manually with: ${RERUN_CMD}" >&2
echo " To run interactively: bash ${SELF_PATH}" >&2
exit 0
fi
fi
@ -357,7 +367,7 @@ done
if [ -n "$INCOMPLETE" ]; then
echo " [v1.27.0.0] migration INCOMPLETE — pending step(s):$INCOMPLETE" >&2
echo " Completed steps are journaled and will be skipped on re-run." >&2
echo " Re-run via: /setup-gbrain --rerun-migration" >&2
echo " Re-run manually with: ${RERUN_CMD}" >&2
exit 1
fi
touch "$DONE"

View File

@ -190,6 +190,13 @@ describe('v1.27.0.0 migration — #1383 consent + failure-stays-pending contract
expect(r.code).toBe(0);
expect(r.stderr).toContain('skipping for now');
expect(r.stderr).toContain('GSTACK_MIGRATE_ASSUME_YES=1');
// The remediation must be REAL: a direct invocation of this script.
// `/setup-gbrain --rerun-migration` never existed, and the runners'
// version windows never re-select a passed migration, so "will ask
// again next upgrade" was false.
expect(r.stderr).toContain('v1.27.0.0.sh');
expect(r.stderr).not.toContain('--rerun-migration');
expect(r.stderr).not.toContain('ask again');
// Old state untouched, nothing recorded as done.
expect(fs.existsSync(path.join(tmpHome, '.gstack-brain-remote.txt'))).toBe(true);
expect(fs.existsSync(path.join(tmpHome, '.gstack-artifacts-remote.txt'))).toBe(false);
@ -205,6 +212,11 @@ describe('v1.27.0.0 migration — #1383 consent + failure-stays-pending contract
expect(r.code).toBe(1);
expect(r.stderr).toContain('PENDING');
expect(r.stderr).toContain('INCOMPLETE');
// Honest remediation: direct invocation, not the nonexistent
// /setup-gbrain --rerun-migration flag.
expect(r.stderr).toContain('Re-run manually with:');
expect(r.stderr).toContain('GSTACK_MIGRATE_ASSUME_YES=1');
expect(r.stderr).not.toContain('--rerun-migration');
expect(fs.existsSync(path.join(tmpHome, '.gstack/.migrations/v1.27.0.0.done'))).toBe(false);
const journal = fs.readFileSync(
path.join(tmpHome, '.gstack/.migrations/v1.27.0.0.journal'),