Make the Text workspace compact and preserve editing context

Replace the oversized header and reference rail with stable editor slots and a retained supporting drawer. Bind diagnostic, result and menu actions to their original publication and visit; preserve effective selections on navigation and dismiss Actions, Find and the drawer one surface per Escape.

Retain exact Windows source captures, eight final gates (871 desktop passes), independent reviews, native selection/rename/recovery trials and the original failures. All 526 tested inputs and staged evidence were byte-checked before commit. Combined preview integration and packaging remain with issue 27; Linux remains paused.
This commit is contained in:
2026-09-12 22:00:36 -07:00
parent 6a244fb21c
commit 2df7f580aa
660 changed files with 69626 additions and 738 deletions
@@ -0,0 +1,55 @@
"""Preserve closed native trial 2 and its actual attempt-5 inputs and gates."""
from pathlib import Path
import datetime
import hashlib
import json
import shutil
base = Path(__file__).resolve().parent
root = Path('C:/ar-text-9e8r6t')
dest = root / 'harness/experiments/text-workspace-native2-20260913'
dest.mkdir()
records = []
def keep(source, relative):
target = dest / relative
target.parent.mkdir(parents=True, exist_ok=True)
assert not target.exists()
raw = source.read_bytes()
shutil.copyfile(source, target)
assert target.read_bytes() == raw
records.append({'path': relative, 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
trial = base / 'trial-text-2'
closed = json.loads((trial / 'closed.json').read_text())
assert closed['exitCode'] == 0 and closed['binaryUnchanged'] and closed['dllUnchanged']
for source in sorted(trial.rglob('*')):
rel = source.relative_to(trial)
if source.is_file() and (len(rel.parts) == 1 or rel.parts[0] == 'screenshots' or rel.parts[0].startswith('verification-')):
keep(source, 'trial-text-2/' + rel.as_posix())
gate = root / '.local/text-workspace-gates-20260912'
for source in sorted((gate / 'attempt-5').iterdir()):
if source.is_file() and source.suffix in ['.json', '.log', '.zip']:
keep(source, 'attempt-5/' + source.name)
for name in ['fixture-manifest.json', 'launch.py', 'verify_saved.py', 'bind_gates.py']:
keep(base / name, 'helpers/' + name)
keep(gate / 'gate.py', 'helpers/gate.py')
keep(Path(__file__), 'helpers/archive_trial2.py')
for fixture in ['simple', 'representative']:
for variant in ['baseline', 'expected']:
folder = base / fixture / variant
for source in sorted(folder.rglob('*')):
if source.is_file():
keep(source, 'fixtures/' + fixture + '/' + variant + '/' + source.relative_to(folder).as_posix())
scope = base / 'scope-stress'
scope_manifest = json.loads((scope / 'manifest.json').read_text())
for name, row in scope_manifest['files'].items():
raw = (scope / 'model' / name).read_bytes()
assert len(raw) == row['after_bytes'] and hashlib.sha256(raw).hexdigest() == row['after_sha256']
for source in sorted(scope.rglob('*')):
if source.is_file():
keep(source, 'fixtures/scope-stress/' + source.relative_to(scope).as_posix())
with (dest / 'manifest.json').open('x', encoding='utf-8', newline='\n') as output:
json.dump({'atUtc': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'scope': 'Closed attempt-5 native trial2. Selection and transaction results are bounded; inherited Find/drawer simultaneous Escape found and subsequent correction pending. Runtime binaries remain preserved separately by hash.', 'scopeStressFilesUnchanged': True, 'files': records}, output, indent=2)
output.write('\n')
print(json.dumps({'directory': str(dest), 'files': len(records), 'bytes': sum(row['bytes'] for row in records), 'manifestSha256': hashlib.sha256((dest / 'manifest.json').read_bytes()).hexdigest()}))
@@ -0,0 +1,56 @@
"""Preserve closed native trial 2 and its actual attempt-5 inputs and gates."""
from pathlib import Path
import datetime
import hashlib
import json
import shutil
base = Path(__file__).resolve().parent
root = Path('C:/ar-text-9e8r6t')
dest = root / 'harness/experiments/text-workspace-native2-20260913'
dest.mkdir(exist_ok=True)
records = []
def keep(source, relative):
target = dest / relative
target.parent.mkdir(parents=True, exist_ok=True)
raw = source.read_bytes()
if not target.exists():
shutil.copyfile(source, target)
assert target.read_bytes() == raw
records.append({'path': relative, 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
trial = base / 'trial-text-2'
closed = json.loads((trial / 'closed.json').read_text())
assert closed['exitCode'] == 0 and closed['binaryUnchanged'] and closed['dllUnchanged']
for source in sorted(trial.rglob('*')):
rel = source.relative_to(trial)
if source.is_file() and (len(rel.parts) == 1 or rel.parts[0] == 'screenshots' or rel.parts[0].startswith('verification-')):
keep(source, 'trial-text-2/' + rel.as_posix())
gate = root / '.local/text-workspace-gates-20260912'
for source in sorted((gate / 'attempt-5').iterdir()):
if source.is_file() and source.suffix in ['.json', '.log', '.zip']:
keep(source, 'attempt-5/' + source.name)
for name in ['fixture-manifest.json', 'launch.py', 'verify_saved.py', 'bind_gates.py']:
keep(base / name, 'helpers/' + name)
keep(gate / 'gate.py', 'helpers/gate.py')
keep(dest / 'helpers/archive_trial2.py', 'helpers/archive_trial2.py')
keep(Path(__file__), 'helpers/archive_trial2_corrected.py')
for fixture in ['simple', 'representative']:
for variant in ['baseline', 'expected']:
folder = base / fixture / variant
for source in sorted(folder.rglob('*')):
if source.is_file():
keep(source, 'fixtures/' + fixture + '/' + variant + '/' + source.relative_to(folder).as_posix())
scope = base / 'scope-stress'
scope_manifest = json.loads((scope / 'manifest.json').read_text(encoding='utf-8'))
for name, row in scope_manifest['files'].items():
raw = (scope / 'model' / name).read_bytes()
assert len(raw) == row['after_bytes'] and hashlib.sha256(raw).hexdigest() == row['after_sha256']
for source in sorted(scope.rglob('*')):
if source.is_file():
keep(source, 'fixtures/scope-stress/' + source.relative_to(scope).as_posix())
with (dest / 'manifest.json').open('x', encoding='utf-8', newline='\n') as output:
json.dump({'atUtc': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'scope': 'Closed attempt-5 native trial2. Selection and transaction results are bounded; inherited Find/drawer simultaneous Escape found and subsequent correction pending. Runtime binaries remain preserved separately by hash.', 'scopeStressFilesUnchanged': True, 'files': records}, output, indent=2)
output.write('\n')
print(json.dumps({'directory': str(dest), 'files': len(records), 'bytes': sum(row['bytes'] for row in records), 'manifestSha256': hashlib.sha256((dest / 'manifest.json').read_bytes()).hexdigest()}))
@@ -0,0 +1,88 @@
"""Bind completed Windows gate inputs and preserved GUI for a development trial."""
from pathlib import Path
from datetime import datetime, timezone
import hashlib
import json
import re
import subprocess
import sys
BASE = Path(__file__).resolve().parent
ROOT = Path('C:/ar-text-9e8r6t')
attempt = sys.argv[1]
assert re.fullmatch(r'attempt-[0-9]+', attempt)
gate = ROOT / '.local/text-workspace-gates-20260912' / attempt
destination = BASE / (attempt + '-launch-manifest.json')
assert not destination.exists()
def identity(path):
raw = path.read_bytes()
return {'path': str(path.resolve()), 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()}
def read(name):
return json.loads((gate / name).read_text(encoding='utf-8'))
names = ['clippy', 'membership', 'focused', 'selection', 'tests', 'timing', 'gui']
complete = read('complete.json')
assert complete['inputsUnchanged'] is True and complete['gates'] == names
inputs = read('inputs.json')
assert identity(gate / 'inputs.zip')['sha256'] == inputs['archiveSha256']
assert subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT).decode().strip() == inputs['baseCommit']
scopes = ['Cargo.toml', 'Cargo.lock', 'crates', 'build', '.cargo', 'docs', 'examples', 'harness/fixtures']
raw_names = subprocess.check_output(['git', 'ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', *scopes], cwd=ROOT)
current_names = sorted(set(name.decode() for name in raw_names.split(b'\0') if name))
assert current_names == [item['path'] for item in inputs['files']]
for item in inputs['files']:
path = (ROOT / item['path']).resolve()
assert path.is_relative_to(ROOT.resolve())
measured = identity(path)
assert all(measured[key] == item[key] for key in ['bytes', 'sha256'])
evidence = [identity(gate / name) for name in ['inputs.json', 'inputs.zip', 'environment.json', 'complete.json']]
receipts = {}
for name in names:
receipt = read(name + '-result.json')
assert receipt['exitCode'] == 0 and receipt['inputsUnchanged'] is True
for stream in ['stdout', 'stderr']:
log = identity(gate / (name + '-' + stream + '.log'))
assert log['sha256'] == receipt[stream + 'Sha256']
evidence.append(log)
evidence.append(identity(gate / (name + '-result.json')))
receipts[name] = receipt
membership = receipts['membership']['testMembership']
assert not membership['missing'] and membership['diagnosticGuardCount'] == 20
assert any('queued_group_toggle_cannot_mutate' in name for name in membership['required'])
assert any('all_reference_exceptions_fit_allocated_width' in name for name in membership['required'])
assert sum('text_workspace::focus_selection_tests::' in name for name in membership['required']) == 4
assert sum('source_navigation::selection::tests::' in name for name in membership['required']) == 7
test_output = (gate / 'tests-stdout.log').read_text(encoding='utf-8')
result = re.search(r'test result: ok\. (\d+) passed; 0 failed; (\d+) ignored;', test_output)
assert result and sum(map(int, result.groups())) == membership['listed']
timing_output = (gate / 'timing-stdout.log').read_text(encoding='utf-8')
assert 'test result: ok. 1 passed; 0 failed;' in timing_output
binary_record = receipts['gui']['binary']
binary = identity(Path(binary_record['preserved']))
assert all(binary[key] == binary_record[key] for key in ['bytes', 'sha256'])
artifact = binary_record['artifact']
assert Path(artifact['manifest_path']).resolve() == ROOT / 'crates/oa-desktop/Cargo.toml'
assert artifact['target']['name'] == 'arcadia-studio'
assert artifact['executable'] == binary_record['path']
manifest = {
'atUtc': datetime.now(timezone.utc).isoformat(),
'nativeReady': True,
'scope': 'Completed Windows source gates authorize development GUI evaluation; native and packaged acceptance remain pending.',
'target': 'x86_64-pc-windows-gnullvm',
'baseCommit': inputs['baseCommit'],
'sourceFiles': len(inputs['files']),
'sourceArchiveSha256': inputs['archiveSha256'],
'membership': membership,
'binary': binary,
'evidence': evidence,
'helper': identity(Path(__file__)),
}
with destination.open('x', encoding='utf-8', newline='\n') as output:
json.dump(manifest, output, indent=2)
output.write('\n')
print(json.dumps(identity(destination)), flush=True)
@@ -0,0 +1,435 @@
{
"preparedAtUtc": "2026-09-12T11:17:21.035184+00:00",
"oracle_sha256": "967d9ba3c6fb3a7efb410833903ec94556ca2d48a67d5072c8bb160f40a00f9c",
"dll_sha256": "f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4",
"cases": {
"simple": {
"original": "valid-baseline",
"original_files": {
"links.arcadia": {
"sha256": "d3229ecf6300804103eb7f85bd5891c022f6f6c194dbdbbdcb54e9550338dc3b",
"bytes": 211
},
"project.arcadia": {
"sha256": "79e26836c048a35aaf98b21ff006ae8ac931160abd9913b9e67b542303215414",
"bytes": 277
},
"救援/assess.arcadia": {
"sha256": "d99593537e67b2dfd293623f467ffbd46af4ea259dffae55d1fe9995c86e6992",
"bytes": 192
},
"救援/confirm.arcadia": {
"sha256": "591b32db3b1282825750d002d9293cfc450d55252506623302ce36c949fe9919",
"bytes": 92
}
},
"literal_edits": [
{
"path": "救援/assess.arcadia",
"before": "oa_activity assess \"Assess 救援 request\"",
"after": "oa_activity assess_damage \"Assess 救援 request\"",
"count": 1,
"before_snippet_spans_at_edit": [
{
"start": 47,
"end": 89
}
]
},
{
"path": "links.arcadia",
"before": "; source @assess; target @confirm;",
"after": "; source @assess_damage; target @confirm;",
"count": 1,
"before_snippet_spans_at_edit": [
{
"start": 127,
"end": 161
}
]
}
],
"expected_files": {
"links.arcadia": {
"sha256": "c056d46011b3b86ae05dc49b8e6d69cba903f8e7379b06c6d0c5d93639768a09",
"bytes": 218
},
"project.arcadia": {
"sha256": "79e26836c048a35aaf98b21ff006ae8ac931160abd9913b9e67b542303215414",
"bytes": 277
},
"救援/assess.arcadia": {
"sha256": "8d326ec33370b8ecf73f6d611904875994888baa3495f7c1df4613866e645d03",
"bytes": 199
},
"救援/confirm.arcadia": {
"sha256": "591b32db3b1282825750d002d9293cfc450d55252506623302ce36c949fe9919",
"bytes": 92
}
},
"changed_files": [
"links.arcadia",
"救援/assess.arcadia"
],
"arcadia_files": 4
},
"representative": {
"original": "release1-baseline",
"original_files": {
"evidence/repair-check.md": {
"sha256": "f4db17bdca4ecbb1bf0caef01b2da5f1f7f798ab3152b648ce6dd8696a6a68e5",
"bytes": 1419
},
"expected-diagnostics.json": {
"sha256": "3700393d76b940cfc076bf52861bd7b1f43370f8eabce3594531bd0bf1fc851e",
"bytes": 288
},
"model.json": {
"sha256": "ef0ef4006c3e09d5db6e1b621256b3f7d6642f3a7b09cc34607cfbcca830c727",
"bytes": 134520
},
"model.rs": {
"sha256": "15f30f6bde655808fe754665c26d560e36f2a9bad340f346b09137d0d05045f5",
"bytes": 28762
},
"oa/activities/activity_oa_restore_work.arcadia": {
"sha256": "83e73d0a013d5c3e1a4af0d9139ab0cfa362d25a846671fc2dac59181061a9d4",
"bytes": 1307
},
"oa/behavior/process_oa_assessment_procedure.arcadia": {
"sha256": "172c32c044ef4b5bc58a1f4635cc81f48dabb4014479b47dce7b25fedf2dbd0d",
"bytes": 697
},
"oa/behavior/process_oa_field_procedure.arcadia": {
"sha256": "d2552dc5383e2e91cb302a790364e197f663c2edc013a2ab1978789825c9c324",
"bytes": 1781
},
"oa/behavior/process_oa_response.arcadia": {
"sha256": "cf86f46fa5c5d70592ef43f1bc1cb4d968efd8add384ba88036bef6b88aa4abc",
"bytes": 3225
},
"oa/behavior/scenario_oa_conversation.arcadia": {
"sha256": "b25be524e98a35ebac5e4481b7609c027b32baf9605e8097f807560f94a77ca6",
"bytes": 1795
},
"oa/behavior/scenario_oa_full_scenario.arcadia": {
"sha256": "00a1edf2c9707a0eb62ac070c2d02467874f2c9c1f273cc6ddb53d6d65999a1c",
"bytes": 1261
},
"oa/behavior/state_machine_oa_monitor.arcadia": {
"sha256": "447c9ad1359f4a31ecf975ad07c0b08d8e7e03191fb0858e2fc56f377b223cd5",
"bytes": 2022
},
"oa/capabilities.arcadia": {
"sha256": "fc8012e5554350b12e1cb80080f8feab80d933c9b33c0f2a7bb500cb7d609936",
"bytes": 781
},
"oa/model.arcadia": {
"sha256": "f7cf914766ea73ec53b85e32d117ea9a9dba52d3e038246863541ae7069b1a15",
"bytes": 661
},
"oa/participants.arcadia": {
"sha256": "951764c14179f27c10e315acf2ea37d1fff54c77b8441e23addd239e8c715ce3",
"bytes": 1834
},
"oa/types.arcadia": {
"sha256": "9d0396fb82dd5733edd8d1cf52f968ca84906927c704f9cf0944a7fae215cf49",
"bytes": 788
},
"project.arcadia": {
"sha256": "b2674e6bf77cfe0f6f0ba79c81d2e96d92f39c02ca2c6266d80e91723bfb9fda",
"bytes": 1958
},
"README.md": {
"sha256": "113cfb1cf38a98b51bff60442d86a35d636a3d80ef206bece7d53d0aae67f2d5",
"bytes": 11137
},
"sa/behavior/process_sa_assessment_procedure.arcadia": {
"sha256": "73928ced61c06cbc08728d7956676a50fd4c05aa5b7f1ff4f29ce27a0b0f2088",
"bytes": 706
},
"sa/behavior/process_sa_field_procedure.arcadia": {
"sha256": "886d462af83110cbfa55dd232a667ea1446761234471357cbb878794e98e8768",
"bytes": 1790
},
"sa/behavior/process_sa_response.arcadia": {
"sha256": "041785fc22842423822431bd5e6e8d16094ebd0716965e7c765fb8c1d7549e8a",
"bytes": 3234
},
"sa/behavior/scenario_sa_conversation.arcadia": {
"sha256": "97276f5757ee9aa12a0dbd9d3ccd58174b3091162bb8bcce357cec20a45f5d85",
"bytes": 2127
},
"sa/behavior/scenario_sa_full_scenario.arcadia": {
"sha256": "e12fc406b99d60a2f7768aaa0b25ba560e8605f0b8e37f3a7cdd3b8443562b74",
"bytes": 1256
},
"sa/behavior/state_machine_sa_monitor.arcadia": {
"sha256": "05ce29af99424c491c47fe2450dc6f5f8ce995511c01ec7e17bb5855be3c9736",
"bytes": 2022
},
"sa/capabilities.arcadia": {
"sha256": "b6912fb3ece439912345fa71724acd462e716a1e5a88203a1058a5c3b2c20a4f",
"bytes": 781
},
"sa/functions/function_sa_audit_thresholds.arcadia": {
"sha256": "e5a04325d52183956dca814dd90f4e56c96c6b7db0f4f202f203ecb49c3e0f4f",
"bytes": 297
},
"sa/functions/function_sa_restore_work.arcadia": {
"sha256": "fddeb67308051325041fee641fe758ddf43345b7c47b66d433616ad07fdccdd6",
"bytes": 2576
},
"sa/model.arcadia": {
"sha256": "d431509251acb859fbb98733b6d18add952495e10a78703fbe8f31e40bc083c4",
"bytes": 661
},
"sa/participants.arcadia": {
"sha256": "780d2eb08b217b67b55febb3d34846f727b8ee9018df6c5741748647e36b2ff8",
"bytes": 4012
},
"sa/types.arcadia": {
"sha256": "101fc0fbd99f1101514aa7b6da4f8e535aae0bb94c9e2b9e7e6c151135b28660",
"bytes": 1227
},
"traceability.arcadia": {
"sha256": "48a96f543456c9b5a5798fc795594e4119147fe45f11a6f109f141b7f514560f",
"bytes": 29506
},
"transition-before.json": {
"sha256": "2253e6434f741687e22327c37d520ed15c043bc36025498650bc2366bb6a874d",
"bytes": 35801
},
"transition-request.json": {
"sha256": "43b9a22e5f95ad3bc0ebd2478ead0e14406854abc989ae94ded9367b013d812a",
"bytes": 4276
},
"views/diagram_oa_allocation_view.arcadia": {
"sha256": "dfc0eb61e0e2aa5bda45524571fbfa3494f44ce19696f3e15e07438074a07bc7",
"bytes": 2176
},
"views/diagram_sa_allocation_view.arcadia": {
"sha256": "b78b43a26a82efb8fbd5374b09c329fa341f57b29f635d397b9ef8aede71d389",
"bytes": 2173
},
"views/diagram_sa_capability_view.arcadia": {
"sha256": "75e8dc9fb30f25d6f8fd3c6b595593ab4f98958a25798f961e336e0fac557649",
"bytes": 1620
},
"views/diagram_sa_service_view.arcadia": {
"sha256": "b08c84f3ea633e7c78dfdad3272f75415f6256cf3614b6d99bfd4f0269076c9b",
"bytes": 2209
},
"views/diagram_sa_state_view.arcadia": {
"sha256": "5f42f4c605e57b817d8400ed21f2b14bfc4e1592aebe941ff113767504c2b869",
"bytes": 1931
}
},
"literal_edits": [
{
"path": "oa/activities/activity_oa_restore_work.arcadia",
"before": "oa_activity oa_restore_work \"Restore safe pressure\"",
"after": "oa_activity oa_restore_pressure \"Restore safe pressure\"",
"count": 1,
"before_snippet_spans_at_edit": [
{
"start": 0,
"end": 51
}
]
},
{
"path": "oa/activities/activity_oa_restore_work.arcadia",
"before": " parent @oa_restore_work;",
"after": " parent @oa_restore_pressure;",
"count": 4,
"before_snippet_spans_at_edit": [
{
"start": 250,
"end": 278
},
{
"start": 393,
"end": 421
},
{
"start": 539,
"end": 567
},
{
"start": 679,
"end": 707
}
]
},
{
"path": "traceability.arcadia",
"before": " oa @oa_restore_work;",
"after": " oa @oa_restore_pressure;",
"count": 1,
"before_snippet_spans_at_edit": [
{
"start": 26877,
"end": 26901
}
]
}
],
"expected_files": {
"evidence/repair-check.md": {
"sha256": "f4db17bdca4ecbb1bf0caef01b2da5f1f7f798ab3152b648ce6dd8696a6a68e5",
"bytes": 1419
},
"expected-diagnostics.json": {
"sha256": "3700393d76b940cfc076bf52861bd7b1f43370f8eabce3594531bd0bf1fc851e",
"bytes": 288
},
"model.json": {
"sha256": "ef0ef4006c3e09d5db6e1b621256b3f7d6642f3a7b09cc34607cfbcca830c727",
"bytes": 134520
},
"model.rs": {
"sha256": "15f30f6bde655808fe754665c26d560e36f2a9bad340f346b09137d0d05045f5",
"bytes": 28762
},
"oa/activities/activity_oa_restore_work.arcadia": {
"sha256": "8c6cf1e9b6fdd118602659b6fb3ad0f1988ae700fcd548abede259da2c3a29e5",
"bytes": 1327
},
"oa/behavior/process_oa_assessment_procedure.arcadia": {
"sha256": "172c32c044ef4b5bc58a1f4635cc81f48dabb4014479b47dce7b25fedf2dbd0d",
"bytes": 697
},
"oa/behavior/process_oa_field_procedure.arcadia": {
"sha256": "d2552dc5383e2e91cb302a790364e197f663c2edc013a2ab1978789825c9c324",
"bytes": 1781
},
"oa/behavior/process_oa_response.arcadia": {
"sha256": "cf86f46fa5c5d70592ef43f1bc1cb4d968efd8add384ba88036bef6b88aa4abc",
"bytes": 3225
},
"oa/behavior/scenario_oa_conversation.arcadia": {
"sha256": "b25be524e98a35ebac5e4481b7609c027b32baf9605e8097f807560f94a77ca6",
"bytes": 1795
},
"oa/behavior/scenario_oa_full_scenario.arcadia": {
"sha256": "00a1edf2c9707a0eb62ac070c2d02467874f2c9c1f273cc6ddb53d6d65999a1c",
"bytes": 1261
},
"oa/behavior/state_machine_oa_monitor.arcadia": {
"sha256": "447c9ad1359f4a31ecf975ad07c0b08d8e7e03191fb0858e2fc56f377b223cd5",
"bytes": 2022
},
"oa/capabilities.arcadia": {
"sha256": "fc8012e5554350b12e1cb80080f8feab80d933c9b33c0f2a7bb500cb7d609936",
"bytes": 781
},
"oa/model.arcadia": {
"sha256": "f7cf914766ea73ec53b85e32d117ea9a9dba52d3e038246863541ae7069b1a15",
"bytes": 661
},
"oa/participants.arcadia": {
"sha256": "951764c14179f27c10e315acf2ea37d1fff54c77b8441e23addd239e8c715ce3",
"bytes": 1834
},
"oa/types.arcadia": {
"sha256": "9d0396fb82dd5733edd8d1cf52f968ca84906927c704f9cf0944a7fae215cf49",
"bytes": 788
},
"project.arcadia": {
"sha256": "b2674e6bf77cfe0f6f0ba79c81d2e96d92f39c02ca2c6266d80e91723bfb9fda",
"bytes": 1958
},
"README.md": {
"sha256": "113cfb1cf38a98b51bff60442d86a35d636a3d80ef206bece7d53d0aae67f2d5",
"bytes": 11137
},
"sa/behavior/process_sa_assessment_procedure.arcadia": {
"sha256": "73928ced61c06cbc08728d7956676a50fd4c05aa5b7f1ff4f29ce27a0b0f2088",
"bytes": 706
},
"sa/behavior/process_sa_field_procedure.arcadia": {
"sha256": "886d462af83110cbfa55dd232a667ea1446761234471357cbb878794e98e8768",
"bytes": 1790
},
"sa/behavior/process_sa_response.arcadia": {
"sha256": "041785fc22842423822431bd5e6e8d16094ebd0716965e7c765fb8c1d7549e8a",
"bytes": 3234
},
"sa/behavior/scenario_sa_conversation.arcadia": {
"sha256": "97276f5757ee9aa12a0dbd9d3ccd58174b3091162bb8bcce357cec20a45f5d85",
"bytes": 2127
},
"sa/behavior/scenario_sa_full_scenario.arcadia": {
"sha256": "e12fc406b99d60a2f7768aaa0b25ba560e8605f0b8e37f3a7cdd3b8443562b74",
"bytes": 1256
},
"sa/behavior/state_machine_sa_monitor.arcadia": {
"sha256": "05ce29af99424c491c47fe2450dc6f5f8ce995511c01ec7e17bb5855be3c9736",
"bytes": 2022
},
"sa/capabilities.arcadia": {
"sha256": "b6912fb3ece439912345fa71724acd462e716a1e5a88203a1058a5c3b2c20a4f",
"bytes": 781
},
"sa/functions/function_sa_audit_thresholds.arcadia": {
"sha256": "e5a04325d52183956dca814dd90f4e56c96c6b7db0f4f202f203ecb49c3e0f4f",
"bytes": 297
},
"sa/functions/function_sa_restore_work.arcadia": {
"sha256": "fddeb67308051325041fee641fe758ddf43345b7c47b66d433616ad07fdccdd6",
"bytes": 2576
},
"sa/model.arcadia": {
"sha256": "d431509251acb859fbb98733b6d18add952495e10a78703fbe8f31e40bc083c4",
"bytes": 661
},
"sa/participants.arcadia": {
"sha256": "780d2eb08b217b67b55febb3d34846f727b8ee9018df6c5741748647e36b2ff8",
"bytes": 4012
},
"sa/types.arcadia": {
"sha256": "101fc0fbd99f1101514aa7b6da4f8e535aae0bb94c9e2b9e7e6c151135b28660",
"bytes": 1227
},
"traceability.arcadia": {
"sha256": "cd3d7ebaf7d6aedf1eaa739afaf0268c487b05cc2685233568425ce0498cf338",
"bytes": 29510
},
"transition-before.json": {
"sha256": "2253e6434f741687e22327c37d520ed15c043bc36025498650bc2366bb6a874d",
"bytes": 35801
},
"transition-request.json": {
"sha256": "43b9a22e5f95ad3bc0ebd2478ead0e14406854abc989ae94ded9367b013d812a",
"bytes": 4276
},
"views/diagram_oa_allocation_view.arcadia": {
"sha256": "dfc0eb61e0e2aa5bda45524571fbfa3494f44ce19696f3e15e07438074a07bc7",
"bytes": 2176
},
"views/diagram_sa_allocation_view.arcadia": {
"sha256": "b78b43a26a82efb8fbd5374b09c329fa341f57b29f635d397b9ef8aede71d389",
"bytes": 2173
},
"views/diagram_sa_capability_view.arcadia": {
"sha256": "75e8dc9fb30f25d6f8fd3c6b595593ab4f98958a25798f961e336e0fac557649",
"bytes": 1620
},
"views/diagram_sa_service_view.arcadia": {
"sha256": "b08c84f3ea633e7c78dfdad3272f75415f6256cf3614b6d99bfd4f0269076c9b",
"bytes": 2209
},
"views/diagram_sa_state_view.arcadia": {
"sha256": "5f42f4c605e57b817d8400ed21f2b14bfc4e1592aebe941ff113767504c2b869",
"bytes": 1931
}
},
"changed_files": [
"oa/activities/activity_oa_restore_work.arcadia",
"traceability.arcadia"
],
"arcadia_files": 30
}
}
}
@@ -0,0 +1,109 @@
"""Capture exact working inputs and run one serial Windows acceptance attempt."""
import datetime
import hashlib
import json
import os
from pathlib import Path
import re
import shutil
import subprocess
import sys
import time
import zipfile
ROOT = Path(__file__).resolve().parents[2]
BASE = Path(__file__).resolve().parent
label = sys.argv[1]
if not re.fullmatch(r'attempt-[0-9]+', label):
raise RuntimeError('Invalid attempt label')
DEST = BASE / label
DEST.mkdir()
if os.environ.get('CARGO_BUILD_JOBS') != '1':
raise RuntimeError('One Windows compiler job required')
SCOPES = ['Cargo.toml', 'Cargo.lock', 'crates', 'build', '.cargo', 'docs', 'examples', 'harness/fixtures']
def now():
return datetime.datetime.now(datetime.timezone.utc).isoformat()
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def names():
data = subprocess.check_output(['git', 'ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', *SCOPES], cwd=ROOT)
return sorted(set(p.decode() for p in data.split(b'\0') if p))
def write(name, value):
with (DEST / name).open('x', encoding='utf-8', newline='\n') as output:
json.dump(value, output, indent=2)
output.write('\n')
inputs = []
with zipfile.ZipFile(DEST / 'inputs.zip', 'x', zipfile.ZIP_DEFLATED) as archive:
for name in names():
raw = (ROOT / name).read_bytes()
archive.writestr(name, raw)
inputs.append({'path': name, 'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()})
def verify():
return names() == [row['path'] for row in inputs] and all(sha(ROOT / row['path']) == row['sha256'] for row in inputs)
write('inputs.json', {'atUtc': now(), 'baseCommit': subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=ROOT).decode().strip(), 'archiveSha256': sha(DEST / 'inputs.zip'), 'files': inputs})
write('environment.json', {'atUtc': now(), 'versions': {name: subprocess.check_output(command, cwd=ROOT).decode() for name, command in [('rustc', ['rustc', '-vV']), ('cargo', ['cargo', '-V'])]}, 'variables': {key: os.environ.get(key) for key in ['RUSTUP_HOME', 'CARGO_HOME', 'RUSTUP_TOOLCHAIN', 'CARGO_TARGET_DIR', 'CARGO_BUILD_JOBS', 'CARGO_TARGET_X86_64_PC_WINDOWS_GNULLVM_LINKER']}})
gates = [
('clippy', ['cargo', 'clippy', '--locked', '--offline', '-p', 'oa-desktop', '--all-targets', '--', '-D', 'warnings']),
('membership', ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--', '--list']),
('focused', ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', 'text_workspace', '--', '--nocapture', '--test-threads=1']),
('selection', ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', 'selection', '--', '--nocapture', '--test-threads=1']),
('tests', ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--', '--test-threads=1']),
('timing', ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', 'app::source_rename::timing_tests::accepted_release1_prepare_commit_sync_and_confirm_timing', '--', '--ignored', '--nocapture', '--test-threads=1']),
('gui', ['cargo', 'build', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--message-format=json-render-diagnostics']),
]
for name, command in gates:
if not verify():
raise RuntimeError('Source inputs changed before gate')
print(json.dumps({'starting': name, 'command': command}), flush=True)
start, clock = now(), time.perf_counter()
with (DEST / (name + '-stdout.log')).open('xb') as out, (DEST / (name + '-stderr.log')).open('xb') as err:
result = subprocess.run(command, cwd=ROOT, stdout=out, stderr=err)
receipt = {'command': command, 'started': start, 'finished': now(), 'seconds': time.perf_counter() - clock, 'exitCode': result.returncode, 'inputsUnchanged': verify(), 'stdoutSha256': sha(DEST / (name + '-stdout.log')), 'stderrSha256': sha(DEST / (name + '-stderr.log'))}
if name == 'membership' and result.returncode == 0:
listed = {line.removesuffix(': test') for line in (DEST / 'membership-stdout.log').read_text(encoding='utf-8').splitlines() if line.endswith(': test')}
required = {
'app::text_workspace::tests::document_reset_preserves_popup_token_sequence_and_drops_old_menu_authority',
'app::text_workspace::tests::stale_retained_group_can_expand_without_navigating_or_applying_drafts',
'app::text_workspace::lifecycle_tests::saved_new_destination_republishes_current_warning_and_refuses_old_primary_and_related',
'app::text_workspace::lifecycle_tests::invalid_repair_open_clears_prior_presentation_and_publishes_current_problems_preserving_worker',
'views::text_workspace::tests::highlighted_sensor_editor_retains_real_scrolled_buffer_across_panel_rebuilds',
'views::text_workspace::tests::drawer_clamps_to_actual_center_allocation_including_oversize_requests',
'diagnostic_input::tests::same_publication_new_visit_cancels_armed_rows_without_a_hidden_tree_frame',
'app::source_symbols::tests::retained_choices_cannot_replay_after_hide_or_references_problems_references',
'app::text_workspace::tests::queued_group_toggle_cannot_mutate_a_reopened_or_rotated_visit',
'views::text_workspace::summary_visibility_tests::all_reference_exceptions_fit_allocated_width_with_wide_alias_and_large_counts',
'app::text_workspace::focus_selection_tests::word_and_line_selection_survive_find_close_and_escape_then_replace_exact_bytes',
'app::text_workspace::focus_selection_tests::mounted_direct_typing_control_and_old_cursor_roundtrip_discriminate_selection_loss',
'app::text_workspace::focus_selection_tests::stale_focus_ticket_and_later_raw_input_cannot_steal_focus_or_change_selected_bytes',
'app::text_workspace::focus_selection_tests::explicit_cursor_navigation_still_moves_and_selects_requested_line',
'app::source_symbols::tests::effective_selection_survives_file_roundtrip_and_definition_back',
'app::source_symbols::tests::effective_selection_is_untouched_by_noop_missing_invalid_or_cancelled_navigation',
'app::source_symbols::tests::changed_active_origin_back_keeps_current_effective_selection',
'app::source_symbols::tests::source_creation_preserves_outgoing_selection_and_undisplayed_entry_cursor',
'source_navigation::selection::tests::unicode_normal_ranges_preserve_forward_and_reverse_direction',
'source_navigation::selection::tests::repeated_unicode_words_capture_the_selected_occurrence_without_searching',
'source_navigation::selection::tests::line_selection_expands_past_its_interior_unicode_caret',
'source_navigation::selection::tests::multiline_ranges_use_copied_lf_and_utf8_columns_for_physical_crlf_and_mixed_endings',
'source_navigation::selection::tests::expanded_word_and_line_modes_capture_multiline_ranges_in_both_directions',
'source_navigation::selection::tests::trailing_newline_selection_restores_endpoint_on_the_empty_last_line',
'source_navigation::selection::tests::absent_and_empty_selection_do_not_move_the_departing_caret',
}
receipt['testMembership'] = {'listed': len(listed), 'required': sorted(required), 'missing': sorted(required - listed), 'diagnosticGuardCount': sum(name.startswith('diagnostic_input::tests::') for name in listed)}
if required - listed or receipt['testMembership']['diagnosticGuardCount'] != 20:
write(name + '-result.json', receipt)
raise RuntimeError('New Text workspace test membership differs; shared-target cache output is not accepted')
if name == 'gui' and result.returncode == 0:
records = [json.loads(line) for line in (DEST / 'gui-stdout.log').read_text(encoding='utf-8').splitlines() if line.startswith('{')]
artifacts = [record for record in records if record.get('reason') == 'compiler-artifact' and record.get('target', {}).get('name') == 'arcadia-studio' and record.get('executable')]
if len(artifacts) != 1:
raise RuntimeError('Expected exactly one desktop artifact')
binary = Path(artifacts[0]['executable'])
shutil.copyfile(binary, DEST / 'arcadia-studio.exe')
if sha(binary) != sha(DEST / 'arcadia-studio.exe'):
raise RuntimeError('Desktop preservation differs')
receipt['binary'] = {'path': str(binary), 'preserved': str(DEST / 'arcadia-studio.exe'), 'sha256': sha(binary), 'bytes': binary.stat().st_size, 'artifact': artifacts[0]}
write(name + '-result.json', receipt)
print(json.dumps(receipt), flush=True)
if result.returncode or not receipt['inputsUnchanged']:
raise SystemExit(result.returncode or 1)
write('complete.json', {'atUtc': now(), 'inputsUnchanged': verify(), 'gates': [name for name, _ in gates], 'scope': 'Windows headless tests/lint/timing/build; no native acceptance'})
@@ -0,0 +1,79 @@
"""Launch a gate-bound development GUI in a fresh private profile; retain child."""
from pathlib import Path
from datetime import datetime, timezone
import hashlib
import json
import os
import re
import shutil
import subprocess
import sys
BASE = Path(__file__).resolve().parent
def now():
return datetime.now(timezone.utc).isoformat()
def identity(path):
raw = path.read_bytes()
return {'bytes': len(raw), 'sha256': hashlib.sha256(raw).hexdigest()}
manifest_path, manifest_hash, label = sys.argv[1:]
manifest_path = Path(manifest_path)
assert manifest_path.is_absolute() and identity(manifest_path)['sha256'] == manifest_hash
manifest = json.loads(manifest_path.read_text(encoding='utf-8'))
assert manifest['nativeReady'] is True and re.fullmatch('trial-text-[0-9]+', label)
assert manifest['target'] == 'x86_64-pc-windows-gnullvm'
for item in [manifest['binary'], *manifest['evidence']]:
path = Path(item['path'])
assert path.is_absolute() and identity(path) == {key: item[key] for key in ['bytes', 'sha256']}
dll = BASE / 'runtime/libunwind.dll'
assert identity(dll)['sha256'] == 'f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4'
trial = BASE / label
trial.mkdir()
for name in ['bin', 'profile/roaming', 'profile/local', 'profile/Desktop', 'tmp', 'cwd', 'screenshots']:
(trial / name).mkdir(parents=True, exist_ok=True)
executable = trial / 'bin/arcadia-studio.exe'
shutil.copyfile(manifest['binary']['path'], executable)
shutil.copyfile(dll, trial / 'bin/libunwind.dll')
assert identity(executable) == {key: manifest['binary'][key] for key in ['bytes', 'sha256']}
assert identity(dll) == identity(trial / 'bin/libunwind.dll')
shutil.copyfile(manifest_path, trial / 'launch-manifest.json')
def record(name, value):
with (trial / name).open('x', encoding='utf-8', newline='\n') as output:
json.dump(value, output, indent=2)
output.write('\n')
inherited = {key.upper(): value for key, value in os.environ.items()}
env = {key: inherited[key.upper()] for key in ['SystemRoot', 'SystemDrive', 'ProgramData', 'ALLUSERSPROFILE', 'PUBLIC']}
system = env['SystemRoot']
env.update({'WINDIR': system, 'PATH': system + '\\System32;' + system,
'USERPROFILE': str(trial / 'profile'), 'APPDATA': str(trial / 'profile/roaming'),
'LOCALAPPDATA': str(trial / 'profile/local'),
'TEMP': str(trial / 'tmp'), 'TMP': str(trial / 'tmp')})
with (trial / 'stdout.log').open('xb') as out, (trial / 'stderr.log').open('xb') as err:
start = now()
child = subprocess.Popen([str(executable)], cwd=trial / 'cwd', env=env, stdout=out, stderr=err,
creationflags=subprocess.CREATE_NO_WINDOW)
receipt_error = None
try:
receipt = {'started': start, 'pid': child.pid, 'executable': str(executable),
'binary': identity(executable), 'environment': env, 'cwd': str(trial / 'cwd'),
'manifestSha256': manifest_hash, 'helper': identity(Path(__file__)),
'scope': 'Development GUI launch, not packaged release acceptance.'}
record('launch.json', receipt)
print(json.dumps(receipt), flush=True)
except Exception as error:
receipt_error = repr(error)
finally:
code = child.wait()
finished = now()
closure = {'finished': finished, 'pid': child.pid, 'exitCode': code,
'stdout': identity(trial / 'stdout.log'), 'stderr': identity(trial / 'stderr.log'),
'binaryUnchanged': identity(executable) == {key: manifest['binary'][key] for key in ['bytes', 'sha256']},
'dllUnchanged': identity(dll) == identity(trial / 'bin/libunwind.dll'),
'launchReceiptError': receipt_error}
record('closed.json', closure)
print(json.dumps(closure), flush=True)
sys.exit(0 if code == 0 and receipt_error is None and closure['binaryUnchanged'] and closure['dllUnchanged'] else 1)
@@ -0,0 +1,80 @@
"""Read-only full saved-model/source and physical-byte comparison after a GUI step."""
from datetime import datetime, timezone
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess
import sys
import time
BASE = Path(__file__).resolve().parent
ROOT = BASE.parents[1]
trial, case, expected, step = sys.argv[1:]
if not re.fullmatch(r'trial-text-[0-9]+', trial):
raise RuntimeError('Invalid trial')
if case not in ['simple', 'representative'] or expected not in ['baseline', 'expected']:
raise RuntimeError('Invalid fixture or expectation')
if not re.fullmatch(r'[a-z0-9-]+', step):
raise RuntimeError('Invalid step')
TRIAL = BASE / trial
launch = json.loads((TRIAL / 'launch.json').read_text(encoding='utf-8'))
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def inventory(folder):
return {p.relative_to(folder).as_posix(): {'sha256': sha(p), 'bytes': p.stat().st_size}
for p in sorted(folder.rglob('*')) if p.is_file()}
def now():
return datetime.now(timezone.utc).isoformat()
manifest_path = BASE / 'fixture-manifest.json'
if sha(manifest_path) != 'a25651305b23da985eb6d8c637a687a0c4261b5a8c0d8ef84dda95a51fbed931':
raise RuntimeError('Authored fixture manifest changed')
manifest = json.loads(manifest_path.read_text(encoding='utf-8'))
for label, record in manifest['cases'].items():
for variant, key in [('baseline', 'original_files'), ('expected', 'expected_files')]:
if inventory(BASE / label / variant) != record[key]:
raise RuntimeError('Authored expectation changed')
oracle = ROOT / '.local/staged-source-oracle-20260911/staged-source-authoring-contract.exe'
dll = BASE / 'runtime/libunwind.dll'
if sha(oracle) != manifest['oracle_sha256'] or sha(dll) != manifest['dll_sha256']:
raise RuntimeError('Oracle or DLL changed')
if sha(Path(launch['executable'])) != launch['binary']['sha256']:
raise RuntimeError('Native executable changed')
destination = TRIAL / ('verification-' + case + '-' + step)
destination.mkdir()
actual = BASE / case / 'work'
before = inventory(actual)
expectation = manifest['cases'][case]['original_files' if expected == 'baseline' else 'expected_files']
system = os.environ['SystemRoot']
env = {'SystemRoot': system, 'SystemDrive': os.environ['SystemDrive'], 'WINDIR': system,
'PATH': str(dll.parent) + ';' + system + '\\System32;' + system, 'RUST_BACKTRACE': '0'}
command = [str(oracle), 'same', str(BASE / case / expected / 'project.arcadia'), str(actual / 'project.arcadia')]
started, timer = now(), time.perf_counter()
failure = None
code = None
with (destination / 'stdout.log').open('xb') as out, (destination / 'stderr.log').open('xb') as err:
try:
result = subprocess.run(command, cwd=BASE, env=env, stdout=out, stderr=err, timeout=55)
code = result.returncode
except (subprocess.TimeoutExpired, OSError) as error:
failure = {'type': type(error).__name__, 'message': str(error)}
after = inventory(actual)
receipt = {'startedUtc': started, 'finishedUtc': now(), 'seconds': time.perf_counter() - timer,
'command': command, 'environment': env, 'exitCode': code, 'failure': failure,
'scope': 'Saved disk state only; does not inspect the live unsaved GUI model.',
'binarySha256': launch['binary']['sha256'], 'oracleSha256': sha(oracle), 'dllSha256': sha(dll),
'expectedVariant': expected, 'actualFiles': after, 'physicalBytesMatch': before == expectation,
'actualUnchangedByOracle': before == after,
'stdoutSha256': sha(destination / 'stdout.log'), 'stderrSha256': sha(destination / 'stderr.log')}
receipt['passed'] = code == 0 and failure is None and before == expectation and after == before
(destination / 'result.json').write_text(json.dumps(receipt, indent=2) + '\n', encoding='utf-8')
print(json.dumps({'passed': receipt['passed'], 'receipt': str(destination / 'result.json'),
'stdout': (destination / 'stdout.log').read_text(encoding='utf-8', errors='replace')}), flush=True)
if not receipt['passed']:
raise SystemExit(1)