docs(mosaic): preserve nested receipt integrity and independent review evidence
This commit is contained in:
parent
bbd7da2403
commit
54392cc0de
10 changed files with 982 additions and 104 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -88,3 +88,21 @@
|
||||||
- Preserved the [geometry gate](docs/design/STEP20C_STATIC_NESTED_GEOMETRY_REPLAY_GATE.md)
|
- Preserved the [geometry gate](docs/design/STEP20C_STATIC_NESTED_GEOMETRY_REPLAY_GATE.md)
|
||||||
and experimental source fixture with its historical INCONCLUSIVE verdict; STEP20C NEXT, architecture UNDECIDED and
|
and experimental source fixture with its historical INCONCLUSIVE verdict; STEP20C NEXT, architecture UNDECIDED and
|
||||||
production multi-output NOT YET SUPPORTED. No production/package/UX change.
|
production multi-output NOT YET SUPPORTED. No production/package/UX change.
|
||||||
|
|
||||||
|
## Local receipt semantic integrity gate — offline only
|
||||||
|
|
||||||
|
The [R02 receipt-integrity gate](docs/design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
|
||||||
|
is local and experimental. The real writer/aggregate share semantic validation
|
||||||
|
through the existing immutable-data replay and R01 input correlation; typed
|
||||||
|
receipt content, scenario-specific omissions, AST/test inventories and final
|
||||||
|
review bindings are checked. Historical geometry evidence remains INCONCLUSIVE;
|
||||||
|
this correction cannot retroactively qualify static popups. The final local gate
|
||||||
|
is READY_FOR_NEW_RUNTIME: 206 offline tests pass, 13478 recorded invalid mutations
|
||||||
|
are rejected, and independent review accepts the final 18-source/15-receipt
|
||||||
|
bindings after one bounded B-01 writer repair. The actual writer returns READY
|
||||||
|
with five PASS markers and no blockers. R02 is RESOLVED for this offline fixture;
|
||||||
|
partial AST coverage and runtime limitations remain explicit. Phase B is
|
||||||
|
uncommitted and unpublished, and readiness only permits requesting a separate
|
||||||
|
future authorization. No compositor/runtime authorization,
|
||||||
|
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
|
||||||
|
|
@ -454,3 +454,21 @@ terminal-code repairs are accepted; no readiness or new static popup result.
|
||||||
No graphical run or execution reservation occurred. Close the residual offline
|
No graphical run or execution reservation occurred. Close the residual offline
|
||||||
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
||||||
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
||||||
|
## Local receipt semantic integrity gate — offline only
|
||||||
|
|
||||||
|
The [R02 receipt-integrity gate](design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
|
||||||
|
is local and experimental. The real writer/aggregate share semantic validation
|
||||||
|
through the existing immutable-data replay and R01 input correlation; typed
|
||||||
|
receipt content, scenario-specific omissions, AST/test inventories and final
|
||||||
|
review bindings are checked. Historical geometry evidence remains INCONCLUSIVE;
|
||||||
|
this correction cannot retroactively qualify static popups. The final local gate
|
||||||
|
is READY_FOR_NEW_RUNTIME: 206 offline tests pass, 13478 recorded invalid mutations
|
||||||
|
are rejected, and independent review accepts the final 18-source/15-receipt
|
||||||
|
bindings after one bounded B-01 writer repair. The actual writer returns READY
|
||||||
|
with five PASS markers and no blockers. R02 is RESOLVED for this offline fixture;
|
||||||
|
partial AST coverage and runtime limitations remain explicit. Phase B is
|
||||||
|
uncommitted and unpublished, and readiness only permits requesting a separate
|
||||||
|
future authorization. No compositor/runtime authorization,
|
||||||
|
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
|
||||||
|
|
@ -395,3 +395,21 @@ terminal-code repairs are accepted; no readiness or new static popup result.
|
||||||
No graphical run or execution reservation occurred. Close the residual offline
|
No graphical run or execution reservation occurred. Close the residual offline
|
||||||
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
||||||
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
||||||
|
## Local receipt semantic integrity gate — offline only
|
||||||
|
|
||||||
|
The [R02 receipt-integrity gate](design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
|
||||||
|
is local and experimental. The real writer/aggregate share semantic validation
|
||||||
|
through the existing immutable-data replay and R01 input correlation; typed
|
||||||
|
receipt content, scenario-specific omissions, AST/test inventories and final
|
||||||
|
review bindings are checked. Historical geometry evidence remains INCONCLUSIVE;
|
||||||
|
this correction cannot retroactively qualify static popups. The final local gate
|
||||||
|
is READY_FOR_NEW_RUNTIME: 206 offline tests pass, 13478 recorded invalid mutations
|
||||||
|
are rejected, and independent review accepts the final 18-source/15-receipt
|
||||||
|
bindings after one bounded B-01 writer repair. The actual writer returns READY
|
||||||
|
with five PASS markers and no blockers. R02 is RESOLVED for this offline fixture;
|
||||||
|
partial AST coverage and runtime limitations remain explicit. Phase B is
|
||||||
|
uncommitted and unpublished, and readiness only permits requesting a separate
|
||||||
|
future authorization. No compositor/runtime authorization,
|
||||||
|
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
|
||||||
|
|
@ -313,3 +313,21 @@ terminal-code repairs are accepted; no readiness or new static popup result.
|
||||||
No graphical run or execution reservation occurred. Close the residual offline
|
No graphical run or execution reservation occurred. Close the residual offline
|
||||||
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
||||||
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
||||||
|
## Local receipt semantic integrity gate — offline only
|
||||||
|
|
||||||
|
The [R02 receipt-integrity gate](design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
|
||||||
|
is local and experimental. The real writer/aggregate share semantic validation
|
||||||
|
through the existing immutable-data replay and R01 input correlation; typed
|
||||||
|
receipt content, scenario-specific omissions, AST/test inventories and final
|
||||||
|
review bindings are checked. Historical geometry evidence remains INCONCLUSIVE;
|
||||||
|
this correction cannot retroactively qualify static popups. The final local gate
|
||||||
|
is READY_FOR_NEW_RUNTIME: 206 offline tests pass, 13478 recorded invalid mutations
|
||||||
|
are rejected, and independent review accepts the final 18-source/15-receipt
|
||||||
|
bindings after one bounded B-01 writer repair. The actual writer returns READY
|
||||||
|
with five PASS markers and no blockers. R02 is RESOLVED for this offline fixture;
|
||||||
|
partial AST coverage and runtime limitations remain explicit. Phase B is
|
||||||
|
uncommitted and unpublished, and readiness only permits requesting a separate
|
||||||
|
future authorization. No compositor/runtime authorization,
|
||||||
|
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
|
||||||
|
|
@ -399,3 +399,21 @@ terminal-code repairs are accepted; no readiness or new static popup result.
|
||||||
No graphical run or execution reservation occurred. Close the residual offline
|
No graphical run or execution reservation occurred. Close the residual offline
|
||||||
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
receipt-validation gate before proposing runtime. Architecture UNDECIDED;
|
||||||
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
||||||
|
## Local receipt semantic integrity gate — offline only
|
||||||
|
|
||||||
|
The [R02 receipt-integrity gate](design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md)
|
||||||
|
is local and experimental. The real writer/aggregate share semantic validation
|
||||||
|
through the existing immutable-data replay and R01 input correlation; typed
|
||||||
|
receipt content, scenario-specific omissions, AST/test inventories and final
|
||||||
|
review bindings are checked. Historical geometry evidence remains INCONCLUSIVE;
|
||||||
|
this correction cannot retroactively qualify static popups. The final local gate
|
||||||
|
is READY_FOR_NEW_RUNTIME: 206 offline tests pass, 13478 recorded invalid mutations
|
||||||
|
are rejected, and independent review accepts the final 18-source/15-receipt
|
||||||
|
bindings after one bounded B-01 writer repair. The actual writer returns READY
|
||||||
|
with five PASS markers and no blockers. R02 is RESOLVED for this offline fixture;
|
||||||
|
partial AST coverage and runtime limitations remain explicit. Phase B is
|
||||||
|
uncommitted and unpublished, and readiness only permits requesting a separate
|
||||||
|
future authorization. No compositor/runtime authorization,
|
||||||
|
production/UX/package change or STEP20D work follows. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT; production multi-output NOT YET SUPPORTED.
|
||||||
|
|
|
||||||
224
docs/design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md
Normal file
224
docs/design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md
Normal file
|
|
@ -0,0 +1,224 @@
|
||||||
|
# STEP20C static nested receipt semantic integrity gate
|
||||||
|
|
||||||
|
EXPERIMENTAL, offline only; semantic integrity gate READY_FOR_NEW_RUNTIME,
|
||||||
|
with independent acceptance of the final bound fixture and receipts.
|
||||||
|
Historical geometry gate remains INCONCLUSIVE. Architecture UNDECIDED;
|
||||||
|
STEP20C NEXT, production multi-output NOT YET SUPPORTED. No graphical run,
|
||||||
|
Mosaic/SceneFX build, client execution, capture, input, grab, camera or runtime reservation.
|
||||||
|
|
||||||
|
## Pre-implementation contract
|
||||||
|
|
||||||
|
The published `write_results.py` SHA-256 is
|
||||||
|
`94ddab595dd9765d3edaa7158a6a98319f3be6b15a62842e4b10eeacfb530cfa`.
|
||||||
|
Its `REQUIRED` names fifteen receipts; independent-review is the sixteenth
|
||||||
|
dependency. `write()` loads the receipts, computes bindings, and calls
|
||||||
|
`aggregate(evidence, hash_file, bindings)`. The pre-correction function checks status,
|
||||||
|
field presence, nine-case cardinality and some file hashes. It does not verify
|
||||||
|
the effective nested content. Three actual in-memory calls accept a bare PASS
|
||||||
|
input correlation, null rendered content/bbox/count/intersection, or nine
|
||||||
|
empty root objects. These are R02-A/B/C, not compositor observations.
|
||||||
|
|
||||||
|
The correction must use this entrypoint for all decisions. Downstream gates not checked after a failed prerequisite are also INCONCLUSIVE. Invalid evidence
|
||||||
|
returns INCONCLUSIVE with a named blocker and degrades its dependent marker;
|
||||||
|
invalid evidence is neither a compositor crash nor an architectural rejection.
|
||||||
|
Unexpected implementation failures cannot become PASS. Missing files and
|
||||||
|
malformed JSON must also produce blockers. No old receipts are overwritten.
|
||||||
|
|
||||||
|
## Required receipt schema and relationships
|
||||||
|
|
||||||
|
| Receipt | Required real content and types | Provenance and semantic relationship |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| native-shm | positive integer buffer, rectangle size, positive stride, format, source, identity qualification | Replay actual SHM create/attach/ACK; 420×320, stride 1680, format 1; frame identity remains NOT PROVEN |
|
||||||
|
| xdg-configure | toplevel rectangle, positive initial/assigned ACK, initial configure, new-buffer boolean, popup qualification | Replay initial 0×0/ACK20 versus assigned 636×573/ACK21; no replacement buffer |
|
||||||
|
| applied | positive owner/PID/workspace, scene/window rectangles, titlebar, finite scroll, globalclip, generation qualification | Replay IPC/source/applied trace; scene (-320,0,640,600), titlebar25, scroll160, viewport(-800,0,800,600) |
|
||||||
|
| rendered | content rectangle, bbox, nonnegative integer count, visible intersection, native/destination distinction | Replay native geometry and retained image through existing typed model: (-318,25,636,573), bbox[482,25,800,598), 182214 pixels; output origin, clipping and area agree |
|
||||||
|
| positioner | integer flags, A/B local rectangles, content origin, predicted A/B, runtime qualification | Source-backed flags0; translate A then B from painted origin; prediction never runtime |
|
||||||
|
| historical-evidence | complete mandatory input path/hash mapping, diagnostic path, runtime qualification | Actual immutable files must exist; replay source/IPC/calibration/reference inputs are all verified |
|
||||||
|
| historical-replay | exactly nine unique campaign identities; owner/PID/workspace, origin, A/B/configured, protocol, clip, colors, callbacks, injections, buttons, lifecycle, file inventory, input correlation | Re-execute unchanged replay and R01 correlation on retained logs/IPC/images in a disposable directory, then compare every field, type and value |
|
||||||
|
| popup-root | nine case/origin/A/clip projections | Exact identity join and projection from independently replayed original data; owner is supplied by that joined replay, not fabricated in the historical root schema |
|
||||||
|
| popup-nested | nine case/B/protocol/standard/dismissal projections | B→A parent, distinct actual serials, configure/ACK/map and lifecycle replay; same identities/geometries/protocol as historical-replay |
|
||||||
|
| source-audit | pins, 17 unique source contracts, functions, claims, excerpts, source-version receipt/hash | Mandatory historical contract set; actual source/excerpt/version bytes verified |
|
||||||
|
| client-provenance | mandatory inputs, patch, adapted source, four protocols, comparison, three builds, C17 command receipts | Retained compilation receipts only; source/output/protocol hashes and flags verified, no new build or execution |
|
||||||
|
| assertion-register | full source/artifact inventories, AST records, counts, 145 historical assertions | Enumerate current AST and use the existing assertion checker for identities, classification and actual test correlations |
|
||||||
|
| assertion-coverage | entries, 145 assertions, coverage counts, unresolved list, runtime scope | Recompute from register; partial executed coverage remains explicit |
|
||||||
|
| offline-core-coverage | status, unproved list | Recompute necessary existing pure model guards from register; no invented runtime coverage |
|
||||||
|
| test-receipts | complete source inventory, unique actual tests, mode/line/contract observations, statuses | Fresh current code; genuine non-aggregator then negative-suite preflights bootstrap aggregation tests without forcing PASS; the complete mandatory negative test set and final full suite must pass before review |
|
||||||
|
| independent-review | ACCEPTED, independent=true, exact final source and evidence bindings | Genuine report file/hash, reviewer provenance, executed commands, mandatory independent attack results, findings and limitations; positive unit control has memory-only synthetic acceptance, rejected by the real file-backed writer |
|
||||||
|
|
||||||
|
Rectangles use [x,y,width,height]; PNG bbox uses [x1,y1,x2,y2).
|
||||||
|
IDs/serials/counts are integers (booleans are invalid), coordinates are finite.
|
||||||
|
Positive visible counts require positive valid bboxes; count cannot exceed area.
|
||||||
|
No semantic trust is granted merely because a file hashes to its own receipt.
|
||||||
|
Re-derived source observations must match, including owner, workspace, camera,
|
||||||
|
output origin, titlebar, source/destination and input local/global translation.
|
||||||
|
|
||||||
|
The fixed nine-campaign gate is intentionally scenario-specific. Standard
|
||||||
|
control `clip=null` is required and legitimate. Color `bbox=null` is legitimate
|
||||||
|
with zero pixels. Nested `standard=null` and `dismissal=null` are legitimate
|
||||||
|
only where their original scenario did not exercise that operation. Toggle
|
||||||
|
requires its real standard receipt; close_b requires explicit B close and A
|
||||||
|
survival in the original replay (the historical nested projection lacks that
|
||||||
|
field); outside/dismissal scenarios require real done/destruction and absence
|
||||||
|
of forbidden popup buttons. Unattributable early seat callbacks keep their
|
||||||
|
explicit NOT AVAILABLE label. Native-frame and atomic-generation qualifications
|
||||||
|
remain unproved. Missing scenario-required facts are invalid, never filled in.
|
||||||
|
|
||||||
|
## Freshness, mutation tests and independent review
|
||||||
|
|
||||||
|
Bind all fixture source files and all fifteen evidence files. The aggregator
|
||||||
|
checks the current source bytes and actual loaded evidence against these files;
|
||||||
|
review must contain the identical bindings. A source or receipt change after
|
||||||
|
review invalidates acceptance, even if a new matching author hash is supplied.
|
||||||
|
Inventories with defined mandatory sets reject omitted members. The historical
|
||||||
|
67/88-entry sealed manifests remain read-only and are never regenerated.
|
||||||
|
|
||||||
|
Order: reproduce R02; correct real aggregate; positive control; deletion,
|
||||||
|
null/{}/[]/empty-string mutations; cross-receipt contradictions; stale/missing
|
||||||
|
source/evidence/patch/review bindings; writer test in a private directory;
|
||||||
|
nine-case replay; new receipts; AST/Shell/Git/inventory; source freeze;
|
||||||
|
independent review of final bytes; binding verification; verdict; new manifests.
|
||||||
|
Each original counterexample has its own test and receipt. Tests use independent
|
||||||
|
deep copies and call the actual aggregate, with no replacement policy/mock.
|
||||||
|
|
||||||
|
One configured Astra/high final-reviewer independently reproduces attacks
|
||||||
|
without relying on the author's mutation suite. It records files/hashes,
|
||||||
|
commands/results, limits and ACCEPTED/CORRECTION_REQUIRED/NOT_PROVEN. One
|
||||||
|
bounded correction and delta review are allowed; unresolved material findings
|
||||||
|
keep INCONCLUSIVE. An accepted earlier version cannot sign changed bytes.
|
||||||
|
|
||||||
|
Marker dependencies retain the existing geometry/XDG/assertion/regression/
|
||||||
|
review groups; any invalid mandatory dependency prevents READY_FOR_NEW_RUNTIME.
|
||||||
|
READY means only readiness to request authorization in a separate ticket.
|
||||||
|
Static popup qualification and architectural conclusions are untouched.
|
||||||
|
|
||||||
|
## Results
|
||||||
|
|
||||||
|
Phase A was published at `bbd7da24036f741130b2ff542f429b416fb9c7e5` on both
|
||||||
|
origin/main and github/main, with a clean worktree at its gate. Phase B remains
|
||||||
|
local, uncommitted and unpublished. The historical verdict is not superseded.
|
||||||
|
|
||||||
|
`SWAYFX_MOSAIC_STATIC_NESTED_RECEIPT_INTEGRITY_GATE=READY_FOR_NEW_RUNTIME`
|
||||||
|
|
||||||
|
The final genuine independent review is ACCEPTED. The actual file-backed writer,
|
||||||
|
using that review rather than a synthetic test receipt, returns READY_FOR_NEW_RUNTIME
|
||||||
|
with all five markers PASS and no blockers. R02 is RESOLVED for this offline
|
||||||
|
fixture; R01/R03 retain their historical accepted status. No material finding
|
||||||
|
remains in the bounded review scope. Architecture remains UNDECIDED.
|
||||||
|
|
||||||
|
## Initial independent review and bounded repair
|
||||||
|
|
||||||
|
The initial Astra/high read-only audit rejects the version with B-01:
|
||||||
|
`write()` lets a JSON decoder RecursionError escape, leaving pre-existing
|
||||||
|
runner-readiness/offline-gate READY files unchanged. The direct reproduction
|
||||||
|
uses a 200001-byte rendered.json with 100000 nested arrays. The initial
|
||||||
|
CORRECTION_REQUIRED report and bindings are retained separately; no acceptance
|
||||||
|
of changed bytes is implied.
|
||||||
|
|
||||||
|
The authorized repair is limited to treating decoder/encoder RecursionError
|
||||||
|
as an invalid required receipt, and a real writer regression proving both
|
||||||
|
old READY artifacts become INCONCLUSIVE. No parser framework, runtime change
|
||||||
|
or scientific dataset limit is introduced. The current-code offline
|
||||||
|
validation was rerun and the repaired delta submitted to an independent reviewer.
|
||||||
|
|
||||||
|
|
||||||
|
## Final executed evidence and limitations
|
||||||
|
|
||||||
|
Private laboratory: `/home/fy59/swayfx-mosaic-receipt-integrity-cof0umuk/`.
|
||||||
|
Historical laboratory: `/home/fy59/swayfx-mosaic-static-nested-geometry-replay-a56csvoo/`.
|
||||||
|
The original `aggregate()` and fixture are retained in `sources-before/`; the
|
||||||
|
initial reviewed version is in `reviewed-fixture-v1/`, and final code in
|
||||||
|
`proposed-fixture/`. `raw/phase-B-complete.diff` records the complete local delta.
|
||||||
|
|
||||||
|
| Executed check | Final observed result |
|
||||||
|
| --- | --- |
|
||||||
|
| Non-aggregator bootstrap | 145 tests PASS, genuine receipts |
|
||||||
|
| Mandatory negative bootstrap | 204 tests PASS, genuine receipts |
|
||||||
|
| Final full offline suite | 206 tests PASS, 474.694 seconds |
|
||||||
|
| Original R02-A/B/C | 3 separate mutations INCONCLUSIVE with named blockers |
|
||||||
|
| Field deletion | 2668 mutations INCONCLUSIVE |
|
||||||
|
| Null / empty object / empty list / empty string | 10604 invalid mutations INCONCLUSIVE; legitimate omissions separately accepted |
|
||||||
|
| Cross-receipt contradiction | 173 mutations INCONCLUSIVE |
|
||||||
|
| Stale/missing files, source/patch/review bindings | 30 mutations INCONCLUSIVE |
|
||||||
|
| Recorded mutation total | 13478 rejected, no recorded invalid mutation READY |
|
||||||
|
| Positive complete receipt control | READY_FOR_NEW_RUNTIME; SYNTHETIC_IN_MEMORY_ONLY |
|
||||||
|
| Historical replay | All nine campaigns PASS through unchanged replay/R01 functions |
|
||||||
|
| AST register | 2371 sites, including 145 frozen historical assertions; 314 positive+negative, 872 positive-only, 1179 unexecuted |
|
||||||
|
| Pure model coverage | No unresolved pure invariant; partial executed coverage remains explicit |
|
||||||
|
| Independent final delta | 12 required attacks rejected, one memory positive accepted, three real-writer controls PASS |
|
||||||
|
| Actual accepted writer | READY_FOR_NEW_RUNTIME, five PASS markers, no blockers; final source/receipt bindings unchanged |
|
||||||
|
|
||||||
|
The initial independent Astra/high report is CORRECTION_REQUIRED due to B-01.
|
||||||
|
One bounded repair was performed, followed by the read-only Sol/medium delta
|
||||||
|
review ACCEPTED for the new 18-source/15-receipt bindings. These are distinct
|
||||||
|
reviews; the older review was never reused as acceptance of changed code.
|
||||||
|
The final report is `independent-review.md` (SHA-256
|
||||||
|
`311af1fe694d1bde88884afa21ef16a4fe908d6cfa47b6cbed515d1a21fedc9e`),
|
||||||
|
and its receipt is `results/independent-review.json` (SHA-256
|
||||||
|
`4d8401978e69a6c54f2f6144ba06deff4952671bc8e1ae3008376ab6ffe01e09`).
|
||||||
|
|
||||||
|
Final source SHA-256 values:
|
||||||
|
|
||||||
|
- `write_results.py`: `9202522721caa1815d3824a3db315c8cdb27e607ce1678907774faa1c9c14c0c`.
|
||||||
|
- `receipt_integrity.py`: `3f32003f7de74336f2be17e063295d51f683d40936568fd8aebebeb5d3f9b45f`.
|
||||||
|
- `tests_offline.py`: `0e188fe64d0c3d8a6fda227bf4ef8b31658b86390b5ed73d97d0e3bf851b67d1`.
|
||||||
|
|
||||||
|
Commands and exit codes are retained in `results/commands.json`, reviewer
|
||||||
|
receipts, final validation receipts and `raw/`. Intermediate author test failures
|
||||||
|
(including an incomplete assertion inventory and test-bootstrap completeness)
|
||||||
|
were corrected before freeze and remain preserved. The delta review's first
|
||||||
|
static-harness attempt exited 1 due to a Path conversion typo; its correction
|
||||||
|
and successful retry are retained. None is concealed as a successful run.
|
||||||
|
|
||||||
|
The existing offline suite prepared three client-only C17 utilities in disposable
|
||||||
|
test directories; no client was executed, and neither compositor nor SceneFX
|
||||||
|
was built. No new image, serial, pointer injection, grab, camera operation,
|
||||||
|
compositor socket, runtime reservation or installation was produced. Retained
|
||||||
|
image parsing is offline replay, not capture. Protected production files,
|
||||||
|
package, cumulative patch and historical sealed manifest entries are unchanged.
|
||||||
|
|
||||||
|
Freshness binds raw receipt bytes as well as canonical parsed content and source
|
||||||
|
bytes. A formatting change also expires a reviewed file. New source or receipt
|
||||||
|
bytes require new independent acceptance; matching freshly calculated author
|
||||||
|
hashes alone cannot preserve a prior ACCEPTED verdict. Source/evidence manifests
|
||||||
|
are sealed only for this new laboratory after final checks. Historical manifests
|
||||||
|
remain exactly the published 67/88-entry originals.
|
||||||
|
|
||||||
|
This finite mutation campaign and independent audit support the fixed historical
|
||||||
|
fixture contract; they do not prove arbitrary future receipt schemas or universal
|
||||||
|
parser/resource resilience. READY is solely permission-request readiness.
|
||||||
|
Native-frame identity, atomic transaction generation, GPU-reference lifetime,
|
||||||
|
new static popup geometry/pixels/input/grabs/dismissal/standard return, and the
|
||||||
|
remaining output/damage/effects/ABI matrix remain NOT TESTED or NOT PROVEN as
|
||||||
|
previously documented. No architectural or UX decision follows. STEP20C stays
|
||||||
|
NEXT and production multi-output stays NOT YET SUPPORTED. The smallest next
|
||||||
|
step is a separately authorized static-popup runtime ticket; this ticket
|
||||||
|
performs no such run.
|
||||||
|
|
||||||
|
## Historical receipt-integrity evidence freeze — 2026-10-13
|
||||||
|
|
||||||
|
Ticket `SWAYFX_MOSAIC_STEP20C_RECEIPT_FREEZE_AND_STATIC_NESTED_RUNTIME_V1`,
|
||||||
|
phase A, preserves the accepted R02 version for publication. Statements above
|
||||||
|
about local/unpublished phase B and absent runtime authorization describe the
|
||||||
|
previous offline ticket. This freeze changes no reviewed fixture byte and no
|
||||||
|
sealed laboratory file; the separate runtime handoff requires its own evidence,
|
||||||
|
authorization and independent acceptance.
|
||||||
|
|
||||||
|
The 76 source entries and 199 evidence entries in the receipt-integrity LAB
|
||||||
|
were individually verified. Manifest SHA-256 values are respectively
|
||||||
|
`dbd96db3f19f6eb60fc8be13c62b1e71944a759b481d008a7825b3720cf525ce` and
|
||||||
|
`f00ca54e39bff031a5bda585ea52cfebe9239e71b4c7ee7dc5c41a930e1598b3`.
|
||||||
|
The final report and review receipt hashes remain exactly those recorded above.
|
||||||
|
All 18 source and 15 mandatory receipt bindings match independent acceptance.
|
||||||
|
The actual aggregate was freshly called: READY_FOR_NEW_RUNTIME, five PASS
|
||||||
|
markers, no blocker. The three original R02 counterexamples were freshly
|
||||||
|
rejected; a disposable real-writer B-01 check replaced both prior READY files
|
||||||
|
with INCONCLUSIVE. No synthetic independent acceptance was persisted.
|
||||||
|
|
||||||
|
The retained 206-test, nine-replay and 13478-rejected-mutation results were
|
||||||
|
verified from their immutable receipts, not relabelled as a newly executed full
|
||||||
|
suite. Python AST, Markdown links, complete diff including untracked files,
|
||||||
|
310 protected paths and `git diff --check` passed. No runtime, build, capture,
|
||||||
|
client execution, socket or reservation belongs to phase A. Historical initial
|
||||||
|
CORRECTION_REQUIRED and final ACCEPTED reviews remain separate. Architecture
|
||||||
|
UNDECIDED; static popup runtime NOT TESTED; STEP20C NEXT, production multi-output
|
||||||
|
NOT YET SUPPORTED.
|
||||||
|
|
@ -125,7 +125,7 @@ forbidden action is separated from earlier legitimate visible buttons and its
|
||||||
actual observed events feed dismissal. Corrupted coordinates, recipients,
|
actual observed events feed dismissal. Corrupted coordinates, recipients,
|
||||||
extra invisible buttons and button order fail closed.
|
extra invisible buttons and button order fail closed.
|
||||||
|
|
||||||
R02: `aggregate` is the single gate implementation used by writer and tests.
|
Historical R02 disposition (published freeze): `aggregate` was the single gate implementation used by writer and tests.
|
||||||
SHM, XDG/configured geometry, source contracts/pins, client provenance/C17,
|
SHM, XDG/configured geometry, source contracts/pins, client provenance/C17,
|
||||||
all nine historical cases, register/coverage/core and test receipts are
|
all nine historical cases, register/coverage/core and test receipts are
|
||||||
mandatory and checked for freshness and structural presence. The bounded
|
mandatory and checked for freshness and structural presence. The bounded
|
||||||
|
|
@ -151,7 +151,7 @@ remain inventoried. Re-run the offline sequence after source changes before
|
||||||
handing the final unsealed fixture to the parent for bounded review.
|
handing the final unsealed fixture to the parent for bounded review.
|
||||||
|
|
||||||
|
|
||||||
## Final offline disposition — INCONCLUSIVE / NOT READY
|
## Historical offline disposition — INCONCLUSIVE / NOT READY
|
||||||
|
|
||||||
The independent tester ran195 tests with0 failures and all9 historical cases.
|
The independent tester ran195 tests with0 failures and all9 historical cases.
|
||||||
The bounded independent reviewer ran65 targeted tests PASS and resolved R01/R03,
|
The bounded independent reviewer ran65 targeted tests PASS and resolved R01/R03,
|
||||||
|
|
@ -167,3 +167,46 @@ The four raw technical PASS labels do not prove effective receipt completeness.
|
||||||
The fixture is prepared but NOT READY; run.py must remain unexecuted. The next
|
The fixture is prepared but NOT READY; run.py must remain unexecuted. The next
|
||||||
step is a separately scoped offline correction of aggregate's semantic-content
|
step is a separately scoped offline correction of aggregate's semantic-content
|
||||||
guards and their negative regressions. No new runtime/budget is authorized.
|
guards and their negative regressions. No new runtime/budget is authorized.
|
||||||
|
|
||||||
|
## Local R02 semantic integrity correction
|
||||||
|
|
||||||
|
See [the receipt contract](../../../docs/design/STEP20C_STATIC_NESTED_RECEIPT_INTEGRITY_GATE.md).
|
||||||
|
`aggregate()` remains the single decision function used by `write()` and tests.
|
||||||
|
`receipt_integrity.py` replays the original data through existing geometry,
|
||||||
|
protocol and R01 correlation functions in disposable offline directories, and
|
||||||
|
compares every typed receipt field. It uses the existing AST checker and checks
|
||||||
|
complete mandatory file inventories. Null clips in standard controls, zero-color
|
||||||
|
null bboxes and scenario-specific absent standard/dismissal observations remain
|
||||||
|
legitimate; required toggle/close/dismissal observations cannot be deleted.
|
||||||
|
No historical receipt, raw log, image or sealed manifest is rewritten.
|
||||||
|
|
||||||
|
Bindings cover all fixture sources, all mandatory receipt file bytes and the
|
||||||
|
canonical parsed content. A changed source/receipt loses prior acceptance.
|
||||||
|
Unit M0 acceptance is synthetic, explicitly memory-only. The real writer only
|
||||||
|
reads the external independent review; it never signs acceptance. Final readiness
|
||||||
|
is determined by that exact bound review and the genuine test receipts.
|
||||||
|
|
||||||
|
In a new offline LAB, run the existing replay, run `tests_offline.py LAB --preflight`,
|
||||||
|
then `assertions.py LAB`. Copy these genuine receipts under `LAB/preflight/results/`
|
||||||
|
before running `tests_offline.py LAB --negative-preflight`. Regenerate the AST
|
||||||
|
receipts and replace the new LAB preflight snapshot with these genuinely executed
|
||||||
|
negative-suite receipts, then run `tests_offline.py LAB` for the final validation.
|
||||||
|
This prevents circular test bootstrapping
|
||||||
|
without forcing PASS or substituting old source hashes. Regenerate the final
|
||||||
|
AST receipts, freeze source/evidence bytes, and request independent review.
|
||||||
|
Initial preflight covers non-aggregator tests. Negative preflight collects all
|
||||||
|
required negative test IDs without claiming M0 readiness. Final validation uses
|
||||||
|
that complete snapshot and must pass its positive controls as well. The suite
|
||||||
|
executes the R02/mutation/writer tests. No synthetic review file is written.
|
||||||
|
All generated output belongs outside Git. These are Python/offline operations
|
||||||
|
only; no runtime command or ledger initialization is authorized.
|
||||||
|
|
||||||
|
The historical INCONCLUSIVE verdict above remains frozen. The local semantic
|
||||||
|
gate can establish only readiness to request a separate future authorization,
|
||||||
|
never static popup success. R01/R03 and the runner are unchanged. Phase B is
|
||||||
|
local, uncommitted and unpublished.
|
||||||
|
|
||||||
|
The bounded B-01 repair treats JSON decoder/encoder recursion exhaustion as
|
||||||
|
malformed required evidence. The real writer must replace pre-existing READY
|
||||||
|
artifacts with INCONCLUSIVE; decoder failure never retains a qualified gate.
|
||||||
|
This is receipt error handling, not a compositor/SceneFX rejection.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,314 @@
|
||||||
|
"""Semantic checks for the fixed, retained offline campaign; no runtime action.
|
||||||
|
|
||||||
|
WHY: self-consistent labels/hashes cannot establish observations. Reuse the
|
||||||
|
qualified replay, input correlation and AST checker instead of a second model.
|
||||||
|
CONTRACT: historical inputs are read-only; all checker output is disposable.
|
||||||
|
INVARIANT: cached replay is bound to sealed input bytes, never caller receipts.
|
||||||
|
"""
|
||||||
|
from functools import lru_cache
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from support import sha
|
||||||
|
|
||||||
|
HERE = Path(__file__).resolve().parent
|
||||||
|
SEALED = Path('/home/fy59/swayfx-mosaic-static-nested-geometry-replay-a56csvoo')
|
||||||
|
SEALS = {'source-sha256.txt': 'e1230ba1292f12d913b762f0678e638a2effb513b74eb44dd232c12aa4acea1d',
|
||||||
|
'evidence-sha256.txt': '22b9ac035da95ba914c28d72d8aa6f019c16c2854095d81ceb62c0bd10da8dbe'}
|
||||||
|
REVIEW_ATTACKS = {'R02-A','R02-B','R02-C','root-empty','nested-empty','input-partial',
|
||||||
|
'render-incoherent','standard-missing','dismissal-missing',
|
||||||
|
'serial-contradiction','source-stale','old-review-bindings'}
|
||||||
|
|
||||||
|
|
||||||
|
def check(ok, reason):
|
||||||
|
if not ok:
|
||||||
|
raise ValueError(reason)
|
||||||
|
|
||||||
|
|
||||||
|
def encoded(value):
|
||||||
|
return json.dumps(value, sort_keys=True, separators=(',', ':'), allow_nan=False)
|
||||||
|
|
||||||
|
|
||||||
|
def same(actual, expected, path='receipt'):
|
||||||
|
"""Types matter: Python's True == 1 must not accept a serial or count."""
|
||||||
|
check(type(actual) is type(expected), path + ': wrong type')
|
||||||
|
if isinstance(expected, dict):
|
||||||
|
check(set(actual) == set(expected), path + ': missing/unexpected fields')
|
||||||
|
for key in expected:
|
||||||
|
same(actual[key], expected[key], path + '.' + key)
|
||||||
|
elif isinstance(expected, list):
|
||||||
|
check(len(actual) == len(expected), path + ': incomplete observations')
|
||||||
|
for index, value in enumerate(expected):
|
||||||
|
same(actual[index], value, path + '[' + str(index) + ']')
|
||||||
|
else:
|
||||||
|
if isinstance(actual, float):
|
||||||
|
check(math.isfinite(actual), path + ': nonfinite coordinate')
|
||||||
|
check(actual == expected, path + ': contradicts original observation')
|
||||||
|
|
||||||
|
|
||||||
|
def fresh(mapping, hash_file, required=None):
|
||||||
|
check(isinstance(mapping, dict) and bool(mapping), 'missing hash inventory')
|
||||||
|
if required is not None:
|
||||||
|
check(set(mapping) == set(required), 'incomplete mandatory inventory')
|
||||||
|
for path, digest in mapping.items():
|
||||||
|
check(isinstance(path, str) and bool(path), 'invalid input path')
|
||||||
|
check(isinstance(digest, str) and len(digest) == 64 and
|
||||||
|
all(c in '0123456789abcdef' for c in digest), 'missing/invalid SHA-256')
|
||||||
|
check(hash_file(path) == digest, 'missing/stale file: ' + path)
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def sealed_receipts():
|
||||||
|
"""Bootstrap only the immutable historical source/provenance contracts.
|
||||||
|
|
||||||
|
The fixed manifests authenticate the campaign used by this bounded gate.
|
||||||
|
This does not accept derived semantics: geometry/input are replayed below.
|
||||||
|
"""
|
||||||
|
for name, digest in SEALS.items():
|
||||||
|
check(sha(SEALED / 'results' / name) == digest, 'historical seal changed')
|
||||||
|
rows = (SEALED / 'results' / name).read_text().splitlines()
|
||||||
|
check(len(rows) == (67 if name.startswith('source') else 88), 'seal inventory incomplete')
|
||||||
|
for row in rows:
|
||||||
|
expected, path = row.split(' ', 1)
|
||||||
|
check(sha(path) == expected, 'sealed historical file changed: ' + path)
|
||||||
|
return {name: json.loads((SEALED / 'results' / (name + '.json')).read_text())
|
||||||
|
for name in ('source-audit', 'client-provenance', 'historical-replay', 'historical-evidence')}
|
||||||
|
|
||||||
|
|
||||||
|
def historical_inputs():
|
||||||
|
from replay import NESTED, HISTORICAL
|
||||||
|
old = sealed_receipts()
|
||||||
|
expected = dict(old['historical-evidence']['inputs'])
|
||||||
|
manifest = HISTORICAL / 'results/evidence-sha256.txt'
|
||||||
|
check(sha(manifest) == '5750d1e74636c2d276800f795ed0214c3e12999908149855af0b382a2da9bfb4',
|
||||||
|
'original geometry evidence seal changed')
|
||||||
|
sealed_raw = {path: digest for digest,path in
|
||||||
|
(line.split(' ',1) for line in manifest.read_text().splitlines())}
|
||||||
|
# Replay also reads these original IPC/calibration/reference observations.
|
||||||
|
extra = [str(HISTORICAL / rel) for rel in (
|
||||||
|
'results/camera-calibration.json', 'results/E1-applied-snapshot.json',
|
||||||
|
'results/geometry-fixture-diagnostic.json', 'run/H2-reference-1.png', 'run/H2-reference-2.png')]
|
||||||
|
for path in extra:expected[path]=sealed_raw[path]
|
||||||
|
for row in old['historical-replay']['cases']:
|
||||||
|
expected.update({str(NESTED / row['case'] / name): digest for name,digest in row['files'].items()})
|
||||||
|
fresh(expected, sha)
|
||||||
|
return dict(sorted(expected.items()))
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def rederived(input_key):
|
||||||
|
"""Bounded cache: one replay, keyed by every raw input's real SHA-256.
|
||||||
|
|
||||||
|
Rechecking hashes before lookup prevents a stale cache from authorizing
|
||||||
|
changed observations. No subprocess, client or compositor is executed.
|
||||||
|
"""
|
||||||
|
from replay import replay_native, replay_nested
|
||||||
|
with tempfile.TemporaryDirectory(prefix='mosaic-receipt-replay-') as tmp:
|
||||||
|
root = Path(tmp)
|
||||||
|
(root / 'results').mkdir()
|
||||||
|
replay_native(root)
|
||||||
|
replay_nested(root)
|
||||||
|
values = {p.stem: json.loads(p.read_text()) for p in (root / 'results').glob('*.json')}
|
||||||
|
# The positioner is a source prediction, separate from historical configure.
|
||||||
|
values['positioner'] = dict(status='PASS source-backed prediction', flags=0,
|
||||||
|
A=[100,80,350,170], B=[100,60,300,130], predicted_content_origin=[-318,25],
|
||||||
|
predicted_A=[-218,105,350,170], predicted_B=[-118,165,300,130],
|
||||||
|
runtime='NOT TESTED; actual configure/ACK/map required')
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=16)
|
||||||
|
def checked_historical(name, receipt_key, input_key):
|
||||||
|
same(json.loads(receipt_key), rederived(input_key)[name], name)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_historical(name, data, hash_file, inputs=None):
|
||||||
|
inputs = historical_inputs() if inputs is None else inputs
|
||||||
|
# Exact typed comparisons include all scenario-specific observations, not
|
||||||
|
# just lists/status. Standard/null/zero-color cases follow the real replay.
|
||||||
|
checked_historical(name, encoded(data), tuple(inputs.items()))
|
||||||
|
|
||||||
|
|
||||||
|
def validate_source_audit(data, hash_file):
|
||||||
|
expected = sealed_receipts()['source-audit']
|
||||||
|
same(data, expected, 'source-audit')
|
||||||
|
for contract in data['contracts']:
|
||||||
|
fresh({contract['source']: contract['sha256']}, hash_file)
|
||||||
|
lines = Path(contract['source']).read_text().splitlines()
|
||||||
|
for excerpt in contract['excerpts']:
|
||||||
|
check(excerpt['token'] in lines[excerpt['line'] - 1], 'source excerpt token/line mismatch')
|
||||||
|
check(excerpt['text'] in '\n'.join(lines), 'source excerpt absent')
|
||||||
|
fresh({data['source_version_receipt']: data['source_version_sha256']}, hash_file)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_client(data, hash_file):
|
||||||
|
expected = sealed_receipts()['client-provenance']
|
||||||
|
same(data, expected, 'client-provenance')
|
||||||
|
fresh(data['inputs'], hash_file, expected['inputs'])
|
||||||
|
fresh({str(HERE / 'placement.patch'): data['patch']}, hash_file)
|
||||||
|
builds = {b['client']: b for b in data['builds']}
|
||||||
|
for command in data['commands']:
|
||||||
|
check(command['exit'] == 0, 'historical C17 command failed')
|
||||||
|
label, argv = command['label'], command['argv']
|
||||||
|
if label.endswith('-compile') and label[:-8] in builds:
|
||||||
|
build = builds[label[:-8]]
|
||||||
|
source = next(v for v in argv if v.endswith('/' + label[:-8] + '.c'))
|
||||||
|
output = argv[argv.index('-o') + 1]
|
||||||
|
fresh({source: build['source'], output: build['binary']}, hash_file)
|
||||||
|
fresh({str(Path(source).parent / n): v for n, v in data['protocols'].items()}, hash_file)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_tests(data, hash_file):
|
||||||
|
check(set(data)=={'status','source_inventory','tests'}, 'missing test receipt fields')
|
||||||
|
files = {str(p) for p in HERE.iterdir() if p.suffix in ('.py', '.patch', '.json')}
|
||||||
|
fresh(data['source_inventory'], hash_file, files)
|
||||||
|
tests = data['tests']
|
||||||
|
check(isinstance(tests, list) and bool(tests), 'missing executed tests')
|
||||||
|
ids = set()
|
||||||
|
# WHY: M0 must consume a genuinely completed negative suite. Excluding the
|
||||||
|
# two positive controls avoids a circular requirement for their own PASS.
|
||||||
|
import tests_offline
|
||||||
|
mandatory = {'Case.' + n for n in dir(tests_offline.Case)
|
||||||
|
if n.startswith('test_') and n not in (
|
||||||
|
'test_positive_aggregate_complete_bound','test_integrity_legitimate_omissions')}
|
||||||
|
allowed={'Case.'+n for n in dir(tests_offline.Case) if n.startswith('test_')}
|
||||||
|
for test in tests:
|
||||||
|
check(isinstance(test, dict), 'malformed test receipt')
|
||||||
|
check(test['status'] == 'PASS' and test['mode'] in ('positive', 'negative'), 'failed/unclassified test')
|
||||||
|
check(isinstance(test['id'], str) and '.Case.test_' in test['id'], 'invalid test identity')
|
||||||
|
check(test['id'] not in ids, 'duplicate test identity')
|
||||||
|
ids.add(test['id'])
|
||||||
|
check(test['id'].split('.Case.')[0] in ('__main__','tests_offline') and
|
||||||
|
test['id'][test['id'].index('Case.'):] in allowed,'unknown executed test identity')
|
||||||
|
for field in ('executed_lines', 'failed_lines', 'contracts'):
|
||||||
|
check(isinstance(test[field], list), 'missing test trace: ' + field)
|
||||||
|
check(bool(test['executed_lines']) and all(isinstance(line,str) and bool(line)
|
||||||
|
for line in test['executed_lines']), 'empty executed test trace')
|
||||||
|
for c in test['contracts']:
|
||||||
|
check(isinstance(c['contract'], str) and bool(c['contract']) and type(c['pass']) is bool,
|
||||||
|
'invalid executed contract')
|
||||||
|
check(mandatory <= {n[n.index('Case.'):] for n in ids}, 'incomplete mandatory negative suite')
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=1)
|
||||||
|
def checked_register(key):
|
||||||
|
"""Use the original qualified AST checker, writing only to a temp LAB."""
|
||||||
|
import assertions
|
||||||
|
evidence = json.loads(key)
|
||||||
|
with tempfile.TemporaryDirectory(prefix='mosaic-receipt-register-') as tmp:
|
||||||
|
lab = Path(tmp)
|
||||||
|
(lab / 'results').mkdir()
|
||||||
|
for name, data in evidence.items():
|
||||||
|
(lab / 'results' / (name + '.json')).write_text(json.dumps(data))
|
||||||
|
# WHY: checking existing AST keys alone allowed null or misleading
|
||||||
|
# derived classification/coverage fields. Regenerate every record
|
||||||
|
# through the same classifier and executed-receipt logic as the writer
|
||||||
|
# workflow, then compare the full caller-provided register and core.
|
||||||
|
coverage=assertions.build(lab)
|
||||||
|
generated=json.loads((lab/'results/assertion-register.json').read_text())
|
||||||
|
same(evidence['assertion-register'],generated,'assertion-register effective content')
|
||||||
|
same(evidence['offline-core-coverage'],json.loads((lab/'results/offline-core-coverage.json').read_text()),'offline-core-coverage effective content')
|
||||||
|
return coverage
|
||||||
|
|
||||||
|
|
||||||
|
def validate_register(name, evidence, hash_file):
|
||||||
|
import assertions
|
||||||
|
register = evidence['assertion-register']
|
||||||
|
check(set(register)=={'status','source_inventory','artifact_inventory','records','counts','historical_asserts'},
|
||||||
|
'missing register receipt fields')
|
||||||
|
same(register['historical_asserts'],145,'historical assertion count')
|
||||||
|
same(register['status'],'CLASSIFIED; execution status is per-entry','register classification scope')
|
||||||
|
paths = [assertions.HISTORY / n for n in assertions.HISTORICAL_FILES] + [
|
||||||
|
p for p in sorted(HERE.glob('*.py')) if p.name != 'tests_offline.py']
|
||||||
|
required = {str(p.relative_to(assertions.REPO)) for p in paths}
|
||||||
|
check(set(register['source_inventory']) == required, 'incomplete AST source inventory')
|
||||||
|
fresh({str(assertions.REPO / p): v for p,v in register['source_inventory'].items()}, hash_file)
|
||||||
|
artifacts = {str(p) for p in HERE.iterdir() if p.suffix in ('.patch', '.json')}
|
||||||
|
fresh(register['artifact_inventory'], hash_file, artifacts)
|
||||||
|
selected = {n: evidence[n] for n in ('assertion-register', 'test-receipts', 'offline-core-coverage')}
|
||||||
|
coverage = checked_register(encoded(selected))
|
||||||
|
records = register['records']
|
||||||
|
counts = {kind: sum(r['kind'] == kind for r in records) for kind in sorted({r['kind'] for r in records})}
|
||||||
|
same(register['counts'], counts, 'AST counts')
|
||||||
|
same(evidence['assertion-coverage'], coverage, 'assertion-coverage')
|
||||||
|
core = {'model.py', 'ledger.py', 'authorization.py', 'observations.py', 'pixels.py'}
|
||||||
|
unproved = [r['id'] for r in records if Path(r['source']).name in core and
|
||||||
|
r['kind'] == 'checked invariant' and not
|
||||||
|
(r['positive_executed_test_ids'] and r['negative_executed_test_ids'])]
|
||||||
|
same(evidence['offline-core-coverage'], dict(status='PASS' if not unproved else 'FAIL NOT PROVEN', unproved=unproved), 'offline-core-coverage')
|
||||||
|
check(not unproved and coverage['unresolved_pure_invariants'] == [], 'necessary pure coverage unproved')
|
||||||
|
|
||||||
|
|
||||||
|
def make_bindings(evidence, evidence_files=None):
|
||||||
|
"""Canonical content digest supports M0 in memory and binds real receipts.
|
||||||
|
|
||||||
|
WHY: raw file hashes alone cannot bind a caller's mutated parsed object.
|
||||||
|
File hashes remain separate; formatting changes after review also expire it.
|
||||||
|
"""
|
||||||
|
from write_results import REQUIRED
|
||||||
|
result = dict(source_delta={p.name: sha(p) for p in HERE.iterdir() if p.is_file()},
|
||||||
|
evidence_content={n: hashlib.sha256(encoded(evidence[n]).encode()).hexdigest() for n in REQUIRED})
|
||||||
|
if evidence_files is not None:
|
||||||
|
result['evidence_files'] = {n: str(p) for n,p in evidence_files.items()}
|
||||||
|
result['evidence_sha256'] = {n: sha(p) for n,p in evidence_files.items()}
|
||||||
|
else:
|
||||||
|
# Memory-only tests bind canonical bytes, not imaginary evidence files.
|
||||||
|
result['evidence_sha256'] = dict(result['evidence_content'])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def validate_review(evidence, bindings, hash_file):
|
||||||
|
from write_results import REQUIRED
|
||||||
|
check(isinstance(bindings, dict), 'missing final bindings')
|
||||||
|
current = make_bindings(evidence)
|
||||||
|
same(bindings['source_delta'], current['source_delta'], 'review final sources')
|
||||||
|
fresh({str(HERE / n): v for n,v in bindings['source_delta'].items()}, hash_file)
|
||||||
|
same(bindings['evidence_content'], current['evidence_content'], 'review final receipt content')
|
||||||
|
check(set(bindings['evidence_sha256']) == set(REQUIRED), 'missing evidence bindings')
|
||||||
|
if 'evidence_files' in bindings:
|
||||||
|
check(set(bindings['evidence_files']) == set(REQUIRED), 'missing evidence paths')
|
||||||
|
for name in REQUIRED:
|
||||||
|
path = bindings['evidence_files'][name]
|
||||||
|
fresh({path: bindings['evidence_sha256'][name]}, hash_file)
|
||||||
|
same(json.loads(Path(path).read_text()), evidence[name], 'loaded proof ' + name)
|
||||||
|
else:
|
||||||
|
same(bindings['evidence_sha256'], current['evidence_content'], 'memory evidence hashes')
|
||||||
|
review = evidence['independent-review']
|
||||||
|
check(review['status'] == 'ACCEPTED' and review['independent'] is True, 'review not independently ACCEPTED')
|
||||||
|
for key, value in bindings.items():
|
||||||
|
same(review[key], value, 'review not bound to final source/evidence hashes: ' + key)
|
||||||
|
if 'evidence_files' not in bindings:
|
||||||
|
# CONTRACT: only the in-memory positive control may use synthetic
|
||||||
|
# acceptance. The writer always supplies evidence_files and cannot
|
||||||
|
# turn this test receipt into independent publication authority.
|
||||||
|
check(review['scope']=='SYNTHETIC_IN_MEMORY_ONLY','unqualified memory review')
|
||||||
|
return
|
||||||
|
check(review['scope']=='FINAL_OFFLINE_RECEIPT_INTEGRITY','synthetic/incorrect persisted review scope')
|
||||||
|
check(review['reviewer_role'] in ('final-reviewer','reviewer') and
|
||||||
|
isinstance(review['reviewer_agent'],str) and bool(review['reviewer_agent']) and
|
||||||
|
review['read_only'] is True,'missing independent reviewer provenance')
|
||||||
|
fresh({review['report_file']:review['report_sha256']},hash_file)
|
||||||
|
report=Path(review['report_file']).read_text()
|
||||||
|
check('RECEIPT_INTEGRITY_REVIEW=ACCEPTED' in report,'report does not accept final version')
|
||||||
|
commands=review['commands']
|
||||||
|
check(isinstance(commands,list) and bool(commands),'missing executed review commands')
|
||||||
|
for command in commands:
|
||||||
|
check(isinstance(command['argv'],list) and bool(command['argv']) and
|
||||||
|
all(isinstance(a,str) and bool(a) for a in command['argv']) and
|
||||||
|
type(command['exit_code']) is int and command['exit_code']==0,
|
||||||
|
'review command absent/failed')
|
||||||
|
mutations=review['mutations']
|
||||||
|
check(isinstance(mutations,dict) and REVIEW_ATTACKS<=set(mutations),'incomplete independent mutation set')
|
||||||
|
for name in REVIEW_ATTACKS:
|
||||||
|
result=mutations[name]
|
||||||
|
check(result['status']=='INCONCLUSIVE' and isinstance(result['blockers'],list) and
|
||||||
|
bool(result['blockers']) and all(isinstance(b,str) and bool(b) for b in result['blockers']),
|
||||||
|
'independent attack not rejected: '+name)
|
||||||
|
check(isinstance(review['findings'],list) and
|
||||||
|
all(isinstance(f,dict) and f.get('severity') in ('NON_BLOCKING','FUTURE_SCOPE') for f in review['findings']),
|
||||||
|
'material independent finding unresolved')
|
||||||
|
check(isinstance(review['limitations'],list) and bool(review['limitations']) and
|
||||||
|
all(isinstance(s,str) and bool(s) for s in review['limitations']), 'review scope absent')
|
||||||
|
|
@ -20,6 +20,9 @@ from support import save
|
||||||
|
|
||||||
HERE=Path(__file__).resolve().parent
|
HERE=Path(__file__).resolve().parent
|
||||||
RECEIPTS=[]
|
RECEIPTS=[]
|
||||||
|
FIXTURE_SNAPSHOT=None
|
||||||
|
BASELINE_CHECKED=False
|
||||||
|
BOOTSTRAP=False
|
||||||
ACTIVE=None
|
ACTIVE=None
|
||||||
TRACKED={str(p.resolve()) for p in HERE.glob('*.py')}
|
TRACKED={str(p.resolve()) for p in HERE.glob('*.py')}
|
||||||
LINES={}
|
LINES={}
|
||||||
|
|
@ -331,8 +334,8 @@ class Case(unittest.TestCase):
|
||||||
auth['registered_lab']='wrong';f.write_text(json.dumps(auth));self.reject('registered-fresh-lab-required',lambda:authorize(root,f))
|
auth['registered_lab']='wrong';f.write_text(json.dumps(auth));self.reject('registered-fresh-lab-required',lambda:authorize(root,f))
|
||||||
def test_negative_offline_lab_authorization(self):
|
def test_negative_offline_lab_authorization(self):
|
||||||
with tempfile.TemporaryDirectory(prefix='geometry-auth-test-') as tmp:
|
with tempfile.TemporaryDirectory(prefix='geometry-auth-test-') as tmp:
|
||||||
root=Path(tmp);f=root/'auth.json';f.write_text(json.dumps(dict(scope='one-new-static-nested-headless-run',explicit_user_authorization=True,ticket='synthetic-future-unit-test',registered_lab=str(LAB.resolve()))))
|
root=Path(tmp);f=root/'auth.json';f.write_text(json.dumps(dict(scope='one-new-static-nested-headless-run',explicit_user_authorization=True,ticket='synthetic-future-unit-test',registered_lab=str(HISTORICAL.resolve()))))
|
||||||
self.reject('historical-or-offline-lab-forbidden',lambda:authorize(LAB,f))
|
self.reject('historical-or-offline-lab-forbidden',lambda:authorize(HISTORICAL,f))
|
||||||
def test_negative_ledger_sequences(self):
|
def test_negative_ledger_sequences(self):
|
||||||
with tempfile.TemporaryDirectory(prefix='geometry-ledger-test-') as tmp:
|
with tempfile.TemporaryDirectory(prefix='geometry-ledger-test-') as tmp:
|
||||||
p=Path(tmp)/'budget.json';initial_for_offline_test(p);reserve(p,'click');state=json.loads(p.read_text());state['events'][0]['seq']=5
|
p=Path(tmp)/'budget.json';initial_for_offline_test(p);reserve(p,'click');state=json.loads(p.read_text());state['events'][0]['seq']=5
|
||||||
|
|
@ -455,40 +458,41 @@ class Case(unittest.TestCase):
|
||||||
data,recorded=self.exchange(invocation=True);self.assertIsNone(data['ipc_exit'])
|
data,recorded=self.exchange(invocation=True);self.assertIsNone(data['ipc_exit'])
|
||||||
self.assertIn('ipc_error',data);self.assertFalse(data['scientific_cleanup_pass']);self.assertEqual(recorded,[])
|
self.assertIn('ipc_error',data);self.assertFalse(data['scientific_cleanup_pass']);self.assertEqual(recorded,[])
|
||||||
|
|
||||||
|
def test_receipt_fail_closed_empty(self):
|
||||||
|
from write_results import aggregate
|
||||||
|
result=aggregate({},lambda path:None,{})
|
||||||
|
self.assertEqual(result['status'],'INCONCLUSIVE')
|
||||||
|
self.assertTrue(result['blockers'])
|
||||||
|
|
||||||
|
def test_receipt_fail_closed_status_only(self):
|
||||||
|
from write_results import aggregate,REQUIRED
|
||||||
|
result=aggregate({n:{'status':'PASS'} for n in REQUIRED},lambda path:None,{})
|
||||||
|
self.assertEqual(result['status'],'INCONCLUSIVE')
|
||||||
|
self.assertEqual(set(result['markers'].values()),{'INCONCLUSIVE'})
|
||||||
|
|
||||||
def aggregate_fixture(self):
|
def aggregate_fixture(self):
|
||||||
from write_results import REQUIRED,aggregate
|
from write_results import REQUIRED,aggregate
|
||||||
from support import sha
|
from support import sha
|
||||||
evidence={n:json.loads((LAB/'results'/(n+'.json')).read_text()) for n in REQUIRED}
|
from receipt_integrity import make_bindings
|
||||||
# CONTRACT: all acceptance here is a synthetic complete snapshot in memory.
|
# WHY: bootstrap with genuine current preflight receipts, collected
|
||||||
# The real receipts are written only after the entire suite finishes.
|
# before aggregation tests, not forced statuses or obsolete hashes.
|
||||||
evidence['test-receipts']['status']='PASS'
|
root=LAB/'preflight'/'results'
|
||||||
for receipt in evidence['test-receipts']['tests']:receipt['status']='PASS'
|
global FIXTURE_SNAPSHOT
|
||||||
# CONTRACT: this is synthetic independent acceptance in memory only.
|
import pickle,copy
|
||||||
bindings={'source_delta':{'fixture':'synthetic-final-hash'},'evidence_sha256':{'proof':'synthetic-proof-hash'}}
|
if FIXTURE_SNAPSHOT is None:
|
||||||
evidence['independent-review']=dict(status='ACCEPTED',independent=True,**bindings)
|
evidence={n:json.loads((root/(n+'.json')).read_text()) for n in REQUIRED}
|
||||||
# INVARIANT: immutable synthetic hash provider avoids bootstrapping current
|
FIXTURE_SNAPSHOT=(pickle.dumps(evidence),make_bindings(evidence))
|
||||||
# test receipts from the suite that is still producing those receipts.
|
# Separate object graphs for every mutation. The serialization is an
|
||||||
# WHY: source inventories in this synthetic snapshot must describe the
|
# in-memory copy of our own JSON, never untrusted external pickle input.
|
||||||
# same bytes even while the real on-disk register awaits regeneration.
|
evidence=pickle.loads(FIXTURE_SNAPSHOT[0])
|
||||||
evidence['test-receipts']['source_inventory']={n:sha(n) for n in evidence['test-receipts']['source_inventory']}
|
bindings=copy.deepcopy(FIXTURE_SNAPSHOT[1])
|
||||||
evidence['assertion-register']['source_inventory']={n:sha(HERE.parents[2]/n) for n in evidence['assertion-register']['source_inventory']}
|
# CONTRACT: synthetic acceptance exists in this independent memory
|
||||||
hashes={}
|
# snapshot only. It is never persisted as the real review.
|
||||||
for name in ('historical-evidence','client-provenance','test-receipts'):
|
evidence['independent-review']=dict(status='ACCEPTED',independent=True,scope='SYNTHETIC_IN_MEMORY_ONLY',**__import__('copy').deepcopy(bindings))
|
||||||
hashes.update(evidence[name].get('inputs',{}));hashes.update(evidence[name].get('source_inventory',{}))
|
def safe_hash(path):
|
||||||
reg=evidence['assertion-register'];hashes.update({str(HERE.parents[2]/n):v for n,v in reg['source_inventory'].items()});hashes.update(reg['artifact_inventory'])
|
try:return sha(path)
|
||||||
audit=evidence['source-audit'];hashes.update({c['source']:c['sha256'] for c in audit['contracts']})
|
except (OSError,ValueError):return None
|
||||||
hashes[audit['source_version_receipt']]=audit['source_version_sha256']
|
return aggregate,evidence,safe_hash,bindings
|
||||||
for case in evidence['historical-replay']['cases']:
|
|
||||||
hashes.update({str(NESTED/case['case']/n):v for n,v in case['files'].items()})
|
|
||||||
client=evidence['client-provenance'];hashes[str(HERE/'placement.patch')]=client['patch']
|
|
||||||
builds={v['client']:v for v in client['builds']}
|
|
||||||
for command in client['commands']:
|
|
||||||
label=command['label'];argv=command['argv']
|
|
||||||
if label.endswith('-compile') and label[:-8] in builds:
|
|
||||||
build=builds[label[:-8]];source=next(v for v in argv if v.endswith('/'+label[:-8]+'.c'))
|
|
||||||
hashes[source]=build['source'];hashes[argv[argv.index('-o')+1]]=build['binary']
|
|
||||||
hashes.update({str(Path(source).parent/n):v for n,v in client['protocols'].items()})
|
|
||||||
return aggregate,evidence,lambda path:hashes.get(str(path)),bindings
|
|
||||||
|
|
||||||
def test_positive_aggregate_complete_bound(self):
|
def test_positive_aggregate_complete_bound(self):
|
||||||
fn,e,h,b=self.aggregate_fixture();result=fn(e,h,b)
|
fn,e,h,b=self.aggregate_fixture();result=fn(e,h,b)
|
||||||
|
|
@ -576,24 +580,237 @@ for gate in REQUIRED:
|
||||||
current=copy.deepcopy(original);current['evidence_sha256'][gate]='changed-proof'
|
current=copy.deepcopy(original);current['evidence_sha256'][gate]='changed-proof'
|
||||||
result=fn(e,h,current)
|
result=fn(e,h,current)
|
||||||
self.assertEqual(result['status'],'INCONCLUSIVE')
|
self.assertEqual(result['status'],'INCONCLUSIVE')
|
||||||
self.assertTrue(any('review not bound' in x for x in result['blockers']))
|
self.assertTrue(any(x.startswith('independent-review:') for x in result['blockers']))
|
||||||
setattr(Case,'test_negative_aggregate_'+gate.replace('-','_')+'_stale_review_binding',test)
|
setattr(Case,'test_negative_aggregate_'+gate.replace('-','_')+'_stale_review_binding',test)
|
||||||
|
|
||||||
|
|
||||||
|
def integrity_negative(self, label, mutate, group, category):
|
||||||
|
import copy
|
||||||
|
from receipt_integrity import make_bindings
|
||||||
|
fn,e,h,b=self.aggregate_fixture()
|
||||||
|
global BASELINE_CHECKED
|
||||||
|
if not BOOTSTRAP and not BASELINE_CHECKED:
|
||||||
|
self.assertEqual(fn(e,h,b)['status'],'READY_FOR_NEW_RUNTIME','mutation baseline must be complete')
|
||||||
|
BASELINE_CHECKED=True
|
||||||
|
mutate(e)
|
||||||
|
# Rebind the synthetic memory-only review to the mutation so the semantic
|
||||||
|
# checker itself must reject it; stale-review rejection alone is inadequate.
|
||||||
|
if group!='independent-review':
|
||||||
|
import hashlib
|
||||||
|
from receipt_integrity import encoded
|
||||||
|
b=copy.deepcopy(b)
|
||||||
|
b['evidence_content'][group]=hashlib.sha256(encoded(e[group]).encode()).hexdigest()
|
||||||
|
b['evidence_sha256'][group]=b['evidence_content'][group]
|
||||||
|
e['independent-review']=dict(status='ACCEPTED',independent=True,scope='SYNTHETIC_IN_MEMORY_ONLY',**copy.deepcopy(b))
|
||||||
|
r=fn(e,h,b)
|
||||||
|
self.assertEqual(r['status'],'INCONCLUSIVE',label)
|
||||||
|
self.assertTrue(any(x.startswith(group+':') for x in r['blockers']),(label,r['blockers']))
|
||||||
|
for marker,dependencies in r['marker_scope'].items():
|
||||||
|
if group in dependencies:self.assertEqual(r['markers'][marker],'INCONCLUSIVE',label)
|
||||||
|
MUTATIONS.append(dict(label=label,category=category,gate=group,status=r['status'],blockers=r['blockers'],markers=r['markers']))
|
||||||
|
|
||||||
|
|
||||||
|
MUTATIONS=[]
|
||||||
|
def original_R02(self, name):
|
||||||
|
def mutate(e):
|
||||||
|
if name=='A':e['historical-replay']['cases'][0]['input_correlation']={'status':'PASS'}
|
||||||
|
elif name=='B':
|
||||||
|
for k in ('content','PNG_bbox','count','visible_intersection'):e['rendered'][k]=None
|
||||||
|
else:e['popup-root']['cases']=[{} for _ in range(9)]
|
||||||
|
integrity_negative(self,'R02-'+name,mutate,{'A':'historical-replay','B':'rendered','C':'popup-root'}[name],'original')
|
||||||
|
|
||||||
|
for letter in 'ABC':
|
||||||
|
def test(self,letter=letter):original_R02(self,letter)
|
||||||
|
setattr(Case,'test_integrity_R02_'+letter,test)
|
||||||
|
|
||||||
|
|
||||||
|
def essential_paths(evidence):
|
||||||
|
"""Required fields, including scenario-specific nested original facts.
|
||||||
|
|
||||||
|
All root/nested observations are inspected in all nine cases. Empty
|
||||||
|
failed_lines/contracts and scenario nulls are legitimate and not mutated
|
||||||
|
into the same value; deleting their schema key still must be rejected.
|
||||||
|
"""
|
||||||
|
for gate in REQUIRED:
|
||||||
|
for key in evidence[gate]:yield gate,[key]
|
||||||
|
for gate in ('historical-replay','popup-root','popup-nested'):
|
||||||
|
for index,row in enumerate(evidence[gate]['cases']):
|
||||||
|
def walk(value,path):
|
||||||
|
if isinstance(value,dict):
|
||||||
|
for k,v in value.items():
|
||||||
|
yield path+[k]
|
||||||
|
# File inventories are complete mappings, not samples.
|
||||||
|
yield from walk(v,path+[k])
|
||||||
|
elif isinstance(value,list) and value and isinstance(value[0],dict):
|
||||||
|
for i,v in enumerate(value):yield from walk(v,path+[i])
|
||||||
|
for path in walk(row,['cases',index]):yield gate,path
|
||||||
|
|
||||||
|
|
||||||
|
def access(e,gate,path):
|
||||||
|
node=e[gate]
|
||||||
|
for part in path[:-1]:node=node[part]
|
||||||
|
return node,path[-1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_deletions(self):
|
||||||
|
# WHY: bulk mutation receipts prove returned verdicts, not line coverage.
|
||||||
|
# Individual R02/positive tests keep tracing; suppressing tracing here
|
||||||
|
# avoids charging repeated read/hash loops as scientific branch proof.
|
||||||
|
sys.settrace(None)
|
||||||
|
_,e,_,_=self.aggregate_fixture()
|
||||||
|
for gate,path in essential_paths(e):
|
||||||
|
def mutate(d,gate=gate,path=path):
|
||||||
|
parent,key=access(d,gate,path);del parent[key]
|
||||||
|
integrity_negative(self,gate+'/'+str(path),mutate,gate,'deletion')
|
||||||
|
|
||||||
|
|
||||||
|
def test_nullifications(self):
|
||||||
|
sys.settrace(None)
|
||||||
|
_,e,_,_=self.aggregate_fixture()
|
||||||
|
for gate,path in essential_paths(e):
|
||||||
|
parent,key=access(e,gate,path);original=parent[key]
|
||||||
|
for value in (None,{},[], ''):
|
||||||
|
if type(value) is type(original) and value==original:continue
|
||||||
|
def mutate(d,gate=gate,path=path,value=value):
|
||||||
|
parent,key=access(d,gate,path);parent[key]=value
|
||||||
|
integrity_negative(self,gate+'/'+str(path)+'='+repr(value),mutate,gate,'nullification')
|
||||||
|
|
||||||
|
|
||||||
|
def test_contradictions(self):
|
||||||
|
sys.settrace(None)
|
||||||
|
attacks=[('rendered',['content',3],320),('rendered',['content',1],0),
|
||||||
|
('rendered',['PNG_bbox',0],483),('rendered',['count'],182215),
|
||||||
|
('rendered',['count'],True),('applied',['scroll'],161.0),
|
||||||
|
('applied',['globalclip',0],0),('applied',['titlebar'],0),
|
||||||
|
('native-shm',['stride'],1280),('native-shm',['buffer'],True),
|
||||||
|
('xdg-configure',['assigned_ACK'],20),('positioner',['flags'],1)]
|
||||||
|
attacks += [('assertion-register',['records',0,'test_status'],None),
|
||||||
|
('assertion-register',['records',0,'domain'],'invented classification'),
|
||||||
|
('assertion-register',['historical_asserts'],True),
|
||||||
|
('test-receipts',['tests',0,'executed_lines'],[]),
|
||||||
|
('test-receipts',['tests',0,'id'],'__main__.Case.test_fabricated')]
|
||||||
|
for index in range(9):
|
||||||
|
for field,value in [('owner',999),('workspace',999),('origin',[0,0]),('A',[0,0,300,170]),('B',[0,0,300,130]),('case','unknown')]:
|
||||||
|
attacks.append(('historical-replay',['cases',index,field],value))
|
||||||
|
attacks += [('historical-replay',['cases',index,'protocol','grabs',1,'parent'],'TOPLEVEL'),
|
||||||
|
('historical-replay',['cases',index,'protocol','grabs',1,'serial'],55),
|
||||||
|
('historical-replay',['cases',index,'input_correlation','buttons',0,'target'],'POPUP_B'),
|
||||||
|
('historical-replay',['cases',index,'input_correlation','buttons',0,'serial'],999),
|
||||||
|
('historical-replay',['cases',index,'input_correlation','buttons',1,'state'],1),
|
||||||
|
('historical-replay',['cases',index,'input_correlation','callbacks',-1,'local'],[99999.0,1.0]),
|
||||||
|
('historical-replay',['cases',index,'input_correlation','actions',0,'motion_msec'],99999),
|
||||||
|
('popup-root',['cases',index,'origin'],[0,0]),
|
||||||
|
('popup-root',['cases',index,'clip'],[0,0,1,1]),
|
||||||
|
('popup-nested',['cases',index,'B'],[0,0,300,130]),
|
||||||
|
('popup-nested',['cases',index,'protocol','grabs',1,'ack'],999)]
|
||||||
|
for gate,path,value in attacks:
|
||||||
|
def mutate(d,gate=gate,path=path,value=value):
|
||||||
|
parent,key=access(d,gate,path);parent[key]=value
|
||||||
|
integrity_negative(self,gate+'/'+str(path),mutate,gate,'contradiction')
|
||||||
|
for gate in ('historical-replay','popup-root','popup-nested'):
|
||||||
|
integrity_negative(self,gate+' duplicated identity',lambda d,gate=gate:d[gate]['cases'].__setitem__(1,__import__('copy').deepcopy(d[gate]['cases'][0])),gate,'contradiction')
|
||||||
|
|
||||||
|
|
||||||
|
def test_freshness(self):
|
||||||
|
import copy
|
||||||
|
fn,e,h,b=self.aggregate_fixture()
|
||||||
|
from receipt_integrity import make_bindings
|
||||||
|
from support import sha
|
||||||
|
# A correct source hash replaced by the hash of its own mutated file must
|
||||||
|
# still lose the previously signed acceptance.
|
||||||
|
for key in ('source_delta','evidence_sha256','evidence_content'):
|
||||||
|
current=copy.deepcopy(b);first=next(iter(current[key]));current[key][first]='0'*64
|
||||||
|
r=fn(e,h,current);self.assertEqual(r['status'],'INCONCLUSIVE');self.assertTrue(r['blockers'])
|
||||||
|
MUTATIONS.append(dict(label='stale '+key,category='freshness',status=r['status'],blockers=r['blockers']))
|
||||||
|
for gate in REQUIRED:
|
||||||
|
d=copy.deepcopy(e);d[gate]={};current=make_bindings(d)
|
||||||
|
# Old acceptance, even with fresh current bindings, is not reusable.
|
||||||
|
r=fn(d,h,current);self.assertEqual(r['status'],'INCONCLUSIVE')
|
||||||
|
self.assertTrue(any(x.startswith('independent-review:') for x in r['blockers']))
|
||||||
|
for key in ('status','independent','scope','source_delta','evidence_sha256','evidence_content'):
|
||||||
|
for value in (None,{},[], ''):
|
||||||
|
integrity_negative(self,'review '+key+'='+repr(value),lambda d,key=key,value=value:d['independent-review'].__setitem__(key,value),'independent-review','freshness')
|
||||||
|
for file in (str(HERE/'placement.patch'),str(HERE/'receipt_integrity.py'),next(iter(e['historical-evidence']['inputs']))):
|
||||||
|
r=fn(e,lambda p,file=file:None if str(p)==file else h(p),b)
|
||||||
|
self.assertEqual(r['status'],'INCONCLUSIVE');self.assertTrue(r['blockers'])
|
||||||
|
MUTATIONS.append(dict(label='missing '+file,category='freshness',status=r['status'],blockers=r['blockers']))
|
||||||
|
|
||||||
|
|
||||||
|
def test_omissions(self):
|
||||||
|
fn,e,h,b=self.aggregate_fixture()
|
||||||
|
self.assertIsNone(e['popup-root']['cases'][4]['clip'])
|
||||||
|
self.assertIsNone(e['popup-nested']['cases'][0]['standard'])
|
||||||
|
self.assertIsNone(e['popup-nested']['cases'][2]['dismissal'])
|
||||||
|
self.assertIsNone(e['historical-replay']['cases'][0]['colors']['right']['POPUP_B']['bbox'])
|
||||||
|
self.assertEqual(e['historical-replay']['cases'][0]['colors']['right']['POPUP_B']['count'],0)
|
||||||
|
self.assertEqual(fn(e,h,b)['status'],'READY_FOR_NEW_RUNTIME')
|
||||||
|
|
||||||
|
|
||||||
|
def test_writer(self):
|
||||||
|
import contextlib,io,copy
|
||||||
|
from write_results import write,aggregate
|
||||||
|
from receipt_integrity import make_bindings
|
||||||
|
fn,e,h,b=self.aggregate_fixture()
|
||||||
|
# CONTRACT: no synthetic acceptance is persisted, even in the writer test.
|
||||||
|
e['independent-review']={'status':'NOT RUN','independent':False}
|
||||||
|
with tempfile.TemporaryDirectory(prefix='mosaic-real-writer-') as tmp:
|
||||||
|
root=Path(tmp);(root/'results').mkdir()
|
||||||
|
for name,data in e.items():save(root,name,data)
|
||||||
|
current=make_bindings(e,{n:root/'results'/(n+'.json') for n in REQUIRED})
|
||||||
|
expected=aggregate(e,h,current)
|
||||||
|
with contextlib.redirect_stdout(io.StringIO()):observed=write(root)
|
||||||
|
self.assertEqual(observed['status'],expected['status']);self.assertEqual(observed['markers'],expected['markers'])
|
||||||
|
e['rendered']['count']=None;save(root,'rendered',e['rendered'])
|
||||||
|
with contextlib.redirect_stdout(io.StringIO()):observed=write(root)
|
||||||
|
self.assertEqual(observed['status'],'INCONCLUSIVE')
|
||||||
|
self.assertEqual(observed['markers']['STATIC_NESTED_SHM_RENDER_GEOMETRY_REPLAY'],'INCONCLUSIVE')
|
||||||
|
self.assertTrue(any(x.startswith('rendered:') for x in observed['blockers']))
|
||||||
|
# CONTRACT B-01: decoder exhaustion must invalidate persisted READY,
|
||||||
|
# not merely raise before publication. The fake prior marker is an
|
||||||
|
# adversarial receipt in this test-owned temp LAB, not signed review.
|
||||||
|
prior={'status':'READY_FOR_NEW_RUNTIME','marker':'SWAYFX_MOSAIC_STATIC_NESTED_GEOMETRY_OFFLINE_GATE=READY_FOR_NEW_RUNTIME'}
|
||||||
|
save(root,'runner-readiness',prior);save(root,'offline-gate',prior)
|
||||||
|
(root/'results/rendered.json').write_text('['*100000+'0'+']'*100000)
|
||||||
|
with contextlib.redirect_stdout(io.StringIO()):observed=write(root)
|
||||||
|
self.assertEqual(observed['status'],'INCONCLUSIVE')
|
||||||
|
self.assertTrue(any(x.startswith('rendered:') for x in observed['blockers']))
|
||||||
|
for name in ('runner-readiness','offline-gate'):
|
||||||
|
persisted=json.loads((root/'results'/(name+'.json')).read_text())
|
||||||
|
self.assertEqual(persisted['status'],'INCONCLUSIVE')
|
||||||
|
self.assertEqual(persisted['markers']['STATIC_NESTED_SHM_RENDER_GEOMETRY_REPLAY'],'INCONCLUSIVE')
|
||||||
|
save(LAB,'writer-entrypoint-test',dict(status='PASS',aggregate_source=str(Path(aggregate.__code__.co_filename)),mock=False,synthetic_review_persisted=False,invalid=observed['blockers']))
|
||||||
|
|
||||||
|
|
||||||
|
Case.test_integrity_deletions=test_deletions
|
||||||
|
Case.test_integrity_nullifications=test_nullifications
|
||||||
|
Case.test_integrity_contradictions=test_contradictions
|
||||||
|
Case.test_integrity_freshness=test_freshness
|
||||||
|
Case.test_integrity_legitimate_omissions=test_omissions
|
||||||
|
Case.test_integrity_writer=test_writer
|
||||||
|
|
||||||
|
|
||||||
class Result(unittest.TextTestResult):
|
class Result(unittest.TextTestResult):
|
||||||
def addSuccess(self,test):
|
def addSuccess(self,test):
|
||||||
super().addSuccess(test);RECEIPTS.append(dict(id=test.id(),status='PASS',mode='negative' if '.test_negative_' in test.id() else 'positive',executed_lines=sorted(LINES.get(test.id(),set())),failed_lines=sorted(FAILED.get(test.id(),set())),contracts=[{'contract':c,'pass':v} for c,v in sorted(CONTRACTS.get(test.id(),set()))]))
|
super().addSuccess(test);RECEIPTS.append(dict(id=test.id(),status='PASS',mode='negative' if '.test_negative_' in test.id() else 'positive',executed_lines=sorted(LINES.get(test.id(),set())),failed_lines=sorted(FAILED.get(test.id(),set())),contracts=[{'contract':c,'pass':v} for c,v in sorted(CONTRACTS.get(test.id(),set()))]));sys.settrace(trace)
|
||||||
def addFailure(self,test,err):
|
def addFailure(self,test,err):
|
||||||
super().addFailure(test,err);RECEIPTS.append(dict(id=test.id(),status='FAIL',error=str(err[1])))
|
super().addFailure(test,err);RECEIPTS.append(dict(id=test.id(),status='FAIL',error=str(err[1])));sys.settrace(trace)
|
||||||
def addError(self,test,err):
|
def addError(self,test,err):
|
||||||
super().addError(test,err);RECEIPTS.append(dict(id=test.id(),status='FAIL',error=str(err[1])))
|
super().addError(test,err);RECEIPTS.append(dict(id=test.id(),status='FAIL',error=str(err[1])));sys.settrace(trace)
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
parser=argparse.ArgumentParser();parser.add_argument('lab',type=Path);args=parser.parse_args();LAB=args.lab
|
parser=argparse.ArgumentParser();parser.add_argument('lab',type=Path);parser.add_argument('--preflight',action='store_true');parser.add_argument('--negative-preflight',action='store_true');args=parser.parse_args();LAB=args.lab
|
||||||
sys.settrace(trace)
|
sys.settrace(trace)
|
||||||
result=unittest.TextTestRunner(verbosity=2,resultclass=Result).run(unittest.defaultTestLoader.loadTestsFromTestCase(Case))
|
suite=unittest.defaultTestLoader.loadTestsFromTestCase(Case)
|
||||||
|
if args.preflight:suite=unittest.TestSuite(t for t in suite if 'aggregate' not in t.id() and 'integrity' not in t.id())
|
||||||
|
if args.negative_preflight:suite=unittest.TestSuite(t for t in suite if t._testMethodName not in ('test_positive_aggregate_complete_bound','test_integrity_legitimate_omissions'))
|
||||||
|
BOOTSTRAP=args.negative_preflight
|
||||||
|
result=unittest.TextTestRunner(verbosity=2,resultclass=Result).run(suite)
|
||||||
sys.settrace(None)
|
sys.settrace(None)
|
||||||
save(LAB,'test-receipts',dict(source_inventory={str(p):__import__('hashlib').sha256(p.read_bytes()).hexdigest() for p in HERE.iterdir() if p.suffix in ('.py','.patch','.json')},status='PASS' if result.wasSuccessful() else 'FAIL',tests=RECEIPTS))
|
save(LAB,'test-receipts',dict(source_inventory={str(p):__import__('hashlib').sha256(p.read_bytes()).hexdigest() for p in HERE.iterdir() if p.suffix in ('.py','.patch','.json')},status='PASS' if result.wasSuccessful() else 'FAIL',tests=RECEIPTS))
|
||||||
save(LAB,'positive',{'tests':[r for r in RECEIPTS if r.get('mode')=='positive']})
|
save(LAB,'positive',{'tests':[r for r in RECEIPTS if r.get('mode')=='positive']})
|
||||||
save(LAB,'negative',{'tests':[r for r in RECEIPTS if r.get('mode')=='negative']})
|
save(LAB,'negative',{'tests':[r for r in RECEIPTS if r.get('mode')=='negative']})
|
||||||
|
if not args.preflight:
|
||||||
|
save(LAB,'aggregate-negative',{'status':'PASS' if result.wasSuccessful() else 'FAIL', 'mutations':MUTATIONS})
|
||||||
|
for category in ('deletion','nullification','contradiction','freshness','original'):
|
||||||
|
save(LAB,category+'-tests',{'status':'PASS' if result.wasSuccessful() else 'FAIL','mutations':[r for r in MUTATIONS if r['category']==category]})
|
||||||
raise SystemExit(0 if result.wasSuccessful() else 1)
|
raise SystemExit(0 if result.wasSuccessful() else 1)
|
||||||
|
|
|
||||||
|
|
@ -20,71 +20,48 @@ def aggregate(evidence,hash_file,bindings):
|
||||||
WHY: no author test or successful compile can substitute for another gate.
|
WHY: no author test or successful compile can substitute for another gate.
|
||||||
Bindings describe the exact final evidence/source bytes reviewed independently.
|
Bindings describe the exact final evidence/source bytes reviewed independently.
|
||||||
"""
|
"""
|
||||||
|
from receipt_integrity import (validate_historical, validate_source_audit,
|
||||||
|
validate_client, validate_register, validate_tests, validate_review, historical_inputs, fresh)
|
||||||
failures={}
|
failures={}
|
||||||
def need(name,ok,reason):
|
def need(name,ok,reason):
|
||||||
if not ok:failures.setdefault(name,[]).append(reason)
|
if not ok:failures.setdefault(name,[]).append(reason)
|
||||||
def fresh(mapping):
|
def guarded(name, validator):
|
||||||
return bool(mapping) and all(hash_file(path)==digest for path,digest in mapping.items())
|
# CONTRACT: invalid/missing evidence degrades its gate, never crashes
|
||||||
|
# the writer or becomes a compositor/SceneFX architectural failure.
|
||||||
|
try:
|
||||||
|
validator()
|
||||||
|
except (OSError, ValueError, TypeError, KeyError, IndexError, AttributeError,
|
||||||
|
AssertionError, RuntimeError, StopIteration) as error:
|
||||||
|
need(name,False,str(error) or type(error).__name__)
|
||||||
|
if not isinstance(evidence,dict):evidence={}
|
||||||
for name in REQUIRED:
|
for name in REQUIRED:
|
||||||
d=evidence.get(name)
|
d=evidence.get(name)
|
||||||
need(name,isinstance(d,dict) and bool(d),'missing evidence')
|
need(name,isinstance(d,dict) and bool(d),'missing/malformed evidence')
|
||||||
if not isinstance(d,dict):continue
|
if not isinstance(d,dict):continue
|
||||||
status=d.get('status','')
|
status=d.get('status')
|
||||||
need(name,status=='PASS' or status.startswith('PASS ')
|
need(name,isinstance(status,str) and (status=='PASS' or status.startswith('PASS ')
|
||||||
or name=='assertion-register' and status=='CLASSIFIED; execution status is per-entry','gate not PASS')
|
or name=='assertion-register' and status=='CLASSIFIED; execution status is per-entry'),'gate not PASS')
|
||||||
def record(name):return evidence.get(name) or {}
|
input_error=None
|
||||||
for name in ('native-shm','xdg-configure','applied','rendered','positioner'):
|
try:
|
||||||
fields={'native-shm':('size','buffer','stride','format'), 'xdg-configure':('toplevel','initial_ACK','assigned_ACK'),
|
inputs=historical_inputs()
|
||||||
'applied':('owner','workspace','scene','window','titlebar','globalclip'),
|
fresh(inputs,hash_file)
|
||||||
'rendered':('content','PNG_bbox','count','visible_intersection'),
|
except (OSError,ValueError,TypeError,KeyError,AssertionError) as error:
|
||||||
'positioner':('flags','A','B')}[name]
|
inputs=None;input_error=str(error) or type(error).__name__
|
||||||
need(name,all(k in record(name) for k in fields),'incomplete geometry proof')
|
for name in ('native-shm','xdg-configure','applied','rendered','positioner',
|
||||||
need('historical-evidence',fresh(record('historical-evidence').get('inputs',{})),'stale/missing historical inputs')
|
'historical-evidence','historical-replay','popup-root','popup-nested'):
|
||||||
cases=record('historical-replay').get('cases',[])
|
if input_error:need(name,False,input_error)
|
||||||
expected={'run-private_mosaic-crossing-b_cross','run-private_mosaic-crossing-both_cross',
|
else:guarded(name,lambda name=name:validate_historical(name,evidence.get(name),hash_file,inputs))
|
||||||
'run-private_mosaic-toggle-b_cross','run-private_mosaic-outside-visible',
|
# CONTRACT: after a failed prerequisite, unchecked downstream gates are
|
||||||
'run-control-crossing-b_cross','run-control-crossing-both_cross','run-control-outside-visible',
|
# INCONCLUSIVE too. This bounds work on invalid input without granting PASS.
|
||||||
'run-private_mosaic-close_b-visible','run-control-close_b-visible'}
|
def downstream(name,validator):
|
||||||
need('historical-replay',len(cases)==9 and {c.get('case') for c in cases}==expected,'required nine cases incomplete')
|
if failures:need(name,False,'not qualified after failed prerequisite')
|
||||||
for c in cases:
|
else:guarded(name,validator)
|
||||||
need('historical-replay',c.get('status')=='PASS historical sampled replay' and c.get('input_correlation',{}).get('status')=='PASS','case/input proof incomplete')
|
downstream('source-audit',lambda:validate_source_audit(evidence.get('source-audit'),hash_file))
|
||||||
need('historical-replay',fresh({str(__import__('replay').NESTED/c.get('case','')/n):v for n,v in c.get('files',{}).items()}),'stale case files')
|
downstream('client-provenance',lambda:validate_client(evidence.get('client-provenance'),hash_file))
|
||||||
for name in ('popup-root','popup-nested'):
|
downstream('test-receipts',lambda:validate_tests(evidence.get('test-receipts'),hash_file))
|
||||||
need(name,len(record(name).get('cases',[]))==9,'incomplete popup proof')
|
for name in ('assertion-register','assertion-coverage','offline-core-coverage'):
|
||||||
audit=record('source-audit');contracts=audit.get('contracts',[])
|
downstream(name,lambda name=name:validate_register(name,evidence,hash_file))
|
||||||
need('source-audit',len(contracts)==17 and all(c.get('claim') and c.get('excerpts') and hash_file(c.get('source',''))==c.get('sha256') for c in contracts),'incomplete/stale source contracts')
|
downstream('independent-review',lambda:validate_review(evidence,bindings,hash_file))
|
||||||
need('source-audit',bool(audit.get('pins')) and hash_file(audit.get('source_version_receipt',''))==audit.get('source_version_sha256') and bool(audit.get('source_version_sha256')),'stale pinned receipt')
|
|
||||||
client=record('client-provenance');commands=client.get('commands',[])
|
|
||||||
need('client-provenance',fresh(client.get('inputs',{})),'stale client sources')
|
|
||||||
need('client-provenance',all(client.get(k) for k in ('patch','adapted_nested','protocols','protocol_comparison','builds')),'incomplete provenance')
|
|
||||||
needed={n+'-'+mode for n in ('nested-client','pointer-daemon','static-reference') for mode in ('syntax','compile')}
|
|
||||||
need('client-provenance',needed<={c.get('label') for c in commands} and all(c.get('exit')==0 for c in commands),'C17 commands missing/failed')
|
|
||||||
for command in commands:
|
|
||||||
if command.get('label') in needed:need('client-provenance','-std=c17' in command.get('argv',[]) and '-Werror' in command.get('argv',[]),'C17 flags incomplete')
|
|
||||||
need('client-provenance',hash_file(str(HERE/'placement.patch'))==client.get('patch'),'stale placement patch')
|
|
||||||
builds={c.get('client'):c for c in client.get('builds',[])}
|
|
||||||
need('client-provenance',set(builds)=={'nested-client','pointer-daemon','static-reference'},'missing client builds')
|
|
||||||
for command in commands:
|
|
||||||
label=command.get('label','');argv=command.get('argv',[])
|
|
||||||
if label.endswith('-compile') and label[:-8] in builds:
|
|
||||||
build=builds[label[:-8]]
|
|
||||||
output=argv[argv.index('-o')+1] if '-o' in argv else ''
|
|
||||||
source=next((v for v in argv if v.endswith('/'+label[:-8]+'.c')),'')
|
|
||||||
need('client-provenance',bool(output) and hash_file(output)==build.get('binary') and bool(source) and hash_file(source)==build.get('source'),'stale built client/source')
|
|
||||||
directory=Path(source).parent
|
|
||||||
need('client-provenance',all(hash_file(str(directory/n))==v for n,v in client.get('protocols',{}).items()),'stale generated protocols')
|
|
||||||
register=record('assertion-register');inventory=register.get('source_inventory',{})
|
|
||||||
need('assertion-register',fresh({str(HERE.parents[2]/p):v for p,v in inventory.items()}) and fresh(register.get('artifact_inventory',{})),'stale inventory')
|
|
||||||
need('assertion-register',register.get('historical_asserts')==145 and bool(register.get('records')),'incomplete register')
|
|
||||||
coverage=record('assertion-coverage')
|
|
||||||
need('assertion-coverage',coverage.get('status')=='PASS' and coverage.get('historical_asserts')==145 and coverage.get('entries')==len(register.get('records',[])) and coverage.get('unresolved_pure_invariants')==[],'coverage incomplete')
|
|
||||||
need('offline-core-coverage',record('offline-core-coverage').get('unproved')==[],'core unproved')
|
|
||||||
tests=record('test-receipts');receipts=tests.get('tests',[])
|
|
||||||
need('test-receipts',fresh(tests.get('source_inventory',{})),'stale test sources')
|
|
||||||
need('test-receipts',bool(receipts) and all(t.get('status')=='PASS' for t in receipts) and len({t.get('id') for t in receipts})==len(receipts),'missing/failed test receipts')
|
|
||||||
review=record('independent-review')
|
|
||||||
need('independent-review',review.get('status')=='ACCEPTED' and review.get('independent') is True,'review not independently ACCEPTED')
|
|
||||||
need('independent-review',bool(bindings.get('source_delta')) and bool(bindings.get('evidence_sha256')) and all(review.get(k)==v for k,v in bindings.items()),'review not bound to final source/evidence hashes')
|
|
||||||
groups={'STATIC_NESTED_SHM_RENDER_GEOMETRY_REPLAY':('native-shm','applied','rendered','historical-evidence'),
|
groups={'STATIC_NESTED_SHM_RENDER_GEOMETRY_REPLAY':('native-shm','applied','rendered','historical-evidence'),
|
||||||
'STATIC_NESTED_XDG_GEOMETRY_AUDIT':('xdg-configure','positioner','historical-replay','popup-root','popup-nested','source-audit','client-provenance'),
|
'STATIC_NESTED_XDG_GEOMETRY_AUDIT':('xdg-configure','positioner','historical-replay','popup-root','popup-nested','source-audit','client-provenance'),
|
||||||
'STATIC_NESTED_ASSERTION_COVERAGE':('assertion-register','assertion-coverage','offline-core-coverage'),
|
'STATIC_NESTED_ASSERTION_COVERAGE':('assertion-register','assertion-coverage','offline-core-coverage'),
|
||||||
|
|
@ -99,16 +76,25 @@ def write(lab):
|
||||||
results=lab/'results'
|
results=lab/'results'
|
||||||
def read(name):
|
def read(name):
|
||||||
path=results/(name+'.json')
|
path=results/(name+'.json')
|
||||||
return json.loads(path.read_text()) if path.exists() else {}
|
try:return json.loads(path.read_text()) if path.exists() else {}
|
||||||
|
# WHY: a decoder-depth failure must not leave previous READY artifacts
|
||||||
|
# authoritative. CONTRACT: malformed proof reaches the same aggregate
|
||||||
|
# as missing proof, which publishes explicit INCONCLUSIVE markers.
|
||||||
|
except (OSError,ValueError,RecursionError):return {}
|
||||||
aliases={'native-shm-geometry':'native-shm','xdg-configure-geometry':'xdg-configure','applied-content-geometry':'applied','rendered-paint-geometry':'rendered','popup-positioner-audit':'positioner','historical-popup-replay':'historical-replay','root-clip-model':'popup-root','nested-clip-model':'popup-nested','positive-tests':'positive','negative-tests':'negative'}
|
aliases={'native-shm-geometry':'native-shm','xdg-configure-geometry':'xdg-configure','applied-content-geometry':'applied','rendered-paint-geometry':'rendered','popup-positioner-audit':'positioner','historical-popup-replay':'historical-replay','root-clip-model':'popup-root','nested-clip-model':'popup-nested','positive-tests':'positive','negative-tests':'negative'}
|
||||||
for name,source in aliases.items():save(lab,name,read(source))
|
for name,source in aliases.items():save(lab,name,read(source))
|
||||||
coverage=read('assertion-coverage');tests=read('test-receipts');core=read('offline-core-coverage')
|
coverage=read('assertion-coverage');tests=read('test-receipts');core=read('offline-core-coverage')
|
||||||
|
coverage=coverage if isinstance(coverage,dict) else {}
|
||||||
|
tests=tests if isinstance(tests,dict) else {}
|
||||||
reviewfile=results/'independent-review.json'
|
reviewfile=results/'independent-review.json'
|
||||||
review=read('independent-review') if reviewfile.exists() else {'status':'NOT RUN','independent':False}
|
review=read('independent-review') if reviewfile.exists() else {'status':'NOT RUN','independent':False}
|
||||||
evidence={name:read(name) for name in REQUIRED}
|
evidence={name:read(name) for name in REQUIRED}
|
||||||
evidence['independent-review']=review
|
evidence['independent-review']=review
|
||||||
source_delta={p.name:sha(p) for p in HERE.iterdir() if p.is_file()}
|
from receipt_integrity import make_bindings
|
||||||
bindings=dict(source_delta=source_delta,evidence_sha256={name:sha(results/(name+'.json')) for name in REQUIRED if (results/(name+'.json')).exists()})
|
try:
|
||||||
|
bindings=make_bindings(evidence,{name:results/(name+'.json') for name in REQUIRED})
|
||||||
|
except (OSError,ValueError,TypeError,KeyError,RecursionError):
|
||||||
|
bindings={} # Missing/malformed proof cannot carry accepted bindings.
|
||||||
def safe_hash(path):
|
def safe_hash(path):
|
||||||
try:return sha(path)
|
try:return sha(path)
|
||||||
except (OSError,ValueError):return None
|
except (OSError,ValueError):return None
|
||||||
|
|
@ -117,7 +103,10 @@ def write(lab):
|
||||||
save(lab,'popup-geometry-model',dict(status=markers['STATIC_NESTED_XDG_GEOMETRY_AUDIT'],scope='offline typed model and sampled historical replay; new runtime NOT TESTED',root=read('popup-root'),nested=read('popup-nested'),prediction=read('positioner'),source='source-audit.json',native_input='Opening click must lie in actual native surface bounds; destination scaling alone is insufficient'))
|
save(lab,'popup-geometry-model',dict(status=markers['STATIC_NESTED_XDG_GEOMETRY_AUDIT'],scope='offline typed model and sampled historical replay; new runtime NOT TESTED',root=read('popup-root'),nested=read('popup-nested'),prediction=read('positioner'),source='source-audit.json',native_input='Opening click must lie in actual native surface bounds; destination scaling alone is insufficient'))
|
||||||
readiness=dict(status=status,marker='SWAYFX_MOSAIC_STATIC_NESTED_GEOMETRY_OFFLINE_GATE='+status,markers=markers,marker_scope=gates['marker_scope'],review_bindings=bindings,blockers=blockers,runtime='NOT TESTED',architectural_conclusion='UNDECIDED',fixture_only=True,current_ticket_runtime_authorized=False,runtime_budget_initialized=False,independent_review=review)
|
readiness=dict(status=status,marker='SWAYFX_MOSAIC_STATIC_NESTED_GEOMETRY_OFFLINE_GATE='+status,markers=markers,marker_scope=gates['marker_scope'],review_bindings=bindings,blockers=blockers,runtime='NOT TESTED',architectural_conclusion='UNDECIDED',fixture_only=True,current_ticket_runtime_authorized=False,runtime_budget_initialized=False,independent_review=review)
|
||||||
save(lab,'runner-readiness',readiness);save(lab,'offline-gate',readiness)
|
save(lab,'runner-readiness',readiness);save(lab,'offline-gate',readiness)
|
||||||
save(lab,'summary',dict(status=status,markers=markers,tests=len(tests.get('tests',[])),coverage=coverage,core=core,historical_cases=len(read('historical-replay').get('cases',[])),runtime_runs=0,new_popups=0,new_grabs=0,new_captures=0,new_camera_operations=0,runtime_budget_initialized=False,production_changes=False,source_delta={p.name:sha(p) for p in HERE.iterdir() if p.is_file()},manifest='UNSEALED; parent review required',next='independent review of final fixture/register/evidence; separate future authorization required for runtime',limitations=['atomic transaction-generation/native-buffer-frame identity NOT PROVEN','new static popup crossing/grab/input/standard NOT TESTED','vertical/scaled/rotated/migration/full damage NOT TESTED','production cross-output viewport NOT YET SUPPORTED']))
|
def count_rows(value,key):
|
||||||
|
rows=value.get(key) if isinstance(value,dict) else None
|
||||||
|
return len(rows) if isinstance(rows,list) else 0
|
||||||
|
save(lab,'summary',dict(status=status,markers=markers,tests=count_rows(tests,'tests'),coverage=coverage,core=core,historical_cases=count_rows(read('historical-replay'),'cases'),runtime_runs=0,new_popups=0,new_grabs=0,new_captures=0,new_camera_operations=0,runtime_budget_initialized=False,production_changes=False,source_delta={p.name:sha(p) for p in HERE.iterdir() if p.is_file()},manifest='UNSEALED; parent review required',next='independent review of final fixture/register/evidence; separate future authorization required for runtime',limitations=['atomic transaction-generation/native-buffer-frame identity NOT PROVEN','new static popup crossing/grab/input/standard NOT TESTED','vertical/scaled/rotated/migration/full damage NOT TESTED','production cross-output viewport NOT YET SUPPORTED']))
|
||||||
(lab/'independent-review-input.md').write_text('''# Independent review input — EXPERIMENTAL
|
(lab/'independent-review-input.md').write_text('''# Independent review input — EXPERIMENTAL
|
||||||
|
|
||||||
Review this final fixture against the offline gate; review E1/E2, actual
|
Review this final fixture against the offline gate; review E1/E2, actual
|
||||||
|
|
@ -134,6 +123,7 @@ ACCEPTED/CORRECTION_REQUIRED/NOT PROVEN findings. No author review PASS, runtime
|
||||||
launch, budget initialization or manifest sealing is authorized here.
|
launch, budget initialization or manifest sealing is authorized here.
|
||||||
''')
|
''')
|
||||||
print(json.dumps(readiness,indent=2))
|
print(json.dumps(readiness,indent=2))
|
||||||
|
return readiness
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
parser=argparse.ArgumentParser();parser.add_argument('lab',type=Path);write(parser.parse_args().lab)
|
parser=argparse.ArgumentParser();parser.add_argument('lab',type=Path);write(parser.parse_args().lab)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue