test(mosaic): preserve reviewed native OOM and G2 diagnostic kits

This commit is contained in:
fy59 2026-10-15 09:29:13 +02:00
parent c0a822a079
commit bf00b0b0ed
62 changed files with 12458 additions and 21 deletions

2
.gitattributes vendored
View file

@ -4,3 +4,5 @@ tooling/probes/step20c-saved-target-timeout-input/target-hit-trace.patch -whites
tooling/probes/step20c-optimized-blur-cache/*.patch -whitespace
tooling/probes/step20c-targeted-diagnostic/saved-passive.patch -whitespace
tooling/probes/step20c-corec-v2/patches/*.patch -whitespace
tooling/probes/step20c-corec-v2/oom/patches/*.patch -whitespace
tooling/probes/step20c-corec-v2/gpu/*.patch -whitespace

View file

@ -22,3 +22,11 @@ The private c_args compatibility exception keeps -Wswitch warnings visible. GCC1
Verify readelf/nm/ldd-r, no SceneFX DT_NEEDED/RPATH/RUNPATH, exact wlroots SHA7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837 and actual factory binding from wlroots to the executable before runtime. Stage only Mosaic with `DESTDIR="$LAB/stage" meson install -C "$LAB/build-mosaic" --no-rebuild`; add the three exact pinned LICENSE texts and conservative INCORPORATED-NOTICES. Exactly binary0755 plus four notices0644 are allowed under the ticket paths. No symlinks, library or system package. LEGAL_NOT_APPROVED.
This recipe does not reserve a build/run or authorize bypassing budgets/publication/review. Every new build identity requires its own measured SHA/BuildID and reviewer receipt. Retained pristine is independently qualified, never built from these Mosaic sources. No compositor --version or live IPC is part of build validation.
## Separate diagnostic variants
OOM uses `python3 oom/assemble-variant.py --core "$ASSEMBLED" --destination "$OOM_SOURCES"` with an absent destination below /var/tmp. Its complete parent and result manifests are embedded in oom/provenance.json. Build the resulting scene/mosaic using the same private recipe, distinct directories and identity.
GPU uses `python3 gpu/reproduce.py --core "$ASSEMBLED/scene" --destination "$GPU_SCENE" --work "$GPU_WORK"`. Mosaic sources remain the exact CORE sources. For the private GPU SceneFX setup additionally use `-Dc_args=-D_XOPEN_SOURCE=700`; the initial build failure for an undeclared realpath prototype is preserved. This feature macro exposes the XSI declaration without suppressing type diagnostics or changing source. Every binary is separately qualified. The native acquisition root intentionally binds this diagnostic identity to /var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/acquisition. Rebinding it creates a new source and binary identity requiring new review, not a reuse of this candidate's native evidence.
The G2 client can be compiled without running it: generate client-header and private-code for gpu/protocols/xdg-shell.xml and wlr-layer-shell-unstable-v1.xml into an explicit private build directory. Name the headers xdg-shell-client.h and layer-shell-client.h. Compile gpu/clients-g2.c plus both generated protocol C files with `cc -std=c17 -O2 -Wall -Wextra -Werror -Wno-unused-parameter -I "$CLIENT_BUILD" ... -o "$CLIENT_BUILD/g2-client" $(pkg-config --cflags --libs wayland-client)`. Capture exact argv and SHA of inputs/outputs. Compilation alone grants no run admission.

View file

@ -187,3 +187,28 @@ is serial, within j<=8, and never exhausts real RAM. `gates.json` gives the smal
machine-readable source-only gate contract. Generated output remains private;
retain LAB for audit and do not automatically purge it. Publication and the
outer source-only bundle manifest are owned by the parent workflow after review.
## Reviewed diagnostic and prospective graphics supplements
`oom/` contains complete separately reviewed deltas and parent/result manifests;
`gpu/` contains the new, separately reviewed G2 instrumentation and a portable
source reconstruction helper. These diagnostics are distinct from the CORE
binary. `graphics/` contains the reviewed prospective P1/C8/O1/O2/G2 handlers;
all remain NOT_ADMITTED by default until per-case publication/binary/client and
independent review bindings pass. No source-only receipt grants a native run.
Always run the root `verify.py` on reconstructed CORE before variant helpers.
For G2 compare the complete reproduced tree, including modes, against the parent
manifest plus the three declared exact changed files. Its helper checks those
changed files and does not independently qualify an arbitrary parent. To syntax
check the GPU fx_pass body use test-targeted.py --core with the reconstructed GPU
target (the CORE argument shown in its historical CLI example instead checks the
CORE body). compile_commands supplies declared includes only; generated headers
must be prepared in an explicit private directory. See BUILD_RECIPE.md.
Small historical receipts under reviews/ and evidence/ retain the input paths
and status at their time of review. They are audit evidence, not executable
requirements for a vanished LAB. Source reconstruction requires only this Git
kit, pinned Git objects/public sources and declared tools. G2_ROOT is a declared
candidate-bound constant: changing it requires a new source/binary identity.
The surviving-source derivation never recovers historical lost bytes.

View file

@ -0,0 +1,143 @@
{
"schema": "G2-new-source-freeze-v1",
"status": "EXPERIMENTAL_SOURCE_ONLY",
"review": "PENDING_INDEPENDENT_R_GPU",
"runtime": "NOT_RUN",
"actual_gl_observability": "NOT_PROVEN",
"port": "PARTIAL: GLES3 RBO only; GLES2/texture attachments refused",
"metadata_offline": "PASS_CONTROLLED_ONLY",
"whole_field_causality": "NOT_PROVEN",
"present_buffer": "NOT_PROVEN",
"gpu_completion": "NOT_PROVEN",
"pair3_build": "NOT_RUN",
"new_gpu_acquisitions": 0,
"parent_scene_base": "37ccd723bef49e6891156ffafce8f549f01446cc + accepted CORE",
"parent_fx_pass_sha256": "398d594ace7257f4b69319290be7c1f14dc1ded446545ceb337404f5caab0cd3",
"parent_scene_tree": "e7d3fb7b4b76fcf1f9692981759e8070915c2072415a060351c4ff580c42eba1",
"target_scene_tree": "324b546ca85378cc48c4fe323d0e2f8e5e43687c6226de4267386adff5ff008f",
"mosaic_unchanged_tree": "514689ef65925d960acd5b424a10e30c1b7f004926e6fde5247c73ac427dfa91",
"drm_header": {
"path": "/usr/include/libdrm/drm_fourcc.h",
"sha256": "992f33804acda60b0b46f1a272942c3592484ea3217d469239f1cb12249de2eb"
},
"historical_controls": {
"status": "HISTORICAL_REPORTED_ONLY",
"sources": {
"tooling/probes/step20c-core-recovery/gpu-field/validate.py": "204ea3693eeedd61f9f83ca466fa224f5d4d495ab07c78936fd3a9a034ad3f67",
"tooling/probes/step20c-core-recovery/gpu-field/analysis.py": "5341909a7fa4010f52bfc909cd76f2288cfa5c4da9126b7258c47b4ad987fa3d",
"tooling/probes/step20c-optimized-blur-edge/clients.c": "cc913ff83ce20e430d17eda99504278c8cacafb56b81cb44d7bd99ad3f2cf31a"
}
},
"raw_plan": {
"epochs": 3,
"points_per_epoch": 10,
"physical_dimensions": [
800,
600
],
"bytes": 57600000,
"cap": 268435456
},
"capture_plan": {
"H2_baseline": 2,
"H1_H2_epoch_pairs": 3,
"total": 8,
"G2_cap": 16
},
"test_receipt": {
"path": "gpu-fifo-fix/gpu-targeted-tests-corrected.json",
"sha256": "fef54d91e087b3ac131e996200eba88245de0062865079c4337c5d5768b5886d"
},
"files": {
"gpu-kit/README.md": {
"sha256": "929f9c7c91849538a0d910f5448043e288c97dd532f8efe99d94ba9f19596f35",
"bytes": 8311
},
"gpu-kit/clients-g2.c": {
"sha256": "555b59d3e9b765a709d8740b62ebbc5f2de10ad093e34fd22daac0730d957bd3",
"bytes": 13270
},
"gpu-kit/freeze.py": {
"sha256": "7f52460ffa05db52ade985e6bde6f0525e536d09f808a8acc88c7166280687fa",
"bytes": 4112
},
"gpu-kit/g2-native.patch": {
"sha256": "77d7445ceaf643fd5cc708d31c3f2c77feaeb80f8130c419c55e5514ecc8a75d",
"bytes": 27014
},
"gpu-kit/g2_gl.h": {
"sha256": "cd175030be6a2e5d0af036c714c03455ef417f78f20360e00f7e6d1d7be7ab13",
"bytes": 6839
},
"gpu-kit/g2_native.h": {
"sha256": "0dfa9e089853a078094736da7f4e133d7fd648500d380dd7f536a7a6f80fdd8e",
"bytes": 17010
},
"gpu-kit/protocol.py": {
"sha256": "c1cb2b2876178d4f2308dc19bd2a9c3bd9666a684f4b85acc241572420c20496",
"bytes": 7960
},
"gpu-kit/protocols/wlr-layer-shell-unstable-v1.xml": {
"sha256": "996b8c66e1c2276c443336d4cb174634e8e5948823779042f244930525b79cc2",
"bytes": 18462
},
"gpu-kit/protocols/xdg-shell.xml": {
"sha256": "7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df",
"bytes": 63846
},
"gpu-kit/reproduce.py": {
"sha256": "b7849df36bbe0635c540245aa7a8b5c661f055ac6043c47ffe708590a450213c",
"bytes": 2145
},
"gpu-kit/scenario.py": {
"sha256": "a894a74d5b1a9c0378485f0291a8ae788a56bb33ab26665dc6cd033a9271c738",
"bytes": 5161
},
"gpu-kit/test-targeted.py": {
"sha256": "a629807ad31849d600e2a66f7718230da7e4fdbf52442c026e139fc9bf3ff907",
"bytes": 2628
},
"gpu-kit/test_fifo.py": {
"sha256": "a750d98ced8735e52cc3925facf9b68f124ca5451d72ceeb2fe4f0a4d1232274",
"bytes": 2203
},
"gpu-kit/test_gl.c": {
"sha256": "b29598ce74266a7fcec26eeebf26dc85c1dfa70bd437a0a0093e640a80149ed3",
"bytes": 5671
},
"gpu-kit/test_native.c": {
"sha256": "caa9b36831e1223508d1df8885ef287dbe14c92efd7be185efc349e181d46929",
"bytes": 3293
},
"gpu-kit/test_protocol.py": {
"sha256": "d211548d959836edd30256216d66a5d0557dffda0185e8b4c3c2260adce49521",
"bytes": 7378
},
"gpu-kit/validate_source.py": {
"sha256": "00ab0e5822be31dc0cbc9c32656ccad56fb4afc28155a421339616f3a5ce1dc0",
"bytes": 3705
},
"sources/scene-gpu/render/fx_renderer/fx_pass.c": {
"sha256": "c2886ef259fc91431dfe97841387082420ab80a0fe2f07e7dcdb71fc95731181",
"bytes": 49449
},
"sources/scene-gpu/render/fx_renderer/g2_gl.h": {
"sha256": "cd175030be6a2e5d0af036c714c03455ef417f78f20360e00f7e6d1d7be7ab13",
"bytes": 6839
},
"sources/scene-gpu/render/fx_renderer/g2_native.h": {
"sha256": "0dfa9e089853a078094736da7f4e133d7fd648500d380dd7f536a7a6f80fdd8e",
"bytes": 17010
},
"sources/scene-gpu/render/fx_renderer/shaders/blur1.frag": {
"sha256": "01664694e4201efb35ec698e89783e220ed930972b5396b86fa842814cd82d4d",
"bytes": 509,
"unchanged": true
},
"sources/scene-gpu/render/fx_renderer/shaders/blur2.frag": {
"sha256": "1db325237c9a6c70c2d97518e2f690d448cd006139e9f410cd16e097a1677ad1",
"bytes": 822,
"unchanged": true
}
}
}

View file

@ -0,0 +1,819 @@
{
"files": {
"README.md": "3148baa6c004d45cc151789652234cdd07fc961a166e799d0604c937ad6622fc",
"cases.py": "668230af8439e7cbe3b275a06dfd2d3f04e44cdcc133892a18e7d950fa2f0a8e",
"clients/fullscreen-client.c": "7c1a41875a5406b796c05695736e9f6d937d0fc87e8297b80fdccfdc34096605",
"clients/nested-client.c": "957f81886122256afd1dd5712185a021c08927899d3d7664041c64a366bc7438",
"clients/pointer-daemon.c": "8e4eaad95882d0d73866f801899007240b01cb6e15a712e820b3e3f71a78bbe5",
"clients/saved-client.c": "fb23512dea7b74b2ec7468a4e45d12d1a6ee83bf22f261a3d12e9c1077dda8f6",
"clients/static-reference.c": "e346a85ded3345b232cd6edca5a1ac57aebfd548a60e12b3c47a5cf515e6c50e",
"clients/vertical-client.c": "5f15adce7304839cc46150c0153a186724ea5f1f4f51b69aacf01a242a54e9db",
"engine.py": "af2e22687a58803a87d8a406f5d3f780a80194fa5c84595b2a0d98025862cece",
"evidence.py": "70c6bd58bf30c1cb8e4909aa7f2e8d71cbe4ad5ba49253ae94beff067151736a",
"freeze.py": "ff4372f3bedc41b1dae950ee58ca877ca602f24878020b443df72cd0daeece3e",
"fullscreen.py": "cc12e2636ca5facec5b05e56e0235f865c4c67b5d0714b816ca8a0363759b5a9",
"gate.py": "59d078db0701b80a453dd5971f21e5c6dd2e9f76c42d3d8865159cbd1c13c631",
"geometry.py": "76a80e98887d3a3707ee942b48a49c1850cdc4aeeb28237d9fea33fa3470fb12",
"gpu_handler.py": "78f93a9d067cd7f2f5dd40941c3deba955c1cddeb7131bc222208c3c26d4c58b",
"ipc_predicates.py": "5354ba53e1b3f8d0026f4475beebee58d093a81db7d26304cad7085ae3efd352",
"lifecycle.py": "df0c11027b3b8b0ef371ddb6ec4bcfd28dac09835644d0c3ce6e273d5e565e92",
"model.py": "a578fc589fb092dae3ccdcf8c4eec12a97e515f721decc4c968078dedcb2367a",
"offline/test_graphics_v2.py": "455d0297e2deaa14623561a0c893e6e84ea891c74decb38748ef04dbd90e598f",
"offline/test_prospective.py": "09231dfb0e91d693e062f6518b613cc9da6be7a8ecc4e60e2942d27066bc8640",
"oom.py": "7afc9bd27840bbc5b4a3c0eca96dba45d1b90d9a2975b72c897832ba06d9bb0a",
"oom_handler.py": "1ae766b759e58d8fcdc991fa64d3218d159d8a3b90825b7cba555c24aa4501a2",
"parent-provenance.json": "cd4a768a1c4cac81c4d102b7c37346060269b5d56a020c129bf79f31ec79ae80",
"pixels.py": "d315ddad978238ffbf1c8e4d712d4608ba23564703332d814f627f57f7b6e7f5",
"plans.py": "082ef1ecb16a7c4225008c030f9fa3e446837e9569dbf4fae910dab77d80c70b",
"predicates.py": "abe0c4c5b3b6d533d2714e13d317d68cd02e1f1c6180d2972ff94d00c9069cd1",
"prepare.py": "c43bf58bd8668758e101f8437470e820a94251f48536b8c73267b43904ebd21f",
"prepare_fullscreen.py": "eda437d6c4a8e3903e974ee118edcfd33de757e3afd931d35a4ce441c20cdc3d",
"protocols/wlr-virtual-pointer-unstable-v1.xml": "3ff6d540be0bc5228195bf072bde42117ea17945a5c2061add5d3cf97d6bb524",
"protocols/xdg-shell.xml": "7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df",
"run.py": "67b3a71c2ab0e8c5f5f807a3fab93b4aa08ba3d8895dd374d83ed49ded0c20b2",
"saved.py": "3838829f11f539971d0fdeeea44bf9658e9a0383aa228496d27678f06254d8a0",
"saved_validators.py": "b412fedc24869274c8b1506a2800c8d4815c93df859785c6e96f719d692014af",
"validate_offline.py": "ddbdc29fb151d7fe9b2e44e6614796aa2fbfc117b9b76aa34b2905257813fbe6",
"validators.py": "d8ae5e72ed507653e7631cda233bd6bdfd7f31a97f6d4fd6f53427437b28b054",
"wire-fixture.txt": "c6c9fc072f78fbcf9cfdeebcc5becdbdfb61824352495a0e767d7d390267f640"
},
"limits": {
"captures": 180,
"captures_per_run": 18,
"duration_s": 150,
"runs": 14
},
"plans": {
"C1": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 18,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C1",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C2": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 1,
"binary": "core",
"boundary": 600,
"capture_limit": 12,
"client": "vertical-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position 0 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 600\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C2",
"mode": "mosaic",
"outputs": [
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
600,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "v_both_cross"
},
"C3": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 12,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 1000x750 scale 1.25 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C3",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
1000,
750
],
"name": "HEADLESS-1",
"scale": 1.25,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C4": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 12,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 750x1000 scale 1.25 transform 90 position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C4",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
750,
1000
],
"name": "HEADLESS-1",
"scale": 1.25,
"transform": "90"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C5": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 12,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C5",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C6": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 12,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C6",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C7": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 14,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C7",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"C8": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 12,
"client": "fullscreen-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "C8",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "fullscreen_cross",
"reason": "No offline equal-child nonleaf fullscreen configure/crossing certificate; no empirical calibration authorized"
},
"G2": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"hook": 3,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "gpu",
"boundary": 0,
"capture_limit": 16,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "G2",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross",
"reason": "Separately reviewed diagnostic/discriminant source hook and exact binary unavailable"
},
"O1": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"hook": 1,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "oom",
"boundary": 0,
"capture_limit": 8,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "O1",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross",
"reason": "Separately reviewed diagnostic/discriminant source hook and exact binary unavailable"
},
"O2": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"hook": 1,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "oom",
"boundary": 0,
"capture_limit": 8,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "O2",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross",
"reason": "Separately reviewed diagnostic/discriminant source hook and exact binary unavailable"
},
"P0": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "PENDING_INDEPENDENT_REVIEW",
"axis": 0,
"binary": "pristine",
"boundary": 0,
"capture_limit": 10,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "P0",
"mode": "pristine",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross"
},
"P1": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "pristine",
"boundary": 0,
"capture_limit": 10,
"client": "fullscreen-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "P1",
"mode": "pristine",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "fullscreen_cross",
"reason": "No offline equal-child nonleaf fullscreen configure/crossing certificate; no empirical calibration authorized"
},
"R1": {
"action_limits": {
"camera": 6,
"chain": 2,
"click": 12,
"configuration": 70,
"grab": 4,
"move": 24,
"mutation": 26,
"spawn": 12
},
"admission": "NOT_ADMITTED",
"axis": 0,
"binary": "core",
"boundary": 0,
"capture_limit": 14,
"client": "nested-client",
"config": "output HEADLESS-1 resolution 800x600 scale 1 transform normal position -800 0\noutput HEADLESS-2 resolution 800x600 scale 1 transform normal position 0 0\nworkspace 1 output HEADLESS-1\nworkspace 2 output HEADLESS-2\nfocus_follows_mouse no\nseat seat0 hide_cursor 100\nshadows disable\nblur disable\n",
"id": "R1",
"mode": "mosaic",
"outputs": [
{
"logical": [
-800,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-1",
"scale": 1,
"transform": "normal"
},
{
"logical": [
0,
0,
800,
600
],
"mode": [
800,
600
],
"name": "HEADLESS-2",
"scale": 1,
"transform": "normal"
}
],
"placement": "static_cross",
"reason": "Separately reviewed diagnostic/discriminant source hook and exact binary unavailable"
}
},
"preflight": "PENDING_INDEPENDENT_REVIEW",
"real_reservations": 0,
"runtime": "NOT_RUN",
"schema": "graphics-v2-source-freeze",
"source_root": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-kit",
"ticket": "SWAYFX_MOSAIC_STEP20C_REBUILD_FROM_GIT_COREC_OOM_GPU_NIGHT_SHIFT_V1"
}

View file

@ -0,0 +1,86 @@
{
"schema": "corec-v2-oom-source-freeze-v1",
"identity": "COREC_V2_NATIVE_OOM_DIAGNOSTIC",
"status": "READY_FOR_INDEPENDENT_R_OOM_NOT_RUNTIME_ADMISSION",
"created_utc": "2026-10-15T05:58:14.328317+00:00",
"source_root": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit",
"files": {
"GRAPHICS_HANDLER_CONTRACT.md": "4590268e8bdd67214a80c7e3a0fa840ad14921b44bc55b3d3698207433016da8",
"README.md": "9d15adc03d66896b1ac5433a78274b02b2b1c0a9d598c30e7b550ebc61207244",
"assemble-variant.py": "13c8e72a23d005b5720a037fcbf4aa3678313b45158e6f16d3a647b20136895c",
"evidence/adapter-result.json": "f80e1e082ee69b352066170b10c2575065be4f60d2a0b5280f12625137f36c0d",
"evidence/bindings.json": "eebe8faa58f33d2d1570c6d1ad22d0591c3cf2592dc66b3ad2e72b83e6963dd4",
"evidence/result.json": "61c9ed452aac0e00ca7240bacbb4ed7fc0eb123ad52e74a57233f699426ea8e7",
"graphics-adapter.py": "9f22bab4f3f2d5f1bc702a1ca17ba753e703e7ff04b947a1774582993c68358d",
"patches/oom-mosaic.patch": "d9a255a9d6c1ca4aeb2c9b787daeb2d3e70a7e0ab040af211bb6c8c7720d77a2",
"patches/oom-scene.patch": "7981e55523eb9b66789a38655162dc81f3872a19629912522f51d6eeaa60dc3d",
"provenance.json": "0c253406d314591793f561333435431de8c03d38ee3dff997096f108617369fd",
"tests/extract.py": "6b9618c5cfbc41212d9dce53f4b803d2559d5e9abdb668b06f4a49f5d8099987",
"tests/ime-support.inc": "dd39d568e52af445a05a0ba9543a5717b1be3a62dd91f3af03cc8516e3d9b375",
"tests/offline-adapter.py": "e0881879d791511fbde15fb063b4b1b882a23bf924efd624e5d698d2d86ee737",
"tests/oom.c": "4fc85f8b11dd321cc3b1554a770244f96f10b4504e5435bc3baa9b5318cc28e6",
"tests/run.py": "8b4108d5327147363c274d0d6cc120915d938f3e9d31bb0f3aae1b3266c946ae",
"tests/transaction-support.inc": "fe58b77be6efa6b6f02676211988d00cbf8a5796656f6485b61af094d4aae7e0"
},
"source_digest": "bf53e28e6e71c2029e80f4ec616cfec9f09081121dae0b29205143a37a74e1f2",
"parent_review_sha256": "26aa862c741196fdbb8d7cdf5509301e49f763cdd22ffa7bcb1a4bbf09c66f90",
"parent_unchanged": true,
"components": {
"scene": {
"patch": "patches/oom-scene.patch",
"patch_sha256": "7981e55523eb9b66789a38655162dc81f3872a19629912522f51d6eeaa60dc3d",
"source_manifest_sha256": "6867919bf660c15e34893966402a0756ece9fa94f756db6f60b3a690c011f704",
"changed_files": [
"types/scene/oom-diagnostic.inc",
"types/scene/wlr_scene.c"
]
},
"mosaic": {
"patch": "patches/oom-mosaic.patch",
"patch_sha256": "d9a255a9d6c1ca4aeb2c9b787daeb2d3e70a7e0ab040af211bb6c8c7720d77a2",
"source_manifest_sha256": "5580346d00caf05fe09b85dd67ef98496ecbb6994b44a3d7908e174ac25fbaf9",
"changed_files": [
"sway/desktop/xdg_shell.c"
]
}
},
"evidence": {
"c_status": "PASS_BOUNDED",
"positive_runs": 27,
"mutants_compiled": 6,
"mutants_killed": 6,
"native_header_callsite": "PASS_SYNTAX_ONLY",
"adapter": "PASS_OFFLINE",
"exact_bindings_sha256": "eebe8faa58f33d2d1570c6d1ad22d0591c3cf2592dc66b3ad2e72b83e6963dd4",
"reproduction_receipt_sha256": "a7f3cf3d706edee3375ce77239c97a31dfa4d79a7228b2d00931093951eab315",
"mutation_oracles": {
"global_scope": "ordinary native factory must succeed; SIGABRT assertion b",
"after_publication": "exact single scene_tree_init moved before reserve; SIGABRT parent child list assertion before free",
"wrong_role": "nonmatching primary role must succeed; SIGABRT assertion b",
"token_reuse": "second matching call must succeed with failures1; SIGABRT assertion",
"malformed_accepted": "malformed token must not fail reservation; SIGABRT assertion b",
"nonce_ignored": "wrong nonce must not fail reservation; SIGABRT assertion b"
}
},
"gates": {
"R_OOM": "NOT_PROVEN_PENDING_INDEPENDENT_REVIEW",
"build_pair_2": "NOT_RUN",
"O1": "NOT_ADMITTED_NOT_RUN",
"O2": "NOT_ADMITTED_NOT_RUN",
"availability_policy": "UNDECIDED",
"complete_damage": "NOT_PROVEN",
"production_authorized": false
},
"limitations": [
"No complete SceneFX/Mosaic Meson build, compositor, Wayland client, IPC, GPU or native injection",
"Graphics adapter requires parent settled-handler/ledger integration and independent admission",
"Initial shell quoting compile failure preserved at oom-work/h1-extension-1; not counted mutant kill",
"Factory tests use exact source with reduced rendering/damage adapters; native stale sidecars/listeners and survival NOT_PROVEN"
],
"git_mutation": "NONE_BY_THIS_AGENT",
"supersedes_unreviewed_freeze": {
"sha256": "83450c97655064957caade4cf0235810edcfb66da875ea4cb6053b1bd334b250",
"reason": "test oracle strengthened only; native patches and source unchanged",
"archive": "results/oom-source-freeze-pre-oracle.json"
}
}

View file

@ -0,0 +1,152 @@
# G2 — nouveau diagnostic privé, sources seulement
EXPERIMENTAL / SOURCE-ONLY / revue indépendante requise. Aucun résultat G1
perdu n’est récupéré ni requalifié. Les nouvelles sources dérivent de
SceneFX 37ccd723bef49e6891156ffafce8f549f01446cc + CORE accepté. Les copies
`scene-core` et `mosaic-core`, les shaders, les calculs blur/sampler/clear/cache,
les kits graphics et les binaires CORE restent inchangés.
## Contenu et contrat
- `g2-native.patch` : nouveau delta contre `sources/scene-core`, trois fichiers
privés, aucun changement Meson, shader ou ABI publique.
- `g2_gl.h` : corps exact de lecture testé par FakeGL. Contexte EGL courant,
API et version réels ; ES3 confirmé par EGL ET GL avant tout enum ES3.
GLES2 et attachments texture sans dimensions sûres sont explicitement refusés.
RBO : objet attaché, dimensions/format/canaux/alpha/samples, completeness,
read buffer, viewport/scissor, bindings et pack/PBO sont observés.
- `g2_native.h` et `fx_pass.c` : source, down0/1/2, up2/1/0, cache optimisé,
copie sans blur, composition avant submit. Identités époque, nonce,
séquence locale de pass et clé offscreen de l’output. H1 est sélectionné
par le vrai `output->name == HEADLESS-1`, scale1 et transform normal lors de
`fx_render_pass_init_offscreen_buffers` ; jamais par les dimensions seules.
Les slots de passes sont retirés au submit ; réutilisation d’adresse remplacée,
plus de huit passes simultanées = refus explicite.
- `clients-g2.c` : adaptation nouvelle du client edge versionné. Background
uniquement sur commandes exactes `G2-A`, `G2-B`, `G2-A-return`, trois commits
maximum. Le premier payload A est retenu et recopié verbatim à A-return.
Configuration ACK sans dessin background. Motifs fixes RGB connus avant
acquisition ; l’alpha XRGB du payload n’est pas un sentinel de lecture.
SHM privé sous LAB/scratch, buffers immuables jusqu’au release, comptes
release/closure explicites ; RLIMIT_CORE=0 et PR_SET_DUMPABLE=0.
- `protocol.py` : framing/verificateur offline et armement exclusif, aucune
création de processus. `scenario.py` : scénario exécutable `run(session,
binding)` pour une Session du moteur commun liée séparément au nouveau G2.
Aucun lancement automatique à l’import. Le moteur commun n’est pas modifié.
- `validate_source.py` : adaptation bornée des contrôles gpu-field versionnés :
image plane0 FOURCC connu/stride approprié ; auxiliaire AMD/DCC distinct,
aucun image-stride appliqué au plan1, aucune taille DCC ou propriété FD
inventée. Header DRM SHA vérifié. Les exemples anciens restent
HISTORICAL_REPORTED_ONLY ; les fixtures contrôlées ne sont pas des allocations.
## Intrusion GL et limites
`glGetError` consomme une queue non restaurable. Chaque groupe de requêtes
et la lecture est suivi d’un drainage limité à16 codes ; erreurs préexistantes,
queue saturée, erreurs de requête/lecture/restauration refusent READ_SUCCESS.
Le hook restaure puis vérifie chaque binding/paramètre pack qu’il change,
ainsi que le contexte et l’état fonctionnel observé. Aucun glFinish, changement
shader/sampler/clear ou correction numérique. `glReadPixels` retourne void :
les CRC des fichiers et l’alpha ne constituent jamais une preuve de succès.
La lecture peut synchroniser et modifier le timing : diagnostic INTRUSIF.
Programme réellement lié et courant, location/type halfpixel, bits float bruts,
uniformes radius/proj/tex_proj, sampler et capacité mediump sont interrogés.
Les qualifiers et SHA des shaders portent explicitement la base
FROZEN_LINK_INPUT_SOURCE. La capacité n’est pas une mesure de chaque opération.
L’idéal CPU float32 est calculé séparément offline sans égalité, epsilon ajusté
ou fit sur mediump. Dimensions texture GL-level : NOT_PROVEN sur ce port ;
dimensions natives wlr sont conservées séparément. Attachments textures : refus.
Buffer physique présenté, lien au commit/present natif, lifetime et completion
GPU, génération atomique et causalité de tout le champ restent NOT_PROVEN.
Aucun de ces statuts n’est promu par compilation ou contrôles synthétiques.
## Protocole prospectif exact et bornes
Répertoire réel fixe :
`/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/acquisition`, UID courant,
mode0700, aucun lien symbolique. Variables : MOSAIC_G2_DIR (ce chemin exact),
MOSAIC_G2_NONCE (64 chiffres hexadécimaux minuscules).
`epoch-N.arm` doit être un fichier régulier mode0600, UID courant, lien unique,
contenant exactement `<nonce> <N>\n`. Le hook le consomme avant toute observation
par lien exclusif `.consumed`, vérifie l’inode, supprime `.arm` puis fsync.
Aucune réutilisation si `.consumed` existe, même après crash. Les fichiers raw
et JSONL sont exclusifs et fsync. Un rejet de premier A conserve les fichiers
existants et arrête B/A-return ; aucune boucle retry. Les dix readbacks sont
plein cadre physique800×600 RGBA8, soit19,200,000 octets par époque et57,600,000
au total planifié, avec multiplication contrôlée et plafond total256MiB.
Les régions Pixman fraîches sont conservées comme unions de rectangles natifs,
256 rectangles maximum ; hors-domaine frais conservé dans les raw plein cadre.
L’armement peut précéder le commit client ; un passage ancien est refusé par
un contrôle RGB natif exact du motif prospectif complet de l’époque, sans retry.
Le scénario règle le setup puis vérifie deux captures H2 stables avant A,
ensuite trois paires H1/H2, huit captures au total (cap G2 existant16).
Chaque époque est validée avant la commande suivante. Une anomalie H2 refuse
l’époque. Whole H1 A/A-return et H2 ne masquent aucun pixel et utilisent une
tolérance RGB nulle. L’égalité raw source A/A-return est rapportée séparément.
## Interface du parent, avant construction/acquisition G2
La revue R-GPU doit porter sur le gel exact et les logs offline. Le kit ne
crée pas de receipt d’acceptation et n’ouvre pas le ledger G2. La paire3,
le binaire distinct et les sources exactes doivent être liés par le parent
après revue, observabilité suffisante et décision explicite.
Le parent crée ensuite le répertoire fixe et un gate externe mode0600 avec
`source_review=ACCEPTED`, `gl_observability=PASS`, `runtime_authorized=true`,
`pair=3`, `binary_sha256=<nouveau SHA exact>`. `protocol.arm` le contrôle,
mais ne le produit jamais. Cette interface n’auto-autorise aucune acquisition.
`scenario.run(session, binding)` exige une Session G2 avec les outputs
horizontaux H1[-800,0,800,600] et H2[0,0,800,600], limites de capture/action
liées au nouveau diagnostic, identité binaire/librairies vérifiée par le moteur
commun, cleanup/watchdog du parent. `binding` contient : G2_ledger_reserved=True,
gate_file, binary, client, client_sha256, nonce, source_manifest_sha256.
L’autorisation/ledger du parent doit être scellée avant `session.start` ; elle
reste fermée avec les sources seules. Le scénario débite la mutation avant
jeton/commande, et le moteur débite spawns/captures/configuration. Les commandes
IPC utilisent exclusivement le socket explicite privé de Session.
## Reproduction portable offline
`reproduce.py` et `test-targeted.py` sont des CLI source-only portables. Ils
n’infèrent aucun LAB, build, arbre CORE ni répertoire de sortie. Fournir à chaque
appel les chemins explicites :
```sh
KIT=/chemin/vers/gpu-publication-kit
CORE=/chemin/vers/scene-core-reconstruit
CC=/chemin/vers/build-core/compile_commands.json
DEST=/chemin/vers/nouvelle-destination-scene-gpu
WORK=/chemin/vers/repertoire-de-travail-existant
python "$KIT/reproduce.py" --core "$CORE" --destination "$DEST" --work "$WORK"
python "$KIT/test-targeted.py" --core "$CORE" --compile-commands "$CC" --work "$WORK"
```
`CORE` doit être l’arbre SceneFX CORE reconstruit attendu, incluant le commit
SceneFX décrit ci-dessus et le CORE accepté. `DEST` doit être absent et
indépendant de CORE. `WORK` doit exister et rester un espace jetable pour les
logs, exécutables de test et reçus. `reproduce.py` copie CORE vers DEST, applique
`g2-native.patch` puis compare l’ensemble des fichiers modifiés au manifeste
d’empreintes embarqué dans le script. La vérification n’utilise aucun ancien
LAB, reçu ou arbre cible. `test-targeted.py` exige le `compile_commands.json`
associé au CORE fourni pour obtenir les includes nécessaires aux vérifications
de syntaxe; il ne reconstruit aucun compositor.
Les chemins `G2_ROOT` et les chemins d’acquisition déclarés dans le diagnostic
natif restent l’identité exacte de l’ancien LAB, par choix explicite du
diagnostic accepté. Cette recette portable ne rend donc pas ce binaire/configuration
transférable à un autre emplacement. Pour tout autre `G2_ROOT`, il faut une
nouvelle identité de diagnostic, un nouvel examen des sources et des reçus; ne
réutilisez pas silencieusement les sources natives ou leur autorisation.
Les tests utilisent C17, `-Werror`, limite core 0 et processus non dumpable. Le
test native lie uniquement les helpers utilisés avec dead-section removal;
FakeGL exécute le même corps `g2_read` que le hook natif. Ces vérifications ne
sont ni un build natif ni une exécution Wayland/GL/GPU. Statut de la revue
indépendante : PENDING. Runtime G2, vrai readback GL et vraie allocation DRM :
NOT RUN. Aucun sanitizer campaign, build pair, compositor, client Wayland ou
acquisition GPU n’est lancé par cette recette.

View file

@ -0,0 +1,338 @@
#define _POSIX_C_SOURCE 200809L
#include "layer-shell-client.h"
#include "xdg-shell-client.h"
#include <errno.h>
#include <poll.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <wayland-client.h>
#include <sys/resource.h>
#include <sys/prctl.h>
/* WHY: one persistent background supplies real A/B commits below blur_tree.
* CONTRACT: fixed opaque background, premultiplied ARGB glass and static H2.
* INVARIANT: no animation, synthetic configure, popup or held transaction. */
static struct wl_display *display;
static struct wl_compositor *compositor;
static struct wl_shm *shm;
static struct xdg_wm_base *wm;
static struct zwlr_layer_shell_v1 *shell;
static struct wl_output *h1;
static struct wl_surface *surface;
static struct xdg_surface *xdg;
static struct xdg_toplevel *top;
static struct zwlr_layer_surface_v1 *layer;
static const char *mode;
static int width = 420, height = 320;
static unsigned commits, live_buffers, released_buffers;
static char pattern = 'A';
/* G2 new explicit source command protocol; first A bytes retained verbatim. */
static unsigned char *source_a;
static size_t source_a_size;
static const char *source_command;
static uint32_t source_crc(const unsigned char *p,size_t n) {
uint32_t crc=~0u;
for(size_t i=0;i<n;i++) {crc^=p[i];for(int b=0;b<8;b++)crc=(crc>>1)^((0u-(crc&1u))&0xedb88320u);}
return ~crc;
}
static volatile sig_atomic_t running = 1;
struct pixels {
struct wl_buffer *buffer;
void *map;
size_t size;
struct pixels *next;
};
static struct pixels *buffers;
static long long stamp(void) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return (long long)t.tv_sec * 1000000000LL + t.tv_nsec;
}
static void free_pixels(struct pixels *p) {
struct pixels **it = &buffers;
while (*it && *it != p)
it = &(*it)->next;
if (*it)
*it = p->next;
wl_buffer_destroy(p->buffer);
munmap(p->map, p->size);
free(p);
--live_buffers;
}
static void release(void *data, struct wl_buffer *b) {
++released_buffers;
fprintf(stderr, "RELEASE ns=%lld buffer=%u\n", stamp(),
wl_proxy_get_id((struct wl_proxy *)b));
free_pixels(data);
}
static const struct wl_buffer_listener buffer_listener = {.release = release};
static void draw(void) {
/* CONTRACT: exactly one runner command per reserved A/B image.
* INVARIANT: configures cannot draw, and the sequence is A/B/A only. */
if (!strcmp(mode, "background") &&
(width != 800 || height != 600 || commits >= 3 ||
pattern != (commits == 1 ? 'B' : 'A')))
exit(2);
if (width <= 0 || height <= 0 || width > 4096 || height > 4096 ||
live_buffers >= 8)
exit(2);
size_t size = (size_t)width * (size_t)height * 4;
/* CONTRACT: each mapping stays immutable until native wl_buffer.release.
* Bounds keep pool/stride integers valid, with at most eight outstanding. */
char name[512];
const char *runtime = getenv("TMPDIR");
if (!runtime || strcmp(runtime,"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/scratch") || snprintf(name, sizeof(name), "%s/g2-shm-XXXXXX", runtime) >=
(int)sizeof(name))
exit(2);
int fd = mkstemp(name);
if (fd < 0)
exit(2);
unlink(name);
if (ftruncate(fd, (off_t)size) < 0)
exit(2);
struct pixels *p = calloc(1, sizeof(*p));
if (!p)
exit(2);
p->map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
p->size = size;
if (p->map == MAP_FAILED)
exit(2);
uint32_t *pixels = p->map;
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x) {
uint32_t color = 0x00303038;
if (!strcmp(mode, "background"))
color = pattern == 'A' ? (x / 8 % 2 ? 0x000f192d : 0x00f5f5f5)
: (x / 8 % 2 ? 0x00b02040 : 0x0020c0e0);
else if (!strcmp(mode, "glass"))
color = 0x88442010;
else if (!strcmp(mode, "filler"))
color = 0x00000000;
pixels[(size_t)y * (size_t)width + (size_t)x] = color;
}
if (!strcmp(mode,"background")) {
if (!commits) {
source_a=malloc(size);if(!source_a)exit(2);
memcpy(source_a,p->map,size);source_a_size=size;
} else if (commits==2) {
if(!source_a || source_a_size!=size)exit(2);
/* A-return is the preserved original payload, not a fitted redraw. */
memcpy(p->map,source_a,size);
} else if(source_a_size==size && !memcmp(source_a,p->map,size)) exit(2);
fprintf(stderr,"G2_SOURCE_BYTES command=%s bytes=%zu crc32=%08x exact_original=%s\n",
source_command,size,source_crc(p->map,size),commits==2?"true":"not-return");
}
struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, (int)size);
p->buffer = wl_shm_pool_create_buffer(
pool, 0, width, height, width * 4,
(!strcmp(mode, "glass") || !strcmp(mode, "filler"))
? WL_SHM_FORMAT_ARGB8888
: WL_SHM_FORMAT_XRGB8888);
p->next = buffers;
buffers = p;
++live_buffers;
wl_buffer_add_listener(p->buffer, &buffer_listener, p);
wl_surface_attach(surface, p->buffer, 0, 0);
wl_surface_damage_buffer(surface, 0, 0, width, height);
wl_surface_commit(surface);
fprintf(stderr,
"CLIENT_COMMIT ns=%lld mode=%s surface=%u buffer=%u index=%u "
"pattern=%c size=%dx%d damage=0,0,%d,%d\n",
stamp(), mode, wl_proxy_get_id((struct wl_proxy *)surface),
wl_proxy_get_id((struct wl_proxy *)p->buffer), ++commits, pattern,
width, height, width, height);
wl_shm_pool_destroy(pool);
close(fd);
}
static void ping(void *d, struct xdg_wm_base *b, uint32_t s) {
xdg_wm_base_pong(b, s);
}
static const struct xdg_wm_base_listener wm_listener = {.ping = ping};
static void top_configure(void *d, struct xdg_toplevel *t, int32_t w, int32_t h,
struct wl_array *a) {
if (w > 0)
width = w;
if (h > 0)
height = h;
}
static void top_close(void *d, struct xdg_toplevel *t) { running = 0; }
static const struct xdg_toplevel_listener top_listener = {
.configure = top_configure, .close = top_close};
static void configure(void *d, struct xdg_surface *s, uint32_t serial) {
xdg_surface_ack_configure(s, serial);
draw();
}
static const struct xdg_surface_listener xdg_listener = {.configure =
configure};
/* CONTRACT: configures ACK geometry, never submit an unreserved image.
* WHY: duplicate layer configures must not spend autonomous mutations.
* INVARIANT: the runner reserves then sends every A/B draw command. */
static void layer_configure(void *d, struct zwlr_layer_surface_v1 *s,
uint32_t serial, uint32_t w, uint32_t h) {
if (w == 0 || h == 0 || w > 4096 || h > 4096)
exit(2);
if (commits && ((int)w != width || (int)h != height))
exit(2);
width = (int)w;
height = (int)h;
zwlr_layer_surface_v1_ack_configure(s, serial);
fprintf(stderr, "BACKGROUND_CONFIGURED ns=%lld serial=%u size=%dx%d\n",
stamp(), serial, width, height);
}
static void layer_close(void *d, struct zwlr_layer_surface_v1 *s) {
running = 0;
}
static const struct zwlr_layer_surface_v1_listener layer_listener = {
.configure = layer_configure, .closed = layer_close};
static void output_name(void *d, struct wl_output *o, const char *name) {
if (!strcmp(name, "HEADLESS-1"))
h1 = o;
}
static void output_geometry(void *d, struct wl_output *o, int32_t x, int32_t y,
int32_t w, int32_t h, int32_t sp, const char *m,
const char *n, int32_t tr) {}
static void output_mode(void *d, struct wl_output *o, uint32_t flags, int32_t w,
int32_t h, int32_t refresh) {}
static void output_done(void *d, struct wl_output *o) {}
static void output_scale(void *d, struct wl_output *o, int32_t scale) {}
static void output_description(void *d, struct wl_output *o, const char *desc) {
}
static const struct wl_output_listener output_listener = {
.geometry = output_geometry,
.mode = output_mode,
.done = output_done,
.scale = output_scale,
.name = output_name,
.description = output_description};
static void global(void *d, struct wl_registry *r, uint32_t id,
const char *name, uint32_t v) {
if (!strcmp(name, "wl_compositor"))
compositor =
wl_registry_bind(r, id, &wl_compositor_interface, v < 4 ? v : 4);
else if (!strcmp(name, "wl_shm"))
shm = wl_registry_bind(r, id, &wl_shm_interface, 1);
else if (!strcmp(name, "xdg_wm_base"))
wm = wl_registry_bind(r, id, &xdg_wm_base_interface, v < 3 ? v : 3);
else if (!strcmp(name, "zwlr_layer_shell_v1"))
shell =
wl_registry_bind(r, id, &zwlr_layer_shell_v1_interface, v < 2 ? v : 2);
else if (!strcmp(name, "wl_output") && v >= 4) {
struct wl_output *o = wl_registry_bind(r, id, &wl_output_interface, 4);
wl_output_add_listener(o, &output_listener, NULL);
}
}
static void removed(void *d, struct wl_registry *r, uint32_t id) {}
static const struct wl_registry_listener registry_listener = {
.global = global, .global_remove = removed};
static void stop(int s) { running = 0; }
int main(int argc, char **argv) {
struct rlimit core_limit={0,0};
if(setrlimit(RLIMIT_CORE,&core_limit) || prctl(PR_SET_DUMPABLE,0))return 2;
if (argc != 2)
return 2;
mode = argv[1];
if (strcmp(mode, "background") && strcmp(mode, "glass") &&
strcmp(mode, "filler") && strcmp(mode, "reference"))
return 2;
signal(SIGTERM, stop);
display = wl_display_connect(NULL);
if (!display)
return 1;
struct wl_registry *r = wl_display_get_registry(display);
wl_registry_add_listener(r, &registry_listener, NULL);
if (wl_display_roundtrip(display) < 0 || wl_display_roundtrip(display) < 0)
return 1;
if (!compositor || !shm || !wm)
return 2;
xdg_wm_base_add_listener(wm, &wm_listener, NULL);
surface = wl_compositor_create_surface(compositor);
if (!strcmp(mode, "background")) {
if (!shell || !h1)
return 2;
layer = zwlr_layer_shell_v1_get_layer_surface(
shell, surface, h1, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND,
"mosaic-dynamic-background");
zwlr_layer_surface_v1_add_listener(layer, &layer_listener, NULL);
zwlr_layer_surface_v1_set_size(layer, 0, 0);
zwlr_layer_surface_v1_set_anchor(layer,
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
zwlr_layer_surface_v1_set_exclusive_zone(layer, -1);
zwlr_layer_surface_v1_set_keyboard_interactivity(layer, 0);
} else {
xdg = xdg_wm_base_get_xdg_surface(wm, surface);
xdg_surface_add_listener(xdg, &xdg_listener, NULL);
top = xdg_surface_get_toplevel(xdg);
xdg_toplevel_add_listener(top, &top_listener, NULL);
const char *app = !strcmp(mode, "reference") ? "org.mosaic.StaticReference"
: !strcmp(mode, "glass") ? "org.mosaic.BlurGlass"
: "org.mosaic.BlurFiller";
xdg_toplevel_set_app_id(top, app);
xdg_toplevel_set_title(top, app);
}
wl_surface_commit(surface);
while (running) {
if (wl_display_dispatch_pending(display) < 0)
break;
if (wl_display_flush(display) < 0 && errno != EAGAIN)
break;
struct pollfd fds[2] = {
{.fd = wl_display_get_fd(display), .events = POLLIN},
{.fd = STDIN_FILENO, .events = POLLIN}};
int n = poll(fds, 2, 100);
if (n < 0) {
if (errno == EINTR)
continue;
break;
}
if (fds[0].revents & (POLLIN | POLLERR | POLLHUP))
if (wl_display_dispatch(display) < 0)
break;
if (fds[1].revents & POLLIN) {
char cmd[64];
if (!fgets(cmd, sizeof(cmd), stdin))
break;
if (!strcmp(mode, "background") &&
((!commits && !strcmp(cmd,"G2-A\n")) ||
(commits==1 && !strcmp(cmd,"G2-B\n")) ||
(commits==2 && !strcmp(cmd,"G2-A-return\n")))) {
pattern = commits==1?'B':'A';
source_command=commits==0?"G2-A":commits==1?"G2-B":"G2-A-return";
draw();
fprintf(stderr, "COMMAND %c DONE ns=%lld\n", pattern, stamp());
} else if (!strcmp(cmd, "close\n")) {
fprintf(stderr,"CLOSE_RECEIVED\n");running = 0;
}
else if(!strcmp(mode,"background"))return 2;
}
}
int error = wl_display_get_error(display);
fprintf(stderr, "EXIT ns=%lld mode=%s error=%d commits=%u\n", stamp(), mode,
error, commits);
if (layer)
zwlr_layer_surface_v1_destroy(layer);
if (top)
xdg_toplevel_destroy(top);
if (xdg)
xdg_surface_destroy(xdg);
wl_surface_destroy(surface);
wl_display_roundtrip(display);
fprintf(stderr,"SHM_CLOSURE created=%u released=%u\n",commits,released_buffers);
bool all_released=commits==released_buffers;
wl_display_flush(display);
while (buffers)
free_pixels(buffers);
free(source_a);
wl_registry_destroy(r);
wl_display_disconnect(display);
return error || !all_released ? 1 : 0;
}

View file

@ -0,0 +1,34 @@
"""Freeze new G2 source-only bytes and delta. Never accepts its own review."""
import ctypes,difflib,hashlib,json,resource
from pathlib import Path
resource.setrlimit(resource.RLIMIT_CORE,(0,0));assert ctypes.CDLL(None).prctl(4,0,0,0,0)==0
ROOT=Path('/var/tmp/swayfx-mosaic-corec-v2-i516p6po');KIT=Path(__file__).resolve().parent
PARENT=ROOT/'sources/scene-core';TARGET=ROOT/'sources/scene-gpu'
def sha(p):return hashlib.sha256(p.read_bytes()).hexdigest()
def tree(p):return {str(f.relative_to(p)):sha(f) for f in sorted(p.rglob('*')) if f.is_file() and '.git' not in f.relative_to(p).parts}
changed=['render/fx_renderer/fx_pass.c','render/fx_renderer/g2_gl.h','render/fx_renderer/g2_native.h']
assert sha(PARENT/changed[0])=='398d594ace7257f4b69319290be7c1f14dc1ded446545ceb337404f5caab0cd3'
assert sha(Path('/usr/include/libdrm/drm_fourcc.h'))=='992f33804acda60b0b46f1a272942c3592484ea3217d469239f1cb12249de2eb'
for f in changed[1:]:assert sha(KIT/Path(f).name)==sha(TARGET/f)
pmap,tmap=tree(PARENT),tree(TARGET)
assert {name for name in pmap.keys()|tmap.keys() if pmap.get(name)!=tmap.get(name)}==set(changed)
assert tree(ROOT/'sources/mosaic-core')==tree(ROOT/'sources/mosaic-gpu')
patch=''
for f in changed:
old=(PARENT/f).read_text().splitlines(True) if (PARENT/f).exists() else []
patch+=''.join(difflib.unified_diff(old,(TARGET/f).read_text().splitlines(True),fromfile='a/'+f if old else '/dev/null',tofile='b/'+f))
assert not any(line[1:].rstrip('\n').endswith((' ','\t')) for line in patch.splitlines(True) if line.startswith('+') and not line.startswith('+++'))
(KIT/'g2-native.patch').write_text(patch)
files={}
for f in sorted(KIT.rglob('*')):
if f.is_file():files[str(f.relative_to(ROOT))]={'sha256':sha(f),'bytes':f.stat().st_size}
for f in changed:files['sources/scene-gpu/'+f]={'sha256':sha(TARGET/f),'bytes':(TARGET/f).stat().st_size}
for f in ['render/fx_renderer/shaders/blur1.frag','render/fx_renderer/shaders/blur2.frag']:
assert sha(PARENT/f)==sha(TARGET/f)
files['sources/scene-gpu/'+f]={'sha256':sha(TARGET/f),'bytes':(TARGET/f).stat().st_size,'unchanged':True}
tests=json.loads((ROOT/'gpu-fifo-fix/gpu-targeted-tests-corrected.json').read_text());assert tests['pass']
repo=Path('/home/fy59/Documents/Development/swayfx-mosaic')
historical=['tooling/probes/step20c-core-recovery/gpu-field/validate.py','tooling/probes/step20c-core-recovery/gpu-field/analysis.py','tooling/probes/step20c-optimized-blur-edge/clients.c']
m={'schema':'G2-new-source-freeze-v1','status':'EXPERIMENTAL_SOURCE_ONLY','review':'PENDING_INDEPENDENT_R_GPU','runtime':'NOT_RUN','actual_gl_observability':'NOT_PROVEN','port':'PARTIAL: GLES3 RBO only; GLES2/texture attachments refused','metadata_offline':'PASS_CONTROLLED_ONLY','whole_field_causality':'NOT_PROVEN','present_buffer':'NOT_PROVEN','gpu_completion':'NOT_PROVEN','pair3_build':'NOT_RUN','new_gpu_acquisitions':0,'parent_scene_base':'37ccd723bef49e6891156ffafce8f549f01446cc + accepted CORE','parent_fx_pass_sha256':sha(PARENT/changed[0]),'parent_scene_tree':hashlib.sha256(json.dumps(pmap,sort_keys=True).encode()).hexdigest(),'target_scene_tree':hashlib.sha256(json.dumps(tmap,sort_keys=True).encode()).hexdigest(),'mosaic_unchanged_tree':hashlib.sha256(json.dumps(tree(ROOT/'sources/mosaic-core'),sort_keys=True).encode()).hexdigest(),'drm_header':{'path':'/usr/include/libdrm/drm_fourcc.h','sha256':sha(Path('/usr/include/libdrm/drm_fourcc.h'))},'historical_controls':{'status':'HISTORICAL_REPORTED_ONLY','sources':{f:sha(repo/f) for f in historical}},'raw_plan':{'epochs':3,'points_per_epoch':10,'physical_dimensions':[800,600],'bytes':57600000,'cap':268435456},'capture_plan':{'H2_baseline':2,'H1_H2_epoch_pairs':3,'total':8,'G2_cap':16},'test_receipt':{'path':'gpu-fifo-fix/gpu-targeted-tests-corrected.json','sha256':sha(ROOT/'gpu-fifo-fix/gpu-targeted-tests-corrected.json')},'files':files}
(ROOT/'results/gpu-source-freeze-corrected.json').write_text(json.dumps(m,indent=2)+'\n')
print(json.dumps({'status':m['status'],'review':m['review'],'files':len(files),'freeze_sha256':sha(ROOT/'results/gpu-source-freeze-corrected.json')},indent=2))

View file

@ -0,0 +1,438 @@
--- a/render/fx_renderer/fx_pass.c
+++ b/render/fx_renderer/fx_pass.c
@@ -1,3 +1,4 @@
+#include <GLES3/gl3.h> /* private G2 state observability */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -21,6 +22,8 @@
#include "scenefx/types/fx/blur_data.h"
#include "util/matrix.h"
+#include "g2_native.h"
+
#define MAX_QUADS 86 // 4kb
struct fx_render_texture_options fx_render_texture_options_default(
@@ -66,6 +69,8 @@
output->name);
return false;
}
+
+ g2_track_output(pass, output);
// Update the buffers if needed
struct fx_renderer *renderer = pass->buffer->renderer;
@@ -115,6 +120,9 @@
TRACY_BOTH_ZONES_START(pass->buffer->renderer);
push_fx_debug(renderer);
+
+ g2_sample_native(pass, pass->buffer, 9, NULL);
+ g2_forget_output(pass);
if (timer) {
// clear disjoint flag
@@ -898,6 +906,7 @@
set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box);
set_tex_matrix(shader->tex_proj, options->transform, &src_fbox);
+ g2_uniform(pass, shader, texture, options->clip);
render(&dst_box, options->clip, shader->pos_attrib);
glBindTexture(texture->target, 0);
@@ -1057,6 +1066,7 @@
for (int i = 0; i < blur_data.num_passes; ++i) {
wlr_region_scale(&scaled_damage, &damage, 1.0f / (1 << (i + 1)));
render_blur_segments(pass, fx_options, &renderer->shaders.blur1);
+ g2_sample_native(pass, fx_options->current_buffer, (unsigned)i + 1, &scaled_damage);
}
// Upscale
@@ -1064,6 +1074,7 @@
// when upsampling we make the region twice as big
wlr_region_scale(&scaled_damage, &damage, 1.0f / (1 << i));
render_blur_segments(pass, fx_options, &renderer->shaders.blur2);
+ g2_sample_native(pass, fx_options->current_buffer, 6u - (unsigned)i, &scaled_damage);
}
pixman_region32_fini(&scaled_damage);
@@ -1223,15 +1234,18 @@
struct fx_render_blur_pass_options blur_options = *fx_options;
blur_options.current_buffer = pass->buffer;
blur_options.tex_options.base.clip = &clip;
+ g2_begin(pass, pass->buffer, &blur_options);
struct fx_framebuffer *fx_buffer = get_main_buffer_blur(pass, &blur_options);
if (fx_buffer != NULL) {
// Render the newly blurred content into the blur_buffer
fx_render_pass_read_to_buffer(pass, &clip,
pass->fx_offscreen_buffers->optimized_blur_buffer, fx_buffer);
+ g2_sample_native(pass, pass->fx_offscreen_buffers->optimized_blur_buffer, 7, &clip);
// Save the current scene pass state
fx_render_pass_read_to_buffer(pass, &clip,
pass->fx_offscreen_buffers->optimized_no_blur_buffer, pass->buffer);
+ g2_sample_native(pass, pass->fx_offscreen_buffers->optimized_no_blur_buffer, 8, &clip);
}
pixman_region32_fini(&clip);
--- /dev/null
+++ b/render/fx_renderer/g2_gl.h
@@ -0,0 +1,134 @@
+/* G2 new source-only intrusive diagnostic. No production API. */
+#ifndef G2_GL_H
+#define G2_GL_H
+#include <EGL/egl.h>
+#include <GLES3/gl3.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#define G2_CAP (256u * 1024u * 1024u)
+#define G2_ERRORS 16
+struct g2_errors { GLenum values[G2_ERRORS]; unsigned count; bool exhausted; };
+struct g2_state {
+ GLint read_fbo, draw_fbo, rbo, pack, pbo, row, skip_rows, skip_pixels;
+ GLint viewport[4], scissor[4], program, active, texture;
+ GLboolean scissor_on;
+};
+struct g2_sample {
+ EGLContext context; EGLint client_version; EGLenum api;
+ char version[160]; struct g2_state before, after;
+ struct g2_errors pre, query, read, restore;
+ GLint object_type, object, level, width, height, format, channels[4];
+ GLint read_buffer, samples; GLenum status; size_t bytes; unsigned char *pixels;
+ bool success; const char *reason;
+};
+static struct g2_errors g2_drain(void) {
+ struct g2_errors e = {0};
+ for (unsigned i=0;i<G2_ERRORS;i++) {
+ GLenum v=glGetError(); if (v==GL_NO_ERROR) return e;
+ e.values[e.count++]=v;
+ }
+ /* No unbounded probing: sixteen errors means attribution rejected. */
+ e.exhausted=true; return e;
+}
+static bool g2_clean(struct g2_errors e) { return !e.count && !e.exhausted; }
+static bool g2_size(int w,int h,size_t used,size_t *n) {
+ if(w<=0 || h<=0 || used>G2_CAP || (size_t)w>SIZE_MAX/4/(size_t)h) return false;
+ *n=(size_t)w*(size_t)h*4; return *n<=G2_CAP-used;
+}
+static void g2_state_get(struct g2_state *s) {
+ memset(s,0,sizeof(*s));
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING,&s->read_fbo);
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,&s->draw_fbo);
+ glGetIntegerv(GL_RENDERBUFFER_BINDING,&s->rbo);
+ glGetIntegerv(GL_PACK_ALIGNMENT,&s->pack);
+ glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING,&s->pbo);
+ glGetIntegerv(GL_PACK_ROW_LENGTH,&s->row);
+ glGetIntegerv(GL_PACK_SKIP_ROWS,&s->skip_rows);
+ glGetIntegerv(GL_PACK_SKIP_PIXELS,&s->skip_pixels);
+ glGetIntegerv(GL_VIEWPORT,s->viewport); glGetIntegerv(GL_SCISSOR_BOX,s->scissor);
+ s->scissor_on=glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_CURRENT_PROGRAM,&s->program);
+ glGetIntegerv(GL_ACTIVE_TEXTURE,&s->active);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D,&s->texture);
+}
+static void g2_state_restore(const struct g2_state *s) {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER,(GLuint)s->read_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER,(GLuint)s->draw_fbo);
+ glBindRenderbuffer(GL_RENDERBUFFER,(GLuint)s->rbo);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER,(GLuint)s->pbo);
+ glPixelStorei(GL_PACK_ALIGNMENT,s->pack);
+ glPixelStorei(GL_PACK_ROW_LENGTH,s->row);
+ glPixelStorei(GL_PACK_SKIP_ROWS,s->skip_rows);
+ glPixelStorei(GL_PACK_SKIP_PIXELS,s->skip_pixels);
+}
+/* Called with the actual current native target. ES2 is explicitly unsupported:
+ * no ES3-only enum is ever queried before both EGL and GL attest ES3.
+ * Only native RBO color attachments are accepted. Texture attachments retain
+ * type/name/level, but safe dimensions on this pinned API are NOT_PROVEN.
+ * Error queue consumption and synchronous readback cannot be restored. */
+static struct g2_sample g2_read(GLuint fbo,int width,int height,size_t used) {
+ struct g2_sample s={.reason="NOT_PROVEN"}; bool saved=false, changed=false;
+ s.context=eglGetCurrentContext(); s.api=eglQueryAPI();
+ if(s.context==EGL_NO_CONTEXT || s.api!=EGL_OPENGL_ES_API) {s.reason="UNKNOWN_CONTEXT"; return s;}
+ if(!eglQueryContext(eglGetCurrentDisplay(),s.context,EGL_CONTEXT_CLIENT_VERSION,&s.client_version)) {
+ s.reason="EGL_QUERY_FAILED"; return s;
+ }
+ s.pre=g2_drain(); if(!g2_clean(s.pre)) {s.reason="PREEXISTING_GL_ERRORS"; return s;}
+ const char *v=(const char *)glGetString(GL_VERSION);
+ if(v) snprintf(s.version,sizeof(s.version),"%s",v);
+ s.query=g2_drain(); if(!g2_clean(s.query)) {s.reason="VERSION_QUERY_ERROR"; return s;}
+ if(s.client_version<3 || !v || strncmp(v,"OpenGL ES 3.",12)!=0) {
+ s.reason="GLES_STATE_NOT_SUPPORTED"; return s;
+ }
+ if(!g2_size(width,height,used,&s.bytes)) {s.reason="RAW_BUDGET_OR_OVERFLOW"; return s;}
+ g2_state_get(&s.before); s.query=g2_drain();
+ if(!g2_clean(s.query)) {s.reason="STATE_QUERY_ERROR"; return s;}
+ saved=true; changed=true;
+ glBindFramebuffer(GL_READ_FRAMEBUFFER,fbo);
+ glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,&s.object_type);
+ glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,&s.object);
+ if(s.object_type==GL_RENDERBUFFER && s.object>0) {
+ glBindRenderbuffer(GL_RENDERBUFFER,(GLuint)s.object);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH,&s.width);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT,&s.height);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_INTERNAL_FORMAT,&s.format);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_SAMPLES,&s.samples);
+ const GLenum c[4]={GL_RENDERBUFFER_RED_SIZE,GL_RENDERBUFFER_GREEN_SIZE,GL_RENDERBUFFER_BLUE_SIZE,GL_RENDERBUFFER_ALPHA_SIZE};
+ for(int i=0;i<4;i++) glGetRenderbufferParameteriv(GL_RENDERBUFFER,c[i],&s.channels[i]);
+ } else if(s.object_type==GL_TEXTURE) {
+ glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,&s.level);
+ }
+ glGetIntegerv(GL_READ_BUFFER,&s.read_buffer);
+ s.status=glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ s.query=g2_drain();
+ if(!g2_clean(s.query)) {s.reason="ATTACHMENT_QUERY_ERROR"; goto done;}
+ if(s.object_type!=GL_RENDERBUFFER) {s.reason="TEXTURE_ATTACHMENT_DIMENSIONS_NOT_PROVEN"; goto done;}
+ if(s.read_buffer!=GL_COLOR_ATTACHMENT0 || s.samples!=0 || s.status!=GL_FRAMEBUFFER_COMPLETE || s.width!=width || s.height!=height ||
+ s.channels[0]!=8 || s.channels[1]!=8 || s.channels[2]!=8 || (s.channels[3]!=0 && s.channels[3]!=8)) {
+ s.reason="ATTACHMENT_UNSUPPORTED"; goto done;
+ }
+ glBindBuffer(GL_PIXEL_PACK_BUFFER,0); glPixelStorei(GL_PACK_ALIGNMENT,1);
+ glPixelStorei(GL_PACK_ROW_LENGTH,0); glPixelStorei(GL_PACK_SKIP_ROWS,0); glPixelStorei(GL_PACK_SKIP_PIXELS,0);
+ s.query=g2_drain(); if(!g2_clean(s.query)) {s.reason="PACK_QUERY_ERROR"; goto done;}
+ s.pixels=malloc(s.bytes); if(!s.pixels) {s.reason="ALLOCATION_FAILED"; goto done;}
+ /* glReadPixels returns void. NO alpha sentinel or file hash success gate. */
+ glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,s.pixels);
+ s.read=g2_drain();
+ if(!g2_clean(s.read)) {s.reason="READ_GL_ERROR"; goto done;}
+ s.success=true; s.reason="READ_SUCCESS";
+ done:
+ if(saved && changed) {
+ g2_state_restore(&s.before); g2_state_get(&s.after); s.restore=g2_drain();
+ if(!g2_clean(s.restore) || memcmp(&s.before,&s.after,sizeof(s.before)) || eglGetCurrentContext()!=s.context) {
+ s.success=false; s.reason="RESTORE_FAILED";
+ }
+ }
+ return s;
+}
+#endif
--- /dev/null
+++ b/render/fx_renderer/g2_native.h
@@ -0,0 +1,220 @@
+/* PRIVATE G2. Included only by the new diagnostic fx_pass.c. */
+#ifndef G2_NATIVE_H
+#define G2_NATIVE_H
+#include "g2_gl.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <wlr/render/dmabuf.h>
+#include <drm_fourcc.h>
+#include <wlr/types/wlr_buffer.h>
+#define G2_ROOT "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/acquisition"
+static struct {
+ bool stopped, active; unsigned epoch, point; size_t used;
+ int dir; FILE *meta; const void *pass, *output;
+ uintptr_t pass_sequence; char nonce[65];
+} g2={.dir=-1};
+static const char *g2_names[]={"source","down0","down1","down2","up2","up1","up0","optimized-cache","no-blur-cache","composition-presubmit"};
+static void g2_fail(const char *reason) {
+ g2.stopped=true;
+ if(g2.meta) {fprintf(g2.meta,"{\"kind\":\"rejected\",\"reason\":\"%s\",\"point\":%u}\n",reason,g2.point); fflush(g2.meta); fsync(fileno(g2.meta)); fclose(g2.meta); g2.meta=NULL;}
+ g2.active=false;
+}
+static uint32_t g2_crc(const unsigned char *p,size_t n) {
+ uint32_t crc=~0u;
+ for(size_t i=0;i<n;i++) {crc^=p[i]; for(int b=0;b<8;b++) crc=(crc>>1)^((0u-(crc&1u))&0xedb88320u);}
+ return ~crc;
+}
+static bool g2_write(int fd,const void *ptr,size_t n) {
+ const char *p=ptr; while(n) {ssize_t k=write(fd,p,n); if(k<0 && errno==EINTR) continue; if(k<=0)return false; p+=k;n-=(size_t)k;} return true;
+}
+static void g2_error_json(const char *name,struct g2_errors e) {
+ fprintf(g2.meta,",\"%s\":{\"exhausted\":%s,\"codes\":[",name,e.exhausted?"true":"false");
+ for(unsigned i=0;i<e.count;i++) {fprintf(g2.meta,"%s%u",i?",":"",e.values[i]);}
+ fputs("]}",g2.meta);
+}
+static void g2_state_json(const char *name,const struct g2_state *s) {
+ fprintf(g2.meta,",\"%s\":{\"read_draw_rbo_pack_pbo_row_skip\":[%d,%d,%d,%d,%d,%d,%d,%d],\"viewport\":[%d,%d,%d,%d],\"scissor\":[%d,%d,%d,%d],\"scissor_enabled\":%u,\"program_active_texture\":[%d,%d,%d]}",name,s->read_fbo,s->draw_fbo,s->rbo,s->pack,s->pbo,s->row,s->skip_rows,s->skip_pixels,s->viewport[0],s->viewport[1],s->viewport[2],s->viewport[3],s->scissor[0],s->scissor[1],s->scissor[2],s->scissor[3],s->scissor_on,s->program,s->active,s->texture);
+}
+static void g2_region(const pixman_region32_t *region) {
+ int n=0; pixman_box32_t *r=region?pixman_region32_rectangles(region,&n):NULL;
+ fputs(",\"fresh_rectangles\":[",g2.meta);
+ if(n>256) {fputs("],\"fresh_region_overflow\":true",g2.meta);return;}
+ for(int i=0;i<n;i++)fprintf(g2.meta,"%s[%d,%d,%d,%d]",i?",":"",r[i].x1,r[i].y1,r[i].x2,r[i].y2);
+ fputs("]",g2.meta);
+}
+static bool g2_dmabuf_supported(struct fx_framebuffer *b) {
+ struct wlr_dmabuf_attributes a={0};
+ if(!wlr_buffer_get_dmabuf(b->buffer,&a))return false;
+ bool format=a.format==DRM_FORMAT_ABGR8888 || a.format==DRM_FORMAT_XBGR8888 || a.format==DRM_FORMAT_ARGB8888 || a.format==DRM_FORMAT_XRGB8888;
+ bool amd=a.modifier==UINT64_C(0x020000001046bb04);
+ if(!format || (a.modifier!=0 && !amd) || a.n_planes!=(amd?2:1) || a.width!=b->buffer->width || a.height!=b->buffer->height || a.width<=0 || a.height<=0)return false;
+ if((uint64_t)a.stride[0]<(uint64_t)a.width*4)return false;
+ for(int i=0;i<a.n_planes;i++) {struct stat st;if(!a.stride[i] || a.fd[i]<0 || fstat(a.fd[i],&st))return false;}
+ return true; /* Metadata sanity, NEVER modifier decoding/allocation proof. */
+}
+static void g2_native_object(struct fx_framebuffer *b) {
+ fprintf(g2.meta,",\"native\":{\"fx\":\"%"PRIxPTR"\",\"wlr\":\"%"PRIxPTR"\",\"fbo_rbo_tex\":[%u,%u,%u],\"dimensions\":[%d,%d],\"image\":\"%"PRIxPTR"\"}",(uintptr_t)b,(uintptr_t)b->buffer,b->fbo,b->rbo,b->tex,b->buffer->width,b->buffer->height,(uintptr_t)b->image);
+ struct wlr_dmabuf_attributes a={0};
+ if(!wlr_buffer_get_dmabuf(b->buffer,&a)) {fputs(",\"dmabuf\":null",g2.meta);return;}
+ /* Borrowed descriptors: NEVER finish(), close(), duplicate or seek these FDs.
+ * fstat exposes descriptor identity, not a trustworthy DCC allocation length. */
+ fprintf(g2.meta,",\"dmabuf\":{\"format\":%u,\"modifier\":\"%016"PRIx64"\",\"dimensions\":[%d,%d],\"borrowed\":true,\"allocation_length\":\"NOT_PROVEN\",\"planes\":[",a.format,a.modifier,a.width,a.height);
+ if(a.n_planes<1 || a.n_planes>4) {fputs("]}",g2.meta);return;}
+ for(int i=0;i<a.n_planes;i++) {struct stat st={0};bool ok=fstat(a.fd[i],&st)==0;
+ fprintf(g2.meta,"%s{\"stride\":%u,\"offset\":%u,\"fd\":%d,\"fstat_ok\":%s,\"dev\":%ju,\"ino\":%ju}",i?",":"",a.stride[i],a.offset[i],a.fd[i],ok?"true":"false",(uintmax_t)st.st_dev,(uintmax_t)st.st_ino);}
+ fputs("]}",g2.meta);
+}
+static bool g2_owned(int fd,mode_t mode) {struct stat s;return fstat(fd,&s)==0 && s.st_uid==geteuid() && (s.st_mode&0777)==mode;}
+static bool g2_open(void) {
+ if(g2.dir>=0)return true;
+ const char *d=getenv("MOSAIC_G2_DIR"),*nonce=getenv("MOSAIC_G2_NONCE"); char real[PATH_MAX];
+ if(!d || !nonce)return false;
+ if(strlen(nonce)!=64 || !realpath(d,real) || strcmp(real,G2_ROOT) || strcmp(d,G2_ROOT)) {g2.stopped=true;return false;}
+ for(unsigned i=0;i<64;i++)if(!((nonce[i]>='0'&&nonce[i]<='9')||(nonce[i]>='a'&&nonce[i]<='f'))) {g2.stopped=true;return false;}
+ g2.dir=open(d,O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
+ if(g2.dir<0 || !g2_owned(g2.dir,0700)) {if(g2.dir>=0)close(g2.dir);g2.dir=-1;g2.stopped=true;return false;}
+ memcpy(g2.nonce,nonce,65);return true;
+}
+static void g2_begin(struct fx_gles_render_pass *pass,struct fx_framebuffer *source,struct fx_render_blur_pass_options *options);
+static bool g2_expected_source(const struct g2_sample *s,unsigned epoch) {
+ if(s->width!=800 || s->height!=600 || !s->pixels)return false;
+ const unsigned char a[2][3]={{245,245,245},{15,25,45}};
+ const unsigned char b[2][3]={{32,192,224},{176,32,64}};
+ for(int y=0;y<600;y++)for(int x=0;x<800;x++) {
+ const unsigned char *expected=(epoch==2?b:a)[(x/8)%2];
+ if(memcmp(s->pixels+((size_t)y*800+(size_t)x)*4,expected,3))return false;
+ }
+ return true; /* RGB source admission only; alpha is recorded, never sentinel. */
+}
+static void g2_sample_native(struct fx_gles_render_pass *pass,struct fx_framebuffer *b,unsigned point,const pixman_region32_t *region) {
+ if(!g2.active || g2.pass!=pass)return;
+ if(point!=g2.point || point>=10) {g2_fail("STAGE_ORDER_OR_DUPLICATE");return;}
+ if(region && pixman_region32_n_rects(region)>256) {g2_fail("REGION_LIMIT");return;}
+ if(!g2_dmabuf_supported(b)) {g2_fail("DMABUF_METADATA_UNSUPPORTED");return;}
+ struct g2_sample s=g2_read(b->fbo,b->buffer->width,b->buffer->height,g2.used);
+ fprintf(g2.meta,"{\"kind\":\"sample\",\"epoch\":%u,\"pass_sequence\":%"PRIuPTR",\"point\":%u,\"stage\":\"%s\",\"context\":\"%"PRIxPTR"\",\"api\":%u,\"client_version\":%d,\"result\":\"%s\",\"bytes\":%zu,\"attachment\":[%d,%d,%d,%d,%d,%d],\"channels\":[%d,%d,%d,%d],\"status\":%u",g2.epoch,g2.pass_sequence,point,g2_names[point],(uintptr_t)s.context,s.api,s.client_version,s.reason,s.bytes,s.object_type,s.object,s.level,s.width,s.height,s.format,s.channels[0],s.channels[1],s.channels[2],s.channels[3],s.status);
+ fprintf(g2.meta,",\"read_buffer\":%d,\"samples\":%d",s.read_buffer,s.samples);
+ fputs(",\"gl_version_hex\":\"",g2.meta);for(size_t i=0;i<strlen(s.version);i++)fprintf(g2.meta,"%02x",(unsigned char)s.version[i]);fputc('"',g2.meta);
+ g2_error_json("pre_errors",s.pre);g2_error_json("query_errors",s.query);g2_error_json("read_errors",s.read);g2_error_json("restore_errors",s.restore);
+ g2_state_json("before",&s.before);g2_state_json("after",&s.after);g2_native_object(b);g2_region(region);
+ if(!s.success) {fputs("}\n",g2.meta);free(s.pixels);g2_fail(s.reason);return;}
+ char name[64];snprintf(name,sizeof(name),"epoch-%u-point-%u.rgba",g2.epoch,point);
+ int fd=openat(g2.dir,name,O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,0600);
+ bool ok=fd>=0 && g2_write(fd,s.pixels,s.bytes) && fsync(fd)==0;
+ if(fd>=0 && close(fd))ok=false;
+ fprintf(g2.meta,",\"crc32\":\"%08x\",\"file\":\"%s\",\"published\":%s}\n",g2_crc(s.pixels,s.bytes),name,ok?"true":"false");
+ g2.used+=s.bytes;
+ if(!ok || fflush(g2.meta) || fsync(fileno(g2.meta))) {free(s.pixels);g2_fail("PUBLICATION_FAILED");return;}
+ g2.point++;
+ if(point==0 && !g2_expected_source(&s,g2.epoch)) {free(s.pixels);g2_fail("SOURCE_PATTERN_NOT_CURRENT_EPOCH");return;}
+ free(s.pixels);
+ if(point==9) {
+ fprintf(g2.meta,"{\"kind\":\"end\",\"epoch\":%u,\"points\":10,\"raw_total\":%zu,\"accepted\":true}\n",g2.epoch,g2.used);
+ bool final_ok=fflush(g2.meta)==0 && fsync(fileno(g2.meta))==0;
+ if(fclose(g2.meta)) {final_ok=false;}
+ g2.meta=NULL;g2.active=false;
+ if(!final_ok)g2.stopped=true;
+ if(g2.epoch==3)g2.stopped=true;
+ }
+}
+/* Explicit intended-output mapping; bounded eight outputs, no public ABI. */
+static struct {const void *pass;bool intended;} g2_outputs[8];
+static void g2_forget_output(struct fx_gles_render_pass *pass) {
+ for(unsigned i=0;i<8;i++)if(g2_outputs[i].pass==pass) {
+ g2_outputs[i].pass=NULL;g2_outputs[i].intended=false;
+ }
+}
+static bool g2_intended_output(struct fx_gles_render_pass *pass) {
+ for(unsigned i=0;i<8;i++)if(g2_outputs[i].pass==pass)return g2_outputs[i].intended;
+ return false;
+}
+static void g2_track_output(struct fx_gles_render_pass *pass,struct wlr_output *output) {
+ /* A native pass owns its mapping only until submit. Address reuse overwrites
+ * prior identity. Overflow never silently associates another output. */
+ g2_forget_output(pass);
+ for(unsigned i=0;i<8;i++)if(!g2_outputs[i].pass) {
+ g2_outputs[i].pass=pass;
+ g2_outputs[i].intended=strcmp(output->name,"HEADLESS-1")==0 && output->scale==1.0f && output->transform==WL_OUTPUT_TRANSFORM_NORMAL;
+ return;
+ }
+ g2_fail("TOO_MANY_SIMULTANEOUS_NATIVE_PASSES");
+}
+static void g2_begin(struct fx_gles_render_pass *pass,struct fx_framebuffer *source,struct fx_render_blur_pass_options *options) {
+ if(g2.stopped)return;
+ if(g2.active) {if(g2.pass==pass)g2_fail("MULTIPLE_OPTIMIZED_CANDIDATES");return;}
+ if(!g2_intended_output(pass) || !g2_open())return;
+ unsigned e=g2.epoch+1;if(e>3)return;
+ char arm[40],consumed[40],meta[40],expected[80],data[81]={0};
+ snprintf(arm,sizeof(arm),"epoch-%u.arm",e);snprintf(consumed,sizeof(consumed),"epoch-%u.consumed",e);
+ snprintf(expected,sizeof(expected),"%s %u\n",g2.nonce,e);
+ /* WHY: O_NONBLOCK makes non-regular substitutions (especially a FIFO with
+ * no writer) fail closed without stalling the compositor callback.
+ * CONTRACT: validate identity, permissions, link count and exact bounded
+ * framing size before reading or consuming the arm token. */
+ int fd=openat(g2.dir,arm,O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC);if(fd<0) {if(errno!=ENOENT)g2.stopped=true;return;}
+ struct stat st;
+ bool ok=fstat(fd,&st)==0 && S_ISREG(st.st_mode) && st.st_uid==geteuid() &&
+ (st.st_mode&0777)==0600 && st.st_nlink==1 && st.st_size==(off_t)strlen(expected);
+ if(!ok) {close(fd);g2.stopped=true;return;}
+ ssize_t n=read(fd,data,sizeof(data)-1);
+ if(n!=(ssize_t)strlen(expected) || memcmp(data,expected,(size_t)n)) {close(fd);g2.stopped=true;return;}
+ /* Consume BEFORE any query, readback or publication. Existing consumed token
+ * is fatal, even if a prior process died or first A was rejected. */
+ struct stat linked;
+ if(linkat(g2.dir,arm,g2.dir,consumed,0) || fstatat(g2.dir,consumed,&linked,AT_SYMLINK_NOFOLLOW) ||
+ !S_ISREG(linked.st_mode) || linked.st_dev!=st.st_dev || linked.st_ino!=st.st_ino || linked.st_nlink!=2 ||
+ unlinkat(g2.dir,arm,0) || fsync(g2.dir)) {close(fd);g2.stopped=true;return;}
+ close(fd);
+ g2.epoch=e;g2.point=0;g2.pass=pass;g2.pass_sequence++;g2.active=true;
+ snprintf(meta,sizeof(meta),"epoch-%u.jsonl",e);fd=openat(g2.dir,meta,O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,0600);
+ if(fd<0 || !(g2.meta=fdopen(fd,"w"))) {if(fd>=0)close(fd);g2.stopped=true;g2.active=false;return;}
+ fprintf(g2.meta,"{\"kind\":\"begin\",\"schema\":\"G2-new-v1\",\"epoch\":%u,\"label\":\"%s\",\"nonce\":\"%s\",\"output\":\"HEADLESS-1\",\"pass\":\"%"PRIxPTR"\",\"offscreen_output_key\":\"%"PRIxPTR"\",\"intrusive_error_queue\":true,\"error_queue_restorable\":false,\"readback_may_synchronize\":true,\"rows\":\"GL_LOW_TO_HIGH\",\"present_buffer\":\"NOT_PROVEN\",\"gpu_completion\":\"NOT_PROVEN\",\"lifetime\":\"NOT_PROVEN\"}\n",e,e==1?"A":e==2?"B":"A-return",g2.nonce,(uintptr_t)pass,(uintptr_t)pass->fx_offscreen_buffers);
+ if(options->blur_data->num_passes!=3 || options->blur_strength!=1.0f || blur_data_should_parameters_blur_effects(options->blur_data)) {g2_fail("NON_PROSPECTIVE_BLUR_CONFIGURATION");return;}
+ g2_sample_native(pass,source,0,options->tex_options.base.clip);
+}
+/* Executed while the actual blur program and source sampler remain bound. */
+static void g2_uniform(struct fx_gles_render_pass *pass,struct blur_shader *shader,struct fx_texture *texture,const pixman_region32_t *region) {
+ if(!g2.active || g2.pass!=pass || g2.point<1 || g2.point>6)return;
+ if(region && pixman_region32_n_rects(region)>256) {g2_fail("REGION_LIMIT");return;}
+ struct g2_errors pre=g2_drain();if(!g2_clean(pre)) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("pre_errors",pre);fputs("}\n",g2.meta);g2_fail("PRE_UNIFORM_GL_ERROR");return;}
+ struct g2_state draw_state;GLboolean color_mask[4]={0};
+ g2_state_get(&draw_state);glGetBooleanv(GL_COLOR_WRITEMASK,color_mask);
+ GLboolean blend=glIsEnabled(GL_BLEND),stencil=glIsEnabled(GL_STENCIL_TEST);
+ GLint program=0,min=0,mag=0,wraps=0,wrapt=0;GLfloat value[2]={0};GLint range[2]={0},precision=0;
+ glGetIntegerv(GL_CURRENT_PROGRAM,&program);
+ struct g2_errors initial=g2_drain();
+ if(!g2_clean(initial)) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_PROGRAM_QUERY_ERROR");return;}
+ if(program!=(GLint)shader->program || shader->halfpixel<0 || texture->target!=GL_TEXTURE_2D) {g2_fail("UNIFORM_PROGRAM_OR_TARGET");return;}
+ GLint actual=glGetUniformLocation((GLuint)program,"halfpixel");
+ initial=g2_drain();
+ if(!g2_clean(initial) || actual!=shader->halfpixel) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_LOCATION");return;}
+ GLint count=0;glGetProgramiv((GLuint)program,GL_ACTIVE_UNIFORMS,&count);bool typed=false;
+ initial=g2_drain();
+ if(!g2_clean(initial) || count<0 || count>128) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_COUNT");return;}
+ for(GLuint i=0;i<(GLuint)count;i++) {char name[128];GLsizei len=0;GLint size=0;GLenum type=0;glGetActiveUniform((GLuint)program,i,sizeof(name),&len,&size,&type,name);
+ if(len==9 && !memcmp(name,"halfpixel",9) && size==1 && type==GL_FLOAT_VEC2)typed=true;
+ }
+ GLfloat radius=0,proj[9]={0},tex_proj[9]={0};
+ glGetUniformfv((GLuint)program,shader->radius,&radius);
+ glGetUniformfv((GLuint)program,shader->proj,proj);glGetUniformfv((GLuint)program,shader->tex_proj,tex_proj);
+ glGetUniformfv((GLuint)program,actual,value);
+ glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT,range,&precision);
+ glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,&min);glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,&mag);
+ glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,&wraps);glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,&wrapt);
+ struct g2_errors errors=g2_drain();if(!g2_clean(errors)||!typed) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",errors);fputs("}\n",g2.meta);g2_fail("UNIFORM_QUERY_OR_TYPE");return;}
+ uint32_t bits[2];memcpy(bits,value,sizeof(bits));
+ fprintf(g2.meta,"{\"kind\":\"uniform\",\"point\":%u,\"program\":%d,\"location\":%d,\"type\":%u,\"actual_bits\":[%u,%u],\"shader_default_float\":\"mediump\",\"varying\":\"mediump\",\"precision_capability\":[%d,%d,%d],\"operation_precision\":\"NOT_PROVEN\",\"sampler\":[%d,%d,%d,%d],\"source_texture\":%u,\"native_texture_dimensions\":[%u,%u],\"gl_level_dimensions\":\"NOT_PROVEN\"",g2.point,program,actual,GL_FLOAT_VEC2,bits[0],bits[1],range[0],range[1],precision,min,mag,wraps,wrapt,texture->tex,texture->wlr_texture.width,texture->wlr_texture.height);
+ fprintf(g2.meta,",\"qualifier_basis\":\"FROZEN_LINK_INPUT_SOURCE\",\"shader_source_sha256\":\"%s\"",g2.point<=3?"01664694e4201efb35ec698e89783e220ed930972b5396b86fa842814cd82d4d":"1db325237c9a6c70c2d97518e2f690d448cd006139e9f410cd16e097a1677ad1");
+ uint32_t radius_bits,proj_bits[9],tex_proj_bits[9];memcpy(&radius_bits,&radius,4);memcpy(proj_bits,proj,sizeof(proj));memcpy(tex_proj_bits,tex_proj,sizeof(tex_proj));
+ fprintf(g2.meta,",\"other_uniforms\":{\"radius_location\":%d,\"radius_bits\":%u,\"proj_location\":%d,\"proj_bits\":[",shader->radius,radius_bits,shader->proj);
+ for(unsigned i=0;i<9;i++)fprintf(g2.meta,"%s%u",i?",":"",proj_bits[i]);
+ fprintf(g2.meta,"],\"tex_proj_location\":%d,\"tex_proj_bits\":[",shader->tex_proj);
+ for(unsigned i=0;i<9;i++)fprintf(g2.meta,"%s%u",i?",":"",tex_proj_bits[i]);
+ fputs("]}",g2.meta);g2_state_json("draw_state",&draw_state);
+ fprintf(g2.meta,",\"blend_stencil\":[%u,%u],\"color_mask\":[%u,%u,%u,%u]",blend,stencil,color_mask[0],color_mask[1],color_mask[2],color_mask[3]);
+ g2_region(region);fputs("}\n",g2.meta);
+}
+#endif

View file

@ -0,0 +1,134 @@
/* G2 new source-only intrusive diagnostic. No production API. */
#ifndef G2_GL_H
#define G2_GL_H
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define G2_CAP (256u * 1024u * 1024u)
#define G2_ERRORS 16
struct g2_errors { GLenum values[G2_ERRORS]; unsigned count; bool exhausted; };
struct g2_state {
GLint read_fbo, draw_fbo, rbo, pack, pbo, row, skip_rows, skip_pixels;
GLint viewport[4], scissor[4], program, active, texture;
GLboolean scissor_on;
};
struct g2_sample {
EGLContext context; EGLint client_version; EGLenum api;
char version[160]; struct g2_state before, after;
struct g2_errors pre, query, read, restore;
GLint object_type, object, level, width, height, format, channels[4];
GLint read_buffer, samples; GLenum status; size_t bytes; unsigned char *pixels;
bool success; const char *reason;
};
static struct g2_errors g2_drain(void) {
struct g2_errors e = {0};
for (unsigned i=0;i<G2_ERRORS;i++) {
GLenum v=glGetError(); if (v==GL_NO_ERROR) return e;
e.values[e.count++]=v;
}
/* No unbounded probing: sixteen errors means attribution rejected. */
e.exhausted=true; return e;
}
static bool g2_clean(struct g2_errors e) { return !e.count && !e.exhausted; }
static bool g2_size(int w,int h,size_t used,size_t *n) {
if(w<=0 || h<=0 || used>G2_CAP || (size_t)w>SIZE_MAX/4/(size_t)h) return false;
*n=(size_t)w*(size_t)h*4; return *n<=G2_CAP-used;
}
static void g2_state_get(struct g2_state *s) {
memset(s,0,sizeof(*s));
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING,&s->read_fbo);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,&s->draw_fbo);
glGetIntegerv(GL_RENDERBUFFER_BINDING,&s->rbo);
glGetIntegerv(GL_PACK_ALIGNMENT,&s->pack);
glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING,&s->pbo);
glGetIntegerv(GL_PACK_ROW_LENGTH,&s->row);
glGetIntegerv(GL_PACK_SKIP_ROWS,&s->skip_rows);
glGetIntegerv(GL_PACK_SKIP_PIXELS,&s->skip_pixels);
glGetIntegerv(GL_VIEWPORT,s->viewport); glGetIntegerv(GL_SCISSOR_BOX,s->scissor);
s->scissor_on=glIsEnabled(GL_SCISSOR_TEST);
glGetIntegerv(GL_CURRENT_PROGRAM,&s->program);
glGetIntegerv(GL_ACTIVE_TEXTURE,&s->active);
glGetIntegerv(GL_TEXTURE_BINDING_2D,&s->texture);
}
static void g2_state_restore(const struct g2_state *s) {
glBindFramebuffer(GL_READ_FRAMEBUFFER,(GLuint)s->read_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,(GLuint)s->draw_fbo);
glBindRenderbuffer(GL_RENDERBUFFER,(GLuint)s->rbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER,(GLuint)s->pbo);
glPixelStorei(GL_PACK_ALIGNMENT,s->pack);
glPixelStorei(GL_PACK_ROW_LENGTH,s->row);
glPixelStorei(GL_PACK_SKIP_ROWS,s->skip_rows);
glPixelStorei(GL_PACK_SKIP_PIXELS,s->skip_pixels);
}
/* Called with the actual current native target. ES2 is explicitly unsupported:
* no ES3-only enum is ever queried before both EGL and GL attest ES3.
* Only native RBO color attachments are accepted. Texture attachments retain
* type/name/level, but safe dimensions on this pinned API are NOT_PROVEN.
* Error queue consumption and synchronous readback cannot be restored. */
static struct g2_sample g2_read(GLuint fbo,int width,int height,size_t used) {
struct g2_sample s={.reason="NOT_PROVEN"}; bool saved=false, changed=false;
s.context=eglGetCurrentContext(); s.api=eglQueryAPI();
if(s.context==EGL_NO_CONTEXT || s.api!=EGL_OPENGL_ES_API) {s.reason="UNKNOWN_CONTEXT"; return s;}
if(!eglQueryContext(eglGetCurrentDisplay(),s.context,EGL_CONTEXT_CLIENT_VERSION,&s.client_version)) {
s.reason="EGL_QUERY_FAILED"; return s;
}
s.pre=g2_drain(); if(!g2_clean(s.pre)) {s.reason="PREEXISTING_GL_ERRORS"; return s;}
const char *v=(const char *)glGetString(GL_VERSION);
if(v) snprintf(s.version,sizeof(s.version),"%s",v);
s.query=g2_drain(); if(!g2_clean(s.query)) {s.reason="VERSION_QUERY_ERROR"; return s;}
if(s.client_version<3 || !v || strncmp(v,"OpenGL ES 3.",12)!=0) {
s.reason="GLES_STATE_NOT_SUPPORTED"; return s;
}
if(!g2_size(width,height,used,&s.bytes)) {s.reason="RAW_BUDGET_OR_OVERFLOW"; return s;}
g2_state_get(&s.before); s.query=g2_drain();
if(!g2_clean(s.query)) {s.reason="STATE_QUERY_ERROR"; return s;}
saved=true; changed=true;
glBindFramebuffer(GL_READ_FRAMEBUFFER,fbo);
glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,&s.object_type);
glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,&s.object);
if(s.object_type==GL_RENDERBUFFER && s.object>0) {
glBindRenderbuffer(GL_RENDERBUFFER,(GLuint)s.object);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH,&s.width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT,&s.height);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_INTERNAL_FORMAT,&s.format);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_SAMPLES,&s.samples);
const GLenum c[4]={GL_RENDERBUFFER_RED_SIZE,GL_RENDERBUFFER_GREEN_SIZE,GL_RENDERBUFFER_BLUE_SIZE,GL_RENDERBUFFER_ALPHA_SIZE};
for(int i=0;i<4;i++) glGetRenderbufferParameteriv(GL_RENDERBUFFER,c[i],&s.channels[i]);
} else if(s.object_type==GL_TEXTURE) {
glGetFramebufferAttachmentParameteriv(GL_READ_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,&s.level);
}
glGetIntegerv(GL_READ_BUFFER,&s.read_buffer);
s.status=glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
s.query=g2_drain();
if(!g2_clean(s.query)) {s.reason="ATTACHMENT_QUERY_ERROR"; goto done;}
if(s.object_type!=GL_RENDERBUFFER) {s.reason="TEXTURE_ATTACHMENT_DIMENSIONS_NOT_PROVEN"; goto done;}
if(s.read_buffer!=GL_COLOR_ATTACHMENT0 || s.samples!=0 || s.status!=GL_FRAMEBUFFER_COMPLETE || s.width!=width || s.height!=height ||
s.channels[0]!=8 || s.channels[1]!=8 || s.channels[2]!=8 || (s.channels[3]!=0 && s.channels[3]!=8)) {
s.reason="ATTACHMENT_UNSUPPORTED"; goto done;
}
glBindBuffer(GL_PIXEL_PACK_BUFFER,0); glPixelStorei(GL_PACK_ALIGNMENT,1);
glPixelStorei(GL_PACK_ROW_LENGTH,0); glPixelStorei(GL_PACK_SKIP_ROWS,0); glPixelStorei(GL_PACK_SKIP_PIXELS,0);
s.query=g2_drain(); if(!g2_clean(s.query)) {s.reason="PACK_QUERY_ERROR"; goto done;}
s.pixels=malloc(s.bytes); if(!s.pixels) {s.reason="ALLOCATION_FAILED"; goto done;}
/* glReadPixels returns void. NO alpha sentinel or file hash success gate. */
glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,s.pixels);
s.read=g2_drain();
if(!g2_clean(s.read)) {s.reason="READ_GL_ERROR"; goto done;}
s.success=true; s.reason="READ_SUCCESS";
done:
if(saved && changed) {
g2_state_restore(&s.before); g2_state_get(&s.after); s.restore=g2_drain();
if(!g2_clean(s.restore) || memcmp(&s.before,&s.after,sizeof(s.before)) || eglGetCurrentContext()!=s.context) {
s.success=false; s.reason="RESTORE_FAILED";
}
}
return s;
}
#endif

View file

@ -0,0 +1,220 @@
/* PRIVATE G2. Included only by the new diagnostic fx_pass.c. */
#ifndef G2_NATIVE_H
#define G2_NATIVE_H
#include "g2_gl.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <wlr/render/dmabuf.h>
#include <drm_fourcc.h>
#include <wlr/types/wlr_buffer.h>
#define G2_ROOT "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/acquisition"
static struct {
bool stopped, active; unsigned epoch, point; size_t used;
int dir; FILE *meta; const void *pass, *output;
uintptr_t pass_sequence; char nonce[65];
} g2={.dir=-1};
static const char *g2_names[]={"source","down0","down1","down2","up2","up1","up0","optimized-cache","no-blur-cache","composition-presubmit"};
static void g2_fail(const char *reason) {
g2.stopped=true;
if(g2.meta) {fprintf(g2.meta,"{\"kind\":\"rejected\",\"reason\":\"%s\",\"point\":%u}\n",reason,g2.point); fflush(g2.meta); fsync(fileno(g2.meta)); fclose(g2.meta); g2.meta=NULL;}
g2.active=false;
}
static uint32_t g2_crc(const unsigned char *p,size_t n) {
uint32_t crc=~0u;
for(size_t i=0;i<n;i++) {crc^=p[i]; for(int b=0;b<8;b++) crc=(crc>>1)^((0u-(crc&1u))&0xedb88320u);}
return ~crc;
}
static bool g2_write(int fd,const void *ptr,size_t n) {
const char *p=ptr; while(n) {ssize_t k=write(fd,p,n); if(k<0 && errno==EINTR) continue; if(k<=0)return false; p+=k;n-=(size_t)k;} return true;
}
static void g2_error_json(const char *name,struct g2_errors e) {
fprintf(g2.meta,",\"%s\":{\"exhausted\":%s,\"codes\":[",name,e.exhausted?"true":"false");
for(unsigned i=0;i<e.count;i++) {fprintf(g2.meta,"%s%u",i?",":"",e.values[i]);}
fputs("]}",g2.meta);
}
static void g2_state_json(const char *name,const struct g2_state *s) {
fprintf(g2.meta,",\"%s\":{\"read_draw_rbo_pack_pbo_row_skip\":[%d,%d,%d,%d,%d,%d,%d,%d],\"viewport\":[%d,%d,%d,%d],\"scissor\":[%d,%d,%d,%d],\"scissor_enabled\":%u,\"program_active_texture\":[%d,%d,%d]}",name,s->read_fbo,s->draw_fbo,s->rbo,s->pack,s->pbo,s->row,s->skip_rows,s->skip_pixels,s->viewport[0],s->viewport[1],s->viewport[2],s->viewport[3],s->scissor[0],s->scissor[1],s->scissor[2],s->scissor[3],s->scissor_on,s->program,s->active,s->texture);
}
static void g2_region(const pixman_region32_t *region) {
int n=0; pixman_box32_t *r=region?pixman_region32_rectangles(region,&n):NULL;
fputs(",\"fresh_rectangles\":[",g2.meta);
if(n>256) {fputs("],\"fresh_region_overflow\":true",g2.meta);return;}
for(int i=0;i<n;i++)fprintf(g2.meta,"%s[%d,%d,%d,%d]",i?",":"",r[i].x1,r[i].y1,r[i].x2,r[i].y2);
fputs("]",g2.meta);
}
static bool g2_dmabuf_supported(struct fx_framebuffer *b) {
struct wlr_dmabuf_attributes a={0};
if(!wlr_buffer_get_dmabuf(b->buffer,&a))return false;
bool format=a.format==DRM_FORMAT_ABGR8888 || a.format==DRM_FORMAT_XBGR8888 || a.format==DRM_FORMAT_ARGB8888 || a.format==DRM_FORMAT_XRGB8888;
bool amd=a.modifier==UINT64_C(0x020000001046bb04);
if(!format || (a.modifier!=0 && !amd) || a.n_planes!=(amd?2:1) || a.width!=b->buffer->width || a.height!=b->buffer->height || a.width<=0 || a.height<=0)return false;
if((uint64_t)a.stride[0]<(uint64_t)a.width*4)return false;
for(int i=0;i<a.n_planes;i++) {struct stat st;if(!a.stride[i] || a.fd[i]<0 || fstat(a.fd[i],&st))return false;}
return true; /* Metadata sanity, NEVER modifier decoding/allocation proof. */
}
static void g2_native_object(struct fx_framebuffer *b) {
fprintf(g2.meta,",\"native\":{\"fx\":\"%"PRIxPTR"\",\"wlr\":\"%"PRIxPTR"\",\"fbo_rbo_tex\":[%u,%u,%u],\"dimensions\":[%d,%d],\"image\":\"%"PRIxPTR"\"}",(uintptr_t)b,(uintptr_t)b->buffer,b->fbo,b->rbo,b->tex,b->buffer->width,b->buffer->height,(uintptr_t)b->image);
struct wlr_dmabuf_attributes a={0};
if(!wlr_buffer_get_dmabuf(b->buffer,&a)) {fputs(",\"dmabuf\":null",g2.meta);return;}
/* Borrowed descriptors: NEVER finish(), close(), duplicate or seek these FDs.
* fstat exposes descriptor identity, not a trustworthy DCC allocation length. */
fprintf(g2.meta,",\"dmabuf\":{\"format\":%u,\"modifier\":\"%016"PRIx64"\",\"dimensions\":[%d,%d],\"borrowed\":true,\"allocation_length\":\"NOT_PROVEN\",\"planes\":[",a.format,a.modifier,a.width,a.height);
if(a.n_planes<1 || a.n_planes>4) {fputs("]}",g2.meta);return;}
for(int i=0;i<a.n_planes;i++) {struct stat st={0};bool ok=fstat(a.fd[i],&st)==0;
fprintf(g2.meta,"%s{\"stride\":%u,\"offset\":%u,\"fd\":%d,\"fstat_ok\":%s,\"dev\":%ju,\"ino\":%ju}",i?",":"",a.stride[i],a.offset[i],a.fd[i],ok?"true":"false",(uintmax_t)st.st_dev,(uintmax_t)st.st_ino);}
fputs("]}",g2.meta);
}
static bool g2_owned(int fd,mode_t mode) {struct stat s;return fstat(fd,&s)==0 && s.st_uid==geteuid() && (s.st_mode&0777)==mode;}
static bool g2_open(void) {
if(g2.dir>=0)return true;
const char *d=getenv("MOSAIC_G2_DIR"),*nonce=getenv("MOSAIC_G2_NONCE"); char real[PATH_MAX];
if(!d || !nonce)return false;
if(strlen(nonce)!=64 || !realpath(d,real) || strcmp(real,G2_ROOT) || strcmp(d,G2_ROOT)) {g2.stopped=true;return false;}
for(unsigned i=0;i<64;i++)if(!((nonce[i]>='0'&&nonce[i]<='9')||(nonce[i]>='a'&&nonce[i]<='f'))) {g2.stopped=true;return false;}
g2.dir=open(d,O_RDONLY|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if(g2.dir<0 || !g2_owned(g2.dir,0700)) {if(g2.dir>=0)close(g2.dir);g2.dir=-1;g2.stopped=true;return false;}
memcpy(g2.nonce,nonce,65);return true;
}
static void g2_begin(struct fx_gles_render_pass *pass,struct fx_framebuffer *source,struct fx_render_blur_pass_options *options);
static bool g2_expected_source(const struct g2_sample *s,unsigned epoch) {
if(s->width!=800 || s->height!=600 || !s->pixels)return false;
const unsigned char a[2][3]={{245,245,245},{15,25,45}};
const unsigned char b[2][3]={{32,192,224},{176,32,64}};
for(int y=0;y<600;y++)for(int x=0;x<800;x++) {
const unsigned char *expected=(epoch==2?b:a)[(x/8)%2];
if(memcmp(s->pixels+((size_t)y*800+(size_t)x)*4,expected,3))return false;
}
return true; /* RGB source admission only; alpha is recorded, never sentinel. */
}
static void g2_sample_native(struct fx_gles_render_pass *pass,struct fx_framebuffer *b,unsigned point,const pixman_region32_t *region) {
if(!g2.active || g2.pass!=pass)return;
if(point!=g2.point || point>=10) {g2_fail("STAGE_ORDER_OR_DUPLICATE");return;}
if(region && pixman_region32_n_rects(region)>256) {g2_fail("REGION_LIMIT");return;}
if(!g2_dmabuf_supported(b)) {g2_fail("DMABUF_METADATA_UNSUPPORTED");return;}
struct g2_sample s=g2_read(b->fbo,b->buffer->width,b->buffer->height,g2.used);
fprintf(g2.meta,"{\"kind\":\"sample\",\"epoch\":%u,\"pass_sequence\":%"PRIuPTR",\"point\":%u,\"stage\":\"%s\",\"context\":\"%"PRIxPTR"\",\"api\":%u,\"client_version\":%d,\"result\":\"%s\",\"bytes\":%zu,\"attachment\":[%d,%d,%d,%d,%d,%d],\"channels\":[%d,%d,%d,%d],\"status\":%u",g2.epoch,g2.pass_sequence,point,g2_names[point],(uintptr_t)s.context,s.api,s.client_version,s.reason,s.bytes,s.object_type,s.object,s.level,s.width,s.height,s.format,s.channels[0],s.channels[1],s.channels[2],s.channels[3],s.status);
fprintf(g2.meta,",\"read_buffer\":%d,\"samples\":%d",s.read_buffer,s.samples);
fputs(",\"gl_version_hex\":\"",g2.meta);for(size_t i=0;i<strlen(s.version);i++)fprintf(g2.meta,"%02x",(unsigned char)s.version[i]);fputc('"',g2.meta);
g2_error_json("pre_errors",s.pre);g2_error_json("query_errors",s.query);g2_error_json("read_errors",s.read);g2_error_json("restore_errors",s.restore);
g2_state_json("before",&s.before);g2_state_json("after",&s.after);g2_native_object(b);g2_region(region);
if(!s.success) {fputs("}\n",g2.meta);free(s.pixels);g2_fail(s.reason);return;}
char name[64];snprintf(name,sizeof(name),"epoch-%u-point-%u.rgba",g2.epoch,point);
int fd=openat(g2.dir,name,O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,0600);
bool ok=fd>=0 && g2_write(fd,s.pixels,s.bytes) && fsync(fd)==0;
if(fd>=0 && close(fd))ok=false;
fprintf(g2.meta,",\"crc32\":\"%08x\",\"file\":\"%s\",\"published\":%s}\n",g2_crc(s.pixels,s.bytes),name,ok?"true":"false");
g2.used+=s.bytes;
if(!ok || fflush(g2.meta) || fsync(fileno(g2.meta))) {free(s.pixels);g2_fail("PUBLICATION_FAILED");return;}
g2.point++;
if(point==0 && !g2_expected_source(&s,g2.epoch)) {free(s.pixels);g2_fail("SOURCE_PATTERN_NOT_CURRENT_EPOCH");return;}
free(s.pixels);
if(point==9) {
fprintf(g2.meta,"{\"kind\":\"end\",\"epoch\":%u,\"points\":10,\"raw_total\":%zu,\"accepted\":true}\n",g2.epoch,g2.used);
bool final_ok=fflush(g2.meta)==0 && fsync(fileno(g2.meta))==0;
if(fclose(g2.meta)) {final_ok=false;}
g2.meta=NULL;g2.active=false;
if(!final_ok)g2.stopped=true;
if(g2.epoch==3)g2.stopped=true;
}
}
/* Explicit intended-output mapping; bounded eight outputs, no public ABI. */
static struct {const void *pass;bool intended;} g2_outputs[8];
static void g2_forget_output(struct fx_gles_render_pass *pass) {
for(unsigned i=0;i<8;i++)if(g2_outputs[i].pass==pass) {
g2_outputs[i].pass=NULL;g2_outputs[i].intended=false;
}
}
static bool g2_intended_output(struct fx_gles_render_pass *pass) {
for(unsigned i=0;i<8;i++)if(g2_outputs[i].pass==pass)return g2_outputs[i].intended;
return false;
}
static void g2_track_output(struct fx_gles_render_pass *pass,struct wlr_output *output) {
/* A native pass owns its mapping only until submit. Address reuse overwrites
* prior identity. Overflow never silently associates another output. */
g2_forget_output(pass);
for(unsigned i=0;i<8;i++)if(!g2_outputs[i].pass) {
g2_outputs[i].pass=pass;
g2_outputs[i].intended=strcmp(output->name,"HEADLESS-1")==0 && output->scale==1.0f && output->transform==WL_OUTPUT_TRANSFORM_NORMAL;
return;
}
g2_fail("TOO_MANY_SIMULTANEOUS_NATIVE_PASSES");
}
static void g2_begin(struct fx_gles_render_pass *pass,struct fx_framebuffer *source,struct fx_render_blur_pass_options *options) {
if(g2.stopped)return;
if(g2.active) {if(g2.pass==pass)g2_fail("MULTIPLE_OPTIMIZED_CANDIDATES");return;}
if(!g2_intended_output(pass) || !g2_open())return;
unsigned e=g2.epoch+1;if(e>3)return;
char arm[40],consumed[40],meta[40],expected[80],data[81]={0};
snprintf(arm,sizeof(arm),"epoch-%u.arm",e);snprintf(consumed,sizeof(consumed),"epoch-%u.consumed",e);
snprintf(expected,sizeof(expected),"%s %u\n",g2.nonce,e);
/* WHY: O_NONBLOCK makes non-regular substitutions (especially a FIFO with
* no writer) fail closed without stalling the compositor callback.
* CONTRACT: validate identity, permissions, link count and exact bounded
* framing size before reading or consuming the arm token. */
int fd=openat(g2.dir,arm,O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC);if(fd<0) {if(errno!=ENOENT)g2.stopped=true;return;}
struct stat st;
bool ok=fstat(fd,&st)==0 && S_ISREG(st.st_mode) && st.st_uid==geteuid() &&
(st.st_mode&0777)==0600 && st.st_nlink==1 && st.st_size==(off_t)strlen(expected);
if(!ok) {close(fd);g2.stopped=true;return;}
ssize_t n=read(fd,data,sizeof(data)-1);
if(n!=(ssize_t)strlen(expected) || memcmp(data,expected,(size_t)n)) {close(fd);g2.stopped=true;return;}
/* Consume BEFORE any query, readback or publication. Existing consumed token
* is fatal, even if a prior process died or first A was rejected. */
struct stat linked;
if(linkat(g2.dir,arm,g2.dir,consumed,0) || fstatat(g2.dir,consumed,&linked,AT_SYMLINK_NOFOLLOW) ||
!S_ISREG(linked.st_mode) || linked.st_dev!=st.st_dev || linked.st_ino!=st.st_ino || linked.st_nlink!=2 ||
unlinkat(g2.dir,arm,0) || fsync(g2.dir)) {close(fd);g2.stopped=true;return;}
close(fd);
g2.epoch=e;g2.point=0;g2.pass=pass;g2.pass_sequence++;g2.active=true;
snprintf(meta,sizeof(meta),"epoch-%u.jsonl",e);fd=openat(g2.dir,meta,O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,0600);
if(fd<0 || !(g2.meta=fdopen(fd,"w"))) {if(fd>=0)close(fd);g2.stopped=true;g2.active=false;return;}
fprintf(g2.meta,"{\"kind\":\"begin\",\"schema\":\"G2-new-v1\",\"epoch\":%u,\"label\":\"%s\",\"nonce\":\"%s\",\"output\":\"HEADLESS-1\",\"pass\":\"%"PRIxPTR"\",\"offscreen_output_key\":\"%"PRIxPTR"\",\"intrusive_error_queue\":true,\"error_queue_restorable\":false,\"readback_may_synchronize\":true,\"rows\":\"GL_LOW_TO_HIGH\",\"present_buffer\":\"NOT_PROVEN\",\"gpu_completion\":\"NOT_PROVEN\",\"lifetime\":\"NOT_PROVEN\"}\n",e,e==1?"A":e==2?"B":"A-return",g2.nonce,(uintptr_t)pass,(uintptr_t)pass->fx_offscreen_buffers);
if(options->blur_data->num_passes!=3 || options->blur_strength!=1.0f || blur_data_should_parameters_blur_effects(options->blur_data)) {g2_fail("NON_PROSPECTIVE_BLUR_CONFIGURATION");return;}
g2_sample_native(pass,source,0,options->tex_options.base.clip);
}
/* Executed while the actual blur program and source sampler remain bound. */
static void g2_uniform(struct fx_gles_render_pass *pass,struct blur_shader *shader,struct fx_texture *texture,const pixman_region32_t *region) {
if(!g2.active || g2.pass!=pass || g2.point<1 || g2.point>6)return;
if(region && pixman_region32_n_rects(region)>256) {g2_fail("REGION_LIMIT");return;}
struct g2_errors pre=g2_drain();if(!g2_clean(pre)) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("pre_errors",pre);fputs("}\n",g2.meta);g2_fail("PRE_UNIFORM_GL_ERROR");return;}
struct g2_state draw_state;GLboolean color_mask[4]={0};
g2_state_get(&draw_state);glGetBooleanv(GL_COLOR_WRITEMASK,color_mask);
GLboolean blend=glIsEnabled(GL_BLEND),stencil=glIsEnabled(GL_STENCIL_TEST);
GLint program=0,min=0,mag=0,wraps=0,wrapt=0;GLfloat value[2]={0};GLint range[2]={0},precision=0;
glGetIntegerv(GL_CURRENT_PROGRAM,&program);
struct g2_errors initial=g2_drain();
if(!g2_clean(initial)) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_PROGRAM_QUERY_ERROR");return;}
if(program!=(GLint)shader->program || shader->halfpixel<0 || texture->target!=GL_TEXTURE_2D) {g2_fail("UNIFORM_PROGRAM_OR_TARGET");return;}
GLint actual=glGetUniformLocation((GLuint)program,"halfpixel");
initial=g2_drain();
if(!g2_clean(initial) || actual!=shader->halfpixel) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_LOCATION");return;}
GLint count=0;glGetProgramiv((GLuint)program,GL_ACTIVE_UNIFORMS,&count);bool typed=false;
initial=g2_drain();
if(!g2_clean(initial) || count<0 || count>128) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",initial);fputs("}\n",g2.meta);g2_fail("UNIFORM_COUNT");return;}
for(GLuint i=0;i<(GLuint)count;i++) {char name[128];GLsizei len=0;GLint size=0;GLenum type=0;glGetActiveUniform((GLuint)program,i,sizeof(name),&len,&size,&type,name);
if(len==9 && !memcmp(name,"halfpixel",9) && size==1 && type==GL_FLOAT_VEC2)typed=true;
}
GLfloat radius=0,proj[9]={0},tex_proj[9]={0};
glGetUniformfv((GLuint)program,shader->radius,&radius);
glGetUniformfv((GLuint)program,shader->proj,proj);glGetUniformfv((GLuint)program,shader->tex_proj,tex_proj);
glGetUniformfv((GLuint)program,actual,value);
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT,range,&precision);
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,&min);glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,&mag);
glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,&wraps);glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,&wrapt);
struct g2_errors errors=g2_drain();if(!g2_clean(errors)||!typed) {fputs("{\"kind\":\"uniform-errors\"",g2.meta);g2_error_json("query_errors",errors);fputs("}\n",g2.meta);g2_fail("UNIFORM_QUERY_OR_TYPE");return;}
uint32_t bits[2];memcpy(bits,value,sizeof(bits));
fprintf(g2.meta,"{\"kind\":\"uniform\",\"point\":%u,\"program\":%d,\"location\":%d,\"type\":%u,\"actual_bits\":[%u,%u],\"shader_default_float\":\"mediump\",\"varying\":\"mediump\",\"precision_capability\":[%d,%d,%d],\"operation_precision\":\"NOT_PROVEN\",\"sampler\":[%d,%d,%d,%d],\"source_texture\":%u,\"native_texture_dimensions\":[%u,%u],\"gl_level_dimensions\":\"NOT_PROVEN\"",g2.point,program,actual,GL_FLOAT_VEC2,bits[0],bits[1],range[0],range[1],precision,min,mag,wraps,wrapt,texture->tex,texture->wlr_texture.width,texture->wlr_texture.height);
fprintf(g2.meta,",\"qualifier_basis\":\"FROZEN_LINK_INPUT_SOURCE\",\"shader_source_sha256\":\"%s\"",g2.point<=3?"01664694e4201efb35ec698e89783e220ed930972b5396b86fa842814cd82d4d":"1db325237c9a6c70c2d97518e2f690d448cd006139e9f410cd16e097a1677ad1");
uint32_t radius_bits,proj_bits[9],tex_proj_bits[9];memcpy(&radius_bits,&radius,4);memcpy(proj_bits,proj,sizeof(proj));memcpy(tex_proj_bits,tex_proj,sizeof(tex_proj));
fprintf(g2.meta,",\"other_uniforms\":{\"radius_location\":%d,\"radius_bits\":%u,\"proj_location\":%d,\"proj_bits\":[",shader->radius,radius_bits,shader->proj);
for(unsigned i=0;i<9;i++)fprintf(g2.meta,"%s%u",i?",":"",proj_bits[i]);
fprintf(g2.meta,"],\"tex_proj_location\":%d,\"tex_proj_bits\":[",shader->tex_proj);
for(unsigned i=0;i<9;i++)fprintf(g2.meta,"%s%u",i?",":"",tex_proj_bits[i]);
fputs("]}",g2.meta);g2_state_json("draw_state",&draw_state);
fprintf(g2.meta,",\"blend_stencil\":[%u,%u],\"color_mask\":[%u,%u,%u,%u]",blend,stencil,color_mask[0],color_mask[1],color_mask[2],color_mask[3]);
g2_region(region);fputs("}\n",g2.meta);
}
#endif

View file

@ -0,0 +1,93 @@
"""G2 protocol tooling; never spawns compositor/client/GPU or grants review.
prepare-plan prints prospective framing only. arm requires an external accepted
review and runtime authorization. No retry is implemented. All files exclusive.
"""
import argparse,hashlib,json,os,stat,zlib
from pathlib import Path
from validate_source import need,metadata,halfpixel
CAP=256*1024*1024
FRAME=(800,600)
STAGES=['source','down0','down1','down2','up2','up1','up0','optimized-cache','no-blur-cache','composition-presubmit']
ROOT=Path('/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/acquisition')
def owned(p,mode):
s=p.lstat();need(not stat.S_ISLNK(s.st_mode) and s.st_uid==os.geteuid() and stat.S_IMODE(s.st_mode)==mode,'owned path/mode')
return s
def bounded(p,cap):
s=owned(p,0o600);need(stat.S_ISREG(s.st_mode) and s.st_size<=cap and s.st_nlink==1,'bounded regular exclusive file')
fd=os.open(p,os.O_RDONLY|os.O_NOFOLLOW|os.O_CLOEXEC)
try:
after=os.fstat(fd);need((s.st_dev,s.st_ino)==(after.st_dev,after.st_ino),'path identity')
data=os.read(fd,cap+1);need(len(data)==s.st_size and len(data)<=cap,'bounded stable framing');return data
finally:os.close(fd)
def exclusive(p,b):
fd=os.open(p,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW|os.O_CLOEXEC,0o600)
try:
with os.fdopen(fd,'wb',closefd=False) as f:f.write(b);f.flush();os.fsync(fd)
finally:os.close(fd)
d=os.open(p.parent,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW)
try:os.fsync(d)
finally:os.close(d)
def epoch(directory,e,nonce,prior=0):
need(e in (1,2,3),'epoch')
raw=bounded(directory/f'epoch-{e}.jsonl',1024*1024);need(raw.endswith(b'\n'),'metadata line framing')
rows=[json.loads(x) for x in raw.splitlines()];need(len(rows)==18,'bounded exact event count')
begin,end=rows[0],rows[-1]
need(begin['kind']=='begin' and begin['schema']=='G2-new-v1' and begin['epoch']==e and begin['nonce']==nonce and begin['label']==('A','B','A-return')[e-1],'begin identity')
need(begin['output']=='HEADLESS-1' and begin['intrusive_error_queue'] is True and begin['error_queue_restorable'] is False,'intrusion/output')
need(end['kind']=='end' and end['epoch']==e and end['points']==10 and end['accepted'] is True,'complete accepted epoch; rejection or incomplete A stops all')
# Consumed files intentionally had one hard link during atomic consumption;
# publication is accepted only after arm unlink gives a single link again.
need(bounded(directory/f'epoch-{e}.consumed',80)==f'{nonce} {e}\n'.encode(),'consumed token')
samples=[x for x in rows if x['kind']=='sample'];uniforms=[x for x in rows if x['kind']=='uniform']
need(len(samples)==10 and len(uniforms)==6,'stage/uniform count')
need([x['point'] for x in samples]==list(range(10)) and [x['point'] for x in uniforms]==list(range(1,7)),'strict point order')
need([x['kind'] for x in rows[1:-1]]==['sample']+['uniform','sample']*6+['sample']*3,'query/draw/read sequence')
total=prior;context=samples[0]['context'];source_analysis=[]
for p,s in enumerate(samples):
need(s['point']==p and s['stage']==STAGES[p] and s['epoch']==e and s['pass_sequence']==e and s['context']==context and context!='0','pass/context identity')
need(s['result']=='READ_SUCCESS' and s['published'] is True and s['before']==s['after'],'GL/read/state acceptance')
for key in ('pre_errors','query_errors','read_errors','restore_errors'):need(s[key]=={'exhausted':False,'codes':[]},'error queue ambiguity')
need(s['client_version']>=3 and bytes.fromhex(s['gl_version_hex']).startswith(b'OpenGL ES 3.'),'observed actual GLES3')
a=s['attachment'];need(a[0]==0x8d41 and a[1]>0 and a[2]==0 and a[3:5]==s['native']['dimensions'] and s['status']==0x8cd5 and s['read_buffer']==0x8ce0 and s['samples']==0,'supported RBO attachment')
need(s['channels'][:3]==[8,8,8] and s['channels'][3] in (0,8),'actual alpha storage')
native=s['native'];need(native['fbo_rbo_tex'][1]==a[1] and all(int(native[key],16)>0 for key in ('fx','wlr','image')),'native attachment identity')
d=s['dmabuf'];need(d is not None and d['borrowed'] is True and d['dimensions']==native['dimensions'],'actual borrowed dmabuf')
metadata(dict(d,width=d['dimensions'][0],height=d['dimensions'][1]))
w,h=native['dimensions'];need((w,h)==FRAME,'prospective physical full-frame dimensions');n=w*h*4;need(0<n<=CAP-total and s['bytes']==n,'checked full-frame raw budget');total+=n
need(s['file']==f'epoch-{e}-point-{p}.rgba','fixed exclusive raw filename')
b=bounded(directory/s['file'],CAP);need(len(b)==n and f'{zlib.crc32(b):08x}'==s['crc32'],'raw framing/CRC')
if p==0:
colors=((32,192,224),(176,32,64)) if e==2 else ((245,245,245),(15,25,45))
for y in range(h):
for x in range(w):need(tuple(b[(y*w+x)*4:(y*w+x)*4+3])==colors[(x//8)%2],'native RGB source does not belong to current epoch')
need(s.get('fresh_region_overflow') is not True and len(s['fresh_rectangles'])<=256 and all(len(r)==4 and 0<=r[0]<=r[2]<=w and 0<=r[1]<=r[3]<=h for r in s['fresh_rectangles']),'actual fresh region rectangles')
for u in uniforms:
need(u['type']==0x8b50 and u['program']>0 and u['location']>=0 and u['shader_default_float']=='mediump' and u['varying']=='mediump','uniform native program/type/qualifier')
need(u['sampler']==[9729,9729,33071,33071] and len(u['precision_capability'])==3,'actual sampler/capability')
source_analysis.append(halfpixel(*u['native_texture_dimensions'],u['point']<=3,u['actual_bits']))
need(end['raw_total']==total,'cumulative raw budget')
return {'epoch':e,'raw_total':total,'context':context,'uniform_comparison':source_analysis,'whole_field_causality':'NOT_PROVEN','native_present_buffer':'NOT_PROVEN','gpu_completion':'NOT_PROVEN'}
def gate(directory,gatefile,binary):
need(directory==ROOT and directory.resolve(strict=True)==ROOT,'fixed real acquisition path')
owned(directory,0o700)
g=json.loads(bounded(gatefile,65536));need(g['source_review']=='ACCEPTED' and g['gl_observability']=='PASS' and g['runtime_authorized'] is True and g['pair']==3,'independent external review/authorization gate')
need(hashlib.sha256(binary.read_bytes()).hexdigest()==g['binary_sha256'],'distinct reviewed binary identity')
return g
def arm(directory,e,nonce,gatefile,binary):
gate(directory,gatefile,binary);need(len(nonce)==64 and all(x in '0123456789abcdef' for x in nonce),'nonce')
# Prior complete success is mandatory. An existing consumed/current epoch,
# failed A, or any unexpected future epoch prevents every subsequent arm.
total=0
for prior in range(1,e):total=epoch(directory,prior,nonce,total)['raw_total']
need(e in (1,2,3),'one-shot three epochs')
for future in range(e,5):need(not any(directory.glob(f'epoch-{future}.*')),'no retry/future token')
exclusive(directory/f'epoch-{e}.arm',f'{nonce} {e}\n'.encode())
def plan():
return {'schema':'G2-new-v1','status':'EXPERIMENTAL_SOURCE_ONLY_REVIEW_REQUIRED','pair':3,'max_raw_bytes':CAP,'epochs':['A','B','A-return'],'points':STAGES,'requirements':['Independent R-GPU exact-source acceptance','GL observability acceptance','Explicit third pair and distinct binary identity','External one-shot ledger reservation before compositor spawn','Explicit source A/B/A client commands with original A byte identity','If A incomplete/rejected STOP; preserve bytes, no B, no retry'],'intrusive':['glGetError consumes nonrestorable queue','glReadPixels may synchronize timing'],'unobserved':['native presented physical buffer','GPU completion','GPU object lifetime','atomic generation'],'launches_gpu':False}
if __name__=='__main__':
p=argparse.ArgumentParser();p.add_argument('operation',choices=['prepare-plan','verify-epoch','arm']);p.add_argument('--epoch',type=int);p.add_argument('--nonce');p.add_argument('--gate',type=Path);p.add_argument('--binary',type=Path);a=p.parse_args()
if a.operation=='prepare-plan':print(json.dumps(plan(),indent=2))
elif a.operation=='verify-epoch':print(json.dumps(epoch(ROOT,a.epoch,a.nonce),indent=2))
else:arm(ROOT,a.epoch,a.nonce,a.gate,a.binary)

View file

@ -0,0 +1,390 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wlr_layer_shell_unstable_v1">
<copyright>
Copyright © 2017 Drew DeVault
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="zwlr_layer_shell_v1" version="4">
<description summary="create surfaces that are layers of the desktop">
Clients can use this interface to assign the surface_layer role to
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
rendered with a defined z-depth respective to each other. They may also be
anchored to the edges and corners of a screen and specify input handling
semantics. This interface should be suitable for the implementation of
many desktop shell components, and a broad number of other applications
that interact with the desktop.
</description>
<request name="get_layer_surface">
<description summary="create a layer_surface from a surface">
Create a layer surface for an existing surface. This assigns the role of
layer_surface, or raises a protocol error if another role is already
assigned.
Creating a layer surface from a wl_surface which has a buffer attached
or committed is a client error, and any attempts by a client to attach
or manipulate a buffer prior to the first layer_surface.configure call
must also be treated as errors.
After creating a layer_surface object and setting it up, the client
must perform an initial commit without any buffer attached.
The compositor will reply with a layer_surface.configure event.
The client must acknowledge it and is then allowed to attach a buffer
to map the surface.
You may pass NULL for output to allow the compositor to decide which
output to use. Generally this will be the one that the user most
recently interacted with.
Clients can specify a namespace that defines the purpose of the layer
surface.
</description>
<arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
<arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
<arg name="namespace" type="string" summary="namespace for the layer surface"/>
</request>
<enum name="error">
<entry name="role" value="0" summary="wl_surface has another role"/>
<entry name="invalid_layer" value="1" summary="layer value is invalid"/>
<entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
</enum>
<enum name="layer">
<description summary="available layers for surfaces">
These values indicate which layers a surface can be rendered in. They
are ordered by z depth, bottom-most first. Traditional shell surfaces
will typically be rendered between the bottom and top layers.
Fullscreen shell surfaces are typically rendered at the top layer.
Multiple surfaces can share a single layer, and ordering within a
single layer is undefined.
</description>
<entry name="background" value="0"/>
<entry name="bottom" value="1"/>
<entry name="top" value="2"/>
<entry name="overlay" value="3"/>
</enum>
<!-- Version 3 additions -->
<request name="destroy" type="destructor" since="3">
<description summary="destroy the layer_shell object">
This request indicates that the client will not use the layer_shell
object any more. Objects that have been created through this instance
are not affected.
</description>
</request>
</interface>
<interface name="zwlr_layer_surface_v1" version="4">
<description summary="layer metadata interface">
An interface that may be implemented by a wl_surface, for surfaces that
are designed to be rendered as a layer of a stacked desktop-like
environment.
Layer surface state (layer, size, anchor, exclusive zone,
margin, interactivity) is double-buffered, and will be applied at the
time wl_surface.commit of the corresponding wl_surface is called.
Attaching a null buffer to a layer surface unmaps it.
Unmapping a layer_surface means that the surface cannot be shown by the
compositor until it is explicitly mapped again. The layer_surface
returns to the state it had right after layer_shell.get_layer_surface.
The client can re-map the surface by performing a commit without any
buffer attached, waiting for a configure event and handling it as usual.
</description>
<request name="set_size">
<description summary="sets the size of the surface">
Sets the size of the surface in surface-local coordinates. The
compositor will display the surface centered with respect to its
anchors.
If you pass 0 for either value, the compositor will assign it and
inform you of the assignment in the configure event. You must set your
anchor to opposite edges in the dimensions you omit; not doing so is a
protocol error. Both values are 0 by default.
Size is double-buffered, see wl_surface.commit.
</description>
<arg name="width" type="uint"/>
<arg name="height" type="uint"/>
</request>
<request name="set_anchor">
<description summary="configures the anchor point of the surface">
Requests that the compositor anchor the surface to the specified edges
and corners. If two orthogonal edges are specified (e.g. 'top' and
'left'), then the anchor point will be the intersection of the edges
(e.g. the top left corner of the output); otherwise the anchor point
will be centered on that edge, or in the center if none is specified.
Anchor is double-buffered, see wl_surface.commit.
</description>
<arg name="anchor" type="uint" enum="anchor"/>
</request>
<request name="set_exclusive_zone">
<description summary="configures the exclusive geometry of this surface">
Requests that the compositor avoids occluding an area with other
surfaces. The compositor's use of this information is
implementation-dependent - do not assume that this region will not
actually be occluded.
A positive value is only meaningful if the surface is anchored to one
edge or an edge and both perpendicular edges. If the surface is not
anchored, anchored to only two perpendicular edges (a corner), anchored
to only two parallel edges or anchored to all edges, a positive value
will be treated the same as zero.
A positive zone is the distance from the edge in surface-local
coordinates to consider exclusive.
Surfaces that do not wish to have an exclusive zone may instead specify
how they should interact with surfaces that do. If set to zero, the
surface indicates that it would like to be moved to avoid occluding
surfaces with a positive exclusive zone. If set to -1, the surface
indicates that it would not like to be moved to accommodate for other
surfaces, and the compositor should extend it all the way to the edges
it is anchored to.
For example, a panel might set its exclusive zone to 10, so that
maximized shell surfaces are not shown on top of it. A notification
might set its exclusive zone to 0, so that it is moved to avoid
occluding the panel, but shell surfaces are shown underneath it. A
wallpaper or lock screen might set their exclusive zone to -1, so that
they stretch below or over the panel.
The default value is 0.
Exclusive zone is double-buffered, see wl_surface.commit.
</description>
<arg name="zone" type="int"/>
</request>
<request name="set_margin">
<description summary="sets a margin from the anchor point">
Requests that the surface be placed some distance away from the anchor
point on the output, in surface-local coordinates. Setting this value
for edges you are not anchored to has no effect.
The exclusive zone includes the margin.
Margin is double-buffered, see wl_surface.commit.
</description>
<arg name="top" type="int"/>
<arg name="right" type="int"/>
<arg name="bottom" type="int"/>
<arg name="left" type="int"/>
</request>
<enum name="keyboard_interactivity">
<description summary="types of keyboard interaction possible for a layer shell surface">
Types of keyboard interaction possible for layer shell surfaces. The
rationale for this is twofold: (1) some applications are not interested
in keyboard events and not allowing them to be focused can improve the
desktop experience; (2) some applications will want to take exclusive
keyboard focus.
</description>
<entry name="none" value="0">
<description summary="no keyboard focus is possible">
This value indicates that this surface is not interested in keyboard
events and the compositor should never assign it the keyboard focus.
This is the default value, set for newly created layer shell surfaces.
This is useful for e.g. desktop widgets that display information or
only have interaction with non-keyboard input devices.
</description>
</entry>
<entry name="exclusive" value="1">
<description summary="request exclusive keyboard focus">
Request exclusive keyboard focus if this surface is above the shell surface layer.
For the top and overlay layers, the seat will always give
exclusive keyboard focus to the top-most layer which has keyboard
interactivity set to exclusive. If this layer contains multiple
surfaces with keyboard interactivity set to exclusive, the compositor
determines the one receiving keyboard events in an implementation-
defined manner. In this case, no guarantee is made when this surface
will receive keyboard focus (if ever).
For the bottom and background layers, the compositor is allowed to use
normal focus semantics.
This setting is mainly intended for applications that need to ensure
they receive all keyboard events, such as a lock screen or a password
prompt.
</description>
</entry>
<entry name="on_demand" value="2" since="4">
<description summary="request regular keyboard focus semantics">
This requests the compositor to allow this surface to be focused and
unfocused by the user in an implementation-defined manner. The user
should be able to unfocus this surface even regardless of the layer
it is on.
Typically, the compositor will want to use its normal mechanism to
manage keyboard focus between layer shell surfaces with this setting
and regular toplevels on the desktop layer (e.g. click to focus).
Nevertheless, it is possible for a compositor to require a special
interaction to focus or unfocus layer shell surfaces (e.g. requiring
a click even if focus follows the mouse normally, or providing a
keybinding to switch focus between layers).
This setting is mainly intended for desktop shell components (e.g.
panels) that allow keyboard interaction. Using this option can allow
implementing a desktop shell that can be fully usable without the
mouse.
</description>
</entry>
</enum>
<request name="set_keyboard_interactivity">
<description summary="requests keyboard events">
Set how keyboard events are delivered to this surface. By default,
layer shell surfaces do not receive keyboard events; this request can
be used to change this.
This setting is inherited by child surfaces set by the get_popup
request.
Layer surfaces receive pointer, touch, and tablet events normally. If
you do not want to receive them, set the input region on your surface
to an empty region.
Keyboard interactivity is double-buffered, see wl_surface.commit.
</description>
<arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
</request>
<request name="get_popup">
<description summary="assign this layer_surface as an xdg_popup parent">
This assigns an xdg_popup's parent to this layer_surface. This popup
should have been created via xdg_surface::get_popup with the parent set
to NULL, and this request must be invoked before committing the popup's
initial state.
See the documentation of xdg_popup for more details about what an
xdg_popup is and how it is used.
</description>
<arg name="popup" type="object" interface="xdg_popup"/>
</request>
<request name="ack_configure">
<description summary="ack a configure event">
When a configure event is received, if a client commits the
surface in response to the configure event, then the client
must make an ack_configure request sometime before the commit
request, passing along the serial of the configure event.
If the client receives multiple configure events before it
can respond to one, it only has to ack the last configure event.
A client is not required to commit immediately after sending
an ack_configure request - it may even ack_configure several times
before its next surface commit.
A client may send multiple ack_configure requests before committing, but
only the last request sent before a commit indicates which configure
event the client really is responding to.
</description>
<arg name="serial" type="uint" summary="the serial from the configure event"/>
</request>
<request name="destroy" type="destructor">
<description summary="destroy the layer_surface">
This request destroys the layer surface.
</description>
</request>
<event name="configure">
<description summary="suggest a surface change">
The configure event asks the client to resize its surface.
Clients should arrange their surface for the new states, and then send
an ack_configure request with the serial sent in this configure event at
some point before committing the new surface.
The client is free to dismiss all but the last configure event it
received.
The width and height arguments specify the size of the window in
surface-local coordinates.
The size is a hint, in the sense that the client is free to ignore it if
it doesn't resize, pick a smaller size (to satisfy aspect ratio or
resize in steps of NxM pixels). If the client picks a smaller size and
is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
surface will be centered on this axis.
If the width or height arguments are zero, it means the client should
decide its own window dimension.
</description>
<arg name="serial" type="uint"/>
<arg name="width" type="uint"/>
<arg name="height" type="uint"/>
</event>
<event name="closed">
<description summary="surface should be closed">
The closed event is sent by the compositor when the surface will no
longer be shown. The output may have been destroyed or the user may
have asked for it to be removed. Further changes to the surface will be
ignored. The client should destroy the resource after receiving this
event, and create a new surface if they so choose.
</description>
</event>
<enum name="error">
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
<entry name="invalid_size" value="1" summary="size is invalid"/>
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
</enum>
<enum name="anchor" bitfield="true">
<entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
<entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
<entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
<entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
</enum>
<!-- Version 2 additions -->
<request name="set_layer" since="2">
<description summary="change the layer of the surface">
Change the layer that the surface is rendered on.
Layer is double-buffered, see wl_surface.commit.
</description>
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
</request>
</interface>
</protocol>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
"""Apply and verify G2 against an explicitly supplied reconstructed CORE tree.
Source-only operation: no build, compositor, Wayland or GPU work is performed.
"""
import argparse
import ctypes
import hashlib
import json
import resource
import shutil
import subprocess
from pathlib import Path
resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
assert ctypes.CDLL(None).prctl(4, 0, 0, 0, 0) == 0
KIT = Path(__file__).resolve().parent
EXPECTED = {
"render/fx_renderer/fx_pass.c": "c2886ef259fc91431dfe97841387082420ab80a0fe2f07e7dcdb71fc95731181",
"render/fx_renderer/g2_gl.h": "cd175030be6a2e5d0af036c714c03455ef417f78f20360e00f7e6d1d7be7ab13",
"render/fx_renderer/g2_native.h": "0dfa9e089853a078094736da7f4e133d7fd648500d380dd7f536a7a6f80fdd8e",
}
PATCH_SHA256 = "77d7445ceaf643fd5cc708d31c3f2c77feaeb80f8130c419c55e5514ecc8a75d"
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def tree(path):
return {
str(file.relative_to(path)): sha(file)
for file in sorted(path.rglob("*"))
if file.is_file() and ".git" not in file.relative_to(path).parts
}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--core", required=True, type=Path, help="reconstructed CORE SceneFX source tree")
parser.add_argument("--destination", required=True, type=Path, help="new, absent output directory")
parser.add_argument("--work", required=True, type=Path, help="existing disposable directory for receipts/logs")
args = parser.parse_args()
core = args.core.resolve(strict=True)
destination = args.destination.resolve()
work = args.work.resolve(strict=True)
if not core.is_dir() or not work.is_dir():
parser.error("--core and --work must be existing directories")
if destination.exists():
parser.error("--destination must not already exist")
if destination == core or destination in core.parents or core in destination.parents:
parser.error("--destination must be separate from --core")
patch_file = KIT / "g2-native.patch"
if sha(patch_file) != PATCH_SHA256:
parser.error("kit patch does not match its embedded publication hash")
before = tree(core)
shutil.copytree(core, destination, ignore=shutil.ignore_patterns(".git"))
command = ["patch", "--batch", "--forward", "-p1", "-i", str(patch_file)]
result = subprocess.run(command, cwd=destination, text=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
actual = tree(destination)
changed = {name for name in before.keys() | actual.keys() if before.get(name) != actual.get(name)}
expected_changed = set(EXPECTED)
native_hashes = {name: actual.get(name) for name in sorted(expected_changed)}
receipt = {
"schema": "G2-portable-source-reproduction-v1",
"status": "PASS" if result.returncode == 0 and changed == expected_changed and native_hashes == EXPECTED else "FAIL",
"core": str(core),
"destination": str(destination),
"work": str(work),
"patch_sha256": sha(patch_file),
"command": command,
"exit": result.returncode,
"stdout": result.stdout,
"changed_files": sorted(changed),
"expected_native_sha256": EXPECTED,
"actual_native_sha256": native_hashes,
"all_changed_files_match_embedded_manifest": changed == expected_changed and native_hashes == EXPECTED,
"core_unchanged": tree(core) == before,
"runtime_or_build_started": False,
}
receipt_path = work / "gpu-patch-reproduction.json"
receipt_path.write_text(json.dumps(receipt, indent=2) + "\n")
print(json.dumps(receipt, indent=2))
raise SystemExit(0 if receipt["status"] == "PASS" and receipt["core_unchanged"] else 1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,68 @@
"""Executable G2 scenario adapter. Import has NO run/arm/spawn side effect.
The parent binds an accepted pair #3 Session and reserves its own G2 ledger.
The common Session owns its private sockets, process groups and timeout cleanup.
"""
import hashlib,json,time
from pathlib import Path
from PIL import ImageChops
from protocol import ROOT,arm,epoch,gate,need
def exact_rgb(a,b):
need(a.mode==b.mode=='RGB' and a.size==b.size,'whole-output homologous RGB')
d=ImageChops.difference(a,b)
# Exact all-output zero tolerance. This is a result, not an admission mask.
return {'equal':d.getbbox() is None,'bbox':list(d.getbbox()) if d.getbbox() else None,'extrema':[list(x) for x in d.getextrema()],'pixels':a.width*a.height,'tolerance':0}
def run(s,binding):
"""Must be called once AFTER external review+ledger binding, BEFORE s.start.
binding: gate_file, binary, client, nonce, source_manifest_sha256,
G2_ledger_reserved=True, reviewed_scene_sha256. All operations debit s.ledger.
No retry path; an exception before epoch A completes bypasses B/A-return.
"""
need(binding.get('G2_ledger_reserved') is True,'external closed-ledger reservation absent')
need(s.spec['id']=='G2' and s.spec['binary']=='core','distinct G2 Session identity/static pair')
need(s.auth['binary']==binding['binary'],'accepted exact third executable')
need(s.auth['manifest_sha256']==binding['source_manifest_sha256'],'frozen G2 manifest identity')
gate(ROOT,Path(binding['gate_file']),Path(binding['binary']))
need(not any(ROOT.glob('epoch-*')),'fresh one-shot publication directory')
nonce=binding['nonce'];s.env.update(MOSAIC_G2_DIR=str(ROOT),MOSAIC_G2_NONCE=nonce,WLR_RENDERER='gles2')
s.start()
# Session captures actual executable hash, mapped libraries, renderer and
# explicit private sockets. Its caller owns finally/cleanup and verdict.
client=Path(binding['client']);need(client.is_file() and hashlib.sha256(client.read_bytes()).hexdigest()==binding['client_sha256'],'new client identity')
s.cmd('workspace 2');s.spawn('g2-reference',[client,'reference']);s.wait(lambda:s.find('g2-reference'));rid=s.find('g2-reference')['id'];s.cmd(f'[con_id={rid}] border none')
s.cmd('workspace 1');s.cmd('layout mosaic');s.cmd('gaps inner 0')
s.spawn('g2-background',[client,'background']);s.wait(lambda:'BACKGROUND_CONFIGURED ' in s.log('g2-background'))
s.spawn('g2-glass',[client,'glass']);s.wait(lambda:s.find('g2-glass'));gid=s.find('g2-glass')['id'];s.cmd(f'[con_id={gid}] border none')
s.cmd('blur enable');s.cmd('blur_xray disable');s.cmd('blur_passes 3');s.cmd('blur_radius 5');s.cmd('blur_brightness 1');s.cmd('blur_contrast 1');s.cmd('blur_noise 0');s.cmd('blur_saturation 1')
# Settle setup before the first arm. This sleep carries no proof of GPU
# completion; exact native source admission rejects any wrong candidate.
time.sleep(.35)
reference=s.capture('G2-H2-baseline1','HEADLESS-2');time.sleep(.15)
reference2=s.capture('G2-H2-baseline2','HEADLESS-2')
baseline=exact_rgb(reference,reference2);s.save('G2-H2-baseline',baseline)
need(baseline['equal'],'static whole H2 baseline changed before A')
captures=[];validated=[];total=0
for e,command in enumerate(('G2-A','G2-B','G2-A-return'),1):
s.debit('mutation');s.record('G2-epoch-reservation',epoch=e,raw_cap=256*1024*1024)
arm(ROOT,e,nonce,Path(binding['gate_file']),Path(binding['binary']))
s.proc['g2-background'].stdin.write(command+'\n');s.proc['g2-background'].stdin.flush()
s.wait(lambda:f'G2_SOURCE_BYTES command={command} ' in s.log('g2-background'))
path=ROOT/f'epoch-{e}.jsonl'
def complete_or_rejected():
if not path.exists():return False
data=path.read_bytes();need(len(data)<=1024*1024,'bounded metadata while waiting')
if b'"kind":"rejected"' in data:raise RuntimeError(f'epoch {e} rejected; STOP, no next command/retry')
return data.endswith(b'\n') and b'"kind":"end"' in data
s.wait(complete_or_rejected)
# Failure here exits before subsequent epoch token or source command.
result=epoch(ROOT,e,nonce,total);total=result['raw_total'];validated.append(result)
pictures=s.pair_capture(f'G2-{command}');captures.append(pictures);s.snapshot(f'G2-{command}')
h2=exact_rgb(reference,pictures[1]);s.save(f'G2-{command}-wholeH2',h2)
need(h2['equal'],'whole H2 changed: rejected epoch, STOP without retry')
s.record('G2-epoch-accepted',epoch=e,command=command,native_raw_total=total)
whole_h1=exact_rgb(captures[0][0],captures[2][0]);whole_h2=[exact_rgb(captures[0][1],x[1]) for x in captures[1:]]
sa=(ROOT/'epoch-1-point-0.rgba').read_bytes();sr=(ROOT/'epoch-3-point-0.rgba').read_bytes()
result={'schema':'G2-new-v1','epochs':validated,'native_source_A_Areturn_exact':sa==sr,'whole_H1_A_Areturn':whole_h1,'whole_H2_baseline':baseline,'whole_H2_A_B_Areturn':whole_h2,'whole_field_causality':'NOT_PROVEN','physical_present_buffer':'NOT_PROVEN','gpu_completion':'NOT_PROVEN','atomic_generation':'NOT_PROVEN','instrumentation':'INTRUSIVE_ERROR_QUEUE_AND_READBACK_SYNC','source_commands':['G2-A','G2-B','G2-A-return']}
s.save('G2-result',result)
for name in ('g2-glass','g2-background','g2-reference'):s.close_client(name,'close')
return result

View file

@ -0,0 +1,98 @@
"""Offline source-only checks using explicit reconstructed CORE prerequisites."""
import argparse
import ctypes
import json
import resource
import shlex
import subprocess
import sys
from pathlib import Path
resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
assert ctypes.CDLL(None).prctl(4, 0, 0, 0, 0) == 0
KIT = Path(__file__).resolve().parent
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--core", required=True, type=Path, help="reconstructed CORE SceneFX source tree")
parser.add_argument("--compile-commands", required=True, type=Path, help="CORE compile_commands.json")
parser.add_argument("--work", required=True, type=Path, help="existing disposable directory for outputs/logs")
args = parser.parse_args()
core = args.core.resolve(strict=True)
compile_commands = args.compile_commands.resolve(strict=True)
work = args.work.resolve(strict=True)
if not core.is_dir() or not work.is_dir():
parser.error("--core and --work must be existing directories")
if not compile_commands.is_file():
parser.error("--compile-commands must name a regular file")
entries = json.loads(compile_commands.read_text())
source = core / "render/fx_renderer/fx_pass.c"
entry = next((item for item in entries
if Path(item["file"]).as_posix().endswith("/render/fx_renderer/fx_pass.c")), None)
if entry is None:
parser.error("compile_commands.json has no entry for --core/render/fx_renderer/fx_pass.c")
args_cc = shlex.split(entry["command"])
args_cc = args_cc[args_cc.index("cc"):]
base = []
skip = False
for token in args_cc:
if skip:
skip = False
continue
if token in ("-o", "-MF", "-MQ"):
skip = True
continue
if token in ("-MD", "-c") or token.startswith("-std="):
continue
if token.endswith("/fx_pass.c"):
continue
base.append(token)
base += ["-std=c17", "-D_GNU_SOURCE"]
protocol_runner = """import sys,tempfile
from pathlib import Path
from unittest.mock import patch
sys.path.insert(0, sys.argv[1])
import test_protocol as t
t.BASE=Path(sys.argv[2])
with tempfile.TemporaryDirectory(prefix='protocol-controlled-', dir=t.BASE) as temp:
p=Path(temp); p.chmod(0o700)
for name in ('framing','accepted','rejected','token'): (p/name).mkdir(mode=0o700)
with patch.object(t.protocol, 'FRAME', (2,3)):
t.framing(p/'framing'); t.token_test(p/'token')
t.scenario_test(p/'accepted',False); t.scenario_test(p/'rejected',True)
"""
commands = [
(["cc", "-std=c17", "-Wall", "-Wextra", "-Werror", "-I" + str(KIT), str(KIT / "test_gl.c"), "-o", str(work / "test_gl")], work),
([str(work / "test_gl")], work),
(["python", str(KIT / "validate_source.py")], work),
(base + [str(source), "-fsyntax-only"], Path(entry["directory"])),
([sys.executable, "-c", protocol_runner, str(KIT), str(work)], work),
(base + ["-I" + str(core / "render/fx_renderer"), "-Wno-unused-function", "-ffunction-sections", "-fdata-sections", str(KIT / "test_native.c"), "-Wl,--gc-sections", "-o", str(work / "test_native")], Path(entry["directory"])),
([str(work / "test_native")], work),
]
commands += [(["wayland-scanner", "client-header", str(KIT / "protocols" / xml), str(work / header)], work)
for xml, header in [("wlr-layer-shell-unstable-v1.xml", "layer-shell-client.h"), ("xdg-shell.xml", "xdg-shell-client.h")]]
commands += [(["cc", "-std=c17", "-Wall", "-Wextra", "-Werror", "-Wno-unused-parameter", "-I" + str(work), "-fsyntax-only", str(KIT / "clients-g2.c")], work)]
rows = []
for index, (command, cwd) in enumerate(commands):
result = subprocess.run(command, cwd=cwd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
log = work / f"final-g2-test-{index}.log"
log.write_text(result.stdout)
rows.append({"command": command, "cwd": str(cwd), "returncode": result.returncode, "log": str(log)})
print(f"{index}: exit={result.returncode}\n{result.stdout}")
if result.returncode:
break
passed = len(rows) == len(commands) and all(row["returncode"] == 0 for row in rows)
(work / "gpu-targeted-tests.json").write_text(json.dumps({
"schema": "G2-targeted-source-only-portable-v1", "core": str(core),
"compile_commands": str(compile_commands), "work": str(work),
"core_limit": [0, 0], "test_process_dumpable": 0,
"campaigns_started": 0, "commands": rows, "pass": passed,
"native_build_or_runtime_started": False,
}, indent=2) + "\n")
raise SystemExit(0 if passed else 1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,36 @@
"""Compile the exact production g2_begin body into the reviewed stub harness."""
import ctypes,json,os,resource,subprocess,tempfile
from pathlib import Path
ROOT=Path('/var/tmp/swayfx-mosaic-corec-v2-i516p6po');KIT=Path(__file__).resolve().parent
WORK=ROOT/'gpu-fifo-fix/work';WORK.mkdir(parents=True,exist_ok=True)
resource.setrlimit(resource.RLIMIT_CORE,(0,0));assert ctypes.CDLL(None).prctl(4,0,0,0,0)==0
header=(ROOT/'sources/scene-gpu/render/fx_renderer/g2_native.h').read_text()
marker='static void g2_begin(struct fx_gles_render_pass *pass,struct fx_framebuffer *source,struct fx_render_blur_pass_options *options) {'
start=header.index(marker);brace=header.index('{',start);depth=0;end=None
for i in range(brace,len(header)):
if header[i]=='{':depth+=1
elif header[i]=='}':
depth-=1
if depth==0:end=i+1;break
assert end is not None
body=header[start:end]
fixture=(ROOT/'ownreview-gpu-oom-build/fifo-exact-g2-begin.c').read_text()
fstart=fixture.index(marker);fbrace=fixture.index('{',fstart);depth=0;fend=None
for i in range(fbrace,len(fixture)):
if fixture[i]=='{':depth+=1
elif fixture[i]=='}':
depth-=1
if depth==0:fend=i+1;break
assert fend is not None
fixture=fixture[:fstart]+body+fixture[fend:]
fixture=fixture.replace('static void g2_fail(const char *s){(void)s;}','static void g2_fail(const char *s){(void)s;g2.stopped=true;}')
source=WORK/'fifo-exact-g2-begin-corrected.c';source.write_text(fixture)
binary=WORK/'fifo-exact-g2-begin-corrected'
cmd=['cc','-std=c17','-Wall','-Wextra','-Werror','-Wno-unused-parameter','-Wno-unused-function',str(source),'-o',str(binary)]
p=subprocess.run(cmd,text=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT);print(p.stdout,end='');assert p.returncode==0
with tempfile.TemporaryDirectory(prefix='fifo-g2-begin-',dir=WORK) as d:
os.chmod(d,0o700);fifo=Path(d)/'epoch-1.arm';os.mkfifo(fifo,0o600)
r=subprocess.run([str(binary),d],timeout=3,text=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
print(r.stdout,end='');assert r.returncode==0, r.returncode
assert fifo.exists() and not (Path(d)/'epoch-1.consumed').exists()
print('PASS exact extracted production g2_begin rejects writerless FIFO promptly before read/consume')

View file

@ -0,0 +1,80 @@
#define _GNU_SOURCE
#include "g2_gl.h"
#include <assert.h>
#include <limits.h>
#include <sys/resource.h>
#include <sys/prctl.h>
static struct g2_state state;
static int mode, read_calls, unsupported, pending, query_count;
static bool read_done;
static const char *version="OpenGL ES 3.2 FakeGL";
static void reset(int m) {
memset(&state,0,sizeof(state));state.read_fbo=11;state.draw_fbo=12;state.rbo=13;
state.pack=8;state.pbo=15;state.row=32;state.skip_rows=2;state.skip_pixels=3;
state.viewport[2]=2;state.viewport[3]=3;state.scissor[2]=2;state.scissor[3]=3;
state.program=21;state.active=GL_TEXTURE0;state.texture=22;
mode=m;read_calls=unsupported=pending=query_count=0;read_done=false;
version=(m==6||m==14)?"OpenGL ES 2.0 FakeGL":"OpenGL ES 3.2 FakeGL";
}
EGLContext EGLAPIENTRY eglGetCurrentContext(void) {return mode==5?EGL_NO_CONTEXT:(EGLContext)(uintptr_t)(mode==17&&read_done?7:5);}
EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) {return (EGLDisplay)(uintptr_t)6;}
EGLenum EGLAPIENTRY eglQueryAPI(void) {return mode==12?EGL_OPENGL_API:EGL_OPENGL_ES_API;}
EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay d,EGLContext c,EGLint a,EGLint *v) {(void)d;(void)c;(void)a;*v=mode==6?2:3;return mode==13?EGL_FALSE:EGL_TRUE;}
GLenum GL_APIENTRY glGetError(void) {
if(mode==1 && query_count==0) {query_count++;return GL_INVALID_OPERATION;}
if(mode==8)return GL_INVALID_OPERATION;
if(pending){GLenum e=(GLenum)pending;pending=0;return e;}return GL_NO_ERROR;
}
const GLubyte *GL_APIENTRY glGetString(GLenum e) {(void)e;return (const GLubyte *)version;}
void GL_APIENTRY glGetIntegerv(GLenum e,GLint *v) {
if(mode==6)unsupported++;
if(mode==2 && query_count++==0)pending=GL_INVALID_ENUM;
switch(e) {
#define FIELD(e,f) case e:*v=state.f;break
case GL_READ_BUFFER:*v=mode==16?GL_NONE:GL_COLOR_ATTACHMENT0;break;
FIELD(GL_READ_FRAMEBUFFER_BINDING,read_fbo);FIELD(GL_DRAW_FRAMEBUFFER_BINDING,draw_fbo);
FIELD(GL_RENDERBUFFER_BINDING,rbo);FIELD(GL_PACK_ALIGNMENT,pack);FIELD(GL_PIXEL_PACK_BUFFER_BINDING,pbo);
FIELD(GL_PACK_ROW_LENGTH,row);FIELD(GL_PACK_SKIP_ROWS,skip_rows);FIELD(GL_PACK_SKIP_PIXELS,skip_pixels);
FIELD(GL_CURRENT_PROGRAM,program);FIELD(GL_ACTIVE_TEXTURE,active);FIELD(GL_TEXTURE_BINDING_2D,texture);
case GL_VIEWPORT:memcpy(v,state.viewport,sizeof(state.viewport));break;
case GL_SCISSOR_BOX:memcpy(v,state.scissor,sizeof(state.scissor));break;
default:unsupported++;pending=GL_INVALID_ENUM;break;
}
}
GLboolean GL_APIENTRY glIsEnabled(GLenum e) {(void)e;return state.scissor_on;}
void GL_APIENTRY glBindFramebuffer(GLenum e,GLuint v) {if(e==GL_READ_FRAMEBUFFER)state.read_fbo=(GLint)v;else state.draw_fbo=(GLint)v;}
void GL_APIENTRY glBindRenderbuffer(GLenum e,GLuint v) {(void)e;state.rbo=(GLint)v;}
void GL_APIENTRY glBindBuffer(GLenum e,GLuint v) {(void)e;if(mode==11&&read_done&&v==15)pending=GL_INVALID_OPERATION;if(!(mode==4&&read_done))state.pbo=(GLint)v;}
void GL_APIENTRY glPixelStorei(GLenum e,GLint v) {
if(mode==9&&e==GL_PACK_ALIGNMENT&&v==1)pending=GL_INVALID_OPERATION;
switch(e) {case GL_PACK_ALIGNMENT:state.pack=v;break;case GL_PACK_ROW_LENGTH:state.row=v;break;
case GL_PACK_SKIP_ROWS:state.skip_rows=v;break;case GL_PACK_SKIP_PIXELS:state.skip_pixels=v;break;default:unsupported++;}
}
void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum t,GLenum a,GLenum e,GLint *v) {
(void)t;(void)a;if(mode==10)pending=GL_INVALID_ENUM;*v=e==GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE?(mode==7?GL_TEXTURE:GL_RENDERBUFFER):e==GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME?44:0;
}
void GL_APIENTRY glGetRenderbufferParameteriv(GLenum t,GLenum e,GLint *v) {
(void)t;*v=e==GL_RENDERBUFFER_WIDTH?2:e==GL_RENDERBUFFER_HEIGHT?3:e==GL_RENDERBUFFER_INTERNAL_FORMAT?GL_RGBA8:e==GL_RENDERBUFFER_SAMPLES?(mode==15?4:0):8;
}
GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum e) {(void)e;return GL_FRAMEBUFFER_COMPLETE;}
void GL_APIENTRY glReadPixels(GLint x,GLint y,GLsizei w,GLsizei h,GLenum f,GLenum t,void *p) {
(void)x;(void)y;assert(f==GL_RGBA&&t==GL_UNSIGNED_BYTE);assert(state.pbo==0&&state.pack==1&&state.row==0);
read_calls++;read_done=true;if(mode==3)pending=GL_INVALID_OPERATION;else memset(p,0,(size_t)w*(size_t)h*4);
}
int main(void) {
struct rlimit r={0,0};assert(!setrlimit(RLIMIT_CORE,&r));assert(!prctl(PR_SET_DUMPABLE,0));
const char *reasons[]={"READ_SUCCESS","PREEXISTING_GL_ERRORS","STATE_QUERY_ERROR","READ_GL_ERROR","RESTORE_FAILED","UNKNOWN_CONTEXT","GLES_STATE_NOT_SUPPORTED","TEXTURE_ATTACHMENT_DIMENSIONS_NOT_PROVEN","PREEXISTING_GL_ERRORS","PACK_QUERY_ERROR","ATTACHMENT_QUERY_ERROR","RESTORE_FAILED","UNKNOWN_CONTEXT","EGL_QUERY_FAILED","GLES_STATE_NOT_SUPPORTED","ATTACHMENT_UNSUPPORTED","ATTACHMENT_UNSUPPORTED","RESTORE_FAILED"};
for(int i=0;i<18;i++) {
reset(i);struct g2_state before=state;struct g2_sample s=g2_read(99,2,3,0);
assert(s.success==(i==0));assert(!strcmp(s.reason,reasons[i]));assert(!unsupported);
if(i==0||i==3||i==7)assert(!memcmp(&state,&before,sizeof(state)));
if(i==0){assert(read_calls==1&&s.bytes==24);for(size_t n=0;n<s.bytes;n++)assert(s.pixels[n]==0);}
if(i==1||i==2||i==5||i==6||i==7||i==8||i==9||i==10||i==12||i==13||i==14||i==15||i==16)assert(!read_calls);
if(i==8)assert(s.pre.exhausted&&s.pre.count==G2_ERRORS);
printf("PASS exact g2_read mode=%d reason=%s\n",i,s.reason);free(s.pixels);
}
size_t n=0;assert(!g2_size(INT_MAX,INT_MAX,0,&n));assert(!g2_size(2,3,G2_CAP-23,&n));assert(!g2_size(-1,3,0,&n));
assert(g2_size(2,3,G2_CAP-24,&n)&&n==24);
reset(0);struct g2_sample s=g2_read(99,INT_MAX,INT_MAX,0);assert(!s.success&&!read_calls);free(s.pixels);
puts("PASS size/overflow/exact-cap; black RGBA alpha zero is valid, no sentinel gate");return 0;
}

View file

@ -0,0 +1,68 @@
#include <GLES3/gl3.h> /* private G2 state observability */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <pixman.h>
#include <time.h>
#include <unistd.h>
#include <wlr/render/allocator.h>
#include <wlr/render/drm_syncobj.h>
#include <wlr/util/transform.h>
#include <wlr/util/log.h>
#include <wlr/util/region.h>
#include "render/egl.h"
#include "render/fx_renderer/fx_renderer.h"
#include "render/fx_renderer/shaders.h"
#include "render/pass.h"
#include "render/tracy.h"
#include "scenefx/render/fx_renderer/fx_offscreen_buffers.h"
#include "scenefx/render/fx_renderer/fx_renderer.h"
#include "scenefx/types/fx/blur_data.h"
#include "util/matrix.h"
#include "g2_native.h"
#include <sys/resource.h>
#include <sys/prctl.h>
int main(void) {
struct rlimit r={0,0};assert(!setrlimit(RLIMIT_CORE,&r));assert(!prctl(PR_SET_DUMPABLE,0));
struct fx_gles_render_pass passes[9]={0};
struct wlr_output h1={.name="HEADLESS-1",.scale=1,.transform=WL_OUTPUT_TRANSFORM_NORMAL};
struct wlr_output h2={.name="HEADLESS-2",.scale=1,.transform=WL_OUTPUT_TRANSFORM_NORMAL};
for(unsigned i=0;i<9;i++) {
g2_track_output(&passes[i],i%2?&h2:&h1);
assert(g2_intended_output(&passes[i])==(i%2==0));
g2_forget_output(&passes[i]);assert(!g2_intended_output(&passes[i]));
}
assert(!g2.stopped);
g2_track_output(&passes[0],&h1);assert(g2_intended_output(&passes[0]));
g2_track_output(&passes[0],&h2);assert(!g2_intended_output(&passes[0]));
g2_forget_output(&passes[0]);g2_track_output(&passes[0],&h1);assert(g2_intended_output(&passes[0]));g2_forget_output(&passes[0]);
for(unsigned i=0;i<9;i++)g2_track_output(&passes[i],i%2?&h2:&h1);
assert(g2.stopped && !g2_intended_output(&passes[8]));
for(unsigned i=0;i<9;i++) {g2_forget_output(&passes[i]);}
g2.stopped=false;
puts("PASS nine sequential passes/output forget, pointer reuse H1/H2 and nine-simultaneous fail-closed overflow");
struct g2_sample s={.width=800,.height=600,.bytes=800*600*4};s.pixels=calloc(1,s.bytes);assert(s.pixels);
for(int y=0;y<600;y++)for(int x=0;x<800;x++) {
const unsigned char a[2][3]={{245,245,245},{15,25,45}};
memcpy(s.pixels+((size_t)y*800+(size_t)x)*4,a[(x/8)%2],3);
}
assert(g2_expected_source(&s,1));assert(g2_expected_source(&s,3));assert(!g2_expected_source(&s,2));
s.pixels[4]^=1;assert(!g2_expected_source(&s,1));s.pixels[4]^=1;
for(int y=0;y<600;y++)for(int x=0;x<800;x++) {
const unsigned char b[2][3]={{32,192,224},{176,32,64}};
memcpy(s.pixels+((size_t)y*800+(size_t)x)*4,b[(x/8)%2],3);
}
assert(g2_expected_source(&s,2));assert(!g2_expected_source(&s,3));free(s.pixels);
assert(g2_crc((const unsigned char *)"123456789",9)==UINT32_C(0xcbf43926));
FILE *f=tmpfile();assert(f && g2_owned(fileno(f),0600));assert(g2_write(fileno(f),"frame",5));assert(!fseek(f,0,SEEK_SET));char b[6]={0};assert(fread(b,1,5,f)==5 && !strcmp(b,"frame"));assert(!fclose(f));
assert(!setenv("MOSAIC_G2_DIR","/tmp",1));assert(!setenv("MOSAIC_G2_NONCE","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",1));
assert(!g2_open() && g2.stopped && g2.dir==-1);
puts("PASS exact native source epoch RGB admission A/B/A-return and negative substitution");
puts("PASS exact native CRC framing/writer/owned FD cleanup and wrong realpath refusal");
return 0;
}

View file

@ -0,0 +1,110 @@
"""Controlled synthetic framing and scenario tests; NO GPU/native evidence."""
import resource,ctypes
resource.setrlimit(resource.RLIMIT_CORE,(0,0))
assert ctypes.CDLL(None).prctl(4,0,0,0,0)==0
import json,os,shutil,tempfile,zlib,copy
from pathlib import Path
from unittest.mock import patch
from PIL import Image
import protocol,scenario
from validate_source import Rejected
NONCE='a'*64
BASE=Path('/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-fifo-fix/work')
def write_epoch(d,e,total):
raw=bytes(([32,192,224,255] if e==2 else [245,245,245,255])*6);total+=len(raw)*10
rows=[dict(kind='begin',schema='G2-new-v1',epoch=e,nonce=NONCE,label=('A','B','A-return')[e-1],output='HEADLESS-1',intrusive_error_queue=True,error_queue_restorable=False)]
for p,stage in enumerate(protocol.STAGES):
if 1<=p<=6:rows.append(dict(kind='uniform',point=p,type=0x8b50,program=5,location=3,shader_default_float='mediump',varying='mediump',sampler=[9729,9729,33071,33071],precision_capability=[15,15,10],native_texture_dimensions=[2,3],actual_bits=[1,2]))
filename=f'epoch-{e}-point-{p}.rgba';protocol.exclusive(d/filename,raw)
rows.append(dict(kind='sample',epoch=e,point=p,stage=stage,pass_sequence=e,context='5',result='READ_SUCCESS',published=True,before={'pack':8},after={'pack':8},pre_errors={'exhausted':False,'codes':[]},query_errors={'exhausted':False,'codes':[]},read_errors={'exhausted':False,'codes':[]},restore_errors={'exhausted':False,'codes':[]},client_version=3,gl_version_hex=b'OpenGL ES 3.2 ControlledFake'.hex(),attachment=[0x8d41,44,0,2,3,0x8058],channels=[8,8,8,8],status=0x8cd5,read_buffer=0x8ce0,samples=0,native={'dimensions':[2,3],'fbo_rbo_tex':[11,44,22],'fx':'1','wlr':'2','image':'3'},dmabuf={'borrowed':True,'dimensions':[2,3],'format':int.from_bytes(b'AB24','little'),'modifier':'0000000000000000','planes':[{'stride':8,'offset':0}]},bytes=len(raw),file=filename,crc32=f'{zlib.crc32(raw):08x}',fresh_rectangles=[[0,0,2,3]]))
rows.append(dict(kind='end',epoch=e,points=10,accepted=True,raw_total=total))
protocol.exclusive(d/f'epoch-{e}.jsonl',b''.join((json.dumps(row,separators=(',',':'))+'\n').encode() for row in rows));(None if (d/f'epoch-{e}.consumed').exists() else protocol.exclusive(d/f'epoch-{e}.consumed',f'{NONCE} {e}\n'.encode()))
return rows,total
def framing(d):
rows,total=write_epoch(d,1,0);assert protocol.epoch(d,1,NONCE)['raw_total']==240
tests=[('read-error',lambda x:x[1]['read_errors']['codes'].append(0x502)),('restore',lambda x:x[1]['after'].update(pack=1)),('context',lambda x:x[1].update(context='0')),('path',lambda x:x[1].update(file='../escape')),('budget',lambda x:x[1].update(bytes=protocol.CAP+1)),('incomplete',lambda x:x.pop()),('stage',lambda x:x[1].update(stage='presented-buffer'))]
p=d/'epoch-1.jsonl'
for label,mutate in tests:
changed=copy.deepcopy(rows);mutate(changed);p.write_text(''.join(json.dumps(x)+'\n' for x in changed));p.chmod(0o600)
try:protocol.epoch(d,1,NONCE)
except (Rejected,KeyError,AssertionError):print('PASS controlled framing rejection',label)
else:raise AssertionError(label)
p.write_text(''.join(json.dumps(x)+'\n' for x in rows));p.chmod(0o600)
q=d/'epoch-1-point-0.rgba';q.write_bytes(b'bad')
try:protocol.epoch(d,1,NONCE)
except Rejected:print('PASS raw truncation/CRC rejection')
else:raise AssertionError('truncation')
q.unlink();q.symlink_to('/dev/null')
try:protocol.bounded(q,10)
except Rejected:print('PASS symlink refusal')
else:raise AssertionError('symlink')
try:protocol.exclusive(p,b'overwrite')
except FileExistsError:print('PASS exclusive publication refusal')
else:raise AssertionError('exclusive')
assert scenario.exact_rgb(Image.new('RGB',(2,3)),Image.new('RGB',(2,3)))['equal']
a=Image.new('RGB',(2,3));b=a.copy();b.putpixel((1,2),(1,0,0));assert not scenario.exact_rgb(a,b)['equal']
print('PASS whole H1/H2 all-pixel zero RGB tolerance')
def token_test(d):
with patch.object(protocol,'gate',lambda *args:None):
protocol.arm(d,1,NONCE,d/'gate',d/'binary')
assert protocol.bounded(d/'epoch-1.arm',80)==f'{NONCE} 1\n'.encode()
for e in (1,2):
try:protocol.arm(d,e,NONCE,d/'gate',d/'binary')
except (Rejected,FileNotFoundError):pass
else:raise AssertionError('retry or B before complete A')
os.link(d/'epoch-1.arm',d/'epoch-1.consumed');(d/'epoch-1.arm').unlink()
write_epoch(d,1,0)
protocol.arm(d,2,NONCE,d/'gate',d/'binary')
try:protocol.arm(d,3,NONCE,d/'gate',d/'binary')
except (Rejected,FileNotFoundError):pass
else:raise AssertionError('return before complete B')
print('PASS exact arm token nonce/exclusive/replay and first A completion gate, controlled directory')
class Session:
def __init__(self,d,fail=False):
self.d=d;self.fail=fail;self.commands=[];self.captures=0;self.total=0;self.env={};self.spec={'id':'G2','binary':'core'};self.auth={'binary':str(d/'fake-binary'),'manifest_sha256':'controlled'};self.proc={};self.data={};self.saved={}
def start(self):self.data['started']=True
def cmd(self,*a,**kw):pass
def spawn(self,name,argv):
parent=self
class Input:
def write(self,text):
parent.commands.append(text.strip());e=len(parent.commands)
if parent.fail:protocol.exclusive(parent.d/f'epoch-{e}.jsonl',b'{"kind":"rejected"}\n')
else:_,parent.total=write_epoch(parent.d,e,parent.total)
def flush(self):pass
self.proc[name]=type('Process',(),{'stdin':Input()})()
def wait(self,fn):assert fn()
def find(self,name):return {'id':1}
def log(self,name):return 'BACKGROUND_CONFIGURED '+' '.join('G2_SOURCE_BYTES command='+x+' ' for x in self.commands)
def debit(self,*a):pass
def record(self,*a,**kw):pass
def capture(self,*a):self.captures+=1;return Image.new('RGB',(2,3))
def pair_capture(self,*a):self.captures+=2;return [Image.new('RGB',(2,3)),Image.new('RGB',(2,3))]
def snapshot(self,*a):pass
def save(self,name,result):self.saved[name]=result
def close_client(self,*a):pass
def scenario_test(d,fail):
s=Session(d,fail);binary=d/'fake-binary';binary.write_bytes(b'controlled')
binding=dict(G2_ledger_reserved=True,binary=str(binary),source_manifest_sha256='controlled',gate_file=str(d/'gate'),client=str(binary),client_sha256=__import__('hashlib').sha256(binary.read_bytes()).hexdigest(),nonce=NONCE)
armed=[]
with patch.object(scenario,'ROOT',d),patch.object(scenario,'gate',lambda *args:None),patch.object(scenario,'arm',lambda root,e,*args:armed.append(e)),patch.object(scenario.time,'sleep',lambda seconds:None):
if fail:
try:scenario.run(s,binding)
except RuntimeError:pass
else:raise AssertionError('rejected A continued')
assert s.commands==['G2-A'] and armed==[1] and s.captures==2
print('PASS rejected first A stops B/A-return: exact executable adapter, fake Session only')
else:
r=scenario.run(s,binding);assert s.commands==['G2-A','G2-B','G2-A-return'] and armed==[1,2,3] and s.captures==8 and r['whole_H1_A_Areturn']['equal']
print('PASS one-shot A/B/A adapter flow, eight captures with whole H1/H2 and H2 baseline, controlled framing')
if __name__=='__main__':
with tempfile.TemporaryDirectory(prefix='protocol-controlled-',dir=BASE) as temp:
p=Path(temp);p.chmod(0o700)
for name in ('framing','accepted','rejected','token'):(p/name).mkdir(mode=0o700)
with patch.object(protocol,'FRAME',(2,3)):
framing(p/'framing');token_test(p/'token');scenario_test(p/'accepted',False);scenario_test(p/'rejected',True)

View file

@ -0,0 +1,53 @@
"""New G2 offline controls. Historical G1 stays HISTORICAL_REPORTED_ONLY."""
import resource,ctypes
resource.setrlimit(resource.RLIMIT_CORE,(0,0))
assert ctypes.CDLL(None).prctl(4,0,0,0,0)==0
import hashlib,json,struct
from pathlib import Path
HEADER_SHA='992f33804acda60b0b46f1a272942c3592484ea3217d469239f1cb12249de2eb'
BPP={int.from_bytes(s,'little'):4 for s in (b'AB24',b'XB24',b'AR24',b'XR24')}
AMD='020000001046bb04'
class Rejected(ValueError):pass
def need(x,msg):
if not x:raise Rejected(msg)
def metadata(o):
need(type(o['width']) is int and type(o['height']) is int and 0<o['width']<=2**31-1 and 0<o['height']<=2**31-1,'dimensions')
need(o['format'] in BPP,'unknown FOURCC')
need(o['modifier'] in ('0000000000000000',AMD),'unknown modifier')
planes=o['planes'];need(len(planes)==(2 if o['modifier']==AMD else 1),'plane count')
for p in planes:
need(all(type(p[k]) is int and 0<=p[k]<=2**32-1 for k in ('stride','offset')) and p['stride']>0,'plane uint32')
need(p['offset']+p['stride']<=2**64-1,'overflow')
p=planes[0];need(p['stride']>=o['width']*BPP[o['format']],'image stride')
end=p['offset']+p['stride']*(o['height']-1)+o['width']*BPP[o['format']]
need(end<=2**64-1,'image overflow')
# No fabricated DCC extent or same-allocation restriction. fstat sizes are
# recorded as descriptor metadata, not interpreted as allocation length.
return {'image_stride':'PASS','auxiliary_stride':'NOT_AN_IMAGE_STRIDE' if len(planes)>1 else 'N/A','allocation_bounds':'NOT_PROVEN','fd_ownership':'BORROWED' if o.get('borrowed') is True else 'NOT_PROVEN','decode_support':'NOT_PROVEN'}
def f32(x):return struct.unpack('<f',struct.pack('<f',x))[0]
def bits(x):return struct.unpack('<I',struct.pack('<f',x))[0]
def halfpixel(width,height,down,observed):
need(width>0 and height>0 and len(observed)==2 and all(type(x)is int and 0<=x<=2**32-1 for x in observed),'uniform framing')
divisor=f32(2.0)
ideal=[f32(f32(.5)/f32(f32(n)/divisor if down else f32(n)*divisor)) for n in (width,height)]
return {'observed_bits':observed,'cpu_float32_ideal_bits':[bits(x) for x in ideal],'comparison_gate':'NONE','effective_arithmetic':'NOT_PROVEN','capability_is_per_operation_precision':False}
def test():
from copy import deepcopy
need(hashlib.sha256(Path('/usr/include/libdrm/drm_fourcc.h').read_bytes()).hexdigest()==HEADER_SHA,'header pin')
o={'width':800,'height':600,'format':int.from_bytes(b'AB24','little'),'modifier':AMD,'planes':[{'stride':3584,'offset':0},{'stride':1024,'offset':2293760}],'borrowed':True}
r=metadata(o);need(r['auxiliary_stride']=='NOT_AN_IMAGE_STRIDE','AMD aux')
# Controlled fixtures, never actual allocation evidence or historical PASS.
for label,fn in [('unknown-format',lambda x:x.update(format=1)),('short-image',lambda x:x['planes'][0].update(stride=3199)),('plane-count',lambda x:x['planes'].pop()),('unknown-modifier',lambda x:x.update(modifier='ffffffffffffffff')),('negative-offset',lambda x:x['planes'][1].update(offset=-1)),('zero-aux',lambda x:x['planes'][1].update(stride=0))]:
x=deepcopy(o);fn(x)
try:metadata(x)
except Rejected:print('PASS controlled rejection',label)
else:raise AssertionError(label)
u=halfpixel(800,600,True,[bits(1/800),bits(1/600)])
v=halfpixel(800,600,True,[bits(.0012493133544921875),bits(.0016660690307617188)])
need(u['cpu_float32_ideal_bits']==v['cpu_float32_ideal_bits'] and u['observed_bits']!=v['observed_bits'] and v['comparison_gate']=='NONE','no mediump equality or fit')
try:halfpixel(800,600,False,[2**32,0])
except Rejected:pass
else:raise AssertionError('uniform framing')
print('PASS controlled AMD/linear policy and separate halfpixel bits; HISTORICAL_REPORTED_ONLY')
if __name__=='__main__':test()

View file

@ -1,3 +1,100 @@
# Prospective private revision: P1/C8/O1/O2 and G2 wiring
EXPERIMENTAL SOURCE ONLY. No new reservation, IPC, native injection, capture,
compositor launch or GPU execution has been performed by this revision. The
accepted graphics-kit and runtime-git-kit remain immutable. The real budget
retains P0/C1..C7; C7 remains INCONCLUSIVE. G2 and R1 remain NOT_ADMITTED unless
the exact prospective gate below is satisfied (R1 has no override).
The old published commit had a C7 fixture oracle bug: resize uses
max(0,min(previous,max_scroll)), but migration invokes move.c661
workspace_move_to_output, then move.c668 seat_set_focus, then seat.c1204-1212
focused-cell reveal. The observed old800 ->1120 for focused logical1280..1920
and viewport800 was legal. This revision fixes only future/offline predicates;
it never reruns or relabels the consumed C7. C2 future geometry now records
crossing_axis/crossing_boundary; old raw crossingX0 receipts stay immutable.
P1/C8 select an explicit two-equal-child nonleaf splith group by con_id, then
fullscreen that group. The separate fullscreen-client requests legal anchors
350/80 and100/60, widths900, and draws after each configure. Actual configure,
ACK, native buffer, paint and pointer-local input qualify measured crossing.
Noncrossing is NOT_EXERCISED. No Mosaic camera scroll is used in that branch.
P1 captures10; C8 captures12 including a fresh post-fullscreen/splith pair.
C8 compares its actual role/configure/geometry record against P1. This does not
prove an atomic current fullscreen generation; that property is NOT_PROVEN.
Both fullscreen samples compare the complete H2 RGB field against the stable
reference with measured configured popup rectangles clipped to H2 and composed
in A-then-B order. This P1/C8 source correction remains pending independent
delta review; it does not admit either run.
O1/O2 use a distinct oom ELF, captures8, hook1. SMX_OOM_* belongs solely to the
compositor process environment after the clean allowlist. The exclusive nonce
and role token is debited before writing, only after stable reference/owner;
O2 additionally requires real rootA native success and configure/ACK/buffer/map.
The failed popup validates its real button serial/grab wire without awaiting
MAP. Native role, nonce, PID, counters, unpublished pointers and NULL result are
required. Raw client no_memory/errno/exit remain separate from ordinary close.
Only a demonstrated no_memory disconnect has its own scientific cleanup path;
arbitrary errors and compositor death stay INCONCLUSIVE. Any unresolved O1
outcome blocks O2 admission. Missing observations are retained as NOT_PROVEN.
G2 uses the unchanged gpu-kit/scenario.py via GPUSceneSession/AdapterSession.
The actual Session identity is gpu/static SceneFX. The frozen adapter's legacy
'core' name is translated only by that narrow view. MOSAIC_G2_* and WLR_RENDERER
are compositor-only. Every epoch debits mutation+hook before native arm; three
hooks maximum, eight actual captures within the unchanged cap16. Layer-client
closure validates its actual layer role independently of XDG ownership. The
source freeze is supplied by the independent final review and reconciled against
the current immutable GPU manifest and every source SHA/size. No superseded
prospective freeze is hardcoded.
Source-only tests never establish actual GL observability. Capability preflight
acceptance is distinct from native observation; native_gl_status stays NOT_RUN. Rejected A stops B
and A-return; native error queue/readback remains intrusive. Present buffer,
GPU completion, whole-field causality and atomic generations remain NOT_PROVEN.
Independent review/publication and a new complete manifest are mandatory before
any run. All plans stay NOT_ADMITTED by default. The existing independent review
must additionally bind prospective[run] with decision=ACCEPTED,
source_manifest_sha256 equal to that manifest and client_build_review=ACCEPTED.
P1/C8 also bind client_binary/client_binary_sha256 (the dedicated fullscreen-client)
and client_build_receipt/client_build_receipt_sha256; the gate reconciles the
receipt's source SHA and generated ELF SHA before every action.
O1/O2 additionally bind variant_identity=COREC_V2_NATIVE_OOM_DIAGNOSTIC and
accepted oom_source_review_sha256=a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c.
G2 additionally binds gpu_source_review=ACCEPTED,
gl_observability_preflight=ACCEPTED, native_gl_status=NOT_RUN,
build_review=ACCEPTED, pair=3, gpu_source_manifest as the canonical final freeze path below LAB and
gpu_source_manifest_sha256 equal to its independently accepted SHA; each of those
three acceptance statuses requires its *_receipt path and *_receipt_sha256. It also binds
gate_file/gate_file_sha256 and binding={binary, client, client_sha256,
source_manifest_sha256, gate_file}. The run nonce is derived from the fresh
ledger reservation token, never prefilled in a source review. The frozen native G2
gate independently requires source_review ACCEPTED, legacy gl_observability PASS,
runtime_authorized true, pair3 and the exact binary SHA. Its legacy PASS is
accepted only with gl_observability_scope=PREFLIGHT_CAPABILITY_ONLY and
native_gl_status=NOT_RUN; real ES3/RBO acceptance comes from epoch metadata. No test invents those
acceptances. The full kit publication must include new graphics and diagnostic
source bytes; source review does not authorize binary build or native execution.
Portable preparation from any working directory (LAB must already be canonical
and owned, all outputs remain under it):
```sh
LAB=/var/tmp/swayfx-mosaic-corec-v2-i516p6po
"$LAB/run-env" python "$LAB/graphics-next-kit/prepare_fullscreen.py" --lab "$LAB"
"$LAB/run-env" python "$LAB/graphics-next-kit/validate_offline.py" --lab "$LAB" --gpu-source-manifest "$LAB/results/gpu-source-freeze-corrected.json"
"$LAB/run-env" python "$LAB/graphics-next-kit/freeze.py" --lab "$LAB"
```
Preparation refuses an existing new client-build directory and never replaces
any of the five accepted clients. No client is executed. Freeze and validation
write graphics-next-work only; no old results or budget files are overwritten.
---
The following historical base README describes the original engine; its old
freeze/preparation destinations are not this revision's commands.
# STEP20C CORE-C V2 graphics source fixture
EXPERIMENTAL. Source implementation and offline controls; graphics preflight is
@ -80,7 +177,7 @@ client/compositor and outer runner raw exits remain distinct.
| ID | Captures | Scenario/admission before independent review |
| --- | ---: | --- |
| P0 | 10 | pristine standard reduced homologous chain, B close/A survives |
| P1 | 10 | NOT_ADMITTED: no comparable fullscreen offline certificate |
| P1 | 10 | NOT_ADMITTED: pending fullscreen whole-H2 source delta review |
| C1 | 18 | horizontal B/forbidden dismissal, new second chain, splith return |
| C2 | 12 | vertical y600 actual root/nested configure geometry |
| C3 | 12 | H1 physical1000x750 scale1.25 logical800x600 negative origin; marker |
@ -88,7 +185,7 @@ client/compositor and outer runner raw exits remain distinct.
| C5 | 12 | hidden motion only until return, same objects/grabs, fresh B input |
| C6 | 12 | real SHM held configure, txn-timeout5000 argv, natural timeout/ACK |
| C7 | 14 | 800→960→800, H1→H2→H1 stable IDs, input after each mutation |
| C8 | 12 | NOT_ADMITTED: same fullscreen certificate missing as P1 |
| C8 | 12 | NOT_ADMITTED: pending fullscreen whole-H2 source delta review |
| O1 | 8 | NOT_ADMITTED: first-allocation diagnostic source/binary unavailable |
| O2 | 8 | NOT_ADMITTED: second-allocation diagnostic source/binary unavailable |
| G2 | 16 | NOT_ADMITTED: new GPU hook/observability unavailable |

View file

@ -39,7 +39,7 @@ def open_chain(s,tail_fillers=0):
aim=s.capture('popup-A-'+str(sum(e['kind']=='spawn' and e['name']=='owner' for e in s.events)),'HEADLESS-1');prov=Provenance(state['owner']['id'],state['workspace']['id'],'NOT OBSERVABLE',state['evidence'])
xyA=solid_point(aim,COLORS['POPUP_A'],s.outputs[0],s.frames['HEADLESS-1'])
tb,bb=s.click('owner',xyA,'left',True);s.wait(lambda:'POPUP_B MAP ' in s.log('owner'));time.sleep(.2)
window=time.monotonic_ns();time.sleep(.15);p=validators.grab(s.log('owner'));g=geometry(s.log('owner'),state['origin'],prov)
window=time.monotonic_ns();time.sleep(.15);p=validators.grab(s.log('owner'));g=geometry(s.log('owner'),state['origin'],prov,s.spec['axis'],s.spec['boundary'])
s.delivery('owner',rect,xy,ta,ba,'TOPLEVEL',p['grabs'][0]['serial']);s.delivery('owner',g['A'],xyA,tb,bb,'POPUP_A',p['grabs'][1]['serial'])
[validators.crosses(g[k],s.spec['axis'],s.spec['boundary']) for k in ('A','B')]
left,right=s.pair_capture('mapped-'+str(sum(e['kind']=='spawn' and e['name']=='owner' for e in s.events)))
@ -89,7 +89,7 @@ def sample_surviving(s,images,tag):
s.save(tag+'-input',dict(status='NOT_EXERCISED',reason='B has no measured visible interior'));return
tails,buttons=s.click('owner',point);s.delivery('owner',geo['B'],point,tails,buttons,'POPUP_B');s.save(tag+'-input',dict(status='PASS',point=point,protocol=prot))
def dynamic_geometry(snap,previous=None):
def dynamic_geometry(snap,previous=None,mutation="resize"):
# WHY: scroll IPC alone does not demonstrate the resize clamp.
# CONTRACT: pinned arrange.c105-131 / mosaic.c125-153, zero inner gap,
# three direct tiled children; calloc row state has no minimum-width setter
@ -108,9 +108,20 @@ def dynamic_geometry(snap,previous=None):
geometry_status='IPC_PENDING_CANDIDATE; native generation NOT OBSERVABLE')
if previous is not None:
need(ws['id']==previous['workspace_id'] and ids==previous['children'],'dynamic workspace/order changed')
expected=min(previous['scroll'],maximum)
need(scroll==expected,'reconstructed camera clamp mismatch')
result.update(expected_scroll=expected,clamp='PASS')
# WHY: move.c661/668 refocuses after migration; seat.c1204-1212
# reveals the focused logical cell after the ordinary resize clamp.
# CONTRACT/INVARIANT: never conflate refocus with resize-only clamp.
expected=max(0,min(previous['scroll'],maximum))
need(mutation in ('resize','migration'),'unknown camera mutation')
if mutation=='migration':
focused=[c for c in children if c.get('focused')]
need(len(focused)==1,'migration exact focused direct child required')
lo=ids.index(focused[0]['id'])*640;hi=lo+640
if lo<expected:expected=lo
elif hi>expected+width:expected=hi-width
expected=max(0,min(expected,maximum))
need(scroll==expected,'reconstructed camera '+mutation+' mismatch')
result.update(expected_scroll=expected,clamp='PASS',mutation=mutation)
return result
def dynamic_pixels(images,outputs,frames,viewport,reference=None):
@ -135,7 +146,7 @@ def dynamic_campaign(s):
s.cmd('workspace 1');s.cmd(command,True);s.expected_output=out
if tag=='resized960':s.outputs[0]={**s.outputs[0],'logical':[-960,0,960,600],'mode':[960,600]}
elif tag=='resized-back':s.outputs[0]=dict(s.spec['outputs'][0])
time.sleep(.35);snap=s.snapshot(tag);current=dynamic_geometry(snap,previous)
time.sleep(.35);snap=s.snapshot(tag);current=dynamic_geometry(snap,previous,"migration" if tag.startswith("migrated") else "resize")
need(current['output']==out and s.find('owner')['id']==owner_id,'dynamic exact owner/output')
expected_viewport=next(o['logical'] for o in s.outputs if o['name']==out)
need(current['viewport']==expected_viewport,'dynamic viewport/output reconstruction')

View file

@ -0,0 +1,303 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>
#include "xdg-shell-client.h"
/* EXPERIMENTAL CONTRACT: every popup owns distinct XDG objects. B's actual
* parent is A's xdg_surface; logs name object IDs as well as colors. */
struct surface {
const char *name;
struct wl_surface *wl;
struct xdg_surface *xdg;
struct xdg_popup *popup;
bool configured, mapped, done;
int width, height, anchor_x, anchor_y;
uint32_t color;
};
static struct wl_display *display;
static struct wl_compositor *compositor;
static struct wl_shm *shm;
static struct xdg_wm_base *wm;
static struct wl_seat *seat;
static struct wl_pointer *pointer;
static struct xdg_toplevel *top_role;
static struct surface top = {.name="TOPLEVEL", .width=420, .height=320, .color=0x002344cc};
static struct surface a = {.name="POPUP_A", .width=300, .height=170, .color=0x00e0c020};
static struct surface b = {.name="POPUP_B", .width=300, .height=130, .color=0x0020d0a0};
static volatile sig_atomic_t running = 1;
static struct surface *entered;
/* Observe client-side SHM release separately from native GPU retirement.
* Keep protocol buffer alive until release; no backing memory is reused. */
static unsigned shm_created, shm_released;
static void buffer_release(void *data, struct wl_buffer *buffer) {
(void)data;
++shm_released;
fprintf(stderr,"SHM_RELEASE buffer=%u released=%u created=%u\n",
wl_proxy_get_id((struct wl_proxy *)buffer),shm_released,shm_created);
wl_buffer_destroy(buffer);
}
static const struct wl_buffer_listener buffer_listener = {.release=buffer_release};
static void draw(struct surface *s) {
size_t bytes = (size_t)s->width * (size_t)s->height * 4;
char path[4096];
const char *scratch = getenv("TMPDIR");
const char *lab = getenv("SMX_LAB");
/* WHY: SHM belongs to LAB, never the short socket-only runtime.
* CONTRACT: launcher supplies canonical LAB/scratch; fail before mkstemp. */
char expected[4096];
int expected_len = lab ? snprintf(expected, sizeof(expected), "%s/scratch", lab) : -1;
int path_len = scratch ? snprintf(path, sizeof(path), "%s/smx-shm-XXXXXX", scratch) : -1;
if (!lab || strncmp(lab, "/var/tmp/", 9) || strstr(lab, "/../") ||
expected_len < 0 || expected_len >= (int)sizeof(expected) ||
!scratch || strcmp(scratch, expected) || path_len < 0 ||
path_len >= (int)sizeof(path)) {
fprintf(stderr, "invalid LAB scratch for SHM\n");
exit(1);
}
int fd = mkstemp(path);
if (fd < 0 || ftruncate(fd, (off_t)bytes) < 0) { perror("buffer"); exit(1); }
unlink(path);
uint32_t *pixels = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (pixels == MAP_FAILED) { perror("mmap"); exit(1); }
for (size_t i=0; i<bytes/4; ++i) pixels[i] = s->color;
struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, (int)bytes);
struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, s->width, s->height,
s->width*4, WL_SHM_FORMAT_XRGB8888);
++shm_created;
wl_buffer_add_listener(buffer,&buffer_listener,NULL);
wl_surface_attach(s->wl, buffer, 0, 0);
wl_surface_damage_buffer(s->wl, 0, 0, s->width, s->height);
wl_surface_commit(s->wl);
wl_shm_pool_destroy(pool);
munmap(pixels, bytes);
close(fd);
s->mapped = true;
fprintf(stderr, "%s MAP wl=%u xdg=%u\n", s->name,
wl_proxy_get_id((struct wl_proxy *)s->wl), wl_proxy_get_id((struct wl_proxy *)s->xdg));
}
static void on_ping(void *data, struct xdg_wm_base *base, uint32_t serial) {
xdg_wm_base_pong(base, serial);
}
static const struct xdg_wm_base_listener wm_listener = {.ping=on_ping};
static void on_xdg_configure(void *data, struct xdg_surface *xdg, uint32_t serial) {
struct surface *s=data;
fprintf(stderr, "%s XDG_CONFIGURE serial=%u ack\n", s->name, serial);
xdg_surface_ack_configure(xdg, serial);
s->configured=true;
if (!s->done) draw(s); /* fresh native commit after every configure */
}
static const struct xdg_surface_listener xdg_listener = {.configure=on_xdg_configure};
static void on_top_configure(void *data, struct xdg_toplevel *role, int32_t w,
int32_t h, struct wl_array *states) {
fprintf(stderr, "TOPLEVEL ROLE_CONFIGURE w=%d h=%d\n", w,h);
}
static void on_top_close(void *data, struct xdg_toplevel *role) {
fprintf(stderr, "TOPLEVEL CLOSE_REQUEST\n"); running=0;
}
static const struct xdg_toplevel_listener top_listener = {
.configure=on_top_configure, .close=on_top_close,
};
static void on_popup_configure(void *data, struct xdg_popup *role, int32_t x,
int32_t y, int32_t w, int32_t h) {
struct surface *s=data;
fprintf(stderr, "%s ROLE_CONFIGURE x=%d y=%d w=%d h=%d\n",s->name,x,y,w,h);
}
static void on_popup_done(void *data, struct xdg_popup *role) {
struct surface *s=data;
s->done=true;
s->mapped=false;
fprintf(stderr, "%s POPUP_DONE role=%u\n",s->name,wl_proxy_get_id((struct wl_proxy *)role));
}
static const struct xdg_popup_listener popup_listener = {
.configure=on_popup_configure, .popup_done=on_popup_done,
};
/* WHY: XDG requires child-first destruction even if the compositor sends
* dismissals for multiple levels in one dispatch batch. */
static void destroy_popup(struct surface *s) {
if (!s->popup) return;
fprintf(stderr,"%s DESTROY role=%u xdg=%u wl=%u\n",s->name,
wl_proxy_get_id((struct wl_proxy *)s->popup),
wl_proxy_get_id((struct wl_proxy *)s->xdg),
wl_proxy_get_id((struct wl_proxy *)s->wl));
xdg_popup_destroy(s->popup);
xdg_surface_destroy(s->xdg);
wl_surface_destroy(s->wl);
s->popup=NULL; s->xdg=NULL; s->wl=NULL; s->mapped=false;
if (entered==s) entered=NULL;
}
static void collect_dismissals(void) {
if (b.done) destroy_popup(&b);
if (a.done) {
destroy_popup(&b);
destroy_popup(&a);
}
}
static void open_popup(struct surface *s, struct surface *parent, uint32_t serial) {
if (s->popup || !parent->mapped || !serial) return;
s->wl=wl_compositor_create_surface(compositor);
s->xdg=xdg_wm_base_get_xdg_surface(wm,s->wl);
xdg_surface_add_listener(s->xdg,&xdg_listener,s);
struct xdg_positioner *pos=xdg_wm_base_create_positioner(wm);
xdg_positioner_set_size(pos,s->width,s->height);
xdg_positioner_set_anchor_rect(pos,s->anchor_x,s->anchor_y,1,1);
xdg_positioner_set_anchor(pos,XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_gravity(pos,XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
s->popup=xdg_surface_get_popup(s->xdg,parent->xdg,pos);
xdg_popup_add_listener(s->popup,&popup_listener,s);
fprintf(stderr,"%s CREATE wl=%u xdg=%u role=%u parent=%s parent_xdg=%u\n",
s->name,wl_proxy_get_id((struct wl_proxy *)s->wl),
wl_proxy_get_id((struct wl_proxy *)s->xdg),
wl_proxy_get_id((struct wl_proxy *)s->popup),parent->name,
wl_proxy_get_id((struct wl_proxy *)parent->xdg));
fprintf(stderr,"%s GRAB_REQUEST origin=wl_pointer.button target=%s serial=%u used=%u\n",
s->name,parent->name,serial,serial);
xdg_popup_grab(s->popup,seat,serial);
wl_surface_commit(s->wl); /* Initial bufferless commit requests configure. */
xdg_positioner_destroy(pos);
}
static struct surface *which(struct wl_surface *wl) {
if (wl==top.wl) return &top;
if (wl==a.wl && wl) return &a;
if (wl==b.wl && wl) return &b;
return NULL;
}
static void on_enter(void *data,struct wl_pointer *ptr,uint32_t serial,
struct wl_surface *wl,wl_fixed_t x,wl_fixed_t y) {
entered=which(wl);
fprintf(stderr,"POINTER_ENTER target=%s wl=%u serial=%u x=%.2f y=%.2f\n",
entered?entered->name:"OTHER",wl_proxy_get_id((struct wl_proxy *)wl),serial,
wl_fixed_to_double(x),wl_fixed_to_double(y));
}
static void on_leave(void *data,struct wl_pointer *ptr,uint32_t serial,
struct wl_surface *wl) {
struct surface *s=which(wl);
fprintf(stderr,"POINTER_LEAVE target=%s serial=%u\n",s?s->name:"OTHER",serial);
if (entered==s) entered=NULL;
}
static void on_motion(void *data,struct wl_pointer *ptr,uint32_t time,
wl_fixed_t x,wl_fixed_t y) {
fprintf(stderr,"POINTER_MOTION target=%s x=%.2f y=%.2f\n",
entered?entered->name:"OTHER",wl_fixed_to_double(x),wl_fixed_to_double(y));
}
static void on_button(void *data,struct wl_pointer *ptr,uint32_t serial,
uint32_t time,uint32_t button,uint32_t state) {
fprintf(stderr,"POINTER_BUTTON target=%s serial=%u button=%u state=%u\n",
entered?entered->name:"OTHER",serial,button,state);
if (state!=WL_POINTER_BUTTON_STATE_PRESSED || button!=272) return;
if (entered==&top && !a.popup) open_popup(&a,&top,serial);
else if (entered==&a && a.mapped && !b.popup) open_popup(&b,&a,serial);
}
static void on_axis(void *data,struct wl_pointer *ptr,uint32_t t,uint32_t axis,wl_fixed_t v) {}
static void on_frame(void *data,struct wl_pointer *ptr) {}
static const struct wl_pointer_listener pointer_listener={
.enter=on_enter,.leave=on_leave,.motion=on_motion,.button=on_button,
.axis=on_axis,.frame=on_frame,
};
static void on_caps(void *data,struct wl_seat *s,uint32_t caps) {
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !pointer) {
pointer=wl_seat_get_pointer(s);
wl_pointer_add_listener(pointer,&pointer_listener,NULL);
}
}
static void on_seat_name(void *data,struct wl_seat *s,const char *name) {}
static const struct wl_seat_listener seat_listener={.capabilities=on_caps,.name=on_seat_name};
static void on_global(void *data,struct wl_registry *reg,uint32_t name,
const char *interface,uint32_t version) {
if (!strcmp(interface,wl_compositor_interface.name))
compositor=wl_registry_bind(reg,name,&wl_compositor_interface,version<4?version:4);
else if (!strcmp(interface,wl_shm_interface.name))
shm=wl_registry_bind(reg,name,&wl_shm_interface,1);
else if (!strcmp(interface,xdg_wm_base_interface.name))
wm=wl_registry_bind(reg,name,&xdg_wm_base_interface,version<3?version:3);
else if (!strcmp(interface,wl_seat_interface.name)) {
seat=wl_registry_bind(reg,name,&wl_seat_interface,version<5?version:5);
wl_seat_add_listener(seat,&seat_listener,NULL);
}
}
static void on_removed(void *data,struct wl_registry *reg,uint32_t name) {}
static const struct wl_registry_listener registry_listener={.global=on_global,.global_remove=on_removed};
static void stop(int sig) { running=0; }
int main(int argc,char **argv) {
signal(SIGTERM,stop);
const char *placement=argc>1?argv[1]:"b_cross";
/* EXPERIMENTAL: only placement changes; serial/grab/lifecycle stay historical.
* Both 1x1 anchors lie inside their parent SHM window geometry. */
/* WHY/CONTRACT/INVARIANT: fullscreen group geometry is measured; legal
* anchors and wide buffers request crossing without forcing native placement. */
if (!strcmp(placement,"fullscreen_cross")) {
a.anchor_x=350; a.anchor_y=80; a.width=900;
b.anchor_x=100; b.anchor_y=60; b.width=900;
} else if (!strcmp(placement,"static_cross")) {
a.anchor_x=100; a.anchor_y=80; a.width=350;
b.anchor_x=100; b.anchor_y=60; b.width=300;
} else if (!strcmp(placement,"visible")) {
a.anchor_x=50; a.anchor_y=80; a.width=250;
b.anchor_x=20; b.anchor_y=60; b.width=170;
} else if (!strcmp(placement,"both_cross")) {
a.anchor_x=350; a.anchor_y=80; a.width=350;
b.anchor_x=160; b.anchor_y=60; b.width=300;
} else if (!strcmp(placement,"b_cross")) {
a.anchor_x=200; a.anchor_y=80; a.width=300;
b.anchor_x=220; b.anchor_y=60; b.width=300;
} else { fprintf(stderr,"invalid placement\n"); return 2; }
display=wl_display_connect(NULL);
if (!display) { fprintf(stderr,"cannot connect Wayland\n"); return 1; }
struct wl_registry *registry=wl_display_get_registry(display);
wl_registry_add_listener(registry,&registry_listener,NULL);
wl_display_roundtrip(display); wl_display_roundtrip(display);
if (!compositor || !shm || !wm || !seat || !pointer) {
fprintf(stderr,"missing Wayland globals/pointer\n"); return 1;
}
xdg_wm_base_add_listener(wm,&wm_listener,NULL);
top.wl=wl_compositor_create_surface(compositor);
top.xdg=xdg_wm_base_get_xdg_surface(wm,top.wl);
xdg_surface_add_listener(top.xdg,&xdg_listener,&top);
top_role=xdg_surface_get_toplevel(top.xdg);
xdg_toplevel_add_listener(top_role,&top_listener,NULL);
xdg_toplevel_set_title(top_role,"Mosaic Nested Grab Probe");
xdg_toplevel_set_app_id(top_role,"org.mosaic.NestedGrabProbe");
fprintf(stderr,"TOPLEVEL CREATE wl=%u xdg=%u role=%u placement=%s\n",
wl_proxy_get_id((struct wl_proxy *)top.wl),
wl_proxy_get_id((struct wl_proxy *)top.xdg),
wl_proxy_get_id((struct wl_proxy *)top_role),placement);
wl_surface_commit(top.wl);
while (running) {
wl_display_flush(display);
struct pollfd fds[2]={{.fd=wl_display_get_fd(display),.events=POLLIN},
{.fd=STDIN_FILENO,.events=POLLIN}};
int ready=poll(fds,2,500);
if (ready<0) { if (errno==EINTR) continue; perror("poll"); break; }
if (fds[0].revents & (POLLIN|POLLERR|POLLHUP)) {
if (wl_display_dispatch(display)<0) break;
collect_dismissals();
}
if (fds[1].revents & POLLIN) {
char cmd[64];
if (fgets(cmd,sizeof(cmd),stdin)) {
if (!strncmp(cmd,"close_b",7)) { destroy_popup(&b); fprintf(stderr,"COMMAND close_b DONE\n"); }
else if (!strncmp(cmd,"close_owner",11)) { fprintf(stderr,"CLOSE_RECEIVED\nCOMMAND close_owner\n"); running=0; }
}
}
}
destroy_popup(&b); destroy_popup(&a);
fprintf(stderr,"TOPLEVEL DESTROY\n");
xdg_toplevel_destroy(top_role); xdg_surface_destroy(top.xdg); wl_surface_destroy(top.wl);
wl_display_roundtrip(display);
fprintf(stderr,"SHM_CLOSURE created=%u released=%u\n",shm_created,shm_released);
wl_display_flush(display);
/* WHY/CONTRACT/INVARIANT: exit0 does not prove protocol error0. */
fprintf(stderr,"EXIT error=%d\n",wl_display_get_error(display));
wl_display_disconnect(display);
return 0;
}

View file

@ -30,6 +30,9 @@ class Session:
for k,box in [('TL',(15,15,44,44)),('TR',(755,15,784,44)),('BL',(15,555,44,584)),('BR',(755,555,784,584)),('C',(385,285,414,314))]:draw.rectangle(box,fill=MARKERS[k])
marker.save(self.run/'marker-source.png');self.marker_source=self.run/'marker-source.png';self.record('generated-content-PNG',path=str(self.marker_source),counts_as_capture=False)
need(cfg==self.spec['config'],'sealed config bytes');(self.run/'config').write_text(cfg);self.watch=threading.Thread(target=self.watchdog,daemon=True);self.watch.start()
if spec['id'] in ('O1','O2'):
from oom import process_environment
self.oom_env=process_environment(self.lab,spec['id'],auth['token'])
self.comp=self.spawn('compositor',[auth['binary'],'-d',*(['-Dtxn-timeout=5000'] if spec['id']=='C6' else []),'-c',self.run/'config'])
self.sock=self.wait(lambda:next(iter(self.runtime.glob('sway-ipc.*.sock')),None));display=self.wait(lambda:next((p for p in self.runtime.glob('wayland-*') if p.is_socket()),None))
self.env.update(WAYLAND_DISPLAY=display.name,SWAYSOCK=str(self.sock));need(Path(f'/proc/{self.comp.pid}/exe').resolve()==Path(auth['binary']).resolve() and sha(Path(f'/proc/{self.comp.pid}/exe'))==auth['binary_sha256'],'actual executable')
@ -37,7 +40,7 @@ class Session:
paths={s.split()[-1] for s in maps.splitlines() if len(s.split())>=6 and s.split()[-1].startswith('/')}
wl=[Path(p).resolve() for p in paths if 'libwlroots' in p];need(wl==[Path(auth['wlroots'])] and sha(wl[0])==auth['wlroots_sha256'],'mapped wlroots')
scene=[Path(p).resolve() for p in paths if 'libscenefx' in p]
if spec['binary']=='core':need(not scene,'static SceneFX')
if spec['binary'] in ('core','oom','gpu'):need(not scene,'static SceneFX')
else:need(scene==[Path(auth['pristine_scene'])] and sha(scene[0])==auth['pristine_scene_sha256'],'mapped pristine SceneFX')
render=[s for s in self.log('compositor').splitlines() if any(x in s for x in ('Creating scenefx FX renderer','GL renderer:','GL vendor:','Using OpenGL ES'))]
need(any('Creating scenefx FX renderer' in s for s in render) and any('GL renderer:' in s for s in render),'actual renderer')
@ -80,7 +83,13 @@ class Session:
# can escape the watchdog's owned-group snapshot by racing its deadline.
with getattr(self,'proc_lock',threading.RLock()):
need(not self.expired,'expired before process creation')
p=subprocess.Popen(actual_argv,stdin=subprocess.PIPE,stdout=f,stderr=subprocess.STDOUT,text=True,start_new_session=True,env={**self.env,**({'WAYLAND_DEBUG':'1'} if debug else {})})
# WHY/CONTRACT/INVARIANT: diagnostics are compositor-private and
# never enter the environment shared with capture, IPC or clients.
child_env={**self.env,**({'WAYLAND_DEBUG':'1'} if debug else {})}
need(not any(k.startswith(('SMX_OOM_','MOSAIC_G2_')) for k in child_env),'diagnostic environment leaked into common environment')
if name=='compositor':
child_env.update(getattr(self,'oom_env',{}));child_env.update(getattr(self,'compositor_environment',{}))
p=subprocess.Popen(actual_argv,stdin=subprocess.PIPE,stdout=f,stderr=subprocess.STDOUT,text=True,start_new_session=True,env=child_env)
self.proc[name]=p
self.record('spawn',name=name,pid=p.pid,requested_argv=requested_argv,actual_argv=actual_argv);return p
def log(self,name):return (self.run/(name+'.log')).read_text(errors='replace')
@ -129,7 +138,12 @@ class Session:
def find(self,name):
pid=self.proc[name].pid;rows=[n for n in nodes(self.ipc('-t','get_tree')) if n.get('pid')==pid];need(len(rows)<=1,'client owner ambiguity');return rows[0] if rows else None
def launch_client(self,name,client,*args):
p=self.spawn(name,[self.lab/'graphics-tests/client-build'/client,*args],True);self.wait(lambda:self.find(name));time.sleep(.25);return p
build=self.lab/('graphics-next-work/client-build' if client=='fullscreen-client' else 'graphics-tests/client-build')
p=self.spawn(name,[build/client,*args],True);self.wait(lambda:self.find(name));time.sleep(.25)
if client=='fullscreen-client':
exe=Path(f'/proc/{p.pid}/exe');need(exe.resolve()==build/client and sha(exe)==self.auth['prospective']['client_binary_sha256'],'actual fullscreen client executable')
self.record('fullscreen-client-identity',pid=p.pid,binary=str(exe.resolve()),sha256=sha(exe))
return p
def capture(self,tag,out,orientation_pending=False):
self.debit('capture');spec=next(o for o in self.outputs if o['name']==out);p=self.run/(tag+'.png');need(not p.exists(),'capture unique')
t=time.monotonic_ns();r=subprocess.run(['grim','-s',str(spec['scale']),'-o',out,str(p)],env=self.env,capture_output=True,text=True,timeout=4)
@ -268,7 +282,7 @@ class Session:
reaped=all(not Path('/proc',str(p.pid)).exists() for p in self.proc.values());need(reaped,'owned process residual');shutil.rmtree(self.runtime)
seconds=time.monotonic()-self.started
protocol_errors=[n for n in self.proc if n not in ('compositor','pointer') and re.search(r'wl_display[^\n]*\.error\(|protocol error|invalid_popup_parent|not_the_topmost_popup',self.log(n),re.I)]
cleanup_pass=bool(closure_coverage and all(c['status']=='PASS' for c in closures) and not rescue and reaped and seconds<=150 and not self.expired and not protocol_errors and all(p['exit']==0 for p in codes))
cleanup_pass=bool(closure_coverage and all(c['status']=='PASS' for c in closures) and not rescue and reaped and seconds<=150 and not self.expired and all(any(c['name']==n and c.get('expected_enomem') for c in closures) for n in protocol_errors) and all(p['exit']==0 or any(c['pid']==p['pid'] and c.get('expected_enomem') for c in closures) for p in codes))
transport_pass=terminal is not None and terminal.get('ipc_exit') in (0,1) and 'wait_error' not in terminal and 'ipc_error' not in terminal
final_status=measurement_status if failure is None and cleanup_pass and transport_pass else 'INCONCLUSIVE'
self.save('outcome',dict(status=final_status,measurements_pass=measurement_status,architecture_verdict='INCONCLUSIVE',evidence_provenance=self.auth,untested_matrix_cells=['ATOMIC_GENERATION','COMPLETE_DAMAGE','NATIVE_BUFFER_IDENTITY','GPU_LIFETIME'],scientific_cleanup='PASS' if cleanup_pass else 'INCONCLUSIVE',runtime_exit=codes,measurements_status=measurement_status,failure=failure,terminal=terminal,helper_exits=getattr(self,'helper_exits',[]),explicit_client_closures=self.closed,mechanical_cleanup='PASS' if reaped and not rescue and not self.runtime.exists() else 'INCONCLUSIVE',client_closures=closures,processes=codes,rescue=rescue,reaped=reaped,runtime_removed=not self.runtime.exists(),seconds=seconds,watchdog=self.expired,protocol_errors=protocol_errors,cleanup_pass=cleanup_pass,transport_status='PASS' if transport_pass else 'INCONCLUSIVE'))

View file

@ -10,6 +10,6 @@ def freeze(lab):
files={str(p.relative_to(root)):sha(p) for p in sorted(root.rglob("*")) if p.is_file()}
if any(name.endswith((".pyc",".png",".so",".o")) or "__pycache__" in name for name in files):raise ValueError("generated artifact in source kit")
result=dict(schema="graphics-v2-source-freeze",ticket=TICKET,source_root=str(root),files=files,plans=RUNS,limits=LIMITS,preflight="PENDING_INDEPENDENT_REVIEW",runtime="NOT_RUN",real_reservations=0)
durable(lab/"results/graphics-source-freeze.json",result);return result
durable(lab/"graphics-next-work/graphics-source-freeze.json",result);return result
if __name__=="__main__":
p=argparse.ArgumentParser();p.add_argument("--lab",required=True);a=p.parse_args();freeze(a.lab)

View file

@ -0,0 +1,114 @@
"""Prospective equal-child nonleaf fullscreen handler; applied evidence is sampled."""
import re,time
import cases,validators
from engine import COLORS
from geometry import *
from ipc_predicates import ancestry
from model import Provenance
from PIL import Image,ImageChops,ImageDraw
from predicates import geometry
def group_candidate(state,peer_id,group_id=None,fullscreen=True):
path=ancestry(state['snapshot']['tree'],state['owner']['id'])
if fullscreen:
group=validators.fullscreen_ancestor(path)
need(group['type']=='con' and group.get('fullscreen_mode')==1 and len(group['nodes'])==2,'exact nonleaf fullscreen group')
else:
rows=[n for n in path[:-1] if n.get('type')=='con' and n.get('id')==group_id]
need(len(rows)==1,'current two-child group absent after fullscreen exit');group=rows[0]
need(group.get('fullscreen_mode',0)==0 and len(group.get('nodes',[]))==2,'group still fullscreen or child count changed')
need(group_id is None or group['id']==group_id,'fullscreen group identity changed')
need({n['id'] for n in group['nodes']}=={state['owner']['id'],peer_id},'fullscreen exact owner/peer children')
need(group.get('layout')=='splith','fullscreen group split orientation')
rect=group['rect'];out=next(o for o in state['snapshot']['outputs'] if o['name']==state['workspace']['output'])['rect']
if fullscreen:need(rect==out,'fullscreen group does not cover output')
else:need(rect==out,'current split group does not cover output after fullscreen exit')
widths=[n['rect']['width'] for n in group['nodes']]
need(widths[0]==widths[1] and sum(widths)==rect['width'],'fullscreen equal child widths')
return group
def comparable(pristine,core):
# WHY/CONTRACT/INVARIANT: compare actual roles, configures and geometry
# measured for these binaries; matching requested placement is insufficient.
for r in (pristine,core):
need(r['fresh'] and r['crossing_A'] and r['crossing_B'] and crossing(r['popup_A'],0,0) and crossing(r['popup_B'],0,0),'stale/noncrossing fullscreen evidence')
keys=('client_sha256','roles','top_configure','child_rects','group_rect','popup_A','popup_B','configured_A','configured_B','origin','outputs')
need(all(pristine[k]==core[k] for k in keys),'noncomparable pristine/core fullscreen evidence')
return dict(status='PARTIALLY_FEASIBLE',atomic_current_state='NOT_PROVEN')
def fresh_geometry(s,state,p):
return geometry(s.log('owner'),state['origin'],Provenance(state['owner']['id'],state['workspace']['id'],'NOT OBSERVABLE','fresh native paint + pointer-local corroboration'))
def fullscreen_h2_field(images,baseline,g,output,frame,colors,active_roles=('POPUP_A','POPUP_B'),require_crossing=False):
# WHY/CONTRACT/INVARIANT: fullscreen standard overflow must reproduce the
# complete measured H2 field. P1/C8 are scale-1, normal, logical captures;
# configured global rectangles are clipped with half-open output bounds.
need(frame=='logical' and output['scale']==1 and output['transform']=='normal','fullscreen H2 frame/scale/transform unsupported')
ox,oy,ow,oh=output['logical'];need(baseline.size==(ow,oh) and images[1].size==baseline.size,'fullscreen H2 image dimensions')
expected=baseline.copy();draw=ImageDraw.Draw(expected)
parent=g['origin']
for key,name in (('A','POPUP_A'),('B','POPUP_B')):
configured=g['configured_'+key];rect=g[key]
need(len(configured)==len(rect)==4 and configured[2]>0 and configured[3]>0,'fullscreen popup configured extent')
need(rect==[parent[0]+configured[0],parent[1]+configured[1],configured[2],configured[3]],'fullscreen popup geometry/configure mismatch')
if require_crossing:need(g.get('crossing',{}).get(key) is True,'fullscreen popup crossing not traversed')
left=max(rect[0],ox);top=max(rect[1],oy);right=min(rect[0]+rect[2],ox+ow);bottom=min(rect[1]+rect[3],oy+oh)
if name in active_roles and left<right and top<bottom:
# Pillow endpoints are inclusive; convert our half-open rectangle.
draw.rectangle((left-ox,top-oy,right-ox-1,bottom-oy-1),fill=colors[name])
parent=rect
need(ImageChops.difference(expected,images[1]).getbbox() is None,'fullscreen whole H2 RGB field differs')
def input_target(s,images,g,target,key):
point=None
for index,output in enumerate(s.outputs):
try:point=solid_point(images[index],COLORS[target],output,s.frames[output['name']],g[key]);break
except Ambiguous:continue
need(point is not None,'popup has no visible solid input region on either output')
tails,buttons=s.click('owner',point);s.delivery('owner',g[key],point,tails,buttons,target)
def run(s):
cases.init_reference(s,1);s.debit('chain');s.launch_client('owner','fullscreen-client','fullscreen_cross')
owner_id=s.find('owner')['id'];s.cmd(f'[con_id={owner_id}] split h');s.launch_client('fullscreen-peer','static-reference')
peer_id=s.find('fullscreen-peer')['id'];tree=s.snapshot('fullscreen-before')['tree'];path=ancestry(tree,owner_id)
group=path[-2];need(group.get('type')=='con' and {n['id'] for n in group.get('nodes',[])}=={owner_id,peer_id},'exact two-child group preparation')
gid=group['id'];cut=len(s.log('owner'));s.cmd(f'[con_id={gid}] fullscreen enable');s.cmd(f'[con_id={owner_id}] focus')
s.wait(lambda:'TOPLEVEL XDG_CONFIGURE ' in s.log('owner')[cut:] and 'TOPLEVEL MAP ' in s.log('owner')[cut:]);time.sleep(.2)
state=s.owner('owner');group=group_candidate(state,peer_id,gid);baseline=cases.stable_reference(s)
top=s.capture('fullscreen-owner','HEADLESS-1');xy=solid_point(top,COLORS['TOPLEVEL'],s.outputs[0],s.frames['HEADLESS-1'],[*state['origin'],420,320])
ta,ba=s.click('owner',xy,'left',True);s.wait(lambda:'POPUP_A MAP ' in s.log('owner'))
root=s.capture('fullscreen-rootA','HEADLESS-1');xyA=solid_point(root,COLORS['POPUP_A'],s.outputs[0],s.frames['HEADLESS-1'])
tb,bb=s.click('owner',xyA,'left',True);s.wait(lambda:'POPUP_B MAP ' in s.log('owner'));time.sleep(.2)
p=validators.grab(s.log('owner'));g=fresh_geometry(s,state,p)
s.delivery('owner',[*state['origin'],420,320],xy,ta,ba,'TOPLEVEL',p['grabs'][0]['serial'])
s.delivery('owner',g['A'],xyA,tb,bb,'POPUP_A',p['grabs'][1]['serial'])
images=s.pair_capture('fullscreen-mapped')
if not all(crossing(g[k],0,0) for k in ('A','B')):
s.save('fullscreen-not-exercised',dict(status='NOT_EXERCISED',geometry=g,reason='actual configured popup crossing absent'))
return 'NOT_EXERCISED'
validators.standard_spill(images,COLORS)
fullscreen_h2_field(images,baseline,g,s.outputs[1],s.frames['HEADLESS-2'],COLORS,require_crossing=True)
fresh=s.owner('owner');group_candidate(fresh,peer_id,gid);need(fresh['origin']==state['origin'],'stale fullscreen geometry')
record=dict(client_sha256=s.auth['prospective']['client_binary_sha256'],source_manifest_sha256=s.auth['manifest_sha256'],fresh=True,crossing_A=True,crossing_B=True,roles=p['hierarchy'],top_configure=re.findall(r'TOPLEVEL ROLE_CONFIGURE w=(\d+) h=(\d+)',s.log('owner'))[-1],child_rects=[c['rect'] for c in group['nodes']],group_rect=group['rect'],popup_A=g['A'],popup_B=g['B'],configured_A=g['configured_A'],configured_B=g['configured_B'],origin=g['origin'],outputs=s.outputs,owner_id=owner_id,group_id=gid,peer_id=peer_id,protocol=p,atomic_current_state='NOT_PROVEN')
s.save('fullscreen-comparability',record)
input_target(s,images,g,'POPUP_B','B');input_target(s,images,g,'POPUP_A','A')
if s.spec['id']=='C8':
s.cmd(f'[con_id={gid}] fullscreen disable',True);s.cmd(f'[con_id={state["workspace"]["id"]}] layout splith',True);s.expected_layout='splith';time.sleep(.35)
state=s.owner('owner');need(state['owner']['id']==owner_id,'C8 owner identity changed')
p2=validators.grab(s.log('owner'));need(p2['ids']==p['ids'],'C8 popup chain changed')
state=s.owner('owner');need(state['owner']['id']==owner_id,'C8 owner identity changed after fullscreen exit')
group_candidate(state,peer_id,gid,fullscreen=False)
g=fresh_geometry(s,state,p)
images=s.pair_capture('fullscreen-exited-standard')
fullscreen_h2_field(images,baseline,g,s.outputs[1],s.frames['HEADLESS-2'],COLORS);input_target(s,images,g,'POPUP_B','B')
before=s.log('owner');start=time.monotonic_ns();s.client_cmd('owner','close_b','COMMAND close_b DONE');time.sleep(.2)
from lifecycle import explicit_child_close
explicit_child_close(before,s.log('owner'),p['ids'],start,time.monotonic_ns())
state=s.owner('owner');need(state['owner']['id']==owner_id,'owner identity changed after B close')
group_candidate(state,peer_id,gid,fullscreen=s.spec['id']=='P1');g=fresh_geometry(s,state,p)
images=s.pair_capture('fullscreen-B-closed');need(not any(count(image,COLORS['POPUP_B']) for image in images),'B residual')
fullscreen_h2_field(images,baseline,g,s.outputs[1],s.frames['HEADLESS-2'],COLORS,active_roles=('POPUP_A',));input_target(s,images,g,'POPUP_A','A')
s.close_client('owner')
if s.spec['id']=='P1' and any(n.get('id')==gid for n in cases.nodes(s.snapshot('fullscreen-after-owner')['tree'])):s.cmd(f'[con_id={gid}] fullscreen disable',True)
final=s.pair_capture('fullscreen-final');exact(baseline,final[1])
return 'PARTIALLY_FEASIBLE'

View file

@ -66,7 +66,13 @@ class Ledger:
def admit(self,rid,manifest,review,publication):
auth=validate_review(self.lab,manifest,review,publication,rid,offline=self.offline)
def reserve(d):
spec=RUNS[rid];need(not any(r["id"]==rid for r in d["runs"]),"consumed run")
spec=RUNS[rid]
# WHY/CONTRACT/INVARIANT: O2 is dependent evidence, never a retry after O1
# availability or invariant failure. Missing/unfinished O1 blocks admission.
if rid=='O2':
prior=[r for r in d['runs'] if r['id']=='O1']
need(len(prior)==1 and prior[0]['status']=='COMPLETED' and prior[0].get('outcome',{}).get('status')=='PARTIALLY_FEASIBLE',"O1 critical/unresolved failure blocks O2")
need(not any(r["id"]==rid for r in d["runs"]),"consumed run")
need(len(d["runs"])<14 and sum(r["capture_limit"] for r in d["runs"])+spec["capture_limit"]<=180,"global budget")
token=uuid.uuid4().hex;r=dict(id=rid,token=token,started_ns=time.monotonic_ns(),capture_limit=spec["capture_limit"],action_limits=spec["action_limits"],actions={},status="RESERVED",bindings=auth)
d["runs"].append(r);return dict(auth,token=token,run_id=rid,lab=str(self.lab),offline=self.offline),d
@ -98,7 +104,21 @@ def validate_review(lab,manifest,review,publication,rid,offline=False):
need(m.get("schema")=="graphics-v2-frozen-inputs" and m.get("limits")==LIMITS and m.get("plans")==RUNS,"manifest schema/plans/caps")
need(r.get("decision")=="ACCEPTED" and r.get("independent") is True and r.get("reviewer")!=m.get("author") and r.get("reviewer"),"independent review absent")
need(r.get("manifest_sha256")==sha(manifest) and rid in r.get("authorized_runs",[]),"stale review/case not admitted")
need(RUNS[rid]["admission"]!="NOT_ADMITTED","scenario NOT_ADMITTED: "+RUNS[rid].get("reason",""))
if RUNS[rid]["admission"]=="NOT_ADMITTED":
need(rid in ('P1','C8','O1','O2','G2'),"scenario NOT_ADMITTED")
prospective=r.get('prospective',{}).get(rid,{})
need(prospective.get('decision')=='ACCEPTED' and prospective.get('source_manifest_sha256')==sha(manifest),"prospective case review absent/stale")
need(prospective.get('client_build_review')=='ACCEPTED',"new client/build review absent")
if rid in ('P1','C8'):
cb=Path(prospective.get('client_binary',''));cr=Path(prospective.get('client_build_receipt',''))
need(cb==lab/'graphics-next-work/client-build/fullscreen-client' and sha(cb)==prospective.get('client_binary_sha256'),"new fullscreen client bytes")
need(cr.resolve().is_relative_to(lab) and sha(cr)==prospective.get('client_build_receipt_sha256'),"new client build receipt bytes")
compile_receipt=json.loads(cr.read_text())
need(compile_receipt.get('status')=='PASS' and compile_receipt['generated']['fullscreen-client']==sha(cb) and compile_receipt['inputs']['clients/fullscreen-client.c']==m['files']['clients/fullscreen-client.c'],"client compile/source binding")
if rid in ('O1','O2'):
need(prospective.get('oom_source_review_sha256')=='a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c',"OOM source review binding")
need(sha(lab/'review-oom-runtime/oom-source-receipt.json')==prospective['oom_source_review_sha256'],"OOM source review bytes changed")
need(prospective.get('variant_identity')=='COREC_V2_NATIVE_OOM_DIAGNOSTIC',"OOM variant identity")
root=Path(m["source_root"]);need(root.resolve()==root and root.is_relative_to(lab),"source root outside LAB")
need(m.get("files"),"empty inputs")
for rel,h in m["files"].items():
@ -125,8 +145,14 @@ def validate_review(lab,manifest,review,publication,rid,offline=False):
source_digest=digest(m["files"])
need(p.get("ticket")==TICKET and p.get("source_digest")==source_digest and p.get("decision")=="VERIFIED" and p.get("origin_sha")==p.get("github_sha") and re.fullmatch(r"[0-9a-f]{40}",p.get("origin_sha","")),"source kit unpublished")
need(p.get("offline_test_only",False)==offline,"publication namespace")
if rid=='G2':
from gpu_handler import validate_source_binding
validate_source_binding(lab,r.get('prospective',{}).get(rid,{}))
auth=m["identities"][RUNS[rid]["binary"]]
need(sha(auth["binary"])==auth["binary_sha256"],"binary changed")
if rid in ('O1','O2','G2'):
need(auth['binary_sha256'] not in (m['identities']['core']['binary_sha256'],m['identities']['pristine']['binary_sha256']),"distinct diagnostic ELF required")
need(sha(auth["wlroots"])==auth["wlroots_sha256"]==WL_SHA,"wlroots changed")
if rid=='G2':need(all(other.get('binary_sha256')!=auth['binary_sha256'] for name,other in m['identities'].items() if name!='gpu'),'GPU pair3 must differ from every other ELF')
need(auth.get("build_review")=="ACCEPTED" and auth.get("source_qualification")=="ACCEPTED","binary/source qualification pending")
return dict(auth,manifest=str(manifest),review=str(review),publication=str(publication),manifest_sha256=sha(manifest),review_sha256=sha(review),publication_sha256=sha(publication),source_digest=source_digest)
return dict(auth,prospective=r.get('prospective',{}).get(rid,{}),manifest=str(manifest),review=str(review),publication=str(publication),manifest_sha256=sha(manifest),review_sha256=sha(review),publication_sha256=sha(publication),source_digest=source_digest)

View file

@ -0,0 +1,83 @@
"""Narrow wiring of frozen G2 adapter to graphics Session. No native execution at import."""
import importlib,sys,json,re
from pathlib import Path
from engine import Session
from gate import need,sha
def validate_source_binding(lab,review):
need(review.get('gpu_source_review')=='ACCEPTED' and review.get('gl_observability_preflight')=='ACCEPTED' and review.get('native_gl_status')=='NOT_RUN' and review.get('build_review')=='ACCEPTED' and review.get('pair')==3,'G2 independent source/GL/build3 acceptance missing')
manifest=Path(review.get('gpu_source_manifest',''));need(manifest.is_absolute() and manifest.resolve()==manifest and manifest.is_relative_to(lab),'G2 canonical reviewed source manifest path')
expected=review.get('gpu_source_manifest_sha256','')
need(re.fullmatch('[0-9a-f]{64}',expected) and expected==sha(manifest),'G2 exact reviewed source freeze')
m=json.loads(manifest.read_text());root=lab/'gpu-kit'
# WHY/CONTRACT/INVARIANT: external source remains frozen; its adapter is
# imported only after actual byte validation, never by a status string alone.
files=m['files']
for rel,h in files.items():
p=lab/rel;need(not Path(rel).is_absolute() and p.resolve().is_relative_to(lab) and sha(p)==h['sha256'] and p.stat().st_size==h['bytes'],'G2 frozen source changed')
need({str(p.relative_to(root)) for p in root.rglob('*') if p.is_file()}=={str(Path(rel).relative_to('gpu-kit')) for rel in files if Path(rel).parts[0]=='gpu-kit'},'G2 source addition/removal')
for key in ('gpu_source_review','gl_observability_preflight','build_review'):
path=Path(review[key+'_receipt']);need(path.resolve().is_relative_to(lab) and sha(path)==review[key+'_receipt_sha256'],'G2 review receipt bytes')
binding=review['binding'];client=Path(binding['client']);need(client.resolve().is_relative_to(lab) and sha(client)==binding['client_sha256'],'G2 reviewed client bytes')
gatefile=Path(review['gate_file']);need(gatefile.resolve().is_relative_to(lab) and sha(gatefile)==review['gate_file_sha256'],'G2 native external gate bytes')
# WHY: the frozen adapter's legacy PASS admits instrumentation capability,
# not an observation made before its first native epoch. CONTRACT/INVARIANT:
# require explicit scope and retain native NOT_RUN until measured metadata.
native_gate=json.loads(gatefile.read_text())
need(native_gate.get('gl_observability')=='PASS' and native_gate.get('gl_observability_scope')=='PREFLIGHT_CAPABILITY_ONLY' and native_gate.get('native_gl_status')=='NOT_RUN','G2 legacy PASS must be scoped preflight only')
def modules(lab):
path=str(lab/'gpu-kit');sys.path.insert(0,path)
try:
# These names have no graphics-kit peer; source freeze includes both.
protocol=importlib.import_module('protocol');scenario=importlib.import_module('scenario')
need(Path(protocol.__file__).resolve()==lab/'gpu-kit/protocol.py' and Path(scenario.__file__).resolve()==lab/'gpu-kit/scenario.py','G2 module origin')
return scenario
finally:sys.path.remove(path)
class CompositorEnvironment:
def __init__(self,session):self.session=session
def update(self,**fields):
need(set(fields)=={'MOSAIC_G2_DIR','MOSAIC_G2_NONCE','WLR_RENDERER'},'G2 compositor environment scope')
need(fields['MOSAIC_G2_DIR']==str(self.session.lab/'gpu-work/acquisition') and re.fullmatch('[0-9a-f]{64}',fields['MOSAIC_G2_NONCE']) and fields['WLR_RENDERER']=='gles2','G2 acquisition environment')
self.session.compositor_environment=fields
class AdapterSession:
"""Compatibility view of pair#3, without changing the actual Session spec.
WHY: frozen adapter calls its static SceneFX branch 'core'. CONTRACT: real
identity/admission remain gpu; no other binary or environment is translated.
"""
def __init__(self,session):
need(session.spec['id']=='G2' and session.spec['binary']=='gpu','G2 real Session identity')
self.session=session;self.spec=dict(session.spec,binary='core');self.env=CompositorEnvironment(session)
def __getattr__(self,name):return getattr(self.session,name)
def debit(self,*kinds):
need(kinds==('mutation',),'unexpected direct G2 adapter debit')
# Each explicit epoch reservation precedes arm, without retry/refund.
self.session.debit('mutation','hook')
def spawn(self,name,argv,debug=False):
need(name in ('g2-reference','g2-background','g2-glass'),'G2 client role')
return self.session.spawn(name,argv,True)
class GPUSceneSession(Session):
def close_client(self,name,command='close'):
need(name in ('g2-reference','g2-background','g2-glass') and command=='close','G2 scientific closure role')
try:
super().close_client(name,command)
proof=self.closed[-1];raw=self.log(name)
mode='background' if name=='g2-background' else 'glass' if name=='g2-glass' else 'reference'
need(re.search(rf'EXIT ns=\d+ mode={mode} error=0 commits=\d+',raw),'G2 exact client role/raw error')
role='zwlr_layer_surface_v1' if mode=='background' else 'xdg_toplevel'
need(re.search(rf'{role}#\d+\.destroy\(\)',raw) and re.search(r'wl_surface#\d+\.destroy\(\)',raw),'G2 native role destruction')
proof.update(role=role,scientific_client=True,meaning='layer closure without invented XDG ownership' if mode=='background' else 'G2 XDG closure')
except Exception as error:
if self.closed and self.closed[-1]['pid']==self.proc[name].pid:self.closed[-1].update(status='INCONCLUSIVE',failure=str(error))
raise
def run(s):
review=s.auth['prospective'];validate_source_binding(s.lab,review)
binding=dict(review['binding'],nonce=s.auth['token']*2)
need(binding['source_manifest_sha256']==s.auth['manifest_sha256'] and binding['binary']==s.auth['binary'] and binding['gate_file']==review['gate_file'],'G2 exact reviewed reservation/binary/gate binding')
result=modules(s.lab).run(AdapterSession(s),dict(binding,G2_ledger_reserved=True))
need(result['native_source_A_Areturn_exact'] and result['whole_H1_A_Areturn']['equal'] and all(v['equal'] for v in result['whole_H2_A_B_Areturn']),'G2 measured return mismatch')
return 'PARTIALLY_FEASIBLE'

View file

@ -0,0 +1,297 @@
"""OFFLINE_TEST_ONLY. Real handlers with fake I/O; no compositor/IPC/client execution."""
import copy,io,json,os,sys,time,unittest
from collections import Counter
from contextlib import ExitStack
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import Mock,patch
sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
import cases,engine,fullscreen,gate,oom,oom_handler,plans,run
from test_graphics_v2 import V2,LAB,KIT
from PIL import Image
class Next(unittest.TestCase):
setUp=V2.setUp
fixture=V2.fixture
rejects=V2.rejects
dynamic_snapshot=V2.dynamic_snapshot
def test_migration_focus_reveal_distinct_from_resize(self):
previous=cases.dynamic_geometry(self.dynamic_snapshot(800,800))
moved=self.dynamic_snapshot(800,1120,'HEADLESS-2');moved['tree']['nodes'][2]['focused']=True
current=cases.dynamic_geometry(moved,previous,'migration');self.assertEqual(current['expected_scroll'],1120)
self.rejects(cases.dynamic_geometry,moved,previous,'resize')
wrong=copy.deepcopy(moved);wrong['tree']['mosaic']['rows'][0]['scroll_x']=800
self.rejects(cases.dynamic_geometry,wrong,previous,'migration')
wrong=copy.deepcopy(moved);wrong['tree']['nodes'][2]['focused']=False
self.rejects(cases.dynamic_geometry,wrong,previous,'migration')
def test_fullscreen_group_and_comparability_negatives(self):
state,peer,group=self.state();fullscreen.group_candidate(state,peer,group)
for change in (lambda g:g.update(fullscreen_mode=0),lambda g:g['nodes'][0].update(fullscreen_mode=1),lambda g:g['nodes'].pop(),lambda g:g['nodes'][0]['rect'].update(width=399)):
bad=copy.deepcopy(state);g=bad['snapshot']['tree']['nodes'][0];change(g)
if g.get('nodes') and g['nodes'][0].get('fullscreen_mode'):g['fullscreen_mode']=0
self.rejects(fullscreen.group_candidate,bad,peer,group)
exited=copy.deepcopy(state);eg=exited['snapshot']['tree']['nodes'][0];eg['fullscreen_mode']=0
eg['nodes'][0]['rect'].update(x=-400);eg['nodes'][1]['rect'].update(x=-800)
exited['origin']=[-398,25];exited['owner']['rect'].update(x=-400)
fullscreen.group_candidate(exited,peer,group,fullscreen=False)
still_full=copy.deepcopy(exited);still_full['snapshot']['tree']['nodes'][0]['fullscreen_mode']=1
self.rejects(fullscreen.group_candidate,still_full,peer,group,fullscreen=False)
raw=(KIT/'wire-fixture.txt').read_text();protocol=fullscreen.validators.grab(raw)
fresh=fullscreen.fresh_geometry(SimpleNamespace(log=lambda _name:raw),exited,protocol)
self.assertEqual(fresh['A'],[-348,505,250,170]);self.assertEqual(fresh['B'],[-328,585,170,130])
record=dict(client_sha256='offline-client',fresh=True,crossing_A=True,crossing_B=True,roles='TOPLEVEL -> POPUP_A -> POPUP_B',top_configure=['400','575'],child_rects=[1,2],group_rect=[-800,0,800,600],popup_A=[-448,105,900,170],popup_B=[-348,165,900,130],configured_A=[350,80,900,170],configured_B=[100,60,900,130],origin=[-798,25],outputs=plans.RUNS['P1']['outputs'])
fullscreen.comparable(record,copy.deepcopy(record))
for key,value in [('fresh',False),('crossing_A',False),('crossing_B',False),('top_configure',['420','320']),('popup_A',[10,105,900,170]),('roles','fake')]:
bad=copy.deepcopy(record);bad[key]=value;self.rejects(fullscreen.comparable,record,bad)
def test_fullscreen_expected_whole_h2_field(self):
from PIL import Image,ImageDraw
colors=engine.COLORS;output=copy.deepcopy(plans.RUNS['P1']['outputs'][1]);baseline=Image.new('RGB',(800,600),(48,48,56))
g=dict(origin=[-798,25],configured_A=[350,80,900,170],configured_B=[100,60,900,130],A=[-448,105,900,170],B=[-348,165,900,130],crossing=dict(A=True,B=True))
def field(geometry=g,out=output):
expected=baseline.copy();draw=ImageDraw.Draw(expected)
for key,name in (('A','POPUP_A'),('B','POPUP_B')):
x,y,w,h=geometry[key];draw.rectangle((max(0,x),max(0,y),min(799,x+w-1),min(599,y+h-1)),fill=colors[name])
return [baseline.copy(),expected]
good=field();fullscreen.fullscreen_h2_field(good,baseline,g,output,'logical',colors)
wrong=field();wrong[1].putpixel((799,599),colors['POPUP_A']);wrong[1].putpixel((798,599),colors['POPUP_B']);self.rejects(fullscreen.fullscreen_h2_field,wrong,baseline,g,output,'logical',colors)
missing=field();missing[1].putpixel((1,110),baseline.getpixel((1,110)));self.rejects(fullscreen.fullscreen_h2_field,missing,baseline,g,output,'logical',colors)
displaced=copy.deepcopy(g);displaced['A'][0]+=1;self.rejects(fullscreen.fullscreen_h2_field,good,baseline,displaced,output,'logical',colors)
excess=field();excess[1].putpixel((700,500),(1,2,3));self.rejects(fullscreen.fullscreen_h2_field,excess,baseline,g,output,'logical',colors)
residual=field();residual[1].putpixel((500,200),baseline.getpixel((500,200)));self.rejects(fullscreen.fullscreen_h2_field,residual,baseline,g,output,'logical',colors)
reverse=baseline.copy();draw=ImageDraw.Draw(reverse)
for key,name in (('B','POPUP_B'),('A','POPUP_A')):
x,y,w,h=g[key];draw.rectangle((max(0,x),max(0,y),min(799,x+w-1),min(599,y+h-1)),fill=colors[name])
self.rejects(fullscreen.fullscreen_h2_field,[baseline.copy(),reverse],baseline,g,output,'logical',colors)
badscale=copy.deepcopy(output);badscale['scale']=2;self.rejects(fullscreen.fullscreen_h2_field,good,baseline,g,badscale,'logical',colors)
moved=dict(origin=[-398,25],configured_A=[350,80,900,170],configured_B=[100,60,900,130],A=[-48,105,900,170],B=[52,165,900,130],crossing=dict(A=False,B=False))
def moved_field(active=('POPUP_A','POPUP_B')):
expected=baseline.copy();draw=ImageDraw.Draw(expected)
for key,name in (('A','POPUP_A'),('B','POPUP_B')):
if name not in active:continue
x,y,w,h=moved[key];draw.rectangle((max(0,x),max(0,y),min(799,x+w-1),min(599,y+h-1)),fill=colors[name])
return [baseline.copy(),expected]
after_exit=moved_field();fullscreen.fullscreen_h2_field(after_exit,baseline,moved,output,'logical',colors)
a_only=moved_field(('POPUP_A',));fullscreen.fullscreen_h2_field(a_only,baseline,moved,output,'logical',colors,active_roles=('POPUP_A',))
b_residual=moved_field()
b_residual[1].putpixel((100,200),colors['POPUP_B']);self.rejects(fullscreen.fullscreen_h2_field,b_residual,baseline,moved,output,'logical',colors,active_roles=('POPUP_A',))
def test_fullscreen_input_uses_visible_output_fallback(self):
from PIL import Image,ImageDraw
outputs=copy.deepcopy(plans.RUNS['C8']['outputs']);frames={o['name']:'logical' for o in outputs}
h1=Image.new('RGB',(800,600),(48,48,56));h2=Image.new('RGB',(800,600),(48,48,56));ImageDraw.Draw(h2).rectangle((100,190,180,270),fill=engine.COLORS['POPUP_B'])
s=SimpleNamespace(outputs=outputs,frames=frames,click=Mock(return_value=({'owner':''},{'owner':[]})),delivery=Mock())
g=dict(B=[52,165,900,130]);fullscreen.input_target(s,[h1,h2],g,'POPUP_B','B')
self.assertGreaterEqual(s.click.call_args.args[1][0],100);self.assertLessEqual(s.click.call_args.args[1][0],180)
s.delivery.assert_called_once_with('owner',g['B'],s.click.call_args.args[1],{'owner':''},{'owner':[]},'POPUP_B')
def state(self):
rect=dict(x=-800,y=0,width=800,height=600)
owner=dict(type='con',id=40,pid=100,rect=dict(x=-800,y=25,width=400,height=575),window_rect=dict(x=2,y=0,width=396,height=575),nodes=[],floating_nodes=[],fullscreen_mode=0)
peer=dict(type='con',id=41,rect=dict(x=-400,y=25,width=400,height=575),nodes=[],fullscreen_mode=0)
group=dict(type='con',id=30,rect=rect,layout='splith',fullscreen_mode=1,nodes=[owner,peer],floating_nodes=[])
ws=dict(type='workspace',id=20,name='1',output='HEADLESS-1',nodes=[group],floating_nodes=[])
state=dict(owner=owner,workspace=ws,origin=[-798,25],snapshot=dict(tree=ws,outputs=[dict(name='HEADLESS-1',rect=rect)]))
return state,41,30
def test_oom_native_failure_role_nonce_pid_counts(self):
env=dict(SMX_OOM_ROLE='root_popup',SMX_OOM_NONCE='a'*32)
line='SMX_OOM ENOMEM role=root_popup nonce='+env['SMX_OOM_NONCE']+' pid=123 xdg=0x1 xdg_parent=0x2 parent=0x3 tree=0x4 children=0 matched=1 failures=1 successes=0 initialized=0 listeners=0 published=0'
oom.native_failure(line,env,123)
for old,new in [('pid=123','pid=124'),('root_popup','nested_popup'),('matched=1','matched=2'),('failures=1','failures=2'),('successes=0','successes=1'),('published=0','published=1'),('nonce='+env['SMX_OOM_NONCE'],'nonce='+'b'*32),('tree=0x4','tree=(nil)')]:self.rejects(oom.native_failure,line.replace(old,new),env,123)
self.rejects(oom.native_failure,line+'\n'+line,env,123)
def test_real_button_before_failed_map_and_disconnect(self):
raw=(KIT/'wire-fixture.txt').read_text();cut=raw.index('POPUP_A ROLE_CONFIGURE ')
before=raw[:cut];proof=oom_handler.opening_before_map(before,'POPUP_A','TOPLEVEL');self.assertGreater(proof['serial'],0)
oom_handler.mapped_root(raw)
self.rejects(oom_handler.mapped_root,raw.replace('.ack_configure(','.wrong_ack('))
self.rejects(oom_handler.mapped_root,raw.replace('250, 170, 1000, 1)','249, 170, 996, 1)'))
for bad in (before.replace('origin=wl_pointer.button','origin=fake'),before.replace('.grab(','.wrong('),before.replace('parent_xdg=','parent_xdg=9')):self.rejects(oom_handler.opening_before_map,bad,'POPUP_A','TOPLEVEL')
raw='wl_display#1.error(nil, 1, "out of memory")\nEXIT error=71'
self.assertTrue(oom_handler.expected_disconnect(raw,0)['expected_enomem'])
for bad,code in [(raw, None),(raw,-9),(raw,7),(raw.replace(', 1,',', 2,'),0),(raw.replace('71','32'),0),('EXIT error=0',0)]:self.rejects(oom_handler.expected_disconnect,bad,code)
s=SimpleNamespace(comp=Mock());s.comp.poll.return_value=-9;self.rejects(oom_handler.availability,s)
def test_compositor_only_environment_no_helpers_clients(self):
env=oom.process_environment(LAB,'O1','a'*32)
with patch.dict(os.environ,env):self.assertFalse(any(k.startswith('SMX_OOM_') for k in gate.clean_environment(LAB)))
s=engine.Session.__new__(engine.Session);s.run=self.root;s.handles=[];s.proc={};s.expired=False;s.env={};s.oom_env=env;s.compositor_environment=dict(MOSAIC_G2_DIR='offline',MOSAIC_G2_NONCE='a'*64,WLR_RENDERER='gles2');s.debit=Mock();s.record=Mock()
with patch.object(engine.shutil,'which',return_value='/usr/bin/prlimit'),patch.object(engine.subprocess,'Popen',return_value=Mock(pid=12)) as popen:
for name in ('compositor','owner','pointer','screenshot'):
s.spawn(name,['not-executed']);actual=popen.call_args.kwargs['env'];self.assertEqual({k:v for k,v in actual.items() if k.startswith('SMX_OOM_')},env if name=='compositor' else {});self.assertEqual(actual.get('MOSAIC_G2_DIR'),'offline' if name=='compositor' else None);self.assertEqual(actual.get('WLR_RENDERER'),'gles2' if name=='compositor' else None)
for h in s.handles:h.close()
def test_arm_scope_debit_before_token_and_no_reuse(self):
folder=LAB/'graphics-runs/O1/run'
# The real arm path is tested via an isolated OFFLINE_TEST_ONLY run directory;
# patch process_environment path construction only, never access real run paths.
env=dict(SMX_OOM_TOKEN_PATH=str(self.root/'oom-token'),SMX_OOM_NONCE='a'*32,SMX_OOM_ROLE='root_popup')
admission=dict(decision='ACCEPTED',source_manifest_sha256='f',oom_source_review_sha256='a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c',variant_identity='COREC_V2_NATIVE_OOM_DIAGNOSTIC')
s=SimpleNamespace(spec=plans.RUNS['O1'],run=self.root,auth=dict(manifest_sha256='f',prospective=admission,build_review='ACCEPTED',publication_sha256='p'),record=Mock())
debits=[]
def debit(kind):self.assertFalse(Path(env['SMX_OOM_TOKEN_PATH']).exists());debits.append(kind)
s.debit=debit;stable=dict(startup=True,owner=True,neighbor=True,reference_H2_twice=True)
for key in stable:
bad=dict(stable);bad[key]=False;self.rejects(oom.arm,s,env,admission,bad)
self.assertEqual(debits,[]);oom.arm(s,env,admission,stable);self.assertEqual(debits,['hook'])
self.assertEqual((self.root/'oom-token').read_text(),'SMXOOM1 '+'a'*32+' root_popup\n')
s.debit=Mock()
with self.assertRaises(FileExistsError):oom.arm(s,env,admission,stable)
self.assertEqual(s.debit.call_count,1)
s.spec=plans.RUNS['O2'];env['SMX_OOM_ROLE']='nested_popup'
self.rejects(oom.arm,s,env,admission,dict(stable,rootA=True,rootA_native_success=False))
def test_gate_dependency_and_prospective_review(self):
ledger,m,r,p,_,_=self.fixture()
for rid in ('P1','C8','O1','O2','G2','R1'):self.rejects(ledger.admit,rid,m,r,p)
auth=dict(binary='fake')
with patch.object(gate,'validate_review',return_value=auth):
self.rejects(ledger.admit,'O2',m,r,p)
a=ledger.admit('O1',m,r,p);ledger.complete(a,dict(status='INCONCLUSIVE'))
self.rejects(ledger.admit,'O2',m,r,p)
self.assertEqual([x['id'] for x in json.loads(ledger.path.read_text())['runs']],['O1'])
def test_client_immutability_and_future_c2_axis(self):
for name in ('nested-client.c','vertical-client.c','saved-client.c','static-reference.c','pointer-daemon.c'):
self.assertEqual((KIT/'clients'/name).read_bytes(),(LAB/'graphics-kit/clients'/name).read_bytes())
from model import Provenance
from predicates import geometry
g=geometry((KIT/'wire-fixture.txt').read_text(),[0,25],Provenance(40,20,'NOT OBSERVABLE','offline'),1,600)
self.assertEqual(g['crossing_axis'],1);self.assertEqual(g['crossing_boundary'],600);self.assertTrue(all(g['crossing'].values()))
def test_expected_enomem_actual_cleanup_keeps_raw_exit(self):
import threading
class Process:
def __init__(self,pid,code):self.pid=pid;self.returncode=code;self.stdin=io.StringIO()
def poll(self):return self.returncode
def wait(self,timeout=None):return self.returncode
s=engine.Session.__new__(engine.Session);s.spec=plans.RUNS['O1'];s.auth={};s.ledger=Mock();s.run=self.root/'run';s.run.mkdir();s.runtime=self.root/'runtime';s.runtime.mkdir()
s.started=time.monotonic();s.finished=threading.Event();s.expired=False;s.pointer=None;s.env={};s.watch=Mock();s.handles=[];s.events=[];s.closed=[]
s.sock=Mock();s.sock.is_socket.return_value=True;s.comp=Process(999999991,None)
s.proc={'compositor':s.comp,'owner':Process(999999992,1)}
raw='wl_display#1.error(nil, 1, "out of memory")\nEXIT error=71'
(s.run/'owner.log').write_text(raw);s.find=lambda _:None;s.debit=Mock()
oom_handler.retire_enomem(s)
def terminal(*args,**kwargs):s.comp.returncode=0;return SimpleNamespace(returncode=1,stdout='',stderr='')
with patch.object(engine.subprocess,'run',side_effect=terminal),patch.object(engine.os,'killpg',side_effect=ProcessLookupError):
self.assertEqual(s.cleanup('PARTIALLY_FEASIBLE'),'PARTIALLY_FEASIBLE')
out=json.loads((s.run/'outcome.json').read_text());self.assertEqual(out['scientific_cleanup'],'PASS');self.assertEqual(out['client_closures'][0]['exit'],1);self.assertTrue(out['client_closures'][0]['expected_enomem']);self.assertEqual(out['protocol_errors'],['owner'])
def test_gpu_environment_facade_and_hook_debit(self):
import gpu_handler
s=SimpleNamespace(spec=plans.RUNS['G2'],lab=LAB,debit=Mock(),spawn=Mock())
view=gpu_handler.AdapterSession(s);self.assertEqual(view.spec['binary'],'core');self.assertEqual(s.spec['binary'],'gpu')
view.env.update(MOSAIC_G2_DIR=str(LAB/'gpu-work/acquisition'),MOSAIC_G2_NONCE='a'*64,WLR_RENDERER='gles2')
self.assertEqual(s.compositor_environment['MOSAIC_G2_NONCE'],'a'*64)
view.debit('mutation');s.debit.assert_called_once_with('mutation','hook')
view.spawn('g2-background',['client']);s.spawn.assert_called_once_with('g2-background',['client'],True)
self.rejects(view.debit,'capture');self.rejects(view.spawn,'owner',['client'])
self.rejects(view.env.update,MOSAIC_G2_DIR='/tmp/foreign',MOSAIC_G2_NONCE='a'*64,WLR_RENDERER='gles2')
self.rejects(gpu_handler.validate_source_binding,LAB,dict(gpu_source_review='ACCEPTED',gl_observability_preflight='NOT_RUN',native_gl_status='NOT_RUN',build_review='ACCEPTED',pair=3))
def test_gpu_source_binding_actual_frozen_bytes_and_negative(self):
import gpu_handler
receipt=self.root/'external-review.json';receipt.write_text('{"decision":"ACCEPTED","offline_fixture":true,"gl_observability":"PASS","gl_observability_scope":"PREFLIGHT_CAPABILITY_ONLY","native_gl_status":"NOT_RUN"}')
review=dict(gpu_source_review='ACCEPTED',gl_observability_preflight='ACCEPTED',native_gl_status='NOT_RUN',build_review='ACCEPTED',pair=3,gpu_source_manifest=str(Path(os.environ.get('SMX_GPU_SOURCE_MANIFEST',str(LAB/'results/gpu-source-freeze.json')))),gpu_source_manifest_sha256=gate.sha(Path(os.environ.get('SMX_GPU_SOURCE_MANIFEST',str(LAB/'results/gpu-source-freeze.json')))),gate_file=str(receipt),gate_file_sha256=gate.sha(receipt),binding=dict(client=str(receipt),client_sha256=gate.sha(receipt)))
for key in ('gpu_source_review','gl_observability_preflight','build_review'):review[key+'_receipt']=str(receipt);review[key+'_receipt_sha256']=gate.sha(receipt)
gpu_handler.validate_source_binding(LAB,review)
realsha=gpu_handler.sha
with patch.object(gpu_handler,'sha',side_effect=lambda path:'bad' if Path(path)==LAB/'gpu-kit/scenario.py' else realsha(path)):
self.rejects(gpu_handler.validate_source_binding,LAB,review)
for key in ('gpu_source_manifest_sha256','gate_file_sha256','gpu_source_review_receipt_sha256'):
bad=dict(review);bad[key]='wrong';self.rejects(gpu_handler.validate_source_binding,LAB,bad)
def test_gpu_layer_closure_does_not_require_xdg_owner(self):
import gpu_handler
s=gpu_handler.GPUSceneSession.__new__(gpu_handler.GPUSceneSession);s.proc={'g2-background':SimpleNamespace(pid=123)};s.closed=[]
raw='EXIT ns=1 mode=background error=0 commits=3\nzwlr_layer_surface_v1#7.destroy()\nwl_surface#6.destroy()'
s.log=lambda _:raw
def close(self,name,command):self.closed.append(dict(pid=123,status='PASS'))
with patch.object(engine.Session,'close_client',close):
s.close_client('g2-background');self.assertEqual(s.closed[-1]['role'],'zwlr_layer_surface_v1')
raw=raw.replace('zwlr_layer_surface_v1#7.destroy()','xdg_toplevel#7.destroy()');self.rejects(s.close_client,'g2-background');self.assertEqual(s.closed[-1]['status'],'INCONCLUSIVE')
def test_actual_gpu_adapter_caps_and_stop_before_B_on_failed_A(self):
import gpu_handler
scenario=gpu_handler.modules(LAB)
for reject in (False,True):
with self.subTest(reject=reject):
root=self.root/('reject' if reject else 'accepted');root.mkdir()
client=root/'client';client.write_bytes(b'OFFLINE_CLIENT_NOT_EXECUTED')
events=[];commands=[];actions=Counter();test=self
class Input:
def write(self,text):
commands.append(text.strip());e=len(commands)
(root/f'epoch-{e}-point-0.rgba').write_bytes(b'OFFLINE_NATIVE_SOURCE')
(root/f'epoch-{e}.jsonl').write_text('{"kind":"rejected"}\n' if reject else '{"kind":"end"}\n')
def flush(self):pass
class Fake:
def __init__(self):
self.spec=plans.RUNS['G2'];self.auth=dict(binary='synthetic-third-binary',manifest_sha256='f');self.lab=LAB;self.proc={}
def debit(self,*kinds):
actions.update(kinds)
for kind in kinds:test.assertLessEqual(actions[kind],16 if kind=='capture' else self.spec['action_limits'][kind])
def start(self):events.append('start')
def cmd(self,*args):self.debit('configuration')
def spawn(self,name,*args):self.debit('spawn');self.proc[name]=SimpleNamespace(stdin=Input())
def find(self,*args):return dict(id=40)
def wait(self,fn):return fn()
def log(self,name):return 'BACKGROUND_CONFIGURED '+''.join('G2_SOURCE_BYTES command='+c+' ' for c in commands)
def capture(self,*args):self.debit('capture');return Image.new('RGB',(8,8),(48,48,56))
def pair_capture(self,*args):return [self.capture(),self.capture()]
def record(self,*args,**kwargs):pass
def save(self,*args,**kwargs):pass
def snapshot(self,*args):pass
def close_client(self,*args):self.debit('configuration')
fake=Fake();binding=dict(G2_ledger_reserved=True,binary='synthetic-third-binary',source_manifest_sha256='f',gate_file='synthetic-gate',client=str(client),client_sha256=gate.sha(client),nonce='a'*64)
with patch.object(scenario,'ROOT',root),patch.object(scenario,'gate'),patch.object(scenario,'arm'),patch.object(scenario,'epoch',side_effect=lambda directory,e,nonce,prior:dict(raw_total=prior+1)),patch.object(scenario.time,'sleep'),patch.object(gpu_handler.CompositorEnvironment,'update',side_effect=lambda **fields:None):
if reject:
self.rejects(scenario.run,gpu_handler.AdapterSession(fake),binding);self.assertEqual(commands,['G2-A']);self.assertEqual(actions['hook'],1);self.assertEqual(actions['capture'],2)
else:
result=scenario.run(gpu_handler.AdapterSession(fake),binding);self.assertTrue(result['native_source_A_Areturn_exact']);self.assertEqual(actions['capture'],8);self.assertEqual(actions['hook'],3);self.assertEqual(commands,['G2-A','G2-B','G2-A-return'])
def test_new_handler_capture_and_action_caps(self):
for rid,cap in [('P1',10),('C8',12),('O1',8),('O2',8)]:
with self.subTest(rid=rid):self.assertEqual(self.quota(rid)['capture'],cap)
def quota(self,rid):
state,peer,gid=self.state();test=self
class Fake:
def __init__(self):
self.spec=copy.deepcopy(plans.RUNS[rid]);self.outputs=copy.deepcopy(self.spec['outputs']);self.frames={o['name']:'logical' for o in self.outputs};self.actions=Counter();self.proc={};self.events=[];self.run=test.root;self.auth=dict(prospective=dict(client_binary_sha256='offline-client'),manifest_sha256='offline-manifest');self.closed=[];self.oom_env=dict(SMX_OOM_ROLE='root_popup' if rid=='O1' else 'nested_popup',SMX_OOM_NONCE='a'*32);self.comp=Mock(pid=123);self.failed=False
def debit(self,*kinds):
for k in kinds:
self.actions[k]+=1;limit=self.spec['capture_limit'] if k=='capture' else self.spec['action_limits'][k];test.assertLessEqual(self.actions[k],limit)
def cmd(self,c,business=False):
self.debit('mutation' if business else 'configuration')
if rid=='C8' and c.endswith('fullscreen disable'):state['snapshot']['tree']['nodes'][0]['fullscreen_mode']=0
def launch_client(self,n,*args):self.debit('spawn');self.proc[n]=Mock(pid=100 if n=='owner' else 101);self.proc[n].poll.return_value=None
def find(self,n):return dict(id=40 if n=='owner' else 41)
def owner(self,*args):return state
def calibrate(self,*args):return state
def snapshot(self,*args):return state['snapshot']
def capture(self,tag,out):self.debit('capture');return Image.new('RGB',(800,600),(48,48,56))
def pair_capture(self,tag):return [self.capture(tag+'-H1','HEADLESS-1'),self.capture(tag+'-H2','HEADLESS-2')]
def click(self,n,xy,action='right',grab=False):
self.debit('move','click',*(['grab'] if grab else []))
if n=='reference':return {'reference':'wl_pointer#3.button(1, 1, 273, 1)\nwl_pointer#3.button(2, 1, 273, 0)'},{'reference':['BUTTON ns=1 serial=1 button=273 state=1','BUTTON ns=2 serial=2 button=273 state=0']}
return {'owner':''},{'owner':[]}
def inject(self,*args):self.debit('move')
def delivery(self,*args):pass
def wait(self,*args):pass
def save(self,*args):pass
def client_cmd(self,*args):self.debit('configuration')
def close_client(self,*args):self.debit('configuration')
def log(self,n):
if rid in ('P1','C8'):return (KIT/'wire-fixture.txt').read_text()
if n=='compositor':return 'SMX_OOM ENOMEM role='+self.oom_env['SMX_OOM_ROLE']+'\nSMX_OOM result role='+self.oom_env['SMX_OOM_ROLE']+' tree=(nil) failures=1'
raw=(KIT/'wire-fixture.txt').read_text();return raw[:raw.index(('POPUP_A' if rid=='O1' else 'POPUP_B')+' ROLE_CONFIGURE ')]
s=Fake();geo=dict(A=[-448,105,900,170],B=[-348,165,900,130],configured_A=[350,80,900,170],configured_B=[100,60,900,130],origin=[-798,25]);proto=cases.validators.grab((KIT/'wire-fixture.txt').read_text())
with ExitStack() as stack:
stack.enter_context(patch.object(time,'sleep'))
stack.enter_context(patch.object(cases,'stable_reference',side_effect=lambda session:(session.capture('ref1','HEADLESS-2'),session.capture('ref2','HEADLESS-2'))[0]))
if rid in ('P1','C8'):
for name,value in [('solid_point',[-700,100]),('fresh_geometry',geo),('count',0)]:stack.enter_context(patch.object(fullscreen,name,return_value=value))
stack.enter_context(patch.object(fullscreen.validators,'standard_spill'))
stack.enter_context(patch.object(fullscreen,'fullscreen_h2_field'))
import lifecycle
stack.enter_context(patch.object(lifecycle,'explicit_child_close'))
fullscreen.run(s)
else:
stack.enter_context(patch.object(oom_handler,'solid_point',return_value=[-700,100]))
stack.enter_context(patch.object(oom_handler,'native_root_success',return_value=dict(tree='0x1')))
stack.enter_context(patch.object(oom_handler,'availability',return_value=dict(pid=123)))
stack.enter_context(patch.object(oom_handler,'count',side_effect=[1,0]))
stack.enter_context(patch.object(oom,'native_failure',return_value=dict(failures='1')))
stack.enter_context(patch.object(oom,'arm',side_effect=lambda session,*_:session.debit('hook')))
s.auth['prospective']={}
oom_handler.run(s);test.assertEqual(s.actions['hook'],1)
test.assertEqual(s.actions['camera'],0)
return s.actions
if __name__=='__main__':unittest.main(verbosity=2)

View file

@ -0,0 +1,50 @@
"""Private source-only adapter to the independently reviewed graphics-kit Session.
No native run entry point. O1/O2 remain NOT_ADMITTED until separate review.
"""
import os,re
from pathlib import Path
PLANS={
'O1':dict(status='NOT_ADMITTED',role='root_popup',max_captures=8,max_injections=1,requires_rootA_stable=False),
'O2':dict(status='NOT_ADMITTED',role='nested_popup',max_captures=8,max_injections=1,requires_rootA_stable=True),
}
CAPTURES=('reference-H2-a','reference-H2-b','pre-H1','pre-H2','post-H1','post-H2','final-H1','final-H2')
def process_environment(lab,run,nonce):
assert run in PLANS and re.fullmatch('[0-9a-f]{32}',nonce)
lab=Path(lab);assert lab.is_absolute() and lab.resolve()==lab and lab.stat().st_uid==os.getuid()
# Parent must use this update solely in Session's compositor spawn environment.
# Do not put it into Session.env inherited by scientific clients/helpers.
path=lab/'graphics-runs'/run/'run'/'oom-token'
assert not path.exists() and not path.is_symlink()
return dict(SMX_OOM_TOKEN_PATH=str(path),SMX_OOM_NONCE=nonce,SMX_OOM_ROLE=PLANS[run]['role'])
def arm(session,env,admission,stable):
run=session.spec['id'];assert run in PLANS
# Separate reviewed admission must bind variant binary + OOM source freeze,
# graphics engine freeze, independent R-OOM, build review and publication.
assert admission==session.auth['prospective']
assert admission['decision']=='ACCEPTED' and admission['source_manifest_sha256']==session.auth['manifest_sha256']
assert admission['oom_source_review_sha256']=='a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c' and session.auth['build_review']=='ACCEPTED'
assert session.auth['publication_sha256'] and admission['variant_identity']=='COREC_V2_NATIVE_OOM_DIAGNOSTIC'
assert stable['startup'] and stable['owner'] and stable['neighbor'] and stable['reference_H2_twice']
if PLANS[run]['requires_rootA_stable']:assert stable['rootA'] and stable['rootA_native_success']
assert env['SMX_OOM_ROLE']==PLANS[run]['role']
path=Path(env['SMX_OOM_TOKEN_PATH']);assert path.parent.resolve()==session.run.resolve()
assert path.name=='oom-token' and not path.is_symlink()
# The parent's reviewed OOM ledger extension must provide hook cap=1. Debit
# precedes O_EXCL write; failed arm stays spent, with no retry/refund.
session.debit('hook')
fd=os.open(path,os.O_CREAT|os.O_EXCL|os.O_WRONLY|os.O_NOFOLLOW,0o600)
try:
os.fchmod(fd,0o600)
token=f"SMXOOM1 {env['SMX_OOM_NONCE']} {env['SMX_OOM_ROLE']}\n".encode('ascii')
assert os.write(fd,token)==len(token);os.fsync(fd)
finally:os.close(fd)
session.record('oom-arm',role=env['SMX_OOM_ROLE'],nonce=env['SMX_OOM_NONCE'],path=str(path))
def native_failure(log,env,pid):
lines=[line for line in log.splitlines() if 'SMX_OOM ENOMEM ' in line]
assert len(lines)==1
fields=dict(re.findall(r'([a-z_]+)=([^ ]+)',lines[0]))
for key,value in dict(role=env['SMX_OOM_ROLE'],nonce=env['SMX_OOM_NONCE'],pid=str(pid),matched='1',failures='1',initialized='0',listeners='0',published='0').items():assert fields.get(key)==value,(key,fields)
assert all(fields.get(k) not in (None,'(nil)','0x0') for k in ['xdg','xdg_parent','parent','tree'])
assert fields.get('successes')==('0' if env['SMX_OOM_ROLE']=='root_popup' else '1')
assert re.fullmatch(r'\d+',fields.get('children',''))
return fields

View file

@ -0,0 +1,125 @@
"""EXPERIMENTAL prospective O1/O2 handler. No allocator or admission policy."""
import errno,re,time
from pathlib import Path
import cases,oom
from gate import sha,need
from geometry import solid_point,exact,count
from engine import COLORS
def opening_before_map(raw,popup,parent):
# WHY: native no-memory can precede configure/MAP. CONTRACT/INVARIANT:
# validate actual serial/grab/parent wire, never await the failed popup MAP.
rows=re.findall(rf'{popup} CREATE wl=(\d+) xdg=(\d+) role=(\d+) parent={parent} parent_xdg=(\d+)',raw)
need(len(rows)==1,'unique failed popup identity');wl,xdg,role,parent_xdg=map(int,rows[0])
parent_ids=re.findall(rf'{parent} CREATE wl=(\d+) xdg=(\d+) role=(\d+)',raw)
need(len(parent_ids)==1 and int(parent_ids[0][1])==parent_xdg,'failed popup exact parent')
grabs=re.findall(rf'{popup} GRAB_REQUEST origin=wl_pointer.button target={parent} serial=(\d+) used=(\d+)',raw)
need(len(grabs)==1 and grabs[0][0]==grabs[0][1] and int(grabs[0][0])>0,'failed popup real grab')
serial=int(grabs[0][0]);button=raw.index(f'POINTER_BUTTON target={parent} serial={serial} button=272 state=1')
wire=re.search(rf'wl_pointer#\d+\.button\({serial}, \d+, 272, 1\)',raw)
create=re.search(rf'xdg_surface#{xdg}\.get_popup\(new id xdg_popup#{role}, xdg_surface#{parent_xdg}, xdg_positioner#\d+\)',raw)
grab=re.search(rf'xdg_popup#{role}\.grab\(wl_seat#\d+, {serial}\)',raw)
need(wire is not None and create is not None and grab is not None and wire.start()<button<create.start()<grab.start(),'failed grab wire association')
return dict(popup=popup,parent=parent,serial=serial,wl=wl,xdg=xdg,role=role,parent_xdg=parent_xdg)
def mapped_root(raw):
proof=opening_before_map(raw,'POPUP_A','TOPLEVEL')
need(raw.count('POPUP_A MAP ')==1 and 'POPUP_A DESTROY ' not in raw and 'POPUP_A POPUP_DONE ' not in raw,'O2 same rootA mapped')
cfg=re.findall(r'POPUP_A ROLE_CONFIGURE x=(-?\d+) y=(-?\d+) w=(\d+) h=(\d+)',raw)
ack=re.findall(r'POPUP_A XDG_CONFIGURE serial=(\d+) ack',raw)
need(len(cfg)==len(ack)==1,'O2 unique rootA configure/ACK')
x,y,w,h=map(int,cfg[0]);serial=int(ack[0]);xdg=proof['xdg'];role=proof['role'];wl=proof['wl']
rolewire=re.search(rf'xdg_popup#{role}\.configure\({x}, {y}, {w}, {h}\)',raw)
ackwire=re.search(rf'xdg_surface#{xdg}\.ack_configure\({serial}\)',raw)
nativecfg=re.search(rf'xdg_surface#{xdg}\.configure\({serial}\)',raw)
attach=re.search(rf'wl_surface#{wl}\.attach\(wl_buffer#(\d+), 0, 0\)',raw)
commits=list(re.finditer(rf'wl_surface#{wl}\.commit\(\)',raw))
need(all((rolewire,ackwire,nativecfg,attach)) and len(commits)==2,'O2 rootA native configure/map evidence')
buffer=attach[1]
created=re.search(rf'create_buffer\(new id wl_buffer#{buffer}, 0, {w}, {h}, {w*4}, 1\)',raw)
need(created is not None and commits[0].start()<rolewire.start()<nativecfg.start()<ackwire.start()<created.start()<attach.start()<commits[1].start()<raw.index('POPUP_A MAP '),'O2 rootA native ACK/SHM order')
return dict(proof,configure=[x,y,w,h],ack=serial,buffer=int(buffer))
def expected_disconnect(raw,code):
# WHY/CONTRACT/INVARIANT: retain raw no_memory code1 and client errno;
# arbitrary errors, server death and missing EXIT never become normal close.
errors=re.findall(r'wl_display#\d+\.error\([^\n]*?, (\d+), [^\n]*\)',raw)
exits=re.findall(r'EXIT error=(\d+)',raw)
need(code in (0,1) and errors==['1'] and len(exits)==1 and int(exits[0]) in (errno.ENOMEM,errno.EPROTO),'expected no-memory disconnect not established')
return dict(exit=code,wire_error=errors,display_errno=exits,expected_enomem=True)
def retire_enomem(s):
p=s.proc['owner'];raw=s.log('owner');proof=expected_disconnect(raw,p.poll())
need(s.find('owner') is None,'disconnected owner remains in IPC')
proof.update(name='owner',pid=p.pid,status='PASS',meaning='EXPECTED_ENOMEM_DISCONNECT; not ordinary close',raw_log=raw)
s.closed.append(proof);s.record('owner-enomem-disconnect',**proof);return proof
def availability(s):
need(s.comp.poll() is None,'critical compositor death')
exe=Path(f'/proc/{s.comp.pid}/exe')
need(exe.resolve()==Path(s.auth['binary']).resolve() and sha(exe)==s.auth['binary_sha256'],'critical compositor PID/executable changed')
maps=Path(f'/proc/{s.comp.pid}/maps').read_text()
paths={str(Path(line.split()[-1]).resolve()) for line in maps.splitlines() if len(line.split())>=6 and line.split()[-1].startswith('/') and 'libwlroots' in line.split()[-1]}
need(paths=={s.auth['wlroots']} and sha(s.auth['wlroots'])==s.auth['wlroots_sha256'],'critical mapped wlroots changed')
return dict(pid=s.comp.pid,exe=str(exe.resolve()),sha256=sha(exe),wlroots=list(paths),maps=maps)
def native_root_success(raw,pid):
lines=[line for line in raw.splitlines() if 'SMX_OOM result ' in line and 'role=root_popup' in line and 'tree=' in line and 'failures=0' in line]
need(len(lines)==1,'O2 rootA native success identity missing/ambiguous')
fields=dict(re.findall(r'([a-z_]+)=([^ ]+)',lines[0]))
need(fields.get('pid')==str(pid) and fields.get('tree') not in (None,'(nil)','0x0'),'O2 native rootA success')
return fields
def run(s):
cases.init_reference(s);s.debit('chain');s.launch_client('owner',s.spec['client'],s.spec['placement']);s.owner('owner')
s.cmd(f'[con_id={s.find("owner")["id"]}] focus');state=s.calibrate('owner')
baseline=cases.stable_reference(s);root_success=None
if s.spec['id']=='O2':
# Owner origin is corroborated below by actual pointer-local delivery.
origin=state['origin'];xy=[origin[0]+10,origin[1]+100]
tails,buttons=s.click('owner',xy,'left',True)
s.wait(lambda:'POPUP_A MAP ' in s.log('owner'));time.sleep(.15)
root_success=native_root_success(s.log('compositor'),s.comp.pid)
proof=mapped_root(s.log('owner'))
s.delivery('owner',[*origin,420,320],xy,tails,buttons,'TOPLEVEL',proof['serial'])
pre=s.pair_capture('oom-pre');exact(baseline,pre[1]);before=s.snapshot('oom-before')
target='TOPLEVEL' if s.spec['id']=='O1' else 'POPUP_A';popup='POPUP_A' if target=='TOPLEVEL' else 'POPUP_B'
xy=solid_point(pre[0],COLORS[target],s.outputs[0],s.frames['HEADLESS-1'])
stable=dict(startup=True,owner=True,neighbor=s.find('reference') is not None,reference_H2_twice=True,rootA=root_success is not None,rootA_native_success=root_success is not None)
oom.arm(s,s.oom_env,s.auth['prospective'],stable)
tails,buttons=s.click('owner',xy,'left',True)
s.wait(lambda:'SMX_OOM ENOMEM ' in s.log('compositor'))
wire=opening_before_map(s.log('owner'),popup,target)
native=oom.native_failure(s.log('compositor'),s.oom_env,s.comp.pid)
results=[line for line in s.log('compositor').splitlines() if 'SMX_OOM result ' in line and 'role='+s.oom_env['SMX_OOM_ROLE']+' ' in line]
need(len(results)==1 and 'tree=(nil)' in results[0] and 'failures=1' in results[0],'native NULL caller outcome absent')
ident=availability(s);after=s.snapshot('oom-after')
need(popup+' MAP ' not in s.log('owner'),'failed popup unexpectedly mapped')
owner_raw_exit=s.proc['owner'].poll();disconnected=None
if owner_raw_exit is None:
time.sleep(.15);owner_raw_exit=s.proc['owner'].poll()
if owner_raw_exit is not None:disconnected=retire_enomem(s)
post=s.pair_capture('oom-post');exact(baseline,post[1])
old_root=dict(status='NOT_EXERCISED',reason='O1 has no old rootA' if root_success is None else 'owner disconnected or rootA dismissed')
if root_success is not None and disconnected is None and 'POPUP_A DESTROY ' not in s.log('owner') and 'POPUP_A POPUP_DONE ' not in s.log('owner'):
need(count(post[0],COLORS['POPUP_A'])>0 and count(post[1],COLORS['POPUP_A'])==0,'surviving rootA sampled clipping')
old_root=dict(status='PARTIALLY_FEASIBLE',native_success=root_success)
neighbor=s.find('reference');need(neighbor is not None,'surviving neighbor absent')
xy=solid_point(post[1],(48,48,56),s.outputs[1],s.frames['HEADLESS-2'])
tails,buttons=s.click('reference',xy)
# WHY/CONTRACT/INVARIANT: a surviving real popup grab may consume the
# outside click to dismiss; only a measured dismissal permits a fresh
# neighbor click. This does not claim universal click-through.
if not buttons.get('reference'):
need('POPUP_DONE ' in tails.get('owner',''),'neighbor input missing without measured outside dismissal')
s.save('oom-neighbor-outside-dismissal',dict(tails=tails,buttons=buttons))
tails,buttons=s.click('reference',xy)
lines=buttons.get('reference',[])
events=[re.search(r'BUTTON ns=\d+ serial=(\d+) button=(\d+) state=(\d+)',line) for line in lines]
need(len(events)==2 and all(events) and [list(map(int,e.groups()[1:])) for e in events]==[[273,1],[273,0]],'fresh neighbor button pair')
for e in events:need(re.search(rf'wl_pointer#\d+\.button\({e[1]}, \d+, 273, {e[3]}\)',tails['reference']) is not None,'neighbor real wire')
need(not any(v for k,v in buttons.items() if k!='reference'),'neighbor button not exclusive')
if disconnected is None:s.close_client('owner')
final=s.pair_capture('oom-final');exact(baseline,final[1])
s.save('oom-measurements',dict(native=native,wire=wire,rootA_success=root_success,old_rootA=old_root,before=before,after=after,availability=ident,owner_raw_exit=owner_raw_exit,owner_disconnect=disconnected,neighbor_buttons=buttons,H2_pre_post_final='EXACT',captures=8,complete_damage='NOT_PROVEN',native_stale_listeners='NOT_PROVEN',native_no_partial_popup='NOT_PROVEN; IPC has no popup-node schema',atomic_generation='NOT_PROVEN'))
return 'PARTIALLY_FEASIBLE'

View file

@ -12,8 +12,13 @@ RUNS['C4']['outputs'][0]=output('HEADLESS-1',[-800,0,800,600],[750,1000],1.25,'9
# Geometry certificates and distinct diagnostics are prerequisite source evidence.
for rid in ('P1','C8'):
RUNS[rid].update(admission='NOT_ADMITTED',reason='No offline equal-child nonleaf fullscreen configure/crossing certificate; no empirical calibration authorized')
for rid in ('P1','C8'):
RUNS[rid].update(client='fullscreen-client',placement='fullscreen_cross')
for rid in ('O1','O2'):
RUNS[rid]['binary']='oom';RUNS[rid]['action_limits']['hook']=1
for rid in ('O1','O2','G2','R1'):
RUNS[rid].update(admission='NOT_ADMITTED',reason='Separately reviewed diagnostic/discriminant source hook and exact binary unavailable')
RUNS['G2']['binary']='gpu';RUNS['G2']['action_limits']['hook']=3
assert len(RUNS)==14 and sum(CAPS.values())==170 and max(CAPS.values())==18
def config(spec):

View file

@ -41,7 +41,7 @@ def configured(text,name):
assert rows,(name,'no configure')
return list(map(int,rows[-1]))
def geometry(text,origin,provenance=None):
def geometry(text,origin,provenance=None,axis=0,boundary=0):
a=configured(text,'POPUP_A');b=configured(text,'POPUP_B')
require(provenance is not None,'popup-owner-provenance-required')
p=provenance
@ -55,7 +55,7 @@ def geometry(text,origin,provenance=None):
parent=popup(parent,Rect(Space.POPUP,*c,p),parent_id,ids[parent_name][1],ack,name+' MAP ' in text)
result[key]=parent.values()
result.update(configured_A=a,configured_B=b,origin=origin,provenance=dict(owner=p.owner,workspace=p.workspace,generation=p.generation,evidence=p.evidence,state=p.state),
crossing={key:crossing(Rect(Space.GLOBAL,*result[key],p),0) for key in ('A','B')})
crossing_axis=axis,crossing_boundary=boundary,crossing={key:(result[key][axis]<boundary<result[key][axis]+result[key][axis+2]) for key in ('A','B')})
return result
def mapped(text):

View file

@ -0,0 +1,20 @@
"""C17 build of the prospective client only. Never executes it."""
import json,shlex,subprocess
from pathlib import Path
from gate import canonical_lab,clean_environment,durable,sha,need
def prepare(lab):
lab=canonical_lab(lab);src=Path(__file__).resolve().parent;build=lab/'graphics-next-work/client-build';build.mkdir(exist_ok=False)
env=clean_environment(lab);commands=[]
def invoke(argv):
r=subprocess.run(list(map(str,argv)),env=env,capture_output=True,text=True,timeout=30)
commands.append(dict(argv=list(map(str,argv)),exit=r.returncode,stdout=r.stdout,stderr=r.stderr))
durable(lab/'graphics-next-work/client-compile.json',dict(status='PENDING' if r.returncode==0 else 'FAIL',commands=commands,runtime='NOT_RUN'))
need(r.returncode==0,'fullscreen client build failed');return r.stdout.strip()
flags=shlex.split(invoke(['pkg-config','--cflags','--libs','wayland-client']))
for mode,suffix in [('client-header','client.h'),('private-code','protocol.c')]:invoke(['wayland-scanner',mode,src/'protocols/xdg-shell.xml',build/('xdg-shell-'+suffix)])
invoke(['cc','-std=c17','-O2','-Wall','-Wextra','-I',build,src/'clients/fullscreen-client.c',build/'xdg-shell-protocol.c','-o',build/'fullscreen-client',*flags])
durable(lab/'graphics-next-work/client-compile.json',dict(status='PASS',commands=commands,inputs={name:sha(src/name) for name in ('clients/fullscreen-client.c','protocols/xdg-shell.xml')},generated={p.name:sha(p) for p in build.iterdir()},runtime='NOT_RUN'))
if __name__=='__main__':
import argparse
p=argparse.ArgumentParser();p.add_argument('--lab',required=True);prepare(p.parse_args().lab)

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""WHY/CONTRACT/INVARIANT: reserve once, reviewed bytes only, no retry."""
import argparse,time,re
import argparse,time,re,json
from gate import Ledger,need
from plans import RUNS
from engine import Session
@ -46,8 +46,26 @@ COLORS=cases.COLORS
def execute(rid,lab,manifest,review,publication,session_factory=Session):
auth=Ledger(lab).admit(rid,manifest,review,publication);s=None;status='INCONCLUSIVE';failure=None
try:
s=session_factory(RUNS[rid],auth);s.start()
if rid=='C1':status=horizontal(s)
if rid=='G2' and session_factory is Session:
from gpu_handler import GPUSceneSession
s=GPUSceneSession(RUNS[rid],auth)
else:s=session_factory(RUNS[rid],auth)
if rid!='G2':s.start()
if rid=='G2':
from gpu_handler import run as gpu_run
status=gpu_run(s)
elif rid in ('P1','C8'):
from fullscreen import run as fullscreen_run
status=fullscreen_run(s)
if rid=='C8' and status=='PARTIALLY_FEASIBLE':
from fullscreen import comparable
control=s.lab/'graphics-runs/P1/run/fullscreen-comparability.json'
need(control.is_file(),'P1 actual comparability evidence missing')
s.save('fullscreen-pair-comparison',comparable(json.loads(control.read_text()),json.loads((s.run/'fullscreen-comparability.json').read_text())))
elif rid in ('O1','O2'):
from oom_handler import run as oom_run
status=oom_run(s)
elif rid=='C1':status=horizontal(s)
elif rid=='C5':status=cases.hidden_campaign(s)
elif rid=='C6':
from saved import run
@ -61,6 +79,8 @@ def execute(rid,lab,manifest,review,publication,session_factory=Session):
normal_remaining(s)
except Exception as error:
failure=f'{type(error).__name__}: {error}';status='INCONCLUSIVE'
if rid in ('O1','O2') and s is not None:
s.save('oom-partial-failure',dict(status='INCONCLUSIVE',failure=failure,critical_or_unresolved=True,blocks_O2=rid=='O1',owner_exit=s.proc['owner'].poll() if 'owner' in s.proc else None,compositor_exit=s.comp.poll() if hasattr(s,'comp') else None,events=s.events,captures_observed=sum(e['kind']=='capture' for e in s.events),captures_expected=8,missing_evidence='NOT_PROVEN; no retry',raw_owner=s.log('owner') if 'owner' in s.proc else None))
finally:
if s is not None:status=s.cleanup(status,failure)
else:Ledger(lab).complete(auth,dict(status='INCONCLUSIVE',failure=failure,session_constructed=False))

View file

@ -0,0 +1,16 @@
"""Run targeted non-GUI validation and retain its command/output receipt."""
import argparse,subprocess,sys
from pathlib import Path
from gate import canonical_lab,clean_environment,durable,sha
def validate(lab,gpu_source_manifest=None):
lab=canonical_lab(lab);root=Path(__file__).resolve().parent;work=lab/'graphics-next-work'
env=clean_environment(lab);env.update(SMX_TEST_LAB=str(lab),SMX_OFFLINE_SCRATCH=str(work/'OFFLINE_TEST_ONLY'))
if gpu_source_manifest:env['SMX_GPU_SOURCE_MANIFEST']=str(Path(gpu_source_manifest).resolve())
argv=[sys.executable,str(root/'offline/test_prospective.py')]
result=subprocess.run(argv,env=env,capture_output=True,text=True,timeout=30)
receipt=dict(status='PASS' if result.returncode==0 else 'FAIL',command=argv,exit=result.returncode,stdout=result.stdout,stderr=result.stderr,source_files={str(p.relative_to(root)):sha(p) for p in sorted(root.rglob('*')) if p.is_file()},runtime='NOT_RUN',new_reservations=0,new_native_captures=0,actual_GL_observability='NOT_TESTED',gpu_source_manifest=str(gpu_source_manifest) if gpu_source_manifest else None,tests='48: original32 plus prospective16',known_corrected_test_failures=['OOM quota synthetic root paint lacked color before patched fake input','G2 quota precreated raw files violated native freshness gate before corrected fake input'])
durable(work/'offline-validation.json',receipt)
return result.returncode
if __name__=='__main__':
p=argparse.ArgumentParser();p.add_argument('--lab',required=True);p.add_argument('--gpu-source-manifest');a=p.parse_args();raise SystemExit(validate(a.lab,a.gpu_source_manifest))

View file

@ -0,0 +1,55 @@
# O1/O2 separate graphics handler — EXPERIMENTAL, NOT_ADMITTED
This adapter does not amend the reviewed graphics-kit. Parent integration must
receive a new immutable manifest/review/publication and new plans O1/O2, with the
new ELF SHA/BuildID/provider. Neither original CORE results nor graphics admission
transfer to it. No native OOM experiment has run. Production policy UNDECIDED.
The reviewed engine Session can be imported; extend its compositor spawn only to
pass process_environment() output. Do not pass diagnostic environment to clients,
pointer, swaymsg or screenshot helpers. The hook-token is absent at startup.
Extend the existing ledger with per-case hook cap=1 and captures cap=8; debit hook
before arm(), never retry/reset/refund. O2 is dependent on no critical O1 failure.
The adapter's admission dictionary is a downstream contract, NOT a cryptographic
admission gate: the parent must verify actual manifests and independent reviews
through its reviewed gate before creating Session. Calling arm() alone is never
sufficient authority. PLANS deliberately stay NOT_ADMITTED here.
Order, each within the predeclared run deadline: startup, owner + neighbor, wait
applied stability, capture H2 reference twice and compare exact whole field;
pre-H1/H2; for O2 open rootA through a measured real button serial/grab, require
native result root_popup success tree identity and stable rootA before pre pair;
arm token after this condition. O1 next real owner button creates root_popup; O2
next real rootA button creates nested_popup. No extra popup/client may race between
arming and the intended call. Record real serial/grab wire evidence. The injection
log identifies role, XDG identity, XDG parent, scene parent/unpublished tree,
parent child count, compositor PID, nonce, one-shot counters and successes.
Immediately inspect owner raw process status and Wayland wl_display ENOMEM code,
wlroots popup mapping/chain, exact native failure, compositor liveness and ELF/PID,
new IPC tree and absence of partial popup nodes. Distinguish compositor death from
owner no-memory disconnect. An ENOMEM owner death may be an observed native NULL
outcome; do not send fake normal close, override exit to zero, or require owner
normal scientific cleanup. Surviving neighbor must receive a new measured input.
For O2 inspect old rootA clipping if it survives; owner ENOMEM disconnect makes
this property NOT_EXERCISED, never PASS. Preserve all raw statuses in receipt.
Capture post-H1/H2 and final-H1/H2, exactly eight captures total including the two
references. Compare complete H2 exact against both references. Reconcile geometry,
input and owner tree before/after. If compositor dies, capture actions cannot run:
record missing evidence NOT_PROVEN/BLOCKED and stop O2 on critical failure. Cleanup
only owned processes/sockets, retain logs. Never force Session.finish() ordinary
client-close assertions onto an ENOMEM client. Complete damage, native stale
sidecars/listeners, atomic generations and GPU lifetime remain NOT_PROVEN unless
separate measured native evidence closes them.
Required per-case receipt: source freeze SHA, build/ELF IDs, gate and publication
SHA, nonce/role/PID, arm time and hook debit, rootA success identity before O2,
serial/grab wire records, single native ENOMEM fields, owner raw exit and protocol
error, compositor survival, owner/neighbor IPC before/after, neighbor input,
H2 reference/pre/post/final equality, surviving rootA clip or NOT_EXERCISED,
eight capture actions/hashes (or honest missing), raw cleanup, limits and verdict.
Parent must implement/test the settled scenario handler and ledger integration
before admitting O1. This file and adapter are SOURCE ONLY, not an executable
scenario CLI and not proof of native availability.

View file

@ -0,0 +1,69 @@
# CORE-C V2 private native OOM diagnostic source variant
EXPERIMENTAL SOURCE ONLY. Production availability policy UNDECIDED. Distinct from
accepted CORE candidate; no production source or dependency change. R-OOM review,
pair-2 build, ELF/staging review and separate graphics admission remain REQUIRED.
O1/O2 runtime NOT_RUN. No global allocator hook, memory pressure or native run.
Parent is exact independently reviewed CORE trees reconstructed with sibling
`kit/assemble.py`. Parent source/C review SHA256:
`26aa862c741196fdbb8d7cdf5509301e49f763cdd22ffa7bcb1a4bbf09c66f90`.
`provenance.json` binds complete parent and variant files/modes and both deltas.
These are parent-relative patches, not cumulative upstream patches: first assemble
the accepted sibling core kit against its public pins, then apply this variant.
The core provenance SHA is bound, every actual source file is verified before
copying and after forward application. No current-source trust by folder name.
Use private LAB/run-env for EVERY command; TMPDIR/TMP/TEMP and all caches/data
must remain under owned LAB /var/tmp, no session env/loader routing inherited.
```sh
LAB/run-env python LAB/oom-kit/assemble-variant.py --core LAB/review-source-c/fresh --destination LAB/oom-work/fresh-variant
LAB/run-env python LAB/oom-kit/tests/run.py --sources LAB/oom-work/fresh-variant --output LAB/oom-work/new-h1-extension
```
Destination/output must be absent canonical paths under /var/tmp. No Meson,
compositor, Wayland client, IPC or GPU is launched. This extends existing H1 C
corpus; no new native/sanitizer campaign reservation is implicitly authorized.
Only primary popup_create scene allocation uses private wrapper; parent XDG role
is obtained via native wlr_xdg_surface_try_from_wlr_surface. Scope resets on return.
Only sidecar reservation at native factory before scene_tree_init can fail.
Unscoped tree creation and tree calloc stay native. Existing caller NULL paths
remain unchanged; native owner ENOMEM/disconnect must be measured, not simulated.
New private SceneFX symbol is not declared/installed in any public API/header.
Native process-only env: SMX_OOM_TOKEN_PATH absolute private LAB canonical path,
SMX_OOM_NONCE 32 lowercase hex, SMX_OOM_ROLE root_popup|nested_popup, snapshotted at
startup. Runner creates token AFTER startup/owner stability and, for O2, successful
stable rootA. Exact bytes `SMXOOM1 <nonce> <role>\n`, O_EXCL, mode0600, owned regular
single-link file. O_NOFOLLOW/O_NONBLOCK/O_CLOEXEC + UID/type/mode/length/content
checks; invalid input disables injection. Private canonical parent directory is
runner-owned; final component symlink refused. No token deletion/rearming/retry.
Once a valid matching scope consumes it, all subsequent calls succeed normally.
Logging includes identities, counters and pre-init native parent list length;
initialized/listeners/published zero is asserted by position/source and tested
factory adapters, not a complete native damage/lifetime measurement.
Nine cases in normal/UBSan/ASan+UBSan: root one-shot, rootA then nested one-shot,
unarmed, wrong role, malformed length/content, wrong nonce, unsafe mode, symlink,
invalid process config. All verify ordinary allocation and final sidecar cleanup.
Six independently compiled direct mutants target global scope, prepublication,
role, token reuse, malformed acceptance and nonce comparison. Each executable
sets PR_SET_DUMPABLE0/GET_DUMPABLE0 before assertions; parent sets RLIMIT_CORE0.
Exact bodies/slices/fullfile hashes are in evidence/bindings.json. Callsite slice
compiles against native wlroots headers, with reduced popup holder only.
Rendering/damage/IME/transaction adapters are inherited source but these OOM tests
only execute factory/lifecycle paths. No complete compositor build or survival.
Initial extension-1 failed compilation due shell quoting of character literals;
fixed before extension-2 PASS; extension-3 includes corrected native parent typed
callsite and PASS; final extension adds a private forward declaration for native
-Wmissing-prototypes compatibility and again PASS. Failed compile did not count as a killed mutant. The final oracle refinement moves init once in its negative mutant and asserts
parent publication before free; all six kills are direct SIGABRT assertions.
Raw earlier attempts remain private. evidence/result.json is the final bounded evidence, not runtime.
Separate graphics-adapter.py and GRAPHICS_HANDLER_CONTRACT.md supply interfaces
and complete scenario contract using existing reviewed graphics engine. They do
not implement the final settled handler/ledger admission. O1/O2 NOT_ADMITTED;
parent must implement/test/review the integration and publish all sources before
O1. Maximum eight captures, one role-matched failure each. No result transfers.

View file

@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""Apply private OOM deltas to exact reviewed CORE trees; no build/runtime."""
import argparse,hashlib,json,os,pathlib,shutil,subprocess
P=pathlib.Path;H=P(__file__).resolve().parent
def manifest(root):
result={}
for p in sorted(root.rglob('*')):
if p.is_symlink():raise ValueError('symlink source')
if p.is_file():result[str(p.relative_to(root))]={'sha256':hashlib.sha256(p.read_bytes()).hexdigest(),'mode':oct(p.stat().st_mode&0o777)}
return result
def main():
ap=argparse.ArgumentParser();ap.add_argument('--core',type=P,required=True);ap.add_argument('--destination',type=P,required=True);a=ap.parse_args()
d=a.destination.absolute();assert d.is_relative_to(P('/var/tmp')) and d!=P('/var/tmp') and d.resolve()==d and not d.exists()
os.umask(0o077);d.mkdir(mode=0o700);p=json.loads((H/'provenance.json').read_text());receipt={}
for c,e in p['components'].items():
assert manifest(a.core/c)==e['parent_files'],c+' exact reviewed parent mismatch'
patch=H/e['patch'];assert hashlib.sha256(patch.read_bytes()).hexdigest()==e['patch_sha256']
dst=d/c;shutil.copytree(a.core/c,dst)
env=dict(os.environ,GIT_CEILING_DIRECTORIES=str(d))
subprocess.run(['git','apply','--check',str(patch)],cwd=dst,env=env,check=True)
subprocess.run(['git','apply',str(patch)],cwd=dst,env=env,check=True)
for r in e['changed_files']:(dst/r).chmod(int(e['files'][r]['mode'],8))
assert manifest(dst)==e['files'],c+' variant mismatch'
receipt[c]={'forward_apply':True,'manifest_sha256':hashlib.sha256(json.dumps(e['files'],sort_keys=True).encode()).hexdigest()}
(d/'assembly-receipt.json').write_text(json.dumps(receipt,indent=2)+'\n');print(json.dumps(receipt,indent=2))
if __name__=='__main__':main()

View file

@ -0,0 +1,11 @@
{
"status": "PASS_OFFLINE",
"checks": [
"exclusive owned token exact bytes0600",
"debit before write",
"rearm refused retaining debit",
"single native failure synthetic parser with nonce/PID/role",
"O2 no stable rootA refused before hook"
],
"runtime": "NOT_RUN"
}

View file

@ -0,0 +1,270 @@
[
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "sidecar definitions",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 1366,
"end_byte_exclusive": 2545,
"start_line": 46,
"slice_sha256": "61128058349bdd75e529df4c564c00c9261fdd188c3ed1785d16e155009f93ac"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_tree_from_node",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 2545,
"end_byte_exclusive": 2749,
"start_line": 81,
"slice_sha256": "eec86e4de94b3e8ecc56bbf1655f5e80bf9b1fb43672e58698818d3bb581757f"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_rect_from_node",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 2751,
"end_byte_exclusive": 2955,
"start_line": 87,
"slice_sha256": "d24ec68f941a9cd25c22638678604fadb5d5c815ea8c9c477f6c79e9797a6604"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_buffer_from_node",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 3223,
"end_byte_exclusive": 3444,
"start_line": 101,
"slice_sha256": "a79c1cb11a8dcfb7c203862a1304ffd74ce532096150a67ff790488ca4e31a16"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_blur_from_node",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 3666,
"end_byte_exclusive": 3870,
"start_line": 114,
"slice_sha256": "406bb535a31826551502f60e3a7f8c9c9a48b1a3bd61c84820ef5f1814d721b6"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_node_get_root",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 3872,
"end_byte_exclusive": 4238,
"start_line": 120,
"slice_sha256": "229ff36d803d141fa9291dfd11da272f4a20a73c3adfd35ce39aba22bdeac134"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_node_init",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 4240,
"end_byte_exclusive": 4684,
"start_line": 135,
"slice_sha256": "fd10c53736e569431d8a5acd3d2c34ded432b2ff3c4948c34d8229d7fe352679"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_tree_init",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 7615,
"end_byte_exclusive": 7837,
"start_line": 239,
"slice_sha256": "6eea6009ad5de2fee58d7b9827250ae03eacfd052ca76ac2d9ae31f6e84c6e3e"
},
{
"component": "scene",
"path": "types/scene/oom-diagnostic.inc",
"symbol": "complete private diagnostic",
"fullfile_sha256": "738d3bdfb536ad0a3e3a53e7a1794456864e3305ff6b859ff799491acee80b93",
"start_byte": 0,
"end_byte_exclusive": 4037,
"slice_sha256": "738d3bdfb536ad0a3e3a53e7a1794456864e3305ff6b859ff799491acee80b93"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_tree_create",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 8809,
"end_byte_exclusive": 9598,
"start_line": 280,
"slice_sha256": "47e6cbe2c8fbbcdae1a98e269f60c2745348af2ca594a4c4c59e2bf1e9ed57b0"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_node_coords",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 63043,
"end_byte_exclusive": 63681,
"start_line": 1985,
"slice_sha256": "bf47222dc25f599102c3c5f1fddf2542327ec8fa4ee070ba55f7e433c03b0f38"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_node_set_enabled",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 60595,
"end_byte_exclusive": 60944,
"start_line": 1885,
"slice_sha256": "2aad4804bb853d2751dcfca03ad9aa73899d116c54fd02eaa3e21d8937e8f2e7"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_node_reparent",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 62347,
"end_byte_exclusive": 63041,
"start_line": 1958,
"slice_sha256": "fa5650b166e1939fe37977b8afed94ed8250a78cafa067a78e79844976e51dfe"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_node_destroy",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 5000,
"end_byte_exclusive": 7613,
"start_line": 166,
"slice_sha256": "bcc37abe8cf74f6d97394ef4ef76c65c5f4850b611d74aa21c81cdcf94bfe113"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_clip_translate",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 23238,
"end_byte_exclusive": 23735,
"start_line": 732,
"slice_sha256": "e278bdd04860150718f2b8684e4872c065a589e73c342eebaed7a034978e8fde"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_node_intersect_clip",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 23961,
"end_byte_exclusive": 24750,
"start_line": 748,
"slice_sha256": "2d7fc0d466a23a359dbef8d528ceb966747617c1422d03aad51069fa705eb32a"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "scene_node_point_inside_clip",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 24752,
"end_byte_exclusive": 25407,
"start_line": 774,
"slice_sha256": "e502de6c90918cb9151400f7f06b1640ef5fcdd64a2aca5cd5de0f8965a3ecf3"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_tree_set_clip",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 31642,
"end_byte_exclusive": 32804,
"start_line": 992,
"slice_sha256": "66169f9f10e9fe7ffc73cf1eeec6440f974a30d944885e4becebcb754567d2c8"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "wlr_scene_tree_get_clip",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 32806,
"end_byte_exclusive": 33035,
"start_line": 1015,
"slice_sha256": "c186bc54ac2b6b63dfa7e812caa3455805b5a5b33874bcde273f6994c73c9e54"
},
{
"component": "scene",
"path": "types/scene/wlr_scene.c",
"symbol": "native hit iterator and data",
"fullfile_sha256": "ad797ab689ebb739582c79142e352ca0781e4a02126927558b813b13ec1b2173",
"start_byte": 64590,
"end_byte_exclusive": 65814,
"start_line": 2040,
"slice_sha256": "31423e212f75590085a4ad75c3ce60555c849e579e0bc0497c04d03b71d0104b"
},
{
"component": "mosaic",
"path": "sway/desktop/transaction.c",
"symbol": "probe_clip_box_intersection",
"fullfile_sha256": "972b2e6d7f897c9e469a5d85e38d43d9e4c9199964a612b871a3fb2f06b27c16",
"start_byte": 37301,
"end_byte_exclusive": 37994,
"start_line": 1041,
"slice_sha256": "4e55af2f6cc0b251f01257e6ccd3b147b3710500bf50cc70b5f1ea9108c26a7b"
},
{
"component": "mosaic",
"path": "sway/desktop/transaction.c",
"symbol": "probe_camera_scroll",
"fullfile_sha256": "972b2e6d7f897c9e469a5d85e38d43d9e4c9199964a612b871a3fb2f06b27c16",
"start_byte": 30510,
"end_byte_exclusive": 30657,
"start_line": 874,
"slice_sha256": "8f70413dfca32aa8aca3462f2024c4705ce85ead3a023723e3b552d9c4a66d0c"
},
{
"component": "mosaic",
"path": "sway/input/text_input.c",
"symbol": "input_popup_set_focus",
"fullfile_sha256": "fe7864d08cd89b3b3d57b4c8373fa4928a353ad483b72fe9c72d93d839d7a7f0",
"start_byte": 12679,
"end_byte_exclusive": 16261,
"start_line": 368,
"slice_sha256": "a901d876f1d492c5c6f3f79b292ba1baa2f4663adec4ebd7f06f9f477e7ddb92"
},
{
"component": "mosaic",
"path": "sway/desktop/transaction.c",
"symbol": "probe_workspace_clip",
"fullfile_sha256": "972b2e6d7f897c9e469a5d85e38d43d9e4c9199964a612b871a3fb2f06b27c16",
"start_byte": 30659,
"end_byte_exclusive": 31434,
"start_line": 879,
"slice_sha256": "ddb762b2d9610e88259b3920c75dbfea7acbac13f41b1b6e3663748884709528"
},
{
"component": "mosaic",
"path": "sway/desktop/transaction.c",
"symbol": "workspace_tiling_scene_x",
"fullfile_sha256": "972b2e6d7f897c9e469a5d85e38d43d9e4c9199964a612b871a3fb2f06b27c16",
"start_byte": 31436,
"end_byte_exclusive": 31961,
"start_line": 898,
"slice_sha256": "188d668788ea8edb504b7914375dc2330da88e2ab312552190badb40644470ca"
},
{
"component": "mosaic",
"path": "sway/desktop/transaction.c",
"symbol": "probe_clip_popup",
"fullfile_sha256": "972b2e6d7f897c9e469a5d85e38d43d9e4c9199964a612b871a3fb2f06b27c16",
"start_byte": 38227,
"end_byte_exclusive": 41840,
"start_line": 1060,
"slice_sha256": "35113ed3d0d4c345e4b4497eeab9d46ec84caad2b99e4f096cbab68c9c73e477"
},
{
"component": "mosaic",
"path": "sway/desktop/xdg_shell.c",
"symbol": "exact primary popup diagnostic callsite",
"fullfile_sha256": "a72c00cf08020160a564d89b2e4d8a9e65ed985c2a94e05a4e134ec4bf790ac7",
"start_byte": 3465,
"end_byte_exclusive": 3764,
"slice_sha256": "8131fad68728498d9282a473f75fe4b7217558c958dd9cadce9dce1b1ca8c648"
}
]

View file

@ -0,0 +1,696 @@
{
"status": "PASS_BOUNDED",
"campaign": "existing H1 source-corpus extension; no native runtime reservation",
"cases": [
"root",
"nested",
"unarmed",
"wrongrole",
"malformed",
"nonce",
"mode",
"symlink",
"invalidenv"
],
"mutants": [
"global_scope",
"after_publication",
"wrong_role",
"token_reuse",
"malformed_accepted",
"nonce_ignored"
],
"records": [
{
"label": "extract",
"argv": [
"/usr/bin/python",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/extract.py",
"--sources",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input",
"--output",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "native-header-callsite-syntax",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-fsyntax-only",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/callsite.c"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-root",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"root"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-nested",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"nested"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-unarmed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"unarmed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-wrongrole",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"wrongrole"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-malformed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"malformed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-nonce",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"nonce"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-mode",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"mode"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-symlink",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"symlink"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "normal-invalidenv",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/normal",
"invalidenv"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-fsanitize=undefined",
"-fno-sanitize-recover=all",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-root",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"root"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-nested",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"nested"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-unarmed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"unarmed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-wrongrole",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"wrongrole"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-malformed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"malformed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-nonce",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"nonce"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-mode",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"mode"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-symlink",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"symlink"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "ubsan-invalidenv",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/ubsan",
"invalidenv"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-fsanitize=address,undefined",
"-fno-sanitize-recover=all",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-root",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"root"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-nested",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"nested"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-unarmed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"unarmed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-wrongrole",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"wrongrole"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-malformed",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"malformed"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-nonce",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"nonce"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-mode",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"mode"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-symlink",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"symlink"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "asan-ubsan-invalidenv",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/asan-ubsan",
"invalidenv"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "global_scope-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-global_scope"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-global_scope",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-global_scope",
"root"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
},
{
"label": "after_publication-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-after_publication"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-after_publication",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-after_publication",
"root"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
},
{
"label": "wrong_role-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-wrong_role"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-wrong_role",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-wrong_role",
"wrongrole"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
},
{
"label": "token_reuse-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-token_reuse"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-token_reuse",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-token_reuse",
"root"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
},
{
"label": "malformed_accepted-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-malformed_accepted"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-malformed_accepted",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-malformed_accepted",
"malformed"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
},
{
"label": "nonce_ignored-compile",
"argv": [
"cc",
"-std=c17",
"-Wall",
"-Wextra",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-function",
"-g",
"-O1",
"-fno-omit-frame-pointer",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/input/scene/include",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final",
"-I/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests",
"-I/usr/include/wlroots-0.20",
"-I/usr/include/pixman-1",
"-I/usr/include/libdrm",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-kit/tests/oom.c",
"-lwlroots-0.20",
"-lwayland-server",
"-lm",
"-lpixman-1",
"-lm",
"-Wno-unused-variable",
"-o",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-nonce_ignored"
],
"rc": 0,
"expected": 0,
"passed": true
},
{
"label": "mutant-nonce_ignored",
"argv": [
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/oom-work/h1-extension-oracle-final/mutant-nonce_ignored",
"nonce"
],
"rc": -6,
"expected": "nonzero runtime assertion/sanitizer",
"passed": true
}
],
"limits": [
"native compositor survival NOT_RUN",
"popup C callsite source binding only; no complete Sway build",
"damage/render use inherited reduced adapters; complete damage NOT_PROVEN"
],
"core_limit": [
0,
0
],
"dumpability": "PR_SET_DUMPABLE0 and PR_GET_DUMPABLE0 asserted in each executable before test assertions"
}

View file

@ -0,0 +1,47 @@
"""Private source-only adapter to the independently reviewed graphics-kit Session.
No native run entry point. O1/O2 remain NOT_ADMITTED until separate review.
"""
import os,re
from pathlib import Path
PLANS={
'O1':dict(status='NOT_ADMITTED',role='root_popup',max_captures=8,max_injections=1,requires_rootA_stable=False),
'O2':dict(status='NOT_ADMITTED',role='nested_popup',max_captures=8,max_injections=1,requires_rootA_stable=True),
}
CAPTURES=('reference-H2-a','reference-H2-b','pre-H1','pre-H2','post-H1','post-H2','final-H1','final-H2')
def process_environment(lab,run,nonce):
assert run in PLANS and re.fullmatch('[0-9a-f]{32}',nonce)
lab=Path(lab);assert lab.is_absolute() and lab.resolve()==lab and lab.stat().st_uid==os.getuid()
# Parent must use this update solely in Session's compositor spawn environment.
# Do not put it into Session.env inherited by scientific clients/helpers.
path=lab/'graphics-runs'/run/'run'/'oom-token'
assert not path.exists() and not path.is_symlink()
return dict(SMX_OOM_TOKEN_PATH=str(path),SMX_OOM_NONCE=nonce,SMX_OOM_ROLE=PLANS[run]['role'])
def arm(session,env,admission,stable):
run=session.spec['id'];assert run in PLANS
# Separate reviewed admission must bind variant binary + OOM source freeze,
# graphics engine freeze, independent R-OOM, build review and publication.
assert admission['decision']=='ACCEPTED' and admission['run']==run
assert admission['oom_source_review']=='ACCEPTED' and admission['build_review']=='ACCEPTED'
assert admission['publication']=='VERIFIED' and admission['variant_identity']=='COREC_V2_NATIVE_OOM_DIAGNOSTIC'
assert stable['startup'] and stable['owner'] and stable['neighbor'] and stable['reference_H2_twice']
if PLANS[run]['requires_rootA_stable']:assert stable['rootA'] and stable['rootA_native_success']
assert env['SMX_OOM_ROLE']==PLANS[run]['role']
path=Path(env['SMX_OOM_TOKEN_PATH']);assert path.parent.resolve()==session.run.resolve()
assert path.name=='oom-token' and not path.is_symlink()
# The parent's reviewed OOM ledger extension must provide hook cap=1. Debit
# precedes O_EXCL write; failed arm stays spent, with no retry/refund.
session.debit('hook')
fd=os.open(path,os.O_CREAT|os.O_EXCL|os.O_WRONLY|os.O_NOFOLLOW,0o600)
try:
os.fchmod(fd,0o600)
token=f"SMXOOM1 {env['SMX_OOM_NONCE']} {env['SMX_OOM_ROLE']}\n".encode('ascii')
assert os.write(fd,token)==len(token);os.fsync(fd)
finally:os.close(fd)
session.record('oom-arm',role=env['SMX_OOM_ROLE'],nonce=env['SMX_OOM_NONCE'],path=str(path))
def native_failure(log,env,pid):
lines=[line for line in log.splitlines() if 'SMX_OOM ENOMEM ' in line]
assert len(lines)==1
fields=dict(re.findall(r'([a-z_]+)=([^ ]+)',lines[0]))
for key,value in dict(role=env['SMX_OOM_ROLE'],nonce=env['SMX_OOM_NONCE'],pid=str(pid),matched='1',failures='1',initialized='0',listeners='0',published='0').items():assert fields.get(key)==value,(key,fields)
assert all(fields.get(k) not in (None,'(nil)','0x0') for k in ['xdg','xdg_parent','parent','tree'])
return fields

View file

@ -0,0 +1,30 @@
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -19,6 +19,13 @@
#include "sway/tree/workspace.h"
#include "sway/xdg_decoration.h"
+// PRIVATE EXPERIMENTAL: exact primary-popup reservation diagnostic only.
+// WHY/CONTRACT: actual XDG parent role scopes only this native factory call.
+// INVARIANT: all existing NULL cleanup/Wayland behavior remains native.
+extern struct wlr_scene_tree *smx_oom_popup_tree_create(
+ struct wlr_scene_tree *parent, const char *role,
+ const void *xdg, const void *xdg_parent);
+
static struct sway_xdg_popup *popup_create(
struct wlr_xdg_popup *wlr_popup, struct sway_view *view,
struct wlr_scene_tree *parent, struct wlr_scene_tree *image_capture_parent);
@@ -90,7 +97,11 @@
popup->wlr_xdg_popup = wlr_popup;
popup->view = view;
- popup->scene_tree = wlr_scene_tree_create(parent);
+ struct wlr_xdg_surface *xdg_parent =
+ wlr_xdg_surface_try_from_wlr_surface(wlr_popup->parent);
+ popup->scene_tree = smx_oom_popup_tree_create(parent,
+ xdg_parent && xdg_parent->role == WLR_XDG_SURFACE_ROLE_POPUP ?
+ "nested_popup" : "root_popup", xdg_surface, xdg_parent);
if (!popup->scene_tree) {
free(popup);
return NULL;

View file

@ -0,0 +1,125 @@
diff --git a/types/scene/oom-diagnostic.inc b/types/scene/oom-diagnostic.inc
new file mode 100644
--- /dev/null
+++ b/types/scene/oom-diagnostic.inc
@@ -0,0 +1,99 @@
+/* PRIVATE EXPERIMENTAL diagnostic; never an installed API or availability policy.
+ * WHY: fail the native sidecar reservation, not an unrelated global allocation.
+ * CONTRACT: constructor snapshots process-private configuration; a later owned
+ * token arms one matching primary popup call only. Invalid input disables it.
+ * INVARIANT: no scene init, listener or parent publication precedes reservation.
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static struct {
+ char path[4096], nonce[33], role[13];
+ bool configured, consumed, scoped;
+ const char *call_role;
+ const void *xdg, *xdg_parent;
+ unsigned matched, failures, successes;
+} oom_diag;
+
+static bool oom_role_valid(const char *s) {
+ return s && (!strcmp(s, "root_popup") || !strcmp(s, "nested_popup"));
+}
+
+__attribute__((constructor)) static void oom_diag_startup(void) {
+ const char *path = getenv("SMX_OOM_TOKEN_PATH");
+ const char *nonce = getenv("SMX_OOM_NONCE");
+ const char *role = getenv("SMX_OOM_ROLE");
+ if (!path || path[0] != '/' || strlen(path) >= sizeof(oom_diag.path) ||
+ !nonce || strlen(nonce) != 32 || !oom_role_valid(role)) return;
+ for (unsigned i = 0; i < 32; ++i) {
+ if (!((nonce[i] >= '0' && nonce[i] <= '9') ||
+ (nonce[i] >= 'a' && nonce[i] <= 'f'))) return;
+ }
+ strcpy(oom_diag.path, path);
+ strcpy(oom_diag.nonce, nonce);
+ strcpy(oom_diag.role, role);
+ oom_diag.configured = true;
+}
+
+static bool oom_diag_token(void) {
+ /* NONBLOCK avoids blocking even on an unexpected FIFO. NOFOLLOW refuses the
+ * final symlink; the runner owns the canonical private LAB parent directory. */
+ int fd = open(oom_diag.path, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0) return false;
+ struct stat st;
+ char token[80], expected[80];
+ int length = snprintf(expected, sizeof(expected), "SMXOOM1 %s %s\n",
+ oom_diag.nonce, oom_diag.role);
+ bool valid = fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
+ st.st_uid == getuid() && (st.st_mode & 0777) == 0600 &&
+ st.st_nlink == 1 && st.st_size == length;
+ ssize_t got = valid ? read(fd, token, sizeof(token)) : -1;
+ close(fd);
+ return valid && got == length && !memcmp(token, expected, (size_t)length);
+}
+
+static void *oom_diag_reserve(struct wlr_scene_tree *parent,
+ struct wlr_scene_tree *tree, size_t size) {
+ if (oom_diag.scoped && oom_diag.configured && !oom_diag.consumed &&
+ !strcmp(oom_diag.call_role, oom_diag.role) && oom_diag_token()) {
+ oom_diag.matched++;
+ oom_diag.consumed = true;
+ oom_diag.failures++;
+ fprintf(stderr, "SMX_OOM ENOMEM role=%s nonce=%s pid=%ld xdg=%p "
+ "xdg_parent=%p parent=%p tree=%p children=%d matched=%u failures=%u "
+ "successes=%u initialized=0 listeners=0 published=0\n",
+ oom_diag.call_role, oom_diag.nonce, (long)getpid(), oom_diag.xdg,
+ oom_diag.xdg_parent, (void *)parent, (void *)tree,
+ wl_list_length(&parent->children), oom_diag.matched,
+ oom_diag.failures, oom_diag.successes);
+ errno = ENOMEM;
+ return NULL;
+ }
+ return calloc(1, size);
+}
+
+/* Private link declaration repeated only in native xdg_shell.c. No public
+ * header/struct or installed ABI is changed. Scope cannot escape this call. */
+struct wlr_scene_tree *smx_oom_popup_tree_create(struct wlr_scene_tree *parent,
+ const char *role, const void *xdg, const void *xdg_parent);
+
+struct wlr_scene_tree *smx_oom_popup_tree_create(struct wlr_scene_tree *parent,
+ const char *role, const void *xdg, const void *xdg_parent) {
+ assert(!oom_diag.scoped && oom_role_valid(role));
+ oom_diag.scoped = true;
+ oom_diag.call_role = role;
+ oom_diag.xdg = xdg;
+ oom_diag.xdg_parent = xdg_parent;
+ struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
+ oom_diag.scoped = false;
+ if (tree) oom_diag.successes++;
+ fprintf(stderr, "SMX_OOM result role=%s pid=%ld xdg=%p xdg_parent=%p "
+ "parent=%p tree=%p successes=%u failures=%u\n", role, (long)getpid(),
+ xdg, xdg_parent, (void *)parent, (void *)tree,
+ oom_diag.successes, oom_diag.failures);
+ oom_diag.call_role = NULL;
+ oom_diag.xdg = oom_diag.xdg_parent = NULL;
+ return tree;
+}
diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c
--- a/types/scene/wlr_scene.c
+++ b/types/scene/wlr_scene.c
@@ -275,6 +275,8 @@
return scene;
}
+#include "oom-diagnostic.inc"
+
struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) {
assert(parent);
@@ -286,7 +288,7 @@
// WHY: admission failure must precede parent publication and listeners.
// CONTRACT: every factory tree has an inactive reservation until destroy.
// INVARIANT: failed reservation leaves no published node or listener.
- struct scene_tree_clip *entry = calloc(1, sizeof(*entry));
+ struct scene_tree_clip *entry = oom_diag_reserve(parent, tree, sizeof(*entry));
if (entry == NULL) {
free(tree);
return NULL;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Extract exact full C bodies and bind offsets/full-file SHA/slice SHA."""
import argparse, hashlib, json, pathlib, re
ap=argparse.ArgumentParser();ap.add_argument("--sources",type=pathlib.Path,required=True);ap.add_argument("--output",type=pathlib.Path,required=True);args=ap.parse_args()
if not args.output.absolute().is_relative_to(pathlib.Path("/var/tmp")) or args.output.absolute().resolve()!=args.output.absolute():
raise ValueError("Explicit private /var/tmp output required")
args.output.mkdir(parents=True,exist_ok=True)
bindings=[]
def extract(component,relative,name):
path=args.sources/component/relative;raw=path.read_bytes()
# Definitions have their opening brace before the next semicolon.
found=[]
for match in re.finditer(rb"^(?:static )?(?:struct [A-Za-z_0-9]+ \*|bool |void |int )"+name.encode()+rb"\(",raw,re.M):
a=match.start();opening=raw.index(b"{",match.end());semi=raw.find(b";",match.end())
if semi>=0 and semi<opening:continue
found.append((a,opening))
assert len(found)==1,(name,found)
a,opening=found[0];end=opening+1;depth=1
while depth:
if raw[end:end+1]==b"{":depth+=1
elif raw[end:end+1]==b"}":depth-=1
end+=1
piece=raw[a:end]
bindings.append(dict(component=component,path=relative,symbol=name,fullfile_sha256=hashlib.sha256(raw).hexdigest(),start_byte=a,end_byte_exclusive=end,start_line=raw[:a].count(b"\n")+1,slice_sha256=hashlib.sha256(piece).hexdigest()))
return piece
scene="types/scene/wlr_scene.c"
raw=(args.sources/"scene"/scene).read_bytes();a=raw.index(b"struct scene_tree_clip {");b=raw.index(b"struct wlr_scene_tree *wlr_scene_tree_from_node",a)
parts=[raw[a:b]];bindings.append(dict(component="scene",path=scene,symbol="sidecar definitions",fullfile_sha256=hashlib.sha256(raw).hexdigest(),start_byte=a,end_byte_exclusive=b,start_line=raw[:a].count(b"\n")+1,slice_sha256=hashlib.sha256(raw[a:b]).hexdigest()))
for name in ["wlr_scene_tree_from_node","wlr_scene_rect_from_node","wlr_scene_buffer_from_node","wlr_scene_blur_from_node","scene_node_get_root","scene_node_init","scene_tree_init","wlr_scene_tree_create","wlr_scene_node_coords","wlr_scene_node_set_enabled","wlr_scene_node_reparent","wlr_scene_node_destroy","scene_clip_translate","scene_node_intersect_clip","scene_node_point_inside_clip","wlr_scene_tree_set_clip","wlr_scene_tree_get_clip"]:
if name == "wlr_scene_tree_create":
diagnostic=(args.sources/"scene/types/scene/oom-diagnostic.inc").read_bytes()
parts.append(diagnostic)
bindings.append(dict(component="scene",path="types/scene/oom-diagnostic.inc",symbol="complete private diagnostic",fullfile_sha256=hashlib.sha256(diagnostic).hexdigest(),start_byte=0,end_byte_exclusive=len(diagnostic),slice_sha256=hashlib.sha256(diagnostic).hexdigest()))
parts.append(extract("scene",scene,name))
a=raw.index(b"struct node_at_data {");b=raw.index(b"struct wlr_scene_node *wlr_scene_node_at",a)
parts.append(raw[a:b]);bindings.append(dict(component="scene",path=scene,symbol="native hit iterator and data",fullfile_sha256=hashlib.sha256(raw).hexdigest(),start_byte=a,end_byte_exclusive=b,start_line=raw[:a].count(b"\n")+1,slice_sha256=hashlib.sha256(raw[a:b]).hexdigest()))
(args.output/"scene.inc").write_bytes(b"\n\n".join(parts)+b"\n")
parts=[extract("mosaic","sway/desktop/transaction.c",name) for name in ["probe_clip_box_intersection","probe_camera_scroll"]]
(args.output/"geometry.inc").write_bytes(b"\n\n".join(parts)+b"\n")
(args.output/"ime.inc").write_bytes(extract("mosaic","sway/input/text_input.c","input_popup_set_focus")+b"\n")
parts=[extract("mosaic","sway/desktop/transaction.c",name) for name in ["probe_workspace_clip","workspace_tiling_scene_x","probe_clip_popup"]]
(args.output/"transaction.inc").write_bytes(b"\n\n".join(parts)+b"\n")
(args.output/"bindings.json").write_text(json.dumps(bindings,indent=2)+"\n")
raw=(args.sources/"mosaic/sway/desktop/xdg_shell.c").read_bytes()
a=raw.index(b"struct wlr_xdg_surface *xdg_parent =");b=raw.index(b"\n\tif (!popup->scene_tree)",a)
piece=raw[a:b]
bindings.append(dict(component="mosaic",path="sway/desktop/xdg_shell.c",symbol="exact primary popup diagnostic callsite",fullfile_sha256=hashlib.sha256(raw).hexdigest(),start_byte=a,end_byte_exclusive=b,slice_sha256=hashlib.sha256(piece).hexdigest()))
(args.output/"callsite.c").write_bytes(b"#define WLR_USE_UNSTABLE\n#include <scenefx/types/wlr_scene.h>\n#include <wlr/types/wlr_xdg_shell.h>\nstruct adapter_popup {struct wlr_scene_tree *scene_tree;};\nextern struct wlr_scene_tree *smx_oom_popup_tree_create(struct wlr_scene_tree *, const char *, const void *, const void *);\nvoid test_callsite(struct adapter_popup *popup, struct wlr_scene_tree *parent, struct wlr_xdg_popup *wlr_popup, struct wlr_xdg_surface *xdg_surface) {\n"+piece+b"\n}\n")
(args.output/"bindings.json").write_text(json.dumps(bindings,indent=2)+"\n")

View file

@ -0,0 +1,38 @@
// Reduced Sway/protocol adapters for the exact input_popup_set_focus body.
// No protocol/grab or real compositor focus/damage claim.
struct wlr_surface {struct {struct wl_signal unmap;}events;};
struct wlr_layer_surface_v1 {struct wlr_surface *surface;void *data;struct wlr_output *output;};
struct wlr_session_lock_surface_v1 {struct wlr_surface *surface;void *data;};
struct sway_container;
struct sway_view {struct wlr_scene_tree *scene_tree;struct {struct wl_signal unmap;}events;struct sway_container *container;};
struct sway_popup_desc {struct wlr_scene_node *relative;struct sway_view *view;};
struct sway_input_popup {struct wl_listener focused_surface_unmap;struct wlr_scene_tree *scene_tree;struct sway_popup_desc desc;struct wlr_output *fixed_output;};
struct sway_layer_surface {struct {struct wlr_scene_tree *tree;} *scene;struct wlr_layer_surface_v1 *layer_surface;};
static struct sway_view *focused_view;
static bool descriptor_live,descriptor_failure;
static unsigned constraints;
#define SWAY_SCENE_DESC_POPUP 1
#define SWAY_DEBUG 1
#define sway_log(level, ...) ((void)(level))
static struct wlr_layer_surface_v1 *wlr_layer_surface_v1_try_from_wlr_surface(struct wlr_surface *s){(void)s;return NULL;}
static struct wlr_session_lock_surface_v1 *wlr_session_lock_surface_v1_try_from_wlr_surface(struct wlr_surface *s){(void)s;return NULL;}
static struct sway_view *view_from_wlr_surface(struct wlr_surface *s){(void)s;return focused_view;}
static void scene_descriptor_destroy(struct wlr_scene_node *n,int type){(void)n;(void)type;descriptor_live=false;}
static bool scene_descriptor_assign(struct wlr_scene_node *n,int type,void *d){(void)n;(void)type;(void)d;if(descriptor_failure)return false;descriptor_live=true;return true;}
static void constrain_popup(struct sway_input_popup *p){(void)p;constraints++;}
#include "ime.inc"
static void ime_tests(struct wlr_scene_tree *root) {
watched=NULL;fail_reservation=0;
struct sway_view view={.scene_tree=wlr_scene_tree_create(root)};assert(view.scene_tree);wl_signal_init(&view.events.unmap);focused_view=&view;
struct sway_input_popup popup={.scene_tree=wlr_scene_tree_create(root)};assert(popup.scene_tree);wl_list_init(&popup.focused_surface_unmap.link);
struct wlr_surface surface={0};wl_signal_init(&surface.events.unmap);
input_popup_set_focus(&popup,&surface);assert(popup.scene_tree->node.enabled);assert(popup.desc.relative);assert(descriptor_live);assert(wl_list_length(&view.events.unmap.listener_list)==1);
fail_reservation=reservations+1;
input_popup_set_focus(&popup,&surface);assert(!popup.scene_tree->node.enabled);assert(!popup.desc.relative&&!popup.desc.view&&!popup.fixed_output);assert(!descriptor_live);assert(wl_list_empty(&view.events.unmap.listener_list));assert(wl_list_empty(&view.scene_tree->children));
// A failed refocus can be retried; only complete admission re-enables.
fail_reservation=0;input_popup_set_focus(&popup,&surface);assert(popup.scene_tree->node.enabled&&popup.desc.relative);assert(wl_list_length(&view.events.unmap.listener_list)==1);
descriptor_failure=true;input_popup_set_focus(&popup,&surface);assert(!popup.scene_tree->node.enabled);assert(!popup.desc.relative&&!descriptor_live);assert(wl_list_empty(&view.events.unmap.listener_list));assert(wl_list_empty(&view.scene_tree->children));
descriptor_failure=false;input_popup_set_focus(&popup,&surface);assert(popup.scene_tree->node.enabled);
input_popup_set_focus(&popup,NULL);assert(!popup.scene_tree->node.enabled&&!popup.desc.relative&&!descriptor_live);assert(wl_list_empty(&view.events.unmap.listener_list));
wlr_scene_node_destroy(&popup.scene_tree->node);wlr_scene_node_destroy(&view.scene_tree->node);focused_view=NULL;assert(!count_clips());
}

View file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
"""Synthetic/token tests only. No actual graphics-engine admission or process."""
import argparse,importlib.util,json,pathlib,stat
P=pathlib.Path;ap=argparse.ArgumentParser();ap.add_argument('--output',type=P,required=True);a=ap.parse_args()
o=a.output.absolute();assert o.is_relative_to(P('/var/tmp')) and not o.exists() and o.resolve()==o;o.mkdir(mode=0o700)
spec=importlib.util.spec_from_file_location('adapter',P(__file__).resolve().parents[1]/'graphics-adapter.py');m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
class Session:
spec={'id':'O1'}
run=o/'run'
def __init__(self):self.calls=[]
def debit(self,k):assert k=='hook';self.calls.append(k)
def record(self,k,**kw):self.calls.append(k)
s=Session();s.run.mkdir(mode=0o700)
e={'SMX_OOM_TOKEN_PATH':str(s.run/'oom-token'),'SMX_OOM_NONCE':'123456789abcdef0123456789abcdef0','SMX_OOM_ROLE':'root_popup'}
a=dict(decision='ACCEPTED',run='O1',oom_source_review='ACCEPTED',build_review='ACCEPTED',publication='VERIFIED',variant_identity='COREC_V2_NATIVE_OOM_DIAGNOSTIC')
stable=dict(startup=True,owner=True,neighbor=True,reference_H2_twice=True)
m.arm(s,e,a,stable);assert s.calls==['hook','oom-arm'];assert (s.run/'oom-token').read_text()=='SMXOOM1 '+e['SMX_OOM_NONCE']+' root_popup\n';assert stat.S_IMODE((s.run/'oom-token').stat().st_mode)==0o600
try:m.arm(s,e,a,stable)
except FileExistsError:pass
else:raise AssertionError('rearm unexpectedly accepted')
assert s.calls==['hook','oom-arm','hook']
log='SMX_OOM ENOMEM role=root_popup nonce='+e['SMX_OOM_NONCE']+' pid=123 xdg=0x1 xdg_parent=0x2 parent=0x3 tree=0x4 children=0 matched=1 failures=1 successes=0 initialized=0 listeners=0 published=0'
m.native_failure(log,e,123)
for bad in [log+'\n'+log,log.replace('pid=123','pid=124'),log.replace('role=root_popup','role=nested_popup')]:
try:m.native_failure(bad,e,123)
except AssertionError:pass
else:raise AssertionError('bad synthetic failure accepted')
s.spec={'id':'O2'};a['run']='O2';stable.update(rootA=False,rootA_native_success=False)
prior=list(s.calls)
try:m.arm(s,e,a,stable)
except AssertionError:pass
else:raise AssertionError('O2 without stable rootA accepted')
assert s.calls==prior
result=dict(status='PASS_OFFLINE',checks=['exclusive owned token exact bytes0600','debit before write','rearm refused retaining debit','single native failure synthetic parser with nonce/PID/role','O2 no stable rootA refused before hook'],runtime='NOT_RUN')
(o/'result.json').write_text(json.dumps(result,indent=2)+'\n');print(result['status'])

View file

@ -0,0 +1,124 @@
#define _POSIX_C_SOURCE 200809L
#define WLR_USE_UNSTABLE
#define WLR_PRIVATE
#define WLR_INFO 1
#define wlr_log(level, ...) ((void)(level))
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wayland-server-core.h>
#include <pixman.h>
#include <scenefx/types/wlr_scene.h>
#include <wlr/render/drm_syncobj.h>
// Adapters: no renderer/output/damage qualification. Actual native scene
// structs, addon set, signals and Pixman are used. Only tree paths exercised.
static unsigned updates, attempts, reservations, fail_reservation, fail_hits;
static void scene_node_update(struct wlr_scene_node *n, pixman_region32_t *damage) {
(void)n; updates++; if(damage) pixman_region32_fini(damage);
}
static void scene_node_visibility(struct wlr_scene_node *n,pixman_region32_t *r) {(void)n;(void)r;}
static void scene_buffer_set_buffer(struct wlr_scene_buffer *n,struct wlr_buffer *b) {(void)n;(void)b;abort();}
static void scene_buffer_set_texture(struct wlr_scene_buffer *n,struct wlr_texture *t) {(void)n;(void)t;abort();}
void linked_node_destroy(struct linked_node *n) {(void)n;abort();}
static size_t sidecar_size;
static struct wlr_scene_tree *watched;
static int expected_children;
static void *injected_calloc(size_t count,size_t size) {
attempts++;
if (size==sidecar_size) {
reservations++;
assert(!watched || wl_list_length(&watched->children)==expected_children);
if(reservations==fail_reservation){fail_hits++;return NULL;}
}
return calloc(count,size);
}
static void injected_free(void *p) {
// Test adapter: assert admission parent state before freeing unpublished tree.
assert(!watched || wl_list_length(&watched->children)==expected_children);
free(p);
}
#define free injected_free
#define calloc injected_calloc
#include "scene.inc"
#undef calloc
#undef free
#include "geometry.inc"
static unsigned count_clips(void) {unsigned n=0;for(struct scene_tree_clip *it=scene_tree_clips;it;it=it->next)n++;return n;}
static unsigned inactive_count(void) {unsigned n=0;for(struct scene_tree_clip *it=scene_tree_clips;it;it=it->next)if(!it->active)n++;return n;}
#include "ime-support.inc"
#include "transaction-support.inc"
static struct wlr_scene *make_root(void) {
struct wlr_scene *s=calloc(1,sizeof(*s));assert(s);scene_tree_init(&s->tree,NULL);
wl_list_init(&s->outputs);wl_list_init(&s->linux_dmabuf_v1_destroy.link);
wl_list_init(&s->gamma_control_manager_v1_destroy.link);wl_list_init(&s->gamma_control_manager_v1_set_gamma.link);return s;
}
static void __attribute__((unused)) geometry(void) {
struct wlr_box a={INT_MIN,INT_MIN,1,1},b={800,0,800,600},r;
assert(!probe_clip_box_intersection(&r,&a,&b));assert(r.width==0);
a=(struct wlr_box){INT_MAX-2,0,2,10};b=a;assert(probe_clip_box_intersection(&a,&a,&b));assert(a.width==2);
a=(struct wlr_box){INT_MIN,0,INT_MAX,20};b=(struct wlr_box){-10,1,20,10};assert(probe_clip_box_intersection(&b,&a,&b));assert(b.x==-10&&b.width==9);
a=(struct wlr_box){INT_MAX,0,1,1};assert(!scene_clip_translate(&a,1,0,&a));assert(a.width==0);
a=(struct wlr_box){1,2,3,4};assert(scene_clip_translate(&a,2,3,&a));assert(a.x==3&&a.y==5);
assert(probe_camera_scroll(NAN)==0);assert(probe_camera_scroll(INFINITY)==0);assert(probe_camera_scroll(-INFINITY)==0);
assert(probe_camera_scroll(1e300)==INT_MAX);assert(probe_camera_scroll(-1e300)==0);assert(probe_camera_scroll(42.9)==42);
}
static void token_write(const char *content, mode_t mode) {
int fd=open(oom_diag.path,O_CREAT|O_EXCL|O_WRONLY,0600);assert(fd>=0);
size_t n=strlen(content);assert(write(fd,content,n)==(ssize_t)n);
assert(fchmod(fd,mode)==0);assert(close(fd)==0);
}
static struct wlr_scene_tree *primary(struct wlr_scene_tree *p,const char *r) {
return smx_oom_popup_tree_create(p,r,(const void *)0x1234,(const void *)0x5678);
}
int main(int argc,char **argv) {
assert(prctl(PR_SET_DUMPABLE,0,0,0,0)==0);
assert(prctl(PR_GET_DUMPABLE,0,0,0,0)==0);
assert(argc==2);sidecar_size=sizeof(struct scene_tree_clip);
struct wlr_scene *s=make_root();struct wlr_scene_tree *root=&s->tree;
char valid[80];snprintf(valid,sizeof(valid),"SMXOOM1 %s %s\n",oom_diag.nonce,oom_diag.role);
bool inject=!strcmp(argv[1],"root")||!strcmp(argv[1],"nested");
struct wlr_scene_tree *a=NULL,*b=NULL;
if(!strcmp(argv[1],"nested")) {
a=primary(root,"root_popup");assert(a);assert(oom_diag.successes==1);
assert(count_clips()==1); // rootA exists before the runner arms.
}
if(strcmp(argv[1],"unarmed") && strcmp(argv[1],"invalidenv")) {
if(!strcmp(argv[1],"malformed")) token_write("bad token\n",0600);
else if(!strcmp(argv[1],"nonce")) token_write("SMXOOM1 00000000000000000000000000000000 root_popup\n",0600);
else if(!strcmp(argv[1],"mode")) token_write(valid,0644);
else if(!strcmp(argv[1],"symlink")) {assert(symlink("/dev/null",oom_diag.path)==0);}
else token_write(valid,0600);
}
// Ordinary/native factories never acquire diagnostic authority, even armed.
unsigned before=count_clips();b=wlr_scene_tree_create(root);assert(b);
assert(!oom_diag.failures);wlr_scene_node_destroy(&b->node);assert(count_clips()==before);
const char *role=!strcmp(argv[1],"nested")?"nested_popup":
!strcmp(argv[1],"wrongrole")?"nested_popup":"root_popup";
struct wlr_scene_tree *parent=a?a:root;
unsigned children=(unsigned)wl_list_length(&parent->children), clips=count_clips();
unsigned listener_count=(unsigned)wl_list_length(&parent->node.events.destroy.listener_list);
watched=parent;expected_children=(int)children;
b=primary(parent,role);watched=NULL;
if(inject) {
assert(!b);assert(errno==ENOMEM);assert(oom_diag.failures==1&&oom_diag.matched==1);
assert((unsigned)wl_list_length(&parent->children)==children);
assert(count_clips()==clips);
assert((unsigned)wl_list_length(&parent->node.events.destroy.listener_list)==listener_count);
assert(!oom_diag.scoped&&!oom_diag.call_role&&!oom_diag.xdg&&!oom_diag.xdg_parent);
// The same valid token is still present: it must never trigger twice.
b=primary(parent,role);assert(b&&oom_diag.failures==1);
} else {assert(b);assert(!oom_diag.failures&&!oom_diag.consumed);}
wlr_scene_node_destroy(&root->node);assert(!count_clips());
printf("PASS case=%s failures=%u matched=%u successes=%u final_reservations=0\n",argv[1],oom_diag.failures,oom_diag.matched,oom_diag.successes);
return 0;
}

View file

@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""Bounded H1 extension only. No compositor, runtime budget or new campaign."""
import argparse,json,os,pathlib,resource,shlex,subprocess,sys
P=pathlib.Path
H=P(__file__).resolve().parent
ap=argparse.ArgumentParser();ap.add_argument('--sources',type=P,required=True);ap.add_argument('--output',type=P,required=True);a=ap.parse_args()
o=a.output.absolute()
assert str(o).startswith('/var/tmp/') and o.resolve()==o and not o.exists()
o.mkdir(mode=0o700);resource.setrlimit(resource.RLIMIT_CORE,(0,0));records=[]
def call(argv,label,env=None,negative=False):
r=subprocess.run(list(map(str,argv)),capture_output=True,env=env)
(o/(label+'.stdout')).write_bytes(r.stdout);(o/(label+'.stderr')).write_bytes(r.stderr)
passed=r.returncode!=0 if negative else r.returncode==0
records.append(dict(label=label,argv=list(map(str,argv)),rc=r.returncode,expected='nonzero runtime assertion/sanitizer' if negative else 0,passed=passed))
(o/'commands.json').write_text(json.dumps(records,indent=2)+'\n');return passed
assert call([sys.executable,H/'extract.py','--sources',a.sources,'--output',o],'extract')
cflags=shlex.split(subprocess.check_output(['pkg-config','--cflags','wayland-server','pixman-1','wlroots-0.20'],text=True))
libs=shlex.split(subprocess.check_output(['pkg-config','--libs','wayland-server','pixman-1','wlroots-0.20'],text=True))
base=['cc','-std=c17','-Wall','-Wextra','-Werror','-Wno-unused-parameter','-Wno-unused-function','-g','-O1','-fno-omit-frame-pointer','-I'+str(a.sources/'scene/include'),'-I'+str(o),'-I'+str(H),*cflags,str(H/'oom.c'),*libs,'-lm']
cases=['root','nested','unarmed','wrongrole','malformed','nonce','mode','symlink','invalidenv']
def env_for(label,case):
return dict(os.environ,SMX_OOM_TOKEN_PATH=str(o/(label+'.token')),SMX_OOM_NONCE='bad' if case=='invalidenv' else '123456789abcdef0123456789abcdef0',SMX_OOM_ROLE='nested_popup' if case=='nested' else 'root_popup',ASAN_OPTIONS='detect_leaks=1:abort_on_error=1',UBSAN_OPTIONS='halt_on_error=1:print_stacktrace=1')
ok=call(['cc','-std=c17','-Wall','-Wextra','-Werror','-fsyntax-only','-I'+str(a.sources/'scene/include'),*cflags,str(o/'callsite.c')],'native-header-callsite-syntax')
for name,flags in [('normal',[]),('ubsan',['-fsanitize=undefined','-fno-sanitize-recover=all']),('asan-ubsan',['-fsanitize=address,undefined','-fno-sanitize-recover=all'])]:
binary=o/name
if not call(base+flags+['-o',str(binary)],name+'-compile'):ok=False;break
for case in cases:
label=name+'-'+case;ok=call([binary,case],label,env_for(label,case)) and ok
original=(o/'scene.inc').read_text()
mutants={
'global_scope':('oom_diag.scoped && oom_diag.configured && !oom_diag.consumed &&\n\t\t\t!strcmp(oom_diag.call_role, oom_diag.role) && oom_diag_token()', 'oom_diag.configured && !oom_diag.consumed && oom_diag_token()'),
'after_publication':('struct scene_tree_clip *entry = oom_diag_reserve(parent, tree, sizeof(*entry));','scene_tree_init(tree, parent);\nstruct scene_tree_clip *entry = oom_diag_reserve(parent, tree, sizeof(*entry));'),
'wrong_role':('!strcmp(oom_diag.call_role, oom_diag.role) && oom_diag_token()','oom_diag_token()'),
'token_reuse':('&& !oom_diag.consumed &&','&&'),
'malformed_accepted':('return valid && got == length && !memcmp(token, expected, (size_t)length);','return true;'),
'nonce_ignored':('!memcmp(token, expected, (size_t)length)','!memcmp(token + 41, expected + 41, (size_t)length - 41)'),
}
for name,(old,new) in mutants.items():
assert original.count(old)==1,(name,original.count(old))
changed=original.replace(old,new)
if name=='after_publication':
marker='scene_tree_init(tree, parent);'
i=changed.index(marker,changed.index(marker)+len(marker))
changed=changed[:i]+changed[i:].replace(marker,'/* moved, not duplicated */',1)
(o/'scene.inc').write_text(changed)
binary=o/('mutant-'+name)
if not call(base+['-Wno-unused-variable','-o',str(binary)],name+'-compile'):ok=False;continue
case={'wrong_role':'wrongrole','malformed_accepted':'malformed','nonce_ignored':'nonce'}.get(name,'root')
label='mutant-'+name;ok=call([binary,case],label,env_for(label,case),negative=True) and ok
(o/'scene.inc').write_text(original)
result=dict(status='PASS_BOUNDED' if ok else 'FAIL',campaign='existing H1 source-corpus extension; no native runtime reservation',cases=cases,mutants=list(mutants),records=records,limits=['native compositor survival NOT_RUN','popup C callsite source binding only; no complete Sway build','damage/render use inherited reduced adapters; complete damage NOT_PROVEN'],core_limit=resource.getrlimit(resource.RLIMIT_CORE),dumpability='PR_SET_DUMPABLE0 and PR_GET_DUMPABLE0 asserted in each executable before test assertions')
(o/'result.json').write_text(json.dumps(result,indent=2)+'\n');print(result['status']);sys.exit(0 if ok else 1)

View file

@ -0,0 +1,41 @@
// Reduced current-state Sway adapters; no transactions, renderer or protocol run.
#define L_MOSAIC 99
#define SWAY_INFO 1
struct list_t {int length;void **items;};
static int list_find(struct list_t *list,void *item){for(int i=0;i<list->length;i++)if(list->items[i]==item)return i;return -1;}
struct side_gaps {int left,right,top,bottom;};
struct mosaic_row {struct {double scroll_x;}state;};
struct mosaic_workspace {struct list_t *rows;};
struct sway_workspace;
struct sway_output {struct {struct sway_workspace *active_workspace;}current;int lx,ly,width,height;};
struct sway_workspace {struct {int layout;struct list_t *tiling;struct sway_output *output;}current;struct mosaic_workspace *mosaic;struct {struct wlr_scene_tree *tiling;}layers;};
struct sway_container {struct {struct sway_workspace *workspace;struct sway_container *parent;int fullscreen_mode;}current;struct wlr_scene_tree *scene_tree;struct {int current_width,current_height;}animation_state;};
#include "transaction.inc"
static void transaction_tests(struct wlr_scene_tree *root) {
struct wlr_scene_tree *tiling=wlr_scene_tree_create(root),*popup=wlr_scene_tree_create(root);assert(tiling&&popup);
struct sway_container parent={.scene_tree=wlr_scene_tree_create(tiling)},con={.scene_tree=wlr_scene_tree_create(parent.scene_tree),.animation_state={100,100}};
con.current.parent=&parent;
void *owners[]={&parent};struct list_t ownerlist={1,owners};
struct mosaic_row row={0};void *rows[]={&row};struct list_t rowlist={1,rows};struct mosaic_workspace mosaic={&rowlist};
struct sway_workspace ws={.current={.layout=L_MOSAIC,.tiling=&ownerlist},.mosaic=&mosaic,.layers={tiling}};
struct sway_output output={.current={&ws},.width=800,.height=600};ws.current.output=&output;con.current.workspace=&ws;parent.current.workspace=&ws;
struct wlr_box area={0,0,800,600};struct side_gaps gaps={0};struct wlr_box out;
probe_workspace_clip(&ws,&area,&gaps);assert(wlr_scene_tree_get_clip(tiling,&out)&&out.width==800);
struct sway_view view={.container=&con};struct sway_popup_desc desc={.view=&view};
probe_clip_popup(&popup->node,&desc);assert(wlr_scene_tree_get_clip(popup,&out)&&out.width==800);
assert(scene_node_point_inside_clip(&popup->node,50,50));
con.scene_tree->node.x=1000;probe_clip_popup(&popup->node,&desc);assert(wlr_scene_tree_get_clip(popup,&out)&&out.width==0);assert(!scene_node_point_inside_clip(&popup->node,50,50));
con.scene_tree->node.x=0;probe_clip_popup(&popup->node,&desc);assert(wlr_scene_tree_get_clip(popup,&out)&&out.width==800);
struct wlr_scene_tree *nested=wlr_scene_tree_create(popup);assert(scene_node_point_inside_clip(&nested->node,50,50));assert(!scene_node_point_inside_clip(&nested->node,900,50));
// Non-leaf CURRENT fullscreen ancestor clears exemption, independent of ws.
parent.current.fullscreen_mode=1;probe_clip_popup(&popup->node,&desc);assert(!wlr_scene_tree_get_clip(popup,&out));parent.current.fullscreen_mode=0;
probe_clip_popup(&popup->node,&desc);assert(wlr_scene_tree_get_clip(popup,&out));
ws.current.layout=0;probe_workspace_clip(&ws,&area,&gaps);probe_clip_popup(&popup->node,&desc);assert(!wlr_scene_tree_get_clip(tiling,&out)&&!wlr_scene_tree_get_clip(popup,&out));
ws.current.layout=L_MOSAIC;
double extremes[]={NAN,INFINITY,-INFINITY,1e300,-1e300};
for(unsigned i=0;i<sizeof(extremes)/sizeof(*extremes);i++) {row.state.scroll_x=extremes[i];probe_workspace_clip(&ws,&area,&gaps);assert(wlr_scene_tree_get_clip(tiling,&out)&&out.width==0);(void)workspace_tiling_scene_x(&ws,&area,&gaps);}
row.state.scroll_x=42.9;probe_workspace_clip(&ws,&area,&gaps);assert(wlr_scene_tree_get_clip(tiling,&out)&&out.x==42);assert(workspace_tiling_scene_x(&ws,&area,&gaps)==-42);
// This helper is used by the full-source fading branch; no engine fading claim.
row.state.scroll_x=100;probe_workspace_clip(&ws,&area,&gaps);assert(wlr_scene_tree_get_clip(tiling,&out)&&out.x==100);
wlr_scene_node_destroy(&popup->node);wlr_scene_node_destroy(&tiling->node);assert(!count_clips());
}

View file

@ -0,0 +1,130 @@
{
"schema": "fullscreen-delta-independent-review-v1",
"reviewer": "fullscreen_delta_final",
"independent": true,
"decision": "ACCEPTED_SOURCE_OFFLINE_ONLY",
"review_result": "PASS",
"scope": "Unique GN-P2-1 correction: fullscreen H2 whole-field predicate, current post-fullscreen group/origin and visible-output input; prospective tests and runner only. No unrelated historical scenarios audited.",
"source_root": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-kit",
"prior_review": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-graphics-next/receipt.json",
"prior_review_sha256": "4c10510414f176c2abf7b37a0d5051ba7591b73df4be681dd878e85440e3a11f",
"prior_finding": "GN-P2-1",
"prior_finding_status": "CLOSED_SOURCE_OFFLINE_ONLY",
"source_manifest": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/ownoutputsLAB/fullscreen-field-fix/graphics-source-freeze-v2.json",
"source_manifest_sha256": "d1ef27525238c09889a2c306e744de212bea0601f4c6def551c2fafdc97110ce",
"old_source_manifest_sha256": "402d2393d07e4e423a402ff4a508c5beb61121c22723939be2d1a0fb767f5085",
"source_files": {
"README.md": "3148baa6c004d45cc151789652234cdd07fc961a166e799d0604c937ad6622fc",
"cases.py": "668230af8439e7cbe3b275a06dfd2d3f04e44cdcc133892a18e7d950fa2f0a8e",
"clients/fullscreen-client.c": "7c1a41875a5406b796c05695736e9f6d937d0fc87e8297b80fdccfdc34096605",
"clients/nested-client.c": "957f81886122256afd1dd5712185a021c08927899d3d7664041c64a366bc7438",
"clients/pointer-daemon.c": "8e4eaad95882d0d73866f801899007240b01cb6e15a712e820b3e3f71a78bbe5",
"clients/saved-client.c": "fb23512dea7b74b2ec7468a4e45d12d1a6ee83bf22f261a3d12e9c1077dda8f6",
"clients/static-reference.c": "e346a85ded3345b232cd6edca5a1ac57aebfd548a60e12b3c47a5cf515e6c50e",
"clients/vertical-client.c": "5f15adce7304839cc46150c0153a186724ea5f1f4f51b69aacf01a242a54e9db",
"engine.py": "af2e22687a58803a87d8a406f5d3f780a80194fa5c84595b2a0d98025862cece",
"evidence.py": "70c6bd58bf30c1cb8e4909aa7f2e8d71cbe4ad5ba49253ae94beff067151736a",
"freeze.py": "ff4372f3bedc41b1dae950ee58ca877ca602f24878020b443df72cd0daeece3e",
"fullscreen.py": "cc12e2636ca5facec5b05e56e0235f865c4c67b5d0714b816ca8a0363759b5a9",
"gate.py": "59d078db0701b80a453dd5971f21e5c6dd2e9f76c42d3d8865159cbd1c13c631",
"geometry.py": "76a80e98887d3a3707ee942b48a49c1850cdc4aeeb28237d9fea33fa3470fb12",
"gpu_handler.py": "78f93a9d067cd7f2f5dd40941c3deba955c1cddeb7131bc222208c3c26d4c58b",
"ipc_predicates.py": "5354ba53e1b3f8d0026f4475beebee58d093a81db7d26304cad7085ae3efd352",
"lifecycle.py": "df0c11027b3b8b0ef371ddb6ec4bcfd28dac09835644d0c3ce6e273d5e565e92",
"model.py": "a578fc589fb092dae3ccdcf8c4eec12a97e515f721decc4c968078dedcb2367a",
"offline/test_graphics_v2.py": "455d0297e2deaa14623561a0c893e6e84ea891c74decb38748ef04dbd90e598f",
"offline/test_prospective.py": "09231dfb0e91d693e062f6518b613cc9da6be7a8ecc4e60e2942d27066bc8640",
"oom.py": "7afc9bd27840bbc5b4a3c0eca96dba45d1b90d9a2975b72c897832ba06d9bb0a",
"oom_handler.py": "1ae766b759e58d8fcdc991fa64d3218d159d8a3b90825b7cba555c24aa4501a2",
"parent-provenance.json": "cd4a768a1c4cac81c4d102b7c37346060269b5d56a020c129bf79f31ec79ae80",
"pixels.py": "d315ddad978238ffbf1c8e4d712d4608ba23564703332d814f627f57f7b6e7f5",
"plans.py": "082ef1ecb16a7c4225008c030f9fa3e446837e9569dbf4fae910dab77d80c70b",
"predicates.py": "abe0c4c5b3b6d533d2714e13d317d68cd02e1f1c6180d2972ff94d00c9069cd1",
"prepare.py": "c43bf58bd8668758e101f8437470e820a94251f48536b8c73267b43904ebd21f",
"prepare_fullscreen.py": "eda437d6c4a8e3903e974ee118edcfd33de757e3afd931d35a4ce441c20cdc3d",
"protocols/wlr-virtual-pointer-unstable-v1.xml": "3ff6d540be0bc5228195bf072bde42117ea17945a5c2061add5d3cf97d6bb524",
"protocols/xdg-shell.xml": "7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df",
"run.py": "67b3a71c2ab0e8c5f5f807a3fab93b4aa08ba3d8895dd374d83ed49ded0c20b2",
"saved.py": "3838829f11f539971d0fdeeea44bf9658e9a0383aa228496d27678f06254d8a0",
"saved_validators.py": "b412fedc24869274c8b1506a2800c8d4815c93df859785c6e96f719d692014af",
"validate_offline.py": "ddbdc29fb151d7fe9b2e44e6614796aa2fbfc117b9b76aa34b2905257813fbe6",
"validators.py": "d8ae5e72ed507653e7631cda233bd6bdfd7f31a97f6d4fd6f53427437b28b054",
"wire-fixture.txt": "c6c9fc072f78fbcf9cfdeebcc5becdbdfb61824352495a0e767d7d390267f640"
},
"changed_files": [
"README.md",
"fullscreen.py",
"offline/test_prospective.py",
"validate_offline.py"
],
"source_manifest_matches": true,
"gpu_source_manifest": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/results/gpu-source-freeze-corrected.json",
"gpu_source_manifest_sha256": "38b1daba551758e0969312a1ed5fc459af877ee7d443f2135d6aa62e4831af0e",
"repair_receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/ownoutputsLAB/fullscreen-field-fix/receipt-v2.json",
"repair_receipt_sha256": "cae2f6c887a4fdcced7b49c535ea9d8805bc6f5b955b3bfc66f5b7f4dc7039b3",
"offline": {
"status": "PASS",
"count": 48,
"original": 32,
"prospective": 16,
"command": [
"/usr/bin/python",
"-B",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-kit/offline/test_prospective.py"
],
"receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-fullscreen-delta/offline-validation.json",
"receipt_sha256": "ec60608a4cbec0fec487e7cef5a1c5c41afadc99c049c4fa01eff84ed7c38d2a",
"scratch": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-fullscreen-delta/OFFLINE_TEST_ONLY",
"note": "Direct unchanged test_prospective.py invocation with corrected GPU manifest; original V2 tests imported and executed. Mechanical real Python child/watchdog tests only, no native client or compositor."
},
"independent_checks": {
"status": "PASS",
"count": 11,
"receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-fullscreen-delta/independent-checks.json",
"receipt_sha256": "74882a7c5feb501309d80548467a55c567f1f6832826519fd08f6192b5ce73f4"
},
"reviewed_symbols": [
"fullscreen.fullscreen_h2_field",
"fullscreen.group_candidate",
"fullscreen.fresh_geometry",
"fullscreen.input_target",
"fullscreen.run",
"offline/test_prospective.py fullscreen direct negatives and quotas",
"validate_offline.validate"
],
"evidence": [
"H2 full RGB field is baseline plus measured global A then nested B, clipped to half-open H2 output bounds; exact zero-tolerance RGB comparison.",
"Integer popup coordinates derive from predicates.configured integer parsing; nested B coordinates are relative to A, checked explicitly by fullscreen_h2_field.",
"Original two-pixel-only image is rejected by actual new predicate, plus independently rendered missing/excess/stack/stale-geometry negatives.",
"C8 rereads current owner/workspace origin and two-child group after fullscreen disable plus splith; fullscreen_mode=0, preserved group identity, current output rect and equal child widths are checked before recomputing geometry.",
"Input iterates both outputs and checks solid interior inside current popup rectangle; direct H1 and H2-only positives pass.",
"After close B, actual handler recomputes geometry, rejects B residual across both images, validates complete A-only H2 field and selects visible A input; final H2 remains exact baseline.",
"Capture/action quota tests remain P1=10 and C8=12; field checks reuse existing captures."
],
"findings": [],
"out_of_scope_observations": [],
"per_case_source_offline_admissibility": {
"P1": "ACCEPTED_SOURCE_OFFLINE_ONLY",
"C8": "ACCEPTED_SOURCE_OFFLINE_ONLY"
},
"runtime_authorized": false,
"authorized_runs": [],
"runtime": "NOT_RUN",
"native_build": "NOT_RUN",
"client_execution": "NOT_RUN",
"native_capture": "NOT_RUN",
"GPU_execution": "NOT_RUN",
"actual_GL_observability": "NOT_TESTED",
"new_reservations": 0,
"new_native_captures": 0,
"new_client_executions": 0,
"source_edits": false,
"git_commands": "NOT_RUN",
"committed": false,
"pushed": false,
"limitations": [
"No native graphical execution or current/applied transaction-generation proof.",
"Acceptance only closes GN-P2-1 at source/offline level; publication, exact binary bindings and explicit per-case admission remain prerequisites for runtime."
],
"next_smallest_step": "Use this final source manifest and independent receipt for the parent source-only decision; no runtime authorization is conferred."
}

View file

@ -0,0 +1,80 @@
{
"schema": "independent-R-D5-GPU-built-bytes-bounded-v1",
"decision": "BOUNDED_ACCEPTED",
"decision_scope": "Exact current candidate built ELF, static archive, strict feature macro configuration, pinned provider binding and DESTDIR manifest only",
"source_freeze_sha256": "38b1daba551758e0969312a1ed5fc459af877ee7d443f2135d6aa62e4831af0e",
"source_review_sha256": "247fa681a20433a36eb8ba6a6545c6c784f6e8d1cf168345fcabb867a86737c4",
"build_final_receipt_sha256": "45416fbb0102d2992f2cad274785f6ce4c13ed1c836de555513a40a338dbb0c9",
"config_notes_sha256": "e37d231b32bdd1ca89b6d4e5942621d18dda6352abe8879ff770441d9cb6c557",
"binary": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/builds/gpu-mosaic/sway/swayfx-mosaic",
"binary_sha256": "b2ba890908e385b0a8884e786b279bfb2e582eed38c7fcd0587b418326eca5bc",
"build_id": "b6a52111beabe3c2122e0142a802415d3c84f9a5",
"archive": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/builds/gpu-scene/libscenefx-0.5.a",
"archive_sha256": "06ccfad8c7dfe4ee425b8de44d22d8daa69e2daa14085d6e6998b201a7ad111b",
"wlroots_sha256": "7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837",
"source_and_stage_checks": "PASS; see source-stage-checks.json",
"build_history": "Initial SceneFX compile failure realpath implicit declaration preserved with exact log hash; CONFIG_ONLY _XOPEN_SOURCE=700 exposes proper declaration, retains -Werror and type diagnostics; successful strict build logs verified",
"scene_actual_standard": "c23 upstream build setting; accepted C17 source syntax checks preserved, no source language relaxation introduced",
"elf": "PASS_ELF64_X86_64; no SceneFX DT_NEEDED/RPATH/RUNPATH; G2 helpers LOCAL; private clip APIs not dynamic exports; no new dynamic exports versus accepted CORE binary",
"provider_binding": "PASS_LOADER_TRACE_ONLY: wlroots wlr_scene_tree_create binds executable SceneFX definition; LD_TRACE_LOADED_OBJECTS=1 LD_BIND_NOW=1 LD_WARN=1 LD_DEBUG=bindings; no init/main transfer or unresolved symbols",
"built_g2_begin_evidence": "openat flags immediate 0xa0800 includes O_NONBLOCK; fstat/geteuid before read then linkat; confirms corrected function linked",
"native_hook_callsite_evidence": "g2_begin before get_main_buffer_blur; g2_uniform before render; per-down/up samples after render_blur_segments; optimized-cache/no-blur samples after copy; composition sample before submit and output-forget; g2_sample_native calls local g2_read",
"model_test": "PASS_REPORTED_LOG_VERIFIED: 1 passed, 0 failed; not rerun",
"direct_negatives": "5 PASS_REJECTED: false binary hash, wrong wlroots hash, dynamic object as archive, stale source, old LAB candidate path",
"G2_client": "Prior accepted corrected targeted test command9 C17 -fsyntax-only PASS; no new client build or execution; no separate G2 client ELF qualified here",
"legal_status": "LEGAL_NOT_APPROVED",
"new_builds": 0,
"new_reservations": 0,
"native_runs": 0,
"GL_runs": 0,
"client_runs": 0,
"IPC_calls": 0,
"git_operations": 0,
"actual_native_GL_context": "NOT_RUN",
"actual_readbacks": "NOT_RUN",
"actual_gl_observability": "NOT_PROVEN",
"native_present_buffer": "NOT_PROVEN",
"gpu_completion": "NOT_PROVEN",
"whole_field_causality": "NOT_PROVEN",
"runtime_authorization_granted": false,
"candidate_blocking_findings": [],
"portable_publication_verdict": "CORRECTION_REQUIRED_BEFORE_PORTABLE_PUBLICATION",
"portable_publication_findings": [
{
"severity": "P2",
"file": "gpu-kit/reproduce.py:10,16,17,20; gpu-kit/test-targeted.py:4,7",
"symbol": "ROOT / main / offline CLI inputs",
"violated_requirement": "Future exact copied Git kit must reproduce corrected GPU source from reconstructed CORE in a new disposable directory without old LAB payload or logs",
"evidence": "reproduce.py fixes ROOT to this LAB, reads corrected freeze at results/gpu-source-freeze-corrected.json outside KIT, compares old sources/scene-core and sources/scene-gpu and requires gpu-fifo-fix/work; test-targeted.py requires old builds/core-scene/compile_commands.json. No destination CLI is provided. README still names original non-corrected evidence. A new CORE reconstruction is never selected by these commands.",
"smallest_correction_direction": "Before publishing portable CLI, parameterize parent/target/work/destination and ship a self-contained expected source manifest or derive target by applying the preserved patch to explicit reconstructed CORE; regenerate only declared build prerequisites and keep output dirs independent. Declare candidate-bound native G2_ROOT separately with new source SHA if derived. Do not silently reuse old LAB."
}
],
"masked_response_content_accessed": false,
"edits": "Own review artifacts only; no source, Git, budget, reservation or build output modified",
"evidence_sha256": {
"header.txt": "c265f88956c8637488d8304bbc49280f00eca43d6dfc47db1b732944058674c4",
"notes.txt": "5229e622edb0e7f8727498b0ceca330102ef33b7ba9a60d9681c151fd55eedd2",
"dynamic.txt": "6786cc65b9e019e92e3897d6a6e98592620218c6a845ef37736642f4046489c9",
"symbols.txt": "bd384ac7d5eb56de15907c2725b16553cadc1a4172548d4724187e02159d317c",
"dynsymbols.txt": "d99ee255963207342e112a542a0ca7cd65afe95f3d1291c15d1626fadf58be46",
"archive.txt": "f50a0a28adbba3ea0e7da6d620ee4984067cafc6b7156bc1c68d38b5b44c73cf",
"wlroots-symbols.txt": "729e5b57302da74d90adb1da7cd092b68d0abd69761c6bf2cea2df57f9ccbe61",
"g2_begin.txt": "6a40c408db150842d969a817d52641aa18a2fbc1d7d04f809dd59c2eed9f5125",
"g2_read.txt": "bb05316a3b29633949590433b2d9247c0e0d203024453bd332bd81f2c11f18ab",
"render.txt": "1ab02ed4a06fa4204a39ae1facb47dbe5b766cb0feff29717154ec91af3541e5",
"wlr_factory.txt": "d97e5e4594ee9c4add61684e85a5136d3238bfeb17bb22219d34e7e9e187b334",
"loader-trace.txt": "66f9f8bbb245009fdce4392e06fb0c0cb06ed7922984a937e6daba572a5a6f64",
"commands.json": "8df56b99c9c2eff8c79be580aee4dabb1b99471f75c98925ec93b84841b67d35",
"source-stage-checks.json": "b14158ecbd4df29e1bca50233694897ac47cc1e2090f2648b0cf71b432ceb1f5",
"render_blur_segments.txt": "3c3ca74ab657e72e0226cc734b3024f8d4c0ef8711ff9cef497f476c405837e7",
"get_main_buffer_blur.txt": "f038063eb139028856c1f4a962e9e8f10446073575b97bed8b0c552765b6e7e7",
"render_pass_submit.txt": "3574bfec82151df21795a05a38fadc1fa32d100446c221f89f748958c0a05f29",
"g2_sample_native.txt": "e730ed383b15c8eb71843c8b905a2c79b94d7014134c5ceb864a837f2ee7247c",
"validate-bound-bytes.py": "52f8c890892e0fad48c072007b00d5ae3636ed963e61ae69c2a715234bfef901",
"stale-native.NOT-BUILD-INPUT.h": "459df66f7baddfd2fe502eba5eeaf185c906e8335b24d4b46b68eb0eefdcc6d2",
"direct-negatives.json": "3502c8e78a866c0496517e3cd369a629a155410522bf9f12a4baadfd3469c661",
"binding-summary.json": "95c33555f938a82db2459662978e7bfd223dc9438c5ce918a352c93d11cb56a1",
"core-dynsymbols.txt": "8945601cac3d7135f1c07855574530165c869b18016f44348159b35a3a856833",
"dynamic-export-delta.json": "fa6d95b2d4889813795c9623b1eb719a5c1aed0392bf717f8bba271976832e04"
}
}

View file

@ -0,0 +1,60 @@
{
"schema": "independent-R-GPU-FIFO-delta-source-review-v1",
"decision": "ACCEPTED",
"scope": "Only FIFO g2_begin correction and directly associated patch/freeze/tests; no broad re-audit",
"inputs_sha256": {
"results/gpu-source-freeze.json": "209c97a910523087a99eb5a303e0c57019542fadaffc8bca9386d79563960de3",
"results/gpu-source-freeze-corrected.json": "38b1daba551758e0969312a1ed5fc459af877ee7d443f2135d6aa62e4831af0e",
"ownreview-gpu-oom-build/gpu-source-review-receipt.json": "db76b1139b00b881dfe0b59f5d6039c430bf16e5800482d68580aaa15c92effa",
"ownreview-gpu-oom-build/gpu-fifo-negative.json": "e0a74d476c496ff1798b4c0d303b34e33b892a9b3396c431249107207a874c2e"
},
"corrected_native_sha256": "0dfa9e089853a078094736da7f4e133d7fd648500d380dd7f536a7a6f80fdd8e",
"corrected_patch_sha256": "77d7445ceaf643fd5cc708d31c3f2c77feaeb80f8130c419c55e5514ecc8a75d",
"freeze_files_verified": 22,
"old_freeze_changed_paths": [
"gpu-kit/freeze.py",
"gpu-kit/g2-native.patch",
"gpu-kit/g2_native.h",
"gpu-kit/reproduce.py",
"gpu-kit/test-targeted.py",
"gpu-kit/test_protocol.py",
"sources/scene-gpu/render/fx_renderer/g2_native.h"
],
"native_delta": "Only g2_begin: O_NONBLOCK; fstat regular/UID/mode/nlink/exact framing size before read; unchanged nonce comparison and consume sequence",
"native_copies_identical": true,
"parent_and_mosaic_unchanged": true,
"shaders_python_protocol_scenario_unchanged": true,
"test_protocol_delta": "BASE output directory only; protocol.py and scenario.py byte-identical to original freeze",
"fifo_test": "PASS exact extracted production function; writerless FIFO0600 rejected, arm retained and consumed absent, alarm not reached",
"targeted_test_commands": 10,
"FakeGL_paths": 18,
"targeted_tests": "PASS",
"source_patch_reproduction": "PASS_EXACT_PARENT_AND_TARGET",
"gl_observability_capability": "PASS_FOR_INTENDED_GLES3_RBO_SCOPE",
"actual_gl_runtime": "NOT_RUN",
"actual_gl_observability": "NOT_PROVEN",
"metadata_offline": "PASS_CONTROLLED_ONLY",
"whole_field_causality": "NOT_PROVEN",
"native_present_buffer": "NOT_PROVEN",
"gpu_completion": "NOT_PROVEN",
"pair3_build": "NOT_RUN",
"G2": "NOT_RUN; other gates and parent final binding required",
"runtime_authorization_granted": false,
"runtime_launches": 0,
"new_gpu_acquisitions": 0,
"blocking_findings": [],
"memory_redirects": "test_fifo WORK, test-targeted WORK/receipt and child test_protocol BASE, reproduce temporary destination/receipt redirected in memory only to this review directory; no script source edited",
"masked_response_content_accessed": false,
"git_diff_check": "PASS",
"git_status": "## main...origin/main\n",
"code_edits": false,
"committed_pushed": false,
"evidence": {
"test_fifo.py.log": "2cee3f97bf93e4ec6982d919682887b217859a146ee0dacd89b50fa9ada99a9c",
"targeted-tests.json": "6bb03b42bec3cc7b69cd0e30a1dd7e076841cf0df31448e60fbf58c907bff73e",
"test-targeted.py.log": "17b223fa8fc494dfb4e151783f04ce0c2493d8bc1f93fb975a87210e98f1fa2b",
"patch-reproduction.json": "bb82b0f4c732cf0ac8e9af6e5a2574f230b5eb18e78d1c1b1fc3cfa0137e4a8b",
"reproduce.py.log": "bb82b0f4c732cf0ac8e9af6e5a2574f230b5eb18e78d1c1b1fc3cfa0137e4a8b",
"runs.json": "01a35ba5bf7039f81c42cffd37cb3f298867ab7266d26786d4194464d9de5ecd"
}
}

View file

@ -0,0 +1,149 @@
{
"schema": "independent-G2-portable-clientbuild-bounded-review-v1",
"decision": "PASS",
"portability_decision": "PASS_BOUNDED_P2_CORRECTED",
"clientbuild_decision": "PASS_EXACT_ELF_REGENERATED_OFFLINE",
"scope": "Portable CLI delta README/reproduce/test-targeted and exact standalone G2 client build only; no new compositor build or runtime qualification",
"prior_separate_finding_receipt": {
"path": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/ownreview-gpu-built/receipt.json",
"sha256": "00e78a136ea39a873adbee07653969f7265607c91d5dec5226f9708a14cc0aec",
"resolved_finding": "P2 portable-publication CLI inputs and outside-LAB dependencies"
},
"source_freeze_sha256": "38b1daba551758e0969312a1ed5fc459af877ee7d443f2135d6aa62e4831af0e",
"publication_manifest_sha256": "891e4aae2c23dadf3a79c185af73d0cd86a1daff6e880e0fa6f277a7b5c79011",
"publication_receipt_sha256": "0969c3b620063ef32abbd2a4206997ab8d8df779e74efc39bfc5573418e9825f",
"kit_review_copy": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/kit",
"only_changed_files": [
"README.md",
"reproduce.py",
"test-targeted.py"
],
"immutable_files_manifest_verified": true,
"core_explicit": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/reassembled-final/scene",
"core_tree_sha256": "e7d3fb7b4b76fcf1f9692981759e8070915c2072415a060351c4ff580c42eba1",
"target_tree_sha256": "324b546ca85378cc48c4fe323d0e2f8e5e43687c6226de4267386adff5ff008f",
"entire_target_matches_frozen_tree": true,
"parent_unchanged": true,
"fresh_reproduction": {
"exit": 0,
"argv": [
"python",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/kit/reproduce.py",
"--core",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/reassembled-final/scene",
"--destination",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/scene-gpu",
"--work",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/work"
],
"log": "positive.log"
},
"negative_tests": {
"wrong_parent": {
"exit": 1,
"argv": [
"python",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/kit/reproduce.py",
"--core",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/wrong-parent",
"--destination",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/wrong-result",
"--work",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/work"
],
"log": "wrong-parent.log"
},
"existing_destination": {
"exit": 2,
"argv": [
"python",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/kit/reproduce.py",
"--core",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/reassembled-final/scene",
"--destination",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/scene-gpu",
"--work",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/work"
],
"log": "existing-destination.log"
},
"corrupt_patch": {
"exit": 2,
"argv": [
"python",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/corrupt-kit/reproduce.py",
"--core",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/reassembled-final/scene",
"--destination",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/corrupt-result",
"--work",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/work"
],
"log": "corrupt-patch.log"
}
},
"independent_targeted_tests": {
"result": "10_COMMANDS_PASS",
"receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/targeted/gpu-targeted-tests.json",
"sha256": "2bd54eee3366af1f8111c45f98aa2c197b1585b2e935ed1145d61f640d2fe3ab",
"source_syntax_checked": "private reconstructed GPU fx_pass.c",
"compile_commands": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-gpu-portable/compile_commands.json",
"prerequisites": "Explicit private source/include and empty private syntax-prerequisites plus installed system headers; no old LAB source/include/build or ccache prerequisite",
"readme_CORE_invocation": "ALSO_PASS; checks CORE fx_pass syntax. GPU invocation separately checks actual patched fx_pass."
},
"client": {
"receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/client-compile.json",
"receipt_sha256": "ecd564f648a1ad3709ee54801a718733fc8572e73ab5d393ca334681ac10c047",
"binary": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/gpu-work/client-build/g2-client",
"sha256": "45b98828e84b94954b4382a3ec1a72d92624667e74534463c133eb3118a689f8",
"expected_sha256": "45b98828e84b94954b4382a3ec1a72d92624667e74534463c133eb3118a689f8",
"original_input_and_generated_hashes": "PASS_ALL",
"independently_regenerated_headers_protocol_code_and_ELF": "PASS_BYTE_IDENTICAL_ALL",
"compiler": "cc -std=c17 -O2 -Wall -Wextra -Werror -Wno-unused-parameter",
"elf": "ELF64 little-endian x86-64 PIE; NEEDED libwayland-client.so.0 libm.so.6 libc.so.6; no RPATH/RUNPATH",
"executed": false
},
"contract_boundary": "CORE is an explicitly reconstructed and verified prerequisite. Helper verifies changed files only; this review additionally compared complete CORE/target tree identities to frozen manifest. No new requirement to duplicate CORE verification in every helper. Native G2_ROOT remains intentionally bound to accepted diagnostic identity. freeze.py remains historical, not a reproduction prerequisite. test_protocol BASE explicitly overridden into private work by runner.",
"findings": [],
"source_edits": 0,
"new_compositor_builds": 0,
"build_pair_changes": 0,
"budget_changes": 0,
"stage_changes": 0,
"native_runs": 0,
"GL_runs": 0,
"client_runs": 0,
"IPC_calls": 0,
"git_mutations": 0,
"masked_content_accessed": false,
"runtime_authorization_granted": false,
"preflight_is_observed_GL": false,
"actual_native_GL_context": "NOT_RUN",
"actual_readbacks": "NOT_RUN",
"actual_gl_observability": "NOT_PROVEN",
"native_present_buffer": "NOT_PROVEN",
"gpu_completion": "NOT_PROVEN",
"whole_field_causality": "NOT_PROVEN",
"legal_status": "LEGAL_NOT_APPROVED",
"next_smallest_step": "Parent may bind this independent bounded result to its explicit CORE reconstruction/verify and complete-target comparison before source-only publication; no runtime authority follows.",
"evidence_sha256": {
"client-checks.json": "b0d45a2829444f152ca4b47876cbd0e1dc08005dc1c51810b88bef85880c1f2a",
"client-command-0.log": "daeb877303c6117ce9622ed510740569c724d685d27e3401d358afb0ab932236",
"client-command-1.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"client-command-2.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"client-command-3.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"client-command-4.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"client-command-5.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"client-elf-dynamic.log": "9fa3ae153ebaf2e1e90a68d3eb4cecbc31e2cceec3ce4080d5ceb8c815beecc8",
"client-elf-header.log": "e80af45dc2349924dc7d33535d43b595b4798c5aacfea98f13fa3a7597564dd0",
"compile_commands.json": "d143056cc46ba6414a1fed0dfc001da1ea838589ca497ab133ea55f617575bbe",
"corrupt-patch.log": "eac777d04b90374ea285b12d3c7adea0b0ee807faea3738e5be3cb268fd94eee",
"existing-destination.log": "287be885a888cefc2379fec937a2a24b61b325faaa0949c82469cf92db58ce0c",
"positive.log": "be31b47cc2ac70adbc85d33944150ec588705ed2f64c2e8ff5a2028370060317",
"preliminary.json": "5e6298bc09ad4e973ca24ec0d1f09de408efb31c76708eedb346c5e5af67b749",
"targeted-readme.log": "17b223fa8fc494dfb4e151783f04ce0c2493d8bc1f93fb975a87210e98f1fa2b",
"targeted.log": "17b223fa8fc494dfb4e151783f04ce0c2493d8bc1f93fb975a87210e98f1fa2b",
"wrong-parent.log": "54f298bb3fbe4b2f911500b264aa1f54bdd6000794321a903d6d32811f5693a1"
},
"per_case_runtime_admission": "NOT_GRANTED; separate independent admission required after publication/freeze for each distinct prospective case"
}

View file

@ -0,0 +1,147 @@
{
"schema": "graphics-next-independent-source-review-v1",
"decision": "CORRECTION_REQUIRED",
"reviewer": "resume_graphics_next_review",
"independent": true,
"scope": "Exactly new graphics-next-kit source delta (16 new/changed files), prospective P1/C8/O1/O2/G2 wiring and immutable source/client bindings; no production or broad architecture review",
"source_root": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-kit",
"source_manifest": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-work/graphics-source-freeze.json",
"source_manifest_sha256": "402d2393d07e4e423a402ff4a508c5beb61121c22723939be2d1a0fb767f5085",
"source_files": {
"README.md": "c0d3722e993a6268998c70da34116095bfa5a0378ee38555191ec97825486b72",
"cases.py": "668230af8439e7cbe3b275a06dfd2d3f04e44cdcc133892a18e7d950fa2f0a8e",
"clients/fullscreen-client.c": "7c1a41875a5406b796c05695736e9f6d937d0fc87e8297b80fdccfdc34096605",
"clients/nested-client.c": "957f81886122256afd1dd5712185a021c08927899d3d7664041c64a366bc7438",
"clients/pointer-daemon.c": "8e4eaad95882d0d73866f801899007240b01cb6e15a712e820b3e3f71a78bbe5",
"clients/saved-client.c": "fb23512dea7b74b2ec7468a4e45d12d1a6ee83bf22f261a3d12e9c1077dda8f6",
"clients/static-reference.c": "e346a85ded3345b232cd6edca5a1ac57aebfd548a60e12b3c47a5cf515e6c50e",
"clients/vertical-client.c": "5f15adce7304839cc46150c0153a186724ea5f1f4f51b69aacf01a242a54e9db",
"engine.py": "af2e22687a58803a87d8a406f5d3f780a80194fa5c84595b2a0d98025862cece",
"evidence.py": "70c6bd58bf30c1cb8e4909aa7f2e8d71cbe4ad5ba49253ae94beff067151736a",
"freeze.py": "ff4372f3bedc41b1dae950ee58ca877ca602f24878020b443df72cd0daeece3e",
"fullscreen.py": "e8853fe436a489794ec82d623bc4515684625352f4afe4bdc12060114fc84b43",
"gate.py": "59d078db0701b80a453dd5971f21e5c6dd2e9f76c42d3d8865159cbd1c13c631",
"geometry.py": "76a80e98887d3a3707ee942b48a49c1850cdc4aeeb28237d9fea33fa3470fb12",
"gpu_handler.py": "78f93a9d067cd7f2f5dd40941c3deba955c1cddeb7131bc222208c3c26d4c58b",
"ipc_predicates.py": "5354ba53e1b3f8d0026f4475beebee58d093a81db7d26304cad7085ae3efd352",
"lifecycle.py": "df0c11027b3b8b0ef371ddb6ec4bcfd28dac09835644d0c3ce6e273d5e565e92",
"model.py": "a578fc589fb092dae3ccdcf8c4eec12a97e515f721decc4c968078dedcb2367a",
"offline/test_graphics_v2.py": "455d0297e2deaa14623561a0c893e6e84ea891c74decb38748ef04dbd90e598f",
"offline/test_prospective.py": "d377e5a4800fdeafe35491ab572e5c38cc56ddf602d1e69897b370fa7ff2b5c5",
"oom.py": "7afc9bd27840bbc5b4a3c0eca96dba45d1b90d9a2975b72c897832ba06d9bb0a",
"oom_handler.py": "1ae766b759e58d8fcdc991fa64d3218d159d8a3b90825b7cba555c24aa4501a2",
"parent-provenance.json": "cd4a768a1c4cac81c4d102b7c37346060269b5d56a020c129bf79f31ec79ae80",
"pixels.py": "d315ddad978238ffbf1c8e4d712d4608ba23564703332d814f627f57f7b6e7f5",
"plans.py": "082ef1ecb16a7c4225008c030f9fa3e446837e9569dbf4fae910dab77d80c70b",
"predicates.py": "abe0c4c5b3b6d533d2714e13d317d68cd02e1f1c6180d2972ff94d00c9069cd1",
"prepare.py": "c43bf58bd8668758e101f8437470e820a94251f48536b8c73267b43904ebd21f",
"prepare_fullscreen.py": "eda437d6c4a8e3903e974ee118edcfd33de757e3afd931d35a4ce441c20cdc3d",
"protocols/wlr-virtual-pointer-unstable-v1.xml": "3ff6d540be0bc5228195bf072bde42117ea17945a5c2061add5d3cf97d6bb524",
"protocols/xdg-shell.xml": "7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df",
"run.py": "67b3a71c2ab0e8c5f5f807a3fab93b4aa08ba3d8895dd374d83ed49ded0c20b2",
"saved.py": "3838829f11f539971d0fdeeea44bf9658e9a0383aa228496d27678f06254d8a0",
"saved_validators.py": "b412fedc24869274c8b1506a2800c8d4815c93df859785c6e96f719d692014af",
"validate_offline.py": "b552a74ef5c346ccd2c24fd3bf6134ca171c63e2b5f7604cc029e544985a1cf7",
"validators.py": "d8ae5e72ed507653e7631cda233bd6bdfd7f31a97f6d4fd6f53427437b28b054",
"wire-fixture.txt": "c6c9fc072f78fbcf9cfdeebcc5becdbdfb61824352495a0e767d7d390267f640"
},
"handoff_sha256": "4a238b15af8f11ad8602550663a3ae0786a906d3139d71ae72416702e6029780",
"gpu_source_manifest": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/results/gpu-source-freeze-corrected.json",
"gpu_source_manifest_sha256": "38b1daba551758e0969312a1ed5fc459af877ee7d443f2135d6aa62e4831af0e",
"external_bindings": {
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-oom-runtime/oom-source-receipt.json": "a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c",
"/var/tmp/swayfx-mosaic-corec-v2-i516p6po/ownreview-gpu-oom-build/oom-built-bytes-receipt.json": "1e5fb11882dcdc1a2cf916f3d6c4d47a8959b59169262ff9470c4b5a9009154a"
},
"client_build_review": {
"binary": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-work/client-build/fullscreen-client",
"sha256": "82fc218f15f2405cca0f2290cc41bbbc6dfead18c641f796f8fcd4012a16af70",
"compile_receipt_sha256": "00c97bec3f87077f7edb6fd5e0d0e7ced7ed6c4c1ac76c9d8456647eb59ee793",
"c17": true,
"generated_exact": true,
"library": "/usr/lib/libwayland-client.so.0.26.0",
"library_sha256": "39c83ae7b73d22f18b4f81da14749c4535c304b7e62910a2f1aae682f279cc9d",
"wayland_imports": [
"wl_display_connect",
"wl_display_disconnect",
"wl_display_dispatch",
"wl_display_flush",
"wl_display_get_error",
"wl_display_get_fd",
"wl_display_roundtrip",
"wl_output_interface",
"wl_proxy_add_listener",
"wl_proxy_get_id",
"wl_proxy_get_version",
"wl_proxy_marshal_flags"
],
"missing_imports": [],
"execution": "NOT_RUN",
"verification_note": "Initial stdout regeneration uses different header guard; corrected regeneration uses identical output basenames under reviewer directory and is byte-exact."
},
"offline": {
"status": "PASS",
"count": 46,
"source_manifest_sha256": "402d2393d07e4e423a402ff4a508c5beb61121c22723939be2d1a0fb767f5085",
"receipt": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-graphics-next/offline-validation.json",
"receipt_sha256": "1f451302e027843ef6fe5b1d6f437e3b5646438bb1554cbe1661dfad76a2c0a0",
"method": "Imported original validate_offline.py. In-memory ReviewPath overrides LAB/graphics-next-work only; clean_environment wrapper redirects reviewer temp/cache. Original test_prospective.py executed unmodified with --gpu-source-manifest equivalent explicit argument supplied to validate().validate.",
"coverage": "32 original direct regression tests + 14 prospective direct tests, actual handlers/fake I/O, fullscreen ancestor/leaf/noncrossing/mismatch, OOM PID/nonce/roles/counts/error/closure/token, GPU manifest binding/caps/first A stop, publication/budget/watchdog"
},
"findings": [
{
"id": "GN-P2-1",
"severity": "P2",
"file": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/graphics-next-kit/fullscreen.py",
"symbol": "run",
"lines": [
58,
68
],
"violated_requirement": "FULLSCREEN_PROSPECTIVE_EXTENSION.md: wholeH2expectedspill; inputs/ticket.md E4: count expected regions and verify whole-output H2 for standard overflow",
"evidence": "The new fullscreen branch only calls validators.standard_spill. That predicate accepts any H2 image containing at least one pixel each of A and B. Direct falsification accepted two pixels at H2 (799,599)/(798,599), outside configured A[-448,105,900,170]/B[-348,165,900,130]; all other H2 pixels reference background. H1 geometry/input and P1/C8 role/configuration equality do not reject this wrong H2 field.",
"falsification": "/var/tmp/swayfx-mosaic-corec-v2-i516p6po/review-graphics-next/fullscreen-spill-falsification.json",
"smallest_correction": "Add a fullscreen-specific expected H2 field/regions check based on the measured configured global A/B rectangles and stack order, using the existing capture pairs. Reject missing, misplaced, excess and stale A/B pixels; preserve zero tolerance and no added captures. Add direct negative tests against this actual new check. Do not broaden changes to historical scenarios."
}
],
"per_case_source_offline_admissibility": {
"P1": "CORRECTION_REQUIRED: GN-P2-1",
"C8": "CORRECTION_REQUIRED: GN-P2-1",
"O1": "ACCEPTED_SOURCE_OFFLINE_ONLY",
"O2": "ACCEPTED_SOURCE_OFFLINE_ONLY; actual successful O1 dependency remains mandatory",
"G2": "ADAPTER_ACCEPTED_SOURCE_OFFLINE_ONLY; independent GPU source and capability preflight plus exact pair3 build review still required",
"R1": "NOT_ADMITTED; no override"
},
"runtime_authorized": false,
"authorized_runs": [],
"runtime": "NOT_RUN",
"native_gl_status": "NOT_RUN",
"actual_GL_observability": "NOT_TESTED",
"new_reservations": 0,
"new_native_captures": 0,
"new_client_executions": 0,
"old_budget": {
"sha256": "8ce8a4134ff841dd0a60e2b108cd8dd688ff891f0867facb377bd0013263d839",
"unchanged": true
},
"limits": {
"runs": 14,
"capture_cap_sum": 170,
"captures_global": 180,
"seconds_per_run": 150
},
"source_edits": false,
"committed": false,
"pushed": false,
"verification_notes": [
"46 tests PASS does not discharge the directly falsified fullscreen field requirement.",
"Readelf, pkg-config, wayland-scanner source regeneration only; no new build or client execution.",
"First header regeneration assertion failed because stdout changes header guard; corrected identical output basenames produced byte-identical generated header/C.",
"Initial pwd/ls discovery commands did not use run-env; every subsequent command used run-env. No session environment or masked transcript content was accessed."
],
"review_artifacts": {
"offline-validation.json": "1f451302e027843ef6fe5b1d6f437e3b5646438bb1554cbe1661dfad76a2c0a0",
"hash-abi-audit.json": "51ce192b64e66406c8209ffcdd9ce34e22ed8eed205171485c08df4f9113461a",
"fullscreen-spill-falsification.json": "adbcdc65e21205adf40859353b88b36dc930f024adc6383bb3d05cb8946e0c0b"
},
"next_smallest_step": "One bounded fullscreen-only correction with direct field/region negatives, then freeze and independent delta re-review; source publication and per-case actual binary freeze remain prerequisites for any run."
}

View file

@ -0,0 +1,23 @@
{
"status": "PASS_BOUNDED_BUILT_BYTES",
"source_files_verified": 503,
"binary_sha256": "6067946bd79ad6fd8da7669ab9b0b3bacfd2638f5d3d8382002b9118db20d835",
"archive_sha256": "bca4b749eadc551f78712d7e1e7bda769125d2e596524a582988ca5346f8eceb",
"build_id": "9bc3dc9055106b343c80a51ded111a382e98442d",
"wlroots_sha256": "7edca9a7d65855addda68e29ba5db94d57c803eb5fa7d0f86db3136b90ca9837",
"source_freeze_sha256": "b471b0029bdb0ce4398660988cb0855eecad99a859ce9224c6c0cdea872a8f02",
"source_review_sha256": "a953a38b49bea11e9c19e84ed2d8218a16b2e5d980e0ba57677eeee0ddf62c6c",
"negative_controls": {
"false_hash": "PASS rejected binary hash",
"wrong_wlroots": "PASS rejected wlroots hash",
"dynamic_archive": "PASS rejected archive hash",
"stale_source": "PASS rejected stale source",
"old_LAB": "PASS rejected old LAB"
},
"stage": "5 exact regular files; 0755/0644; pinned original notices",
"legal": "LEGAL_NOT_APPROVED",
"runtime": "NOT_RUN_BY_REVIEWER",
"O1": "NOT_ADMITTED_NOT_RUN",
"O2": "NOT_ADMITTED_NOT_RUN",
"blocking_findings": []
}

View file

@ -0,0 +1,40 @@
{
"schema": "corec-v2-independent-R-OOM-source",
"decision": "PASS_BOUNDED_SOURCE_ONLY",
"blocking_findings": [],
"freeze_sha256": "b471b0029bdb0ce4398660988cb0855eecad99a859ce9224c6c0cdea872a8f02",
"source_files_verified": 16,
"source_digest": "bf53e28e6e71c2029e80f4ec616cfec9f09081121dae0b29205143a37a74e1f2",
"parent_review_sha256": "26aa862c741196fdbb8d7cdf5509301e49f763cdd22ffa7bcb1a4bbf09c66f90",
"assembly_sha256": "a7f3cf3d706edee3375ce77239c97a31dfa4d79a7228b2d00931093951eab315",
"c_result_sha256": "250f6465c1132ea0cef90bb16dc368df235d95ed04eaf80975db5fb544330d23",
"positive_runs": 27,
"mutants_compiled": 6,
"mutants_direct_SIGABRT": 6,
"direct_negatives_sha256": "6d3293f0c81e50065be82a1e93c32476d52cc1c35ef93434212cef874abf5f4e",
"direct_negative_cases": 9,
"source_evidence": [
"Only primary popup_create factory call scoped; parent role uses native try_from_wlr_surface",
"Actual sidecar calloc replaced before scene_tree_init; tree calloc ordinary; NULL cleanup unchanged",
"Constructor snapshots env; one-shot consumed; O_NOFOLLOW/O_NONBLOCK regular UID0600 single-link bounded exact token",
"No installed header/public struct changes; adapters do not establish native survival"
],
"gates": {
"pair_2_source": "ACCEPTED_FOR_SEPARATE_BUILD_REVIEW",
"native_preflight": "NOT_PROVEN",
"O1": "NOT_ADMITTED_NOT_RUN",
"O2": "NOT_ADMITTED_NOT_RUN",
"availability_policy": "UNDECIDED",
"production": false
},
"reviewer_native_runs": 0,
"source_edits": false,
"limitations": [
"Syntax-only native wlroots callsite; reduced lifecycle adapters; complete compositor build NOT_RUN",
"Final settled graphics handler/admission not implemented by this adapter",
"Native sidecar/listener stale lifetime, complete damage NOT_PROVEN"
],
"review_execution_notes": [
"First assemble invocation failed because new output parent absent; created owned parent and reran exact assembly successfully. No source correction."
]
}