docs: replace the cutover plan with the phased one that matches reality
Phase 1 requires nothing from anyone: agents keep pushing to GitHub, a timer syncs GitHub -> Windy Git every 15 minutes, CI runs on Veron against current code. Phase 2 flips one repo at a time, only when that repo is idle. Records the direction mistake honestly: the source of truth is wherever people are actually typing, not wherever the plan says it should be. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,63 +1,65 @@
|
|||||||
# Windy Git is the daily driver — 2026-08-13
|
# Migration plan — GitHub first, Windy Git second, flip per repo
|
||||||
|
|
||||||
Grant's call, 2026-08-12: **push to Windy Git; GitHub is the second copy.**
|
**Superseded the 2026-08-13 "daily driver" cutover, which was premature.**
|
||||||
|
|
||||||
you ──push──▶ Windy Git (Veron 1) ──▶ CI on 24 cores
|
## What went wrong, recorded so it is not repeated
|
||||||
│
|
|
||||||
└──push-mirror on every commit──▶ GitHub
|
|
||||||
|
|
||||||
## 🔴 The one rule this creates
|
Nine repos were migrated writable with **push-mirrors pointed at GitHub**. At
|
||||||
|
the same time a dozen agent sessions on the Mac mini were pushing to GitHub
|
||||||
|
continuously — so GitHub, not Windy Git, was where the live work actually was.
|
||||||
|
|
||||||
**Do not push directly to GitHub for a migrated repo.**
|
A push-mirror force-updates refs. On its 8-hour timer it would have pushed Windy
|
||||||
|
Git's stale copy **over live work, silently, with no conflict to notice.**
|
||||||
|
|
||||||
A push mirror makes GitHub match Windy Git. Anything committed straight to
|
All nine mirrors were removed before the first timer fired, and every GitHub
|
||||||
GitHub is **overwritten on the next sync**, silently, with no conflict and no
|
repo was verified untouched (latest push predated the mirrors). **No work was
|
||||||
warning. That is the cost of having one writer, and one writer is the point —
|
lost.** The mistake was direction, and the lesson is: *the source of truth is
|
||||||
two writers with no reconciliation is how you lose work you thought was saved.
|
wherever people are actually typing, not wherever the plan says it should be.*
|
||||||
|
|
||||||
If you must hotfix on GitHub: push there, then immediately pull that commit into
|
## Phase 1 — now. Nothing changes for anyone.
|
||||||
Windy Git *before* anything triggers a mirror sync. Better: don't.
|
|
||||||
|
|
||||||
## Migrated (9)
|
Mac mini agents ──push──▶ GitHub ──sync every 15 min──▶ Windy Git ──▶ CI on Veron
|
||||||
|
|
||||||
`windy-calendar` · `windy-search` · `windy-registry` · `Windy-Clone` ·
|
- **You do not have to tell your agents anything.** No remote changes, no
|
||||||
`WindyCloud` · `windy-cloud-sites` · `windy-mind` · `eternitas` · `windy-agent`
|
coordination, no "everyone stop pushing." They keep working exactly as they
|
||||||
|
are.
|
||||||
|
- `windygit-sync.timer` runs `scripts/sync_from_github.sh` every 15 minutes.
|
||||||
|
- Windy Git is **force-updated** on purpose: it holds nothing anyone depends on,
|
||||||
|
so GitHub always wins and there is **no merge to reconcile**. That is the
|
||||||
|
whole point of not flipping until a repo is quiet.
|
||||||
|
- CI runs on Veron 1 against current code, on the 36 workflows that already say
|
||||||
|
`runs-on: [self-hosted, linux, x64]`.
|
||||||
|
|
||||||
All writable (`mirror=false`), all push-mirroring to GitHub with
|
Tracked repos live in `REPOS` in the script (currently 9 of 141).
|
||||||
`sync_on_commit: true`. Clone from `https://app.windygit.com/windyadmin/<repo>.git`.
|
|
||||||
|
|
||||||
**Not migrated on purpose:** `windy-pro`. Six checkouts exist, the build counter
|
## Phase 2 — later, one repo at a time, only when that repo is idle
|
||||||
has forked three ways (main 12 / overnight 34 / wave-44 56), and two sessions
|
|
||||||
recorded different HEADs hours apart. Resolve which is current and write it
|
|
||||||
down first (G11.5). The import script refuses it by name.
|
|
||||||
|
|
||||||
## CI
|
For a single repo, when nobody is mid-work on it:
|
||||||
|
|
||||||
The runner advertises `veron-1`, `linux-x64`, `self-hosted`, `linux`, `x64`.
|
1. Remove it from `REPOS` in `sync_from_github.sh` — **first**, or the sync will
|
||||||
**36 of 36 active workflows in the fleet already say
|
fight its authors and win.
|
||||||
`runs-on: [self-hosted, linux, x64]`** — they were written for the self-hosted
|
2. Point that repo's sessions at Windy Git:
|
||||||
runners that died when the repos went private, so they run **as-is, unedited**.
|
`git remote set-url origin https://app.windygit.com/windyadmin/<repo>.git`
|
||||||
|
3. Add a push-mirror back to GitHub with `sync_on_commit: true`, so GitHub stays
|
||||||
|
a current second copy.
|
||||||
|
|
||||||
Proven: `windy-calendar`'s existing `.github/workflows/ci.yml` ran on Veron 1
|
**Never flip more than one repo at a time, and never while an agent is working
|
||||||
and reported success with no changes.
|
in it.** A dozen parallel sessions is exactly the situation where a big-bang
|
||||||
|
cutover produces the dirty-branch mess this plan exists to avoid.
|
||||||
|
|
||||||
**Per-repo secrets are not imported.** A repo whose CI needs a database URL or
|
## What is NOT on Windy Git
|
||||||
an API key will fail until those are set in its Gitea repo settings. Set them as
|
|
||||||
each repo needs them, not speculatively.
|
**9 of 141 repos.** The whole GitHub account is 1.58 GB, so the rest is a
|
||||||
|
capacity non-issue — it simply has not been imported yet. Add repos to the
|
||||||
|
import list as they become useful to build.
|
||||||
|
|
||||||
|
**`windy-pro` is excluded on purpose.** Six checkouts, a build counter forked
|
||||||
|
three ways, two sessions recording different HEADs hours apart. Resolve which is
|
||||||
|
current and write it down before importing (G11.5). The import script refuses it
|
||||||
|
by name.
|
||||||
|
|
||||||
## Backups
|
## Backups
|
||||||
|
|
||||||
Nightly `windygit-backup.timer` at 04:17 (`Persistent=true`, so a window missed
|
`windygit-backup.timer`, nightly 04:17, `git bundle --all` + verify + `windgit`
|
||||||
while the workstation is off is caught up rather than skipped). Every repo is
|
schema dump to R2, 30-day retention. **Restore rehearsed:** a bundle was pulled
|
||||||
bundled `--all`, verified, and uploaded to R2 with the `windgit` schema.
|
from R2, cloned, and its HEAD matched live `origin/main` exactly.
|
||||||
|
|
||||||
**Restore is rehearsed, not assumed:** a bundle was pulled back from R2, cloned,
|
|
||||||
and its HEAD matched live `origin/main` exactly.
|
|
||||||
|
|
||||||
## Verify the loop yourself
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://app.windygit.com/windyadmin/windy-calendar.git
|
|
||||||
cd windy-calendar && git commit --allow-empty -m "probe" && git push
|
|
||||||
# CI runs on Veron 1; GitHub receives the commit within ~20s
|
|
||||||
```
|
|
||||||
|
|||||||
Reference in New Issue
Block a user