Verify compact source editing in the native application
This commit is contained in:
@@ -105,3 +105,4 @@ harness/experiments/default-fidelity-20260913/**/*.log -whitespace
|
||||
harness/experiments/default-production-20260913/** -text whitespace=cr-at-eol
|
||||
harness/experiments/default-followup-20260913/** -text whitespace=cr-at-eol
|
||||
harness/experiments/default-consumers-20260913/** -text whitespace=cr-at-eol
|
||||
harness/experiments/default-native-20260913/** -text whitespace=cr-at-eol
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# Compact source native workflow evidence
|
||||
|
||||
This package preserves two completed Windows native runs of the default-omission
|
||||
followup, including the original screenshots, window/accessibility metadata,
|
||||
process receipts, producers, input fixture, and both saved source bundles.
|
||||
Run the read-only archive check from any checkout with Python 3:
|
||||
|
||||
```text
|
||||
python harness/experiments/default-native-20260913/verify.py
|
||||
```
|
||||
|
||||
The verifier reads ZIP members in memory. It does not extract files, run the
|
||||
archived programs, build code, or modify the checkout. `files.json` pins the other
|
||||
three outer files; `capture-files.json` pins every original payload inside the ZIP.
|
||||
These hashes establish internal consistency, not cryptographic attestation.
|
||||
|
||||
## Source and executable provenance
|
||||
|
||||
Both native runs record the same 115,056,640-byte `arcadia-studio.exe`, SHA-256
|
||||
`4070927256414a770c5fbcedfaab922810cea33d9f07610b81e9ab8c0465da44`.
|
||||
Their build receipt and the original build stdout/stderr, producer, and complete
|
||||
613-file executed-input snapshot are included under `build/`. These are copied
|
||||
unchanged from the
|
||||
[published consumer package](../default-consumers-20260913/README.md) at commit
|
||||
`94383107153cccb32f3fdcbd8111b6381f3e15aa`.
|
||||
The actual build recorded HEAD `df2e1cd65ca5e56f47669e04a9d4bcb426900fcd`
|
||||
plus the HTTP test subsequently published in `9438310`; the captured source bytes,
|
||||
rather than HEAD alone, identify the tested input. Production code is unchanged
|
||||
from `7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e`.
|
||||
No executable is distributed in this evidence package.
|
||||
|
||||
Both native process receipts close with exit code zero and empty stdout/stderr.
|
||||
Trial 2 additionally pins its producer at launch and its immutable baseline ZIP.
|
||||
Trial 1's runner and the screenshot helper are preserved as original local
|
||||
producers but were not contemporaneously hashed by that trial's receipt.
|
||||
Do not mistake a packaging-time hash for stronger historical provenance.
|
||||
The helper initially selects `trial-1`; the interactive session changed its
|
||||
output directory to `trial-2` for the continuation. Original producer bytes are
|
||||
preserved, including their historical machine-specific paths.
|
||||
|
||||
## Workflow and evidence boundaries
|
||||
|
||||
Trial 1 opened the minimal source fixture, created one activity through Model
|
||||
Explorer, inspected its compact source, and saved the resulting two-file bundle.
|
||||
The important frames are `13-created-activity`, `17-compact-new-activity`, and
|
||||
`27-cleanup-save-submitted`. Intermediate dialog focus and retry captures remain
|
||||
in the archive; the trial was closed before the cleanup interruption.
|
||||
|
||||
Trial 2 reopened that baseline and dragged Work. Its Text view showed x=190,
|
||||
model Undo showed x=120, and model Redo showed x=190 again. It then used Save As,
|
||||
cleared the current model, reopened the saved result, and inspected both source
|
||||
files. Review these frames with their adjacent JSON metadata:
|
||||
|
||||
- `03-baseline-loaded`, `04-drag-work`, `05-text-after-move`.
|
||||
- `06-model-actions`, `07-undo-model`, `08-redo-menu`, `09-redo-model`.
|
||||
- `17-save-complete`, `19-clear-current-model`, `22-reopened-root`,
|
||||
`25-reopened-compact-activity`.
|
||||
|
||||
Screenshot interpretation and the intermediate undo/redo observations require
|
||||
human review. The archive verifier checks their inventory, metadata, timing and
|
||||
byte hashes; it does not infer visible behavior from frame names or run OCR.
|
||||
The machine-checkable before/after oracle independently requires exact bundle
|
||||
membership and bytes: one compact new activity with stable UUID
|
||||
`1e1da408-da79-42ab-a990-9d00b7dc2631`, one root include, and the sole subsequent
|
||||
change `position { x 120.0; y 80.0; };` to
|
||||
`position { x 190.0; y 80.0; };`. The explicit
|
||||
`port_anchors [] ; // Keep explicit automatic placement.` survives exactly.
|
||||
|
||||
`native/bundle-checks/` preserves both closed CLI checks and their original
|
||||
`native/check-saved-bundles.py` producer. Both full bundles parsed and validated,
|
||||
with four expected draft warnings (each activity is unallocated and lacks behavior
|
||||
context), no errors, no IDs requiring stabilization, and no source changes. These
|
||||
checks do not compare the entire parsed model. After explicit extraction to a
|
||||
chosen directory, a rebuilt CLI can check `native/saved-before/project.arcadia`
|
||||
and `native/saved-after/project.arcadia`; the verification script itself never
|
||||
extracts or executes them.
|
||||
|
||||
On reopen the diagram fits/recenters, so screen coordinates cannot prove the
|
||||
persisted x value; the reopened Text frame supplies that observation. Save dialog
|
||||
frames 14–16 retain a filename-selection automation quirk: text first appended,
|
||||
then was visibly corrected before submission. No incorrect path was submitted.
|
||||
|
||||
This is evidence for one ordinary source/graphical workflow on Windows. It is
|
||||
not an exhaustive usability assessment, Linux result, performance experiment,
|
||||
packaged application verification, or full release acceptance. See the linked
|
||||
consumer and core evidence for broader automated coverage.
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"evidence.zip": {
|
||||
"bytes": 5251658,
|
||||
"sha256": "0eb6f2a566deff1275b19b8c5718ebb56f9afde0518ac65c09d885a1d6e84d68"
|
||||
},
|
||||
"README.md": {
|
||||
"bytes": 4964,
|
||||
"sha256": "713c7ccddcffba87c38327ee39e4a82cdff42fe8adb9ce91d3affa26a01d75e4"
|
||||
},
|
||||
"verify.py": {
|
||||
"bytes": 13770,
|
||||
"sha256": "4ea03bbd274e731f4e3856a5965be29a93011c31dc26c62ae09784e7f7b75b27"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
"""Read-only verification of frozen native receipts and exact saved source bytes."""
|
||||
from pathlib import Path, PurePosixPath
|
||||
from datetime import datetime
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import zipfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
HEAD = "df2e1cd65ca5e56f47669e04a9d4bcb426900fcd"
|
||||
GUI = {"bytes": 115056640, "sha256": "4070927256414a770c5fbcedfaab922810cea33d9f07610b81e9ab8c0465da44"}
|
||||
CLI = {"bytes": 20608512, "sha256": "d89aba9f10b598926dfdc5c644474ae891b753e8583a184860e941a359ed0eea"}
|
||||
BUILD = {"bytes": 5538, "sha256": "25c7878f56395ed1e8e6b3532fd9135e0b313fd2b781a4c982f9f2b01a4ec64b"}
|
||||
INPUTS = {"bytes": 102567, "sha256": "6bf74c1f68431a034681b754617c39d387783f71354c9106649aec9480e4f29f"}
|
||||
SOURCES = {"bytes": 2483742, "sha256": "e20f33dc363850a9289103a7be28ad613c3fffb2039061957a0186cac72d541b"}
|
||||
ACTIVITY_PATH = "oa/activities/activity_new_activity.arcadia"
|
||||
ACTIVITY = b'\noa_activity new_activity "New activity" id "1e1da408-da79-42ab-a990-9d00b7dc2631" {\n}\n\n\n'
|
||||
FIXTURE = b'''arcadia 7;
|
||||
project p "Compact source workflow" id "00000000-0000-4000-8000-000000000001" {
|
||||
oa_activity work "Work" id "00000000-0000-4000-8000-000000000002" {}
|
||||
diagram view "Overview" id "00000000-0000-4000-8000-000000000003" {}
|
||||
node placement id "00000000-0000-4000-8000-000000000004" {
|
||||
diagram @view; element @work;
|
||||
position { x 120.0; y 80.0; };
|
||||
port_anchors [] ; // Keep explicit automatic placement.
|
||||
}
|
||||
}
|
||||
'''
|
||||
LABELS = {
|
||||
"trial-1": "01-home 02-open-dialog 03-open-file-field 05-open-after-uia-error 06-open-focused 07-open-path-typed 08-project-opened 09-project-settled 10-open-keyboard-ready 11-open-submitted 12-model-explorer 13-created-activity 14-generated-source 15-source-folder 16-activity-source-row 17-compact-new-activity 18-save-before-request 19-save-before-dialog 20-cleanup-save-dialog 21-cleanup-filename-focus 22-cleanup-filename-caret 23-cleanup-save-path 24-cleanup-save-path-settled 25-cleanup-filename-refocus 26-cleanup-save-path-retry 27-cleanup-save-submitted".split(),
|
||||
"trial-2": "01-home 02-open-baseline 03-baseline-loaded 04-drag-work 05-text-after-move 06-model-actions 07-undo-model 08-redo-menu 09-redo-model 10-save-as-request 11-save-dialog 12-save-filename-focus 13-select-filename 14-enter-save-path 15-correct-path-selection 16-save-path-corrected 17-save-complete 18-home-reopen 19-clear-current-model 20-empty-home 21-reopen-request 22-reopened-root 23-open-source-folder 24-activity-source-list 25-reopened-compact-activity".split(),
|
||||
}
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise SystemExit(message)
|
||||
|
||||
|
||||
def digest(data):
|
||||
return {"bytes": len(data), "sha256": hashlib.sha256(data).hexdigest()}
|
||||
|
||||
|
||||
def membership(archive, expected, label):
|
||||
names = archive.namelist()
|
||||
require(len(names) == len(set(names)) and set(names) == set(expected), label + ": ZIP membership mismatch")
|
||||
require(all(not PurePosixPath(n).is_absolute() and ".." not in PurePosixPath(n).parts and "\\" not in n and ":" not in n for n in names), label + ": unsafe ZIP member")
|
||||
|
||||
|
||||
def time(value):
|
||||
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
|
||||
require(parsed.tzinfo is not None, "Timestamp missing timezone")
|
||||
return parsed
|
||||
|
||||
|
||||
outer = json.loads((ROOT / "files.json").read_text(encoding="utf-8"))
|
||||
require(set(outer) == {"README.md", "verify.py", "evidence.zip"}, "Outer manifest membership mismatch")
|
||||
require({p.name for p in ROOT.iterdir()} == set(outer) | {"files.json"}, "Outer directory membership mismatch")
|
||||
for name, pin in outer.items():
|
||||
require(digest((ROOT / name).read_bytes()) == pin, "Outer hash mismatch: " + name)
|
||||
|
||||
with zipfile.ZipFile(ROOT / "evidence.zip") as z:
|
||||
def read(name):
|
||||
return z.read(name)
|
||||
|
||||
def obj(name):
|
||||
return json.loads(read(name))
|
||||
|
||||
pins = obj("capture-files.json")
|
||||
membership(z, set(pins) | {"capture-files.json"}, "Evidence")
|
||||
for name, pin in pins.items():
|
||||
require(digest(read(name)) == pin, "Payload hash mismatch: " + name)
|
||||
|
||||
build = obj("build/result.json")
|
||||
require(digest(read("build/result.json")) == BUILD, "Original build receipt mismatch")
|
||||
require(build["head"] == HEAD and build["exitCode"] == 0 and build["inputsUnchanged"] is True, "Build closure mismatch")
|
||||
require(build["inputs"] == INPUTS and build["archive"] == SOURCES, "Build source identity mismatch")
|
||||
require(all(build.get(k) == v for k, v in obj("build/started.json").items()), "Build start/result mismatch")
|
||||
require(time(build["start"]) <= time(build["finish"]), "Build chronology mismatch")
|
||||
require(build["command"] == ["cargo", "build", "--locked", "--offline", "--workspace", "--bins", "--message-format=json"], "Build command mismatch")
|
||||
for key, name in [("inputs", "inputs.json"), ("archive", "inputs.zip"), ("helper", "gate-policy.py"), ("stdout", "stdout.log"), ("stderr", "stderr.log")]:
|
||||
require(digest(read("build/" + name)) == build[key], "Build payload mismatch: " + name)
|
||||
source_pins = obj("build/inputs.json")
|
||||
require(len(source_pins) == build["inputCount"] == 613, "Source count mismatch")
|
||||
with zipfile.ZipFile(io.BytesIO(read("build/inputs.zip"))) as sources:
|
||||
membership(sources, source_pins, "Source")
|
||||
for name, pin in source_pins.items():
|
||||
require(digest(sources.read(name)) == pin, "Source blob mismatch: " + name)
|
||||
build_events = [json.loads(line) for line in read("build/stdout.log").decode().splitlines() if line.startswith("{")]
|
||||
require([e.get("success") for e in build_events if e.get("reason") == "build-finished"] == [True], "Build success event mismatch")
|
||||
require([e for e in build_events if e.get("reason") == "compiler-artifact" and e.get("executable")] == [a["cargo"] for a in build["artifacts"]], "Build artifact log mismatch")
|
||||
binaries = {a["cargo"]["target"]["name"]: a for a in build["artifacts"]}
|
||||
require(binaries["arcadia-studio"]["readback"] == GUI and binaries["arcadia"]["readback"] == CLI, "Native binary build identity mismatch")
|
||||
|
||||
expected = {"build/" + n for n in ["result.json", "started.json", "stdout.log", "stderr.log", "inputs.json", "inputs.zip", "gate-policy.py"]}
|
||||
expected |= {"native/" + n for n in ["run-native.py", "run-native-followup.py", "capture-snippet.js", "check-fixture.py", "verify-creation-checkpoint.py", "fixture-check.result.json", "fixture-check.stdout.json", "fixture-check.stderr.log", "input/project.arcadia"]}
|
||||
before = FIXTURE[:-2] + b'\n include "oa/activities/activity_new_activity.arcadia";\n}\n'
|
||||
after = before.replace(b"position { x 120.0; y 80.0; };", b"position { x 190.0; y 80.0; };")
|
||||
require(read("native/input/project.arcadia") == FIXTURE, "Input fixture bytes mismatch")
|
||||
for label, root in [("saved-before", before), ("saved-after", after)]:
|
||||
expected |= {f"native/{label}/project.arcadia", f"native/{label}/{ACTIVITY_PATH}"}
|
||||
require(read(f"native/{label}/project.arcadia") == root and read(f"native/{label}/{ACTIVITY_PATH}") == ACTIVITY, label + ": exact source construction mismatch")
|
||||
|
||||
previous_finish = time(build["finish"])
|
||||
for trial, labels in LABELS.items():
|
||||
prefix = "native/" + trial + "/"
|
||||
expected |= {prefix + n for n in ["started.json", "result.json", "process.json", "stdout.log", "stderr.log"]}
|
||||
result, started, process = (obj(prefix + n + ".json") for n in ["result", "started", "process"])
|
||||
require(all(result.get(k) == v for k, v in started.items()), trial + ": start/result mismatch")
|
||||
require(result["exitCode"] == 0 and result["binary"] == result["binaryAfter"] == GUI, trial + ": process/binary closure mismatch")
|
||||
require(result["buildReceipt"] == BUILD and result["buildHead"] == HEAD and result["buildInputs"] == INPUTS, trial + ": build provenance mismatch")
|
||||
require(result["command"] == [binaries["arcadia-studio"]["cargo"]["executable"]], trial + ": launch command mismatch")
|
||||
require(previous_finish <= time(result["start"]) <= time(process["observed"]) <= time(result["finish"]), trial + ": chronology mismatch")
|
||||
require(isinstance(process["pid"], int) and process["pid"] > 0, trial + ": PID mismatch")
|
||||
for stream in ["stdout", "stderr"]:
|
||||
require(result[stream] == digest(read(prefix + stream + ".log")) == digest(b""), trial + ": unexpected process output")
|
||||
previous_capture = time(result["start"])
|
||||
for label in labels:
|
||||
expected.add(prefix + label + ".json")
|
||||
frame = obj(prefix + label + ".json")
|
||||
require(previous_capture <= time(frame["time"]) <= time(result["finish"]), trial + ": capture chronology mismatch")
|
||||
previous_capture = time(frame["time"])
|
||||
require(frame["window"]["id"] and (isinstance(frame["accessibility"], dict) or (trial, label, frame["accessibility"]) == ("trial-1", "08-project-opened", None)), trial + ": capture metadata mismatch")
|
||||
require(len(frame["images"]) in [1, 2], trial + ": image inventory mismatch")
|
||||
for i, image in enumerate(frame["images"]):
|
||||
name = f"{label}-{i}.jpg"
|
||||
require(image["file"] == name and image["width"] > 0 and image["height"] > 0, trial + ": image metadata mismatch")
|
||||
require(read(prefix + name).startswith(b"\xff\xd8"), trial + ": JPEG bytes mismatch")
|
||||
expected.add(prefix + name)
|
||||
previous_finish = time(result["finish"])
|
||||
if trial == "trial-2":
|
||||
expected.add(prefix + "baseline.zip")
|
||||
require(result["helper"] == digest(read("native/run-native-followup.py")), "Trial 2 producer pin mismatch")
|
||||
require(result["baselineUnchanged"] is True and result["baselineArchive"] == digest(read(prefix + "baseline.zip")), "Baseline receipt mismatch")
|
||||
require(result["baseline"] == {"project.arcadia": digest(before), ACTIVITY_PATH: digest(ACTIVITY)}, "Baseline source pins mismatch")
|
||||
with zipfile.ZipFile(io.BytesIO(read(prefix + "baseline.zip"))) as baseline:
|
||||
membership(baseline, result["baseline"], "Baseline")
|
||||
require(baseline.read("project.arcadia") == before and baseline.read(ACTIVITY_PATH) == ACTIVITY, "Launch baseline bytes mismatch")
|
||||
|
||||
fixture = obj("native/fixture-check.result.json")
|
||||
require(fixture["exitCode"] == 0 and fixture["binary"] == CLI, "Fixture CLI receipt mismatch")
|
||||
require(fixture["fixtureBefore"] == fixture["fixtureAfter"] == digest(FIXTURE), "Fixture CLI source mismatch")
|
||||
for key, suffix in [("stdout", "stdout.json"), ("stderr", "stderr.log")]:
|
||||
require(fixture[key] == digest(read("native/fixture-check." + suffix)), "Fixture CLI stream mismatch")
|
||||
require(read("native/fixture-check.stderr.log") == b"", "Fixture CLI stderr was not empty")
|
||||
expected.add("native/check-saved-bundles.py")
|
||||
expected.add("native/bundle-checks/summary.json")
|
||||
producer = digest(read("native/check-saved-bundles.py"))
|
||||
require(producer == {"bytes": 4238, "sha256": "b1116c3c5227fad2d99d0d4ab421e0840a09120b1aedfa1fd4364b25787450cc"}, "Saved-bundle producer pin mismatch")
|
||||
summary = obj("native/bundle-checks/summary.json")
|
||||
require(summary["status"] == "PASS" and summary["runs"] == ["saved-before", "saved-after"] and summary["producer"] == producer, "Bundle summary mismatch")
|
||||
diagnostics = [{"severity": "warning", "code": code, "object_id": identity}
|
||||
for code in ["unallocated_leaf", "work_without_behavior_context"]
|
||||
for identity in ["00000000-0000-4000-8000-000000000002", "1e1da408-da79-42ab-a990-9d00b7dc2631"]]
|
||||
for label, source in [("saved-before", before), ("saved-after", after)]:
|
||||
prefix = "native/bundle-checks/" + label
|
||||
expected |= {prefix + suffix for suffix in [".result.json", ".stdout.json", ".stderr.log"]}
|
||||
result, report = obj(prefix + ".result.json"), obj(prefix + ".stdout.json")
|
||||
entry = "C:\\ar-default-9e8r6t\\.local\\default-omission-native\\" + label + "\\project.arcadia"
|
||||
require(result["command"] == [binaries["arcadia"]["cargo"]["executable"], "check", entry, "--json"], label + ": CLI command mismatch")
|
||||
require(result["exitCode"] == 0 and result["binary"] == CLI and result["buildReceipt"] == BUILD and result["producer"] == producer, label + ": CLI provenance mismatch")
|
||||
require(result["filesUnchanged"] is True and result["files"] == {"project.arcadia": digest(source), ACTIVITY_PATH: digest(ACTIVITY)}, label + ": CLI input mismatch")
|
||||
require(previous_finish <= time(result["start"]) <= time(result["finish"]), label + ": CLI chronology mismatch")
|
||||
previous_finish = time(result["finish"])
|
||||
require(result["stdout"] == digest(read(prefix + ".stdout.json")) and result["stderr"] == digest(read(prefix + ".stderr.log")) == digest(b""), label + ": CLI streams mismatch")
|
||||
require(report["entry"] == entry and report["operation"] == "check" and report["status"] == "checked" and report["exit_code"] == 0, label + ": CLI status mismatch")
|
||||
require(report["written"] is False and report["changes"] == [] and report["identities_to_stabilize"] == 0, label + ": CLI changed source or identities")
|
||||
require(result["diagnostics"] == [{k: d[k] for k in ["severity", "code", "object_id"]} for d in report["diagnostics"]] == diagnostics, label + ": expected draft diagnostics mismatch")
|
||||
require(set(pins) == expected, "Exact payload inventory mismatch")
|
||||
|
||||
print("Verified closed native trials, unchanged verified GUI, original captures, 613 build inputs, and exact saved-bundle bytes.")
|
||||
print("Intermediate GUI behavior requires screenshot review; no Linux, performance, packaging, or full-release acceptance claim.")
|
||||
@@ -1,5 +1,8 @@
|
||||
# Ordinary default omission: public consumer verification
|
||||
|
||||
Follow-up: the [completed native workflow evidence](text-default-omission-native-20260913.md)
|
||||
supersedes the native-workflow gap recorded at this earlier checkpoint.
|
||||
|
||||
The ordinary source changes at `7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e` now pass the CLI, HTTP and desktop automated consumer gates, strict workspace Clippy, and a matching Windows build. A new HTTP regression test verifies the distinction between preserving authored source and producing compact canonical export. Native workflow acceptance and integration remain incomplete.
|
||||
|
||||
## Executed candidate and results
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# Ordinary default omission: native editing verification
|
||||
|
||||
The matching Windows application completed graphical creation, drag, model Undo/Redo,
|
||||
Save As and reopening for a compact two-file source project. The saved files match the
|
||||
explicit byte oracle: creation adds one include and one compact activity declaration;
|
||||
moving the existing activity changes only its x coordinate from `120.0` to `190.0`.
|
||||
The authored `port_anchors [] ;` field, spacing and rationale comment survive unchanged.
|
||||
|
||||
This is branch-specific ordinary-source acceptance evidence. Integration with source8
|
||||
and the complete OA/SA release remain separate work in Gitea issues 7, 11 and 27.
|
||||
|
||||
## Candidate and observable checks
|
||||
|
||||
Production code is `7bb366f66a8c6f8b6f66fc9b04c9e3b39f84b78e`. The GUI and CLI were built
|
||||
by the [published consumer gate](text-default-omission-consumers-20260913.md), whose 613
|
||||
captured inputs are published at `94383107153cccb32f3fdcbd8111b6381f3e15aa`. The build
|
||||
captured HEAD `df2e1cd` plus the subsequently published HTTP witness, not HEAD alone.
|
||||
No production edits or new build occurred during the native trials.
|
||||
|
||||
| Observation | Evidence and result |
|
||||
| --- | --- |
|
||||
| Trial 1, 12:13:57–12:28:17 UTC | Opened compact source, created an activity through Model Explorer, inspected its compact declaration, saved the two-file baseline, closed normally. |
|
||||
| Trial 2, 13:10:06–13:15:23 UTC | Opened that baseline, dragged Work, observed x `190.0`, chose **Undo model change** and observed x `120.0` plus saved state, then **Redo model change** and observed x `190.0` plus unsaved state. |
|
||||
| Save As and reopen | Saved to a separate folder, selected New to clear the current model, then opened the saved result from Recent models. Source again showed x `190.0`, the original explicit empty field/comment, and the compact included activity. |
|
||||
| Exact saved-source comparison | Both bundles contain exactly the expected two files. The included activity is byte-identical before/after; the root changes only the expected position token. Original baseline remains unchanged. |
|
||||
| CLI checks on both saved bundles | Both exit 0 with empty stderr, no proposed changes and no identities awaiting stabilization. Each reports four expected draft warnings. |
|
||||
| GUI closure | Both trials exit 0, preserve the verified executable hash, and have empty stdout/stderr. |
|
||||
|
||||
The four draft warnings are `unallocated_leaf` and `work_without_behavior_context`
|
||||
for Work and New activity. These are expected for this deliberately minimal fixture;
|
||||
there are no parse or model errors. The created activity retains UUID
|
||||
`1e1da408-da79-42ab-a990-9d00b7dc2631` through both saves and reopening.
|
||||
|
||||
The GUI SHA-256 is `4070927256414a770c5fbcedfaab922810cea33d9f07610b81e9ab8c0465da44`
|
||||
(115,056,640 bytes). The CLI SHA-256 is
|
||||
`d89aba9f10b598926dfdc5c644474ae891b753e8583a184860e941a359ed0eea` (20,608,512 bytes).
|
||||
The baseline root SHA-256 is `dad153f45038ed9ae79ea7263364e6cdedc40737fe7f63fdad7fb198ee7f65c8`;
|
||||
the edited root is `c93bd35eaaf3a19bc07b5c6a4ee5839ab565e9fd90a2605261b7618fc8a7ecef`.
|
||||
The unchanged included file is `42efe80410d56ae9dd919bad6b0633129028339b8271f500f35d9148a058f50a`.
|
||||
|
||||
## Interpretation and limits
|
||||
|
||||
Native Undo/Redo is an observed UI check. The byte oracle checks persisted bundles;
|
||||
it does not expose or compare the complete in-memory model at the intermediate Undo
|
||||
step. CLI checks parse and validate both full bundles, without comparing their complete
|
||||
decoded models. The separately published HTTP and automated desktop tests cover their
|
||||
documented model equality and exact Undo invariants; those results should not be described
|
||||
as additional native observations.
|
||||
|
||||
The diagram recenters on reopening, so comparing screen coordinates across the reopen
|
||||
would be misleading. Persisted x is verified in Text and the saved-byte oracle.
|
||||
Save-dialog accessibility reported Search Box while the filename field visibly held
|
||||
focus. In trial 2 an initial selection attempt did not take effect and typing appended
|
||||
to the filename. Observation caught this before saving; a confirmed selection and
|
||||
replacement produced the intended full path. Original captures retain the correction.
|
||||
This is an automation focus limitation, not evidence of source corruption.
|
||||
|
||||
Trial 2 pins its runner and baseline archive contemporaneously. Trial 1's original
|
||||
runner and the capture snippet are retained, but the trial 1 receipt does not hash those
|
||||
producer files. Do not infer stronger contemporaneous provenance from later archive pins.
|
||||
These short trials do not establish performance, accessibility completeness, large-model
|
||||
usability, cross-platform acceptance or complete release readiness. Linux remains paused
|
||||
by the user.
|
||||
|
||||
## Reproduction and portable evidence
|
||||
|
||||
The [portable package](experiments/default-native-20260913/README.md) contains the actual
|
||||
inputs, saved bundles, original captures and process/CLI receipts. Its read-only verifier
|
||||
checks archive integrity and the scoped machine oracles; screenshots still require human
|
||||
inspection against the workflow above.
|
||||
|
||||
Independent review inspected the 14 key original frames covering creation, movement,
|
||||
Undo/Redo, Save As correction, clearing the model and reopening both source files.
|
||||
It independently checked the saved-byte oracle and process/CLI receipts, ran the portable
|
||||
verifier, and compared all 160 archived original payloads against the raw local evidence.
|
||||
No actionable finding remained. Parent also ran the verifier. The ZIP SHA-256 is
|
||||
`0eb6f2a566deff1275b19b8c5718ebb56f9afde0518ac65c09d885a1d6e84d68` (5,251,658 bytes).
|
||||
|
||||
```text
|
||||
python harness/experiments/default-native-20260913/verify.py
|
||||
arcadia check <extracted>/native/saved-before/project.arcadia --json
|
||||
arcadia check <extracted>/native/saved-after/project.arcadia --json
|
||||
```
|
||||
|
||||
To repeat the native task, build the identified candidate using the documented Windows
|
||||
GNU LLVM environment, open the archived input, create an activity through Model Explorer,
|
||||
inspect its generated file, save a baseline, drag Work, use model Undo/Redo in Text Actions,
|
||||
save to a separate folder, create a new blank model and reopen the saved result. A new
|
||||
activity receives a new UUID; check that it remains stable within the new trial rather
|
||||
than expecting this run's literal UUID.
|
||||
|
||||
No issue closure, integration, tag or release is claimed by this report.
|
||||
Reference in New Issue
Block a user