# Scenario label measurement: preserved candidate and source correction This is an **unwired, uncompiled experiment**, not an accepted renderer policy. Source base: `208268c8aa7f6bc3c2bab6a3c0657358f3f7dc23`. Parent's docs-only worktree HEAD: `75cb09dade2cf4b9a176b5e6159f43e2345d196e`. Only the two new `crates/oa-desktop/src/behavior/scenario_label` module/test paths and this evidence directory belong to this correction. ## Preserved attempt 1 `attempt1/scenario_label.rs` and `attempt1/tests.rs` are the exact raw files reviewed before correction. Both SHA256 values were checked before copying and again after copying; [manifest](attempt1/manifest.json) records source paths and hashes. They remain historical evidence, not alternate compiler inputs. Independent static review identified: 1. A retained Label Arc lacked its font epoch and zoom. Cached dimensions could be reused by painting/hit/navigation after their measurement context changed. 2. Iced's WGPU text cache omits font Version; remeasuring only this module cannot establish dynamic-font parity with an already-populated renderer cache. 3. The font-epoch test had already evicted its original entry with three variants in a capacity-two cache. Different Arc identity did not prove invalidation. 4. Finite scaled metrics could overflow when converted back to world units. Concrete example: size 2, Relative(MAX) line height, zoom 0.5. These were source findings. Neither the old candidate nor the correction was compiled or executed by this worker; no failure/pass count is inferred. ## Corrected experimental seam `RenderSession::after_fonts_settled_and_renderer_reset()` explicitly records a caller-established settled-font rendering lifetime. It does not reset or inspect the renderer. The caller must finish font loading and create a fresh renderer cache, then prohibit font changes between resolution, guarded consumption and draw. A changed global font Version rejects the old session; a new local cache alone is not a repair for WGPU's old glyph buffers. Labels record that session identity/font Version and measured zoom. Displayed text, retained-source bytes, bounds, field retention and canvas Text construction use checked accessors. Another session, another zoom or a detected font change rejects a retained artifact. Returned raw Text/bounds must be consumed in that checked context: holding those values across context changes bypasses the guard. This is an explicit limited contract, not atomic protection against a concurrent font load or an incorrect renderer transform supplied by the caller. Finite world line metrics are checked before shaping. Actual measured dimensions are checked again after division by zoom. The existing 64KiB source and 4096 grapheme budgets remain explicit experiment errors, not adopted product limits. Ten test candidates now include separate resident-entry font-epoch invalidation, fresh-session invalidation, stale artifact rejection for every consumer, and the overflow counterexample. The invalidation assertions require a still-resident entry, positive prior measurement count and an increased count afterward. These tests do not mutate the global font database or claim dynamic-font rendering acceptance. The existing actual Paragraph comparisons remain layout-metric oracles, not raster-ink/Scene collision evidence. ## Pinned primary APIs and remaining evaluator Cargo.lock pins iced_graphics/iced_wgpu 0.14.0 and iced_widget 0.14.2. Relevant local registry sources: `iced_wgpu-0.14.0/src/geometry.rs` (`fill_text`, scaled font metrics), `iced_wgpu-0.14.0/src/text.rs` (`Text::Cached` allocation), `iced_graphics-0.14.0/src/text/cache.rs` (Key/hash lacks Version), and `iced_graphics-0.14.0/src/text.rs` (FontSystem::load_font/version). Independent reviewer confirmed `geometry.rs:306-360`, WGPU `text.rs:443-500` and its retained BufferCache at line 304 (trim at 435 only evicts unused entries), graphics `text/cache.rs:109-146`, and graphics `compositor.rs:69`. The compositor's font-load path changes the global FontSystem, not the WGPU buffer cache. A check immediately before canvas_text is therefore not atomic with the later WGPU prepare; fonts must remain unchanged for the entire session. The module remains undeclared in behavior.rs. Parent may separately add test-only `#[cfg(test)] mod scenario_label;` and run: ``` cargo test -p oa-desktop --locked --offline behavior::scenario_label::tests:: -- --test-threads=1 ``` Expected selection is exactly ten tests, not a claim they pass. Corridors remain external; ordinary/reversed and self-message positioning is not selected here. The bounded prefix search guarantees measured fit, not a globally maximal prefix for all contextual shaping. No wrapping, row-height change, public schema or production gesture is introduced. Real WGPU label ink, activation shoulders, clipping, viewport transforms, and actual navigation integration remain required before adopting the seam. Original fixed 32-grapheme/225-unit rendering is still unchanged for baseline comparison.