AIOS · Fleet Storage · 2026-09-11

Drive Consolidation & Backup Plan

Five (possibly seven) external drives, one machine with no working backup, and a pile of old Time Machine archives holding photos that may exist nowhere else. This is the order of operations, the gates, and the exact commands — written for macOS 15.7.1 before any drive is connected.

Plan only — nothing inspected M2 has no working backup macOS 15.7.1 · build 24G231 Drive count unconfirmed

AWhere the fleet stands

Measured on 2026-09-11. These three numbers are the only verified storage facts in this document — everything about the external drives is unknown until Phase 0.

M2 · SeanVargas
81%
337 Gi used · 83 Gi free of 460 Gi
No working backup
Nano · nanobookpro
83%
744 Gi used · 163 Gi free of 926 Gi
2 TM destinations registered
Mini · insightfulmind
?
Unreachable over ssh — timed out twice
State unknown

The one urgent problem

M2's Time Machine destination Backup is registered, but tmutil latestbackup returns:

Error Domain=com.apple.backupd.ErrorDomain Code=18 "Failed to mount destination."

M2 currently has no backup at all. A registered destination that cannot mount looks like a backup in System Settings and is not one. Phase 6 Step 1 fixes this before any consolidation work begins — every hour spent sorting old drives first is an hour of uninsured exposure on 337 GiB.

Caveat, stated honestly: the drives were unplugged when this was measured, and Code 18 with the drive absent is expected. Re-test with the drive attached before concluding the hardware is bad.

M2's biggest consumers

PathSizeDisposition
~/AI_OS42GCanonical tree — back up. Move working sets and build artifacts only to scratch.
~/Pictures18GBack up. Never exclude.
~/Downloads9.7GBest single candidate to relocate to the scratch drive.
~/Library/Caches6.9GExclude from Time Machine. Regenerable.
~/Movies592MLeave alone.

No passwordless sudo on M2

sudo -n true fails. Every step marked [SUDO] must be typed by Sean in an interactive Terminal. An agent cannot run them. The affected commands are tmutil setdestination, tmutil removedestination, tmutil setquota, tmutil startbackup, mdutil, and every diskutil erase*.

Ruling — 2026-09-11, Sean

The two lanes claiming the 8TB are a no-go. cutroom/DaVinci and 8tb-drive (Mini-as-DAS) do not get the 8TB. Sean will allocate a 2TB drive to cover both of those instead.

Consequence: the 8TB is free for this plan. Phase 5 below stands as written — 8TB carries M2-TimeMachine + Archive. M2’s Time Machine is direct-attached, not network TM over SMB, so no overnight-first-backup penalty and no dependency on Mini being reachable.

Still to pin down when the drives are in front of you. Which 2TB goes to cutroom + Mini-DAS. Worth noting: DaVinci scratch is the most speed-sensitive workload in the whole set, and the Crucial X8 is the fast drive — so pointing the X8 at cutroom satisfies “repurpose the Crucial for fast working use” and “give cutroom a 2TB” with one move. That only works if a spare 2TB exists to take M2’s Time Machine, which is the drive-count question in Phase 0.

Prior context, now superseded but kept for the record: the 8TB had been scoped 2026-07-11 as Mini-as-DAS (/Volumes/AIOS-DAS/{delivery-assets, clone-staging, fleet-backups, archive}), carried by two task cards open 63 and 26 days. That design moves to the 2TB. Mini is currently unreachable over ssh, which no longer blocks anything in this plan.

BThe drives

None of these were connected while this plan was written. Nothing below the "known" column was measured.

Ambiguity that must be resolved first

Sean said "we have two two-terabyte drives," and separately named a 2TB Crucial X8 (M2's backup) and a 2TB drive that backs up Nano. It is not established whether those two ARE the pair, or whether two more 2TB drives exist beyond them. The drive count is unconfirmed.

This is not a detail. It decides whether M2's backup can live on different physical hardware than the archive. Phase 0 resolves it; Phase 5 branches on the answer.

#DriveKnownModel / interfaceHealthContentsProposed role
12TB Crucial X8 Fast. Currently M2's Time Machine target — the one that fails to mount. unknown — confirm in Phase 0 unknown — confirm in Phase 1 unknown — confirm in Phase 2 Fast scratch / working. Unregister from Time Machine.
22TB (Nano's) Nano's backup drive. unknown — confirm in Phase 0 unknown — confirm in Phase 1 Nano Time Machine KEEP AS IS — do not touch
38TB The big one. unknown — confirm in Phase 0 unknown — confirm in Phase 1 unknown — confirm in Phase 2 Archive + (Reading A) M2 Time Machine
4250GB Older / slower. Holds photos and old-device TM backups. unknown — confirm in Phase 0 unknown — confirm in Phase 1 unknown — confirm in Phase 2 Offsite mirror of the irreplaceable subset
5120GB Older / slower. Holds photos and old-device TM backups. unknown — confirm in Phase 0 unknown — confirm in Phase 1 unknown — confirm in Phase 2 Bootable macOS installer, or retire
6–7Possible spare 2TB ×2 Existence unconfirmed. If real, the architecture improves substantially — see Reading B. M2 Time Machine + archive mirror

Sean's stated intent

Backups belong on the slower drives; the fast Crucial gets freed for working use. But the slower drives currently hold photos and valuable data — "most of those are Time Machine backups of older devices." So the value has to come off before anything gets repurposed. That sequencing constraint is what makes Phases 3 and 4 the heart of this plan.


Read-only · always safe

0Inventory without touching anything

Goal: one table describing every drive, written without a single byte written to any of them. Resolve the drive count. Confirm Mini.

0.1

Grant Full Disk Access before anything else

System Settings → Privacy & Security → Full Disk Access → enable Terminalquit and reopen Terminal. The quit-and-reopen is mandatory; the entitlement is read at process launch. Without it tmutil returns empty backup lists and find silently skips protected directories — which makes every count in Phase 4 wrong in a way that is hard to diagnose.

0.2

Baseline with nothing plugged in

bash · M2read-only
mkdir -p /Users/SeanVargas/AI_OS/comms/outputs/2026-09-11-drive-consolidation/inventory
cd /Users/SeanVargas/AI_OS/comms/outputs/2026-09-11-drive-consolidation/inventory

diskutil list > 00-baseline-disklist.txt
cat 00-baseline-disklist.txt

/dev/disk0 is M2's internal SSD (500.3 GB, GUID partition scheme); disk1 and disk3 are its APFS containers. Anything appearing later marked (external, physical) is one of your drives.

0.3

One drive at a time. Always.

bash · M2read-only
diskutil list external physical

Read the IDENTIFIER column carefully. disk4 is a whole drive; disk4s2 is a volume on it. Erase commands aimed at the wrong one destroy the wrong thing. Plugging in two drives at once is the single most common way people erase the drive they meant to keep.

0.4

Capture everything about that drive

bash · M2 — substitute the identifierread-only
DRIVE=disk4   # <-- substitute

diskutil info -all                  > 01-${DRIVE}-info-all.txt
diskutil info /dev/${DRIVE}  | tee    02-${DRIVE}-whole.txt
diskutil list /dev/${DRIVE}  | tee    03-${DRIVE}-layout.txt
system_profiler SPUSBDataType       > 04-usb.txt
system_profiler SPThunderboltDataType > 05-thunderbolt.txt

SPUSBDataType gives the enclosure's real product name and the negotiated link speed (Up to 10 Gb/s vs Up to 480 Mb/s). That negotiated speed is how you tell fast from slow as currently cabled — a 10 Gb/s NVMe drive on a USB-2 cable reports 480 Mb/s and behaves like a slow drive. Try a different cable and port before concluding a drive is slow.

0.5

Telling the filesystems apart

FilesystemHow it looks in diskutil listWhere real free space lives
APFSApple_APFS Container diskN plus a nested APFS Container Scheme block with volumes sharing one poolContainer Free Spacenot the per-volume number, which can read as the whole pool on every volume at once
HFS+TYPE column reads Apple_HFS; File System Personality: Journaled HFS+Volume Free Space / Volume Used Space
exFATTYPE reads Microsoft Basic Data; File System Personality: ExFATVolume Free Space

exFAT cannot hold a Time Machine backup

No permissions, no hard links, no resource forks. It also mangles macOS metadata on copy. If an old drive is exFAT, treat its contents as already metadata-degraded and plan to move them onto APFS.

bash · reading real free spaceread-only
# APFS — the container pool is the truth
diskutil info /dev/disk4s2 | grep -E "Container Total Space|Container Free Space"
diskutil apfs list | sed -n '/disk4/,/^$/p'

# HFS+ / exFAT — the volume numbers are the truth
diskutil info /dev/disk4s2 | grep -E "Volume Total Space|Volume Free Space|Volume Used Space"

# Cross-check anything mounted
df -h | grep -v "^map"
0.6

Mount read-only where you can

For any drive that is old, suspect, or precious, mount it read-only so macOS cannot write journal replays, Spotlight indexes, or .DS_Store files onto it.

bash · verified syntax on macOS 15.7.1read-only
diskutil unmount /dev/disk4s2
diskutil mount readOnly nobrowse -mountPoint /Volumes/RO_disk4s2 /dev/disk4s2

# confirm it actually took
diskutil info /dev/disk4s2 | grep -E "Volume Read-Only|Media Read-Only"
# want: Volume Read-Only: Yes

A read-only mount is a software guard, not a hardware one. It stops accidents, not a determined sudo.

0.7

Stop Spotlight from grinding the old drives

bash · M2[SUDO]
sudo mdutil -i off /Volumes/<DRIVE>
# -X removes the existing index store, which WRITES to the drive.
# Skip -X entirely on any read-only or suspect drive.
sudo mdutil -X /Volumes/<DRIVE>

Indexing a large old drive is hours of sustained random reads on hardware you are trying to be gentle with.

0.8

Check Mini, and record M2's current TM registration

bashread-only
tailscale status | grep -i mini
ping -c 3 100.72.22.100
ssh -o ConnectTimeout=8 seanvargas@100.72.22.100 'hostname; df -h /; tmutil destinationinfo'

# M2's own registered destinations, and their UUIDs (needed in Phase 6)
tmutil destinationinfo
tmutil destinationinfo -X

If Mini does not answer, write "Mini: unreachable as of 2026-09-11, state unknown" into the inventory and proceed. Mini is not on M2's critical path, but you cannot claim a fleet-wide backup posture without it.

0.9

Label the drives physically

Tape and a marker. Every later phase refers to drives by number. Confusing drive 1 with drive 2 during Phase 6 is how people erase a backup they meant to keep.

Verify Phase 0

STOP IF


Read-only · always safe

1Drive health first

Goal: know which drives can be trusted with a write workload, and which get exactly one careful read. These are old drives. Some of them may be failing right now.

1.1

SMART status — and why "Not Supported" is fine

bashread-only
diskutil info /dev/disk4 | grep "SMART Status"
ValueMeaningAction
VerifiedDrive reports itself healthyProceed — but SMART misses a large fraction of real failures, so this is not a guarantee
Not SupportedThe USB enclosure does not pass SMART through. Most bridge chips (JMicron, ASMedia, Realtek) do not relay it.Normal. Not alarming. You simply have no SMART data — judge the drive by behavior instead.
FailingThe drive is telling you it is dyingRescue-read only. Never write. Never reformat. Copy off now and retire it.

Optional deeper look, if you want it: brew install smartmontools then smartctl -d sat -a /dev/disk4 — the -d sat flag often gets through a bridge that diskutil cannot. If smartctl also fails, that confirms the enclosure blocks SMART. Move on.

1.2

Filesystem verification — verify, do not repair

bash · verifyVolume is read-onlyread-only
diskutil verifyVolume /dev/disk4s2
diskutil verifyDisk   /dev/disk4      # APFS container level

Do not run repairVolume on a suspect drive yet

repairVolume writes to the disk. On a dying drive the repair pass can be the thing that kills it. Correct order: verify → if errors, copy the data off first → only then consider repair.

1.3

Behavioral health — more useful than SMART on USB

bash · leave running in a second tab while copyingread-only
log stream --predicate 'eventMessage CONTAINS "I/O error" OR eventMessage CONTAINS "disk4"' --style compact

Red flags: repeated I/O error or media-error messages · clicking or a spin-up/spin-down cycle every few seconds · transfer rate collapsing from tens of MB/s to single-digit KB/s and staying there · the volume unmounting itself mid-copy.

bash · optional sequential-read sanity checkread the warning
dd if=/dev/rdisk4 of=/dev/null bs=1m count=2000 status=progress

Triple-check of=/dev/null

A dd with of= pointed at a disk is the single most destructive typo available on this system. If you are at all unsure, skip this step — it is optional.

Reference throughput: healthy spinning USB drive 60–140 MB/s · SATA SSD over USB 3 350–450 MB/s · NVMe over 10 Gb/s USB 700–1000 MB/s. Anything sustained under ~20 MB/s on a modern drive means a USB-2 link or a sick drive.

The rule for this entire playbook

A suspect drive gets read ONCE, carefully, copying off. It never gets a long write workload.

Why, concretely: reformatting a drive and writing 400 GB to it is hours of sustained writes — the heaviest possible load applied to hardware you already distrust. If it dies at hour three you lose the drive and whatever you were writing. If that write was the consolidated archive, you lose the consolidation too. Corollary: a drive that survived a rescue read is not thereby proven healthy. Old drives that held your only copy of something are retirement candidates, not backup candidates.

Verify Phase 1

Every drive carries a trust level: TRUST (safe for a write workload) / READ-ONCE (rescue only) / RETIRE. At least one TRUST drive is large enough to receive everything — Phase 5 depends on it.

STOP IF


Read-only · always safe

2Classify what is on each drive

Goal: a written classification per drive into four buckets. Still no copying.

BucketWhat it isDisposition
(a) TM backups of old devicesMachines you no longer runHigh value, high extraction difficulty → Phase 3
(b) Loose archivesPhotos, video, documents, .photoslibrary bundles, project foldersCopy + dedup → Phase 3
(c) Regenerable junk.dmg/.pkg, OS installers, node_modules, cachesDiscard — but list it before discarding
(d) UnknownAnything you cannot classify in 30 secondsTreat as (b). Unknown is not "junk."

du lies on APFS — use it for shape only, never for proof

du under-reports when files are clones (clonefile — Finder duplicate, cp -c, many installers), because shared blocks get charged to one path or to none. It over-reports apparent size on sparse files. Hard links inside Time Machine backups break it in the other direction.

This exact trap cost real time on this fleet: 18 Chrome clone directories showed as 24.8 GiB in du, and deleting one released 18 MiB. Use du -h -d 2 to eyeball a drive's shape. Never use it to prove a copy is complete — that is Phase 4.

Finding Time Machine backups — three formats, three commands

bash · HFS+ directory formread-only
DRV="/Volumes/<DRIVE>"   # <-- substitute

ls -la "$DRV/Backups.backupdb/"
ls -la "$DRV/Backups.backupdb/"*/
# structure: Backups.backupdb/<Machine>/<YYYY-MM-DD-HHMMSS>/<Volume>/...
# dated dirs share storage via hard links — apparent sizes will far exceed
# the drive's capacity. That is normal.
bash · sparsebundle formread-only
ls -la "$DRV"/*.sparsebundle
find "$DRV" -maxdepth 3 \( -name "*.sparsebundle" -o -name "*.backupbundle" \)

# A .sparsebundle is a DIRECTORY that looks like a file in Finder.
# Inside: bands/ (thousands of numbered chunks), Info.plist, token.
# Never copy bands individually. Mount it — see Phase 3.
bash · APFS snapshot form (Big Sur and later)needs Full Disk Access
diskutil apfs list /dev/disk4
# look for a volume whose role includes Backup

tmutil listbackups -d "$DRV"
diskutil apfs listSnapshots /dev/disk4s1
# APFS TM backups are snapshots on a dedicated volume — not folders
# you can browse with ls. tmutil or the Time Machine UI only.
bash · whose backup is this?read-only
ls "$DRV/Backups.backupdb/"                     # HFS+: dir name = machine name
plutil -p "$DRV"/*.sparsebundle/com.apple.TimeMachine.MachineID.plist
tmutil listbackups -d "$DRV" | head

Find Photos libraries before touching anything

bashread-only
find "$DRV" -maxdepth 4 -name "*.photoslibrary"        -print
find "$DRV" -maxdepth 4 -name "*.photolibrary"         -print   # iPhoto
find "$DRV" -maxdepth 4 -name "*.aplibrary"            -print   # Aperture
find "$DRV" -maxdepth 4 -name "*.migratedphotolibrary" -print

Anything found here follows the Phase 3 Photos rules. Do not enter these bundles.

Count the loose material

bashread-only
# stills + RAW
find "$DRV" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.heic" \
  -o -iname "*.png" -o -iname "*.dng" -o -iname "*.cr2" -o -iname "*.nef" \
  -o -iname "*.arw" \) | wc -l

# video
find "$DRV" -type f \( -iname "*.mov" -o -iname "*.mp4" -o -iname "*.m4v" \
  -o -iname "*.avi" -o -iname "*.mts" \) | wc -l

# documents
find "$DRV" -type f \( -iname "*.pdf" -o -iname "*.doc*" -o -iname "*.xls*" \
  -o -iname "*.pages" -o -iname "*.numbers" -o -iname "*.key" \) | wc -l

# the biggest individual files — usually where the surprises are
find "$DRV" -type f -size +500M -exec ls -lh {} \; | awk '{print $5, $9}' | sort -hr | head -40

Triage rule: if re-acquiring it costs under ten minutes and zero dollars, it is bucket (c). If you would have to email someone to get it back, it is bucket (b).

Verify Phase 2

A CONTENTS-drive-<N>.md exists per drive. Every top-level directory on every drive is assigned to a bucket. Bucket (d) is written down explicitly rather than silently ignored.

STOP IF


Highest risk · highest value

3Extract value from old Time Machine backups

This is where the irreplaceable data comes off. Every operation here is a READ from the old drive and a WRITE to the 8TB staging area. Nothing writes back to a source.

3.0

Staging tree on the 8TB

bashwrites to 8TB only
STAGE="/Volumes/<8TB>/_STAGING"      # <-- substitute
mkdir -p "$STAGE"/{tm-extract,loose,photoslibs,manifests,quarantine}
tm-extract/
one folder per old machine pulled from a TM backup
loose/
one folder per source drive — keeps provenance
photoslibs/
whole .photoslibrary bundles, copied intact
manifests/
hash manifests and counts — this is your Phase 4 evidence
quarantine/
anything unclassified. Keep it; sort later.

Keeping source-drive provenance in the folder names is what makes dedup and verification tractable. Do not merge everything flat yet.

3.1

Finder route — try this first, lowest risk

  1. Connect the drive; let it mount normally.
  2. Hold Option and click the Time Machine icon in the menu bar.
  3. Choose "Browse Other Backup Disks…"
  4. Pick drive → machine → date.
  5. Drag what you want out to $STAGE/tm-extract/<machine>/.

No Time Machine menu-bar icon? System Settings → Control Center → Time Machine → Show in Menu Bar, or open /System/Applications/Time Machine.app directly.

When this route works, use it. Slower to click through, but it restores metadata, permissions, and resource forks correctly and it cannot corrupt the source.

3.2

tmutil route — for bulk extraction

bash · needs Full Disk Accessread-only on source
DRV="/Volumes/<DRIVE>"

tmutil listbackups -d "$DRV"
tmutil listbackups -d "$DRV" -t      # terse timestamps
tmutil latestbackup  -d "$DRV"

BK="/Volumes/<DRIVE>/Backups.backupdb/<Machine>/2021-06-14-093211"
ls -la "$BK"
ls -la "$BK"/*/Users/
bash · metadata-correct extractionwrites to 8TB only
# preferred: preserves ACLs, xattrs, Finder metadata
tmutil restore -v "$BK/Macintosh HD - Data/Users/<olduser>/Pictures" \
                  "$STAGE/tm-extract/<machine>/Pictures"

# fallback when tmutil restore refuses (common across machines/users)
ditto "$BK/Macintosh HD - Data/Users/<olduser>/Pictures" \
      "$STAGE/tm-extract/<machine>/Pictures"

Use ditto, not rsync, on this machine

Verified on M2: /usr/bin/rsync is openrsync (protocol version 29 / rsync 2.6.9 compatible), and no Homebrew rsync is installed (/opt/homebrew/bin/rsync does not exist). openrsync does not reliably honor -H (hard links), -A (ACLs), or -X (xattrs) — exactly the flags a Time Machine extraction needs. Use ditto for local drive-to-drive copies, or brew install rsync first. Do not assume rsync -aHAX behaves the way it does on Linux here.

3.3

Mounting a .sparsebundle by hand

bash · -readonly verified present in hdiutil attachread-only
hdiutil attach -readonly "/Volumes/<DRIVE>/<name>.sparsebundle"
# mounts under /Volumes/<BundleVolumeName>, usually "Time Machine Backups"

ls -la "/Volumes/Time Machine Backups/Backups.backupdb/"
tmutil listbackups -d "/Volumes/Time Machine Backups"

hdiutil detach "/Volumes/Time Machine Backups"

Use -readonly every time — it means a mistake inside the mounted backup cannot damage the backup. If detach says busy, close Finder windows and any Terminal whose working directory is inside it; -force is a last resort.

If the bundle refuses to attach, copy the whole .sparsebundle directory to the 8TB with ditto first, then run any repair attempt against the copy. Never against the original.

3.4

Encrypted backups — confirm the password early

bashread-only
diskutil info /dev/disk4s2 | grep -E "FileVault|Encrypted|Unlocked"
hdiutil attach -readonly "/Volumes/<DRIVE>/<name>.sparsebundle"   # will prompt
security find-generic-password -s "<sparsebundle name>" 2>&1 | head -5

Also check Keychain Access.app → search the drive or backup name → look for a Time Machine or disk-image password entry.

STOP IF you cannot unlock an encrypted backup

Do not plan any drive reuse that assumes you will get that data back. There are exactly three honest options: keep hunting for the password, keep the drive as-is indefinitely and never reformat it, or consciously write the data off. Reformatting an encrypted backup you never unlocked is permanent, silent data loss.

3.5

Photos Libraries — the rule that saves your photos

Never copy individual files out of a .photoslibrary bundle

It is not a folder of pictures. It is a SQLite database (database/Photos.sqlite) plus originals/ (content-hashed, meaningless filenames) plus resources/derivatives/ (generated display-resolution JPEGs) plus non-destructive adjustment records.

What you lose by copying files out of the bundle:

  • You get derivative JPEGs instead of originals — lower quality, stripped of edit history.
  • Albums, favorites, faces, keywords, captions, memories, shared-album membership all live in the database. All lost.
  • Live Photos split into an orphan still and an orphan video.
  • Edits are database records, so an "edited" photo copies out as the unedited original — or as a flattened derivative. You will not know which.
  • Filenames under originals/ are UUID-derived. The result is unusable as an archive.

Method 1 — copy the whole bundle (archival)

bashwrites to 8TB only
ditto "/Volumes/<DRIVE>/Pictures/Photos Library.photoslibrary" \
      "$STAGE/photoslibs/<drive-N>-Photos Library.photoslibrary"

ditto treats the bundle as the opaque unit it is. The library stays openable in Photos.app — that is what makes it a real archive rather than a pile of JPEGs.

Method 2 — export originals (for merging and dedup)

  1. Hold Option while launching Photos.app → Choose Library → pick the copy on the 8TB, not the original.
  2. Cmd-A to select all.
  3. File → Export → Export Unmodified Originals for N Photos…
  4. Enable Export IPTC as XMP so keywords and captions survive as sidecars.
  5. Export into $STAGE/loose/<drive-N>-photos-export/.

Use Export Unmodified Originals, not plain Export. Plain Export writes rendered JPEGs with edits baked in and metadata partially stripped.

Do both when the library matters

Keep the bundle (Method 1) as the authoritative archive and produce an export (Method 2) as the thing you dedup and browse. Disk is cheap on an 8TB; a lost photo library is not recoverable.

Check before you count a library as rescued

If the old library was iCloud-optimized (Download Originals to this Mac was OFF), the local bundle may hold only low-res placeholders. Confirm before you treat it as a copy of anything.

3.6

Deduplication — by content hash, never by filename

Why filenames are useless here

Every iPhone produces IMG_0001.JPG through IMG_9999.JPG and then wraps around. Two completely different photos from two different phones routinely share a filename, and the same photo copied through three devices routinely has three different names. Filename dedup gives you both false positives (deleting a unique photo) and false negatives (keeping five copies).

bash · step 1 — hash manifest of the whole staging treeread-only
cd "$STAGE"
find "$STAGE/tm-extract" "$STAGE/loose" -type f -size +1k \
  -not -name ".DS_Store" -not -path "*/.Spotlight-V100/*" -print0 \
  | xargs -0 shasum -a 256 > "$STAGE/manifests/stage-$(date +%Y%m%d).sha256"

wc -l "$STAGE/manifests/stage-$(date +%Y%m%d).sha256"
bash · step 2 — find duplicate hashes and their real costread-only
M="$STAGE/manifests/stage-$(date +%Y%m%d).sha256"

awk '{print $1}' "$M" | sort | uniq -d > "$STAGE/manifests/dupe-hashes.txt"
wc -l "$STAGE/manifests/dupe-hashes.txt"

# logical bytes across all copies — stat, NOT du
grep -F -f "$STAGE/manifests/dupe-hashes.txt" "$M" \
  | sed 's/^[a-f0-9]*  //' \
  | while IFS= read -r f; do stat -f '%z' "$f"; done \
  | awk '{s+=$1} END {printf "%.2f GiB across all copies\n", s/1024/1024/1024}'
bash · step 3 — review groups, then MOVE (never rm)review by eye
sort "$M" > "$STAGE/manifests/stage-sorted.sha256"
awk 'NR==FNR{d[$1];next} ($1 in d)' \
    "$STAGE/manifests/dupe-hashes.txt" "$STAGE/manifests/stage-sorted.sha256" \
    > "$STAGE/manifests/dupe-groups.txt"
head -60 "$STAGE/manifests/dupe-groups.txt"

mkdir -p "$STAGE/_dupes-pending-delete"
mv "/path/to/redundant/copy.jpg" "$STAGE/_dupes-pending-delete/"

Each group of lines sharing a hash is a set of byte-identical files. Keep the copy with the most informative path — usually tm-extract/<machine>/…/Pictures/…, not quarantine/. Move, do not rm. Delete the holding folder only after Phase 4 passes and you have lived with the result for a week.

What hash dedup will NOT catch

The same photo re-encoded, resized, or re-exported has different bytes and the same picture. That is perceptual dedup — a harder, human-in-the-loop problem. Do not try to solve it during the migration. Byte-identical dedup is safe and mechanical; run anything beyond it against the consolidated archive later, once it is safely in place.

Verify Phase 3

Every processed drive has a corresponding tree under $STAGE · copy-failures.txt is empty or every entry is accounted for · every .photoslibrary found in Phase 2 exists as a whole bundle under photoslibs/ · a hash manifest exists.

STOP IF


THE GATE · no shortcuts

4Verify before you erase

STOP GATEA reformatted drive has no undo

There is no Trash, no snapshot, and no diskutil unerase. Data-recovery services exist, cost four figures, and usually fail on SSDs because TRIM has already zeroed the blocks.

Nothing gets reformatted until every check on this page reads PASS.

The three things that DO constitute proof

File count · total logical bytes (stat -f '%z', the file's real size independent of allocation) · content hashes on a random sample. du is not on this list and never will be — see the APFS clone/sparse trap in Phase 2.

4.1  File count match

bashread-only
SRC="/Volumes/<DRIVE>/<folder>"
DST="$STAGE/loose/<drive-N>/<folder>"

SRC_N=$(find "$SRC" -type f -not -name ".DS_Store" | wc -l | tr -d ' ')
DST_N=$(find "$DST" -type f -not -name ".DS_Store" | wc -l | tr -d ' ')
echo "SRC files: $SRC_N / DST files: $DST_N"
[ "$SRC_N" = "$DST_N" ] && echo "COUNT: PASS" || echo "COUNT: FAIL"

# also dirs (catches empty dirs ditto created but never filled)
echo "dirs  SRC=$(find "$SRC" -type d | wc -l) DST=$(find "$DST" -type d | wc -l)"
# also symlinks (a bad copy silently dereferences or drops them)
echo "links SRC=$(find "$SRC" -type l | wc -l) DST=$(find "$DST" -type l | wc -l)"

4.2  Total logical byte match

bash · stat -f '%z' is immune to clones and sparse filesread-only
bytes_of() {
  find "$1" -type f -not -name ".DS_Store" -print0 \
    | xargs -0 stat -f '%z' \
    | awk '{s+=$1} END {printf "%d\n", s}'
}

SRC_B=$(bytes_of "$SRC"); DST_B=$(bytes_of "$DST")
echo "SRC bytes: $SRC_B / DST bytes: $DST_B"
[ "$SRC_B" = "$DST_B" ] && echo "BYTES: PASS" || echo "BYTES: FAIL — diff $((SRC_B - DST_B))"

4.3  Content hash spot check

Count and bytes can both match while content is corrupt — a truncated-then-padded file, a bit-flip from a dying drive. Hashes are the only thing that catches that.

bash · raise N to 300+ for anything irreplaceableread-only
N=100

cd "$SRC"
find . -type f -not -name ".DS_Store" | sort -R | head -$N > /tmp/sample-list.txt

( cd "$SRC" && tr '\n' '\0' < /tmp/sample-list.txt | xargs -0 shasum -a 256 ) \
  | sort > "$STAGE/manifests/verify-src.sha256"
( cd "$DST" && tr '\n' '\0' < /tmp/sample-list.txt | xargs -0 shasum -a 256 ) \
  | sort > "$STAGE/manifests/verify-dst.sha256"

# FAIL CLOSED. Check the hashing actually RAN before trusting the diff:
# if both manifests are empty, `diff` succeeds and you get a false PASS.
SAMPLE_N=$(wc -l < /tmp/sample-list.txt | tr -d ' ')
SRC_H=$(wc -l < "$STAGE/manifests/verify-src.sha256" | tr -d ' ')
DST_H=$(wc -l < "$STAGE/manifests/verify-dst.sha256" | tr -d ' ')
echo "expected $SAMPLE_N | src $SRC_H | dst $DST_H"

if [ "$SAMPLE_N" -eq 0 ] || [ "$SRC_H" -ne "$SAMPLE_N" ] || [ "$DST_H" -ne "$SAMPLE_N" ]; then
  echo "HASH SAMPLE: INVALID - hashing did not run correctly. NOT a pass. Do not erase."
elif diff -q "$STAGE/manifests/verify-src.sha256" "$STAGE/manifests/verify-dst.sha256" >/dev/null; then
  echo "HASH SAMPLE: PASS ($SAMPLE_N/$SAMPLE_N matched)"
else
  echo "HASH SAMPLE: FAIL - content differs. Do not erase anything."
fi
bash · for truly irreplaceable trees, hash everythingread-only
( cd "$SRC" && find . -type f -not -name ".DS_Store" -print0 | xargs -0 shasum -a 256 ) | sort > full-src.sha256
( cd "$DST" && find . -type f -not -name ".DS_Store" -print0 | xargs -0 shasum -a 256 ) | sort > full-dst.sha256
[ -s full-src.sha256 ] && [ -s full-dst.sha256 ] && diff -q full-src.sha256 full-dst.sha256 >/dev/null \
  && echo "FULL HASH: PASS" || echo "FULL HASH: NOT VERIFIED - empty manifest or mismatch. Do not erase."

4.4  Photos libraries verify differently

You cannot meaningfully hash-compare the inside of a live library mid-flight, and you should not try. Verify it the way it will actually be used:

  1. ditto the bundle to the 8TB.
  2. Run 4.1 and 4.2 across the bundle — bundles are just directories to find.
  3. Open the copy in Photos.app (Option-launch → Choose Library → the copy).
  4. Confirm: photo count matches, albums present, edited photos still show edits, Live Photos still play.
  5. Only then treat the source as expendable.

Step 3 is the real test. A byte-perfect copy of a corrupt library is a corrupt library.

4.5  The gate file

$STAGE/manifests/GATE-drive-<N>.mdevidence
Drive:        <N> / <volume name> / <model>
Source path:  /Volumes/.../...
Dest path:    /Volumes/<8TB>/_STAGING/...
Files:        SRC=<n>  DST=<n>   PASS/FAIL
Dirs:         SRC=<n>  DST=<n>   PASS/FAIL
Bytes:        SRC=<n>  DST=<n>   PASS/FAIL
Hash sample:  <n> files, diff clean?  PASS/FAIL
Photos libs:  opened in Photos.app and verified?  YES/NO/NA
Verified on:  <date>
STOP IFany of these → DO NOT ERASE
  • Any COUNT, BYTES, or HASH check reads FAIL.
  • A Photos library will not open from the copy.
  • An encrypted backup on that drive was never unlocked.
  • Bucket (d) "unknown" content on that drive was never classified.
  • The 8TB has not passed Phase 1 health checks.
  • You are tired, it is late, or you are in a hurry. Erase commands are the one category where the failure mode is unrecoverable. Do them rested, in daylight, one drive at a time, reading the device identifier out loud.

Decision · needs the drive count

5Target architecture

The arithmetic, first

Time Machine needs 1.5× to 2× the source size to hold a useful history. At 1× it can hold one snapshot and then immediately starts deleting old backups. Below 1× it cannot complete a first backup at all. Time Machine does not compress. M2's source data is 337 GiB.

DriveMarketingReal usableHolds 337 GiB once?Viable M2 TM target? (needs ≥ ~505 GiB)
8TB8 TB~7.28 TiBYesYes — 21× headroom
2TB Crucial X82 TB~1.82 TiBYesYes technically (5.5×) — but Sean wants it freed
2TB (Nano's)2 TB~1.82 TiBYesOff limits — Nano's
250GB250 GB~232 GiBNONO — smaller than M2's used data
120GB120 GB~111 GiBNONO — one third of M2's used data

Said plainly

A 250GB drive cannot hold a 337 GiB Time Machine backup. Not compressed, not thinned, not ever. The same is more true of the 120GB. No amount of exclusions makes these backup targets — you would have to exclude ~/AI_OS (42G) and ~/Pictures (18G) and more, which means the "backup" excludes the things you most need backed up.

What they are good for: 250GB → second copy of the irreplaceable subset (photos + documents core, very likely under 232 GiB after dedup), or a single-project scratch disk. 120GB → bootable macOS 15 installer (~16 GB, genuinely useful when a Mac will not boot), sneakernet disk, or retirement. If the 120GB is an old spinner with unknown SMART, retire it — keeping marginal old drives around creates a temptation to trust them.

Current state → end state

today unchanged new role conditional risk concentration

Reading A — 5 drives total (Crucial + Nano's ARE the two 2TB drives)

Drive 1 · now
2TB Crucial X8
M2 Time Machine target — and the destination that currently fails to mount. Fast hardware doing slow-drive work.
Drive 1 · end state
FAST SCRATCH
Offloaded ~/Downloads + AI_OS working sets, video scratch, VM images. Unregistered from Time Machine. Nothing on it is the only copy of anything.
Drive 2 · now
2TB — Nano's backup
Nano Time Machine. 744 Gi source into ~1.82 TiB — healthy headroom.
Drive 2 · end state
UNCHANGED
Stays Nano's backup. Do not touch, do not reformat, do not borrow.
Drive 3 · now
8TB
Contents unknown — confirm in Phase 0.
Drive 3 · end state
ARCHIVE + M2 TIME MACHINE
Two APFS volumes in one container: M2-TimeMachine and Archive. Single point of failure — see below.
Drive 4 · now
250GB
Old-device TM backups + loose photos. Value must come off first.
Drive 4 · end state
OFFSITE MIRROR
Photos + documents core copied from Archive, verified, then stored somewhere other than the desk the 8TB sits on. This is your "1 offsite" and it costs nothing.
Drive 5 · now
120GB
Old-device TM backups + loose photos.
Drive 5 · end state
BOOT INSTALLER — OR RETIRE
Bootable macOS 15 installer (~16 GB). If it is an old spinner with unknown SMART, retire it instead.

Reading B — 7 drives total (two spare 2TB drives exist)

Drive 3 · 8TB
was: archive + backup
Under Reading A it had to carry both.
Drive 3 · end state
ARCHIVE ONLY
Single Archive volume. No backup duty. Risk unbundled.
Drive 6 · spare 2TB
unconfirmed
Existence must be established in Phase 0.
Drive 6 · end state
M2 TIME MACHINE
337 GiB into ~1.82 TiB — 5.5× headroom, on different physical hardware than the archive. This is the outcome to hope for.
Drive 7 · spare 2TB
unconfirmed
Existence must be established in Phase 0.
Drive 7 · end state
ARCHIVE MIRROR
Second copy of the archive up to 1.82 TiB — or Mini's backup once Mini is reachable again.

Reading B is materially better

It is the difference between "my backup and my archive are on the same device" and "they are not." That is why the Phase 0 drive count is not bookkeeping.

Why scratch and Time Machine must never share a drive

#ReasonConsequence
1Time Machine consumes all free space by design.It fills the destination, then thins old backups. Your scratch capacity shrinks to zero, then TM starts deleting backup history to make room for scratch files.
2Time Machine wants an exclusive APFS volume.On macOS 15 it claims the volume with a Backup role and manages snapshots on it. Sharing with active scratch I/O is unsupported territory.
3Contention.A backup is thousands of small writes plus snapshot bookkeeping. Running a video export against the same device makes both slow and can drop the volume on a USB bridge.
4Blast radius.Scratch drives get erased casually — that is the point. The moment scratch is also your backup, "just wipe the scratch drive" becomes a data-loss event.

3-2-1, and the single point of failure

The standard is 3 copies, 2 different media, 1 offsite. Under Reading A the proposed end state gives you:

DataCopy 1Copy 2Copy 3Offsite?
M2 live system (337 GiB)M2 internal SSD8TB M2-TimeMachineNo
Consolidated archive8TB Archive250GB (irreplaceable subset)Only if you physically carry the 250GB elsewhere
THE RISKname it, do not hedge it

Under Reading A, the 8TB holds both M2's only backup and the only full copy of the consolidated archive. If that one drive dies, you lose your backup and your archive in the same instant.

Two APFS volumes on one container do not help. They share a container, a partition table, a controller, an enclosure, a cable, and a power supply. That is not a backup architecture — it is one drive with two names on it.

It is still strictly better than today, because today M2 has zero working backups. Take the improvement, then close the gap.

Closing the gap, in priority order, with hardware on hand

1

Immediately: copy the irreplaceable subset (photos + documents after dedup) to the 250GB, verify with Phase 4, and store it somewhere other than the desk the 8TB sits on. That is your "1 offsite" and it costs nothing.

2

Resolve the drive count. If Reading B is true, move M2's Time Machine to a spare 2TB and the single point of failure disappears entirely.

3

Cloud for the irreplaceable subset. The archive core is the part that cannot be rebuilt. Object storage for the photos+documents core is the only true offsite that survives a house fire. This is the one place where spending money is the right answer, and it is a small amount for the risk actually retired.

4

If Reading A holds and you can spend: a second 8TB as an archive mirror is the clean fix. Rotate it offsite.

5

Fleet-internal partial mitigation: Nano has 163 GiB free; Mini is unknown. Neither can hold the full archive. Do not pretend fleet copies substitute for a real second device — but a copy of the documents portion on Nano costs nothing and beats not having it.

Do not let the perfect block the good

Get M2 backed up to the 8TB today. Then work down that list.

Scratch drive layout (Crucial X8)

/Volumes/Scratch — APFS, not encrypted, not case-sensitiveafter Phase 8
/Volumes/Scratch/
  aios-working/    # offloaded ~/AI_OS working sets — NOT the canonical tree
  downloads/       # relocated ~/Downloads (9.7G today)
  media-scratch/   # video / render intermediates
  vm/              # VM images, container storage
  _EPHEMERAL.txt   # "Everything here is disposable.
                   #  If it matters, it does not live here."

Write that rule into _EPHEMERAL.txt on the drive itself so future-you finds it. Moving ~/Downloads and AI_OS build artifacts is the fastest relief for M2's 81%. Be careful with ~/AI_OS — per fleet convention it is the canonical tree, so move working sets and artifacts, not the tree. Add the scratch volume to Time Machine's exclusions so you are not backing up disposable data.

STOP IF


Contains the only destructive step

6Execution order

Dependency-ordered. Every step ends at a safe resting state — you can stop after any of them and be no worse off than when you started.

1

Emergency — give M2 a working backup. Do this FIRST.

Precondition: 8TB exists, passed Phase 1, and Phase 2 says it is empty or holds only already-classified material.

Why first: every hour spent on consolidation before this is an hour of uninsured exposure on 337 GiB. If M2's SSD dies tonight, all of it goes.

bash · addVolume is ADDITIVE — it does not erase the container[SUDO] on steps 2-3
# 1. confirm the identifier — only this drive connected
diskutil list external physical

# 2. create a dedicated TM volume inside the existing APFS container
diskutil apfs addVolume /dev/disk<N> APFS "M2-TimeMachine"

# 3. register it, APPENDING (-a) rather than replacing
sudo tmutil setdestination -a /Volumes/M2-TimeMachine
tmutil destinationinfo

# 4. first backup, blocking so you can watch it succeed
sudo tmutil startbackup --block --destination <destination-id>

# 5. prove it
tmutil latestbackup

If the 8TB already holds data you have not extracted, skip to Step 2 and come back. Do not erase it. If the 8TB is not APFS and must be converted, that is destructive — read the gate below.

Safe resting state after Step 1

M2 has a real, verified backup. This alone justifies the whole exercise. You can stop here for a week.

STOP GATEbefore ANY diskutil erase* on the 8TB

Proceed only if all are true:

  • diskutil list /dev/disk<N> output is on screen and you have read the identifier out loud
  • Phase 2 classification exists for this drive
  • Phase 4 gate file reads PASS for everything on it — or the drive is confirmed empty
  • Only ONE external drive is connected right now
  • You are not tired and not rushing
reference only — do not run until every box is checkedDESTRUCTIVE
# ERASES THE ENTIRE DRIVE. NO UNDO.
# diskutil eraseDisk APFS "Archive" GPT /dev/disk<N>

Prefer diskutil apfs addVolume (non-destructive) over eraseDisk whenever the drive is already APFS.

2

Inventory and health, every drive  (Phases 0 + 1)

Precondition: none — read-only, always safe. Output: complete drive table, count resolved, trust levels assigned, Mini's status recorded. Resting state: you know what you have; nothing changed.

3

Classify  (Phase 2)

Order: process the most suspect drive first. A dying drive's data is the most time-sensitive thing you own; healthy drives will wait, failing ones will not. Resting state: you know what is on each drive; nothing changed.

4

Extract, drive by drive  (Phase 3)

Precondition: Steps 1–3 done; $STAGE has ≥ 2× the source drive's used space free. Per drive: mount read-only → extract → hash manifest → erase nothing.

Rollback: the source is untouched behind a read-only mount. Delete the staging folder and start over — zero risk to the source. Resting state: that drive's data exists in two places.

5

Verify each extraction  (Phase 4)

Output: GATE-drive-<N>.md reading PASS on every line. Rollback: re-extract; source is still intact. Resting state: extraction is proven — and this is the last point at which everything is still recoverable from the original drives. Past this line, erasures begin.

6

Dedup and consolidate  (Phase 3.6)

Action: build the single Archive tree; move duplicates to _dupes-pending-delete/ and do not empty it yet. Rollback: move files back out — fully reversible.

7

Second copy of the irreplaceable subset → 250GB

Action: copy photos + documents core to the 250GB, verify with Phase 4, take it to a different physical location. Why here: this is the step that makes the erasures in Step 8 safe. Do not reorder it after them.

STOP GATEStep 8 destroys data permanently

Do not enter Step 8 unless all of these hold:

  • Step 5 gate files read PASS for this specific drive
  • Step 7 is complete — the second copy exists and is offsite
  • _dupes-pending-delete/ has been reviewed
  • M2's Time Machine has completed at least one successful backup and tmutil latestbackup returns a real timestamp
  • At least 7 days have passed since Step 5 for this drive. Deferred regret is real; a week costs nothing but patience
  • Only this one drive is connected

Rollback for Step 8: NONE. This is the point of no return. That is why every gate above it exists.

8

Repurpose the old drives  FIRST DESTRUCTIVE STEP

  1. Lowest-value drive first (the 120GB). If something about the process is wrong, you find out on the drive you care about least.
  2. Then the 250GB — but only if Step 7 did not claim it. If it is now the irreplaceable mirror, it does not get erased at all.
  3. Then the Crucial X8 → scratch. Unregister it from Time Machine before erasing, so macOS stops reporting a destination that no longer exists:
bash[SUDO]
tmutil destinationinfo -X                  # find the destination ID for "Backup"
sudo tmutil removedestination <destination-id>
tmutil destinationinfo                     # confirm it is gone

A stale registration is exactly what makes M2 look backed up today while having no backup. Clear it.

9

Set up scratch and offload M2

Action: create the scratch layout, move ~/Downloads and AI_OS working sets, add TM exclusions. Rollback: move the data back — reversible. Target: M2 below 70% used (81% today).

10

Empty the holding folders

Precondition: everything above done, plus a full week of normal use with nothing found missing. Action: delete _dupes-pending-delete/; collapse _STAGING into the final Archive layout. Rollback: none after deletion — which is why it is last, and why it waits.


Steady state

7Ongoing

7.1  Register and manage a Time Machine destination

bash · needs Full Disk Access[SUDO]
sudo tmutil setdestination -a /Volumes/M2-TimeMachine   # -a appends, keeps existing

tmutil destinationinfo
tmutil destinationinfo -X                               # plist, includes UUIDs

sudo tmutil removedestination <destination-id>          # clear a stale one
sudo tmutil setquota <destination-id> 2000              # cap TM at 2000 GB

setquota matters on the 8TB under Reading A. Without a quota, Time Machine grows to fill the volume — eventually consuming the space you wanted for the archive.

7.2  Exclusions — set these before the first big backup

bash · -p makes the exclusion path-based and stickyno sudo needed
tmutil addexclusion -p /Volumes/Scratch
tmutil addexclusion -p /Users/SeanVargas/Library/Caches
tmutil addexclusion -p /Users/SeanVargas/Downloads    # only if truly disposable

tmutil isexcluded /Volumes/Scratch /Users/SeanVargas/Library/Caches
tmutil removeexclusion -p /Volumes/Scratch           # undo

Without -p the exclusion attaches to a specific file/inode and is lost when the item is recreated. Use -p for directories. Do not exclude ~/AI_OS, ~/Pictures, or ~/Documents. Those are the whole point.

7.3  Verify a backup actually completed

bashread-only
tmutil latestbackup                    # the one that matters
tmutil listbackups
tmutil listbackups -t
tmutil latestbackup -d /Volumes/M2-TimeMachine
tmutil compare                         # what changed between the last two
tmutil compare -@ / /Volumes/M2-TimeMachine/<backup-path>

# deeper diagnosis when a backup fails — always pipe through tail/grep
log show --predicate 'subsystem == "com.apple.TimeMachine"' --last 24h --style compact | tail -100
ResultMeaning
A path with today's or yesterday's timestampPASS — a real backup exists
Code 18 "Failed to mount destination", drive unpluggedExpected. Proves nothing about the drive. Re-test with the drive attached.
Code 18 with the drive mounted and visible in FinderReal problem — corrupt TM volume, wrong destination ID, or a failing drive. Treat that drive as READ-ONCE per Phase 1.

7.4  The monthly five-minute check

~/AI_OS/ops/scripts/backup-check.shmonthly
#!/bin/bash
echo "=== $(date) ==="
df -h / | tail -1
tmutil destinationinfo
tmutil latestbackup || echo "!!! NO BACKUP — INVESTIGATE NOW !!!"
tmutil listbackups 2>/dev/null | wc -l
diskutil info /dev/disk<8TB> | grep -E "SMART Status|Container Free Space"
stat -f '%Sm' /Volumes/<250GB>/irreplaceable 2>/dev/null || echo "250GB not connected"

Four questions it must answer every month. Any "no" is an action item, not a note.

  1. Does tmutil latestbackup return a timestamp within the last 7 days?
  2. Is M2 below 80% disk usage?
  3. Is the 8TB's SMART status unchanged from last month?
  4. Has the irreplaceable mirror been refreshed within 90 days?

7.5  Annual

The restore test — the most-skipped, most-valuable step

Once a year, actually restore something non-trivial from Time Machine — a folder, not a single file — and confirm it comes back intact. An untested backup is a hypothesis, not a backup. Also re-run Phase 1 health checks on every drive, and re-read the 3-2-1 gap: has the mitigation actually been done, or is it still a plan?


CGaps and unknowns

Everything this plan assumes but could not verify. Each is a real hole, not a formality. Nothing in this document is a measurement of a drive.

#UnknownImpactResolved by
1Drive count — 5 or 7?Decides whether M2's backup can live on separate hardware from the archive. The single most consequential unknown here.Phase 0.3–0.9
2Contents of every drive. Nothing inspected; none connected.Every size estimate, dedup expectation, and timeline in this plan is unvalidated.Phase 2
3Mini's state. Unreachable, timed out twice.Cannot claim a fleet-wide backup posture. Mini may be unbacked-up too.Phase 0.8
4Whether any backup is encrypted, and whether the password is known.An encrypted backup without its password is not recoverable data. Could invalidate a whole drive's "value extracted" assumption.Phase 3.4 — check early
5Drive models, interfaces, real speeds. Only the Crucial X8 is named."Fast" and "slow" are characterization, not measurement. A USB-2 cable makes a fast drive slow.Phase 0.4–0.5
6Actual health of all drives. Age unknown, SMART unread, most USB enclosures report Not Supported anyway.The architecture depends on the 8TB being trustworthy. If it is not, the plan does not hold.Phase 1
7Why M2's TM destination fails to mount.Code 18 with the drive unplugged is expected — or the X8 may be sick, which would also make it a poor scratch drive.Phase 7.3, retested attached
8Which old machines have backups here, and whether their data exists elsewhere.Some extraction effort may be redundant with iCloud or existing copies.Phase 2
9Whether old Photos libraries hold originals or iCloud placeholders.An "archived" library of thumbnails is not an archive.Phase 3.5
10Post-dedup size of the irreplaceable subset.The 250GB-as-mirror plan assumes it lands under 232 GiB. Plausible, unverified. If it exceeds that, the offsite plan needs different hardware or cloud.Phase 3.6 — measure with stat, not du
11Free space on the 8TB right now. Assumed largely empty.If it is full, Phase 3 staging has nowhere to go and Step 1 cannot proceed.Phase 0.5
12Whether Sean has any cloud backup today.Changes how urgent the offsite gap is.Ask Sean
13Nano's and Mini's backup freshness. Nano has two destinations registered; whether either completed recently is unknown.Registered ≠ working. M2 proves that.ssh SeanVargas@100.116.58.44 'tmutil latestbackup'