From a7fc288f1cb7c3c220ab9311dd2bc1b99c8c8ee9 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Fri, 4 Sep 2026 12:17:52 -0700 Subject: [PATCH 1/2] fix(org-migration): fail on a bad baseline path, and route the runbook to the transfer steps Running the runbook straight through (D -> E -> F) hits `verify.sh` before any repo has moved, and with a baseline path that does not exist. Neither failure announced itself: - `verify.sh` validated the after-dir but never the baseline dir. A wrong path meant every repo simply missed its baseline file, so the comparison loop printed "missing snapshot" for the whole move list -- 31 lines that read as catastrophic drift rather than as one typo. Now it fails on the path and names it. An existing-but-empty baseline dir is the same class of mistake and is checked too. - The runbook's Part F cited `docs/data/org-migration/baseline`; the directory is dated, `2026-09-04-baseline`. - Parts A-E cover design Step 2 only, but Part F verifies a transfer that no part of the runbook performs -- Steps 3 and 4 live in the design doc and were never linked. Add a stop block before Part F with the transfer commands and the pointer, so the document no longer reads as complete start-to-finish. Part G additionally notes that a shell opened before the rename holds a stale sourced `gh` wrapper, which fails closed trying to switch to `smartwatermelon`; `exec bash -l` clears it. This bit on ASIAGO. Tests: two cases in test-verify.sh, both confirmed failing against the unpatched script before the fix. Claude-Session: https://claude.ai/code/session_01P7jGdvXTTzxwxjpf34qUbM --- docs/runbooks/org-migration-rename.md | 51 ++++++++++++++++++++-- scripts/org-migration/tests/test-verify.sh | 26 +++++++++++ scripts/org-migration/verify.sh | 14 ++++++ 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/docs/runbooks/org-migration-rename.md b/docs/runbooks/org-migration-rename.md index a5d380e..55f99d9 100644 --- a/docs/runbooks/org-migration-rename.md +++ b/docs/runbooks/org-migration-rename.md @@ -72,13 +72,49 @@ gh api repos/smartwatermelon/dotfiles --jq '.owner.login + " " + .owner.type' # cd ~/Developer/dotfiles && gh pr list --limit 1 # identity guard passes, no error ``` +## Stop: the transfer happens outside this runbook + +Parts A–E cover **Step 2** of the design only: the rename and the org. No +repo has moved yet. Parts F and G below verify a transfer, so do not run +them here — every repo would still report `owner is twistedmelonman (User)`, +which is correct for this moment and looks like 31 failures. + +Go to `docs/superpowers/specs/2026-09-03-org-migration-design.md` and do: + +- **Step 3** — transfer `github-workflows` alone and prove one consumer per + org still runs green. It is the cross-org dependency: both orgs reference + `uses: smartwatermelon/github-workflows/...`. Read the run log to confirm + the reusable workflow resolved from the new owner; a green check by itself + is not evidence. + + ```bash + bash scripts/org-migration/transfer.sh scripts/org-migration/move-list.txt \ + --only github-workflows --dry-run + bash scripts/org-migration/transfer.sh scripts/org-migration/move-list.txt \ + --only github-workflows + ``` + +- **Step 4** — transfer the remaining repos: + + ```bash + bash scripts/org-migration/transfer.sh scripts/org-migration/move-list.txt --dry-run + bash scripts/org-migration/transfer.sh scripts/org-migration/move-list.txt + ``` + +Come back to Part F when Step 4 is done. + ## F. Verify the transfer (`verify.sh`) +Run this **after** design Steps 3 and 4, not before. + ```bash bash scripts/org-migration/verify.sh scripts/org-migration/move-list.txt \ - docs/data/org-migration/baseline "$(mktemp -d)" + docs/data/org-migration/2026-09-04-baseline "$(mktemp -d)" ``` +The baseline directory is dated. `verify.sh` fails and names the path if you +get it wrong, rather than reporting every repo as a missing snapshot. + **Always give `verify.sh` a fresh, empty after-dir.** It refuses a directory that already holds files, because a leftover JSON from an earlier run would be compared as though this run had just written it — a repo whose snapshot failed @@ -103,8 +139,17 @@ real drift. ## G. The other two machines (TILSIT, MIMOLETTE) -Run section D on each, before the alias-removal PR (plan Task 12) merges. -Until then the alias keeps the old `hosts.yml` name working. +Run section D on each, before the alias-removal PR (plan Task 12, design +Step 6) merges. Until then the alias keeps the old `hosts.yml` name working. + +Section D re-logins the keyring. On a machine whose shell was already open +before the rename, the sourced `gh` wrapper is also stale: reload it with +`exec bash -l` before verifying, or the old wrapper still tries to switch to +`smartwatermelon` and fails closed. `which gh` and `hash -t gh` show the +staleness; `command -v` does not. + +Steps 5–7 of the design (org secret, cleanup, docs) are not covered by this +runbook. ## Undo diff --git a/scripts/org-migration/tests/test-verify.sh b/scripts/org-migration/tests/test-verify.sh index b563c18..8cd55b0 100755 --- a/scripts/org-migration/tests/test-verify.sh +++ b/scripts/org-migration/tests/test-verify.sh @@ -194,4 +194,30 @@ else _fail "nested clone broken: rc=${rc} err=${err}" fi +# Case 10: a baseline dir that does not exist must fail on the path, not +# degrade into a "missing snapshot" line per repo. A mistyped baseline path +# otherwise reads as total drift across the whole move list. +out="$(OM_TEST_CORE="${WORK}/core-good" PATH="${WORK}/bin:${PATH}" bash "${VERIFY}" \ + "${WORK}/list" "${WORK}/nonexistent-baseline" "${WORK}/after-missing-base" \ + --clones "${WORK}/clones-good" 2>&1)" +rc=$? +if [[ "${rc}" -eq 1 && "${out}" == *"does not exist"* && "${out}" != *"missing snapshot"* ]]; then + _pass "missing baseline dir: named as the failure, exit 1" +else + _fail "missing baseline dir: rc=${rc} out=${out}" +fi + +# Case 11: an empty baseline dir is the same class of mistake -- a path that +# exists but holds no snapshots. +mkdir -p "${WORK}/empty-baseline" +out="$(OM_TEST_CORE="${WORK}/core-good" PATH="${WORK}/bin:${PATH}" bash "${VERIFY}" \ + "${WORK}/list" "${WORK}/empty-baseline" "${WORK}/after-empty-base" \ + --clones "${WORK}/clones-good" 2>&1)" +rc=$? +if [[ "${rc}" -eq 1 && "${out}" == *"is empty"* && "${out}" != *"missing snapshot"* ]]; then + _pass "empty baseline dir: named as the failure, exit 1" +else + _fail "empty baseline dir: rc=${rc} out=${out}" +fi + exit "${fail}" diff --git a/scripts/org-migration/verify.sh b/scripts/org-migration/verify.sh index 3f4c413..79492a0 100755 --- a/scripts/org-migration/verify.sh +++ b/scripts/org-migration/verify.sh @@ -34,6 +34,20 @@ base="${positional[1]}" after="${positional[2]}" fail=0 +# The baseline dir must exist and hold snapshots. Without this check a wrong +# path is not an error: every repo simply misses its baseline file and the +# comparison loop reports "missing snapshot" for the whole move list, which +# reads as catastrophic drift rather than as a typo. Fail on the path itself +# so the message names the real problem. +if [[ ! -d "${base}" ]]; then + echo "verify: baseline-dir ${base} does not exist" >&2 + exit 1 +fi +if [[ -z "$(ls -A "${base}" 2>/dev/null || true)" ]]; then + echo "verify: baseline-dir ${base} is empty" >&2 + exit 1 +fi + # The after-dir must be ours alone. A leftover JSON from an earlier run would # be compared as though this run had just written it, so a repo whose snapshot # failed now could still be reported ok from stale state. From 47c2f2e13391a0c3cbe73a13f4f61fc5a9948885 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Fri, 4 Sep 2026 12:23:07 -0700 Subject: [PATCH 2/2] chore: retrigger CI after github-workflows org transfer The prior runs failed at workflow resolution (0s, no jobs): Actions does not follow owner redirects for reusable workflow references, and smartwatermelon/github-workflows did not literally exist between the org creation and the transfer. Nothing in the tree changed. Claude-Session: https://claude.ai/code/session_01P7jGdvXTTzxwxjpf34qUbM