15 KiB
STEP20C saved target boundary crossing probe
EXPERIMENTAL / PARTIALLY_FEASIBLE, measured 2026-10-12. STEP20C remains NEXT and production multi-output Mosaic is NOT YET SUPPORTED. This is a new, independent campaign following the saved transaction buffer freeze, whose verdict remains INCONCLUSIVE. No Mosaic production, cumulative patch, package, UX or SceneFX algorithm change is authorized here.
Scientific identity and source path
The target is the XDG toplevel with app_id=org.mosaic.SavedBufferProbe.
Its Sway tiled container, borrowed workspace tiling row, view scene tree,
live content tree, temporary saved tree and saved scene buffer are distinct.
The source buffer of this view must be identified before the transaction.
An output buffer or optimized blur cache is never evidence for that source.
transaction_commit configures a changed-size visible view when
should_configure holds, then view_save_buffer creates a sibling saved tree
under view->scene_tree. view_save_buffer_iterator visits enabled live
buffers via wlr_scene_node_for_each_buffer, creates saved scene nodes via
wlr_scene_buffer_create, and calls wlr_scene_buffer_set_buffer with the
source buffer. Current live content is disabled and the saved tree enabled.
transaction_progress applies on readiness or handle_timeout; the normal
apply_container_state path calls view_remove_saved_buffer. SceneFX's
scene_node_intersect_clip intersects ancestral tree clips for visible/damage
regions and scene_node_point_inside_clip guards node-at; scene_entry_render
is the actual render-entry observation. This source path warrants a test, not
a clipping conclusion. The target node ID must be correlated from source to
saved creation to render entry and destruction. Parentage and enabled state
must be recorded. Pointer equality alone does not prove all GPU references
were released.
Geometry gate before reservation
Use only two normal scale-1 headless outputs: H1 (-800,0),800x600 and H2
(0,0),800x600. Map the deterministic C17 XDG client and ordinary reference
clients, settle focus, query actual outputs and workspace Mosaic state, and
measure the target source scene buffer: node pointer, source buffer
pointer, global node coordinates, destination width/height, source box,
transform, owner container/view, applied camera and tiled clip. A container
rect alone is insufficient. The previous runner issued relative
layout mosaic scroll 400 and reached applied scroll 1760, leaving its target
outside H1. Here desired_scroll is computed from the measured source buffer
left/right and applied current_scroll; issue exactly one signed
delta=desired_scroll-current_scroll, then remeasure. Require
left<0<right, preferably at least 64 logical pixels on each side, a visible
H1 intersection and a theoretical H2 intersection. The source must be
nonempty, have a tiled Mosaic ancestor clip, and remain stable after focus.
If any gate fails, stop that run before reserving an episode. Do not scan
camera positions or create a second lab to evade the budget.
The transaction trigger may alter pending dimensions. During the hold,
remeasure the saved scene buffer and require all of:
SAVED_TARGET_CREATED, SAVED_TARGET_ENABLED,
SAVED_TARGET_BUFFER_NONEMPTY, SAVED_TARGET_CROSSES_X0, and
SAVED_TARGET_RENDER_ENTRY_OBSERVED. Correlate exact view, owner, source
buffer and saved node. If the actual saved node does not cross, classify the
episode NOT EXERCISED even if another saved node renders.
Episodes, observations and bounds
Use pinned SwayFX 0.6 fd71a6bdc061bd633b488ae7b83e8a6981d22f86,
private Mosaic cd550382b311efdbfe3ed892f4e1d281d852e754, SceneFX 0.5
37ccd723bef49e6891156ffafce8f549f01446cc and wlroots 0.20.2.
Reapply the preserved clipping and trace patches without changing their bytes.
Any additional passive trace is a separate hashed private patch. Build and
run only in one disposable /tmp laboratory, with private 0700 runtime,
Wayland and Sway IPC sockets. -Dtxn-timeout=2500 is a lab policy only; source
parsing and equal use in comparable modes must be confirmed. Do not use
-Dtxn-wait, -Dnoatomic, direct save calls, compositor sleeps or altered
pending transaction counts.
At most one run each: C2 private Mosaic (priority), C0 pristine splith and C1
private splith. Each has at most two reserved episodes: E1 real configure
hold then latest-valid-serial ACK and commit before timeout; E2 a second real
hold until natural timeout with the client alive and pings serviced. The
ordinary gaps inner current set trigger is acceptable only when a changed
target configure and waiting instruction are observed. During E1 collect the
target saved node, render entry and minimal capture, then release promptly;
no six pointer injections during the hold. Observe applied transaction,
saved-tree removal and live-content return in both episodes.
Define H1 permitted and H2 forbidden regions before pixel analysis. Require
target SHM color on H1 while the saved node renders, no target color on H2,
and whole-H2 RGB equality against its reference; retain every difference.
Sample allowed and forbidden pointer points only if the hold window permits.
Distinguish wlr_scene_node_at, descriptor/surface association, seat notice
and client delivery; a saved scene buffer need not deliver clicks to the
held client. Record available damage around creation, activation, removal and
new live image, native commits/presents when traced, and do not infer every
intermediate frame from stabilized PNGs. Do not compare unrelated clocks.
Mapped-view destruction is NOT TESTED unless separately shown safe and within
budget. No rotation, scale, migration, resize, popup, effects or camera
hide/return pair belongs to this campaign.
The locked persistent ledger permits three runs, two episodes per mode, one calculated camera adjustment in the Mosaic run, at most 16 captures per run and 48 overall, and 150 seconds per run. Reserve before an episode; a failed reservation is consumed and never refunded. Preserve the exact runner copy, raw logs, outputs, captures, exit codes, structured JSON and SHA-256 source and evidence manifests. Offline ledger tests precede any run. Stop early on uncalibrated geometry, a noncrossing saved target, or an incident; preserve the facts and do not call placement error BLOCKED.
FEASIBLE requires correct target identity/crossing/render, permitted H1 pixels, no forbidden H2 pixels/hits, ACK and timeout cleanup and no blocking standard regression. PARTIALLY_FEASIBLE requires crossing and rendering with limited input, lifetime or damage evidence. INCONCLUSIVE covers absent target crossing/render or inseparable identities. BLOCKED requires a reproduced forbidden pixel/hit, lifetime defect, crash or blocking regression. Any unstudied matrix cell remains NOT TESTED. Neither an experimental success nor a compile qualifies STEP20C production.
Measured campaign and incidents
The independent LAB is /tmp/swayfx-mosaic-nested-grab-eVtLtpYd. Its private
passive geometry patch is target-geometry-trace.patch, SHA-256
7bbb27bc8617645e1acfd0589a410d470426363bd8a108bd43fc1006747f012e.
The old saved-buffer Sway and SceneFX trace patches retained their published
bytes. The private build used -Dtxn-timeout=2500 in all three modes; source
parses txn-timeout= into server.txn_timeout_ms, whose default is 200 ms.
All outputs were queried as H1 (-800,0),800x600 and H2 (0,0),800x600,
scale 1, normal. The target's workspace was ID 6 on H1, container ID 8,
view 0x55997bcb85b0; pointers identify objects only within this process.
Before correction the applied camera read 1760 and the actual source
scene buffer was [-1918,-1282) with 636×573 destination/source size,
normal transform and source box (0,0,636,573). The fixture computed
desired_scroll=160 and issued exactly one relative delta −1600.
Afterward get_tree read scroll 160 and the same source node/buffer at
[-318,318), y=25..598. H1's applied tiled scene was (-160,0) with clip
(160,0,800,600), equivalent to global x [-800,0). No subsequent focus
action moved the camera. The 318-pixel permitted and theoretical forbidden
horizontal portions exceed the 64-pixel preflight target. This run passed
source preflight before E1 reservation.
In E1, a genuine held configure (serial 50) followed a changed target size.
The target saved tree 0x55997bcecd00 was created under its view tree,
and target saved node 0x55997bd6a560 reused source buffer
0x55997bd4ec00. Its measured global box was [-318,318)×[25,598);
content_enabled=0, saved_enabled=1. The same node entered SB_RENDER
with global visible extent [-318,0)×[25,598) and damage extent in output
coordinates [(482,25),(800,598)). The held H1 capture contained 182,214
pixels of the target's prior SHM color (32,208,160); the H2 capture
contained zero of that color. The client ACKed the real serial 50 and
committed a new buffer before 2500 ms; the target saved tree was destroyed,
and the applied H1 capture contained the new target color. This is direct
partial saved-target crossing and render evidence, rather than evidence from
the other three saved nodes in the transaction.
Whole-H2 RGB comparison did not equal its reference during E1: 253 pixels
changed in [4,35,15,58). Each changed pixel went from (245,224,220) in
the reference to (48,48,56) in the held image. The same count, box and color
transition appeared in the new pristine control after timeout and both old
pristine/Mosaic final-timeout comparisons. It is consistent with a
reference-specific disappearing shape, but its cause is UNDECIDED. It is
not target SHM color, and this evidence does not establish a Mosaic leak.
The whole-H2 equality requirement nevertheless remains unmet.
E2 created a new saved buffer after E1's ACK, as the ordinary client commit
changed its source pointer. The new target snapshot was observed at
[-258,378)×[55,568), and its own node 0x55997bcea350 entered render
with visible extent [-258,-30)×[55,568). The executed runner still
compared that new pointer with the pre-E1 source pointer and stopped with
actual target saved buffer does not cross x=0. That error is misleading:
the trace proves crossing; the failed condition was stale buffer identity.
The runner was corrected locally to remeasure before each episode, but the
exact executed copy remains in runs/*/fixture-source.py. No Mosaic E2
capture or natural timeout was obtained; shutdown follows the fixture
exception. Do not treat this as a compositor timeout or clipping failure.
The run was not repeated and both episode reservations remain spent.
C0 (instrumented pristine SwayFX source, unmodified SceneFX behavior) and C1
(private standard splith) completed their held ACK and natural 2500 ms
timeout episodes, with saved-tree cleanup. Their standard tiling geometry is
not camera-equivalent to C2. Neither had target-color pixels on H2 during its
ACK hold. No blocking standard regression was demonstrated. The new C0 final
timeout image showed the same 253-pixel H2 difference; C1's H2 remained
identical throughout. C2's target input during hold, surface/client delivery,
complete damage and native buffer/texture release remain NOT TESTED or
unqualified. Mapped-view destruction, output changes, effects and intermediate
frames were outside the matrix.
The persistent ledger reads 3/3 runs, 6/6 episode reservations,
26/48 captures (C0 10, C1 10, C2 6), and 1/1 calculated Mosaic
camera adjustment. All run durations were below 150 seconds. No extra run or
camera retry is authorized. The raw runs, structured results, runner copies,
exit codes, build log and SHA-256 manifests are under the LAB. The result is
SWAYFX_MOSAIC_SAVED_BUFFER_TARGET_CROSSING_PROBE=PARTIALLY_FEASIBLE:
target crossing/render and permitted H1 pixels are established, while whole-H2
equality, input, full damage/lifetime and Mosaic target timeout cleanup are
unqualified. Architectural conclusion: UNDECIDED. No SceneFX algorithm or
production Mosaic correction is justified by a reproduced counterexample.
The final source manifest covers 913 entries (including the three private
source trees and fixture), SHA-256
816b55d94936fa32c7272845cd2f0514a55ad73b3cb04d32d442d5910e3da09b.
The evidence manifest covers 99 raw and derived entries, SHA-256
0ea45da93396810cf63c451f64d47101c4d4b8c7fb27900043494a0ec591096e.
Both passed entry-by-entry verification. They exclude the report itself, whose
wording was synchronized after the measurements.
Freeze audit: H2 reference and E2 clip (offline, no replay)
The exact executed runner is the manifest-covered fixture-source.py in each
run (SHA-256 51eb1274b757701e80f54004016944b7fa23f731d194193d1baabbe25a6cdc82).
The preserved local run.py differs: it remeasures TARGET_SOURCE before
each episode, so E2 no longer compares a post-ACK source buffer against the
pre-E1 pointer. This fixes the identified correlation condition in source;
the corrected runner was NOT EXECUTED in this exhausted campaign.
An offline full-RGB comparison of the old and new LABs found five nonempty
H2-reference differences: old pristine timeout-applied, old Mosaic
timeout-applied, new pristine timeout-applied, and new Mosaic ACK-held and
ACK-applied. Each has exactly 253 changed pixels filling the complete
rectangle [4,15)×[35,58) (11×23), with every pixel changing from
#F5E0DC (245,224,220) to #303038 (48,48,56). No other H2 pixel
differs in those comparisons, and none of the changed pixels is a target SHM
color. The corresponding new-reference-to-image capture-start intervals are
about 2.725 s for pristine timeout, 0.083 s for Mosaic ACK-held and 0.180 s
for Mosaic ACK-applied; the old pristine/Mosaic timeout intervals are about
1.455/1.476 s. Other sampled H2 pairs remained equal. These timings can
sample either phase of a blinking cursor; they do not prove a blink event.
The H2 reference process was Kitty with the fixture argument
background=#303038. The local ~/.config/kitty/kitty.conf and included
generated-appearance.conf predate these runs and contain cursor_shape block, a later cursor_blink_interval 0.5, and cursor color #f5e0dc.
The matching filled rectangle, exact colors and repeated pristine/Mosaic
observations strongly support a blinking Kitty block cursor as the cause.
The recorded logs do not capture Kitty's effective parsed configuration or
its cursor phase, so causal confirmation remains open. Whole-H2 RGB
equality remains historically unsatisfied; no pixels were masked or images
rewritten. The next lab must use a static reference.
The E2 saved target itself crossed x=0. Its render visible extent ended at
x=-30, matching the applied tiled Mosaic clip after E1's 30-pixel gaps:
H1 logged tile_scene=-130,30, local clip (160,0,740,540) and global
viewport [-770,-30)×[30,570). The source in transaction.c derives clip
width/height from output usable area minus current gaps. Thus the measured
right bound is explained by this outer tiled clip and gap geometry; it does
not establish an additional content/view clip. E2's timeout and cleanup
remain NOT TESTED because the fixture stopped before expiration.