148 lines
9.3 KiB
Markdown
148 lines
9.3 KiB
Markdown
# 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.
|
|
|
|
## 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):
|
|
|
|
```powershell
|
|
& ./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.
|