# Editor IA slice 7 — one pause ## Context **Verified read-only against `494cbee` (clean) on 2026-08-28.** Slice 7 is the IA doc's bullet (`plans/editor-operations-ia.md:157-161`): `Pause{Downloads,Transcriptions,Backfill}Button` → one button, "the six actions" → one pair, the polarity normalization in `laneState.ts` goes, **keep the aria labels**. Its reconciliation (`:87-91`) fixes the definition: *"pause operation X" = "pause the root of the tree that dispatches X"*, one action mapping onto the **four legacy fields**, **no new settings block** — unified-ops step 6 (slice 9) migrates storage later. A pause is a hold, never a stop (`unified-operations-model.md:137`): every gate returns `limit() === 0` and `runPool` idle-waits. **Decided (operator, 2026-08-28):** (a) the button and the action are keyed **by lane** — the gate is per lane, three speaker operations share one, and "a per-operation page is not a per-operation switch" (`STATE.md:401`); `pauseLaneFor(operationId)` is how an operation page finds its lane. (b) The single definition reaches the **dispatch holds too**, not just the readers. (c) The runner pages get a pause beside Start/Drain/Stop. **What the census found (corrects the IA bullet in four places):** 1. **Four gates, three polarities, eight actions in two files.** `transcriptionsPaused` (`settings.ts:152`; plus the LIVE `WorkerPool.pauseAll/resumeAll/isPaused`, `workerPool.ts:283-316`, re-applied at boot by `editor/instrumentation.ts:56-73`), `downloadsPaused` (`:157`), `digest.digestsPaused` (`:474`), `backfill.enabled` (`:289-292`, **inverted**, shared by diarization / attribution-text / attribution-diarized, and deliberately also written by the `LaneSettingsForm` checkbox, `operations/settingsActions.ts:214` — keep that; "two places to set it, and they cannot drift", `jobs/actions.ts:331-342`). Actions: `jobs/actions.ts:150-178` (downloads), `:180-215` (digests), `:329-379` (backfill); `workers/actions.ts:9-23,60-83` (`pauseAllWorkersAction`/`resumeAllWorkersAction`: pool + best-effort persist). 2. **Three UI copies, one dead.** `PauseTranscriptionsButton.tsx` (2 sites: `jobs/active/page.tsx:37`, `workers/components/WorkersView.tsx:125-129`); `PauseDownloadsButton.tsx` (**zero** importers); four inline `LaneControl` descriptors in `LaneDeck.tsx` (`:126-148,216-238,283-309,437-459`, rendered by `LaneCard` through `LaneActionButton`, the shared primitive); and `SweepLane.tsx:187-211` on ui `Button` with a *composed* aria-label (`"Pause Digest"`, `"Pause Speakers"`) and the **opposite emphasis** (warning tint when NOT held; `LaneActionButton`'s `active` variant is warning-filled when held — "a held lane is visible from across the room"). `CommandPalette.tsx:110-131` calls the workers pair. 3. **The inversion lives in three readers, and the widget ships it raw.** `LaneDeck.tsx:471` (`gateHeld: !laneEnabled`), `operations/lanes.ts:334-336`, `jobs/active/buildActiveJobs.ts:337`; `api/widget/sync/route.ts:72,96,289,296` sends `digest.paused` and `backfill.enabled`. Readers of those two wire fields: `LaneDeck.tsx:255,403,471,551` only — no spec, no unit test, nothing in `MonitorWidget`/`WidgetControls` (precedent for a wire rename: slice 4's `noDigest → digestReachable`). 4. **Every existing label survives one canonical table.** Playwright's `getByRole(…, {name})` is case-insensitive substring unless `exact`, and **no pause/resume lookup uses `exact`** (grep verified). So `auto-queue.spec.ts:1186`'s `"Pause Digest"` (scoped to `section[data-lane="digest"]`) matches the canonical `"pause digests"`, and `backfill.spec.ts:809,820` / `widget.spec.ts:803,810` `"pause backfill"` are kept byte-identical. `"Pause Speakers"`, `"Pause Derived"`, `"Resume Digest"`, `"Hold the lane"` are asserted nowhere. 5. **Transcription's `held` is the live pool on every UI surface, never the flag.** `isGateHeld(settings, "transcription")` answers "will the pool be paused after a restart", not "is it paused now"; the e2e harness rewrites `test-settings.json` wholesale between tests while the pool keeps its `pausedSnapshot`. Surfaces (all live, unchanged): `LaneDeck.tsx:67`, `WorkersView.tsx:119`, `jobs/active/page.tsx:19`, `MonitorWidget.tsx:229`, `buildQueueView.ts:243`, `/api/pulse`, `/api/worker/health`. The flag is read in exactly two places after this slice: the boot hook and the action's no-op check. 6. **The runner pages have no pause at all** (`RunnerOperationView`/`LaneHeader.tsx:51-84`: Start/Drain/Stop only; `AutoQueueKindStatus` `status.ts:33-53` carries no held field; `railStates.ts:36` hard-codes `gateHeld: false` so the rail can never show a runner holding). Worse, `/operations/transcription` says **"no enabled worker to run it"** while paused, because `pauseAll` disables every worker and `autoRunner.ts:598` reports `no-workers`. **Hazards carried through every commit:** the runner section's contract (`RunnerOperationView.tsx:21-35`) forbids nested `
` and reserves `role="status"` — `LaneActionButton` is a plain `