docs(mosaic): preserve static nested runtime and standard transition evidence

This commit is contained in:
fy59 2026-10-13 21:23:16 +02:00
parent 54392cc0de
commit c5f96a34e3
10 changed files with 990 additions and 0 deletions

View file

@ -472,3 +472,19 @@ uncommitted and unpublished, and readiness only permits requesting a separate
future authorization. No compositor/runtime authorization,
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
## Preserved static nested runtime handoff — experimental evidence
The [handoff and valid-grab report](design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md)
records PASS transfer/preflight and one unchanged-static-binary run, verdict
INCONCLUSIVE. Four genuine grabs and sampled E1/E2 Mosaic crossing pixels,
E1 visible/forbidden input and dismissal passed. E2 reached splith with mapped
popups and standard pixels, then a fixture root-window consistency predicate
rejected the old-to-cleared clip transition. Offline retained observations
support settled clip removal; standard A/B input, explicit child close/A survival
and final H2 restoration remain NOT TESTED. Raw runner/IPC exit1 and clean
compositor/client exits0 remain intact. No rerun or algorithm change; historical phase B
is preserved for publication by the E2 completion batch. Architecture UNDECIDED, STEP20C NEXT,
production multi-output NOT YET SUPPORTED; broader damage/generation/output/
effects/ABI/distribution gates remain open.

View file

@ -413,3 +413,19 @@ uncommitted and unpublished, and readiness only permits requesting a separate
future authorization. No compositor/runtime authorization,
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
## Preserved static nested runtime handoff — experimental evidence
The [handoff and valid-grab report](design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md)
records PASS transfer/preflight and one unchanged-static-binary run, verdict
INCONCLUSIVE. Four genuine grabs and sampled E1/E2 Mosaic crossing pixels,
E1 visible/forbidden input and dismissal passed. E2 reached splith with mapped
popups and standard pixels, then a fixture root-window consistency predicate
rejected the old-to-cleared clip transition. Offline retained observations
support settled clip removal; standard A/B input, explicit child close/A survival
and final H2 restoration remain NOT TESTED. Raw runner/IPC exit1 and clean
compositor/client exits0 remain intact. No rerun or algorithm change; historical phase B
is preserved for publication by the E2 completion batch. Architecture UNDECIDED, STEP20C NEXT,
production multi-output NOT YET SUPPORTED; broader damage/generation/output/
effects/ABI/distribution gates remain open.

View file

@ -331,3 +331,19 @@ uncommitted and unpublished, and readiness only permits requesting a separate
future authorization. No compositor/runtime authorization,
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
## Preserved static nested runtime handoff — experimental evidence
The [handoff and valid-grab report](design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md)
records PASS transfer/preflight and one unchanged-static-binary run, verdict
INCONCLUSIVE. Four genuine grabs and sampled E1/E2 Mosaic crossing pixels,
E1 visible/forbidden input and dismissal passed. E2 reached splith with mapped
popups and standard pixels, then a fixture root-window consistency predicate
rejected the old-to-cleared clip transition. Offline retained observations
support settled clip removal; standard A/B input, explicit child close/A survival
and final H2 restoration remain NOT TESTED. Raw runner/IPC exit1 and clean
compositor/client exits0 remain intact. No rerun or algorithm change; historical phase B
is preserved for publication by the E2 completion batch. Architecture UNDECIDED, STEP20C NEXT,
production multi-output NOT YET SUPPORTED; broader damage/generation/output/
effects/ABI/distribution gates remain open.

View file

@ -417,3 +417,19 @@ uncommitted and unpublished, and readiness only permits requesting a separate
future authorization. No compositor/runtime authorization,
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
## Preserved static nested runtime handoff — experimental evidence
The [handoff and valid-grab report](design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md)
records PASS transfer/preflight and one unchanged-static-binary run, verdict
INCONCLUSIVE. Four genuine grabs and sampled E1/E2 Mosaic crossing pixels,
E1 visible/forbidden input and dismissal passed. E2 reached splith with mapped
popups and standard pixels, then a fixture root-window consistency predicate
rejected the old-to-cleared clip transition. Offline retained observations
support settled clip removal; standard A/B input, explicit child close/A survival
and final H2 restoration remain NOT TESTED. Raw runner/IPC exit1 and clean
compositor/client exits0 remain intact. No rerun or algorithm change; historical phase B
is preserved for publication by the E2 completion batch. Architecture UNDECIDED, STEP20C NEXT,
production multi-output NOT YET SUPPORTED; broader damage/generation/output/
effects/ABI/distribution gates remain open.

View file

@ -0,0 +1,329 @@
# STEP20C static nested runtime handoff and valid-grab gate
EXPERIMENTAL / INCONCLUSIVE; sole runtime stopped on a fixture observation-window
predicate during standard return. Architecture UNDECIDED. The pre-execution
contract below is preserved; observed results and remaining untested gates follow.
Ticket: `SWAYFX_MOSAIC_STEP20C_RECEIPT_FREEZE_AND_STATIC_NESTED_RUNTIME_V1`.
Phase A is published at `54392cc0de7c8391c4f216cb83eee64be322ec72`, verified
on Forgejo and GitHub with a clean worktree. The historical phase B is preserved for publication by
`SWAYFX_MOSAIC_STEP20C_E2_COMPLETION_AND_PRIVATE_INTEGRATION_BATCH_V1`.
Pre-execution publication restrictions below describe the consumed historical
ticket; they do not authorize a replay. STEP20A DONE, STEP20B EXPERIMENTAL, STEP20C NEXT, STEP20D–G
PLANNED; production multi-output NOT YET SUPPORTED.
## Contract recorded before preparation or execution
Canonical [architecture](../ARCHITECTURE.md), [UX](../UX.md),
[limitations](../KNOWN_LIMITATIONS.md) and [roadmap](../ROADMAP.md) govern.
The [accepted receipt-integrity gate](STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
qualifies offline receipts, not runtime. Its LAB
`/home/fy59/swayfx-mosaic-receipt-integrity-cof0umuk/` is read-only.
Verify all 76 source and 199 evidence entries, their fixed manifest hashes,
the accepted report/receipt hashes, 18 source bindings, 15 mandatory receipts,
the actual aggregate's five PASS markers and empty blocker list. Preserve B-01,
the initial CORRECTION_REQUIRED and final independent ACCEPTED separately.
The historical offline-gate lacks `fixture_sha256`; no historical runtime
fixture manifest exists. Its receipts must not be edited. A new transfer
receipt records exact source/destination copies and hashes, historical
acceptance scope, destination LAB and current ticket. Copy accepted receipts
under `accepted-offline/` without rewriting their embedded historical paths.
Retain their raw-byte and parsed-content bindings. The runtime offline-gate is
an explicitly derived transfer receipt, not a newly signed historical review.
Its fixture hash is computed from a real manifest after client preparation.
The [runtime fixture](../../tooling/probes/step20c-static-nested-runtime/README.md)
adds preparation, read-only preflight and single-use dispatch around the
unchanged reviewed runner and modules. Preserve exact copies in LAB/fixture;
historical acceptance covers their bytes, and an independent handoff reviewer
must separately accept the new transfer/authorization/dispatch code and final
manifest. Changes to reviewed runner/modules would expire continuity and
require independent delta acceptance before launch. No Mosaic/SceneFX algorithm
or production source modification is authorized.
## Immutable inventory and ownership
Create one fresh mode-0700 LAB outside Git, one exclusive durable owner registry
for this ticket, one fresh campaign-owner and a registration identifying ticket,
LAB, local UID, binary, binary/wlroots hashes and fixture manifest hash. Do not
reuse old owners or ledgers. Registry creation and launch consumption use
exclusive creation and file/directory fsync; a consumed launch is never refunded.
The existing ledger remains the action authority: run1, chain2, grab4, click9,
capture16, camera2, transition1, move24; maximum runtime150 seconds.
The fixture manifest contains exact runner/modules/scripts/patch/client sources,
protocols, prepared executables, immutable configuration template, accepted
receipt copies and referenced source/evidence manifest bytes. It excludes all
mutable budgets, logs, future PNGs/results, temporary files, authorization and
derived receipts containing the manifest hash, avoiding circular hashes.
Preflight checks excluded identity/authorization/transfer/review records through
explicit bindings. No manifest merely asserts a chosen hash.
Reuse static binary SHA256
`f82557c1a9978a5e9665b9b4291b74880253725359e3df1c5b8d554921f7603b`,
build ID `942db64269640778ee433e5970ba1100bc60f94c`, from the retained stage;
wlroots `/usr/lib/libwlroots-0.20.so` SHA256
`7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837`.
Verify ELF64/x86-64, mode0755, clipping symbols, no SceneFX DT_NEEDED, no
RPATH/RUNPATH and resolved relocations. Build only three historical C17 clients
using the byte-identical static_cross patch and protocol hashes. Copy their
client-build executables exclusively to the runner's LAB root paths; compare
hashes/modes and reject symlinks. No compositor/library rebuild or installation.
Authorization is explicit for this ticket and exact LAB, scope
`one-new-static-nested-headless-run`, with explicit_user_authorization=true,
owner_registry, binary, binary_sha256 and wlroots_sha256. The original
authorization.py is always called. Additional read-only preflight verifies
exact ticket, owner/UID, registration, immutable manifest and accepted review,
actual binary/wlroots/client identity and a completely unused ledger.
Offline negative tests must refuse every specified invalid authorization,
old/exhausted LAB, changed/missing manifest, unaccepted review and consumed run.
No socket, subprocess compositor or debit is allowed during those tests.
Only after independent handoff acceptance and all controls PASS may preflight
publish `STATIC_NESTED_RUNTIME_PREFLIGHT=PASS`. Dispatch then exclusively consumes
the ticket launch token and executes the frozen runner, which atomically debits
run before runtime creation. A failed launch consumes authorization permanently.
No second run, even after a fixture failure.
## Scientific run and stop rules
HEADLESS-1(-800,0), HEADLESS-2(0,0), each800×600, scale1, normal. Runtime0700,
private Wayland and explicit private swaymsg -s only; inherited desktop/loader
settings are removed. Record observed renderer/log/mappings; WLR_RENDERER=pixman
alone does not identify the actual SceneFX renderer. Historical controls are
read-only; no new pristine run. Reference H2 is a unique PID/AppID/con_id on
workspace2, targeted border none, full800×600 #303038; stored border width need
not be zero. Two full RGB captures after calibration, at least500ms apart,
must be identical. Stop dependent measurements on instability.
Each new E1/E2 owner has separately observed container/PID/workspace, applied
scene/content/titlebar, native420×320 SHM versus tiled destination, camera and
global clip[-800,0)×[0,600). At most one calculated camera correction per chain.
Never hardcode historical identities or adjust popup positions empirically.
Actual configure/ACK/map determines A and B geometry and both must cross x=0.
Open A with a real toplevel left-button serial and B with a fresh A serial;
require pre-map grabs and correct toplevel→A→B hierarchy and distinct serials.
E1 measures H1 popup retention, whole-H2 equality, owner-derived root/inherited
clip, visible B right press/release and forbidden H2 continuation right click.
Distinguish actual invisible delivery from legitimate topmost-first popup_done
and child-first destruction; record H2 reference callbacks and residual pixels.
Close E1 normally and never reuse destroyed objects.
E2 uses a fresh process/objects/serials in the same compositor. Open both grabs
under Mosaic, then targeted owner layout splith without outside click. Require
same workspace, mapped owner/A/B, no premature dismissal, tiled/root/inherited
clip removal. Remeasure standard origin, A/B H2 pixels and full masks; H2 may
normally differ from the empty reference while popups overflow. Click B on H2,
close B explicitly, verify A survives, click A, close owner and require whole-H2
reference restoration. Preserve raw IPC/compositor/client exit codes and streams.
IPC exit1 is separable only after completed science, handled exit/compositor0,
clean client exits, no protocol/crash and no rescue masking earlier failure.
Stop on identity/isolation/protocol/serial/parent failure, absent/non-comparable
popup, unstable reference, demonstrated leak, standard regression/residual clip,
crash or budget limit. Fixture failures are INCONCLUSIVE; demonstrated product
defects BLOCKED. No retry or algorithm repair is authorized. Available damage
extents qualify only measured intervals: no all-frame/minimal-damage/native-PNG
buffer/atomic-generation claim. Hidden owner, scale/rotation/migration/effects/
saved buffers remain separate gates.
## Closeout requirements
Retain exact runner/clients/config, provenance/authorization/handoff/review,
preflight/budget, all measured geometry/protocol/serial/clip/pixel/input/lifecycle,
damage/terminal/cleanup/matrix/summary receipts, raw logs/IPC/PNGs and final
source/evidence manifests in LAB. Generated/binary/large files stay outside Git.
Document actual PASS/FAIL/NOT TESTED, raw codes and budget. A handoff failure
means runtime NOT_RUN and global INCONCLUSIVE. Otherwise apply the ticket's
FEASIBLE/PARTIALLY_FEASIBLE/INCONCLUSIVE/BLOCKED criteria. Architectural choice is
tested-matrix feasibility, requires-redesign, or UNDECIDED; no production gate
is closed by this isolated campaign. Phase B must remain uncommitted/unpublished.
## Preparation candidate correction, before independent acceptance
The first 19-test preflight suite had five harness errors: unchanged
model.require correctly raised Invalid(ValueError), but tests expected
AssertionError. Its FAIL receipt, logs, source candidate, manifest and original
registration are preserved separately. Only new test exception expectations
are corrected; no historical reviewed module changes. The same LAB and zero
ledger remain in place. The original exclusive registration is immutable.
A single exclusive/fsynced registration-amendment explicitly binds its hash,
superseded fixture hash, final fixture hash and unchanged ticket/LAB/UID/owner/
binary identities. Handoff, authorization and new independent acceptance bind
both registration hashes separately. No budget/owner/token reset occurs.
The first candidate has no independent acceptance; its invalidated manifest
cannot authorize runtime. Only the reviewed final candidate can pass preflight.
## Executed handoff and authorization
New LAB: `/home/fy59/swayfx-mosaic-static-nested-runtime-pvn0osxm/`.
The initial preparation FAIL (19 tests, five harness errors) remains in
`candidate-v1/` and raw logs. The corrected suite passed 19 tests in8.008s;
the independent reviewer separately ran all19 PASS. Original registration
SHA256 `4a60089a548df2f9f2210e58e8fe23459104ff0002a01f6735a98d6f26faf0bf`
remains intact. The exclusive amendment SHA256 is
`362ab64728ca359c700bf1755d91788be9508ba776f03c711eda5f7d03df4d84`.
No ledger, owner or consumed token was reset. Final runtime inventory has92
immutable entries, SHA256
`1982bcc27dcc1d567997554c77791f42e5edaf447ccc12c21aea7f25659bf566`.
The historical runner SHA256 remains
`4382f2c0ffc8a41a6a65aecfca72dff762ded528f667288d179acbb354a9fcc9`.
Independent handoff review `/root/handoff_review` (Sol/medium, isolated,
read-only) accepts final sources, transfers and bindings. Its exact report was
materialized by the parent without textual alteration, SHA256
`af04fa9979ee24b5f87cff70807d7d853d316dbafb8660d7e779c0798088684c`.
This review is separate from the historical offline ACCEPTED; neither signs
new graphical results. Original historical report/review/76-source/199-proof
manifest bytes were checked again after runtime and remain unchanged.
`STATIC_NESTED_RUNTIME_HANDOFF=PASS`
`STATIC_NESTED_RUNTIME_PREFLIGHT=PASS`
The complete reviewed preflight passed before any reservation, with all
counters zero and no run/socket. Dispatch consumed its exclusive ticket token,
then the unchanged runner reserved exactly one run. Post-run pure checks of
both original authorize() and strict preflight refuse `fresh-run-required`.
No second runner/compositor launch was attempted. The unused action allowance
does not permit another run or budget reimbursement.
## Observed binary, outputs and reference
The original and private copy remain SHA256 f82557c1…21f7603b, full hash above,
ELF64 x86-64, mode0755, expected build ID, both clipping definitions, no
SceneFX dynamic dependency or RPATH/RUNPATH and resolved relocations. Actual
process maps identify system `/usr/lib/libwlroots-0.20.so` with the expected
SHA256; pkg-config reports0.20.2. No dynamic SceneFX was loaded. The rendering
log observes Mesa EGL, AMD GL vendor, AMD Radeon780M radeonsi and successful
FX renderer shader initialization. The actual path is FX/GLES, not Pixman;
the requested environment variable alone was not treated as renderer evidence.
Outputs have the exact requested signed geometry, scale1/normal. H2 reference
is PID2051837, con_id7, workspace2 (workspace ID5), AppID
org.mosaic.StaticReference, border none, empty decoration and full800×600
window. Stored border width2 is legitimate. The targeted con_id command leaves
the H1 filler unaffected. Both full RGB references are uniform#303038 and
identical, zero changed pixels, capture starts834.619ms apart.
E1 owner con_id9/PID2051849 and E2 con_id10/PID2052030 occupy workspace1
(ID6) on H1. Each uses one computed correction -320, scroll480→160, scene
(-320,0,640,600), painted content origin(-318,25). Native SHM420×320 remains
distinct from configured tiled content636×573, border/titlebar translation and
paint. The global tiled and owner-derived root viewport is[-800,0)×[0,600).
## E1 and E2 Mosaic observations
| Measurement | E1 | E2 |
| --- | --- | --- |
| Root real left-button grab serial |33|91|
| Nested real left-button grab serial |42|100|
| Root configured local rectangle |100,80,350,170|100,80,350,170|
| Nested configured local rectangle |100,60,300,130|100,60,300,130|
| Root global rectangle |[-218,105,350,170]|[-218,105,350,170]|
| Nested global rectangle |[-118,165,300,130]|[-118,165,300,130]|
| H1 A/B exact color pixels |24080 /15340|24080 /15340|
| H2 A/B color pixels |0 /0|0 /0|
| Whole-H2 comparison |exact reference|exact reference|
Both levels actually cross x=0 in both chains. Client and WAYLAND_DEBUG records
confirm real serial provenance, pre-map grab, bufferless initial commit,
configure/ACK/attach/map and TOPLEVEL→A→B parent IDs. Four serials are distinct.
E2 is a fresh process/Wayland connection; repeated numeric protocol IDs belong
to separate connection namespaces and denote fresh objects, not reused E1
objects. Root trace is correlated with each actual owner and one live root;
B inherits through the preserved exact source hierarchy. No direct independent
child-clip instrumentation is invented.
E1 visible B right click at(-108,175), local(10,10), delivers serial51 press
and52 release, button273, only to B. Forbidden point(91,195) lies within B's
geometric continuation on H2. Neither popup receives a button; reference H2
receives the actual press/release serial62/63. popup_done and destruction occur
B then A. This is a legitimate outside dismissal, not an invisible popup hit.
E1's post-dismissal H2 is exactly restored; E1 toplevel closes normally with
child-first destruction. These are measured sampled outcomes, not universal
click-through semantics.
## Standard return, actual failure and offline analysis
E2 opens A/B under Mosaic and reaches targeted `[con_id=10] layout splith`,
IPC0/success true, without an outside click. The retained standard snapshot
has the same workspaceID6, layout splith, mapped/visible owner. A/B both remain
present in standard PNGs; no popup_done is recorded. Destruction occurs only
during terminal shutdown after the fixture stops.
The runner fails `root-window-state-consistent` in `root_clip()`. Its window
begins before the layout command is applied and contains both states of the
same root tree0x56292fbcc170:
| Trace ns | Applied observation |
| --- | --- |
|181923034904618|enabled1, clip_valid1, local clip(-482,-25,800,600), prior Mosaic state|
|181923236944243|enabled1, clip_valid0, clip(0,0,0,0), applied standard state|
The layout IPC response is ns181923035203192. Requiring an unchanged root
through this transition is an invalid fixture precondition. The raw failure,
runner exit1 and incomplete-measurements flag remain unchanged. This evidence
does not establish an atomic transaction-generation contract or demonstrate a
product clipping defect. No runner/binary/algorithm was repaired or rerun.
Separate offline reanalysis of the existing standard snapshot/logs/PNGs finds
content origin(-398,25), A[-298,105,350,170], B[-198,165,300,130], settled tiled
clip_valid0/layout1 and root clip_valid0. Exact A/B masks have3120/13260 pixels
on H2. These observations corroborate removal of the inherited boundary and
ordinary overflow; H2 reference equality is intentionally not required during
that overflow. They are labelled OFFLINE_REDERIVED, not a completed runner
standard gate. The parent collector initially used an incorrect PI_MOSAIC
trace name; its failed attempt is retained. Correct PI_SCENE parsing then
completed offline checks without modifying runtime evidence.
Standard B right click, explicit B close with A survival, standard A right
click, normal E2 close and final whole-H2 restoration are **NOT TESTED**.
Missing measurements cannot be filled by source inspection or clean shutdown.
Verdict remains **INCONCLUSIVE**, architecture **UNDECIDED**; static nested
continuity is demonstrated for the sampled Mosaic portion, not the complete
requested standard-input/close matrix. No algorithmic change is justified by
this fixture-window failure.
## Terminal codes, cleanup, budget and remaining limits
Actual runner/dispatch exit1; terminal swaymsg exit1, stdout empty, stderr
`Unable to receive IPC response`. The compositor log shows handled exit and
shutdown; compositor exit0. E1/E2/reference/filler/pointer exits are all0.
No protocol error, crash, watchdog or rescue was recorded. All six PIDs are
reaped, runtime `/tmp/msng-hnvg_4l5` removed, no private socket remains.
Scientific measurements were incomplete: terminal transport is **not** granted
the completed-science exception; `scientific_cleanup_pass=false` and
`transport_incident=false` stay intact despite successful process cleanup.
| Budget | Used | Limit |
| --- | ---: | ---: |
|compositor|1|1|
|XDG chains|2|2|
|grabs|4|4|
|complete clicks|6|9|
|PNG captures|13|16|
|camera corrections|2|2|
|splith transitions|1|1|
|positions|8|24|
|seconds|16.486893|150|
370 damage extents are retained with capture windows. They describe sampled
mapping/dismissal/return intervals only, not every frame, minimal damage,
native PNG buffer identity or atomic generation. Direct child clip trace,
hidden owner, scale/rotation, migration/resize, effects, saved buffers,
exhaustive ABI/graphics maintenance and distribution gates remain open.
No new pristine run was performed; retained controls keep their original scope.
All310 protected source/system/package/patch paths remain unchanged.
`SWAYFX_MOSAIC_STATIC_NESTED_RUNTIME_PROBE=INCONCLUSIVE`
`SWAYFX_MOSAIC_STEP20C_RECEIPT_FREEZE_AND_STATIC_NESTED_RUNTIME_V1=INCONCLUSIVE`
Smallest justified next gate: correct and independently validate the standard
transition observation-window predicate offline against these immutable traces,
then request a separate bounded authorization for still-unmeasured standard
A/B input, child close/survival and final H2 restoration. No current-ticket
rerun, production integration or UX decision follows.

View file

@ -0,0 +1,29 @@
# Static nested runtime handoff — EXPERIMENTAL
This preserved fixture belongs only to ticket
`SWAYFX_MOSAIC_STEP20C_RECEIPT_FREEZE_AND_STATIC_NESTED_RUNTIME_V1`.
Read the [pre-execution protocol](../../../docs/design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md).
The consumed runtime result is [INCONCLUSIVE](RESULTS.md); handoff and preflight
are PASS. Standard B/A input, explicit B close/A survival and final whole-H2
restoration remain NOT TESTED. The original pre-execution fixture and receipts
remain byte-identical in the LAB; these documentation status updates do not
modify the executed scripts or authorize another launch. STEP20C NEXT, architecture
UNDECIDED, production multi-output NOT YET SUPPORTED.
Preparation validates sealed offline evidence, preserves exact copies, builds
only C17 clients, verifies/copies the existing static binary, and creates one
new exclusive ticket-owned LAB/registry/ledger. The historical runner and its
modules are unchanged. A real immutable inventory protects runtime inputs;
mutable runtime output and circular derived hash records are excluded.
The original authorization gate is called by both the new read-only preflight
and the frozen runner. A separate handoff acceptance binds new dispatch code,
manifest and provenance; historical ACCEPTED is never reused to sign this code.
Preflight requires offline negative tests, binary/client identity, current ticket,
owner/UID, unused persistent budget and no prior runtime. Dispatch consumes a
durable exclusive ticket token before the runner's existing debit. Neither
failed launches nor failed actions are refunded. No second run is authorized.
Do not run any script from an old ticket/LAB. All outputs, clients, binaries,
PNGs, logs and sockets belong outside Git. No Mosaic/SceneFX build, production
change, package operation, daily IPC or desktop configuration is permitted.

View file

@ -0,0 +1,33 @@
# Preserved static nested runtime result — INCONCLUSIVE
See [the complete report](../../../docs/design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md)
for the preserved pre-execution contract, accepted handoff, real run, failure,
offline observations and limits. LAB:
`/home/fy59/swayfx-mosaic-static-nested-runtime-pvn0osxm/`.
Handoff PASS, preflight PASS, one static headless compositor launched. Four
genuine root/nested grabs, two real crossing chains, sampled Mosaic pixels and
E1 input/dismissal PASS. E2 reached splith and standard captures, then the
unchanged root consistency predicate rejected its transition window containing
old and cleared clip states. Runner exit1 and all raw evidence are retained.
Standard B/A input, explicit child close/A survival and final H2 restoration
were not executed. Separate offline reanalysis supports standard clip removal
and A/B overflow pixels; it does not complete missing runtime gates.
Used budgets: run1/1, chains2/2, grabs4/4, clicks6/9, captures13/16, camera2/2,
transition1/1, positions8/24;16.486893s/150s. All six owned processes exit0,
no protocol error/rescue/socket residue. Terminal IPC exit1 is retained and
does not qualify for the completed-measurements transport exception.
370 damage extents are partial observations. Renderer actually FX/GLES AMD,
not Pixman inferred from the environment.
Initial preparation test FAIL and corrected19 PASS, append-only registration
amendment and genuine independent handoff acceptance are retained. Historical
offline reviewed bytes and runtime runner/modules/binary are unchanged. This
post-run result file is outside the immutable runtime inventory and its handoff
acceptance; it is covered only by final documentation/evidence validation.
No retry, compositor/library build, install, production/package/patch/UX change
or daily IPC. Historical phase B is preserved for publication by the E2
completion batch, without changing its verdict or executed bytes. Architecture
UNDECIDED, STEP20C NEXT, production multi-output NOT YET SUPPORTED.

View file

@ -0,0 +1,318 @@
#!/usr/bin/env python3
"""Offline transfer and strict preflight around the unchanged historical gate.
WHY: offline acceptance does not authenticate missing runtime installation data.
CONTRACT: historical bytes remain read-only; only new transfer records are made.
INVARIANT: checks create no socket, process, runtime directory or budget debit.
"""
import ast
import hashlib
import json
import os
from pathlib import Path
import shutil
import stat
import subprocess
import sys
import tempfile
HERE = Path(__file__).resolve().parent
REPO = HERE.parents[2]
OLD_FIXTURE = REPO / 'tooling/probes/step20c-static-nested-geometry-replay'
OLD_LAB = Path('/home/fy59/swayfx-mosaic-receipt-integrity-cof0umuk')
TICKET = 'SWAYFX_MOSAIC_STEP20C_RECEIPT_FREEZE_AND_STATIC_NESTED_RUNTIME_V1'
REGISTRY = Path('/home/fy59/swayfx-mosaic-static-nested-runtime-v1.owner')
REGISTRATION = REGISTRY.with_suffix('.registration.json')
AMENDMENT = REGISTRY.with_suffix('.registration-amendment.json')
SPENT = REGISTRY.with_suffix('.launch-consumed.json')
BINARY = Path('/home/fy59/swayfx-mosaic-static-runtime-hm5kbdkt/stage-static/usr/bin/swayfx-mosaic')
BINARY_SHA = 'f82557c1a9978a5e9665b9b4291b74880253725359e3df1c5b8d554921f7603b'
BUILD_ID = '942db64269640778ee433e5970ba1100bc60f94c'
WLROOTS = Path('/usr/lib/libwlroots-0.20.so')
WLROOTS_SHA = '7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837'
SEALS = {'source-sha256.txt': (76, 'dbd96db3f19f6eb60fc8be13c62b1e71944a759b481d008a7825b3720cf525ce'),
'evidence-sha256.txt': (199, 'f00ca54e39bff031a5bda585ea52cfebe9239e71b4c7ee7dc5c41a930e1598b3')}
REPORT_SHA = '311af1fe694d1bde88884afa21ef16a4fe908d6cfa47b6cbed515d1a21fedc9e'
REVIEW_SHA = '4d8401978e69a6c54f2f6144ba06deff4952671bc8e1ae3008376ab6ffe01e09'
sys.path.insert(0, str(OLD_FIXTURE))
from authorization import authorize, MARKER
from ledger import LIMITS, valid
from support import environment, sha, verify
from write_results import REQUIRED, aggregate
from receipt_integrity import make_bindings
def need(ok, message):
if not ok:
raise ValueError(message)
def read(path):
return json.loads(Path(path).read_text())
def exclusive(path, data, mode=0o600):
"""File and parent fsync precede use; existing ownership is never overwritten."""
path = Path(path)
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, mode)
with os.fdopen(fd, 'w') as out:
out.write(data if isinstance(data, str) else json.dumps(data, indent=2) + '\n')
out.flush()
os.fsync(out.fileno())
fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
try:
os.fsync(fd)
finally:
os.close(fd)
def regular(path, mode=None):
path = Path(path)
info = path.lstat()
need(stat.S_ISREG(info.st_mode) and info.st_uid == os.getuid(), 'unsafe-owned-file: ' + str(path))
if mode is not None:
need(stat.S_IMODE(info.st_mode) == mode, 'file-mode: ' + str(path))
def accepted():
"""Revalidate real file-backed bindings with the actual accepted aggregate."""
manifests = {}
for name, (count, digest) in SEALS.items():
p = OLD_LAB / 'results' / name
need(sha(p) == digest, 'historical-manifest-identity')
observed = verify(p)
need(observed['entries'] == count, 'historical-manifest-count')
manifests[name] = observed
need(sha(OLD_LAB / 'independent-review.md') == REPORT_SHA, 'historical-report-identity')
need(sha(OLD_LAB / 'results/independent-review.json') == REVIEW_SHA, 'historical-review-identity')
evidence = {n: read(OLD_LAB / 'results' / (n + '.json')) for n in REQUIRED}
evidence['independent-review'] = read(OLD_LAB / 'results/independent-review.json')
bindings = make_bindings(evidence, {n: OLD_LAB / 'results' / (n + '.json') for n in REQUIRED})
need(bindings == read(OLD_LAB / 'results/review-bindings.json'), 'accepted-bindings')
for name, digest in bindings['source_delta'].items():
need(sha(OLD_FIXTURE / name) == sha(OLD_LAB / 'proposed-fixture' / name) == digest, 'accepted-source: ' + name)
gates = aggregate(evidence, sha, bindings)
need(gates['status'] == 'READY_FOR_NEW_RUNTIME' and not gates['blockers'] and
len(gates['markers']) == 5 and set(gates['markers'].values()) == {'PASS'}, 'accepted-aggregate')
ready = read(OLD_LAB / 'results/offline-gate.json')
need(ready['status'] == 'READY_FOR_NEW_RUNTIME' and ready['marker'] == MARKER and
ready['review_bindings'] == bindings and not ready['blockers'] and ready['markers'] == gates['markers'], 'historical-READY')
return dict(manifests=manifests, bindings=bindings, aggregate=gates,
report_sha256=REPORT_SHA, review_sha256=REVIEW_SHA, historical_lab=str(OLD_LAB))
def copy_exact(source, destination):
source, destination = Path(source), Path(destination)
need(source.is_file() and not source.is_symlink(), 'copy-source-regular')
with source.open('rb') as src, destination.open('xb') as dst:
shutil.copyfileobj(src, dst)
dst.flush()
os.fsync(dst.fileno())
destination.chmod(stat.S_IMODE(source.stat().st_mode))
need(sha(source) == sha(destination), 'copy-identity')
return dict(source=str(source), destination=str(destination), sha256=sha(source))
def run_command(lab, label, argv):
result = subprocess.run(list(map(str, argv)), env=environment(), capture_output=True, text=True, timeout=30)
exclusive(lab / 'raw' / (label + '.json'), dict(argv=list(map(str, argv)), exit_code=result.returncode,
stdout=result.stdout, stderr=result.stderr))
need(result.returncode == 0, 'preparation-command: ' + label)
return result.stdout
def prepare():
proof = accepted()
need(not REGISTRY.exists() and not REGISTRATION.exists() and not AMENDMENT.exists() and not SPENT.exists(), 'ticket-already-registered')
need(not BINARY.is_symlink() and sha(BINARY) == BINARY_SHA and
stat.S_IMODE(BINARY.stat().st_mode) == 0o755 and sha(WLROOTS) == WLROOTS_SHA, 'binary-and-wlroots-before-copy')
lab = Path(tempfile.mkdtemp(prefix='swayfx-mosaic-static-nested-runtime-', dir='/home/fy59'))
lab.chmod(0o700)
exclusive(REGISTRY, str(lab) + '\n')
print('LAB=' + str(lab), flush=True)
for name in ('results', 'raw', 'fixture', 'accepted-offline', 'handoff-source'):
(lab / name).mkdir()
exclusive(lab / 'campaign-owner', str(REGISTRY) + '\n')
transfers = []
# CONTRACT: copied receipts keep historical paths and scope byte-for-byte.
for n in REQUIRED:
transfers.append(copy_exact(OLD_LAB / 'results' / (n + '.json'), lab / 'accepted-offline' / (n + '.json')))
for n in ('offline-gate.json', 'runner-readiness.json', 'review-bindings.json', *SEALS):
transfers.append(copy_exact(OLD_LAB / 'results' / n, lab / 'accepted-offline' / n))
transfers.append(copy_exact(OLD_LAB / 'independent-review.md', lab / 'accepted-offline/independent-review.md'))
transfers.append(copy_exact(OLD_LAB / 'results/independent-review.json', lab / 'accepted-offline/independent-review.json'))
for name in proof['bindings']['source_delta']:
transfers.append(copy_exact(OLD_FIXTURE / name, lab / 'fixture' / name))
for p in sorted(HERE.iterdir()):
if p.is_file():
transfers.append(copy_exact(p, lab / 'handoff-source' / p.name))
copy_exact(REPO / 'docs/design/STEP20C_STATIC_NESTED_RUNTIME_HANDOFF_AND_VALID_GRAB.md', lab / 'protocol-before-run.md')
binary_copy = copy_exact(BINARY, lab / 'swayfx-mosaic')
elf = run_command(lab, 'binary-ELF', ['readelf', '-hW', '-nW', '-dW', lab / 'swayfx-mosaic'])
need('ELF64' in elf and 'Advanced Micro Devices X86-64' in elf and BUILD_ID in elf and
all(s not in elf for s in ('libscenefx', '(RPATH)', '(RUNPATH)')), 'ELF-contract')
symbols = run_command(lab, 'binary-symbols', ['nm', lab / 'swayfx-mosaic'])
need(all(' T ' + n in symbols for n in ('wlr_scene_tree_set_clip', 'wlr_scene_tree_get_clip')), 'clip-symbols')
loader = run_command(lab, 'binary-relocations', ['ldd', '-r', lab / 'swayfx-mosaic'])
need(all(s not in loader for s in ('undefined symbol', 'not found', 'libscenefx')) and
str(WLROOTS.resolve()) in loader, 'resolved-relocations')
exclusive(lab / 'results/binary-identity.json', dict(status='PASS', sha256=BINARY_SHA, build_id=BUILD_ID,
wlroots_sha256=WLROOTS_SHA, copy=binary_copy, mode='0755', ELF='ELF64 x86-64', SceneFX_dynamic=False))
from prepare_clients import prepare as prepare_clients
prepare_clients(lab)
clients = read(lab / 'results/client-provenance.json')
for name in ('nested-client', 'pointer-daemon', 'static-reference'):
installation = copy_exact(lab / 'client-build' / name, lab / name)
regular(lab / name, 0o755)
clients.setdefault('runtime_installation', []).append(installation)
# This is a new runtime build receipt, not one of the historical REQUIREDs.
(lab / 'results/client-provenance.json').write_text(json.dumps(clients, indent=2) + '\n')
tree = ast.parse((lab / 'fixture/run.py').read_text())
configs = [ast.literal_eval(n.value) for n in tree.body if isinstance(n, ast.Assign)
and any(isinstance(t, ast.Name) and t.id == 'config' for t in n.targets)]
need(len(configs) == 1, 'runner-config-constant')
exclusive(lab / 'headless-config-template', configs[0])
exclusive(lab / 'results/accepted-offline-provenance.json', proof)
# Freeze exact runtime inputs, including installed clients and binary, but
# never budgets/logs/future captures or circular manifest-bound records.
immutable = [p for root in ('fixture', 'handoff-source', 'accepted-offline', 'client-build')
for p in (lab / root).iterdir() if p.is_file()]
immutable += [lab / n for n in ('swayfx-mosaic', 'nested-client', 'pointer-daemon', 'static-reference',
'campaign-owner', 'headless-config-template', 'protocol-before-run.md')]
immutable += [lab / 'results' / n for n in ('accepted-offline-provenance.json', 'binary-identity.json', 'client-provenance.json')]
immutable += [OLD_FIXTURE / n for n in proof['bindings']['source_delta']]
immutable += [p for p in HERE.iterdir() if p.is_file()]
immutable += [REGISTRY, BINARY, WLROOTS.resolve()]
need(len(immutable) == len(set(immutable)), 'unique-freeze-paths')
for p in immutable:
need(not p.is_symlink(), 'freeze-no-symlink')
manifest = lab / 'results/fixture-freeze-sha256.txt'
exclusive(manifest, ''.join(sha(p) + ' ' + str(p) + '\n' for p in sorted(immutable)))
fixture = verify(manifest)
registration = dict(ticket=TICKET, lab=str(lab), uid=os.getuid(), owner_registry=str(REGISTRY),
binary=str(BINARY), binary_sha256=BINARY_SHA, wlroots_sha256=WLROOTS_SHA,
fixture_sha256=fixture['sha256'], non_reusable=True)
exclusive(REGISTRATION, registration)
copy_exact(REGISTRATION, lab / 'results/registration.json')
auth = dict(scope='one-new-static-nested-headless-run', explicit_user_authorization=True,
ticket=TICKET, registered_lab=str(lab), owner_registry=str(REGISTRY), binary=str(BINARY),
binary_sha256=BINARY_SHA, wlroots_sha256=WLROOTS_SHA, fixture_sha256=fixture['sha256'], uid=os.getuid(),
authorization_basis='User transmitted the exact current ticket; one private launch only.')
exclusive(lab / 'results/authorization.json', auth)
exclusive(lab / 'results/budget.json', dict(limits=LIMITS, used=dict.fromkeys(LIMITS, 0), events=[]))
transfer = dict(status='PREPARED_FOR_INDEPENDENT_REVIEW', ticket=TICKET, destination_lab=str(lab),
fixture=fixture, transfers=transfers, provenance_sha256=sha(lab / 'results/accepted-offline-provenance.json'),
registration_sha256=sha(REGISTRATION), authorization_sha256=sha(lab / 'results/authorization.json'),
historical_review_scope='FINAL_OFFLINE_RECEIPT_INTEGRITY; does not sign this transfer or dispatch')
exclusive(lab / 'results/runtime-handoff.json', transfer)
# WHY: this derived gate satisfies the runner with verified transfer data,
# while the original historical gate and ACCEPTED review are left intact.
exclusive(lab / 'results/offline-gate.json', dict(status='READY_FOR_NEW_RUNTIME', marker=MARKER,
fixture_sha256=fixture['sha256'], markers=proof['aggregate']['markers'], blockers=[],
scope='DERIVED_TRANSFER_OF_ACCEPTED_OFFLINE_EVIDENCE', historical_gate_sha256=sha(OLD_LAB / 'results/offline-gate.json'),
runtime_handoff_sha256=sha(lab / 'results/runtime-handoff.json')))
copy_exact(OLD_LAB / 'results/independent-review.json', lab / 'results/independent-review.json')
exclusive(lab / 'results/preparation.json', dict(status='PASS', lab=str(lab), fixture=fixture, run_reserved=False))
return lab
def preflight(lab, authorization, review=True):
"""Pure checks; review=False is only for offline tests and review preparation.
CONTRACT: dispatch always uses review=True. The original authorize() is
mandatory and runs before any ticket-owned action can be consumed.
"""
lab = Path(lab).resolve()
need(not sys.flags.optimize, 'assertions-required')
auth = authorize(lab, authorization)
need(auth['ticket'] == TICKET and auth['registered_lab'] == str(lab), 'current-ticket-and-lab')
need(lab.stat().st_uid == os.getuid() and stat.S_IMODE(lab.stat().st_mode) == 0o700, 'lab-local-owner-mode')
regular(REGISTRY, 0o600)
regular(REGISTRATION, 0o600)
regular(lab / 'campaign-owner', 0o600)
need(Path(auth['owner_registry']) == REGISTRY and REGISTRY.read_text().strip() == str(lab) and
(lab / 'campaign-owner').read_text().strip() == str(REGISTRY), 'exclusive-owner-identity')
need(not SPENT.exists() and not (lab / 'run').exists() and not (lab / 'run.lock').exists(), 'fresh-unconsumed-run')
need(not any(stat.S_ISSOCK(p.lstat().st_mode) for p in lab.rglob('*')), 'no-preexisting-sockets')
need(auth['binary'] == str(BINARY) and auth['binary_sha256'] == BINARY_SHA and
auth['wlroots_sha256'] == WLROOTS_SHA and auth['uid'] == os.getuid(), 'authorized-identities')
need(sha(BINARY) == sha(lab / 'swayfx-mosaic') == BINARY_SHA and sha(WLROOTS) == WLROOTS_SHA, 'actual-binary-wlroots')
regular(lab / 'swayfx-mosaic', 0o755)
fixture = verify(lab / 'results/fixture-freeze-sha256.txt')
registration = read(REGISTRATION)
expected = dict(ticket=TICKET, lab=str(lab), uid=os.getuid(), owner_registry=str(REGISTRY), binary=str(BINARY),
binary_sha256=BINARY_SHA, wlroots_sha256=WLROOTS_SHA, fixture_sha256=fixture['sha256'], non_reusable=True)
need(registration == read(lab / 'results/registration.json'), 'original-registration-copy')
if AMENDMENT.exists():
# WHY: a rejected preparation candidate is never silently accepted as
# final. CONTRACT: preserve original registration and append exactly one
# pre-runtime amendment; ownership and all budget counters are retained.
regular(AMENDMENT, 0o600)
amendment = read(AMENDMENT)
original_identity = {k: v for k, v in registration.items() if k != 'fixture_sha256'}
need(original_identity == {k: v for k, v in expected.items() if k != 'fixture_sha256'}, 'amendment-identity-unchanged')
need(amendment == dict(registration=expected, previous_registration_sha256=sha(REGISTRATION),
superseded_fixture_sha256=registration['fixture_sha256'], reason='pre-runtime test exception-class correction',
runtime_reserved=False, budget_reset=False), 'append-only-registration-amendment')
need(read(lab / 'results/registration-amendment.json') == amendment, 'amendment-copy')
else:
need(registration == expected, 'durable-registration-bindings')
need(auth['fixture_sha256'] == fixture['sha256'], 'authorization-fixture-binding')
proof = accepted()
need(read(lab / 'results/accepted-offline-provenance.json') == proof, 'accepted-offline-provenance')
handoff = read(lab / 'results/runtime-handoff.json')
need(handoff['ticket'] == TICKET and handoff['destination_lab'] == str(lab) and handoff['fixture'] == fixture and
handoff['registration_sha256'] == sha(REGISTRATION) and handoff['authorization_sha256'] == sha(authorization) and
handoff['provenance_sha256'] == sha(lab / 'results/accepted-offline-provenance.json'), 'handoff-bindings')
if AMENDMENT.exists():
need(handoff['registration_amendment_sha256'] == sha(AMENDMENT) and
auth['registration_amendment_sha256'] == sha(AMENDMENT), 'explicit-amendment-binding')
for item in handoff['transfers']:
need(sha(item['source']) == sha(item['destination']) == item['sha256'], 'exact-transfer: ' + item['source'])
gate = read(lab / 'results/offline-gate.json')
need(gate == dict(status='READY_FOR_NEW_RUNTIME', marker=MARKER, fixture_sha256=fixture['sha256'],
markers=proof['aggregate']['markers'], blockers=[], scope='DERIVED_TRANSFER_OF_ACCEPTED_OFFLINE_EVIDENCE',
historical_gate_sha256=sha(OLD_LAB / 'results/offline-gate.json'),
runtime_handoff_sha256=sha(lab / 'results/runtime-handoff.json')), 'derived-gate-bindings')
need(sha(lab / 'results/independent-review.json') == REVIEW_SHA, 'historical-review-copy')
need(read(lab / 'results/binary-identity.json')['status'] == 'PASS', 'binary-receipt')
clients = read(lab / 'results/client-provenance.json')
for item in clients['runtime_installation']:
name = Path(item['destination']).name
need(name in ('nested-client', 'pointer-daemon', 'static-reference') and
item['destination'] == str(lab / name) and item['source'] == str(lab / 'client-build' / name), 'client-installation-path')
regular(lab / name, 0o755)
need(sha(item['source']) == sha(item['destination']) == item['sha256'], 'client-installation-bytes')
need({Path(i['destination']).name for i in clients['runtime_installation']} ==
{'nested-client', 'pointer-daemon', 'static-reference'}, 'all-runtime-clients')
budget = valid(read(lab / 'results/budget.json'))
need(not any(budget['used'].values()) and not budget['events'], 'unused-ledger-required')
if review:
checks = read(lab / 'results/preflight-tests.json')
need(checks['status'] == 'PASS' and checks['tests'] >= 13 and checks['source_sha256'] == sha(HERE / 'tests_offline.py'), 'negative-preflight-tests')
reviewed = read(lab / 'results/handoff-review.json')
need(reviewed['status'] == 'ACCEPTED' and reviewed['independent'] is True and reviewed['read_only'] is True and
reviewed['scope'] == 'STATIC_NESTED_RUNTIME_HANDOFF' and reviewed['fixture_sha256'] == fixture['sha256'] and
reviewed['runtime_handoff_sha256'] == sha(lab / 'results/runtime-handoff.json') and
reviewed['authorization_sha256'] == sha(authorization) and reviewed['registration_sha256'] == sha(REGISTRATION), 'independent-handoff-acceptance')
need(reviewed['source_sha256'] == {p.name: sha(p) for p in HERE.iterdir() if p.is_file()}, 'reviewed-handoff-sources')
if AMENDMENT.exists():
need(reviewed['registration_amendment_sha256'] == sha(AMENDMENT), 'reviewed-registration-amendment')
need(sha(reviewed['report_file']) == reviewed['report_sha256'] and not reviewed['blockers'], 'handoff-review-report')
return dict(status='PASS', marker='STATIC_NESTED_RUNTIME_PREFLIGHT=PASS', fixture=fixture,
authorization='PASS', handoff='PASS' if review else 'PENDING_INDEPENDENT_REVIEW', run_reserved=False,
budget=budget, ticket=TICKET, lab=str(lab))
if __name__ == '__main__':
import argparse
p = argparse.ArgumentParser()
p.add_argument('action', choices=('prepare', 'preflight'))
p.add_argument('lab', nargs='?', type=Path)
a = p.parse_args()
if a.action == 'prepare':
prepare()
else:
result = preflight(a.lab, a.lab / 'results/authorization.json')
exclusive(a.lab / 'results/preflight.json', result)
print(result['marker'])

View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
"""One durable dispatch; never rebuild, retry, refund or reset.
WHY: a new directory must not reopen this ticket's single launch entitlement.
CONTRACT: full reviewed preflight precedes consumption; runner owns its ledger.
INVARIANT: even a dispatch/runner failure leaves the exclusive spent token.
"""
import json
import os
from pathlib import Path
import subprocess
import sys
from handoff import preflight, exclusive, REGISTRY, SPENT, TICKET, sha, environment
def launch(lab):
lab = Path(lab).resolve()
auth = lab / 'results/authorization.json'
result = preflight(lab, auth)
existing = json.loads((lab / 'results/preflight.json').read_text())
if existing != result:
raise ValueError('published-preflight-must-match')
# O_EXCL consumption also arbitrates concurrent dispatches. No action can
# execute if another dispatcher won, even before runner ledger locking.
exclusive(SPENT, dict(ticket=TICKET, lab=str(lab), uid=os.getuid(), owner_registry=str(REGISTRY),
fixture_sha256=result['fixture']['sha256'], authorization_sha256=sha(auth)))
env = environment()
for key in ('LD_DEBUG', 'LD_DEBUG_OUTPUT'):
env.pop(key, None)
argv = [sys.executable, str(lab / 'fixture/run.py'), str(lab), '--future-authorization', str(auth)]
with (lab / 'raw/runner.stdout').open('x') as out, (lab / 'raw/runner.stderr').open('x') as err:
proc = subprocess.run(argv, env=env, stdout=out, stderr=err)
exclusive(lab / 'results/dispatch.json', dict(argv=argv, exit_code=proc.returncode, launch_consumed=True,
runner_sha256=sha(lab / 'fixture/run.py')))
return proc.returncode
if __name__ == '__main__':
raise SystemExit(launch(Path(sys.argv[1])))

View file

@ -0,0 +1,178 @@
#!/usr/bin/env python3
"""File-backed authorization attacks and real ledger tests, never runtime.
CONTRACT: immutable LAB/historical files are never edited by negative tests.
Alternate records model received corrupt inputs; actual verification functions
still execute. Manifest attacks use real disposable files and real SHA checks.
"""
import copy
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
import handoff as h
LAB = None
class Gate(unittest.TestCase):
def auth_attack(self, key, value):
auth = h.read(LAB / 'results/authorization.json')
auth[key] = value
with tempfile.TemporaryDirectory(prefix='nested-auth-negative-') as tmp:
p = Path(tmp) / 'authorization.json'
p.write_text(json.dumps(auth))
with self.assertRaises((ValueError, AssertionError, OSError, KeyError)):
h.preflight(LAB, p, review=False)
def record_attack(self, name, change):
actual = h.read
def read(path):
value = actual(path)
if Path(path) == LAB / 'results' / name:
value = copy.deepcopy(value)
change(value)
return value
with patch.object(h, 'read', read):
with self.assertRaises((ValueError, AssertionError, OSError, KeyError)):
h.preflight(LAB, LAB / 'results/authorization.json', review=False)
def test_positive_real_preflight_without_review(self):
r = h.preflight(LAB, LAB / 'results/authorization.json', review=False)
self.assertEqual(r['handoff'], 'PENDING_INDEPENDENT_REVIEW')
self.assertFalse(r['run_reserved'])
def test_no_authorization(self):
with self.assertRaises(ValueError):
h.preflight(LAB, None, review=False)
def test_old_ticket(self):
self.auth_attack('ticket', 'SWAYFX_MOSAIC_STEP20C_NESTED_OFFLINE_FREEZE_AND_RECEIPT_INTEGRITY_V1')
def test_wrong_lab(self):
self.auth_attack('registered_lab', str(h.OLD_LAB))
def test_exhausted_historical_lab(self):
auth = h.read(LAB / 'results/authorization.json')
old = Path('/home/fy59/swayfx-mosaic-static-nested-grab-m0a5e2qh')
auth['registered_lab'] = str(old)
with tempfile.TemporaryDirectory(prefix='nested-old-lab-negative-') as tmp:
p = Path(tmp) / 'authorization.json'
p.write_text(json.dumps(auth))
with self.assertRaises(ValueError):
h.preflight(old, p, review=False)
def test_wrong_owner(self):
self.auth_attack('owner_registry', '/tmp/nonexistent-old-campaign-owner')
def test_wrong_uid(self):
self.auth_attack('uid', h.os.getuid() + 1)
def test_wrong_binary(self):
self.auth_attack('binary', '/usr/bin/sway')
def test_wrong_binary_hash(self):
self.auth_attack('binary_sha256', '0' * 64)
def test_wrong_wlroots(self):
self.auth_attack('wlroots_sha256', '0' * 64)
def test_wrong_fixture_hash(self):
self.auth_attack('fixture_sha256', '0' * 64)
def test_review_not_accepted_original_gate(self):
# The unchanged authorize() reads the actual file-backed gate/review.
# Preserve original accepted bytes in an isolated negative-test LAB,
# then downgrade its review; no accepted review is invented.
with tempfile.TemporaryDirectory(prefix='nested-review-negative-') as tmp:
lab = Path(tmp)
(lab / 'results').mkdir()
auth = h.read(LAB / 'results/authorization.json')
auth['registered_lab'] = str(lab)
(lab / 'auth.json').write_text(json.dumps(auth))
(lab / 'results/offline-gate.json').write_bytes((LAB / 'results/offline-gate.json').read_bytes())
review = h.read(LAB / 'results/independent-review.json')
review['status'] = 'CORRECTION_REQUIRED'
(lab / 'results/independent-review.json').write_text(json.dumps(review))
with self.assertRaises(ValueError):
h.authorize(lab, lab / 'auth.json')
def test_offline_gate_not_ready_original_gate(self):
with tempfile.TemporaryDirectory(prefix='nested-ready-negative-') as tmp:
lab = Path(tmp)
(lab / 'results').mkdir()
auth = h.read(LAB / 'results/authorization.json')
auth['registered_lab'] = str(lab)
(lab / 'auth.json').write_text(json.dumps(auth))
gate = h.read(LAB / 'results/offline-gate.json')
gate['marker'] = 'INCONCLUSIVE'
(lab / 'results/offline-gate.json').write_text(json.dumps(gate))
(lab / 'results/independent-review.json').write_bytes((LAB / 'results/independent-review.json').read_bytes())
with self.assertRaises(ValueError):
h.authorize(lab, lab / 'auth.json')
def test_missing_manifest(self):
actual = h.verify
with tempfile.TemporaryDirectory(prefix='nested-manifest-negative-') as tmp:
missing = Path(tmp) / 'absent'
def verify(path):
return actual(missing if Path(path) == LAB / 'results/fixture-freeze-sha256.txt' else path)
with patch.object(h, 'verify', verify), self.assertRaises(OSError):
h.preflight(LAB, LAB / 'results/authorization.json', review=False)
def test_changed_manifest_entry(self):
actual = h.verify
with tempfile.TemporaryDirectory(prefix='nested-manifest-negative-') as tmp:
manifest = Path(tmp) / 'fixture-freeze-sha256.txt'
rows = (LAB / 'results/fixture-freeze-sha256.txt').read_text().splitlines(True)
rows[0] = '0' * 64 + rows[0][64:]
manifest.write_text(''.join(rows))
def verify(path):
return actual(manifest if Path(path) == LAB / 'results/fixture-freeze-sha256.txt' else path)
with patch.object(h, 'verify', verify), self.assertRaises(AssertionError):
h.preflight(LAB, LAB / 'results/authorization.json', review=False)
def test_run_already_consumed(self):
def consume(b):
b['used']['run'] = 1
b['events'] = [dict(seq=0, kind='run', ns=1)]
self.record_attack('budget.json', consume)
def test_dispatch_already_consumed(self):
with tempfile.TemporaryDirectory(prefix='nested-consumed-negative-') as tmp:
p = Path(tmp) / 'spent'
p.write_text('consumed')
with patch.object(h, 'SPENT', p), self.assertRaises(ValueError):
h.preflight(LAB, LAB / 'results/authorization.json', review=False)
def test_durable_exclusive_consumption(self):
with tempfile.TemporaryDirectory(prefix='nested-exclusive-test-') as tmp:
p = Path(tmp) / 'spent'
h.exclusive(p, dict(ticket=h.TICKET))
before = p.read_bytes()
with self.assertRaises(FileExistsError):
h.exclusive(p, dict(ticket='second'))
self.assertEqual(p.read_bytes(), before)
def test_ledger_exhaustion_and_atomic_bundle(self):
from ledger import initial_for_offline_test, reserve
with tempfile.TemporaryDirectory(prefix='geometry-ledger-test-') as tmp:
p = Path(tmp) / 'budget.json'
initial_for_offline_test(p)
reserve(p, 'run')
before = p.read_bytes()
with self.assertRaises(ValueError):
reserve(p, 'run', 'click')
self.assertEqual(p.read_bytes(), before)
self.assertEqual(h.valid(h.read(p))['used']['run'], 1)
if __name__ == '__main__':
import sys
LAB = Path(sys.argv[1]).resolve()
result = unittest.TextTestRunner(verbosity=2).run(unittest.defaultTestLoader.loadTestsFromTestCase(Gate))
h.exclusive(LAB / 'results/preflight-tests.json', dict(status='PASS' if result.wasSuccessful() else 'FAIL',
tests=result.testsRun, failures=len(result.failures), errors=len(result.errors),
source_sha256=h.sha(Path(__file__)), run_reserved=False, runtime_runs=0))
raise SystemExit(0 if result.wasSuccessful() else 1)