"""Authorized STEP3 release capsule; same diagnostic/profile proofs, no resident access."""
import importlib.util
import json
from pathlib import Path
import shutil
import sys
sys.dont_write_bytecode = True
OUT = Path(__file__).resolve().parent
ROOT = OUT.parents[3]
BASE = ROOT/'.spt/preserved/302/todlando-step2-field/run.py'
spec = importlib.util.spec_from_file_location('step3_field_base', BASE)
f = importlib.util.module_from_spec(spec)
spec.loader.exec_module(f)
g = f.g
f.OUT = f.r.OUT = g.OUT = OUT
g.TREE = ROOT/'.worktrees/302-portmapper-off-field'
g.TARGET = g.TREE/'target'
f.r.HEAD = '0611a05864760946c184a3263aae968058c5ed2e'
f.r.BRANCH = 'diag/302-portmapper-off-field'
FIX = '712c987f086f0f3564d139e8ff3775ce0bbd8ec2'
HELPER = OUT/'pool-controller.exe'
PHASES = ('pool-claim','build-jobs8','fixtures','guards','meet-diag','starve','attach','stack-unit','checks','version','pool-release')

class Step3FieldPhase(f.FieldPhase):
    def __init__(self, name):
        super().__init__(name)
        if name == 'build-jobs8':
            self.name = 'build'

    def prepare(self):
        if g.os.name != 'nt':
            raise RuntimeError('Windows only')
        self.receipt['source_before'] = self.source('before')
        source = self.receipt['source_before']
        self.receipt['branch'] = self.metadata('branch','--show-current').decode().strip()
        if source['head'] != f.r.HEAD or source['diff_sha256'] != f.r.EMPTY_SHA256 or self.receipt['branch'] != f.r.BRANCH:
            raise RuntimeError('exact clean assembly commit required')
        if self.metadata('ls-files','--others','--exclude-standard').strip():
            raise RuntimeError('untracked assembly source refused')
        g.reparse_guard(g.TARGET)
        foreign = self.env.get('CARGO_TARGET_DIR')
        if foreign and (g.TREE/foreign).resolve() != g.TARGET.resolve():
            raise RuntimeError('foreign inherited target override')
        if self.name == 'pool-claim':
            if g.TARGET.exists() and next(g.TARGET.iterdir(),None) is not None:
                raise RuntimeError('authorized cold pool must be absent or empty')
        else:
            claim = json.loads((OUT/'pool-claim/receipt.json').read_bytes())
            if claim['status'] != 'passed' or claim['driver_exit'] != 0 or claim['source_before']['source_map_sha256'] != source['source_map_sha256'] or claim['source_before']['head'] != f.r.HEAD:
                raise RuntimeError('successful unchanged assembly pool claim required')
        base = Path(g.os.environ['LOCALAPPDATA'])/'Temp'
        g.reparse_guard(base)
        if g.inside(base.resolve(),ROOT):
            raise RuntimeError('private temp must be outside repository')
        private = Path(g.tempfile.mkdtemp(prefix='spt-302-step3-field-'+self.name+'-',dir=base))
        home,tmp = private/'home',private/'tmp'
        home.mkdir(); tmp.mkdir()
        overlay = dict(CARGO_TARGET_DIR=str(g.TARGET),CARGO_BUILD_JOBS='2',NEXTEST_PROFILE='ci-windows',SPT_HOME=str(home),TEMP=str(tmp),TMP=str(tmp),SPT_INSTALL_NO_FIREWALL='1',SPT_TEST_EPHEMERAL_ADVISORY_PORTS='1',**f.r.PROFILE_ENV)
        if self.name == 'build':
            overlay['CARGO_BUILD_JOBS'] = '8'
            self.receipt['build_jobs_authority'] = 'MFTKRX7V'
        if self.name == 'meet-diag':
            overlay['SPT_RC_HITCH_DIAG'] = '1'
        self.env.update(overlay)
        self.receipt.update(environment_allowlist=overlay,private_root=str(private),profile=f.r.PROFILE,
            authority='UF6PGKRW',cold_authority='F3UWX2LQ',pool_direction='VWR3JKIL',fix_commit=FIX,
            step3_driver_sha256=g.digest(Path(__file__)),predecessor_driver_sha256=g.digest(BASE),
            processes_before=g.census(),free_bytes_start=g.shutil.disk_usage(g.TREE).free,
            pool_controller=json.loads((OUT/'pool-controller-provenance.json').read_bytes()))
        if g.digest(HELPER)!=self.receipt['pool_controller']['sha256']:
            raise RuntimeError('pool controller identity changed')
        self.flush()

    def execute(self):
        if self.name == 'pool-claim':
            self.run('claim',[str(HELPER),'pool-claim','--pool',str(g.TARGET),'--label','todlando-302-step3-field'],timeout=120)
        elif self.name == 'pool-release':
            self.run('release',[str(HELPER),'pool-release','--pool',str(g.TARGET)],timeout=120)
        elif self.name == 'fixtures':
            before = {str(path):g.digest(path) for path in (g.TARGET/'release/spt.exe',g.TARGET/'release/spt.pdb')}
            self.run('fixture-build',['cargo','build','--release','--locked','-p','mock-adapter','--bin','mock-session'])
            after = {str(path):g.digest(path) for path in (g.TARGET/'release/spt.exe',g.TARGET/'release/spt.pdb')}
            self.receipt.update(spt_before_fixture=before,spt_after_fixture=after)
            if before != after:
                raise RuntimeError('fixture build changed the capsule application')
            fixture = g.TARGET/'release/mock-session.exe'
            self.receipt['fixture'] = dict(path=str(fixture),bytes=fixture.stat().st_size,sha256=g.digest(fixture))
            self.flush()
        else:
            super().execute()
            if self.name == 'build':
                subjects = OUT/'built-subjects'
                subjects.mkdir()
                for name in ('spt.exe','spt.pdb'):
                    shutil.copy2(g.TARGET/'release'/name,subjects/name)
                self.receipt['immutable_subjects'] = {name:dict(path=str(subjects/name),sha256=g.digest(subjects/name),bytes=(subjects/name).stat().st_size) for name in ('spt.exe','spt.pdb')}
                self.flush()
            if self.name == 'guards':
                wanted = ('spt-net','spt_net','net::endpoint::tests::all_bind_scopes_exchange_without_portmapper_activity')
                if wanted not in {tuple(row) for row in self.receipt['inventory_selected']}:
                    raise RuntimeError('all-scope mapper regression omitted from release guards')

f.r.Phase = Step3FieldPhase
if __name__ == '__main__':
    sys.exit(f.r.main())
