60 lines
3.7 KiB
Python
60 lines
3.7 KiB
Python
import hashlib
|
|
import json
|
|
import pathlib
|
|
import subprocess
|
|
from datetime import datetime, timezone
|
|
|
|
root = pathlib.Path(__file__).resolve().parents[1]
|
|
state_path = root / '.dryforge/execution.json'
|
|
state = json.loads(state_path.read_text(encoding='utf-8'))
|
|
def git(*args):
|
|
return subprocess.check_output(['git', *args], cwd=root, text=True).strip()
|
|
def digest(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
assert git('branch', '--show-current') == state['feature_branch']
|
|
assert git('rev-parse', state['protected_base']) == state['initial_commit']
|
|
for name, expected in state['protected_product_hashes'].items():
|
|
assert digest(root / name) == expected, name
|
|
diff = git('diff', '--name-status', state['initial_commit'] + '...HEAD').splitlines()
|
|
assert len(diff) == 32, len(diff)
|
|
for line in diff:
|
|
status, name = line.split('\t', 1)
|
|
assert status == 'A', line
|
|
assert name.startswith(('SourceAssets/Models/Heroes/', 'SourceAssets/Models/Meadow/',
|
|
'Assets/MagnetismHeroes/UnityRuntime/Presentation/Models/Heroes/',
|
|
'Assets/MagnetismHeroes/UnityRuntime/Presentation/Models/Meadow/')) or name in (
|
|
'tools/models/build_hero.py', 'tools/models/build_meadow.py'), name
|
|
checked = 0
|
|
for group in ('Heroes', 'Meadow'):
|
|
provenance = json.loads((root / f'SourceAssets/Models/{group}/provenance.json').read_text())
|
|
for record in provenance['files']:
|
|
path = root / record['path']
|
|
assert path.stat().st_size == record['bytes'], record['path']
|
|
assert digest(path) == record['sha256'], record['path']
|
|
checked += 1
|
|
subprocess.run(['git', 'diff', '--check', state['initial_commit'] + '...HEAD'], cwd=root, check=True)
|
|
assert git('status', '--porcelain') == '', 'Unexpected tracked/untracked change'
|
|
evidence = {
|
|
'status': 'PASS', 'scope': 'Model candidates only; user approval pending',
|
|
'checkedUtc': datetime.now(timezone.utc).isoformat(), 'featureCommit': git('rev-parse', 'HEAD'),
|
|
'protectedBaseCommit': state['initial_commit'], 'protectedProductFilesUnchanged': len(state['protected_product_hashes']),
|
|
'candidateFilesAdded': len(diff), 'provenanceResourceHashesChecked': checked,
|
|
'commands': [
|
|
{'command': 'Blender --background --python-exit-code 1 --python tools/models/build_hero.py -- --verify-only',
|
|
'exitCode': 0, 'log': 'Heroes/integrated-verify.log',
|
|
'assertion': 'ASSERTIONS_OK and REOPEN_AND_FBX_REIMPORT_OK evaluated'},
|
|
{'command': 'Blender --background --python-exit-code 1 --python tools/models/build_meadow.py -- --verify-only --review-dir artifacts/verification/VisualUpgrade/ModelReview/Meadow',
|
|
'exitCode': 0, 'log': 'Meadow/integrated-verify.log',
|
|
'assertion': 'MEADOW_VERIFY_PASS evaluated; 21 assets and 23 resources'},
|
|
{'command': 'python .dryforge/verify-model-integration.py', 'exitCode': 0,
|
|
'assertion': '533 protected product hashes, 32 additions, candidate provenance hashes, clean tree and protected dev checked'}],
|
|
'userApproval': 'PENDING', 'unityGameplayAndroid': 'NOT_RUN; awaits explicit model approval'
|
|
}
|
|
review = root / 'artifacts/verification/VisualUpgrade/ModelReview'
|
|
(review / 'integration-verification.json').write_text(json.dumps(evidence, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
state['tasks'].update(T1='completed_model_candidate', T2='completed_model_candidate', T3='awaiting_explicit_user_model_approval')
|
|
state['model_integration'] = evidence
|
|
state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
print(json.dumps({k: evidence[k] for k in ('status', 'featureCommit', 'protectedProductFilesUnchanged', 'candidateFilesAdded', 'provenanceResourceHashesChecked', 'userApproval')}, ensure_ascii=False))
|