Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Decision Records

Architecture decision records: what was decided, what the alternative was, and what it costs. Each one is short and each one names a trade-off — an ADR with no downside section is a press release, not a record.

These sixteen are the decisions that shape the structure of the library and would be expensive to reverse. They are not the complete set: PLAN.md §7 holds sixty-four resolved decisions, most of which are API details rather than architecture (whether a configuring method returns void or self, how a particular exception factory is spelled). Each ADR below cites the §7 numbers it comes from, so the fuller reasoning is one hop away.

#DecisionShapes
0001Decorate a PSR-18 clientThe whole library
0002JSON cassettes, YAML opt-inOn-disk format
0003Recording allowed locally, refused on CISafety default
0004Interactions are snapshots, not PSR-7 objectsCore data model
0005Session lock behind an optional interfacePersistence contract
0006Configuration freezes at the sessionLifecycle
0007Redaction normalises both sidesMatching + redaction
0008Redaction is one rule class with a target enumHook pipeline
0009A session never replays what it just recordedRecording semantics
0010Scoping splits session and managerCassette identity
0011Guzzle integrates through withInner() satellitesBridges
0012Strict mode verified in close(), never __destructLifecycle
0013Large bodies move to sidecar filesStorage
0014Decompression applies to the recording run tooRecord/replay parity
0015Only PSR-18 exception interfaces are recordedTransport errors
0016Laravel bridge in its own repositoryPackaging

The thread running through them

Several of these are the same decision applied in different places. Record and replay must be indistinguishable from the caller’s side produces 0014 (decompress on both runs), 0004 (rebuild responses rather than hand back stored ones) and 0009 (the recording run makes the requests the code actually makes).

State belongs to the session, not the object produces 0006, 0010 and 0011 — all three fall out of the bridges needing to construct clients freely without fragmenting the run.

Optional capability goes in a second interface produces 0005 and the ExplainsMismatch treatment of matcher diagnostics: the minimum contract stays implementable, and the extra is detected with instanceof.

Writing a new one

New work is either a PLAN.md §8 idea being promoted — in which case write the decision in §7 first — or a correction to something already here. If the change alters one of the sixteen above, amend that ADR with a Superseded by line rather than editing the decision out of history.