Two reviewers over the #1345/#1348/#1349 wave; no blockers, two
majors, several minors — all fixed.
- La16 was still billed at 4 B/px: the no-conversion special case
keyed on native_bpp == 4, which La16 also is — but only Rgba8 is a
real move in into_rgba8, so La16's decode peak is 8. The case now
keys on the color type, and a table test pins every layout's peak
(plus GIF's screen+frame 8) so the accounting can't silently drift.
- A control-routed open of a damaged-but-recoverable drawing parked
the operation behind the RecoveryPrompt modal (hang until the JS
timeout, silent drop if another op arrived, or false success when a
human declined). The open op now settles as failed with
recovery_required and the parse error; the prompt stays for humans,
automation can retry through the recovery flow.
- json_values_match: integers beyond f64 precision compared by value
(a u64 could round-trip-match a float); integral pairs now compare
exactly and mixed integer/float matches only when the float is whole
and equals the integer.
- A queued web open settles with the explicit queued marker whenever
the open slot was busy (the old name check made same-named in-flight
opens look completed with an empty result).
- ocs-control.js resolves with the API object reference, not
window.ocsControl (undefined if the bridge already existed when the
script ran); DATALINK on web says the typed path is superseded by
the picker instead of silently discarding it; the wipeout depth test
probes past the page background's rectangle; and the plot-path doc
comment names the function it actually mirrors.
Upstream issues, fixed:
#1345 — hatches plotted at draw_depth 0.0: the plot path cloned models
from the hatch cache, which bakes the depth at seed time; the canvas
re-reads the live depth map every frame, which is why the editor was
right and every export (PDF and native printing — both route through
the exporter) was wrong, with hatch-vs-hatch ties broken by HashMap
order. The plot path now re-reads the depth map per entity, and the
exporter's tie-break ranks follow the editor's own pass order
(hatch < image < wire fill < wire < text < wipeout) instead of pinning
hatches between fills and wires. Pinned by content-stream operator-
order tests (back/front hatches, overlapping hatches, interleaved
wire-between-hatches) and a scene test that fails pre-fix.
#1348 — set_properties' optimistic-concurrency compare now matches
numbers by value (10.0 == 10) through json_values_match, compatible
with the shape of upstream PR #1350; nested objects/arrays recurse.
#1349 — web automation contract: control protocol 2 (v1 clients still
accepted) adds {op:'open', name, data_base64} routed through the
guarded open queue; window.ocsControl.ready/request promise wrapper
with an ocs-ready event (web/ocs-control.js); the startup donation
prompt is suppressed once a control request is seen (opt-in pre-boot
via localStorage); docs/automation documents the whole web contract.
Also: DATALINK CSV-to-table works on web (picker + bytes through the
session registry — was std::fs, silently dead); COLORSCHEME accepts
System (prefers-color-scheme on web, AppsUseLightTheme on Windows).
Decode accounting, made honest per the fix-of-fix review: into_rgba8
allocates the RGBA destination while the native buffer is alive for
every non-Rgba8 layout (L8 5, La8 6, Rgb8 7, L16 6, La16 8 B/px
peaks — the formula now says so), GIF bills the screen+frame
coexistence at 8 B/px, and TIFF drops the 3x multipliers both ways —
tiff 0.11 splits the given budget between frame and scratch (a total
ceiling), so the old double-billing refused honest 16-bit GeoTIFFs
~2.25x early while admitting hostile chunk transients at 3x. The
image-refusal-unknown-size locale key moves to the group the catalog
always claimed (file).