Verify Windows contextual authoring and preserve postboot evidence

This commit is contained in:
2026-09-11 09:04:30 -07:00
parent ca53f574e5
commit b2c3e54001
178 changed files with 13108 additions and 53 deletions
@@ -0,0 +1,57 @@
import datetime
import hashlib
import json
from pathlib import Path
import sys
import uuid
repo = Path(__file__).resolve().parents[2]
trial = repo / '.local/native-qa/contextual-source-20260911-v2/lifeline'
base = repo / 'harness/fixtures/staged-source-authoring/base'
mode = sys.argv[1]
assert mode in ('before-stop', 'after-restore')
expected = {p.name: p.read_text(encoding='utf-8') for p in base.glob('*.arcadia')}
assert len(expected) == 2
matches = []
for p in (trial / 'profile/local/ArcadiaStudio/recovery').glob('*.json'):
raw = p.read_bytes()
j = json.loads(raw)
draft = (j.get('behavior') or {}).get('draft') or {}
source = (draft.get('source') or {}).get('editing') or {}
if (draft.get('name') == ' Retain parent 雨 ' and source.get('name') == ' Retain source Δ '
and (mode == 'before-stop' or j.get('origin') is None)):
matches.append((p, raw, j, draft, source))
assert len(matches) == 1, f'Expected one completed matching recovery record, got {len(matches)}'
p, raw, j, draft, source = matches[0]
assert j['accepted'] == {'entry': 'project.arcadia', 'files': expected}
assert j['workspace']['entry'] == 'project.arcadia'
assert j['workspace']['applied'] is True
assert j['workspace']['files'] == {k: [v, v] for k, v in expected.items()}
assert set(j['workspace']['reachable']) == set(expected)
assert source['kind'] == 'Activity' and source['layer'] == 'Oa' and source['parent'] is None
assert source['document'] == 'd1510000-0000-4000-8000-000000000001'
assert source['scope'] == {'Lifeline': {'owner': 'd1510000-0000-4000-8000-000000000002', 'viewpoint': 'OperationalActivity'}}
assert draft['tool'] == 'Lifeline' and draft['source']['staged'] is None
assert draft['owner'] == 'd1510000-0000-4000-8000-000000000002'
ids = [draft['invocation'], source['id'], source['token'], *source['identities']]
assert len(ids) == 4 and len(set(ids)) == 4
assert all(uuid.UUID(i).version == 4 for i in ids)
if mode == 'before-stop':
assert {p.name: p.read_text(encoding='utf-8') for p in (trial / 'work').glob('*.arcadia')} == expected
else:
before = json.loads((trial / 'recovery-evidence/before-stop.json').read_bytes())
assert j['accepted'] == before['accepted']
assert j['behavior'] == before['behavior'], 'Authored pending behavior/identities changed on restore'
assert j['origin'] is None, 'Recovered copy must not retain writable source origin'
out = trial / 'recovery-evidence'
out.mkdir(exist_ok=True)
with (out / f'{mode}.json').open('xb') as f:
f.write(raw)
result = {'atUtc': datetime.datetime.now(datetime.timezone.utc).isoformat(), 'mode': mode,
'source': str(p), 'sha256': hashlib.sha256(raw).hexdigest(), 'reservedIds': ids,
'acceptedBaselineFiles': len(expected), 'rawParentAndChildNames': 'exact',
'kindAndRoot': 'Activity/Oa/root', 'result': 'PASS'}
with (out / f'{mode}-result.json').open('x', encoding='utf-8') as f:
json.dump(result, f, ensure_ascii=False, indent=2)
f.write('\n')
print(json.dumps(result, ensure_ascii=False))
@@ -0,0 +1,58 @@
"""Preserve a real GUI Save checkpoint and run the unchanged independent oracle."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import shutil
import subprocess
parser = argparse.ArgumentParser()
parser.add_argument('trial', choices=['lifeline', 'machine'])
parser.add_argument('checkpoint', choices=['first', 'undo', 'redo', 'reopen', 'cancelled'])
args = parser.parse_args()
root = Path(__file__).resolve().parents[2]
stage = root/'.local/native-qa/contextual-source-20260911-v2'/args.trial
prior = root/'.local/native-qa/contextual-source-20260911-v1'
base = root/'harness/fixtures/staged-source-authoring/base'
oracle = root/'.local/staged-source-oracle-20260911/staged-source-authoring-contract.exe'
runtime = prior/'bin'
digest = lambda p: hashlib.sha256(p.read_bytes()).hexdigest().upper()
assert digest(oracle) == '967D9BA3C6FB3A7EFB410833903EC94556CA2D48A67D5072C8BB160F40A00F9C'
assert digest(runtime/'libunwind.dll') == 'F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4'
destination = stage/('checkpoint-'+args.checkpoint)
assert not destination.exists(), 'Refuse to overwrite a checkpoint'
source = stage/('cancelled-copy' if args.checkpoint == 'cancelled' else 'work')
assert source.is_dir() and (source/'project.arcadia').is_file()
assert all(not p.is_symlink() for p in source.rglob('*'))
shutil.copytree(source, destination)
entry = lambda p:str(p/'project.arcadia')
first = stage/'checkpoint-first'
commands = []
if args.checkpoint == 'cancelled':
assert args.trial == 'lifeline'
commands.append(['same', entry(base), entry(destination)])
elif args.checkpoint == 'undo':
commands.append(['same', entry(base if args.trial == 'lifeline' else prior/'checkpoint-chain'), entry(destination), entry(first)])
elif args.trial == 'lifeline':
commands.append(['check', 'lifeline', entry(base), entry(destination), entry(first)])
else:
commands.append(['check', 'machine', entry(base), entry(destination), entry(prior/'checkpoint-lifeline'), entry(prior/'checkpoint-chain'), entry(first)])
if args.checkpoint == 'reopen':
commands.append(['same', entry(stage/'checkpoint-redo'), entry(destination)])
env = dict(os.environ)
system_root = next(v for k,v in env.items() if k.upper() == 'SYSTEMROOT')
env['PATH'] = str(runtime)+';'+system_root+'\\System32;'+system_root
results = []
for index, command in enumerate(commands, 1):
log = stage/(args.checkpoint+'-check-'+str(index)+'.log')
assert not log.exists()
result = subprocess.run([str(oracle), *command],env=env,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
log.write_bytes(result.stdout)
results.append({'args':command, 'exitCode':result.returncode, 'log':log.name})
record = {'scope':'Independent complete model, raw source, original identity and physical-file contract', 'trial':args.trial,'checkpoint':args.checkpoint,'oracleSha256':digest(oracle),'checks':results,'files':[{'path':p.relative_to(destination).as_posix(),'bytes':p.stat().st_size,'sha256':digest(p)} for p in sorted(destination.rglob('*')) if p.is_file()]}
(stage/(args.checkpoint+'-result.json')).write_text(json.dumps(record,indent=2)+'\n',encoding='utf8')
for result in results:
print((stage/result['log']).read_text(encoding='utf8'), end='')
assert all(result['exitCode'] == 0 for result in results), 'Oracle failure preserved'
print(json.dumps({'state':'pass','trial':args.trial,'checkpoint':args.checkpoint,'files':len(record['files']),'checks':len(results)}))
@@ -0,0 +1,43 @@
param(
[Parameter(Mandatory)][ValidateSet('lifeline','machine')][string]$Trial,
[Parameter(Mandatory)][ValidatePattern('^[a-z0-9-]+$')][string]$Run
)
$ErrorActionPreference = 'Stop'
$trialRepo = 'C:\Users\User\Documents\Git\ARCADIA-Studio'
$evidence = Join-Path $trialRepo '.local/contextual-source-layout-20260911'
$verified = Join-Path $evidence 'gui-verified'
$nativeTrial = Join-Path $trialRepo ".local/native-qa/contextual-source-20260911-v2/$Trial"
$launchDir = Join-Path $nativeTrial "runs/$Run"
if (Test-Path -LiteralPath $launchDir) { throw 'Refuse to overwrite a native run' }
if (Get-Process -Name arcadia-studio -ErrorAction SilentlyContinue) { throw 'Studio already running' }
$preflight = Get-Content -LiteralPath (Join-Path (Split-Path $nativeTrial) 'preflight.json') -Raw | ConvertFrom-Json
if (@($preflight.checks | Where-Object exitCode -ne 0).Count) { throw 'Native input oracle did not pass' }
$manifest = Get-Content -LiteralPath (Join-Path $verified 'manifest.json') -Raw | ConvertFrom-Json
foreach ($artifact in $manifest.artifacts) {
if ((Get-FileHash -LiteralPath (Join-Path $verified $artifact.file) -Algorithm SHA256).Hash -ne $artifact.sha256) { throw 'Verified artifact changed' }
}
foreach ($gate in 'focused4','clippy1','fmt1','gui1') {
$status = Get-Content -LiteralPath (Join-Path $evidence ($gate + '-status.json')) -Raw | ConvertFrom-Json
if ($status.exitCode -ne 0) { throw "Unpassed build gate $gate" }
}
New-Item -ItemType Directory -Path $launchDir | Out-Null
foreach ($part in 'local','roaming') {
$profilePart = Join-Path $nativeTrial "profile/$part"
if (-not (Test-Path -LiteralPath $profilePart)) { New-Item -ItemType Directory -Path $profilePart | Out-Null }
}
$savedPath = $env:PATH
$savedAppData = $env:APPDATA
$savedLocalAppData = $env:LOCALAPPDATA
try {
$env:PATH = "$verified;$env:SystemRoot\System32;$env:SystemRoot"
$env:APPDATA = "$nativeTrial/profile/roaming"
$env:LOCALAPPDATA = "$nativeTrial/profile/local"
$binary = Join-Path $verified 'arcadia-studio.exe'
$child = Start-Process -FilePath $binary -WorkingDirectory $verified -WindowStyle Hidden -PassThru -RedirectStandardOutput "$launchDir/stdout.log" -RedirectStandardError "$launchDir/stderr.log"
[ordered]@{pid=$child.Id;startedUtc=[DateTimeOffset]::UtcNow.ToString('o');trial=$Trial;run=$Run;executable=$binary;artifacts=$manifest.artifacts;profile="$nativeTrial/profile";workingModel="$nativeTrial/work/project.arcadia";scope='Matching corrected source-layout GUI; native assertions remain separate'} | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath "$launchDir/launch.json"
$child | Select-Object Id,ProcessName
} finally {
$env:PATH = $savedPath
$env:APPDATA = $savedAppData
$env:LOCALAPPDATA = $savedLocalAppData
}
@@ -0,0 +1,49 @@
import hashlib
import json
import os
from pathlib import Path
import shutil
import subprocess
import sys
root = Path(__file__).resolve().parents[2]
prior = root/'.local/native-qa/contextual-source-20260911-v1'
stage = root/'.local/native-qa/contextual-source-20260911-v2'
base = root/'harness/fixtures/staged-source-authoring/base'
oracle = root/'.local/staged-source-oracle-20260911/staged-source-authoring-contract.exe'
digest = lambda p: hashlib.sha256(p.read_bytes()).hexdigest().upper()
resume = sys.argv[1:] == ['--resume-preflight']
assert not stage.exists() or resume, 'Refuse to overwrite native stage'
assert digest(base/'project.arcadia') == 'AA844950EC4FB86F262A257E1FC370A26557EA7978D8A4CAB78265037660234C'
assert digest(base/'notes.arcadia') == 'AD9DE02963C20D1F43856455A797DEB05CA674659E45F2C4B96B52783024F8BD'
assert digest(oracle) == '967D9BA3C6FB3A7EFB410833903EC94556CA2D48A67D5072C8BB160F40A00F9C'
assert digest(prior/'bin/libunwind.dll') == 'F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4'
def inventory(directory):
return {p.relative_to(directory).as_posix():digest(p) for p in directory.rglob('*') if p.is_file()}
assert inventory(prior/'checkpoint-chain-redo') == inventory(prior/'checkpoint-chain')
assert len(inventory(prior/'checkpoint-chain-redo')) == 4
if resume:
assert not (stage/'preflight.json').exists()
assert inventory(base) == inventory(stage/'lifeline/work')
assert inventory(prior/'checkpoint-chain-redo') == inventory(stage/'machine/work')
else:
shutil.copytree(base, stage/'lifeline/work')
shutil.copytree(prior/'checkpoint-chain-redo', stage/'machine/work')
env = dict(os.environ)
system_root = next(v for k,v in env.items() if k.upper() == 'SYSTEMROOT')
env['PATH'] = str(prior/'bin') + ';' + system_root + '\\System32;' + system_root
entry = lambda p:str(p/'project.arcadia')
checks = [
('self-check', ['self-check', entry(base)]),
('lifeline-initial', ['check', 'baseline', entry(base), entry(stage/'lifeline/work')]),
('machine-initial', ['check', 'chain', entry(base), entry(stage/'machine/work'), entry(prior/'checkpoint-lifeline'), entry(prior/'checkpoint-chain')]),
]
results = []
for name,args in checks:
assert not (stage/(name+'.log')).exists(), 'Refuse to overwrite earlier checker log'
p = subprocess.run([str(oracle),*args],env=env,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
(stage/(name+'.log')).write_bytes(p.stdout)
results.append({'check':name, 'exitCode':p.returncode, 'args':args})
assert p.returncode == 0, p.stdout
(stage/'preflight.json').write_text(json.dumps({'scope':'Frozen inputs only; no new GUI or native interaction', 'oracle':str(oracle), 'oracleSha256':digest(oracle), 'checks':results, 'lifelineInput':inventory(stage/'lifeline/work'), 'machineInput':inventory(stage/'machine/work')},indent=2)+'\n',encoding='utf8')
print(json.dumps({'state':'prepared', 'checks':len(results), 'path':str(stage)}))