`pvpGameState.svelte.ts` has held the PvP store since the duel shipped, and in all that time it had never had a unit test that exercised it directly, only the end-to-end suite watching it through a page. [`PvpSyncEngine`](/posts/the-design-with-no-second-copy) already took the sync and transport logic out of the store and made all of that testable behind a fake `PvpSyncApi`, but the store itself still called `new EventSource(...)` and touched `localStorage` inline, both of which meant a real browser to run at all.

The question worth resolving before doing anything was whether wrapping the whole store in a factory would even work. Svelte 5's runes are normally written inside a component; `$state` and `$derived` called from a plain function, invoked more than once outside any component, was untested territory for this codebase. Rather than start the refactor and find out mid-way, a throwaway spike answered it first: a branch converting the store into `createPvpGameStore(deps)`, invoked twice in the same process, one production instance and one for a test.

The runes turned out not to be the risk at all. Both instances compiled and behaved correctly, no rune-specific errors anywhere, and the store uses no `$effect` that could have depended on component lifecycle. The only real friction was mundane DOM typing, the real `EventSource`'s `onmessage` carrying a far wider type than the store actually reads, fixed with one documented cast at the default factory boundary. With the spike proving the seam and a separate check confirming the injection point didn't conflict with the SSE architecture decisions already on record, converting the store for real was a locked decision rather than an open question by the time it started.

```typescript
/** Injectable dependencies for the store. `api`/`clock` pass straight
 *  through to PvpSyncEngine, which was already injectable — this store
 *  itself only needed an EventSource constructor and a storage abstraction
 *  to become fully testable. */
export interface PvpGameStoreDeps {
	createEventSource?: (url: string) => EventSourceLike;
	storage?: Storage;
	api?: PvpSyncApi;
	clock?: Clock;
}

export function createPvpGameStore(deps: PvpGameStoreDeps = {}) {
```

`export const pvpGame = createPvpGameStore()` sits at the bottom of the file as the real production singleton, so every existing caller, the layout and the PvP page, needed zero changes. The fake storage a test can supply throws loudly instead of quietly returning `undefined` if it's ever reached outside a `browser` guard, catching a class of SSR bug at the moment it happens rather than downstream as a mysterious null.

The conversion surfaced one bug the store had been carrying by accident: its own `now()` and the `Clock` object passed into `createPvpSyncEngine` were built independently, two separate `Date.now` references that happened to agree only because nothing had ever made them disagree. Threading a single `Clock` through both call sites turned that coincidence into a guarantee. `pvpGameState.svelte.test.ts` is new, and covers the outcome-application quartet through fake transports, a rejected word never reaching it, and `leave()` tearing down one instance without touching a sibling, none of which had a home to be tested in before this file had a seam to test through.