9.3 KiB
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 records source paths and
hashes. They remain historical evidence, not alternate compiler inputs.
Independent static review identified:
- A retained Label Arc lacked its font epoch and zoom. Cached dimensions could be reused by painting/hit/navigation after their measurement context changed.
- Iced's WGPU text cache omits font Version; remeasuring only this module cannot establish dynamic-font parity with an already-populated renderer cache.
- 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.
- 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.
Preserved attempt 2 and missing font-version branch
attempt2/ preserves both corrected raw source files and this note before the
follow-up, with exact SHA256 checks before and after copying. The root reviewer
found that local cache epoch invalidation and a fresh session identity did not
exercise an actual global font Version change. That specific branch was still
untested; the historical ten tests were not evidence for it.
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.
Eleven ordinary test candidates now include separate resident-entry font-epoch invalidation, fresh-session invalidation, stale artifact rejection for every consumer, and the overflow counterexample, plus finite world-position/rectangle-endpoint validation for bounds_at and canvas_text. This last check does not establish validity under arbitrary camera transforms or contain raster ink. The invalidation assertions require a still-resident entry, positive prior measurement count and an increased count afterward. These ordinary 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.
One additional ignored test, actual_font_load_rejects_retained_label_and_old_session,
must run alone in a fresh process. It resolves a label, extracts the actual
Iced-Icons font bytes that pinned Iced embeds in its global fontdb, independently
parses them into a fresh fontdb and confirms the expected family, then loads owned
valid bytes through actual FontSystem::load_font. Both a new face and a changed
Version must be observed. The old Label's five consumer accessors and old-session
Cache::resolve must return FontSetChanged; no new measurements may occur.
This is a valid duplicate-face load, not invalid input used merely to increment a version. It does not claim the selected face or visual metrics change, create a WGPU renderer, or test renderer recovery after dynamic loading. No font asset, system-specific font path, download, or new dependency is needed. Version mutation is not undone; dedicated process exit is the isolation boundary.
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
The normal filter selects twelve tests: eleven ordinary tests and one ignored
global-font test. This is an expected selection, not a claim they pass. Do not run
the whole desktop suite with --include-ignored to exercise the font test.
After the parent compiles and records a matching test executable, use the exact isolation runner (no Cargo invocation inside the runner):
& ./harness/experiments/scenario-label-measurement-20260913/run-font-version-test.ps1 `
-TestExecutable $desktopTestExe -ExpectedSha256 $expectedTestHash `
-RunDirectory $freshEvidenceDir
It verifies the supplied binary hash, lists exactly one ignored test, then starts a separate fresh executable process with:
--ignored --exact behavior::scenario_label::tests::actual_font_load_rejects_retained_label_and_old_session --nocapture --test-threads=1
The runner refuses an existing result directory and requires exactly one passing
test, preserving selection/output/receipt. Parent must provide the matching DLL
environment and source-to-binary provenance. Runner and tests are unexecuted.
It also accepts -TestName scenario_label::tests::actual_font_load_rejects_retained_label_and_old_session
for a parent-built standalone test wrapper importing the exact module at crate
root. That result must be reported as standalone Iced/module evidence, not desktop
or native integration. Wrapper, dependency artifacts and source hashes must be
bound separately by the compiler owner.
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.
Parent corridor candidate and isolated evaluator
The parent added scenario_label/corridor.rs: a bounded geometric candidate that subtracts padded blockers intersecting the full label band and selects the widest connected interval, with deterministic anchor/leftmost tie-breaking. It takes an explicit finite caller-supplied band; self/reversed corridor construction, actual Scene integration, font/ink clearance and release gesture policy remain unimplemented. Six unexecuted tests cover intermediate activations, unsorted overlapping blockers, complete-band intersections, ties, explicit self/reversed bands and invalid/overflow coordinates. This is an evaluation candidate, not an adopted paint policy.
attempt3 preserves both corrected raw label modules and the first raw corridor before scoped rustfmt. standalone.rs imports the actual three current source files without copying their implementation or wiring the desktop. Its expected listing is 18 tests: 17 ordinary and one ignored global-font mutation. Compiling/running that wrapper against explicitly identified pinned Iced/unicode dependencies is a standalone evaluator only; it does not establish desktop integration or WGPU/native acceptance. Use the font runner with the standalone exact test name documented above, in a separate process. No execution result is claimed by this prepared note; subsequent gate evidence will record actual results.