"""Private dimensionless PSD-policy screen on declared and native Schur inputs."""
from __future__ import annotations
import hashlib
import json
import subprocess
import types
from datetime import datetime, timezone
from pathlib import Path
import jsonschema
import numpy as np
from pydantic import BaseModel, ConfigDict
from calibrex.core import continuous_time_sliding_window_fit as sliding
from calibrex.core.validation import validate_file
from calibrex.evaluation import continuous_time_sliding_window as evaluation

ROOT=Path(__file__).resolve().parents[2]
OUT=Path(__file__).resolve().parent
SOURCE='8861ed65ebbcffb13a182ac4cd549db88ef763f2'


def sha(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()


def factor(information):
    matrix=np.asarray(information,dtype=float)
    if matrix.shape!=(6,6) or not np.isfinite(matrix).all():
        raise ValueError('finite 6x6 matrix required')
    norm=float(np.linalg.norm(matrix,ord=np.inf))
    if np.linalg.norm(matrix-matrix.T,ord=np.inf)>60*np.finfo(float).eps*norm:
        raise ValueError('asymmetric information')
    matrix=.5*(matrix+matrix.T)
    diagonal=np.diag(matrix)
    if np.any(diagonal<0):
        raise ValueError('negative diagonal: no implicit repair in this policy')
    active=diagonal>0
    if np.any(matrix[~active,:]!=0):
        raise ValueError('nonzero row with zero diagonal')
    if not np.any(active):
        return np.zeros((6,6)),0.0
    scale=np.sqrt(diagonal[active])
    normalized=matrix[np.ix_(active,active)]/np.outer(scale,scale)
    eigenvalues,vectors=np.linalg.eigh(normalized)
    tolerance=60*np.finfo(float).eps*float(np.max(np.abs(eigenvalues)))
    if eigenvalues.min() < -tolerance:
        raise ValueError('indefinite equilibrated information')
    local=np.diag(np.sqrt(np.maximum(eigenvalues,0)))@vectors.T
    result=np.zeros((6,6))
    result[np.ix_(active,active)]=local*scale[None,:]
    return result,float(eigenvalues.min())


class Row(BaseModel):
    model_config=ConfigDict(extra='forbid')
    name: str
    source: str
    declared_class: str
    information: list[list[float]]
    accepted: bool
    reason: str | None
    normalized_minimum_eigenvalue: float | None
    factor_gram_relative_error: float | None


class Record(BaseModel):
    model_config=ConfigDict(extra='forbid')
    scope: str
    rows: list[Row]
    native_policy_status: str
    provenance: dict[str,object]


assert subprocess.check_output(['git','rev-parse','HEAD'],cwd=ROOT,text=True).strip()==SOURCE
original={p.relative_to(ROOT).as_posix():sha(p) for p in (ROOT/'src/calibrex').rglob('*.py')}
origin={'created_at':datetime.now(timezone.utc).isoformat(),'source_commit':SOURCE,'generator':Path(__file__).name,
 'launcher_sha256':sha(Path(__file__)),'source_files_raw_sha256':original,
 'parent_scale_audit_sha256':sha(ROOT/'outputs/prior-scale-contract-audit-v1/result.json')}
protocol={'known_spent_seed':20260820,'input_source':'Native unmodified sliding-window evaluator; pass-through capture only',
 'policy':'Require nonnegative diagonal, exact zero rows for zero diagonal; symmetric relative tolerance; spectral PSD check after diagonal equilibration',
 'repairs':'No negative diagonal repair or positive nullspace floor; only tiny normalized negative eigensolver roundoff clipped',
 'additional_fixtures':['positive-diagonal-anisotropic-indefinite','roundoff-negative-diagonal','weak-psd'],
 'provenance':origin}
path=OUT/'protocol.json'; assert not path.exists(); path.write_bytes((json.dumps(protocol,indent=2)+'\n').encode())
inputs=[]
parent=json.loads((ROOT/'outputs/prior-scale-contract-audit-v1/result.json').read_text())
for row in parent['cases']:
 if row['policy']=='older_absolute_floor_policy':
  inputs.append((row['family']+'@'+str(row['global_scale']),'constructed',row['mathematical_class'],np.array(row['information'])))
positive=np.diag([1e12,1.,1.,1e-3,1e-3,1.]); positive[3,4]=positive[4,3]=1.1e-3
inputs.extend([('positive-diagonal-anisotropic-indefinite','constructed','indefinite',positive),
 ('roundoff-negative-diagonal','constructed','algebraically indefinite, roundoff sized',np.diag([1.,2.,3.,4.,0.,-1e-15])),
 ('weak-psd','constructed','PSD',np.diag([1e12,1e-3,1e-3,1e-16,0.,0.]))])
captured=[]


def capture_split(hessian,gradient,**kwargs):
    captured.append({'hessian':hessian.tolist(),'gradient':gradient.tolist(),
        'retained_knot_count':kwargs['retained_knot_count'],
        'start_knot_index':kwargs['start_knot_index']})
    return sliding.split_retained_information(hessian,gradient,**kwargs)


private_sliding=types.FunctionType(sliding.fit_sliding_window_trajectory.__code__,
 dict(vars(sliding),split_retained_information=capture_split),argdefs=sliding.fit_sliding_window_trajectory.__defaults__)
private_sliding.__kwdefaults__=sliding.fit_sliding_window_trajectory.__kwdefaults__
private_evaluation=types.FunctionType(evaluation.run_synthetic_sliding_window_recovery.__code__,
 dict(vars(evaluation),fit_sliding_window_trajectory=private_sliding),argdefs=evaluation.run_synthetic_sliding_window_recovery.__defaults__)
private_evaluation.__kwdefaults__=evaluation.run_synthetic_sliding_window_recovery.__kwdefaults__
artifact=private_evaluation(seed=20260820,command=['python','outputs/prior-equilibrated-policy-audit-v1/probe.py'])
artifact=artifact.model_copy(update={'provenance':artifact.provenance.model_copy(update={
 'generator':artifact.provenance.generator+'.PRIVATE_PRIOR_INPUT_CAPTURE','generator_version':'development-only'})})
artifact.save(OUT/'native-result.json')
assert validate_file(OUT/'native-result.json',kind='continuous-time-sliding-window').valid
assert captured
path=OUT/'captured-normal-inputs.json'; assert not path.exists(); path.write_bytes((json.dumps({'inputs':captured,'provenance':origin},indent=2)+'\n').encode())
for index,item in enumerate(captured):
 matrix=np.array(item['hessian'])
 for knot in range(item['retained_knot_count']):
  inputs.append((f'native-{index}-knot-{knot}','native Schur input','produced by native Schur; no validity assumption',matrix[6*knot:6*knot+6,6*knot:6*knot+6]))
rows=[]
for name,source,classification,matrix in inputs:
 reason,eigenvalue,error=None,None,None
 try:
  square_root,eigenvalue=factor(matrix)
  error=float(np.max(np.abs(square_root.T@square_root-.5*(matrix+matrix.T)))/max(np.max(np.abs(matrix)),np.finfo(float).tiny))
  accepted=True
 except ValueError as exception:
  accepted=False; reason=str(exception)
 rows.append(Row(name=name,source=source,declared_class=classification,information=matrix.tolist(),
  accepted=accepted,reason=reason,normalized_minimum_eigenvalue=eigenvalue,factor_gram_relative_error=error))
assert original=={p.relative_to(ROOT).as_posix():sha(p) for p in (ROOT/'src/calibrex').rglob('*.py')}
record=Record(scope='Private proposed input contract only; no source or calibration behavior change. Rejecting tiny negative diagonals is an explicit draft choice, not a complete backward-error repair policy. One spent native seed checks compatibility only. No speed, accuracy, universal stationarity or adoption claim.',rows=rows,native_policy_status=artifact.policy_status,
 provenance=dict(origin,native_artifact_sha256=sha(OUT/'native-result.json'),captured_inputs_sha256=sha(OUT/'captured-normal-inputs.json'),source_unchanged=True))
for name,data in [('result.json',record.model_dump()),('result.schema.json',Record.model_json_schema())]:
 path=OUT/name; assert not path.exists(); path.write_bytes((json.dumps(data,indent=2,allow_nan=False)+'\n').encode())
jsonschema.validate(record.model_dump(),Record.model_json_schema())
print(json.dumps({'cases':len(rows),'native_policy':artifact.policy_status,'accepted':sum(r.accepted for r in rows),
 'rejected':sum(not r.accepted for r in rows),'native_inputs':[{'name':r.name,'accepted':r.accepted,'reason':r.reason,'scaled_min_eigenvalue':r.normalized_minimum_eigenvalue} for r in rows if r.source=='native Schur input'],
 'valid_constructed_rejected':[r.name for r in rows if r.declared_class in ('SPD','PSD') and not r.accepted],
 'invalid_constructed_accepted':[r.name for r in rows if r.source=='constructed' and r.declared_class not in ('SPD','PSD') and r.accepted]}),flush=True)
