Skip to content

Stop-path latency, transcript survival, and a dead-bridge crash - #73

Merged
div0-space merged 295 commits into
developfrom
fix/the-tail-patches
Aug 19, 2026
Merged

Stop-path latency, transcript survival, and a dead-bridge crash#73
div0-space merged 295 commits into
developfrom
fix/the-tail-patches

Conversation

@div0-space

@div0-space div0-space commented Aug 12, 2026

Copy link
Copy Markdown
Member

Carries the accumulated branch work plus today's stop-path and STT cuts.

What this fixes

The stop path cost 49.5s on a take that owed no work. Measured 2026-08-12,
stop_path_budget: total=49.492s phases={rec_stop=36.701s, final_pass=0.000s, postproc=0.122s, format=11.085s}.

  • 30.005s of rec_stop was a timeout on the wrong condition. The
    end-of-session closure loop exited on pending_spans().is_empty(), but a span
    can be held by the Apple volatile window rather than by a missing Whisper
    window, and no completion clears that gate. It now waits on outstanding
    Layer 1 jobs. Verified live after install: rec_stop 36.7s → 6.9s.
  • The last span could never seal. The end-of-session seal clock came from
    the PCM sample counter while span timestamps come from SFSpeech's segment
    clock, which can sit milliseconds ahead — the span missed the volatile window
    by one millisecond and froze there. seal_remaining_at_session_end anchors
    on the spans' own timestamps.
  • ~1.0s of format was a cold embedder loaded in series behind the LLM.
    The load now overlaps the model round-trip, scoped to lanes that will
    actually reach the semantic guard.

The live-overlay repetition, root-caused and fixed. SFSpeech cumulative
finals REVISE the previous hypothesis (substitutions "szuty" → "skróty",
insertions, deletions). The segment-less rescue split the novel suffix with an
exact canvas.contains(prefix) probe — anchored at the callback's first word
and all-or-nothing — so one revised word re-committed the whole restatement.
The 2026-08-12 18:44 take delivered 62% of its words inside a repeated 6-gram,
one phrase four times over. revision_tolerant_known_prefix replaces the
probe: longest callback prefix within max(1, k/5) word edits (banded
word-level edit distance over the canvas tail; 1-2-word probes stay exact; the
matched prefix's last word must itself align, so trailing novel speech can
never be deleted into the match).

Verified by replaying the operator's actual take WAV through the production
Apple lane (tests/replay_take.rs, ignored diagnostic harness, env recipe in
its doc):

probe words repeated 6-grams coverage
exact contains 526 78 57.0%
positional tolerance 400 31 32.0%
edit-distance (shipped) 319 10 12.5%

319 delivered words against ~318 spoken — parity with speech; the residual is
largely the take's genuinely repeated content.

A dead Apple STT bridge took the whole app down. Rust's SIGPIPE-ignore
setup never runs in a cdylib inside a Swift host; the first write_pcm after
the bridge died killed the application with no ReportCrash entry. Same defect
the MCP client already carried a fix for (U14, a35a64b); the per-fd
F_SETNOSIGPIPE remedy now lives in util::pipes and both callers share it.

Engine warnings no longer discard the transcript. EngineEvent::Warning is
non-fatal by FFI contract, but the overlay's phrase-matching filter let
recoverable warnings reach presentTerminalError, which clears every committed
utterance. A non-empty draft is never thrown away now.

A correction, stated plainly

f8519df2 removed the lexicon pass from the cumulative-final prefix probe on
the strength of a comment claiming the canvas was pre-lexicon. The claim was
false and the change was a regression; it is reverted in 7dc7bf28 with a
guard that actually exercises a lexicon rewrite.

Still open

  • A bridge that fails to spawn degrades silently: the session mills the whole
    take against a dead engine and only admits it at stop time.
  • The remaining 11s of format is the provider generating tokens over SSE.

Gates

  • cargo test -p codescribe-core --lib — 1189 passed, 0 failed, 6 ignored
  • cargo clippy --workspace --all-targets -- -D warnings — clean
  • make verify-swift-format — wired into make lint this branch

Authored-By: claude agents@vetcoders.io

… settings)

lane_truth_keychain_only_secret_sets_probe_core_readiness hard-coded
LLM_ASSISTIVE_API_KEY while operator Settings select Anthropic, so
key_env_key became LLM_ANTHROPIC_API_KEY and the test failed outside a
clean env. Inject Keychain-only secret for the active assistive
provider's api_key_env_key instead.

Authored-By: grok <agents@vetcoders.io>
Enable Anthropic adaptive thinking in request payloads when policy allows it, so reasoning deltas can stream instead of showing only a placeholder. Rework Agent Chat sidebar behavior from hide/show to expanded/compact rail modes with mode-owned split widths, preventing unrecoverable collapse and empty column gaps. Also update focus policy to treat NSScrollView-backed text views as text input targets (fixing TextEditor click focus loss), and add tests for both the focus fix and sidebar mode geometry/toggle behavior.

model: claude opus 6
time: 2026-08-05 15:10:48
… example

- keygen: fresh Ed25519 pair, prints the ready gh-variable line and fingerprint,
  seed shown once on stderr and zeroed after
- sign: mints CSK1 tokens from CODESCRIBE_LICENSE_SIGNER_SEED_HEX at runtime;
  email/sku/updates-months/seat-limit as arguments
- refuses the RFC 8032 dev seed — production issuance can never reuse the
  publicly known test vector
- closes the gap where the repo shipped a verifier and a dev signer but no
  production issuance path at all

Authored-By: claude <agents@vetcoders.io>
…source pointers

- adaptive_thinking: cover the true path — thinking:{type:"adaptive"} reaches
  the wire, never a manual budget_tokens; false leaves the body untouched
- DEFAULT_MAX_TOKENS 8192 -> 128_000 (model-family output ceiling; we always
  stream). Doctrine: the agent's output is never capped — with adaptive
  thinking counting against max_tokens the old cap throttled doubly
- new tools/output_guard: single tool chunks above ~25K chars are truncated
  WITH a pointer instead of silently — generated output (process/git/search)
  spills in full to Config::config_dir()/agent/spill and the chunk names the
  file; on-disk sources (read_file) point back at their own path
- read_file previously cut at 40K chars with no marker at all — silent
  knowledge loss; now every cut is visible and recoverable
- unit tests: pass-through, spill integrity (full original preserved),
  pointer presence for both guard variants

Authored-By: claude <agents@vetcoders.io>
…art final pass

- Add pure `tail_gap_start_index(total_samples, sample_rate, from_secs)`:
  clamped sample-index math for the uncommitted tail boundary; non-positive
  or non-finite `from_secs` means whole file, past-the-end yields `len`,
  zero sample rate cannot produce a bogus offset.
- Add `whisper_tail_gap_transcribe_file(path, from_secs, language)`: loads the
  WAV, slices off everything before the last committed utterance end and runs
  the existing VAD-gated `whisper_tail_patch_transcribe` on that tail only.
  Boundary past the recording returns an empty transcript without touching
  Whisper. Never a full-file re-pass when a positive boundary exists —
  full-file re-pass stays FINAL_PASS_MODE=Always territory.
- Cover both with inline tests: clamp math, a synthesized 2s silence WAV whose
  tail short-circuits on the VAD gate, and an out-of-range boundary.

Authored-By: claude <agents@vetcoders.io>
- Add `FinalPassAction` (SkipStreamingFinal | FullFileRepass | TailGapFill):
  the lossy bool could not distinguish "re-transcribe the whole file" from
  "transcribe the uncommitted tail and append it" — both collapsed to false,
  which is how Smart drifted into full-file re-passes over committed text.
- Add `final_pass_action(mode, completeness)` with the operator hard mapping
  (2026-08-05): Always -> FullFileRepass regardless of completeness;
  Smart+Complete -> SkipStreamingFinal; Smart+Incomplete -> TailGapFill;
  Off -> SkipStreamingFinal regardless. FullFileRepass is reachable from
  Always and from nowhere else.
- Keep `should_skip_full_final_repass` as a documented transitional shim
  delegating to the typed action with byte-for-byte unchanged runtime
  semantics; it must die once the stop path consumes actions directly.
- State the Smart hard rule in the module doc header: per-utterance /
  tail-only gap fill, appended to immutable committed text, never full-file.
- Tests: full (mode x completeness) matrix, the shim-agreement property, and
  `test_only_always_mode_may_full_file_repass` iterating every combination to
  assert FullFileRepass is produced by Always alone.

Authored-By: claude <agents@vetcoders.io>
…n session telemetry

- Add `committed_through_secs: Option<f32>` to SessionTelemetrySnapshot — the
  audio boundary of committed streaming text.
- SessionTelemetrySink folds EngineEvent::UtteranceFinal `end_ts` as a monotonic
  max, so an out-of-order final never rewinds the boundary.
- Default/reset leave the boundary as None (no committed audio yet).
- Test-first: test_session_telemetry_tracks_committed_through_secs_monotonic_max
  covers default None, 3.2 -> 7.9 advance, out-of-order 5.0 held at 7.9, reset.
- Adapt the one exhaustive SessionTelemetrySnapshot literal in controller tests
  so the new field keeps the crate compiling.
- Enables Smart-mode stop to transcribe only the uncommitted tail instead of a
  full-file re-pass (append-only doctrine — committed text is immutable).

Authored-By: claude <agents@vetcoders.io>
…ss actions

- add append_tail_gap in final_pass.rs: append-only join of a Whisper tail
  gap-fill onto committed streaming text (trimmed streaming is always an
  untouched prefix of the result; single-space seam; empty operands handled)
- switch the stop path from should_skip_full_final_repass to a match on
  final_pass_action: SkipStreamingFinal and FullFileRepass keep byte-identical
  behavior, Off stays hard off
- add the Smart TailGapFill arm: boundary from session telemetry
  committed_through_secs, spawn_blocking whisper_tail_gap_transcribe_file,
  append via append_tail_gap, LocalFinalPass verdict with reason=smart_tail_gap
  and disposition Changed/Unchanged, FinalPassStages timing + info! receipt
  `final_pass_tail_gap mode=smart from_secs=.. appended_chars=..`
- retire the transitional shim should_skip_full_final_repass and port every
  bool-based scenario to the typed action API (Smart+Incomplete now asserts
  TailGapFill, never FullFileRepass — the old expectation was the violation)
- pin lexicon as ungated on the tail-gap path: dictionary rewrites both the
  committed prefix and the appended tail of a composed transcript

Authored-By: claude <agents@vetcoders.io>
…ail duplication holes

- Add codescribe_core::stt::resolve_tail_gap_boundary + TailGapBoundary:
  Some(t>0) -> From(t); missing/zero/non-finite boundary -> WholeSessionBootstrap
  only when the streaming canvas is EMPTY, otherwise Skip. Kills the
  committed_through_secs.unwrap_or(0.0) path that turned Smart+Incomplete
  (no_commit_source / no_coverage / empty) into a whole-file Whisper pass
  appended onto existing streaming text.
- Wire the controller TailGapFill arm to the policy: From(t) keeps reason
  "smart_tail_gap", WholeSessionBootstrap runs from 0.0 with reason
  "smart_bootstrap_gap_fill", Skip emits an honest Skipped verdict with reason
  "tail_gap_no_boundary" and never invokes Whisper. FinalPassStages bookkeeping
  unchanged.
- Dedup overlapping preview words in append_tail_gap: drop the longest leading
  tail word-run that repeats the trailing streaming words (case- and
  edge-punctuation-insensitive comparison, original tail words appended). Tail
  fully contained in the committed suffix appends nothing. The streaming side is
  never mutated - it stays an exact prefix of the result.
- Tests: resolve_tail_gap_boundary_matrix (core) and
  test_append_tail_gap_dedups_overlapping_preview_words (app), both RED first.

Authored-By: claude <agents@vetcoders.io>
- Commit 50ecc83 added the offline license signer example reading
  CODESCRIBE_LICENSE_SIGNER_SEED_HEX without a registry entry, so the shared
  e2e_env_registry gate failed for every agent on the tree.
- Register it in the build category next to CODESCRIBE_LOCAL_INSTALL: empty
  default, string, restart reload, described as an example-only signing seed
  that the app runtime never reads and that must never reach .env or CI.

Authored-By: claude <agents@vetcoders.io>
…L_PASS_MODE

- Move FinalPassRoutingMode + env resolution (FINAL_PASS_MODE /
  CODESCRIBE_FINAL_PASS_MODE / legacy CODESCRIBE_LOCAL_STT_FINAL_PASS,
  default Smart) into codescribe_core::config::final_pass so every stop
  lane consults one parser; app/controller/final_pass.rs re-exports it at
  the historic path, controller call sites untouched
- Move the env/parse tests with the type (serial-guarded, matching the
  neighbouring env-test discipline in core)
- ComposerTranscript now folds UtteranceFinal::end_ts into a monotonic-max
  committed_through_secs, mirroring SessionTelemetrySink; empty finals
  still seal their audio so it is never gap-filled twice
- Add composer_final_pass_plan: Always -> FullFile, Off -> SkipStreaming,
  Smart -> resolve_tail_gap_boundary (From/WholeSessionBootstrap/Skip)
- stop_recording/run_final_pass obey the plan: tail gap-fill via
  whisper_tail_gap_transcribe_file under Smart, no Whisper at all under
  Off (streaming splice stays the fallback), full WAV only under Always;
  plan + mode logged at info on target "composer-dictation"
- Closes the verifier hole: the composer voice-note lane ran an
  unconditional full-WAV re-pass with zero mode consultation

Authored-By: claude <agents@vetcoders.io>
… merge

- Composer voice-note lane lost gap-fill words under FINAL_PASS_MODE=smart:
  the Smart tail was routed through `merge_live_whisper`, whose
  `coalesce_substitutes` folds the boundary DeleteA+InsertB pair into a
  Substitute that keeps live and DISCARDS the whisper token. Measured at HEAD:
  ("raz dwa" live + "trzy cztery" tail) -> "raz dwa cztery".
- Promote the audited append-only composer to core as
  `codescribe_core::stt::append_tail_gap` (with `overlap_key` /
  `leading_overlap_words`), beside `resolve_tail_gap_boundary`, so both Smart
  stop lanes share ONE implementation instead of a twin. `final_pass.rs` keeps a
  `pub(crate)` re-export at the historic path; controller call sites and tests
  are untouched.
- Bridge: new plan-aware `compose_composer_transcript` — `TailGap` appends the
  bare tail via the shared core primitive, `FullFile` keeps the whole-WAV merge,
  `SkipStreaming` returns the streaming splice. New internal
  `ComposerTranscriptSource::TailGapAppend` label (enum is bridge-private, never
  crosses the UniFFI surface) and the stop receipt now carries `plan`.
- Make `run_final_pass`'s plan dispatch exhaustive: `FullFile` is named
  explicitly so a future `ComposerFinalPassPlan` variant is a compile error
  instead of silently falling into the forbidden full-file re-pass.
- Controller: replace the `f32::NAN` Skip sentinel with `Option<(f32, &str)>`, so
  the Skip arm never produces a `from_secs` and correctness no longer depends on
  branch ordering. Verdict reasons unchanged (`tail_gap_no_boundary`,
  `smart_tail_gap`, `smart_bootstrap_gap_fill`).
- Tests: bridge TailGap append/merge/empty-tail cases (RED first) plus core
  `append_tail_gap` prefix-immutability, dedup and empty-operand tests. Drop a
  rotting `mod.rs:NNNN` reference from a controller test doc comment.

Authored-By: claude <agents@vetcoders.io>
Standardizes repository guidance by rewriting AGENTS.md with the canonical swarm/doctrine directive, simplifying CLAUDE.md to defer to AGENTS.md, updating the commit message template, and removing the legacy .aiassistant markdown rule while ignoring the .aiassistant directory. It also appends a new UI divergence audit signal to AGENT_BUS.md.

On the code side, it cleans the Teacher HTML report heading to a neutral title and updates Swift UniFFI bridge stop-recording documentation to reflect FINAL_PASS_MODE behavior (Always/Smart/Off), with the regenerated stop_recording checksum updated accordingly.
…s tail-silence contract on CI

- tail_silence_contract went red on CI after deprivatize (6ffcf44) removed the
  in-repo operator-speech fixture: without ~/.codescribe/data_assets the test
  fell back to a synthetic 440 Hz sine, which real Silero rightly refuses to
  classify as speech, so BOTH whisper segments were dropped (dropped_count 2 != 1).
- Add tests/assets/synthetic_speech_tts.wav: 10.8 s of macOS TTS speech
  (pl_PL voice, 16 kHz mono, 343 KB) — synthetic by construction, zero operator
  voice, safe under the deprivatize fence (which stays untouched:
  tests/assets/data_assets/* remains ignored).
- canonical_wav_path now falls back to the committed TTS fixture before the
  sine synthesis; private fixtures still win when present.
- Verified RED->GREEN in a CI-like env (HOME hidden): FAILED 2!=1 before,
  ok after; normal env stays green on the private fixture.

Authored-By: claude <agents@vetcoders.io>
…che rail formatters

Sample 2026-08-07 10:43 (0.13.3) caught the main thread pinned 93/93 samples
inside _NSPopoverCloseAndAnimate -> becomeKeyWindow -> AgentChatStore
refreshThreadsFromExternalChange -> RealThreadsEngine.listThreads, with 42/93
under fresh NSDateFormatter/ICU construction per rail row. Distinct from the
2026-08-01 (0.13.2) freeze (SwiftUI render storm, fixed by 937189f).

- AgentChatStore: external-change triggers now coalesce onto the next
  main-queue tick (single pending flag, no timers) — a window-ordering storm
  collapses to one disk re-read and runs outside the notification callout
- AgentChatStore.replaceThreads: identical rail rows no longer publish —
  an unchanged `threads =` still rebuilt the whole window body (937189f
  lesson); matched rows reuse instances, so equality also fixes selection
- ThreadRailMeta.relativeTime: cached DateFormatters (full ICU init was paid
  once per row per refresh); calendar reassigned only when a caller differs
- ThreadsRefreshTests: C5 storm-coalescing (10 posts -> 1 list call) and C6
  unchanged-refresh-does-not-publish, observed RED before the fix; existing
  contracts drain the coalescing tick before asserting

Authored-By: claude <agents@vetcoders.io>
…finite end_ts; mark signer seed as secret

PR #69 review findings (Copilot):

- helpers.rs telemetry fold: non-finite end_ts (NaN/±inf) no longer touches
  committed_through_secs — NaN fell through the `current >= end_ts` arm and
  overwrote a valid boundary, silently degrading Smart tail gap-fill to Skip;
  now at parity with ComposerTranscript::note_committed_through (RED observed
  before the guard: NaN replaced Some(3.2))
- ENV_REGISTRY: CODESCRIBE_LICENSE_SIGNER_SEED_HEX typed as "secret" (was
  "string") matching LLM_API_KEY convention so tooling never renders it as
  plain config

The two rustfmt comments are stale: cargo fmt --check exits 0 on the current
branch and the CI Format Check is green.

Authored-By: claude <agents@vetcoders.io>
…ugh the documented order

- add scripts/lib/data-assets.sh — the one shell-side implementation of the
  fixture resolution contract (CODESCRIBE_DATA_ASSETS → ~/.codescribe/data_assets
  → gitignored in-repo drop dir) that the README, the Rust e2e helpers and
  bench-stt.sh already shared but the harness and the Makefile did not
- scripts/e2e-blackhole-dictation.sh: resolve the fixture argument through it;
  a missing corpus exits 2 listing every path checked, before any audio device
  is touched
- Makefile: derive DATA_ASSETS_DIR, ENGINE_CLIP, the parity clip and the 01–04
  ENGINE_ALL_CLIPS glob from the resolver — all four hardcoded the single tier
  gitignore keeps empty by design, so every ENGINE_* target was dead on a host
  whose home corpus held the audio
- retain the parity test log under target/e2e-blackhole (gitignored) and surface
  the `parity similarity` line — the measurement evaporated with $WORK, leaving
  the grinding loop a verdict with no number
- tests/data_assets_resolution.rs: 10 hermetic contract tests (fake HOME, fake
  repo root, stub WAVs — no private audio, no audio hardware)
- tests/assets/data_assets/README.md: name the shared resolver, add the
  cold-worker one-liner

No private audio enters git; the .gitignore fence is untouched.

Baseline on this host (macOS 27.0 arm64, branch fix/whisper-final-pass-move-out-if-not-needed):
`make test-engine-parity` exit 0 — parity similarity 161/173 = 0.931 (bar 0.90).

Authored-By: claude <agents@vetcoders.io>
…d fails

- scripts/e2e-blackhole-dictation.sh: `cd "$(dirname "$0")/.." || exit 2`.
  Everything after it is repo-root relative — now including the `.` source of
  the fixture resolver — and the script proceeds to mutate the operator's audio
  device mute/volume state, so a failed cd must abort rather than relocate the
  run (shellcheck SC2164, latent before the resolver, load-bearing after it)
- scripts/lib/data-assets.sh: print the expanded home corpus path in the
  not-found hint instead of a literal `~`, which never expands inside quotes
  and is less useful than the real path (SC2088)

shellcheck -S warning: clean on both files. semgrep: 0 findings.

Authored-By: claude <agents@vetcoders.io>
…e stream state

- Pin bridge swiftc to -target arm64-apple-macos26.0 (Makefile ENGINE_BRIDGE_TARGET + build-app.sh) so host triple no longer drifts to minos 28.0
- Isolate non-Sendable SFSpeech request / DispatchWorkItem / AV teardown behind serial-queue handles (SfSpeechRequestHandle, SfSpeechTimeoutCancel, SfSpeechBufferSession)
- Close Sendable warnings at stream/buffer path without @preconcurrency suppression
- Document the pin in apple_stt README and bridge build comment

Authored-By: grok <agents@vetcoders.io>
…gressive path

The Apple progressive path (daily driver) emitted raw SFSpeech text and
relied on the stop-path postprocess to correct it — a post-commit rewrite,
which the append-only doctrine forbids. Every seal now runs the shared
lexicon + cleanup pass before the text becomes committed canvas.

- route all three Apple seal sites (phrase final, summary fallback,
  open-partial-on-stop) through StreamPostProcessor::process_utterance
  (lexicon + cleanup, no semantic gate); no second postprocessor forked
- keep Preview events RAW — previews are in-flight presentation, not
  canvas, so the rewrite lands exactly once at seal time
- emit DropKind::FilteredEmpty with a counter and a log line when
  postprocess reduces an utterance to nothing, instead of sealing ""
- restore raw_text contract parity with the VAD path: text is corrected,
  raw_text preserves the engine output for the quality loop
- group the six mutable seal counters into AppleSealState so the shared
  postprocessor instance survives the whole stream and emit_stream_events
  stays under the argument-count gate
- report filtered_empty_drops alongside sealed count in the session log

Tests: five apple_seal_lexicon_* cases cover the corrected seal, raw
previews, the filtered-empty drop, the summary fallback seal, and
idempotency under a second stop-path pass.

Authored-By: claude <agents@vetcoders.io>
…or Apple path

- add `LiveAudioBuffer`: bounded drop-oldest PCM ring addressed by session-time
  seconds, so a sealed `UtteranceFinal` resolves back to the audio behind it
  (Layer 1 tail-patch prerequisite, W2-A)
- refuse rather than truncate: ranges evicted past the 120 s cap, starting past
  captured audio, or overshooting it beyond one chunk-quantisation step return
  `None` — a short window looks like success and would address wrong audio
- reject non-finite / negative bounds instead of coercing them; `f32 as u64`
  maps NaN to 0 and saturates inf, same class as the non-finite `end_ts` guard
- feed the buffer worker-side, off the same counter `audio_secs` is derived
  from, so buffer and seal clock cannot drift and the async select loop stays
  lock-free (2026-07-27 interleave contract)
- resolve every seal to its window, prune committed audio, and count
  `unresolved_windows` — F3 falsification sensor visible in the live path
  before Whisper is wired onto the boundary clock

Authored-By: claude <agents@vetcoders.io>
…pple progressive path

W2-A. `CODESCRIBE_LAYERED_TRANSCRIPTION=phase1+` now gap-fills the live canvas
on the daily-driver Apple path, not just on VAD/scheduler.

- Seal-time hand-off: every sealed `UtteranceFinal` resolves to its retained PCM
  window (W1-B) and is handed to an async Layer 1 lane together with the exact
  committed string `ReplaceRange` offsets are computed against.
- F1: the seal path runs on the PCM-forwarding worker thread, so it `try_send`s
  into a bounded queue and counts drops instead of ever blocking capture; the
  async side admits at most one job in flight and runs inference on
  `spawn_blocking`, never on the event-drain loop.
- Ordering: the patch branch flushes every queued engine event before emitting,
  so a `ReplaceRange` can never overtake the `UtteranceFinal` it patches.
- F3 carry-over: a boundary that cannot address retained audio stays counted as
  unresolved and is never handed to Whisper.
- Stop path: the bounded backlog is settled after capture drains rather than
  raced against `ev_rx` closing — a patch that lands only sometimes is worse
  than one that always lands. Capture-sender safety still runs first.
- F2: `TailPatchConfig` thresholds untouched; the shared primitive keeps owning
  the skip decision.
- Hoisted `tail_patch_enabled` / `compute_tail_patch_job` /
  `emit_tail_patch_result` / `emit_session_finalised` to `pub(super)` so both
  live paths read one gate and report one `LayerSummary` shape — no duplication.
- Deleted the `session.rs` honesty warning that said Apple progressive does not
  run Layer 1; updated `tail_patcher` module docs and `docs/env.md`, which the
  wiring turned into falsehoods.
- Tests (RED first): window/committed-text hand-off, unresolved window enqueues
  nothing, layered-off wires nothing, backpressure drops without stalling,
  induced gap emits one bounded `ReplaceRange{TailPatch}` and counts into
  `SessionFinalised.layer_summary`, divergent re-transcription skipped, env gate
  (serial). The Whisper leg itself is the shared VAD-path job, stubbed here
  since no model is loadable under `CODESCRIBE_NO_EMBED=1`.

Authored-By: claude <agents@vetcoders.io>
… tail-patches

- `assemble_live_from_events` dropped `ReplaceRange` on the floor, so every
  Layer 1 `TailPatch` was invisible to the live assembly — and the assembly is
  exactly what `capture_clip_via_device` measures. A layered-on parity run
  therefore scored identically to layered-off: the bar gated nothing.
- Apply the patch to the sealed utterance it targets, keyed by `utterance_id`
  (parallel id vector; `LiveAssembly`'s public shape is unchanged). `rposition`
  mirrors the overlay's `lastIndex(where:)` so both sides patch the same slot.
- Reuse `EngineEvent::apply_to_committed_text` — one source of truth for the
  char-offset contract, shared with the emitter's authoritative buffer.
- Out-of-range and unbound windows are dropped whole, never half-applied;
  `InsertAnnotation` stays out (decoration, not transcript content).
- Tests: patch lands on its own utterance, char-not-byte offsets, unbound /
  overrunning windows dropped, pre-seal patch does not retro-apply.
- `parity_assembly_reads_layer1_tail_patches` guards the harness itself,
  always-on (no model, no loopback): layered-on must not read byte-identical
  to layered-off.
- New `make test-engine-parity-layered` names the layered-on gate instead of
  leaving it an undocumented env incantation.

Authored-By: claude <agents@vetcoders.io>
…ilPatch; composer consumes layer events

- `{selection_N}` markers anchor to absolute offsets in the live text captured
  at selection time. A `ReplaceRange` that changes an earlier span's length
  slid every marker behind it, walking the intent fence into the middle of an
  unrelated word. `applyReplaceRange` now rebases them in the same transaction:
  markers before the span hold, markers after ride the delta, markers whose
  anchor text was rewritten collapse to the patch boundary (never dropped,
  never left past the replacement).
- `renderedOffset(forTextOffset:)` translates Rust char offsets into rendered
  offsets so annotation decoration cannot skew the rebase.
- `liveTextOffset(ofSegmentAt:)` mirrors `rawLiveText`'s own assembly (blank
  segments dropped, single-space join) so the two cannot drift apart.
- `ComposerDictationListener.onReplaceRange` was an accidental no-op: the
  composer builds its own preview from `onFinal`, so it kept showing text the
  engine had already retracted — split-brain against the overlay. It now
  applies bounded patches with the same drop-whole rule.
- `onContextMarker` / `onInsertAnnotation` stay inert on the composer path, now
  documented as a deliberate destination-scoped contract rather than a gap.
- OverlayStateTests: mid-stream replace, own-utterance targeting, char-not-byte
  offsets, unbound/out-of-range drop, and four marker-coexistence bars.
- ComposerMicTests: patch corrects the live preview, targets only its own
  utterance, drops unbound/overrunning windows.

Authored-By: claude <agents@vetcoders.io>
…-0 bar stops scoring Layer 1

- `make test-engine-parity` did not control which lane it measured.
  `CODESCRIBE_LAYERED_TRANSCRIPTION` is a power-user key, NOT promoted to
  settings.json, so `Config::inject_file_env_for_runtime` copies it out of
  `~/.codescribe/.env` into the process environment. The operator's dotenv
  carries `phase1`, so Layer 1 armed itself inside a target whose whole
  purpose is to score Layer 0 against an Apple-fidelity reference — and
  Layer 1 is supposed to diverge from Apple. The bar went red for doing its
  job, and the number was read as an engine regression.
- Receipt, one binary, consecutive runs of the same target: 05:32 census
  `Other: 1` → similarity 0.931 PASS; 05:35 census `Other: 22` → 0.833 FAIL.
  The 05:35 run is the one the supervisor refuted.
- The target now pins `CODESCRIBE_LAYERED_TRANSCRIPTION=off`. Explicit `off`
  also blocks the injection at source: `inject_file_env_for_runtime` only
  fills keys absent from the process env, and the settings.json seed in
  `loader.rs` is guarded the same way.
- `e2e_apple_live_parity` snapshots the requested lane BEFORE capture (the
  first `Config::load()` mutates the process env mid-run, so reading it
  afterwards would report a leak as the request) and asserts it against the
  lane the events actually show. `ReplaceRange { source: TailPatch }` has a
  single producer, so the event stream is a witness no env read can
  contradict.
- The mirror case is covered too: a layered target that produced zero
  tail-patches scored Layer 0 while claiming to gate Layer 1 — the P1-01
  shape, a gate asserting nothing about the thing it exists to gate.
- Seal-time lexicon (W1-A) also emits `ReplaceRange` and rides Layer 0 by
  design; the guard counts `TailPatch` only, so it is not mistaken for a leak.
- Three always-on tests (no model, no loopback) cover leak, unarmed layer,
  and the lexicon-on-Layer-0 case. RED observed on a stub before GREEN.
- The harness prints `layered lane: …` and the test prints `parity lane:
  requested … · measured N tail-patch event(s)`, so every retained log under
  `target/e2e-blackhole/` is self-describing.
- No bar was moved: `PARITY_SIMILARITY_BAR` stays 0.90.

Authored-By: claude <agents@vetcoders.io>
…t stop

- Add CODESCRIBE_QUBE_DONOR (off|on, default off) env + settings seed
- On stop, when on: copy WAV + delivered TXT to ~/.codescribe/qube_inbox/<date>/<session_ts>.{wav,txt}
- Donor writes files only — never Whisper; failures warn, never break delivery
- Register env; unit + controller donor_optin tests (layout, default-off, zero-Whisper Off, Smart)

Authored-By: grok <agents@vetcoders.io>
- Move ensureSpeechAuthorizedForSfSpeech into SF-only helpers (URL, buffer, stream)
- Stop calling Speech auth before ST/SF backend selection on transcribe/stream/live
- Rust init hard-fails / request_auth only when speech_recognition_tcc_required
- Matrix tests: SF × speech_auth outcomes; ST ignores Speech TCC; mic orthogonal
- Document backend-scoped TCC + responsible-process D1 (app vs bridge identity)

Authored-By: grok <agents@vetcoders.io>
…parity bars

- add a third Apple bridge lane, `dictation_transcriber` (SpeechAnalyzer
  family), gated OFF behind `CODESCRIBE_APPLE_DICTATION_TRANSCRIBER=1`;
  unarmed, probe/transcribe routing is byte-for-byte the shipped ST → SF order
- probe/transcribe order becomes ST → DT (armed) → SF; the pure table now lives
  in `probe_backend_fallthrough` + `DictationLane` and replaces the narrower
  `probe_st_sf_fallthrough` seam
- reserve the locale via `AssetInventory` before use: unreserved, DT reports
  `status == .supported` and the analyzer yields ZERO results with no error
  even though `installedLocales` lists the locale
- compose the DT preset by hand (punctuation + volatileResults + audioTimeRange)
  because `.progressiveLongDictation` carries no time index and
  `BridgeSegment.startTs/endTs` is a hard bridge contract
- scope Speech TCC honestly: DT ran the full 140.85 s pl-PL fixture with
  `SFSpeechRecognizer.authorizationStatus() == notDetermined`, so it joins ST on
  the not-required side of the W4-B matrix
- fix `streamAudio`: the feeder fed `AVAudioConverter` one buffer per convert
  call and answered `.endOfStream` to every further pull, so a sample-rate
  conversion ended the stream after 1 buffer / 1486 frames of 2 253 600 — ST's
  file path was truncated to ~0.09 s (empty text, zero segments). Now pulls
  inside the input block and treats `framePosition >= length` as EOF; measured
  coverage 1.0000, last segment 140.82 s
- add `examples/apple_backend_bars` — one lane per run, chosen by the same env
  the product reads, scored with the parity test's own aligner
- measured (05_apple-live-parity, 140.85 s): DT 0.947 vs the system-dictation
  reference at ratio 0.99, head+tail sealed, byte-identical over 3 runs; the
  shipped SFSpeech streaming lane scores 0.898-0.931 and is not repeatable

Authored-By: claude <agents@vetcoders.io>
… canaries

- `scripts/smoke-macos27.sh`: durable per-beta host smoke. Headless rows only —
  raises no TCC dialog, posts no synthetic events, never reads pasteboard
  content unless asked; operator-only rows report SKIP instead of passing
  quietly. `--out` writes the filled checklist, `--with-inference` adds the
  Metal/candle cold-vs-warm row.
- `scripts/smoke/macos27_probe.swift`: permissionless canaries — the 14
  CoreGraphics constants `app/os/hotkeys/platform.rs` hardcodes as raw literals
  checked against the live SDK, CGEventTap create → force-disable → re-arm,
  TCC status matrix with the asking process named, and the S-5
  `responsibility_spawnattrs_setdisclaim` dlsym canary.
- `scripts/smoke/overlay_placement_probe.swift`: NSPanel placement proven by
  compiling `OverlayPlacement.swift` standalone — 65 assertions over six anchors
  × normal/fullscreen/secondary-display geometry plus stale-origin clamp. Skips
  the XCTest host, which boots AppModel and hangs beside the running app.
- `scripts/smoke/appkit-observers.allow`: pinned census of AppKit-notification
  observers. The census is 4, not 1: three `NSScrollView` live-scroll observers
  in `MessageList.swift` are object-scoped with O(1) handlers, so the rule is
  "coalesced OR object-scoped", not "always coalesce".
- `AGENTS.md`: the d79781b lesson as Operational Law 5, enforced by the census
  rather than left as prose.
- `Makefile`: `make smoke-macos27` plus a help entry.

Run on macOS 27.0 (26A5388g), Xcode 26.6, app 0.13.3 (447) live:
PASS 8 · FAIL 1 · SKIP 5 · INFO 6. The single FAIL is real and is NOT a 27
regression — the Sparkle appcast at the shipped SUFeedURL returns HTTP 404
because `site/public/appcast.xml` never reached `main`, so Pages never published
it. Left unfixed on purpose: publishing is an operator button.

Authored-By: claude <agents@vetcoders.io>
…rected env keys

W3-B. `validate-envs.sh` was green because it was not looking, not because the
registry was complete: every pattern it scanned required the key as a literal at
the call site, so `env_bool(ENV_DICTATION_TRANSCRIBER, false)` was invisible.

- Scanner gains a fifth pass over `const NAME: &str = "KEY"` declarations,
  filtered by the repo's own ENV-token naming convention — which is why
  `LICENSE_PREFIX = "CSK1"` and the Keychain-account consts stay out.
- RED first: with the pass added, 8 previously invisible keys were unregistered
  (checked variables 128 -> 140).
- Registered all 8 with defaults read at the source, not guessed:
  CODESCRIBE_APPLE_DICTATION_TRANSCRIBER, CODESCRIBE_TAIL_PATCH_MAX_CHANGE_RATIO,
  CODESCRIBE_AGENT_MAX_TURN_ITERATIONS, CODESCRIBE_LICENSE_PUBLIC_KEY_HEX, and
  the four OpenAI/Anthropic OAuth client-id/issuer keys.
- Corrected the CODESCRIBE_LAYERED_TRANSCRIPTION registry description, which
  still claimed Layer 1 runs on the VAD path only — false since a6b1233 — and
  recorded that it is a power-user key a stale dotenv can arm silently.
- docs/env.md gains the DT gate and the Layer 1 safety threshold.

`.env.example` needs no change: the mirror check is one-directional (example
must be in the registry, not the reverse).

Authored-By: claude <agents@vetcoders.io>
- runtime already defaults CODESCRIBE_LAYERED_TRANSCRIPTION unset → phase1;
  AGENTS.md, STT_CONTRACT, WHISPER_LIVE, the ADR 2026-08-08 table, and the
  tail_patcher module table still said opt-in/off — aligned to the code
- THE_ENGINE_ROADMAP exec table no longer lists W13-2…6 as unstarted after
  settlement 13b1eed; §13 marks single-writer 75c89f5 done
- lbrx file-mode stays a U-WER bench, never a canvas replacement; next field
  cut is take-614 fusion A/B, then operator flips
- prettier on two W13 fixture docs so make check can see the aligned surfaces
- ENV_REGISTRY / docs/env.md alignment landed in the same tree via 230443f
  (peer scooped those two files mid-gate)

Authored-By: grok <agents@vetcoders.io>
…rmatting turns

- 26d0982 dropped the instructions PARAM on chained Responses requests to
  stop the HTTP 400 — but instructions do NOT persist server-side across
  previous_response_id (OpenAI contract), so every chained formatting turn
  ran with no system prompt at all
- live leak on build 661 (2026-08-14 12:06): gpt-5.4-nano answered the raw
  transcript as a chat assistant ("Jasne — oto to samo, przepisane
  czytelnie…" + a follow-up question) and that fiction shipped as the
  formatted lane; semantic guard flagged 0.746 and vetoed auto-paste only
- chained turns now re-carry the prompt as a leading developer input item;
  first turns keep the instructions param only (no duplicate); all three
  call sites (plain, inline chunk, streaming) share build_responses_input
- wire tests: chained request still has no instructions key AND carries the
  developer item; first turn carries neither duplicate

Authored-By: claude <agents@vetcoders.io>
…agent turns

- same promptless-chain class as 5d62aac, agent side: chained_instructions
  drops the instructions param (HTTP 400 pair) but the chain does NOT
  preserve instructions server-side, so every chained agent turn ran with
  no system prompt at all
- new build_request_input prepends the prompt as a leading developer input
  item on chained turns only; first turns keep the param (no duplicate);
  no prompt configured => no developer item
- corrected the lying doc comments (param contract vs server-side carry)
- test chained_turn_recarries_prompt_as_developer_item covers all three
  shapes; existing 400-regression test stays green

Authored-By: claude <agents@vetcoders.io>
…lero VAD probe

- CODESCRIBE_SEAL_ATLAS_DUMP=<path>: after the session-end seal pass the
  Apple-live worker writes every SealedSpan (PCM range, per-word pins,
  whisper_words, typed evidence) as JSON — the session's own final state,
  not a reconstruction; no env, no-op
- core/examples/vad_atlas_probe.rs: production Silero (embedded ONNX,
  default config) over a take WAV -> per-32ms speech probability + RMS/peak
  envelope on the same chunk grid, for overlaying seal-atlas word ranges
- core/examples/format_chain_probe.rs: 1:1 exhibit for the promptless-chain
  formatting leak — two format_text turns in one process, second chained

Verified on take 01 (60.1 s replay, live SFSpeech bridge): 11 sealed spans
dumped; 20/20 word-grain pins sit >=75% on Silero speech chunks; span 2
exposes a 41-chars-in-100ms clock lie (known unresolved-window family).

Authored-By: claude <agents@vetcoders.io>
…rsion after AUTO format

- finalizeTranscript and late applyFinalTranscript now arm the one-step
  revert slot when the shown FINAL came from auto formatting and differs
  from the raw assembly; before, only manual Format armed it, so an
  auto-formatted transcript was a one-way door (operator agreement
  2026-08-13, re-raised 2026-08-14)
- guards: no arm when Auto Format is off, when a manual slot is already
  held, or when shown == raw (nothing to revert to)
- tests: both arrival orders (authoritative-before-finalize and late) plus
  the Auto-Format-off negative; falsified against pre-fix code — same
  suite RED with 4 failures exactly in the new tests, GREEN 351/351 after

Authored-By: claude <agents@vetcoders.io>
…tead of hard-failing

- previous_response_not_found is key-scope poison, not retention: the id
  minted under a rotated-away Keychain key is invisible to the new key
  (measured 2026-08-12 22:31->23:02: three identical failures after the swap,
  transcript delivered raw; same-key chain proven alive hours later with
  full content recall on 2026-08-14)
- one-shot recovery in the retry loop: drop the stored response_id for THIS
  mode only and re-run the same attempt unchained (first-turn shape carries
  the system prompt via instructions - no promptless leak)
- retry loop converted to explicit counter so the recovery does not consume
  the (often zero) retry budget
- unit test pins the classifier to the provider error code alone

Authored-By: claude <agents@vetcoders.io>
…on path linearized

- seven lines (Apple live, VAD/scheduler, Layer-1 tail-patch, stop path,
  formatting LLM, assistive agent, file/cloud) as station-by-station maps
  with file::symbol anchors verified on HEAD
- seven named junctions (PCM clock, canvas, truth adjudication, postprocess,
  Responses chain, history, overlay delivery) with their contracts
- dashed-lines table: all six built-but-OFF flags with evidence and the
  measurement each flip still needs
- user-surface table: what each UI surface shows and which line feeds it

Authored-By: claude <agents@vetcoders.io>
…reaming ground truth

- new api_truth prompt section appended to BOTH composers (controller
  helpers + UniFFI bridge, both personas): /v1/responses wire shape,
  previous_response_id as durable server-side memory, the three measured
  sharp edges (pair-400, no prompt carry across chains, key/org-scoped ids),
  SSE event order, resp_stt cross-modal chaining, layered STT shape
- ANSWER-FIRST RULE: extract intent from rough spoken requests and answer
  substantively; at most one clarifying question; never numbered option
  menus (operator incident 2026-08-14: engine question got a questionnaire)
- anchor test pins the load-bearing facts through future edits

Authored-By: claude <agents@vetcoders.io>
…nto a let-chain

clippy collapsible_if (-D warnings) went RED on HEAD after 5f7755e and
blocked everyone's gates; edition-2024 let-chain restores green with
identical behavior.

Authored-By: claude <agents@vetcoders.io>
…s and endpoints live together

- operator directive 2026-08-14: three tiers (vendors with PINNED official
  endpoints + OAuth, custom compatible {endpoint,api-key} atomic rows,
  STT lanes ws/ndjson/file); lanes consume provider references, never URLs
- names the measured drift classes it closes: chain poisoning on key swap,
  dual auth identity per lane, slot asymmetry, contradictory settings surface
- invariants I1-I5 incl. chain state keyed by credential fingerprint with
  reset-on-write (self-heal 65e578e demoted to backstop)

Authored-By: claude <agents@vetcoders.io>
…ed audio

A first SFSpeech final that arrives after the 120 s retention horizon
poisoned the whole session: last_sealed_end only advances on a successful
resolve, so the [0..end_ts] window failed forever and Layer 1 received
zero Whisper windows for the entire take. Measured live 2026-08-14:
247 s take, first final at 156 s, 11/11 unresolved_windows, tail-patch
lane open but starved, WARN-only.

- clamp from to retained_start_secs when it fell off retention (that
  audio is committed canvas by definition); WARN receipt on every clamp
- genuine clock lies stay fail-closed: an end_ts that precedes the sealed
  canvas or overshoots the session still resolves to None (F3 contract)
- test seal_window_clamps_start_after_retention_eviction: falsified —
  RED with the clamp disabled, GREEN with it; module suite 34/34

Authored-By: claude <agents@vetcoders.io>
…le engine lifecycle

The product ships a "Hands-free silence" setting and the progressive lane
logged a WARN that it ignores it — on every single take. One monolithic
SFSpeech request ran for the whole session, so a take that is mostly
silence starved the engine: measured 2026-08-14, a 247 s take whose first
final arrived at 156 s went 11/11 unresolved windows and fed Layer 1
nothing.

The threshold now drives the engine lifecycle: speech opens an SFSpeech
epoch, silence past the threshold closes it (seal + finish), and the
engine rests while the mic and Silero keep watching. The next speech edge
wakes a fresh epoch with a 0.40 s pre-roll cut from retained audio.

- EpochGate + SpeechEdgeSource (own SpeechSession, independent of the
  CODESCRIBE_SILERO_FUSION experiment flag); Silero unavailable = fail
  open to one continuous stream
- shift_events: bridge timestamps are lifted onto the session PCM clock in
  ONE place, so seal windows, Layer 1 ranges and word pins keep speaking
  the same clock across epochs
- retention and fusion ingest keep running while the engine rests
- utterance_silence_sec unset = the pre-lifecycle worker, bit for bit
- tests: shift identity at base 0, shift onto session clock, sleep after
  threshold silence + wake with pre-roll, disarmed never sleeps; falsified
  (2 RED against stubs, 4/4 green after wiring); module 38/38, chunker
  15/15, clippy clean

Authored-By: claude <agents@vetcoders.io>
…ire-truth change and defuse a two-clock flake

- chunk_failure_is_fail_open_and_keeps_chain: the tail matcher pinned the
  OLD wire order (previous_response_id before instructions param); since
  5d62aac the closing prompt rides as a leading developer input item
  INSIDE input, which serializes before previous_response_id - matcher
  updated to the current truth and strengthened (developer item required)
- stop_seam settle waiter: 10s backstop raced the chunk request's own 10s
  budget under machine load (measured flake, chunk still Pending at the
  deadline); backstop moved out of reach to 30s and the three
  CODESCRIBE_INLINE_FORMAT_*_TIMEOUT_MS clocks pinned in the lane pin so
  the operator dotenv cannot recalibrate them under the tests
- stability: 5 consecutive green family runs post-fix (was ~1-in-3 red)

Authored-By: claude <agents@vetcoders.io>
…mary

- Wire TOGGLE_SILENCE_SEC onto hold as well as toggle so EpochGate actually
  rests SFSpeech on the daily-driver Fn/Globe path and Layer 1 can be fed
- Settings Layer 1 absent now matches core (unset → phase1); drop the
  "Experimental" lie that could persist off and starve the live tail-patch
- Replay inherits settings silence when set; product copy/docs/registry
  describe epoch rest/wake, not wav-VAD auto-send
- Name CODESCRIBE_VAD_* as dead folklore; register CODESCRIBE_SEAL_ATLAS_DUMP
- lbrx stays a U-WER bench; fusion stays OFF; do not crown candle

Authored-By: grok <agents@vetcoders.io>
… the canvas

Three walls stood between a computed recovery and the user's text. All
three were measured on the operator's own take (144425), 2026-08-14.

1. AUTHORITY GATE discarded richer truth. change_ratio>0.5 skipped the
   patch, and the under-commit escape needed 0.8 token coverage — which
   collapses exactly when Layer 0 mangles words, so the worse Apple heard
   the more certain the rejection. Live log: 295 change-ratio skips, 181
   (61%) carrying MORE material, 5341 characters discarded. Now the two
   fused decisions are split: placing into the canvas still needs trusted
   anchors, but a starved canvas (Whisper carrying ~3x) escalates to the
   stop path instead of the receipt. Divergence on a healthy canvas still
   skips; low agreement still never touches the live canvas.

2. LATE COMPLETIONS WERE ORPHANED. tail_patch_outcomes was drained only
   inside the seal tick, so a window finishing after its span sealed sat
   in the map forever: the patcher logged 2 residual_required recoveries
   while the session counted under_commit_escalations=0 and the UI got
   zero warnings. deliver_sealed_tail_patch now delivers those, sharing
   one emit path with the seal tick.

3. FUSION CANCELLED LAYER 1. With the lane armed, a rewrite refused by
   the sealed fence returned Skipped — throwing away the bounded patches
   Layer 1 had already computed for the same audio. It now falls back to
   them: fusion loses the race, the append lane still lands.

Measured effect on take 144425: escalations 0 -> 2, delivered text
171 -> 216 chars, "hard pruna" recovered correctly.

KNOWN DEFECT, not fixed here: recoveries can duplicate a phrase the
NEIGHBOURING utterance already carries (measured: 3 repeated 4-grams,
WER 0.463 -> 0.610 on this take). canvas_already_carries only sees the
patched utterance's own canvas; cross-utterance duplication needs the
neighbour context this seam does not receive. Do not ship before that.

Co-authored work: Silero edge unification, ledger->seal binding and the
atlas receipt landed in the same tree from a dispatched agent.

Authored-By: claude <agents@vetcoders.io>
…stop duplicate appends

Layer 1 sees one utterance at a time, so a phrase the canvas already holds
elsewhere reads as a gap and is appended a second time. Measured on the
operator's take the first run where recoveries reached the canvas at all:
three repeated 4-grams, WER 0.463 -> 0.610.

- TailPatchRequest carries neighbour_context (the sealed prefix); threaded
  through the lane into compute_tail_patch_with_context. The VAD lane has no
  sealed-prefix accumulator and passes empty, i.e. previous behaviour.
- canvas_already_carries matches a CONTIGUOUS run of DUPLICATE_RUN_TOKENS (4)
  on alignment keys, in the utterance's own canvas or the neighbour's. Full-run
  equality was defeated by the very defect it guards: one mangled edge word
  ('hard Pru' vs recovered 'hard pruna') and the duplicate lands anyway.
- classify_under_commit takes UnderCommitScan instead of growing an eighth
  positional argument (no new clippy silencer).
- test reproduces the measured duplication and pins both halves: blind call
  duplicates, context-aware call escalates and leaves the canvas byte-identical.

Gates: tail_patcher 31/31, streaming 162/162, clippy -D warnings clean.

STILL OPEN, measured this run: on take 144425 the duplicate comes from the
NEXT utterance, not a previous one — Whisper's window for a short utterance
carried speech Apple later assigned to the following final. A past-only
neighbour context cannot see it; the delivered text is unchanged (216 chars,
same three repeated 4-grams). Deduplication has to happen where the canvas is
complete (reducer/delivery) or the patch must wait for its neighbour. Not
shippable until that lands.

Authored-By: claude <agents@vetcoders.io>
…y delivered

Layer 1 computes a patch against the canvas as it stood when the job was
dispatched. SFSpeech can restate the SAME utterance at greater length in the
meantime and deliver those words itself; the patch then lands on the
restatement and duplicates the phrase.

Measured on take 144425: an append computed for a 15-char canvas landed on the
47-char restatement — three repeated 4-grams, WER 0.463 -> 0.610, i.e. the
recovery cost more than it gained.

The reducer is the last place that sees the canvas as it actually stands, so
the guard sits there: pure insertions (start == end) are dropped when the
committed text already carries a 4-token run of them, via the new public
 seam. Substitutions are untouched — they
replace the very span they would be compared against.

Replay of the same take: duplicate 4-grams 3 -> 0, WER 0.610 -> 0.439, and a
genuine gap fill still lands (pinned by the new reducer test).

HONEST LIMIT: on this take Whisper now contributes almost nothing to the LIVE
canvas (174 chars vs 171 without Layer 1) — most recoveries route to
residual_required, i.e. the stop path, which this harness does not measure.
The next measurement is delivered text after stop, not live_text.

Authored-By: claude <agents@vetcoders.io>
…t the live canvas

The harness printed live_text only, so every measurement this session
judged the during-hold canvas and called it the result. Layer 1 recoveries
that cannot be placed inline are escalated as residual_required — i.e.
explicitly owed to the stop path — and that path was invisible here.

First measurement with it visible, take 144425: DELIVERED == LIVE TEXT,
174 chars, byte-identical. The escalated recoveries add nothing.

Authored-By: claude <agents@vetcoders.io>
…he coverage bar

Hypothesis, after finding that escalation has no executor (stop path is
routing_off on this lane and composes its residual from session partials,
never from Layer 1): if the recovery cannot be escalated anywhere, place it
even on weak anchors and let the last-mile duplicate guard sort it out.

Measured across five takes, DELIVERED text vs the lbrx reference:

  take              OFF     ON      delta
  01_no-to-dobra    0.356   0.425   +0.068
  02_kubernetes     0.713   0.713    0.000
  03_algorytm       0.726   0.709   -0.017
  05_apple-parity   0.784   0.773   -0.010
  144425_loctree    0.439   0.439    0.000
  mean              0.604   0.612   +0.008

Rejected. Words placed beside an anchor the canvas cannot vouch for land in
the wrong part of the sentence more often than they fill a real gap, and the
duplicate guard cannot catch that — it catches repeats, not misplacement.
Reverted; the verdict is recorded where the bar is read so the next session
does not re-run it.

Two findings worth more than the experiment:
- Delivered WER against lbrx is 0.44-0.78 across these takes REGARDLESS of the
  flag. The gap is not in this gate.
- 05_apple-parity delivers 30 repeated 4-grams and 03_algorytm 6, with Layer 1
  patches barely involved — that duplication comes from the Apple lane's own
  restated finals, not from recovery. Unexamined.

Authored-By: claude <agents@vetcoders.io>
Copilot AI review requested due to automatic review settings August 14, 2026 19:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

- clear a fully re-heard Apple final instead of presenting the committed canvas as a volatile tail
- make SessionFinalised persist committed canvas and close the presentation emitter on the Apple path
- pin both production seams with regressions proven red before the runtime fix and green after it

Authored-By: Codex <agents@vetcoders.io>
- Merge the five-commit fusion authority series with cumulative-final duplication guards.
- Keep W13 fusion default OFF and align the lane docs with the engine roadmap.
- Remove process-env test races and capture restart-only idempotence per session.

Authored-By: Codex <agents@vetcoders.io>
- make Silero fusion default ON with explicit falsey off-switch tokens
- align the active lane map and env registry with the canonical transcript-lanes contract
- preserve race-free pure flag parsing and verify the full hermetic gate

Authored-By: Codex <agents@vetcoders.io>
- restore the original engine roadmap rule that default flips stay operator decisions
- keep the fusion implementation available behind an explicit truthy env value
- align the env registry and pin the unset-default behavior with a focused test

Authored-By: Codex <agents@vetcoders.io>
- clamp Apple callback timestamps to the captured sample clock before advancing the seal floor
- count tail patches only after the live worker accepts them and abandon orphaned stop-time work honestly
- pace the WAV channel replay through the production buffered-session helper

Authored-By: Codex <agents@vetcoders.io>
Copilot AI review requested due to automatic review settings August 14, 2026 23:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@div0-space
div0-space merged commit a06370a into develop Aug 19, 2026
4 checks passed
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.

3 participants