"""Rig a same-character GLB on configured DGXA and retain source provenance. Only explicit --generate starts inference. Reuses a byte-verified cached result. --backend remote requires a verified remote receipt and refuses local fallback. The approved low-poly mesh is preserved and receives these weights later. """ import argparse import hashlib import json from pathlib import Path import shutil import sys import time import uuid REPO=Path(__file__).resolve().parents[1] def digest(path): return hashlib.sha256(path.read_bytes()).hexdigest() def main(): parser=argparse.ArgumentParser(description=__doc__) parser.add_argument('--source',type=Path,required=True) parser.add_argument('--out',type=Path,required=True) parser.add_argument('--generate',action='store_true') parser.add_argument('--backend',choices=('auto','remote'),default='auto',help='remote refuses an implicit local fallback') args=parser.parse_args() source=args.source.resolve();out=args.out.resolve() if not source.is_relative_to(REPO) or not out.is_relative_to(REPO): parser.error('Character source and output must stay in the repository') if source.suffix.lower()!='.glb' or not source.is_file(): parser.error('Expected this character\'s source GLB') source_hash=digest(source);receipt=out/'rig_request.json';target=out/'rigged.glb' if receipt.is_file() and target.is_file(): record=json.loads(receipt.read_text(encoding='utf-8')) if record['source_sha256']==source_hash and record['rig_sha256']==digest(target) and (args.backend=='auto' or record.get('backend')=='remote'): print('PASS cached same-source rig',target);return if not args.generate: parser.error('No verified cache. --generate explicitly requests DGXA rigging') sys.path.insert(0,str(REPO/'Tools')) from dgx3d_animal_pipeline import _ensure_llm3d _ensure_llm3d() from backend.tokenrig_runner import run_tokenrig,_run_remote stage=out/'generations'/uuid.uuid4().hex;stage.mkdir(parents=True) runner=_run_remote if args.backend=='remote' else run_tokenrig result=Path(runner(source,stage,stage/'tokenrig.log',skeleton_template='original')) if not result.is_file() or result.stat().st_size<100: raise RuntimeError('Missing TokenRig result') # The local SkinTokens fallback produced a degenerate single-chain skeleton (Hornlet 2026-10-21); only accept DGXA runs. if 'tokenrig remote failed' in (stage/'tokenrig.log').read_text(encoding='utf-8',errors='replace'): raise RuntimeError('TokenRig fell back to local SkinTokens; reconnect DGXA (Tools/dgx_ensure_ready.py) and retry') log=(stage/'tokenrig.log').read_text(encoding='utf-8',errors='replace') backend='local' if 'tokenrig local:' in log else 'remote' record=dict(status='generated',backend=backend,source=str(source.relative_to(REPO)),source_sha256=source_hash, rig_sha256=digest(result),template='original',stage=str(stage.relative_to(REPO)), generated_at_utc=time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime())) shutil.copy2(result,target) temporary=receipt.with_suffix('.pending.json') temporary.write_text(json.dumps(record,indent=2),encoding='utf-8');temporary.replace(receipt) print('PASS same-source rig',target,flush=True) if __name__=='__main__':main()