Skip to content

Docs: superseded work is one rule with its sites listed; one Generation in Core - #81

Open
dinooo13 wants to merge 2 commits into
core/recording-engine-sessionfrom
docs/superseded-work
Open

dinooo13 wants to merge 2 commits into
core/recording-engine-sessionfrom
docs/superseded-work

Conversation

@dinooo13

Copy link
Copy Markdown
Owner

Part of #73, point 3. Stacked on #80 (core/recording-engine-session), because the site list names its RecordingEngineSession.

What

docs/ARCHITECTURE.md, new section "Superseded work" (a stable name; Generation.swift points at it). It holds:

  • The rule. Work that outlives what it was started for takes a number or an identity when it starts, and compares it with the current one before it acts. It also says why cancelling alone is not enough: a task past its last cancellation check, or a call waiting to enter an actor, runs on regardless.
  • Every site that keeps the rule, with what it compares and what it keeps out:
    • the coordinator's recording
    • UtteranceSlot
    • RecordingEngineSession
    • OutputMuteController's generation and latestSession
    • ClipboardKeeper's restoreID, read-waiter IDs, TranscriptPromise identity and changeCount
    • PasteboardOutput.owedReturn
    • HotkeyMonitorLifecycle.generation, which feeds CarbonHotkeySession's IDs
    • HotkeyRecordingSlot tokens
    • ObservationLoop.generation
    • EngineLoader's engine === self.engine
    • ModelFiles.isCurrent(file, id)
    • S1MiniPolisher.generation
    • OnDeviceLanguageModel.leftover
  • The test convention. Every detached task has a test that supersedes or cancels it mid-flight: on ManualClock where it sleeps on a clock, on a Gate where it waits on other work. A table maps each detached task to its test. The exempt fire-and-forget idempotent ones are named: refiner.prepare(), S1MiniPolisher.warmUpRuntime, session.prewarm() and CorrectionLearner.pasted.

The gap the table showed. restoreOutputDevice chains each restore onto previous?.value, and nothing tested that. The new aSecondRecordingsRestoreWaitsForTheFirst holds the first recording's recordingEnded on a Gate and dictates a second time. Nothing may have ended before the gate opens; after it opens, the order must be [1, 2]. With the chain removed, the test failed 5 of 5 runs.

Generation (as decided, Core only). public struct Generation: Sendable, Equatable with current, next() and isCurrent(_:), plus two small tests. It is adopted in:

  • the coordinator's recording number: recordingID becomes recording, and isCurrent reads recording.isCurrent(id);
  • OutputMuteController.generation.

The other sites are left as they are.

Deviation. The plan listed 15 sites. The table also names OverlayPanel.generation in the app: the pill's show and hide completions check it.

Tests and checks

Benchmark

The Generation change is rename-level, but it is in the coordinator and the recording number is read on the press path, so here is bench-coordinator --runs 101. Apple M1, macOS 27.0, back to back.

Before, core/recording-engine-session (621023c), load 2.33 → 1.58:

Hold Engine Total (median) Share (median / p90 / max) Engine excess (median)
1500 ms 150 ms 160 ms 0.09 ms / 0.11 ms / 0.17 ms 0.24 ms

After, this branch (9b27e4c), load 1.53 → 1.40:

Hold Engine Total (median) Share (median / p90 / max) Engine excess (median)
1500 ms 150 ms 160 ms 0.10 ms / 0.11 ms / 0.17 ms 0.25 ms

Merge note

#78 (tests/no-ordering-sleeps) injects a clock into OutputMuteController. This PR touches the neighbouring lines (generation), so whichever merges second has a small conflict there: keep both the clock and Generation.

For the developer

  • Optional, since nothing between recordingStopped and inserted changed: a few live dictations on an installed build, comparing release-to-paste lines.

🤖 Generated with Claude Code

dinooo13 and others added 2 commits October 16, 2026 15:59
The coordinator's recording number and OutputMuteController's arm counter
read the same way: next() when new work starts, isCurrent(_:) when the old
work wakes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kers' restore chain has a test

ARCHITECTURE gains "Superseded work": the rule, every place that keeps it,
and the test convention for detached tasks. The one detached task without a
supersede test, the speakers' restore waiting for the one before it, gets
aSecondRecordingsRestoreWaitsForTheFirst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant