| simulator-audio.md | rationale | Simulator audio capture (iOS/Android) — design, whole-sim dynamic tap, sim-volume, rejected approaches |
| legacy-browser-fallback-ios-only.md | rationale | Why the JPEG legacy-browser (~5%) fallback exists only on iOS — historical, not a bug |
| monorepo-project-references.md | rationale | Why library packages use TS project references — the exports.types→src bug (#345), rejected alternatives |
| android-sdk-bootstrap.md | rationale | Why setup android bootstraps a self-contained SDK — Android Studio ≠ SDK, the three fragility causes |
| runtime-platform-registration.md | rationale | Why platforms self-register at runtime (AgentRegistry.register) instead of a literal Platform union — the OCP payoff |
| codec-negotiation.md | rationale | Why the browser negotiates H.264 capability before the agent streams — the ~95%/5% floor, black-screen prevention |
| android-rotation.md | rationale | Why rotation uses wm user-rotation + pinned scrcpy 3.3 — legacy command ignored on API 35+ |
| ios-device-recovery.md | rationale | Why tapflow start does not pre-boot iOS, and where zombie-simulator recovery lives |
| agent-keep-awake.md | rationale | Why the agent holds a caffeinate assertion during a session — idle throttle drops the emulator to ~4-5 fps |
| relay-heartbeat.md | rationale | Why the relay runs a ping/pong heartbeat — dead sockets otherwise linger to the TCP timeout |
| relay-resource-rejection.md | rationale | Why the relay rejects new sessions above a CPU/RAM threshold, evaluated relay-side |
| relay-backpressure-frame-drop.md | rationale | Why the relay silently drops frames on bufferedAmount backpressure — bounds memory |
| build-status-deletion-decoupling.md | rationale | Why a build's Done status is decoupled from its delete_after deletion lifetime |
| relay-tunnel-access.md | rationale | Why the relay stays inside the agent's network and tunneling is an opt-in plugin |
| relay-agent-auth.md | rationale | Why remote agents authenticate with an agent-scope PAT instead of an IP check |
| relay-secret-loading.md | rationale | Why the relay loads .env before evaluating its module-singleton config |
| simkit-internals.md | reference | SimulatorKit reverse-engineering notes — binary layout, symbols, touch/button injection |
| measurement.md | reference | Every performance metric emitter — how to enable it, its output, what it means |
| downscale-tuning.md | reference | Encode-resolution downscale lever — QA fidelity vs decode/bandwidth, recommended default |
| frame-envelope.md | reference | Frame envelope wire format (TFFE v1) — 22-byte per-frame timestamp header, magic-byte backward compat |
| sustainability-carbon-math.md | reference | Carbon arithmetic behind the Sustainability page — measured session increment, Apple PER inputs, sensitivity, and the comparisons we dropped |
| streaming-latency-log.md | log | Append-only glass-to-glass latency log — pipeline analysis, attempts, decisions |
| android-video-streaming-diagnosis.md | diagnosis | Android emulator streaming issues traced to root cause, one section per issue |
| awdl-wifi-latency-diagnosis.md | diagnosis | Periodic Wi-Fi stream hitch traced to AWDL via ICMP ping — method and evidence |
| workshop-lab-fork-observations.md | reference | Third-party workshop-lab fork: independent iOS-sim capacity data (~4 seats/32GB) + where our extension seams stop |
| adversarial-review.md | rules | How to run the pre-PR review and the cross-cutting design pass — channel design, prompt skeleton, why a cleared list ages with the diff, why a fix falsifies the prose beside it, why the same review costs 4 minutes or 106 |
| test-and-guard-coverage.md | rules | What a test or a static check must execute to hold its claim — absence assertions verified only by the mutation that creates the absence, four ways a guard gets bypassed, why the success path gets the first mutation, and the three ways a probe passes for the wrong reason — including the one no mutation can find |
| security-bumps.md | rules | Why a security bump is pnpm update before pnpm.overrides — fourteen inert entries measured, why the override key comes from the GHSA advisory and not the Dependabot alert, why the key and its replacement are both capped to one major |