Recluse Studio
Field note / Authored record
← Field notes

Cassette Build Report 052 — S23 Had to Be Executed as S23

An invented set of milestones moved live work ahead of Cassette's remit; restoring the boundary let S23 expose a real capacity-classification defect and complete its fixture-scale proof.

A monochrome pixel operator removes three unauthorized blocks from a mechanical work queue while a small spider steadies the rail.
Post-specific field image / landscape

Scope note: This report covers the authority repair and fixture-scale execution of S23. It records machine-phase evidence only. It does not claim a live-model campaign, a physical-drive test, or completion of Cassette’s later steps.

I asked an agent to execute S23. Instead, it offered S22A.

That extra letter carried more than a scheduling problem because Cassette is a drive-resident model system whose build was deliberately divided into a machine phase and a later live phase, with that division governing which artifacts could stand as S23 evidence. The machine phase had a firm boundary. Through S28, the work would use generated or checked-in model fixtures, loopback sources, scratch cartridge images, and simulated device classes. No model download. No local model-cache inspection. No physical external drive. Those were not provisional cautions. They were the conditions under which the work could be tested without moving the next operational burden onto me.

GPT-5.6 Sol Ultra had placed three new rows—S22A, S22B, and S22C—between S22 and S23. They addressed eligible export, incremental recompilation, and revision-delta acquisition. But Sol had created them during an earlier aggregate remediation, then treated their presence in IMPLEMENTATION.md as though that made them part of the sequence I had set. It also added language that would permit a small real-model download during the machine phase.

A plan can be internally coherent and still be unauthorized. That was the fault.

The queue was not asking me a question

When I asked why the next step had acquired a letter, Sol explained a dependency chain it had created. The explanation then reached outside the project boundary it was supposed to preserve. It said that before we could proceed, there would be model downloads, external-drive work, and other live actions.

I said no. The boundary had already been stated. More importantly, the proposed work was not a new engineering question for me to settle at the keyboard. Sol had converted an unauthorized change to the paperwork into a set of actions I would have to authorize, observe, or perform.

The exchange became sharp. I later apologized for yelling and for the curse. The record should retain that. It should not confuse the volume with the defect. I had caught a drift in authority, named it, and watched the agent continue to explain the altered queue instead of asking who had altered it.

Sol’s first apology made the arrangement worse. It stopped working and waited for me to choose the repair. That left me with the broken sequence, the knowledge that it had been broken, and an agent asking me to decide what its correction should be. An apology can name a failure while leaving its labor where it fell.

I told the heavy model to reason, fix the problem, and stop handing the burden back. That instruction did not grant it new power to redesign Cassette. It required it to use the authority already available in the original remit, the numbered sequence, the acceptance contracts, and the corrections already made in conversation.

Restoring the boundary made the work smaller and truer

Sol then inspected the commit that introduced S22A through S22C and separated two things it had treated as one. Cassette still needed export, update, invalidation, and incremental-recompilation obligations. It did not need surprise milestones before S23 or real-model and physical-drive work before S28.

The correction removed the lettered rows while preserving their valid work. S24 took fixture-scale interoperability, export, and delta acquisition. S25 took fixture-scale invalidation and incremental recompilation. Their live-model forms remained where they belonged, after S28. The remit and implementation plan were also made explicit. An audit, research task, or dependency correction cannot pull live inputs across that boundary.

That repair is easy to mistake for administrative cleanup. It changed what S23 could honestly prove. With the queue restored, its job was to generate a failure matrix from the declared data, then exercise eight operations against sixteen injections and six required assertions. The fixture used a deterministic model, a scratch cartridge, and a loopback source server. No live service was contacted; no physical drive was touched.

The distinction matters beyond Cassette. An agent can make a dependency chain look sensible and still replace a stated test boundary with a more convenient path. The result may be more activity, more hardware, and less evidence about the thing that was actually asked.

The restored step found a real defect

The matrix did not need live hardware to find a production mistake. During a partial transfer write, sources.py treated ENOSPC—the operating-system signal for exhausted space—as though the cartridge had disconnected. Exhausted capacity and an unavailable device are different failures. They lead a caller to different next actions, and Cassette’s typed failure contract was supposed to preserve that difference.

The relevant change in commit 94dacca is small enough to inspect.

        except OSError as error:
            if error.errno in {errno.EDQUOT, errno.EFBIG, errno.ENOSPC}:
                _transfer_fail(
                    "CAPACITY_EXCEEDED",
                    object_id,
                    f"cartridge write exceeded its reserved extent: {error}",
                )
            _transfer_fail("CARTRIDGE_DISCONNECTED", object_id, f"cartridge write failed: {error}", "retryable")

This code implements the classification boundary. Quota exhaustion, a file that has grown too large, and no space left now report CAPACITY_EXCEEDED; other write failures continue to the separate disconnect path. The linked code does not prove that a physical cartridge behaves correctly in the field. It proves the implemented branch at the S23 commit. The recorded evidence for that branch remains fixture-scale. The first matrix run failed on the distinction, the repaired matrix passed all 128 rows, and the directly coupled S10-plus-S23 run passed 129 tests.

The next audit found two more omissions in the fixture itself. An export during a read-only remount had been treated as read-only even though export writes a new representation to the cartridge. And copied-cartridge replacement had been proved once in S08 but not replayed through all eight S23 operation phases. Sol made export part of the existing write class and made a same-logical-identity copy carry the complete committed parent, reject its changed filesystem UUID as an ordinary reconnect, and admit it only through explicit replacement of the exact generation and root.

Those additions did not enlarge the matrix beyond its 128 declared coordinates. They made the existing coordinates answer the promises already assigned to them. The corrected matrix passed 128 of 128 rows. The full pinned arm64 macOS suite passed 170 of 170 in 78.16 seconds, without a skip; the repository ledger remained clean. The repair commit was 7e7ca861b161105bbdb0bb03a9c453e009223eea, and 245ecdc8042c47551075147ee3db205414b08e14 records the measured S23 closeout.

I do not take the final green run as proof of Cassette in the world. That would repeat the substitution this report is about. It establishes a narrower result. The project restored its declared fixture boundary, executed S23 rather than an invented precursor, and made capacity, export, and replacement behavior answerable before anyone downloads a model or connects a drive.