Files
MagnetismHeroes/.dryforge/002/execution-support/verify-model-integration.py
T
2026-10-10 01:27:54 +09:00

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))