synthesis-machine-sync · diff
v1.0.0 to v2.0.0
44 added, 139 removed. Audit B to A.
---
name: synthesis-machine-sync
- description: "Enroll, sync, hand off, and retire Macs in a personal fleet with git plus the leased coordination board. Use when asked to: machine sync, enroll a Mac, fleet handoff, move work to another Mac, resume on another Mac, fleet doctor, bootstrap a new Mac, retire a Mac, workspace subscriptions."
+ description: "Move work between the principal's Macs and bring a Mac in or out: leave with synthesis handoff, arrive and resume, set up a new Mac, retire an old one. Use for: move work to another Mac, resume on another Mac, machine sync, bootstrap a new Mac, enroll a Mac, retire a Mac."
license: "Apache-2.0"
- depends_on: []
+ depends_on: ["synthesis-mac-sync", "synthesis-daily-rituals"]
metadata:
author: "Rajiv Pant"
- version: "1.0.0"
+ version: "2.0.0"
source_repo: "github.com/synthesisengineering/synthesis-skills"
source_type: "public"
+ format: v5
---
# Machine Sync
- Keep a personal fleet of Macs (N=2 first) working as one system. Git remotes
- plus the leased coordination board are the only transports: every shared
- write goes through compare-and-swap, every Mac keeps its own machine
- identity, and no file-replication transport sits in any write path.
-
- This skill is the **protocol** — enroll/sync/leave/handoff plus the engines
- that enforce them. Your personal stores (fleet registry copy, repos
- manifest, subscriptions) travel in the personal knowledge repo and
- materialize to each Mac.
-
- ## Non-negotiables
-
- - Each Mac mints its own stable machine-id once
- (`~/.synthesis/fleet/machine-id`, mode 0600). The file never moves to
- another Mac; only the enrollment receipt names it.
- - The fleet registry (`machines.json`) names exactly one primary. A
- secondary enrolls against the synced copy, never by founding a second
- fleet.
- - Shared board rows identify sessions by `(machine_id, session_uuid,
- client_ref)`. Liveness is heartbeat age on the board, never a pid from
- another Mac.
- - Secrets ride the `synthesis-fleet-secrets` provider, never synced files.
- No secret value appears in any synced store, board message, or receipt.
- - Resume is harness-neutral: plan file + git + board only. No step in the
- handoff path branches on the destination client lane.
-
- ## Enroll a new Mac
-
- Clean-install path only — never copy one Mac's state onto another. One
- command, the same for every scenario, downloads and installs
- everything, then onboards by asking questions: it detects what the Mac
- holds, recommends the best path, finds the knowledge repo over GitHub
- sign-in (running it when needed) or asks for it, derives home, label,
- skill source, workspace, and manifest, founds a new fleet when the
- repo holds none and otherwise joins as a secondary, narrates every
- repo as it lands, and publishes the enrollment back on success:
-
- ```bash
- curl -fsSL https://raw.githubusercontent.com/synthesisengineering/synthesis-skills/stable/onboard.sh | sh
- ```
-
- The join mints identity, clones subscribed repos, installs the hooks
- runtime plus the skill set, enrolls the machine, verifies the doctor, and
- publishes the enrollment to the shared registry. Every step writes a
- receipt under `~/.synthesis/fleet/receipts/`; a rerun after any failure
- or interrupt resumes safely and reports `noop` for finished steps. The
- flags `--kb`, `--label`, `--role`, and `--workspace` override the
- interactive answers for scripted runs. The underlying
- `fleet_bootstrap.py` script is an agent-and-test entry point; humans use
- the one-command installer above (or `synthesis fleet join` once set up).
-
- Robustness: taken labels offer the first free variant; renamed Macs
- are offered a relabel (explicit labels are never touched);
- concurrent enrollments merge instead of conflicting; interrupted
- clones land atomically and reruns resume; mint races adopt the
- winner; role contradictions and foreign unpushed work fail closed
- with the remedy named.
-
- ## Sync (fetch shared state)
-
- Syncing means pulling authority through git, on each Mac, independently:
-
- 1. Refresh the board mirror: `coordination.py status` (authority reads
- always fence through the lease; display reads label their lease SHA).
- 2. Pull subscribed repos; the divergence scan refuses split checkouts
- before they become push races.
- 3. Keep synced configs `~`-rooted: the doctor fails closed on literal
- home paths in synced files, and every consumer expands on load.
-
- Never copy `~/.synthesis` subtrees, seats, spools, or transcript caches
- between Macs. Per-machine state stays per-machine; shared state arrives
- only through its remote.
-
- ## Handoff (move work across Macs)
-
- Work moves; processes do not. The unit is a repo plus its flushed
- manifests, sealed under a ticket id.
+ Keep the principal's Macs working as one system. Work moves; processes do not. Git remotes
+ carry project records and code, the iCloud sync folder carries config and credentials
+ (`synthesis-mac-sync`), and everything else is per Mac: each Mac has its own board, its own
+ sessions and its own claims.
- Source Mac — the gate refuses `BLOCKED` before posting anything:
+ ## Binding rules
- 1. Quiesce: commit or manifest everything; nothing dirty, unpushed, or
- unpulled in the handing-off scope.
- 2. `fleet_handoff.create_handoff_offer`: readiness `REMOTE_READY` (or
- `CLEAN` when nothing moves) posts a `handoff-offer` addressed to the
- destination machine-id, parks the source row (claims frozen, not
- freed), and seals the artifact.
- 3. The sealed artifact (`<ticket>.sealed.json`) carries the ticket id and
- the per-repo `(remote, branch, sha)` triples.
+ 1. **Clean install only.** Never copy one Mac's `~/.synthesis`, board session files, harness caches or transcript caches onto another; shared state arrives only through its remote or the sync folder.
+ 2. **Leave only when nothing claimed is stranded:** `synthesis handoff` per project, then the strand scan. Dirty, unpushed or upstream-less work means the move is not done, and nothing reports it ready.
+ 3. **Arrive without overwriting:** never pull over uncommitted changes; list them and decide with the principal first.
+ 4. **Resume from the records alone:** project files, git and this Mac's board. No step depends on which harness (Claude Code, Codex, Muse) picks the work up.
+ 5. **Secrets travel only through the sync folder's sensitive files** (`chmod 600`), never through git, a board message, a log or a prompt.
+ 6. **Synced config stays `~`-rooted;** a literal `/Users/<name>/` path breaks on the other Mac. Consumers expand `~` and `$HOME` when they load.
+ 7. **A new Mac is protected before its first commit:** setup, config pull, then `synthesis doctor` healthy. A fresh Mac is where a scanner once failed open.
+ 8. **Judge a move by `git log` and `git status`,** never by the absence of an error line: a refused commit can print nothing that looks like failure.
- Destination Mac — pull, verify, claim, accept, resume:
+ ## Contents
- 1. Pull the board; find the offer addressed to this machine-id.
- 2. `fleet_handoff.verify_destination`: every repo resolves by remote URL,
- the offered SHAs are reachable from the remote, and the destination
- tree is clean. Dirty state refuses with the file list; the source row
- stays parked so the work is recoverable.
- 3. Claim the scope through the normal claim verb (overlap with the parked
- source annotates `overlaps-parked`, with provenance), post
- `handoff-accept`, then complete the resume checklist: board truth,
- code truth, context truth (re-read from synced stores), claim truth,
- and the written resume receipt. A resume without a receipt is
- incomplete; the doctor flags it.
- 4. The loop runs identically for every destination lane — no step reads
- the seat's client.
+ - **Procedure** (below): leave, arrive, a new Mac, retire a Mac. Read every time.
+ - `synthesis-mac-sync`'s [leaving-and-arriving.md](../synthesis-mac-sync/references/leaving-and-arriving.md): the same steps with the iCloud checks around them. Read when config also moved.
+ - [references/coverage-map.md](references/coverage-map.md): where every 1.0.0 rule lives now. [references/preserved.md](references/preserved.md): the retired fleet machinery and why, with the 1.0.0 SKILL.md verbatim. Read only to review the rewrite.
- ## Leave (retire a Mac)
+ ## Procedure
- 1. Hand off or release every active row the Mac owns; park rows it may
- resume before the retirement date.
- 2. Mark `retired_at` on its `machines.json` entry and push the registry.
- 3. Re-pin its automations and runner tokens to a live Mac.
- 4. Rotate every secret the retired Mac could read (see
- `synthesis-fleet-secrets`), then wipe its `~/.synthesis/fleet/`
- identity. Retired identities never re-enroll; a returning Mac mints
- fresh.
+ `<rituals>` is the synthesis-daily-rituals folder.
- ## Workspace subscriptions
+ **Leave this Mac.**
- `~/.synthesis/fleet/subscriptions.json` maps each machine-id to the areas
- it may commit. The commit gate refuses unsubscribed staged paths, naming
- the machine and the needed subscription. Escape once per commit with an
- explicit reason, logged on the board:
+ 1. In each session that holds a project's claims: `synthesis handoff -m "<generic message>"`. It commits and pushes only the records inside that session's claims and refuses, with the list, when any is dirty or unpushed.
+ 2. Publish source work by explicit path under each repository's policy; fast-forward pushes only, no `--no-verify`, no force.
+ 3. `python3 <rituals>/scripts/repo_state.py --discover ~/workspaces --fetch`. Resolve or name every DIRTY, DECISION, BLIND or UNREACHABLE repository.
+ 4. If config changed, `brctl monitor --wait-uploaded -t 300 "$ICLOUD_BASE"` before writing the arrive note for the other Mac.
+ 5. `synthesis release`.
- ```bash
- coordination.py check-staged --repository . --json \
- --override-subscription 'hotfix outside subscribed areas'
- ```
+ **Arrive on a Mac.**
- No registry means subscriptions are unenrolled and the gate passes; a
- present registry with an unlisted machine, or paths outside every
- subscribed area, fails closed.
+ 1. `brctl download "$ICLOUD_BASE"` and poll until no `.icloud` placeholder remains; pull config (`synthesis-mac-sync`).
+ 2. `python3 <rituals>/scripts/repo_state.py --discover ~/workspaces --fetch --ff`: fast-forwards only clean branches that are strictly behind; lists uncommitted files and leaves them alone.
+ 3. `synthesis brief <project>`: the phase and next action from the records, with a warning when the knowledge checkout is behind its fetched upstream or a newer copy exists elsewhere. Resolve the warning before working.
+ 4. Board truth (`synthesis who`, `synthesis inbox`), then claim what this session will write: `synthesis claim <paths> --project <id> --goal "<goal>"`.
- ## Doctor
+ **A new Mac.**
- `coordination.py fleet-doctor` runs the whole gate: synced-path
- normalization, lease reachability, lease freshness, workset consistency,
- parked coherence, sealed-artifact verification, and the workset
- divergence scan. Any failure names its check and blocks with exit 1.
+ 1. `python3 <synthesis-onboarding>/scripts/setup.py`. It installs the plugin in each harness, the runtime, its hooks and the global git hooks, and clones the workspace repositories `repos.yaml` declares. Rerun it after any interruption; existing clones are fast-forwarded, and dirty or diverged ones are skipped and named.
+ 2. Pull the synced config and credentials with `synthesis-mac-sync`, then install the private layer.
+ 3. `synthesis doctor`; the first line must say healthy before the first commit.
+ 4. Add the Mac to the machine inventory (`scutil --get LocalHostName`) in the sync folder's config file.
- ## Engine map
+ **Retire a Mac.**
- | Engine | Owns |
- |---|---|
- | `fleet_identity.py` | Machine-id minting, registry enrollment |
- | `fleet_handoff.py` | Source gate, sealed offers, destination resume |
- | `fleet_doctor.py` | Reachability, freshness, coherence, divergence |
- | `fleet_subscriptions.py` | Workspace-subscription gate decisions |
- | `fleet_bootstrap.py` | Idempotent new-Mac provisioning |
- | `fleet_logical.py` | Repo-qualified overlap across checkout paths |
- | `fleet_paths.py` | `~`-normalization primitives and the paths gate |
+ 1. Hand off or release every claim the Mac holds (the leave steps above).
+ 2. Mark it retired in the machine inventory, with the date, and push or sync the change.
+ 3. Re-point its scheduled jobs, launch agents and runner tokens to a live Mac.
+ 4. Rotate every secret the retired Mac could read, then remove its local synthesis state.