docs: publish saved-view group selection verification and native evidence

This commit is contained in:
2026-09-23 02:19:57 -07:00
parent f6a6010bae
commit 7e348d967d
44 changed files with 4666 additions and 0 deletions
@@ -0,0 +1,3 @@
# Preserve the exact pinned evidence and verifier bytes through Git round trips.
* -text whitespace=cr-at-eol
incidents/**/*.arcadia whitespace=-blank-at-eof,cr-at-eol
@@ -0,0 +1,96 @@
# Closed multiselect gate evidence
This package preserves all 19 closed captures selected from
`.local/group-movement-gates`: 14 recorded exit 0, and five recorded exit 101.
Every run reports unchanged captured inputs. The five failures remain failures;
their complete original receipts and streams are included. See the separate
[saved-view report](../../../multiselect-saved-view-20260923.md) for scope and
native observations. These standard-library Python 3.10+ tools do not run Cargo,
Git, archived source or executables.
| Run | Recorded exit | Input files |
| --- | ---: | ---: |
| core-1 | 0 | 722 |
| core-2 | 101 | 729 |
| core-3 | 0 | 729 |
| desktop-1 | 101 | 727 |
| desktop-2 | 101 | 728 |
| desktop-3 | 0 | 729 |
| desktop-4 | 0 | 729 |
| desktop-5 | 0 | 729 |
| format-1 | 0 | 729 |
| format-2 | 0 | 729 |
| lint-1 | 101 | 729 |
| lint-2 | 0 | 729 |
| lint-3 | 0 | 729 |
| native-build-1 | 0 | 729 |
| native-build-2 | 0 | 729 |
| oracle-2 | 101 | 729 |
| oracle-3 | 0 | 729 |
| windows-build-1 | 0 | 729 |
| windows-build-2 | 0 | 729 |
Core-3, desktop-4, format-1, lint-2, native-build-1 and windows-build-1 share the
729-file map `55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb`.
Desktop-5, format-2, lint-3, native-build-2 and windows-build-2 share the distinct
729-file map `99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c`.
The [source identity verifier](../source/README.md) compares those maps with Git
commits `12a7352ddef5f69a144ead8219a50916233d63a9` and
`f6a6010baed9e6164a1fcc7ecd58256a562827d7`, respectively. Earlier maps retain
their own evidence scope; they are not reruns against the later source.
To validate this exact raw run list without writing a package, from the checkout
root run:
```text
python -B harness/experiments/multiselect-20260923/checks/prepare.py --root . --runs core-1 core-2 core-3 desktop-1 desktop-2 desktop-3 desktop-4 desktop-5 format-1 format-2 lint-1 lint-2 lint-3 native-build-1 native-build-2 oracle-2 oracle-3 windows-build-1 windows-build-2 --check-only
```
Missing closure, changed inputs, inconsistent receipts, unavailable exact helpers,
and extra/unexpected run files are refused. Run names must be supplied, must be
unique, and cannot contain path separators.
To create a package, use the same explicit `--runs` list, omit `--check-only`, and
optionally supply `--output PATH`. The default output is this checks directory.
An output package is not overwritten. `--helper PATH` can be repeated to supply
an older gate helper whose exact pinned bytes are no longer the current helper.
Default helper candidates are `.local/group-movement-gates/*.py`.
Verify a completed package anywhere, without the original checkout:
```text
python -B PATH_TO_PACKAGE/verify.py
```
The packager preserves the seven original files per run: started/process/result
receipts, stdout/stderr logs, the input map, and its source ZIP. It preserves the
exact helper bytes named by each receipt. Only byte-identical input maps and ZIPs
are deduplicated into hash-named capsules; their per-run logical mapping remains.
ZIP member ordering and timestamps are fixed. Raw input/log bytes are unchanged.
`manifest.json` records the explicit run list, outcomes, commands, recorded HEADs,
input counts, helper paths, logical mapping and every stored member pin.
`files.json` pins `prepare.py`, `verify.py`, this README, the manifest and archive.
The verifier checks safe exact ZIP membership (including nested source ZIPs),
every recorded byte count/hash, input counts, the 71 vendored iced_widget files,
start/process/finish order, receipt relationships, unchanged-input flags, helper
identity, and exact ordered executable-artifact records parsed from Cargo JSON
stdout. Missing JSON artifact records remain missing; they are not synthesized
from paths or inferred from a successful exit. Non-null artifact readback pins
are checked structurally; executable bytes are not included or independently
verified by this package.
The source capsules are **local historical input snapshots**, including captured
uncommitted work. A recorded HEAD alone does not identify their contents. They
are not an integrated release, a hermetic toolchain distribution, or a claim that
one run's gate applies to a later input map. Commands, paths, PIDs, times and
artifact hashes are historical receipts, not authenticated execution records.
The verifier checks their internal consistency and does not access historical
absolute paths, contact services, extract archives or rerun tests. Pin integrity
is not an external signature or proof against coordinated receipt alteration.
This package has no native interaction, focus, selection, movement, saved-model,
Undo/Redo or full #29 acceptance implication. The native evidence and its
independent evaluator belong in their separate reviewed record. The verification
summary reports captured outcomes, including failures; it does not declare the
feature or all captured gates successful.
@@ -0,0 +1,22 @@
{
"prepare.py": {
"bytes": 4818,
"sha256": "29eedcec091874b26572530517f015ab690ed1a9040abea52248e99603ba5f25"
},
"verify.py": {
"bytes": 8873,
"sha256": "c03513407073bef092d57b968f982b8ffc0c58e095f834fe7464c6a0e8454a9a"
},
"README.md": {
"bytes": 5001,
"sha256": "3f5232af2ebb12003c833e6bc6643b4858950ebf015435a9b850c6a826fe27d0"
},
"manifest.json": {
"bytes": 37083,
"sha256": "c23269443cd059895c672330720a10508ab8ecade0d3686ec3d82ff792c9b457"
},
"evidence.zip": {
"bytes": 25914867,
"sha256": "261660dd8a5e93d917c1d36cad19d1eec0b93e312d1e0dd15f9ea16f5e11c864"
}
}
@@ -0,0 +1,935 @@
{
"schema": 1,
"kind": "multiselect-cargo-gates",
"runs": {
"core-1": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-core",
"--test",
"group_movement",
"--test",
"state_diagrams",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 722,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"core-2": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-core",
"--test",
"group_movement",
"--test",
"state_diagrams",
"--example",
"multiselect_native",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 101,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"core-3": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-core",
"--test",
"group_movement",
"--test",
"state_diagrams",
"--example",
"multiselect_native",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"desktop-1": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-desktop",
"multiselect",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 101,
"inputCount": 727,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"desktop-2": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 101,
"inputCount": 728,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"desktop-3": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"desktop-4": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"desktop-5": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--",
"--nocapture"
],
"head": "12a7352ddef5f69a144ead8219a50916233d63a9",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"format-1": {
"command": [
"cargo",
"fmt",
"--all",
"--",
"--check"
],
"head": "12a7352ddef5f69a144ead8219a50916233d63a9",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"format-2": {
"command": [
"cargo",
"fmt",
"--all",
"--",
"--check"
],
"head": "f6a6010baed9e6164a1fcc7ecd58256a562827d7",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"lint-1": {
"command": [
"cargo",
"clippy",
"--locked",
"--offline",
"-p",
"oa-core",
"-p",
"oa-desktop",
"--all-targets",
"--",
"-D",
"warnings"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 101,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"lint-2": {
"command": [
"cargo",
"clippy",
"--locked",
"--offline",
"-p",
"oa-core",
"-p",
"oa-desktop",
"--all-targets",
"--",
"-D",
"warnings"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"lint-3": {
"command": [
"cargo",
"clippy",
"--locked",
"--offline",
"-p",
"oa-core",
"-p",
"oa-desktop",
"--all-targets",
"--",
"-D",
"warnings"
],
"head": "12a7352ddef5f69a144ead8219a50916233d63a9",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"native-build-1": {
"command": [
"cargo",
"build",
"--locked",
"--offline",
"-p",
"oa-core",
"--example",
"multiselect_native",
"--message-format=json"
],
"head": "12a7352ddef5f69a144ead8219a50916233d63a9",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"native-build-2": {
"command": [
"cargo",
"build",
"--locked",
"--offline",
"-p",
"oa-core",
"--example",
"multiselect_native",
"--message-format=json"
],
"head": "f6a6010baed9e6164a1fcc7ecd58256a562827d7",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"oracle-2": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-core",
"--example",
"multiselect_native",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 101,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"oracle-3": {
"command": [
"cargo",
"test",
"--locked",
"--offline",
"-p",
"oa-core",
"--example",
"multiselect_native",
"--",
"--nocapture"
],
"head": "b8685416f56e53e30bd11ecf93a54cea10ac8458",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"windows-build-1": {
"command": [
"cargo",
"build",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--bin",
"arcadia-studio",
"--message-format=json"
],
"head": "12a7352ddef5f69a144ead8219a50916233d63a9",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"windows-build-2": {
"command": [
"cargo",
"build",
"--locked",
"--offline",
"-p",
"oa-desktop",
"--bin",
"arcadia-studio",
"--message-format=json"
],
"head": "f6a6010baed9e6164a1fcc7ecd58256a562827d7",
"exitCode": 0,
"inputCount": 729,
"helper": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
}
},
"logicalFiles": {
"cargo/core-1/inputs.json": "capsules/a73d565f90b14c986e0f87a7ac3d368c93e053b7e591cffdfa20d8e81e2eae08.json",
"cargo/core-1/inputs.zip": "capsules/2dcb54b1dd51a05cdd983432b114da8a08dce326c42b6e77a6b8772e75d2282f.zip",
"cargo/core-1/process.json": "cargo/core-1/process.json",
"cargo/core-1/result.json": "cargo/core-1/result.json",
"cargo/core-1/started.json": "cargo/core-1/started.json",
"cargo/core-1/stderr.log": "cargo/core-1/stderr.log",
"cargo/core-1/stdout.log": "cargo/core-1/stdout.log",
"cargo/core-2/inputs.json": "capsules/c5b23cd340869d57bd1bc4400041d499ea06a1a7619a6fd6b51e75278c1755e1.json",
"cargo/core-2/inputs.zip": "capsules/df441a733bf28d1c59eab52063ca4b2645067b490b0a2f0072f98fc9225ea2e8.zip",
"cargo/core-2/process.json": "cargo/core-2/process.json",
"cargo/core-2/result.json": "cargo/core-2/result.json",
"cargo/core-2/started.json": "cargo/core-2/started.json",
"cargo/core-2/stderr.log": "cargo/core-2/stderr.log",
"cargo/core-2/stdout.log": "cargo/core-2/stdout.log",
"cargo/core-3/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/core-3/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/core-3/process.json": "cargo/core-3/process.json",
"cargo/core-3/result.json": "cargo/core-3/result.json",
"cargo/core-3/started.json": "cargo/core-3/started.json",
"cargo/core-3/stderr.log": "cargo/core-3/stderr.log",
"cargo/core-3/stdout.log": "cargo/core-3/stdout.log",
"cargo/desktop-1/inputs.json": "capsules/c1083b630ad79ed1fea6933de3221f05b8eb9200694fb0e5dbd637527803579c.json",
"cargo/desktop-1/inputs.zip": "capsules/8d6b08c2b1220cdb48d32cc74004cc9b82e4385f6f50a764f76c4a8630d070bf.zip",
"cargo/desktop-1/process.json": "cargo/desktop-1/process.json",
"cargo/desktop-1/result.json": "cargo/desktop-1/result.json",
"cargo/desktop-1/started.json": "cargo/desktop-1/started.json",
"cargo/desktop-1/stderr.log": "cargo/desktop-1/stderr.log",
"cargo/desktop-1/stdout.log": "cargo/desktop-1/stdout.log",
"cargo/desktop-2/inputs.json": "capsules/5f049dbbee443af86cde70efc74027f290a9bfbd434e5d644aa74ddb4e97566b.json",
"cargo/desktop-2/inputs.zip": "capsules/bf7dc41142e6d087f213b2914e0ffb0e9cd52294f5830301e5e5b78c3470f725.zip",
"cargo/desktop-2/process.json": "cargo/desktop-2/process.json",
"cargo/desktop-2/result.json": "cargo/desktop-2/result.json",
"cargo/desktop-2/started.json": "cargo/desktop-2/started.json",
"cargo/desktop-2/stderr.log": "cargo/desktop-2/stderr.log",
"cargo/desktop-2/stdout.log": "cargo/desktop-2/stdout.log",
"cargo/desktop-3/inputs.json": "capsules/6f8eae7613666bca412e62f67151d6fee9f5bd32fb50363d0ff9b9ac8b190acf.json",
"cargo/desktop-3/inputs.zip": "capsules/cc6233ddec2db0e322659a73a55e1681f5cb3554750ba183a756a29dadf8a8c9.zip",
"cargo/desktop-3/process.json": "cargo/desktop-3/process.json",
"cargo/desktop-3/result.json": "cargo/desktop-3/result.json",
"cargo/desktop-3/started.json": "cargo/desktop-3/started.json",
"cargo/desktop-3/stderr.log": "cargo/desktop-3/stderr.log",
"cargo/desktop-3/stdout.log": "cargo/desktop-3/stdout.log",
"cargo/desktop-4/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/desktop-4/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/desktop-4/process.json": "cargo/desktop-4/process.json",
"cargo/desktop-4/result.json": "cargo/desktop-4/result.json",
"cargo/desktop-4/started.json": "cargo/desktop-4/started.json",
"cargo/desktop-4/stderr.log": "cargo/desktop-4/stderr.log",
"cargo/desktop-4/stdout.log": "cargo/desktop-4/stdout.log",
"cargo/desktop-5/inputs.json": "capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json",
"cargo/desktop-5/inputs.zip": "capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip",
"cargo/desktop-5/process.json": "cargo/desktop-5/process.json",
"cargo/desktop-5/result.json": "cargo/desktop-5/result.json",
"cargo/desktop-5/started.json": "cargo/desktop-5/started.json",
"cargo/desktop-5/stderr.log": "cargo/desktop-5/stderr.log",
"cargo/desktop-5/stdout.log": "cargo/desktop-5/stdout.log",
"cargo/format-1/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/format-1/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/format-1/process.json": "cargo/format-1/process.json",
"cargo/format-1/result.json": "cargo/format-1/result.json",
"cargo/format-1/started.json": "cargo/format-1/started.json",
"cargo/format-1/stderr.log": "cargo/format-1/stderr.log",
"cargo/format-1/stdout.log": "cargo/format-1/stdout.log",
"cargo/format-2/inputs.json": "capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json",
"cargo/format-2/inputs.zip": "capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip",
"cargo/format-2/process.json": "cargo/format-2/process.json",
"cargo/format-2/result.json": "cargo/format-2/result.json",
"cargo/format-2/started.json": "cargo/format-2/started.json",
"cargo/format-2/stderr.log": "cargo/format-2/stderr.log",
"cargo/format-2/stdout.log": "cargo/format-2/stdout.log",
"cargo/lint-1/inputs.json": "capsules/292f6139450109875549801a1da337dac08a8bca4cfa0124139a5d8d042386b9.json",
"cargo/lint-1/inputs.zip": "capsules/d2ec5025067db2c05736bb1c9c9b6250d9199f1b7190e8c09f5a777424790c10.zip",
"cargo/lint-1/process.json": "cargo/lint-1/process.json",
"cargo/lint-1/result.json": "cargo/lint-1/result.json",
"cargo/lint-1/started.json": "cargo/lint-1/started.json",
"cargo/lint-1/stderr.log": "cargo/lint-1/stderr.log",
"cargo/lint-1/stdout.log": "cargo/lint-1/stdout.log",
"cargo/lint-2/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/lint-2/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/lint-2/process.json": "cargo/lint-2/process.json",
"cargo/lint-2/result.json": "cargo/lint-2/result.json",
"cargo/lint-2/started.json": "cargo/lint-2/started.json",
"cargo/lint-2/stderr.log": "cargo/lint-2/stderr.log",
"cargo/lint-2/stdout.log": "cargo/lint-2/stdout.log",
"cargo/lint-3/inputs.json": "capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json",
"cargo/lint-3/inputs.zip": "capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip",
"cargo/lint-3/process.json": "cargo/lint-3/process.json",
"cargo/lint-3/result.json": "cargo/lint-3/result.json",
"cargo/lint-3/started.json": "cargo/lint-3/started.json",
"cargo/lint-3/stderr.log": "cargo/lint-3/stderr.log",
"cargo/lint-3/stdout.log": "cargo/lint-3/stdout.log",
"cargo/native-build-1/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/native-build-1/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/native-build-1/process.json": "cargo/native-build-1/process.json",
"cargo/native-build-1/result.json": "cargo/native-build-1/result.json",
"cargo/native-build-1/started.json": "cargo/native-build-1/started.json",
"cargo/native-build-1/stderr.log": "cargo/native-build-1/stderr.log",
"cargo/native-build-1/stdout.log": "cargo/native-build-1/stdout.log",
"cargo/native-build-2/inputs.json": "capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json",
"cargo/native-build-2/inputs.zip": "capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip",
"cargo/native-build-2/process.json": "cargo/native-build-2/process.json",
"cargo/native-build-2/result.json": "cargo/native-build-2/result.json",
"cargo/native-build-2/started.json": "cargo/native-build-2/started.json",
"cargo/native-build-2/stderr.log": "cargo/native-build-2/stderr.log",
"cargo/native-build-2/stdout.log": "cargo/native-build-2/stdout.log",
"cargo/oracle-2/inputs.json": "capsules/ae16337dbc617e26b23468adb86d963e3bcf7eddf177e8fb4654c69019904548.json",
"cargo/oracle-2/inputs.zip": "capsules/e99bcaf1ab2becbcad0a005bdd0a4eb14fad2075bd7a38433857df4d3cad5e4d.zip",
"cargo/oracle-2/process.json": "cargo/oracle-2/process.json",
"cargo/oracle-2/result.json": "cargo/oracle-2/result.json",
"cargo/oracle-2/started.json": "cargo/oracle-2/started.json",
"cargo/oracle-2/stderr.log": "cargo/oracle-2/stderr.log",
"cargo/oracle-2/stdout.log": "cargo/oracle-2/stdout.log",
"cargo/oracle-3/inputs.json": "capsules/292f6139450109875549801a1da337dac08a8bca4cfa0124139a5d8d042386b9.json",
"cargo/oracle-3/inputs.zip": "capsules/d2ec5025067db2c05736bb1c9c9b6250d9199f1b7190e8c09f5a777424790c10.zip",
"cargo/oracle-3/process.json": "cargo/oracle-3/process.json",
"cargo/oracle-3/result.json": "cargo/oracle-3/result.json",
"cargo/oracle-3/started.json": "cargo/oracle-3/started.json",
"cargo/oracle-3/stderr.log": "cargo/oracle-3/stderr.log",
"cargo/oracle-3/stdout.log": "cargo/oracle-3/stdout.log",
"cargo/windows-build-1/inputs.json": "capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json",
"cargo/windows-build-1/inputs.zip": "capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip",
"cargo/windows-build-1/process.json": "cargo/windows-build-1/process.json",
"cargo/windows-build-1/result.json": "cargo/windows-build-1/result.json",
"cargo/windows-build-1/started.json": "cargo/windows-build-1/started.json",
"cargo/windows-build-1/stderr.log": "cargo/windows-build-1/stderr.log",
"cargo/windows-build-1/stdout.log": "cargo/windows-build-1/stdout.log",
"cargo/windows-build-2/inputs.json": "capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json",
"cargo/windows-build-2/inputs.zip": "capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip",
"cargo/windows-build-2/process.json": "cargo/windows-build-2/process.json",
"cargo/windows-build-2/result.json": "cargo/windows-build-2/result.json",
"cargo/windows-build-2/started.json": "cargo/windows-build-2/started.json",
"cargo/windows-build-2/stderr.log": "cargo/windows-build-2/stderr.log",
"cargo/windows-build-2/stdout.log": "cargo/windows-build-2/stdout.log",
"helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py": "helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py"
},
"members": {
"capsules/292f6139450109875549801a1da337dac08a8bca4cfa0124139a5d8d042386b9.json": {
"bytes": 121985,
"sha256": "292f6139450109875549801a1da337dac08a8bca4cfa0124139a5d8d042386b9"
},
"capsules/2dcb54b1dd51a05cdd983432b114da8a08dce326c42b6e77a6b8772e75d2282f.zip": {
"bytes": 2885634,
"sha256": "2dcb54b1dd51a05cdd983432b114da8a08dce326c42b6e77a6b8772e75d2282f"
},
"capsules/55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb.json": {
"bytes": 121985,
"sha256": "55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb"
},
"capsules/5f049dbbee443af86cde70efc74027f290a9bfbd434e5d644aa74ddb4e97566b.json": {
"bytes": 121820,
"sha256": "5f049dbbee443af86cde70efc74027f290a9bfbd434e5d644aa74ddb4e97566b"
},
"capsules/6f8eae7613666bca412e62f67151d6fee9f5bd32fb50363d0ff9b9ac8b190acf.json": {
"bytes": 121984,
"sha256": "6f8eae7613666bca412e62f67151d6fee9f5bd32fb50363d0ff9b9ac8b190acf"
},
"capsules/8d6b08c2b1220cdb48d32cc74004cc9b82e4385f6f50a764f76c4a8630d070bf.zip": {
"bytes": 2903240,
"sha256": "8d6b08c2b1220cdb48d32cc74004cc9b82e4385f6f50a764f76c4a8630d070bf"
},
"capsules/99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c.json": {
"bytes": 121985,
"sha256": "99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c"
},
"capsules/a73d565f90b14c986e0f87a7ac3d368c93e053b7e591cffdfa20d8e81e2eae08.json": {
"bytes": 120844,
"sha256": "a73d565f90b14c986e0f87a7ac3d368c93e053b7e591cffdfa20d8e81e2eae08"
},
"capsules/aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9.zip": {
"bytes": 2918930,
"sha256": "aa8bb3d7fbd1f73c36913235b0b1d3aa79f6ac418b6c07ade94a7dee4a617bd9"
},
"capsules/ae16337dbc617e26b23468adb86d963e3bcf7eddf177e8fb4654c69019904548.json": {
"bytes": 121984,
"sha256": "ae16337dbc617e26b23468adb86d963e3bcf7eddf177e8fb4654c69019904548"
},
"capsules/bf7dc41142e6d087f213b2914e0ffb0e9cd52294f5830301e5e5b78c3470f725.zip": {
"bytes": 2909281,
"sha256": "bf7dc41142e6d087f213b2914e0ffb0e9cd52294f5830301e5e5b78c3470f725"
},
"capsules/c1083b630ad79ed1fea6933de3221f05b8eb9200694fb0e5dbd637527803579c.json": {
"bytes": 121652,
"sha256": "c1083b630ad79ed1fea6933de3221f05b8eb9200694fb0e5dbd637527803579c"
},
"capsules/c5b23cd340869d57bd1bc4400041d499ea06a1a7619a6fd6b51e75278c1755e1.json": {
"bytes": 121984,
"sha256": "c5b23cd340869d57bd1bc4400041d499ea06a1a7619a6fd6b51e75278c1755e1"
},
"capsules/cc6233ddec2db0e322659a73a55e1681f5cb3554750ba183a756a29dadf8a8c9.zip": {
"bytes": 2917494,
"sha256": "cc6233ddec2db0e322659a73a55e1681f5cb3554750ba183a756a29dadf8a8c9"
},
"capsules/d2ec5025067db2c05736bb1c9c9b6250d9199f1b7190e8c09f5a777424790c10.zip": {
"bytes": 2918296,
"sha256": "d2ec5025067db2c05736bb1c9c9b6250d9199f1b7190e8c09f5a777424790c10"
},
"capsules/df441a733bf28d1c59eab52063ca4b2645067b490b0a2f0072f98fc9225ea2e8.zip": {
"bytes": 2917518,
"sha256": "df441a733bf28d1c59eab52063ca4b2645067b490b0a2f0072f98fc9225ea2e8"
},
"capsules/e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533.zip": {
"bytes": 2918309,
"sha256": "e1c7f3abe7b32616d1081b4a2bb8af2d6d4b071bc2a7cbdd61e96a92ffdc0533"
},
"capsules/e99bcaf1ab2becbcad0a005bdd0a4eb14fad2075bd7a38433857df4d3cad5e4d.zip": {
"bytes": 2917719,
"sha256": "e99bcaf1ab2becbcad0a005bdd0a4eb14fad2075bd7a38433857df4d3cad5e4d"
},
"cargo/core-1/process.json": {
"bytes": 210,
"sha256": "92e5a88b5b86400c13bad4d0a9d490466bb2ef0b6077d14930ac5084187b5506"
},
"cargo/core-1/result.json": {
"bytes": 1821,
"sha256": "c90e020e6d912516fbc5ef5b4bf6a5df5fc668e5f5e19a9108c29bf3723cea9c"
},
"cargo/core-1/started.json": {
"bytes": 1428,
"sha256": "230ea369285569a0fa179fe420b0b2133e7fcb2349601a53d69881e9a66bd39b"
},
"cargo/core-1/stderr.log": {
"bytes": 434,
"sha256": "84a1b0b7352dcde2fe51293feabbddf8e94206d9278e4a38e6d354af8a1bcd48"
},
"cargo/core-1/stdout.log": {
"bytes": 1671,
"sha256": "eb04561c11e394cc368ea1c5e38aa4b1dc8b5c3c44acb168469dd941f80f14e8"
},
"cargo/core-2/process.json": {
"bytes": 245,
"sha256": "020d6cb0ce6e4b9122ac2dcbd86c9c1719479f29d3690247182ade858caba12d"
},
"cargo/core-2/result.json": {
"bytes": 1870,
"sha256": "c97cbcd85b60a3476135bf9026d41868ea091061c12ce4bbc18a40c6023c5b3e"
},
"cargo/core-2/started.json": {
"bytes": 1473,
"sha256": "f367b289c9d378975514fa450e4fa25049f4461156417ba5bd6e79836faf401e"
},
"cargo/core-2/stderr.log": {
"bytes": 5287,
"sha256": "4ea6f38eef014ab8176c3ab1ed9d3be3addb4463a8f073425f1b5493b33a7c86"
},
"cargo/core-2/stdout.log": {
"bytes": 4138,
"sha256": "a2dfdb0d7c6c7ba7e9ef86063a815f43111188a44ae4b0e20717cc3e518b7c3d"
},
"cargo/core-3/process.json": {
"bytes": 245,
"sha256": "b26f22b0aed07e55906b024d1fd94198da1ab1d56363fc5ad66868940ae1c9a4"
},
"cargo/core-3/result.json": {
"bytes": 1867,
"sha256": "6d04a2818750491cb73ebb1b257d214316c048e1ac6165a119a27534d636406c"
},
"cargo/core-3/started.json": {
"bytes": 1473,
"sha256": "49e9d637eb063277925c577266a63e5fd06723ca24726d609dc0e458596e8316"
},
"cargo/core-3/stderr.log": {
"bytes": 539,
"sha256": "f05f7ab2f0244968100eb0e0a82808af8e42dceb5b5de70d034b7ae56bad9489"
},
"cargo/core-3/stdout.log": {
"bytes": 4797,
"sha256": "d0f2180aaecc3b253b473200b77348a19a21594e193ce45c21f040b7242be253"
},
"cargo/desktop-1/process.json": {
"bytes": 172,
"sha256": "d9ba2b6a0968b702af0aa857e7bb8667680eeddc32a0403781cd3d5e2467c067"
},
"cargo/desktop-1/result.json": {
"bytes": 1769,
"sha256": "2384c076e4bbc0e15951671e3a830725213c31cfcded0a27e1bb72802c576dbc"
},
"cargo/desktop-1/started.json": {
"bytes": 1375,
"sha256": "6b1ba478ebe5e14d5ee76199a56874a6a10156c2dd7e9d3830fd5ba5311094d6"
},
"cargo/desktop-1/stderr.log": {
"bytes": 4604,
"sha256": "6a47286c4daaf9f4ac8ac8cca3e98931f7812a44b192128aa67880c1ac930b87"
},
"cargo/desktop-1/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/desktop-2/process.json": {
"bytes": 157,
"sha256": "cc037bab1ec44bd2e4095e165597f5e1d077bae5fce7a96c6a5fd814470d4244"
},
"cargo/desktop-2/result.json": {
"bytes": 1753,
"sha256": "9c037405572273086737e22b60796eff0745f4746ee3f25529f928da53c98fbc"
},
"cargo/desktop-2/started.json": {
"bytes": 1355,
"sha256": "18f71e571722bdb3696195623b3af3a2b9a45d38f98307a68049aacff3fbad9c"
},
"cargo/desktop-2/stderr.log": {
"bytes": 1085,
"sha256": "316e0179675fb071d7d9773d7073d771438ecd70e66c99559f4239e0638a3238"
},
"cargo/desktop-2/stdout.log": {
"bytes": 145051,
"sha256": "7c907317d106ff63347456b5ad2015fa8a9974ffbb7003d0a123afc99879ce42"
},
"cargo/desktop-3/process.json": {
"bytes": 157,
"sha256": "368d265e1ee5cceeb5995172c662dc3bc551591b9600a781c63ed64579760c24"
},
"cargo/desktop-3/result.json": {
"bytes": 1751,
"sha256": "32076fb49a6ddfcef63e77ca9f1edec34700ca80d36f32890581d56035f80054"
},
"cargo/desktop-3/started.json": {
"bytes": 1355,
"sha256": "da1ccd8352380b357d5954a70d86f2c51c8a2da8d1c4b553ca7b281d3000eab9"
},
"cargo/desktop-3/stderr.log": {
"bytes": 626,
"sha256": "5333e25e78f515449877867d0a2bf714b7cb3302c9497d4f4343a1e05e0f8b03"
},
"cargo/desktop-3/stdout.log": {
"bytes": 145562,
"sha256": "dc7e40a7d2ab1e78c74f0ee0344c4b2e5b1402bc6367e93a40780774000e4f81"
},
"cargo/desktop-4/process.json": {
"bytes": 157,
"sha256": "0823d0fbda95fe5efb08a7c11c98a7ac2409b5b3d170cf2e41b702895211abf4"
},
"cargo/desktop-4/result.json": {
"bytes": 1750,
"sha256": "d88b177e9d181f7c9c3685100c8676c0c8954cd0b071344ff5b4bb7a8e498865"
},
"cargo/desktop-4/started.json": {
"bytes": 1355,
"sha256": "0f9927d5c0b09c7fcc8922c68a2c88a4d840e0420a7be90193f566b02312a3d3"
},
"cargo/desktop-4/stderr.log": {
"bytes": 628,
"sha256": "992db238282b7acf1bbfeee7f2c459f9afe4bce814761d70df789e4f6239afcf"
},
"cargo/desktop-4/stdout.log": {
"bytes": 145802,
"sha256": "70c38e8c98cac4f220999481908beb549e5377f6f48c31931f9412ed25a67a41"
},
"cargo/desktop-5/process.json": {
"bytes": 157,
"sha256": "83bf9efc58fa5692f3ed038c107c081e5483d91117c73eddba62d3eb45cc7267"
},
"cargo/desktop-5/result.json": {
"bytes": 1751,
"sha256": "7cbbae8bbceec07cebb4696b999701cd29d46bfd047351aa3e20ea49d7c67ae6"
},
"cargo/desktop-5/started.json": {
"bytes": 1355,
"sha256": "0bfd2a6c185afb1b301e3b6b5f746d0e37251f147590aa2e9f25e370e99f53e8"
},
"cargo/desktop-5/stderr.log": {
"bytes": 631,
"sha256": "466f26c41956ed05629b633827d7ffca497c57c87ff67acff6351043c7bdefd4"
},
"cargo/desktop-5/stdout.log": {
"bytes": 146577,
"sha256": "e89cf5f2375fd40ae70261471d797cbaca5127cb27730e6094a616afa12514ae"
},
"cargo/format-1/process.json": {
"bytes": 116,
"sha256": "bb8e0a7620b40bb5f0932643848a57b0d207dde39006a9a20141c00f13d94284"
},
"cargo/format-1/result.json": {
"bytes": 1687,
"sha256": "967eeddb3fc6a0dc0fdf9a75f575d75fa8f8b0b5ea9c8a422590bcbece6de77b"
},
"cargo/format-1/started.json": {
"bytes": 1299,
"sha256": "ceb354dfbc4a41d72e496342e28475ddcce5a3c17a4e1553f0d699404c374657"
},
"cargo/format-1/stderr.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/format-1/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/format-2/process.json": {
"bytes": 116,
"sha256": "aa31b91d224845b7dd1df777e865c88c5b8f55b66f173053be318132d1bc3870"
},
"cargo/format-2/result.json": {
"bytes": 1687,
"sha256": "c4d5529c8d2feae1b805bd8d404a3817053a5a0cd4ec341aa8c1e0a5c05eed5b"
},
"cargo/format-2/started.json": {
"bytes": 1299,
"sha256": "2ea70bb29d7fef73a194acd7aa36836fd4a54ae8a4be173f919cd2fc32e97919"
},
"cargo/format-2/stderr.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/format-2/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/lint-1/process.json": {
"bytes": 196,
"sha256": "d30e400277dc0bb4a1618689b16ab86be7838cc1b42688185d655df235080286"
},
"cargo/lint-1/result.json": {
"bytes": 1808,
"sha256": "7ffb361d398def4520afc48683a69effbb8b066efd9442ba3b356c8124aae6d9"
},
"cargo/lint-1/started.json": {
"bytes": 1414,
"sha256": "771b5bdc31662fb3b4f76735e92b0e89d31a02188fbce35c5cfb0aea4c37c0ca"
},
"cargo/lint-1/stderr.log": {
"bytes": 1023,
"sha256": "9cbab357d810ce8164a0e614491f53529e61c1cad79793ca429e13897a8dc5ed"
},
"cargo/lint-1/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/lint-2/process.json": {
"bytes": 196,
"sha256": "f4aed65014ed120dc72bd08160559ae0285bc5c4968305a5fb86cf29e8c0d347"
},
"cargo/lint-2/result.json": {
"bytes": 1805,
"sha256": "b873add4777fd8f7516513e2423f9d3eb4a40505a3b1fa7edfbee89fb5c7e0d3"
},
"cargo/lint-2/started.json": {
"bytes": 1414,
"sha256": "0d01a20ec0f7cd796c066c95936c74df0abf8947fca655d900a5bdd4f8dbd610"
},
"cargo/lint-2/stderr.log": {
"bytes": 207,
"sha256": "e6f76746d5864a4de1e9d238c74799e2080e2c6214f51b68a4692d5e15f5b107"
},
"cargo/lint-2/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/lint-3/process.json": {
"bytes": 196,
"sha256": "620094b52dab8f23f389687cf72b8b3aa4effa55697842206a618293537eb869"
},
"cargo/lint-3/result.json": {
"bytes": 1805,
"sha256": "1e7dc472c03d653094850ed653599cee41e50d1639389bbc3fee45e40a754b5c"
},
"cargo/lint-3/started.json": {
"bytes": 1414,
"sha256": "b921ee7102386187c288c1b25aea96a3019ff00a4a508065aefbc4499b7c7818"
},
"cargo/lint-3/stderr.log": {
"bytes": 137,
"sha256": "d19e47547a69ce7956c74f2a65cd1064571985d073bcf497a11a0b0eebcfbd04"
},
"cargo/lint-3/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/native-build-1/process.json": {
"bytes": 194,
"sha256": "390cb979d680b9fdb7e0afa05d6b9d10a25dc27abaff16596d113bb0b2142b43"
},
"cargo/native-build-1/result.json": {
"bytes": 3132,
"sha256": "35f76499ac2a49446b896932c963fd8734a5755e00e3511cedf1e584e7b17704"
},
"cargo/native-build-1/started.json": {
"bytes": 1397,
"sha256": "5f37fc095aa00eae8fae043651a29f387f484bf4a0cc454e3919ea4f49567126"
},
"cargo/native-build-1/stderr.log": {
"bytes": 130,
"sha256": "731d61ee089d75c107edcd02d2cdedcddaad57ec06607ccd0822d9dc71a72720"
},
"cargo/native-build-1/stdout.log": {
"bytes": 41700,
"sha256": "832dc599cad2c9ba28ff9153537fb428390d8f25959f5b4a080cd432f6bea0e8"
},
"cargo/native-build-2/process.json": {
"bytes": 194,
"sha256": "46ff130840d8b12272be43f479adeb0b2ace94ee1d5389c5638a61b22d732496"
},
"cargo/native-build-2/result.json": {
"bytes": 3131,
"sha256": "fbecac3b0f7913db5e2ad19043c7df167a92287833ddf3ea4f24766e86ae523b"
},
"cargo/native-build-2/started.json": {
"bytes": 1397,
"sha256": "cbd2c7ad98baddc3719a5c03bef103747d4cb5c560d631376149f116ede49584"
},
"cargo/native-build-2/stderr.log": {
"bytes": 60,
"sha256": "b2558545bbfa50a0f0c26623c0982eb5f96d71ea228d7c56180edbac0d0b295d"
},
"cargo/native-build-2/stdout.log": {
"bytes": 41699,
"sha256": "7884b8ea1a92d58c7174657560ec38ff9a073e52f93cc19a78290840f2ab5486"
},
"cargo/oracle-2/process.json": {
"bytes": 189,
"sha256": "1e8ffd7a03b22bf2ec43b0d66ae3cc98016a431c4a07499faf3ca0c635b92337"
},
"cargo/oracle-2/result.json": {
"bytes": 1789,
"sha256": "e0b7331751bae8564ee5c28d05029071f1c8460195e6f9e2f0d00a5ae4e05a16"
},
"cargo/oracle-2/started.json": {
"bytes": 1397,
"sha256": "b7a8278dfa2324f0c3ff6e9616a65ef7a51c99699ad700adfe90e2accc435765"
},
"cargo/oracle-2/stderr.log": {
"bytes": 520,
"sha256": "9dd8b849afdbbb2207a9ad82f1b6c6f07fd9cd0846fe4591f33c40fdadcbb3ac"
},
"cargo/oracle-2/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"cargo/oracle-3/process.json": {
"bytes": 189,
"sha256": "a2cb30f512ee390bb03c9fcf5ea8069ca3a05da91f798985efc3f9f54670ace4"
},
"cargo/oracle-3/result.json": {
"bytes": 1791,
"sha256": "f0768fecc9f6711dd3cfc627c60aaf6118216bce47e76faa4cbdda571ac675e4"
},
"cargo/oracle-3/started.json": {
"bytes": 1397,
"sha256": "30cf614b6dede363ae4bdeca56fc4a1ddb7ee19a7e592b1b1616d4a98a53b535"
},
"cargo/oracle-3/stderr.log": {
"bytes": 307,
"sha256": "b4ccc583c5001d81b7208fe6f2e52788d0d40b63c7da034ca1fb90ec2adb18a4"
},
"cargo/oracle-3/stdout.log": {
"bytes": 2968,
"sha256": "e0a62ca8b008370c5a41378eb4c9e2a229a2fcde7bdba55426313c7d23da8aca"
},
"cargo/windows-build-1/process.json": {
"bytes": 189,
"sha256": "4e6b57dc0d5f10ac1b4af991f8b0f7558f4fc5b626e00f1a49c5782ea13abe18"
},
"cargo/windows-build-1/result.json": {
"bytes": 3082,
"sha256": "3cdd09a859288afe71dde6fb51bcc4bca84e47ceb9cb6389d57f6722d9e23fdf"
},
"cargo/windows-build-1/started.json": {
"bytes": 1392,
"sha256": "a3ebcdffc01e93fd5609005a0539eb11bf473b45bc28eee71dd175b943b387eb"
},
"cargo/windows-build-1/stderr.log": {
"bytes": 319,
"sha256": "7201ff3f71fe793907482992a00682023fc6ee1ac0a016f53a048b299ec2fffd"
},
"cargo/windows-build-1/stdout.log": {
"bytes": 284182,
"sha256": "3fc90b8c923415496c7990d33a5fe7211423b83df833a80111079fad71f04a2d"
},
"cargo/windows-build-2/process.json": {
"bytes": 189,
"sha256": "f18acb4c9feede438e1aa67bb86ce2d74f5b3aa0142499ae99b56b23daaf834b"
},
"cargo/windows-build-2/result.json": {
"bytes": 3081,
"sha256": "d7b191ee07c302ffed1017374b0c5d8b86245c0f3348fbac4778ae573397b9de"
},
"cargo/windows-build-2/started.json": {
"bytes": 1392,
"sha256": "b6a6656d966559060f01e87ccbd75837b0cf67e70c77246b20f587167bdbf651"
},
"cargo/windows-build-2/stderr.log": {
"bytes": 137,
"sha256": "aafe81cdd7c1e5558e957d4296d46e3238c72af79ba79d6147c5cc16f938d6ef"
},
"cargo/windows-build-2/stdout.log": {
"bytes": 284179,
"sha256": "cfba733cb79a9496004109bb0bc8b8996df5ec1645691fd79b952063faa519c5"
},
"helpers/6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06.py": {
"bytes": 3502,
"sha256": "6b8fcf64a1eb0869ae29abd66b4e89564a1813fef5898b54f2a17a3230dbaa06"
}
}
}
@@ -0,0 +1,90 @@
"""Package explicitly selected closed gate captures without running Cargo."""
from pathlib import Path
import argparse
import json
import zipfile
from verify import RAW_FILES, pin, parsed, need, run_name, verify_data, verify_package
HERE = Path(__file__).resolve().parent
def collect(root, runs, helpers):
gates = root / ".local/group-movement-gates"
candidates = sorted(gates.glob("*.py")) + helpers
helper_bytes = [path.read_bytes() for path in candidates]
payload, logical, specs = {}, {}, {}
def add(name, data):
stored = ("capsules/" + pin(data)["sha256"] + Path(name).suffix
if name.rsplit("/", 1)[1] in {"inputs.json", "inputs.zip"} else name)
need(stored not in payload or payload[stored] == data, "deduplication collision")
payload[stored] = data
logical[name] = stored
for run in runs:
folder = gates / run
need(folder.is_dir(), "run directory missing: " + run)
paths = list(folder.iterdir())
need(all(path.is_file() and not path.is_symlink() for path in paths)
and {path.name for path in paths} == RAW_FILES, "exact closed raw files required: " + run)
raw = {path.name: path.read_bytes() for path in paths}
result = parsed(raw["result.json"])
need("finish" in result and result["inputsUnchanged"] is True, "unfinished/changed run refused: " + run)
matches = [data for data in helper_bytes if pin(data) == result["helper"]]
need(bool(matches), "exact historical helper unavailable for " + run + "; supply --helper PATH")
helper = "helpers/" + result["helper"]["sha256"] + ".py"
add(helper, matches[0])
for name, data in sorted(raw.items()):
add("cargo/" + run + "/" + name, data)
specs[run] = {key: result[key] for key in ("command", "head", "exitCode", "inputCount")}
specs[run]["helper"] = helper
manifest = {"schema": 1, "kind": "multiselect-cargo-gates", "runs": specs,
"logicalFiles": dict(sorted(logical.items())),
"members": {name: pin(data) for name, data in sorted(payload.items())}}
summary = verify_data(manifest, payload.__getitem__)
return payload, manifest, summary
def write_json(path, value):
with path.open("xb") as output:
output.write((json.dumps(value, indent=2) + "\n").encode("utf-8"))
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=HERE.parents[3], help="checkout holding .local/group-movement-gates")
parser.add_argument("--runs", nargs="+", required=True, help="explicit run names, including failures to retain")
parser.add_argument("--helper", type=Path, action="append", default=[], help="additional exact historical helper (repeatable)")
parser.add_argument("--output", type=Path, default=HERE, help="package directory; existing evidence is never overwritten")
parser.add_argument("--check-only", action="store_true", help="validate raw captures in memory without creating an archive")
args = parser.parse_args()
need(all(run_name(run) for run in args.runs) and len(args.runs) == len(set(args.runs)), "unique safe run names required")
payload, manifest, summary = collect(args.root.resolve(), args.runs, args.helper)
if args.check_only:
print("PASS raw consistency; no package written:", summary)
return
out = args.output.resolve()
out.mkdir(parents=True, exist_ok=True)
for name in ("evidence.zip", "manifest.json", "files.json"):
need(not (out / name).exists(), "existing package output refused: " + name)
for name in ("prepare.py", "verify.py", "README.md"):
data = (HERE / name).read_bytes()
destination = out / name
if destination.exists():
need(destination.read_bytes() == data, "different existing package tool: " + name)
else:
with destination.open("xb") as output:
output.write(data)
with zipfile.ZipFile(out / "evidence.zip", "x", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
for name, data in sorted(payload.items()):
info = zipfile.ZipInfo(name, date_time=(2026, 9, 23, 0, 0, 0))
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o100644 << 16
archive.writestr(info, data)
write_json(out / "manifest.json", manifest)
names = ("prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip")
write_json(out / "files.json", {name: pin((out / name).read_bytes()) for name in names})
need(verify_package(out) == summary, "written package differs from validated captures")
print("PASS package readback:", out, summary)
if __name__ == "__main__":
main()
@@ -0,0 +1,164 @@
"""Offline consistency checks only; never execute or extract archived inputs."""
from pathlib import Path, PurePosixPath
from datetime import datetime
import argparse
import hashlib
import io
import json
import math
import re
import stat
import zipfile
RAW_FILES = {"started.json", "process.json", "result.json", "stdout.log", "stderr.log", "inputs.json", "inputs.zip"}
OUTER_FILES = {"prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip"}
def need(condition, message):
if not condition:
raise ValueError(message)
def pin(data):
return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
def valid_pin(value):
return (isinstance(value, dict) and set(value) == {"bytes", "sha256"}
and type(value["bytes"]) is int and value["bytes"] >= 0
and isinstance(value["sha256"], str)
and re.fullmatch(r"[0-9a-f]{64}", value["sha256"]) is not None)
def safe(name):
return (isinstance(name, str) and bool(name) and "\\" not in name and ":" not in name
and all(ord(char) >= 32 for char in name)
and not PurePosixPath(name).is_absolute()
and all(part not in ("", ".", "..") for part in name.split("/")))
def run_name(name):
return isinstance(name, str) and re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", name) is not None
def parsed(data):
def pairs(items):
result = {}
for key, value in items:
need(key not in result, "duplicate JSON key: " + key)
result[key] = value
return result
def constant(value):
raise ValueError("nonfinite JSON constant: " + value)
return json.loads(data, object_pairs_hook=pairs, parse_constant=constant)
def inventory(archive, expected):
names = archive.namelist()
need(len(names) == len(set(names)) and set(names) == set(expected), "exact ZIP membership")
for entry in archive.infolist():
need(safe(entry.filename) and not entry.is_dir(), "unsafe ZIP member: " + entry.filename)
need(not stat.S_ISLNK(entry.external_attr >> 16), "ZIP symlink: " + entry.filename)
need(valid_pin(expected[entry.filename]), "invalid member pin: " + entry.filename)
need(entry.file_size == expected[entry.filename]["bytes"], "ZIP recorded size: " + entry.filename)
def ordered_times(*values):
times = [datetime.fromisoformat(value) for value in values]
return all(value.utcoffset() is not None for value in times) and times == sorted(times)
def verify_data(manifest, read):
"""Shared read-only verifier for packaged bytes or prepare's in-memory payload."""
need(manifest["schema"] == 1 and manifest["kind"] == "multiselect-cargo-gates", "manifest schema")
runs, logical, stored = manifest["runs"], manifest["logicalFiles"], manifest["members"]
need(isinstance(runs, dict) and bool(runs) and all(run_name(run) for run in runs), "explicit run inventory")
need(all(safe(name) for name in logical) and all(safe(name) for name in stored), "unsafe manifest path")
need(set(logical.values()) == set(stored), "unreferenced or absent stored members")
for name, expected in stored.items():
need(valid_pin(expected) and pin(read(name)) == expected, "stored member hash: " + name)
expected_logical = {"cargo/" + run + "/" + name for run in runs for name in RAW_FILES}
expected_logical.update(spec["helper"] for spec in runs.values())
need(set(logical) == expected_logical, "exact logical raw/helper inventory")
for name, destination in logical.items():
if name.startswith("cargo/") and name.rsplit("/", 1)[1] in {"inputs.json", "inputs.zip"}:
expected = "capsules/" + stored[destination]["sha256"] + PurePosixPath(name).suffix
need(destination == expected, "input capsule mapping: " + name)
else:
need(destination == name, "only input maps/archives may be deduplicated: " + name)
def raw(name):
return read(logical[name])
seen_capsules = set()
for run, spec in runs.items():
prefix = "cargo/" + run + "/"
start = parsed(raw(prefix + "started.json"))
process = parsed(raw(prefix + "process.json"))
result = parsed(raw(prefix + "result.json"))
required_start = {"start", "command", "cwd", "head", "scope", "inputs", "archive",
"inputCount", "environment", "helper", "cargo", "rustc"}
need(required_start <= start.keys(), run + ": incomplete start receipt")
need(all(result.get(key) == value for key, value in start.items()), run + ": start/result relationship")
command = result["command"]
need(isinstance(command, list) and command and command[0] == "cargo"
and all(isinstance(arg, str) for arg in command), run + ": Cargo command")
need(command == process["command"] == spec["command"], run + ": command relationship")
need(result["head"] == spec["head"] and re.fullmatch(r"(?:[0-9a-f]{40}|[0-9a-f]{64})", result["head"]), run + ": HEAD")
need(type(result["exitCode"]) is int and result["exitCode"] == spec["exitCode"], run + ": recorded exit")
need(result["inputsUnchanged"] is True, run + ": changed inputs refused")
need(type(result["seconds"]) in (int, float) and math.isfinite(result["seconds"])
and result["seconds"] >= 0, run + ": duration")
need(type(process["pid"]) is int and process["pid"] > 0, run + ": process identity")
need(ordered_times(start["start"], process["observed"], result["finish"]), run + ": completed timestamp order")
for field, filename in [("inputs", "inputs.json"), ("archive", "inputs.zip"), ("stdout", "stdout.log"), ("stderr", "stderr.log")]:
need(result[field] == pin(raw(prefix + filename)), run + ": " + field + " pin")
need(valid_pin(result["helper"]) and result["helper"] == pin(raw(spec["helper"])), run + ": helper pin")
need(spec["helper"] == "helpers/" + result["helper"]["sha256"] + ".py", run + ": helper mapping")
inputs = parsed(raw(prefix + "inputs.json"))
need(isinstance(inputs, dict) and all(safe(name) for name in inputs), run + ": safe input inventory")
need(type(result["inputCount"]) is int and len(inputs) == result["inputCount"] == spec["inputCount"], run + ": input counts")
need(sum(name.startswith("crates/vendor/iced_widget/") for name in inputs) == 71, run + ": vendor count")
capsule = (logical[prefix + "inputs.json"], logical[prefix + "inputs.zip"])
if capsule not in seen_capsules:
with zipfile.ZipFile(io.BytesIO(raw(prefix + "inputs.zip"))) as source:
inventory(source, inputs)
for name, expected in inputs.items():
need(pin(source.read(name)) == expected, run + ": source hash " + name)
seen_capsules.add(capsule)
artifacts = []
for line in raw(prefix + "stdout.log").decode("utf-8", errors="replace").splitlines():
try:
value = json.loads(line)
except json.JSONDecodeError:
continue
if isinstance(value, dict) and value.get("reason") == "compiler-artifact" and value.get("executable"):
artifacts.append(value)
need(isinstance(result["artifacts"], list), run + ": artifact records")
need(artifacts == [record["cargo"] for record in result["artifacts"]], run + ": Cargo JSON artifact relationship")
for record in result["artifacts"]:
need(set(record) == {"cargo", "readback"}
and (record["readback"] is None or valid_pin(record["readback"])), run + ": artifact readback pin")
print(run, "recorded exit", result["exitCode"], "inputs", len(inputs), "executable records", len(artifacts))
return {"runs": len(runs), "logicalFiles": len(logical), "storedMembers": len(stored), "sourceCapsulePairs": len(seen_capsules)}
def verify_package(root):
files = parsed((root / "files.json").read_bytes())
need(set(files) == OUTER_FILES, "outer file inventory")
for name, expected in files.items():
need(valid_pin(expected) and pin((root / name).read_bytes()) == expected, "outer hash: " + name)
manifest = parsed((root / "manifest.json").read_bytes())
with zipfile.ZipFile(root / "evidence.zip") as archive:
inventory(archive, manifest["members"])
return verify_data(manifest, archive.read)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("package", nargs="?", type=Path, default=Path(__file__).resolve().parent)
args = parser.parse_args()
print("PASS offline consistency:", verify_package(args.package))
print("Historical receipts only; no source/binary execution or native acceptance claim.")
if __name__ == "__main__":
main()
@@ -0,0 +1,35 @@
# Run-2 baseline checker environment incident
The first baseline checker invocation exited `3221225781` (`0xC0000135`) at
2026-09-23 09:07:10 UTC with empty stdout/stderr. The parent reported that this
shell omitted dot-sourcing the toolchain `env.ps1`. After that environment setup,
the same checker command succeeded at 09:08:08 UTC with a complete-Project PASS.
This records a checker-process launch incident, not a failure of the running GUI.
No particular missing DLL was measured or identified.
`run-2-baseline-runtime-environment/` is an exact copy of the failed snapshot:
started/result receipts, empty streams and all nine source files. Its unchanged
command text still names the original `run-2/snapshots/baseline` location; the
parent moved the failed directory aside before retrying. Paths in these records
are historical labels and have not been rewritten.
`retry-baseline/` preserves the successful retry's original started/result
receipts and streams. Direct comparison confirmed identical command, build
receipt, binary, helper, baseline and source pins between attempts. All three
unchanged flags are true in both results. The nine retry source files were
also compared byte for byte with the failed snapshot and are identical; they
are not duplicated here. The successful run's complete snapshots belong in the
separate native evidence package.
`helpers/check-snapshot-2.py` matches the helper pin in both receipts.
`helpers/env.ps1` preserves the environment setup script available when this
incident was packaged. It sets toolchain paths and runtime search paths and
contains no credentials. The checker receipts do not record the environment or
pin `env.ps1`, so the omitted/setup distinction is the parent's invocation
observation, not an independently measured environment comparison. Both scripts
are historical data; this package does not execute them.
The checker binary pin in both attempts is
`4de47a2b62192be6a1394e654f368be19e36fb966d60d6c833a5d51d18247bb1`.
`files.json` pins every included file except itself. Raw bytes are preserved.
No frozen checks, source-identity or native packaging tools were changed.
@@ -0,0 +1,82 @@
{
"helpers/check-snapshot-2.py": {
"bytes": 2494,
"sha256": "1dbfff41f07bd750d4e550660d91ae9790d2442fbfe685dc88b7f63a47f5acb8"
},
"helpers/env.ps1": {
"bytes": 621,
"sha256": "d7eb6249bef73adacdb05cebefe7ca478758c3c38de17a1731bf01f8b25dc379"
},
"README.md": {
"bytes": 2146,
"sha256": "d5a853c62713a6c87d28acfbe28c03bd95459275d0a2eb752d978e5a9b427bc8"
},
"retry-baseline/result.json": {
"bytes": 2758,
"sha256": "ae16cbc54bf5b6054750ef082f47bf0a26ee2dfb7bce46f19c8fd2c1ac622d7f"
},
"retry-baseline/started.json": {
"bytes": 2356,
"sha256": "e172a36f0872d49a8fe0f7200fb56d597b71fd1849dc9902d53ac1813a3c7d4a"
},
"retry-baseline/stderr.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"retry-baseline/stdout.log": {
"bytes": 441,
"sha256": "12842cc4e483e2546f5c8615b17fe72c5fe07f3fb4440469071433c82d9a9b30"
},
"run-2-baseline-runtime-environment/result.json": {
"bytes": 2765,
"sha256": "539b950952461cc300876dbc45fa9ee02a9ecefb6d712fce6b74bad3fa701b30"
},
"run-2-baseline-runtime-environment/source/oa/activities/activity_activity_a.arcadia": {
"bytes": 474,
"sha256": "9bf7c5637d87c97213cf869118e942e8a29a67b429fa58e4de42235bba0980ee"
},
"run-2-baseline-runtime-environment/source/oa/activities/activity_activity_b.arcadia": {
"bytes": 286,
"sha256": "152007669b7c570674aff99615a48a6f557be50f88bbbb3a5edc20b423c79a1f"
},
"run-2-baseline-runtime-environment/source/oa/activities/activity_activity_c.arcadia": {
"bytes": 153,
"sha256": "d726b6b4e1200edd9ef752bb767e38d3d69dcac8eb6135d5f83c93832ff849b1"
},
"run-2-baseline-runtime-environment/source/project.arcadia": {
"bytes": 597,
"sha256": "e7bd67c5785a78766298255ed3d53ff6d65dcd24bde1570ac8a0ff45cc9dc385"
},
"run-2-baseline-runtime-environment/source/sa/functions/function_sa_function.arcadia": {
"bytes": 162,
"sha256": "1c724a9204784435e729badd4ad164b1a6b891840bb1ddc354ac1e175e3d712c"
},
"run-2-baseline-runtime-environment/source/traceability.arcadia": {
"bytes": 522,
"sha256": "26b0b10715ced7aefcde941e6d1c1a6973f174997eae989e32a25c695dfb7cd1"
},
"run-2-baseline-runtime-environment/source/views/diagram_oa_other.arcadia": {
"bytes": 315,
"sha256": "06ceef9cfdbb3ef229a22db6c48d8bb808388e027c37294648555ecbfb6bfab9"
},
"run-2-baseline-runtime-environment/source/views/diagram_oa_view.arcadia": {
"bytes": 1896,
"sha256": "4e7d47d6a03153070687136c89faf01fc6df45ae89e2695beeab2fe4872dbc88"
},
"run-2-baseline-runtime-environment/source/views/diagram_sa_view.arcadia": {
"bytes": 331,
"sha256": "c75b0fe14496631c9b017a32e277d1e5ad5b25e00e06b804fc54d950d7fb57f6"
},
"run-2-baseline-runtime-environment/started.json": {
"bytes": 2356,
"sha256": "338c14c7dc827bd4ab09009bb974ad3c481b07cdbad2437f5291b1ff67b5ba42"
},
"run-2-baseline-runtime-environment/stderr.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"run-2-baseline-runtime-environment/stdout.log": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
}
@@ -0,0 +1,41 @@
"""Copy stable native-saved source and check its complete Project independently."""
from pathlib import Path
import datetime, hashlib, json, re, shutil, subprocess, sys
root = Path('C:/ar-multiselect-9e8r6t')
native = root / '.local/multiselect-native'
label, mode, *rest = sys.argv[1:]
assert not rest and re.fullmatch('[a-z0-9-]+', label)
working = native / 'working-2'
out = native / 'run-2/snapshots' / label
out.mkdir(parents=True, exist_ok=False)
gate_path = root / '.local/group-movement-gates/native-build-2/result.json'
gate = json.loads(gate_path.read_bytes())
assert gate['exitCode'] == 0 and gate['inputsUnchanged']
artifact, = [a for a in gate['artifacts'] if a['cargo']['target']['name'] == 'multiselect_native']
binary = Path(artifact['cargo']['executable'])
baseline = native / 'fixture-2/baseline.json'
def pin(path):
b = path.read_bytes()
return {'bytes': len(b), 'sha256': hashlib.sha256(b).hexdigest()}
def inventory():
return {p.relative_to(working).as_posix():pin(p) for p in sorted(working.rglob('*.arcadia')) if p.is_file()}
def now(): return datetime.datetime.now(datetime.timezone.utc).isoformat()
before = inventory()
assert 'project.arcadia' in before and pin(binary) == artifact['readback']
for name in before:
target = out/'source'/name
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(working/name, target)
assert before == inventory() == {name:pin(out/'source'/name) for name in before}
command = [str(binary), 'check', mode, str(baseline), str(out/'source/project.arcadia')]
start = {'start':now(), 'command':command, 'buildReceipt':pin(gate_path), 'binary':pin(binary), 'helper':pin(Path(__file__)), 'source':before, 'baseline':pin(baseline)}
(out/'started.json').write_text(json.dumps(start,indent=2),encoding='utf-8')
r = subprocess.run(command,cwd=root,capture_output=True)
(out/'stdout.log').write_bytes(r.stdout)
(out/'stderr.log').write_bytes(r.stderr)
result = {**start, 'finish':now(), 'exitCode':r.returncode, 'binaryUnchanged':pin(binary)==artifact['readback'], 'workingSourceUnchanged':before==inventory(), 'baselineUnchanged':pin(baseline)==start['baseline'], 'stdout':pin(out/'stdout.log'), 'stderr':pin(out/'stderr.log')}
(out/'result.json').write_text(json.dumps(result,indent=2),encoding='utf-8')
print(r.stdout.decode(errors='replace'))
print(r.stderr.decode(errors='replace'))
assert result['binaryUnchanged'] and result['workingSourceUnchanged'] and result['baselineUnchanged']
sys.exit(r.returncode)
@@ -0,0 +1,9 @@
$taskRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$env:RUSTUP_HOME = Join-Path $taskRoot '.local\toolchain\rustup'
$env:CARGO_HOME = Join-Path $taskRoot '.local\toolchain\cargo'
$env:RUSTUP_TOOLCHAIN = 'stable-x86_64-pc-windows-gnullvm'
$env:PATH = "$env:CARGO_HOME\bin;$(Join-Path $taskRoot '.local\toolchain\llvm-mingw-20260826-ucrt-x86_64\bin');$env:PATH"
$env:CARGO_TARGET_DIR = Join-Path $taskRoot '.local\target-gnullvm'
# Keep this small development disk from accumulating multi-GiB incremental caches.
$env:CARGO_INCREMENTAL = '0'
$env:CARGO_TARGET_X86_64_PC_WINDOWS_GNULLVM_LINKER = 'clang.exe'
@@ -0,0 +1,77 @@
{
"start": "2026-09-23T09:08:07.906733+00:00",
"command": [
"C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\target-gnullvm\\debug\\examples\\multiselect_native.exe",
"check",
"unchanged",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\fixture-2\\baseline.json",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\run-2\\snapshots\\baseline\\source\\project.arcadia"
],
"buildReceipt": {
"bytes": 3131,
"sha256": "fbecac3b0f7913db5e2ad19043c7df167a92287833ddf3ea4f24766e86ae523b"
},
"binary": {
"bytes": 22162432,
"sha256": "4de47a2b62192be6a1394e654f368be19e36fb966d60d6c833a5d51d18247bb1"
},
"helper": {
"bytes": 2494,
"sha256": "1dbfff41f07bd750d4e550660d91ae9790d2442fbfe685dc88b7f63a47f5acb8"
},
"source": {
"oa/activities/activity_activity_a.arcadia": {
"bytes": 474,
"sha256": "9bf7c5637d87c97213cf869118e942e8a29a67b429fa58e4de42235bba0980ee"
},
"oa/activities/activity_activity_b.arcadia": {
"bytes": 286,
"sha256": "152007669b7c570674aff99615a48a6f557be50f88bbbb3a5edc20b423c79a1f"
},
"oa/activities/activity_activity_c.arcadia": {
"bytes": 153,
"sha256": "d726b6b4e1200edd9ef752bb767e38d3d69dcac8eb6135d5f83c93832ff849b1"
},
"project.arcadia": {
"bytes": 597,
"sha256": "e7bd67c5785a78766298255ed3d53ff6d65dcd24bde1570ac8a0ff45cc9dc385"
},
"sa/functions/function_sa_function.arcadia": {
"bytes": 162,
"sha256": "1c724a9204784435e729badd4ad164b1a6b891840bb1ddc354ac1e175e3d712c"
},
"traceability.arcadia": {
"bytes": 522,
"sha256": "26b0b10715ced7aefcde941e6d1c1a6973f174997eae989e32a25c695dfb7cd1"
},
"views/diagram_oa_other.arcadia": {
"bytes": 315,
"sha256": "06ceef9cfdbb3ef229a22db6c48d8bb808388e027c37294648555ecbfb6bfab9"
},
"views/diagram_oa_view.arcadia": {
"bytes": 1896,
"sha256": "4e7d47d6a03153070687136c89faf01fc6df45ae89e2695beeab2fe4872dbc88"
},
"views/diagram_sa_view.arcadia": {
"bytes": 331,
"sha256": "c75b0fe14496631c9b017a32e277d1e5ad5b25e00e06b804fc54d950d7fb57f6"
}
},
"baseline": {
"bytes": 8944,
"sha256": "d1278e58cd31e1d61093292eddc1d7b2cc9c8cdc7fe5dd3801de8411af8db89d"
},
"finish": "2026-09-23T09:08:08.158861+00:00",
"exitCode": 0,
"binaryUnchanged": true,
"workingSourceUnchanged": true,
"baselineUnchanged": true,
"stdout": {
"bytes": 441,
"sha256": "12842cc4e483e2546f5c8615b17fe72c5fe07f3fb4440469071433c82d9a9b30"
},
"stderr": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
}
@@ -0,0 +1,64 @@
{
"start": "2026-09-23T09:08:07.906733+00:00",
"command": [
"C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\target-gnullvm\\debug\\examples\\multiselect_native.exe",
"check",
"unchanged",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\fixture-2\\baseline.json",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\run-2\\snapshots\\baseline\\source\\project.arcadia"
],
"buildReceipt": {
"bytes": 3131,
"sha256": "fbecac3b0f7913db5e2ad19043c7df167a92287833ddf3ea4f24766e86ae523b"
},
"binary": {
"bytes": 22162432,
"sha256": "4de47a2b62192be6a1394e654f368be19e36fb966d60d6c833a5d51d18247bb1"
},
"helper": {
"bytes": 2494,
"sha256": "1dbfff41f07bd750d4e550660d91ae9790d2442fbfe685dc88b7f63a47f5acb8"
},
"source": {
"oa/activities/activity_activity_a.arcadia": {
"bytes": 474,
"sha256": "9bf7c5637d87c97213cf869118e942e8a29a67b429fa58e4de42235bba0980ee"
},
"oa/activities/activity_activity_b.arcadia": {
"bytes": 286,
"sha256": "152007669b7c570674aff99615a48a6f557be50f88bbbb3a5edc20b423c79a1f"
},
"oa/activities/activity_activity_c.arcadia": {
"bytes": 153,
"sha256": "d726b6b4e1200edd9ef752bb767e38d3d69dcac8eb6135d5f83c93832ff849b1"
},
"project.arcadia": {
"bytes": 597,
"sha256": "e7bd67c5785a78766298255ed3d53ff6d65dcd24bde1570ac8a0ff45cc9dc385"
},
"sa/functions/function_sa_function.arcadia": {
"bytes": 162,
"sha256": "1c724a9204784435e729badd4ad164b1a6b891840bb1ddc354ac1e175e3d712c"
},
"traceability.arcadia": {
"bytes": 522,
"sha256": "26b0b10715ced7aefcde941e6d1c1a6973f174997eae989e32a25c695dfb7cd1"
},
"views/diagram_oa_other.arcadia": {
"bytes": 315,
"sha256": "06ceef9cfdbb3ef229a22db6c48d8bb808388e027c37294648555ecbfb6bfab9"
},
"views/diagram_oa_view.arcadia": {
"bytes": 1896,
"sha256": "4e7d47d6a03153070687136c89faf01fc6df45ae89e2695beeab2fe4872dbc88"
},
"views/diagram_sa_view.arcadia": {
"bytes": 331,
"sha256": "c75b0fe14496631c9b017a32e277d1e5ad5b25e00e06b804fc54d950d7fb57f6"
}
},
"baseline": {
"bytes": 8944,
"sha256": "d1278e58cd31e1d61093292eddc1d7b2cc9c8cdc7fe5dd3801de8411af8db89d"
}
}
@@ -0,0 +1,9 @@
{
"baseline": "C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\fixture-2\\baseline.json",
"comparison": "complete Project equality",
"inferred_common_delta": null,
"limits": "Invariant evaluator only; no pointer/action/focus/Undo/source-byte acceptance claim",
"mode": "unchanged",
"result": "PASS",
"saved": "C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\run-2\\snapshots\\baseline\\source\\project.arcadia"
}
@@ -0,0 +1,77 @@
{
"start": "2026-09-23T09:07:10.546708+00:00",
"command": [
"C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\target-gnullvm\\debug\\examples\\multiselect_native.exe",
"check",
"unchanged",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\fixture-2\\baseline.json",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\run-2\\snapshots\\baseline\\source\\project.arcadia"
],
"buildReceipt": {
"bytes": 3131,
"sha256": "fbecac3b0f7913db5e2ad19043c7df167a92287833ddf3ea4f24766e86ae523b"
},
"binary": {
"bytes": 22162432,
"sha256": "4de47a2b62192be6a1394e654f368be19e36fb966d60d6c833a5d51d18247bb1"
},
"helper": {
"bytes": 2494,
"sha256": "1dbfff41f07bd750d4e550660d91ae9790d2442fbfe685dc88b7f63a47f5acb8"
},
"source": {
"oa/activities/activity_activity_a.arcadia": {
"bytes": 474,
"sha256": "9bf7c5637d87c97213cf869118e942e8a29a67b429fa58e4de42235bba0980ee"
},
"oa/activities/activity_activity_b.arcadia": {
"bytes": 286,
"sha256": "152007669b7c570674aff99615a48a6f557be50f88bbbb3a5edc20b423c79a1f"
},
"oa/activities/activity_activity_c.arcadia": {
"bytes": 153,
"sha256": "d726b6b4e1200edd9ef752bb767e38d3d69dcac8eb6135d5f83c93832ff849b1"
},
"project.arcadia": {
"bytes": 597,
"sha256": "e7bd67c5785a78766298255ed3d53ff6d65dcd24bde1570ac8a0ff45cc9dc385"
},
"sa/functions/function_sa_function.arcadia": {
"bytes": 162,
"sha256": "1c724a9204784435e729badd4ad164b1a6b891840bb1ddc354ac1e175e3d712c"
},
"traceability.arcadia": {
"bytes": 522,
"sha256": "26b0b10715ced7aefcde941e6d1c1a6973f174997eae989e32a25c695dfb7cd1"
},
"views/diagram_oa_other.arcadia": {
"bytes": 315,
"sha256": "06ceef9cfdbb3ef229a22db6c48d8bb808388e027c37294648555ecbfb6bfab9"
},
"views/diagram_oa_view.arcadia": {
"bytes": 1896,
"sha256": "4e7d47d6a03153070687136c89faf01fc6df45ae89e2695beeab2fe4872dbc88"
},
"views/diagram_sa_view.arcadia": {
"bytes": 331,
"sha256": "c75b0fe14496631c9b017a32e277d1e5ad5b25e00e06b804fc54d950d7fb57f6"
}
},
"baseline": {
"bytes": 8944,
"sha256": "d1278e58cd31e1d61093292eddc1d7b2cc9c8cdc7fe5dd3801de8411af8db89d"
},
"finish": "2026-09-23T09:07:10.828848+00:00",
"exitCode": 3221225781,
"binaryUnchanged": true,
"workingSourceUnchanged": true,
"baselineUnchanged": true,
"stdout": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"stderr": {
"bytes": 0,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
}
@@ -0,0 +1,14 @@
oa_activity activity_a "A - receive request" id "f0149281-4798-58d3-acff-131eed250959" {
description "Preserve engineering record activity_a.";
}
oa_activity activity_child "A.1 - classify request" id "5a80d3af-c7ee-59eb-9680-eb80d60cb94f" {
description "Preserve engineering record activity_child.";
parent @activity_a;
}
interaction internal "Request assessment" id "be7a39d9-3463-534e-b37b-76a74077d434" {
source @activity_a;
target @activity_b;
}
@@ -0,0 +1,9 @@
oa_activity activity_b "B - assess request" id "ecf076b7-e8be-5f64-8808-6a2edae5b9e2" {
description "Preserve engineering record activity_b.";
}
interaction external "Response decision" id "927dfa82-40d2-5c5f-a525-6a884725ea1d" {
source @activity_b;
target @activity_c;
}
@@ -0,0 +1,4 @@
oa_activity activity_c "C - dispatch response" id "3b258d00-854d-5ddd-a057-16eedbe31714" {
description "Preserve engineering record activity_c.";
}
@@ -0,0 +1,12 @@
arcadia 7;
project multiselect_native "Multiselect native" id "c1deb118-0fb0-5692-8b80-d24339e5b6c3" {
description "Shift-select A and B; move together, retain C and engineering semantics.";
include "oa/activities/activity_activity_a.arcadia";
include "oa/activities/activity_activity_b.arcadia";
include "oa/activities/activity_activity_c.arcadia";
include "sa/functions/function_sa_function.arcadia";
include "traceability.arcadia";
include "views/diagram_oa_other.arcadia";
include "views/diagram_oa_view.arcadia";
include "views/diagram_sa_view.arcadia";
}
@@ -0,0 +1,4 @@
sa_function sa_function "Technical request processing" id "878a1b33-a7c2-5a68-a8b6-d8273c6354e0" {
description "Preserve engineering record sa_function.";
}
@@ -0,0 +1,16 @@
trace preserved_refinement "Reviewed request refinement" id "b42fb6e3-db90-5349-b957-faeba373ba91" {
baseline {
oa {
description "Preserve engineering record activity_a.";
name "A - receive request";
};
sa {
description "Preserve engineering record sa_function.";
name "Technical request processing";
};
};
description "Group geometry and Hide preserve this trace and both endpoints.";
oa @activity_a;
sa @sa_function;
}
@@ -0,0 +1,13 @@
diagram oa_other "Other OA view - preserve" id "c4a58011-d2d7-59b1-ad58-feacef0e2d78" {
description "Selection changes placement geometry only.";
}
node other_a id "9aa9a68b-4c26-5d21-bc35-63d3f0f311d6" {
diagram @oa_other;
element @activity_a;
position {
x 40.0;
y 60.0;
};
}
@@ -0,0 +1,93 @@
diagram oa_view "Multiselect native - OA overview" id "00000000-0000-0000-0000-000000290001" {
description "Selection changes placement geometry only.";
routes [{
edge @internal;
label {
fraction 0.44999998807907104;
offset {
x 7.0;
y -19.0;
};
};
source_attachment {
offset 0.25;
side Right;
};
target_attachment {
offset 0.699999988079071;
side Left;
};
waypoints [{
x 420.0;
y 145.0;
}, {
x 420.0;
y 186.0;
}];
}, {
edge @external;
label {
fraction 0.44999998807907104;
offset {
x 7.0;
y -19.0;
};
};
source_attachment {
offset 0.25;
side Right;
};
target_attachment {
offset 0.699999988079071;
side Left;
};
waypoints [{
x 725.0;
y 150.0;
}, {
x 725.0;
y 336.0;
}];
}];
}
node node_a id "2670dd46-9fe7-5047-b13d-59817cff96dd" {
diagram @oa_view;
element @activity_a;
position {
x 80.0;
y 80.0;
};
size {
height 260.0;
width 310.0;
};
}
node node_b id "70e322db-f401-58c8-a50e-2f71c61ad721" {
diagram @oa_view;
element @activity_b;
position {
x 470.0;
y 120.0;
};
}
node node_c id "d6b89a5a-6e2f-50f9-9d1e-993304a54583" {
diagram @oa_view;
element @activity_c;
position {
x 780.0;
y 270.0;
};
}
node node_child id "87f4652b-15ef-55ed-ad7e-cc5d22b7facb" {
diagram @oa_view;
element @activity_child;
position {
x 120.0;
y 210.0;
};
}
@@ -0,0 +1,14 @@
diagram sa_view "SA engineering - preserve" id "637b9a3e-bd74-534c-9be5-4470a408729f" {
description "Selection changes placement geometry only.";
layer Sa;
}
node sa_node id "5f1b1c24-0583-5923-a69c-d0ea99ccb18c" {
diagram @sa_view;
element @sa_function;
position {
x 100.0;
y 110.0;
};
}
@@ -0,0 +1,64 @@
{
"start": "2026-09-23T09:07:10.546708+00:00",
"command": [
"C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\target-gnullvm\\debug\\examples\\multiselect_native.exe",
"check",
"unchanged",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\fixture-2\\baseline.json",
"C:\\ar-multiselect-9e8r6t\\.local\\multiselect-native\\run-2\\snapshots\\baseline\\source\\project.arcadia"
],
"buildReceipt": {
"bytes": 3131,
"sha256": "fbecac3b0f7913db5e2ad19043c7df167a92287833ddf3ea4f24766e86ae523b"
},
"binary": {
"bytes": 22162432,
"sha256": "4de47a2b62192be6a1394e654f368be19e36fb966d60d6c833a5d51d18247bb1"
},
"helper": {
"bytes": 2494,
"sha256": "1dbfff41f07bd750d4e550660d91ae9790d2442fbfe685dc88b7f63a47f5acb8"
},
"source": {
"oa/activities/activity_activity_a.arcadia": {
"bytes": 474,
"sha256": "9bf7c5637d87c97213cf869118e942e8a29a67b429fa58e4de42235bba0980ee"
},
"oa/activities/activity_activity_b.arcadia": {
"bytes": 286,
"sha256": "152007669b7c570674aff99615a48a6f557be50f88bbbb3a5edc20b423c79a1f"
},
"oa/activities/activity_activity_c.arcadia": {
"bytes": 153,
"sha256": "d726b6b4e1200edd9ef752bb767e38d3d69dcac8eb6135d5f83c93832ff849b1"
},
"project.arcadia": {
"bytes": 597,
"sha256": "e7bd67c5785a78766298255ed3d53ff6d65dcd24bde1570ac8a0ff45cc9dc385"
},
"sa/functions/function_sa_function.arcadia": {
"bytes": 162,
"sha256": "1c724a9204784435e729badd4ad164b1a6b891840bb1ddc354ac1e175e3d712c"
},
"traceability.arcadia": {
"bytes": 522,
"sha256": "26b0b10715ced7aefcde941e6d1c1a6973f174997eae989e32a25c695dfb7cd1"
},
"views/diagram_oa_other.arcadia": {
"bytes": 315,
"sha256": "06ceef9cfdbb3ef229a22db6c48d8bb808388e027c37294648555ecbfb6bfab9"
},
"views/diagram_oa_view.arcadia": {
"bytes": 1896,
"sha256": "4e7d47d6a03153070687136c89faf01fc6df45ae89e2695beeab2fe4872dbc88"
},
"views/diagram_sa_view.arcadia": {
"bytes": 331,
"sha256": "c75b0fe14496631c9b017a32e277d1e5ad5b25e00e06b804fc54d950d7fb57f6"
}
},
"baseline": {
"bytes": 8944,
"sha256": "d1278e58cd31e1d61093292eddc1d7b2cc9c8cdc7fe5dd3801de8411af8db89d"
}
}
@@ -0,0 +1,91 @@
# Native multiselect evidence package
This package preserves native run-1 and run-2, both closed with exit 0, empty app
stdout/stderr and all three GUI/checker/fixture unchanged flags true. Each run
contains nine positive complete-Project checker snapshots, nine source files per
snapshot and three exact source-history equality groups. Only
`views/diagram_oa_view.arcadia` differs from baseline in its move and hidden
states. These artifacts do not establish native acceptance on their own; consult
the separate [saved-view report](../../../multiselect-saved-view-20260923.md) for
action observations, usability findings and the implemented subset of issue 29.
| Run | Source commit | Captures | Layout scope |
| --- | --- | ---: | --- |
| run-1 | `12a7352ddef5f69a144ead8219a50916233d63a9` | 27 | Before selection/status toolbar correction |
| run-2 | `f6a6010baed9e6164a1fcc7ecd58256a562827d7` | 24 | Corrected toolbar layout build |
Run-1 GUI/checker build receipts refer to the 729-file input map
`55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb`;
run-2 refers to the distinct 729-file map
`99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c`.
The [source identity evidence](../source/README.md) ties those maps to the commits
above. The GUI binary pins differ; the recorded checker binary pins match.
Run-1 is retained as evidence of the earlier layout, not as verification of the
corrected build.
The first run-2 baseline checker attempt failed before the successful retry after
the toolchain environment was initialized. Its unchanged raw snapshot and retry
comparison are preserved separately in the [environment incident](../incidents/README.md).
The successful retry is the baseline snapshot included in this native package;
the failed invocation is not silently reclassified or presented as a GUI failure.
These Python 3.10+ standard-library tools never operate the GUI or rerun the model
checker. From the checkout root, validate both raw runs without writing a package:
```text
python -B harness/experiments/multiselect-20260923/native/prepare.py --root . --runs run-1 run-2 --check-only
```
Omit `--check-only` to package; optionally choose `--output DIRECTORY`. The default
is this native directory. Existing package outputs are not overwritten. A missing
or unfinished run, changed recorded inputs, missing/extra fixture or snapshot
files, unmatched helper bytes, or inconsistent receipts fails preparation.
Verify a completed package independently of the original machine:
```text
python -B PATH_TO_PACKAGE/verify.py
```
Each run includes all original capture JSON/images, process/start/finish records,
generation and app streams, all nine source snapshots and checker streams/receipts,
and the history-bytes record. Its fixture includes baseline JSON, the manifest,
and canonical source files. Exact helpers are found by their recorded hashes among
the native directory's `.py`/`.js` files, so original and suffixed run-2 helpers can
coexist. Helpers are archived as data and never executed by these tools.
Referenced GUI/checker build results, exact gate helpers and input maps are
included. The checker example is read from its pinned historical input ZIP, not
from current source.
Full build logs and large source ZIPs belong in the sibling `checks` package;
verify that package separately. This package validates build receipt, input map,
example-source and executable-pin relationships without duplicating those ZIPs.
It does not contain or execute the GUI/checker binaries.
The verifier checks every archived byte pin and exact safe membership, clean
recorded exit and unchanged flags, process and capture lifetimes, each capture's
normalized executable path against the launched GUI, one consistent positive
window ID per run, fixture/source inventories, nine positive complete-Project
checker reports, baseline/binary/helper
relationships, and the actual archived bytes in three history equality groups.
It verifies that only `views/diagram_oa_view.arcadia` differs from baseline in the
move and hidden source states, and that baseline source bytes match the fixture.
Window identity checks join recorded metadata; the receipts do not independently
map that window handle to the recorded PID. Source models are not recompiled by
this offline Python verifier. Screenshot dimensions are recorded metadata, not a
minimum-window usability evaluation.
`manifest.json` maps each run's original historical paths to archived run,
fixture, helper, build and checker-source members and pins their bytes.
`files.json` pins the packager, verifier, README, manifest and archive. Raw bytes
are preserved; ZIP ordering and timestamps are fixed. Historic absolute paths are
labels and are not accessed by offline verification.
GUI actions remain separately documented parent observations. Screenshots do
not prove which inputs occurred, and the checker infers a bounded common delta
from saved geometry; it cannot validate the exact pointer destination. Source
history byte equality supports the stated saved-state relationships but does not
independently authenticate button presses, focus behavior or Undo stack structure.
Run-1 evidence does not establish the corrected toolbar's usability or any later
binary's behavior. Consult the parent report for the evaluated version, observed
limitations, run differences and the remaining full-issue acceptance work.
@@ -0,0 +1,22 @@
{
"prepare.py": {
"bytes": 7237,
"sha256": "d9d49d3082e485e670b43010822ebd3ab7a79762b36a247dcd3bdfc6b5d7f41d"
},
"verify.py": {
"bytes": 14703,
"sha256": "7ef5f28b6c9a43bf0361eec2d8be33a1e9f284d0ffc21b50fd09a2d082642ce3"
},
"README.md": {
"bytes": 5418,
"sha256": "8d6fa25d8bd97c654e78b89194bd499637427ce027157d568215e13421b22c03"
},
"manifest.json": {
"bytes": 72794,
"sha256": "de7642ad43aa881f7d984629db52ea41b62d0ebacc09260edd80a5c1fee7dd7b"
},
"evidence.zip": {
"bytes": 4399281,
"sha256": "7dc3e0571179e0f67fefe3c73462308b79e4c7f7a09bbd805e0acf0e4faeb1cf"
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,129 @@
"""Package explicit completed native runs; helpers are pinned data, never executed."""
from pathlib import Path
import argparse
import json
import re
import zipfile
from verify import pin, parsed, need, norm, relative, safe, verify_data, verify_package
HERE = Path(__file__).resolve().parent
def collect(root, runs):
native = root / ".local/multiselect-native"
candidates = [path for path in native.iterdir() if path.is_file() and path.suffix in (".py", ".js")]
candidates.extend(sorted((root / ".local/group-movement-gates").glob("*.py")))
helpers = [(path.suffix, path.read_bytes()) for path in candidates]
payload, specs = {}, {}
def add(name, data):
need(safe(name) and (name not in payload or payload[name] == data), "member collision: " + name)
payload[name] = data
def tree(folder, prefix):
need(folder.is_dir(), "missing directory: " + str(folder))
for path in sorted(folder.rglob("*")):
need(not path.is_symlink(), "symlink evidence input")
if path.is_file():
add(prefix + path.relative_to(folder).as_posix(), path.read_bytes())
for run in runs:
folder = native / run
start = parsed((folder / "started.json").read_bytes())
end = parsed((folder / "finished.json").read_bytes())
need(end["exitCode"] == 0 and all(end[k] is True for k in
("guiUnchanged", "checkerUnchanged", "fixtureUnchanged")), "unfinished/changed native run: " + run)
generation = parsed((folder / "generation.json").read_bytes())
history = parsed((folder / "history-bytes.json").read_bytes())
tree(folder, "runs/" + run + "/raw/")
fixture_relative = relative(generation["command"][2], start["cwd"])
need(fixture_relative.startswith(".local/multiselect-native/"), "fixture outside native root")
tree(root / fixture_relative, "runs/" + run + "/fixture/")
spec = {"originalRun": norm(start["cwd"]) + "/.local/multiselect-native/" + run,
"originalFixture": norm(generation["command"][2]), "helpers": {}, "builds": {}}
for key, expected in [("helper", start["helper"]), ("capture", start["capture"]),
("snapshotHelper", start["snapshotHelper"]), ("history", history["helper"])]:
matches = [(suffix, data) for suffix, data in helpers if pin(data) == expected]
need(bool(matches), "exact historical helper unavailable: " + key)
suffix, data = matches[0]
member = "helpers/" + expected["sha256"] + suffix
add(member, data)
spec["helpers"][key] = member
for kind in ("gui", "checker"):
recorded = start[kind]
rel = relative(recorded["receipt"], start["cwd"])
need(rel.startswith(".local/group-movement-gates/") and rel.endswith("/result.json"), "unexpected build receipt location")
receipt = root / rel
data = receipt.read_bytes()
need(pin(data) == recorded["receiptPin"], "historical build receipt changed")
prefix = "builds/" + pin(data)["sha256"] + "/"
add(prefix + "result.json", data)
inputs_data = (receipt.parent / "inputs.json").read_bytes()
need(pin(inputs_data) == recorded["inputs"], "historical build input map changed")
add(prefix + "inputs.json", inputs_data)
spec["builds"][kind] = {"receipt": prefix + "result.json", "inputs": prefix + "inputs.json", "originalRelative": rel}
build_helper = parsed(data)["helper"]
matching_helpers = [(suffix, value) for suffix, value in helpers if pin(value) == build_helper]
need(bool(matching_helpers), "exact historical build helper unavailable")
suffix, helper_data = matching_helpers[0]
helper_member = "helpers/" + build_helper["sha256"] + suffix
add(helper_member, helper_data)
spec["builds"][kind]["helper"] = helper_member
if kind == "checker":
# Read only the pinned historical example, not today's checkout.
archive_path = receipt.parent / "inputs.zip"
need(pin(archive_path.read_bytes()) == parsed(data)["archive"], "checker input archive pin")
source_path = "crates/oa-core/examples/multiselect_native.rs"
with zipfile.ZipFile(archive_path) as archive:
source = archive.read(source_path)
need(pin(source) == parsed(inputs_data)[source_path], "historical checker source pin")
member = "checker-source/" + pin(source)["sha256"] + ".rs"
add(member, source)
spec["checkerSource"] = {"inputPath": source_path, "member": member}
specs[run] = spec
manifest = {"schema": 1, "kind": "multiselect-native", "runs": specs,
"members": {name: pin(data) for name, data in sorted(payload.items())}}
summary = verify_data(manifest, payload.__getitem__)
return payload, manifest, summary
def write_json(path, value):
with path.open("xb") as stream:
stream.write((json.dumps(value, indent=2) + "\n").encode())
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=HERE.parents[3])
parser.add_argument("--runs", nargs="+", required=True)
parser.add_argument("--output", type=Path, default=HERE)
parser.add_argument("--check-only", action="store_true")
args = parser.parse_args()
need(len(args.runs) == len(set(args.runs)) and all(re.fullmatch(r"run-[0-9]+", name) for name in args.runs), "explicit unique run-N names required")
payload, manifest, summary = collect(args.root.resolve(), args.runs)
if args.check_only:
print("PASS raw consistency; no archive written:", summary)
return
out = args.output.resolve()
out.mkdir(parents=True, exist_ok=True)
for name in ("evidence.zip", "manifest.json", "files.json"):
need(not (out / name).exists(), "existing output refused: " + name)
for name in ("prepare.py", "verify.py", "README.md"):
data = (HERE / name).read_bytes()
if (out / name).exists():
need((out / name).read_bytes() == data, "different existing package tool")
else:
with (out / name).open("xb") as stream:
stream.write(data)
with zipfile.ZipFile(out / "evidence.zip", "x", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as archive:
for name, data in sorted(payload.items()):
info = zipfile.ZipInfo(name, date_time=(2026, 9, 23, 0, 0, 0))
info.compress_type = zipfile.ZIP_DEFLATED
info.external_attr = 0o100644 << 16
archive.writestr(info, data)
write_json(out / "manifest.json", manifest)
names = ("prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip")
write_json(out / "files.json", {name: pin((out / name).read_bytes()) for name in names})
need(verify_package(out) == summary, "written package differs from validated evidence")
print("PASS package readback:", out, summary)
if __name__ == "__main__":
main()
@@ -0,0 +1,235 @@
"""Verify archived native receipts and bytes; do not rerun the GUI or checker."""
from pathlib import Path, PurePosixPath
from datetime import datetime
import argparse
import hashlib
import json
import math
import stat
import zipfile
BASE = {"started.json", "finished.json", "generation.json", "generation.stdout.log",
"generation.stderr.log", "app.stdout.log", "app.stderr.log", "processes.json", "history-bytes.json"}
GROUPS = [["baseline", "move-undo", "before-hide", "hide-undo"], ["move", "move-redo"],
["hidden", "hide-redo", "reopened-hidden"]]
MODES = {name: mode for group, mode in zip(GROUPS, ["unchanged", "moved", "hide"]) for name in group}
OUTER = {"prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip"}
def need(ok, message):
if not ok:
raise ValueError(message)
def pin(data):
return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
def safe(name):
return (isinstance(name, str) and bool(name) and "\\" not in name and ":" not in name
and not PurePosixPath(name).is_absolute() and all(ord(c) >= 32 for c in name)
and all(part not in ("", ".", "..") for part in name.split("/")))
def parsed(data):
def unique(items):
result = {}
for key, value in items:
need(key not in result, "duplicate JSON key: " + key)
result[key] = value
return result
return json.loads(data, object_pairs_hook=unique)
def norm(path):
return path.replace("\\", "/").rstrip("/")
def relative(path, root):
prefix = norm(root) + "/"
need(norm(path).startswith(prefix), "recorded path outside owner: " + path)
value = norm(path)[len(prefix):]
need(safe(value), "unsafe recorded relative path")
return value
def ordered(*values):
times = [datetime.fromisoformat(value) for value in values]
return all(t.utcoffset() is not None for t in times) and times == sorted(times)
def zip_inventory(archive, members):
names = archive.namelist()
need(len(names) == len(set(names)) and set(names) == set(members), "exact archive members")
for info in archive.infolist():
need(safe(info.filename) and not info.is_dir() and not stat.S_ISLNK(info.external_attr >> 16), "unsafe archive member")
need(info.file_size == members[info.filename]["bytes"], "archive member size")
def verify_data(manifest, read):
need(manifest["schema"] == 1 and manifest["kind"] == "multiselect-native", "manifest kind")
members, runs = manifest["members"], manifest["runs"]
need(bool(runs) and all(safe(run) and "/" not in run for run in runs), "run names")
need(all(safe(name) for name in members), "safe member names")
for name, expected in members.items():
need(pin(read(name)) == expected, "member pin: " + name)
used = set()
def raw(name):
need(name in members, "missing member: " + name)
used.add(name)
return read(name)
def obj(name):
return parsed(raw(name))
def tree(prefix):
return {name[len(prefix):]: raw(name) for name in members if name.startswith(prefix)}
def pinned_tree(prefix, expected):
actual = tree(prefix)
need({name: pin(data) for name, data in actual.items()} == expected, "exact pinned tree: " + prefix)
return actual
for run, spec in runs.items():
prefix = "runs/" + run + "/raw/"
start, end = obj(prefix + "started.json"), obj(prefix + "finished.json")
generation, process = obj(prefix + "generation.json"), obj(prefix + "processes.json")
history = obj(prefix + "history-bytes.json")
need(end["exitCode"] == 0 and all(end[key] is True for key in
("guiUnchanged", "checkerUnchanged", "fixtureUnchanged")), run + ": clean unchanged closure")
need(ordered(generation["start"], generation["finish"], process["CreationDate"], start["start"], end["finish"], history["verified"]), run + ": process/generation times")
need(process["ProcessId"] == start["pid"] and type(start["pid"]) is int and start["pid"] > 0, run + ": process identity")
need(norm(process["ExecutablePath"]) == norm(start["gui"]["binary"])
and start["command"] == [start["gui"]["binary"]], run + ": GUI command")
need(spec["originalRun"] == norm(start["cwd"]) + "/.local/multiselect-native/" + run, run + ": original run mapping")
need(generation["exitCode"] == 0 and generation["checker"] == start["checker"], run + ": generation checker")
need(generation["command"][:2] == [start["checker"]["binary"], "generate"]
and len(generation["command"]) == 3 and norm(generation["command"][2]) == spec["originalFixture"], run + ": generation command")
for stream in ("stdout", "stderr"):
need(end[stream] == pin(raw(prefix + "app." + stream + ".log")), run + ": app stream")
need(generation[stream] == pin(raw(prefix + "generation." + stream + ".log")), run + ": generation stream")
fixture = pinned_tree("runs/" + run + "/fixture/", start["fixture"])
need(set(fixture) == {"baseline.json", "manifest.json"} | {"source/" + name for name in
obj(prefix + "snapshots/baseline/result.json")["source"]}, run + ": fixture membership")
fixture_manifest = parsed(fixture["manifest.json"])
need(fixture_manifest["fixture"] == "multiselect-native-20260923"
and fixture_manifest["source_entry"] == "project.arcadia", run + ": fixture identity")
need(parsed(fixture["baseline.json"])["id"] == fixture_manifest["ids"]["project"], run + ": baseline identity")
for key, expected in [("helper", start["helper"]), ("capture", start["capture"]),
("snapshotHelper", start["snapshotHelper"]), ("history", history["helper"])]:
need(pin(raw(spec["helpers"][key])) == expected, run + ": helper " + key)
builds = {}
for kind, target in [("gui", "arcadia-studio"), ("checker", "multiselect_native")]:
recorded = start[kind]
build = obj(spec["builds"][kind]["receipt"])
need(pin(raw(spec["builds"][kind]["receipt"])) == recorded["receiptPin"], run + ": build receipt pin")
need(relative(recorded["receipt"], start["cwd"]) == spec["builds"][kind]["originalRelative"], run + ": build path mapping")
need(build["exitCode"] == 0 and build["inputsUnchanged"] is True
and ordered(build["start"], build["finish"], generation["start"]), run + ": accepted preceding build")
need(build["inputs"] == recorded["inputs"] == pin(raw(spec["builds"][kind]["inputs"])), run + ": build input map")
need(pin(raw(spec["builds"][kind]["helper"])) == build["helper"], run + ": build helper pin")
inputs = obj(spec["builds"][kind]["inputs"])
need(len(inputs) == build["inputCount"] and sum(name.startswith("crates/vendor/iced_widget/") for name in inputs) == 71, run + ": build input count")
artifacts = [item for item in build["artifacts"] if item["cargo"]["target"]["name"] == target]
need(len(artifacts) == 1 and artifacts[0]["readback"] == recorded["pin"]
and artifacts[0]["cargo"]["executable"] == recorded["binary"], run + ": executable relationship")
builds[kind] = inputs
need(start["gui"]["inputs"] == start["checker"]["inputs"], run + ": matching GUI/checker inputs")
source = spec["checkerSource"]
need(source["inputPath"] == "crates/oa-core/examples/multiselect_native.rs"
and pin(raw(source["member"])) == builds["checker"][source["inputPath"]], run + ": archived exact checker source")
top = {name[len(prefix):] for name in members if name.startswith(prefix) and "/" not in name[len(prefix):]}
captures = sorted(name for name in top - BASE if name.endswith(".json"))
need(bool(captures), run + ": missing captures")
expected_top = set(BASE) | set(captures)
captured_window = None
for name in captures:
capture = obj(prefix + name)
need(ordered(start["start"], capture["time"], end["finish"]), run + ": capture lifetime")
window = capture["window"]
app = window["app"]
need(isinstance(app, str) and app.startswith("process:")
and norm(app[len("process:"):]) == norm(start["gui"]["binary"]), run + ": captured executable relationship")
need(type(window["id"]) is int and window["id"] > 0, run + ": captured window identity")
if captured_window is None:
captured_window = window["id"]
need(window["id"] == captured_window, run + ": inconsistent captured window identity")
need(isinstance(capture["images"], list), run + ": capture images")
for image in capture["images"]:
filename = image["file"]
need(safe(filename) and "/" not in filename and filename.startswith(name[:-5] + "-")
and filename.endswith((".jpg", ".png")), run + ": capture image mapping")
need(type(image["width"]) is int and image["width"] > 0
and type(image["height"]) is int and image["height"] > 0, run + ": image dimensions")
need(filename not in expected_top, run + ": duplicate image reference")
expected_top.add(filename)
raw(prefix + filename)
need(top == expected_top, run + ": extra/missing top-level run files")
snapshots = {name[len(prefix + "snapshots/"):].split("/")[0] for name in members if name.startswith(prefix + "snapshots/")}
need(snapshots == set(MODES), run + ": exact nine snapshot labels")
states = {}
for label, mode in MODES.items():
folder = prefix + "snapshots/" + label + "/"
began, result = obj(folder + "started.json"), obj(folder + "result.json")
need(all(result.get(key) == value for key, value in began.items()), label + ": start/result")
need(result["exitCode"] == 0 and all(result[key] is True for key in
("binaryUnchanged", "workingSourceUnchanged", "baselineUnchanged")), label + ": unchanged successful checker")
need(ordered(start["start"], result["start"], result["finish"], end["finish"]), label + ": checker lifetime")
need(result["buildReceipt"] == start["checker"]["receiptPin"] and result["binary"] == start["checker"]["pin"]
and result["helper"] == start["snapshotHelper"], label + ": checker provenance")
need(result["baseline"] == pin(fixture["baseline.json"]), label + ": baseline pin")
command = result["command"]
need(len(command) == 5 and command[:3] == [start["checker"]["binary"], "check", mode]
and norm(command[3]) == spec["originalFixture"] + "/baseline.json"
and norm(command[4]) == spec["originalRun"] + "/snapshots/" + label + "/source/project.arcadia", label + ": exact checker command")
for stream in ("stdout", "stderr"):
need(result[stream] == pin(raw(folder + stream + ".log")), label + ": stream pin")
need(not raw(folder + "stderr.log"), label + ": checker stderr")
report = obj(folder + "stdout.log")
need(report["result"] == "PASS" and report["comparison"] == "complete Project equality"
and report["mode"] == mode and report["baseline"] == command[3] and report["saved"] == command[4], label + ": positive checker report")
delta = report["inferred_common_delta"]
if mode == "moved":
need(isinstance(delta, dict) and set(delta) == {"x", "y"}
and all(type(v) in (int, float) and math.isfinite(v) and abs(v) <= 500 for v in delta.values())
and math.hypot(delta["x"], delta["y"]) >= 10, label + ": inferred movement bounds")
else:
need(delta is None, label + ": unexpected inferred delta")
states[label] = pinned_tree(folder + "source/", result["source"])
need(len(states[label]) == history["sourceFilesPerSnapshot"] == 9, label + ": source count")
expected = {folder + name for name in ("started.json", "result.json", "stdout.log", "stderr.log")}
expected.update(folder + "source/" + name for name in states[label])
need({name for name in members if name.startswith(folder)} == expected, label + ": extra snapshot files")
need(history["status"] == "PASS" and history["equalByteGroups"] == GROUPS, run + ": history groups")
for group in GROUPS:
need(all(states[label] == states[group[0]] for label in group), run + ": actual history bytes " + str(group))
need(all(states[a[0]] != states[b[0]] for i, a in enumerate(GROUPS) for b in GROUPS[i + 1:]), run + ": distinct history states")
need(states["baseline"] == {name[7:]: data for name, data in fixture.items() if name.startswith("source/")}, run + ": baseline source exact")
changed = {label: sorted(name for name in set(states["baseline"]) | set(states[label])
if states["baseline"].get(name) != states[label].get(name)) for label in ("move", "hidden")}
need(changed == history["changedFilesFromBaseline"]
== {label: ["views/diagram_oa_view.arcadia"] for label in ("move", "hidden")}, run + ": changed source files")
print(run, "closed exit 0;", len(captures), "captures; nine positive snapshots; exact three-group source history")
need(used == set(members), "unreferenced/extra package members")
return {"runs": len(runs), "members": len(members)}
def verify_package(root):
files = parsed((root / "files.json").read_bytes())
need(set(files) == OUTER, "outer files")
for name, expected in files.items():
need(pin((root / name).read_bytes()) == expected, "outer pin: " + name)
manifest = parsed((root / "manifest.json").read_bytes())
with zipfile.ZipFile(root / "evidence.zip") as archive:
zip_inventory(archive, manifest["members"])
return verify_data(manifest, archive.read)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("package", nargs="?", type=Path, default=Path(__file__).resolve().parent)
args = parser.parse_args()
print("PASS native evidence byte/receipt consistency:", verify_package(args.package))
print("No GUI/checker execution; actions and native acceptance require the separate parent review.")
if __name__ == "__main__":
main()
@@ -0,0 +1,2 @@
# Preserve pinned historical receipts and helper bytes through Git round trips.
* -text whitespace=cr-at-eol
@@ -0,0 +1,52 @@
# Captured inputs and committed source identity
This directory preserves exact historical `committed-desktop-4.json` and
`committed-desktop-5.json` receipts plus `verify-committed-inputs.py` as data.
The original helper contains its historical absolute checkout path; do not run
it for portable verification. The receipts do not themselves pin that helper;
`files.json` pins the copies distributed here and the new verifier/README.
The local `.gitattributes` preserves those pinned bytes through Git round trips;
retain it with this directory rather than normalizing the historical text.
With Python 3.10+, Git, a repository containing both commits, and the completed
sibling checks package, run:
```text
python -B SOURCE_DIRECTORY/verify.py --repo REPOSITORY --checks CHECKS_PACKAGE_DIRECTORY
```
Before that package exists, an explicitly optional raw-input mode is available:
```text
python -B harness/experiments/multiselect-20260923/source/verify.py --repo . --raw-gates .local/group-movement-gates
```
The verifier checks source-evidence pins, captured map byte hashes, recorded gate
success/unchanged flags, counts and 71 vendored iced_widget inputs. It compares the
complete relevant Git tree inventory and every blob's size/SHA-256 at these
commits with their corresponding captured input maps:
- `desktop-4`: `12a7352ddef5f69a144ead8219a50916233d63a9`
- `desktop-5`: `f6a6010baed9e6164a1fcc7ecd58256a562827d7`
The scope matches the historical helper: Cargo manifests/lock/toolchain file,
`crates/`, `build/`, `.cargo/`, `scripts/`, `docs/`, `examples/`,
`harness/fixtures/`, and `harness/prototypes/`. This is the complete inventory
within that scope, not a whole-repository identity claim. Worktree contents,
current HEAD, line-ending checkout conversion and original machine paths do not
participate. Git objects are read by object ID; no checkout, build or archived
helper runs. Both commits must already be available; lazy object fetching is
disabled for these reads.
In package mode, outer checks-package pins and selected member/run relationships
are also checked. Run the checks package's own verifier for its full source ZIP,
logs, helpers and all other gate relationships. Raw mode reads the named local
maps/receipts directly and is not a substitute for packaged-evidence verification.
No source maps or ZIPs are duplicated in this directory.
Historical receipts report an earlier comparison. A successful run of this new
verifier performs a fresh Git-object comparison against the pinned maps. A gate's
recorded HEAD can predate its later source-identical commit; that difference is
why blob comparison is necessary. This evidence identifies tested source bytes;
it does not rerun tests or establish native usability, release integration or
full #29 acceptance.
@@ -0,0 +1,11 @@
{
"checked": "2026-09-23T08:11:54.115058+00:00",
"commit": "12a7352ddef5f69a144ead8219a50916233d63a9",
"gate": "desktop-4",
"inputCount": 729,
"inputMap": {
"bytes": 121985,
"sha256": "55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb"
},
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory"
}
@@ -0,0 +1,11 @@
{
"checked": "2026-09-23T08:53:15.452246+00:00",
"commit": "f6a6010baed9e6164a1fcc7ecd58256a562827d7",
"gate": "desktop-5",
"inputCount": 729,
"inputMap": {
"bytes": 121985,
"sha256": "99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c"
},
"comparison": "Exact committed Git blobs equal every captured input; same complete filtered inventory"
}
@@ -0,0 +1,26 @@
{
".gitattributes": {
"bytes": 109,
"sha256": "aca8eef17dbab8cfedcbe18e1175cfee115802376fac4ec69e8c3320a6399d6c"
},
"README.md": {
"bytes": 2792,
"sha256": "b8db0c2c71e491b6179b3e57d27e5dfb23c9283894219feea328bc632603f2aa"
},
"verify.py": {
"bytes": 7255,
"sha256": "2ed667c127470efb669fb43d5dcdb288f891e42e10e67ef98ca4cd1125df09d1"
},
"verify-committed-inputs.py": {
"bytes": 2138,
"sha256": "ac2b50a73f678456b9628684347484c013f5f9c78f054de72b74f56a34c990d5"
},
"committed-desktop-4.json": {
"bytes": 390,
"sha256": "47c6774bcb7d0c37c50e0ed50f8fb58ee9b55c6fcee30af488481c314a4e66e8"
},
"committed-desktop-5.json": {
"bytes": 390,
"sha256": "da1f08e06bd0af6512da4196618b71d0c4ecc090012f061bb82b6a36f5b7686c"
}
}
@@ -0,0 +1,36 @@
"""Check the tested source inventory against exact Git blobs, not HEAD alone."""
from pathlib import Path
import datetime, hashlib, json, subprocess, sys
root=Path('C:/ar-multiselect-9e8r6t')
run,=sys.argv[1:]
gate=root/'.local/group-movement-gates'/run
inputs=json.loads((gate/'inputs.json').read_bytes())
result=json.loads((gate/'result.json').read_bytes())
assert result['exitCode']==0 and result['inputsUnchanged']
head=subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip()
def relevant(p):
return p in ('Cargo.toml','Cargo.lock','rust-toolchain.toml') or p.startswith(('crates/','build/','.cargo/','scripts/','docs/','examples/','harness/fixtures/','harness/prototypes/'))
paths=subprocess.check_output(['git','ls-tree','-r','--name-only','-z',head],cwd=root).decode().split('\0')
assert set(inputs)=={p for p in paths if p and relevant(p)}, 'Committed input inventory differs'
assert all('\n' not in p for p in inputs)
request=''.join(head+':'+p+'\n' for p in inputs).encode()
raw=subprocess.run(['git','cat-file','--batch'],cwd=root,input=request,capture_output=True,check=True).stdout
offset=0
actual={}
for path in inputs:
end=raw.index(b'\n',offset)
oid,kind,size=raw[offset:end].split()
assert kind==b'blob'
size=int(size)
data=raw[end+1:end+1+size]
assert len(data)==size and raw[end+1+size:end+2+size]==b'\n'
actual[path]={'bytes':size,'sha256':hashlib.sha256(data).hexdigest()}
offset=end+2+size
assert offset==len(raw)
changed=[p for p in inputs if inputs[p]!=actual[p]]
assert not changed, 'Tested bytes differ from committed blobs: '+repr(changed)
data=(gate/'inputs.json').read_bytes()
report={'checked':datetime.datetime.now(datetime.timezone.utc).isoformat(),'commit':head,'gate':run,'inputCount':len(inputs),'inputMap':{'bytes':len(data),'sha256':hashlib.sha256(data).hexdigest()},'comparison':'Exact committed Git blobs equal every captured input; same complete filtered inventory'}
out=root/'.local/group-movement-gates'/('committed-'+run+'.json')
with out.open('x',encoding='utf-8') as f: json.dump(report,f,indent=2)
print(json.dumps(report,indent=2))
@@ -0,0 +1,149 @@
"""Compare captured input maps to exact named Git trees; no builds or checkouts."""
from pathlib import Path, PurePosixPath
import argparse
import hashlib
import json
import os
import subprocess
import zipfile
HERE = Path(__file__).resolve().parent
COMMITS = {"desktop-4": "12a7352ddef5f69a144ead8219a50916233d63a9",
"desktop-5": "f6a6010baed9e6164a1fcc7ecd58256a562827d7"}
COMPARISON = "Exact committed Git blobs equal every captured input; same complete filtered inventory"
FILES = {".gitattributes", "verify.py", "README.md", "verify-committed-inputs.py",
"committed-desktop-4.json", "committed-desktop-5.json"}
def need(ok, message):
if not ok:
raise ValueError(message)
def pin(data):
return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
def parsed(data):
def unique(items):
result = {}
for key, value in items:
need(key not in result, "duplicate JSON key: " + key)
result[key] = value
return result
return json.loads(data, object_pairs_hook=unique)
def safe(name):
return (isinstance(name, str) and bool(name) and "\\" not in name and ":" not in name
and not PurePosixPath(name).is_absolute()
and all(part not in ("", ".", "..") for part in name.split("/")))
def relevant(path):
return path in ("Cargo.toml", "Cargo.lock", "rust-toolchain.toml") or path.startswith(
("crates/", "build/", ".cargo/", "scripts/", "docs/", "examples/", "harness/fixtures/", "harness/prototypes/"))
def git(repo, *arguments, data=None):
environment = dict(os.environ, GIT_NO_LAZY_FETCH="1")
return subprocess.run(["git", *arguments], cwd=repo, input=data, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, check=True, env=environment).stdout
def compare_commit(repo, commit, inputs):
need(git(repo, "rev-parse", "--verify", commit + "^{commit}").decode().strip() == commit, "named commit unavailable")
entries = git(repo, "ls-tree", "-r", "--full-tree", "-z", commit).split(b"\0")
blobs = {}
for entry in filter(None, entries):
header, path_bytes = entry.split(b"\t", 1)
path = path_bytes.decode("utf-8")
if relevant(path):
_mode, kind, oid = header.split()
need(kind == b"blob", "relevant non-blob tree entry: " + path)
need(path not in blobs, "duplicate tree path")
blobs[path] = oid
need(set(blobs) == set(inputs), "complete filtered Git inventory differs; missing="
+ repr(sorted(set(inputs) - set(blobs))) + "; additional=" + repr(sorted(set(blobs) - set(inputs))))
# Object IDs avoid path quoting and commit:path interpretation in batch input.
paths = sorted(blobs)
data = git(repo, "cat-file", "--batch", data=b"".join(blobs[path] + b"\n" for path in paths))
offset, actual = 0, {}
for path in paths:
end = data.index(b"\n", offset)
oid, kind, size_bytes = data[offset:end].split()
size = int(size_bytes)
need(oid == blobs[path] and kind == b"blob" and size >= 0, "Git batch object relationship")
content = data[end + 1:end + 1 + size]
need(len(content) == size and data[end + 1 + size:end + 2 + size] == b"\n", "Git batch framing")
actual[path] = pin(content)
offset = end + 2 + size
need(offset == len(data), "trailing Git batch bytes")
different = [path for path in paths if actual[path] != inputs[path]]
need(not different, "captured bytes differ from named commit: " + repr(different))
def packaged(checks, runs):
files = parsed((checks / "files.json").read_bytes())
need(set(files) == {"prepare.py", "verify.py", "README.md", "manifest.json", "evidence.zip"}, "checks outer inventory")
for name, expected in files.items():
need(pin((checks / name).read_bytes()) == expected, "checks outer pin: " + name)
manifest = parsed((checks / "manifest.json").read_bytes())
need(manifest["schema"] == 1 and manifest["kind"] == "multiselect-cargo-gates", "checks manifest kind")
captured = {}
with zipfile.ZipFile(checks / "evidence.zip") as archive:
names = archive.namelist()
need(len(names) == len(set(names)) and set(names) == set(manifest["members"])
and all(safe(name) for name in names), "checks exact safe members")
def raw(logical):
member = manifest["logicalFiles"][logical]
data = archive.read(member)
need(pin(data) == manifest["members"][member], "checks member pin: " + logical)
return data
for run in runs:
prefix = "cargo/" + run + "/"
result = parsed(raw(prefix + "result.json"))
spec = manifest["runs"][run]
need(all(result[key] == spec[key] for key in ("command", "head", "exitCode", "inputCount")), run + ": checks run relationships")
captured[run] = (raw(prefix + "inputs.json"), result)
return captured
def verify(repo, captured):
outer = parsed((HERE / "files.json").read_bytes())
need(set(outer) == FILES, "source evidence file inventory")
for name, expected in outer.items():
need(pin((HERE / name).read_bytes()) == expected, "source evidence pin: " + name)
for run, commit in COMMITS.items():
receipt = parsed((HERE / ("committed-" + run + ".json")).read_bytes())
need(receipt["gate"] == run and receipt["commit"] == commit
and receipt["comparison"] == COMPARISON, run + ": historical identity relationship")
map_bytes, result = captured[run]
inputs = parsed(map_bytes)
need(pin(map_bytes) == receipt["inputMap"] == result["inputs"], run + ": exact captured input map")
need(result["exitCode"] == 0 and result["inputsUnchanged"] is True, run + ": accepted unchanged gate")
need(len(inputs) == receipt["inputCount"] == result["inputCount"], run + ": input counts")
need(all(safe(path) and relevant(path) for path in inputs), run + ": input scope")
need(sum(path.startswith("crates/vendor/iced_widget/") for path in inputs) == 71, run + ": vendor count")
compare_commit(repo, commit, inputs)
print("PASS exact Git tree/blobs:", run, commit, len(inputs), "captured inputs")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--repo", type=Path, required=True, help="repository with both named commits already present")
source = parser.add_mutually_exclusive_group(required=True)
source.add_argument("--checks", type=Path, help="portable checks package directory")
source.add_argument("--raw-gates", type=Path, help="optional preparation mode: raw gate directory, not a packaged-evidence verification")
args = parser.parse_args()
if args.checks:
captured = packaged(args.checks, COMMITS)
else:
captured = {run: ((args.raw_gates / run / "inputs.json").read_bytes(),
parsed((args.raw_gates / run / "result.json").read_bytes())) for run in COMMITS}
verify(args.repo, captured)
print("Source identity only; no build, checkout, helper execution or native acceptance claim.")
if __name__ == "__main__":
main()
@@ -196,3 +196,82 @@ Only a static inspection and `git diff --check` were performed for these edits.
Formatting, compilation, regression execution and a fresh native before/after
capture remain owned by the parent. Native run-1 continues against its unchanged
pinned binary and cannot serve as verification of this subsequent source edit.
### Native run-2 visual follow-up: stable selection strip
I independently inspected the saved images `03-open-submitted-0.jpg`,
`05-singleton-settled-0.jpg` and `07-group-selected-0.jpg` under native run-2.
This is image inspection separate from the parent's live GUI operation; the
inspector also authored the layout correction, so it is not a fresh-author
review. No UI actions or source edits were performed for this check.
The run records source `f6a6010baed9e6164a1fcc7ecd58256a562827d7` and GUI SHA-256
`49396ee5c24f749cbee54e1fd77e15f5d73b0e19cf246724216ce7464d3deba5`.
At the recorded 1442 by 932 window size, all three images show the canvas top
near y=341 and the zoom at 84%. A's header remains near y=497, B near y=531,
the child near y=606 and C near y=656 across zero, one and two selected targets.
Selection outlines and the Inspector change; the diagram and canvas do not
visibly jump. This corrects the run-1 singleton/group viewport and node shifts
documented above. Pixel positions are approximate visual readings, not a new
instrumented layout measurement.
The strip clearly shows `0 selected`, `1 selected` and `2 selected` respectively.
The group image displays readable `Hide selected`, `Clear selection` and
`Properties edit only B - assess request` on one line with space remaining.
The second line exposes Shift-click add/remove in each state, and the group
state additionally says to drag selected elements to move. No wrapping,
overlap, clipped action caption or obscured diagram content is visible in these
captures. No new visual correction is indicated for this shown window size.
This follow-up establishes only the shown 0/1/2 selection layout and displayed
zoom stability. It does not yet claim run-2 movement, Hide, history, saved-model
checks or completed process lifetime; those actions were still pending at the
time of this image inspection. Long-name/mixed-selection and exact camera/model
invariants remain separate mounted-test evidence, not claims derived from these
three images.
### Closed run-2 follow-up: Hide, history and reopening
After run-2 closed, I independently viewed `15-before-hide-saved-0.jpg`,
`16-hide-group-0.jpg`, `18-hide-undo-0.jpg`, `20-hide-redo-0.jpg` and
`23-reopened-hidden-0.jpg`, and read the nine snapshot checker receipts,
`history-bytes.json` and `finished.json`. I also rehashed the actual nine source
files in each snapshot to compare the three history equality groups, and read
the saved moved/hidden OA view source. This remains an evidence inspection;
the parent observed the actual UI actions. It does not independently
authenticate individual key or pointer events or rerun the model compiler.
Before Hide, two targets are selected. The hidden captures remove A/B while
retaining the child and C; the Explorer retains the engineering activities.
Undo restores A/B and their visible relationships, while the transient selection
appropriately remains empty. Redo returns to the same hidden visible state.
Across these four images, the canvas top stays near y=341, zoom remains 84%,
and child/C positions stay near y=606/y=656. Returning from two selected to zero
therefore no longer causes the run-1 viewport jump. The count, status text and
Inspector change without crowding or covering diagram content. No further
material visual defect was established in these captures.
The reopened hidden image still has the same canvas allocation and only child/C
visible. Its zoom is 88% and the nodes have been refitted into the available
space. This is a reopened transient-camera change, not evidence of changed saved
placement geometry: the reopened source is byte-identical to the other hidden
snapshots and its complete-Project Hide check passes.
All nine checker receipts report exit zero and PASS, with unchanged binary,
working source and baseline pins. The movement and movement-Redo reports infer
the same `(100, 60)` delta. The saved moved view explicitly contains A at
`(180, 140)`, B at `(570, 180)` and the child at `(220, 270)`; C remains at
`(780, 270)`. Internal pins translate, while the external pins and relative
route metadata stay unchanged. The hidden view retains both stored routes and
the baseline child/C placements while omitting A/B placements.
My independent source-inventory hash comparison confirms the recorded byte
groups: baseline = movement Undo = before Hide = Hide Undo; movement = movement
Redo; hidden = Hide Redo = reopened hidden. Each snapshot contains nine files.
The history receipt reports that only `views/diagram_oa_view.arcadia` differs
from baseline for movement and Hide. The final lifecycle receipt records clean
exit zero, unchanged GUI/checker/fixture and empty application stdout/stderr.
There are 24 numbered run-2 capture pairs. These results support the stated
saved-state and visual relationships together with the parent's action
observations; the invariant-oracle, native Shift, SA and unfinished-adapter
limits documented above continue to apply.
+218
View File
@@ -0,0 +1,218 @@
# Ordinary saved-view multiple selection — verification report
**Verified branch contribution, not full issue acceptance.** This report covers the ordinary saved-view
subset of [issue 29](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/29).
Final source is `f6a6010baed9e6164a1fcc7ecd58256a562827d7` on
`codex/multiselect-9e8r6t-20260923`, based on the published State/attachment
checkpoint `b8685416f56e53e30bd11ecf93a54cea10ac8458`. The final Windows desktop
suite, strict lint, formatting, build and corrected-layout native run passed.
Integration with the release owner's later union remains separate work.
## Evaluated source and scope
Native run-1 used commit `12a7352ddef5f69a144ead8219a50916233d63a9` and the
729-file input map
`55a5f354bb5049a8c77ba9bafa833438ebf754649b0cf5d175d0c8dcfcedd7bb`.
Core-3, desktop-4, lint-2, format-1 and both native/checker builds share that
exact input map. Earlier test receipts record HEAD
`b8685416f56e53e30bd11ecf93a54cea10ac8458` because the feature was still
uncommitted; the captured source map, rather than HEAD alone, identifies their
tested contents.
The corrected layout verification uses a distinct 729-file input map,
`99dc46645236e674244e7c4867595a6000d3d85b54bcc9ab2b0c601923ecf66c`,
captured by desktop-5 at HEAD `12a7352ddef5f69a144ead8219a50916233d63a9`.
An exact Git-blob comparison subsequently confirmed the complete captured input
inventory equals commit `f6a6010baed9e6164a1fcc7ecd58256a562827d7`.
Results for the earlier map do not establish the changed layout's behavior.
Desktop-5, lint-3, format-2, native-build-2 and windows-build-2 all use the
corrected map. Native run-2 operated that Windows build; its 117,519,360-byte
executable has SHA-256
`49396ee5c24f749cbee54e1fd77e15f5d73b0e19cf246724216ce7464d3deba5`.
The implemented subset provides exact transient saved-view selection with a
primary Inspector target, Shift toggling and contextual Add/Remove, deferred
stationary-click versus group-drag behavior, simultaneous placement movement,
and group Hide that preserves model objects. The complete typed selection is
admitted or refused; ports/edges are not silently filtered from a group action.
Captured operations reject stale document, revision, surface and selection
generation. Ordinary property edits remain primary-only. Movement uses one
atomic transaction and the same pure plan for preview and commit.
Required behavior and remaining adapter families are defined by the
[contract](multiselect-contract-20260923.md). Design and detailed review evidence
remain in the [core review](multiselect-core-review-20260923.md),
[desktop review](multiselect-desktop-review-20260923.md),
[fresh review](multiselect-fresh-review-20260923.md), and
[native evaluator/layout review](multiselect-native-review-20260923.md).
## Closed gates
The closed receipts below report unchanged captured inputs and successful exit.
Windows used `stable-x86_64-pc-windows-gnullvm`, Cargo 1.98.1 and rustc 1.98.1,
locked/offline dependencies, and the supported headless desktop renderer.
| Gate | Command/result |
| --- | --- |
| core-3 | `cargo test --locked --offline -p oa-core --test group_movement --test state_diagrams --example multiselect_native -- --nocapture`: 7 movement + 13 existing State + 10 evaluator tests passed; zero failures. State test passage does not accept a State group UI adapter. |
| desktop-4 | `cargo test --locked --offline -p oa-desktop -- --nocapture`: 1,256 passed, zero failed, six ignored. Includes mounted focus, passive modifiers across I/O, selection/history and pointer-lifecycle regressions. |
| desktop-5 | Same desktop command, corrected layout: 1,257 passed, zero failed, six existing ignored. The added mounted regression preserves canvas bounds, fitted camera, complete Project, source and empty history across empty/single/group/mixed selection. |
| lint-2 | `cargo clippy --locked --offline -p oa-core -p oa-desktop --all-targets -- -D warnings`: passed. |
| lint-3 / format-2 | Strict all-target Clippy for core/desktop and `cargo fmt --all -- --check` passed on the corrected layout input map. |
| format-1 | `cargo fmt --all -- --check`: passed. |
| native-build-1 / windows-build-1 | Locked/offline checker example and Windows desktop executable builds passed, with matching input maps and recorded executable hashes. |
| native-build-2 / windows-build-2 | Both builds passed from final source `f6a6010`, with matching corrected-layout inputs and executable pins. |
Failures were retained and corrected, not counted as passing evidence:
desktop-1 exposed module visibility/menu-token compile errors; desktop-2
reported one Placement-properties selection regression (1,247 passed, one
failed, six ignored), corrected by recognizing the selected placement identity;
core-2 exposed the evaluator incorrectly rejecting ordinary fixture warnings;
oracle-2 then exposed an unqualified Severity type; lint-1 rejected an
unnecessary clone. Later closed gates above cover the corrected source.
Desktop-3's earlier 1,254/0/6 pass preceded the two passive-modifier suspension
regressions included in desktop-4. Full historical commands, inputs and logs
belong in the checks package, not this summary.
## Native behavior and saved-state evidence
The owning session operated each pinned Windows app through contextual Add for
A/B, one group drag, Save, movement Undo/Redo with Save, return to baseline,
group Hide, Hide Undo/Redo with Save, and reopening the hidden saved source.
These are actual Computer Use observations, not inputs independently replayed
by the evidence verifier. Run-1 retains 27 numbered native captures and run-2
retains 24. Each run has nine saved-source snapshots with evaluator receipts,
process/start/finish records and `history-bytes.json`.
Run-1 records PID 7540 / window 131836; run-2 records PID 5312 / window 20055002.
Each capture names the corresponding pinned executable path and consistent
window identity. Both closing receipts report exit zero, unchanged GUI/checker
binaries and fixture, and empty stdout/stderr. These are joined historical
records, not independent OS authentication of every captured input.
The independent checker compares the complete Project against explicit fixture
expectations and validates JSON/source roundtrips. All nine final snapshots
in each run (18 total) report PASS with stable source, baseline and checker pins:
| Saved state | Verified relationship |
| --- | --- |
| `baseline`, `move-undo`, `before-hide`, `hide-undo` | Equal to the complete baseline Project; all nine source files byte-identical to the fixture baseline. |
| `move`, `move-redo` | A, B and A's unselected child share delta `(100, 60)`; internal route pins translate once. C, one-ended pins, attachments, labels, semantic records, traces and other views remain exact. The two source inventories are byte-identical. |
| `hidden`, `hide-redo`, `reopened-hidden` | Only A/B placements are removed. The child placement, stored routes, model objects and other views remain exact. These three source inventories are byte-identical. |
Across both changed states, the only changed source file is
`views/diagram_oa_view.arcadia`; the other eight source files remain unchanged.
This supports precise saved-state restoration across the observed
one-step history sequence. Equality alone does not authenticate Undo button
presses or establish history behavior without those observations.
The fixture is deliberately incomplete engineering content. The parent observed
11 warnings: `missing_system` ×1, `unallocated_leaf` ×4,
`work_without_behavior_context` ×4, `exchange_without_behavior_context` ×1,
and `non_leaf_work_exchange` ×1. The native status shows 11 model checks; these
are not presented as new application defects or zero-warning acceptance.
The evaluator permits completeness warnings but rejects source errors and
compilation failures.
Run-1 also exposed a real layout issue: forming a group inserted a conditional
toolbar block, resized the canvas and shifted nodes without a geometry edit.
Independent inspection of captures 06 and 08 confirms the shift. The subsequent
correction reserves a fixed selection/status strip, adds a visible
Shift-click hint and includes a mounted bounds/camera regression. Run-1's pinned
binary is unchanged and cannot verify that correction. Desktop-5 passed, and
run-2 then confirmed the corrected behavior: captures 03/05/07 retain the same
canvas top (about y=341), 84% zoom, and node positions across empty/single/group
selection. The count, Hide/Clear controls, primary-only disclosure and Shift
hint are readable at the observed 1442×932 window size.
Run-2's drag was from `(405,533)` to `(489,583)` in window coordinates, an
84-pixel right / 50-pixel down movement at the displayed 84% zoom. The observed
geometry moves accordingly; the independent saved-model oracle finds the
grid-aligned common world delta `(100,60)`. One Ctrl+Z restores baseline, and one
Ctrl+Y restores the moved state. Save and complete-Project checks follow each.
Hide at `(377,287)` removes A/B placements while leaving the child and C at their
previous screen positions; Undo restores A/B without the former clipping or
viewport shift. Zoom remains 84% throughout those edits. Reopening the hidden
source performs the normal fresh fit (88%); camera is transient, and the saved
Project/source remain exact. Capture labels identify each stage.
The initial run-2 baseline checker invocation omitted the shell's GNU toolchain
runtime setup and exited `3221225781` with empty streams. The same checker and
byte-identical source passed after environment setup. The failed snapshot,
retry receipts and exact helpers are retained in the separate
[incident record](experiments/multiselect-20260923/incidents/README.md); it is not
counted as a successful checker attempt or an application crash.
## Reproduce and inspect
Use the repository's [Windows build/packaging guidance](../docs/windows-packaging.md)
and a configured Rust/GNU runtime environment. Captured runs used Rust/Cargo
1.98.1, LLVM-MinGW 20260826, one Cargo job and `CARGO_INCREMENTAL=0`.
`--offline` requires the dependency cache to be present. From the source checkout:
```text
cargo test --locked --offline -p oa-core --test group_movement --test state_diagrams --example multiselect_native -- --nocapture
cargo test --locked --offline -p oa-desktop -- --nocapture
cargo clippy --locked --offline -p oa-core -p oa-desktop --all-targets -- -D warnings
cargo fmt --all -- --check
cargo build --locked --offline -p oa-desktop --bin arcadia-studio
cargo build --locked --offline -p oa-core --example multiselect_native
```
Run the resulting desktop executable with the GNU runtime directory on PATH.
The built `multiselect_native` example accepts `generate NEW_DIRECTORY`; keep
the generated fixture unchanged, copy its `source` directory to a fresh working
directory, and open that copy's `project.arcadia` in the app. After saving each
observed operation, evaluate with:
```text
multiselect_native check unchanged FIXTURE/baseline.json WORKING/project.arcadia
multiselect_native check moved FIXTURE/baseline.json WORKING/project.arcadia
multiselect_native check hide FIXTURE/baseline.json WORKING/project.arcadia
```
Use the mode matching the table above. Preserve separate saved source copies
for the nine named stages and compare their exact inventories/bytes in the
three stated equality groups. Commands cannot substitute for the actual native
selection, movement, history and reopen actions.
Portable verification from a repository containing the named source commits:
```text
python -B harness/experiments/multiselect-20260923/checks/verify.py
python -B harness/experiments/multiselect-20260923/native/verify.py
python -B harness/experiments/multiselect-20260923/source/verify.py --repo . --checks harness/experiments/multiselect-20260923/checks
```
The packages retain original logs, inputs, captures, fixtures and snapshot
receipts. The source verifier freshly compares all captured Git blobs and the
complete filtered inventory at both named commits. These offline checks do not
execute archived code or rerun the GUI; consult their READMEs for precise limits.
## Acceptance limits and delivery
- Both native runs exercise OA Activities in an ordinary Overview, not a native SA
Function workflow. Native selection used contextual Add because the chosen
tool cannot inject held-Shift plus click; mounted tests provide separate
Shift-before-focus evidence. The App-level multiselect tests separately use
SA Functions, a nested Function and a FunctionalExchange in a Functional
Dataflow view; that automated coverage is not a native SA interaction claim.
- The checker infers a bounded common delta from saved A. It verifies group
invariants, not the exact intended pointer destination or drag magnitude.
Native action observations, model equality, byte equality and mounted tests
are distinct evidence and are not interchangeable.
- State, Allocation, derived Process/Scenario group adapters and aggregate
model deletion remain incomplete. This report does not close the full issue,
accept those families, claim Linux verification, or represent an integrated
release. The native runs do not cover every mixed-target, cancellation or
suspension scenario exercised by automated tests.
- Native layout review covers 1442×932, not every minimum-window, DPI or keyboard
accessibility condition. No broad usability acceptance is inferred from this
bounded fixture.
- Portable evidence is supplied under
[checks](experiments/multiselect-20260923/checks/README.md) and
[native](experiments/multiselect-20260923/native/README.md), with separate
[source identity](experiments/multiselect-20260923/source/README.md) and incident
records. The checks package retains 19 closed runs, including five nonzero
historical gates. Raw absolute paths in the receipts are historical labels;
the versioned packages make the evidence consumable on other machines.
@@ -84,3 +84,25 @@ Placement-only Hide removes only explicitly selected placements, not the movemen
Resolved from code: no new target type is needed for State placements; row hits need stronger occurrence identity; State has unsnapped node moves; boundary route behavior is already in core; menu dispatch and App selection boundary must be extended beyond a page test.
Before implementation, inspect the actual then-current ordinary adapter and `group_gesture` API (they are still local work), and enumerate all `StateCanvas` struct literals in existing tests for the added selection field. Inspect `behavior::selected_owner`, BehaviorDiagram/owner navigation and any early-return App paths together when extending reconciliation; owner changes must not survive because `active_diagram` stayed constant. These are discoverable code questions, not user decisions. No additional external research or schema change is indicated.
## Follow-up falsification review of the proposal
Read-only follow-up against the current local implementation confirms the approach, with these tighter constraints. This is a second pass by the same investigator, not an independent-agent approval or execution evidence.
1. **Row visibility must be occurrence-exact, not merely relation-valid.** `visible_row_relation` finds the relation's current source and then accepts any rendered row for that source. It is adequate for existing singleton removal, but not sufficient to validate `StateRow { placement, relation }`. A relation can survive while being reassigned to another State or while its owner's placement is replaced. The group predicate must require the specified projected placement, the relation's current source equal to that placement's element, and membership in that placement's currently rendered `state_action_rows` / `internal_rows`. Falsifier: preserve the relation UUID, reassign its source to another placed State, then deliver the old row snapshot; never rebound selection to the new row. Both row kinds currently lose placement at `hit` and right-click capture, so fixing only one path is incomplete.
2. **Existing primary fallback is now stronger than the initial ordinary adapter.** Current `app/multiselect.rs` preserves the reconciled survivor when `held_primary || lost_primary`, regardless of a legacy semantic-to-placement remap. Keep this rule for State; do not restore the older `lost_primary && legacy.is_none()` condition. State additionally needs an exact row primary marker because both an internal row and an edge inspect a relation UUID. `behavior.diagram.placement` remains a node-inspection field; putting a row owner there would allow legacy Hide to delete its state placement. The typed selection is authoritative for rows, while the inspector still addresses the relation. Falsifier: remove a primary row's occurrence, keep its relation/model work alive, and retain an unrelated selected node; that node becomes primary with one coherent inspector, including after Undo.
3. **Unchanged authored route does not imply unchanged rendered route or labels.** `translated_routes` changes only pins when all actual endpoint owners and any required boundary move together; it preserves manual attachments and `EdgeLabel` fraction/offset. An external route's stored record stays byte-for-byte equal, while its automatic path and computed label position may change as one endpoint moves. State action/internal rows follow their projected state, and `symbol_labels` recomputes collision-aware derived positions after routing. Do not add a second label translation or freeze their old screen positions. Independent assertions must separate authored `EdgeRoute` equality from rendered geometry and symbol-label ownership. Include guards and multi-line transition labels, a State action referencing work shared by another State, and an external route with a manually offset label.
4. **Projected boundary geometry cannot be used as the movement anchor's original authored position.** EntryPoint/ExitPoint X is snapped to the owner boundary by projection; Y is clamped below the header and above the bottom. `StateCanvas` currently captures the original from `diagram.nodes[placement].position`, correctly. A reusable group helper initialized from `ProjectedNode.position` can introduce a large unintended first delta even with an unsnapped policy. Falsifier: stored entry position differs substantially from its displayed boundary position; drag by 7.25 world units and require precisely that stored displacement, with independent projected-boundary expectations. Preserve unsnapped State node movement; bend snapping remains 5 units and ordinary movement 10.
5. **One shared plan is a contract, not sequential reuse of singleton movement.** `diagram::multiselect::group_preview` already consumes only `EditNode`/`SetEdgeRoute` members of the pure planner's Batch into a cloned diagram. State can reuse that small application pattern. Neither preview nor commit may loop through `state_edit::plan(Event::Move)` or `Command::MoveNode`: each sees an incomplete movement map and misses internal pins between unrelated roots. Recheck all selection members against one original snapshot before constructing the plan; commit once through Document. A refused/out-of-bounds member must leave every other member, source and history unchanged.
### Smallest safe implementation split
- **First: exact selection boundary and inspection**, including State context, row hit identity, primary reconciliation, passive modifiers, menu Add/Remove/dismissal and visible membership. Until movement exists, intercept group drags/Delete with an explicit full-set refusal so no singleton fallback is reachable. Test actual App admission before shared side effects, plus same-semantic replacement and row reassignment. This is useful foundation, not completed State group support.
- **Second: placement movement**, integrating unsnapped captured displacement, common atomic planner, diagram-only preview and paint-cache keys. Run independent whole-Project/source/history oracles plus mounted ordered-pointer/Inspector-relayout workflows. Re-run existing State bend/reconnect/attachment checks because hit-priority changes can regress them even without editing their planners.
- **Third: placement Hide and removal boundary**, captured-set Hide with one Undo/Redo, survivor primary and unplaced-picker recovery. Mixed rows/edges and semantic group deletion must remain explicit refusal until the separate aggregate impact-review path exists. A group menu cannot expose enabled singleton destructive actions during any split.
Every split must reject pending property/source/State drafts without calling `apply`, and reject stale snapshots before status, camera, allocation or selection mutation. Advancing source history must retire old snapshots even if semantic/placement UUIDs are unchanged. Reuse existing ordinary stale-event loop for State Move/Hide/Collapse/Refuse with view, owner, tool, revision and selection-generation changes; add the row-source reassignment and entry authored-versus-projected tests above.