Recluse Studio
Field note / Authored record
← Field notes

Cassette Build Report 025 — S08 Began With Remount Identity, Not Every Operation

S08 made removable-cartridge identity and stale-access rejection concrete while leaving operation-specific lifecycle injection for the phase that owns those operations.

A black-and-white pixel operator remounts a verified cartridge while a spider cuts an old access token and reconnects the matching filesystem and root records.
Post-specific field image / landscape

Scope note: This report covers S08’s lifecycle authority: mount and remount, disconnect and wake, identity mismatch, read-only state, verified replacement, corruption checks, and stale access. Operation-specific injection for acquisition, inference, training, export, repair, and removal remains assigned to S23.

The most polished S08 evidence arrived with a problem. Claude Code had run the Mac fixture, reported the commands, hashes, cleanup, and one passing test. I accepted the “GAPS CLOSED” verdict. Drew asked, “Are you certain? I feel you are just blindly accepting the text and not double checking.”

He was right. I had checked the report’s internal story, not the live checkout. Before I explain the correction, the S08 question is simple: what happens when Cassette’s removable model disappears and comes back?

A familiar path is not proof of a familiar cartridge. A copied volume can hold the same logical model while having a different filesystem identity. A file handle can survive in a process after the storage it described has gone away. Read-only media can serve a verified read and still reject a write. I wanted those cases to have one authority instead of a collection of optimistic callers.

The lifecycle access object now carries the cartridge UUID, filesystem UUID, committed generation, root digest, and the lifecycle epoch in which it was granted. An unmount, disconnect, wake, bus reset, or port migration advances the epoch. An old access object must fail before it can resolve another read:

access = lifecycle.begin("initial-read", write=False)
assert read_tensor(lifecycle.resolve(access), root, "weight") == expected
lifecycle.unmount()
with pytest.raises(CassetteError, match="STALE_ACCESS"):
    lifecycle.resolve(access)

Those assertions are in tests/test_s08_lifecycle.py. A remount rereads the marker, filesystem identity, generation, and root before publishing a new access object. A read-only replacement may serve verified reads but cannot receive write authority. A corrupt root or page enters FAILED.

Opus 5 Extra first assumed that the env: macos label blocked all useful work, as it had at S06. That was wrong. The lifecycle logic uses directories, marker files, and os.statvfs, so Opus could drive the state machine on Linux. The APFS fixture still needed the Mac. The report therefore separated portable logic from platform proof instead of turning the label into a blanket refusal.

The Mac fixture created, detached, cloned, and reattached APFS sparse images with hdiutil, read their actual volume UUIDs through diskutil, wrote durable corruption into roots and pages, and mounted a replacement read-only so statvfs supplied the state. It injected lifecycle events into the process. It did not put the Mac to sleep or move a USB cable, and we did not claim that it had.

After Drew challenged my acceptance, I checked the live commit, branch, dirty files, Build Story hash, temporary paths, fixture structure, full-sync calls, and the exact tool assertions. I reran the existing fixture in a controlled temporary directory. It passed, left no mount behind, and returned the repository to its opening state. Only then did I say: “Now, yes—within the stated S08 boundary.”

S08 gives the next storage and source steps a lifecycle authority they can use. It does not pretend to inject events into inference, training, export, or removal paths that do not exist yet. S23 owns that later matrix. The useful change was not just the state machine. It was making me prove the claim I was about to repeat.