from __future__ import annotations

import json
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
OUTPUT = ROOT.parent / "PolicyFaultBench_Colab_ANTHROPIC_CONFIRMATORY_V2.ipynb"


def markdown(source: str) -> dict:
    return {
        "cell_type": "markdown",
        "metadata": {},
        "source": [line + "\n" for line in source.strip().splitlines()],
    }


def code(source: str) -> dict:
    return {
        "cell_type": "code",
        "execution_count": None,
        "metadata": {},
        "outputs": [],
        "source": [line + "\n" for line in source.strip().splitlines()],
    }


cells = [
    markdown(
        """
# PolicyFaultBench — Anthropic Confirmatory Replication v2

هذا الدفتر ينفذ ذراع Anthropic فقط وفق بروتوكول جُمّد قبل التشغيل:

- 12 حالة مطابقة كاملة قبل بدء الدراسة.
- 400 معرّف تجربة جديد، من دون إعادة استخدام نتائج Anthropic السابقة.
- بوابة المطابقة تعمل قبل تقييم السياسة.
- أوراكل الانتقال والاحتواء المصححان يعملان أثناء التشغيل.
- سقف تكلفة Anthropic هو 4 دولارات.
- المفتاح يبقى داخل Colab Secrets ولا يُطبع.

معيار القبول ثابت: 400/400 نجاحًا تأكيديًا صارمًا وصفر فشل احتواء. ستُحفظ
النتيجة وتُبلّغ سواء اجتاز المزود المعيار أم لم يجتزه.

## قبل Run all

1. فعّل وصول هذا الدفتر إلى السر `ANTHROPIC_API_KEY`.
2. شغّل جميع الخلايا.
3. ارفع الملف `PolicyFaultBench_v0.5.0_ANTHROPIC_CONFIRMATORY_V2.zip`.
4. وافق على ربط Google Drive عند الطلب.
"""
    ),
    code(
        """
from google.colab import drive, files, userdata
from pathlib import Path
import hashlib, json, os, shutil, subprocess, sys, time, zipfile

drive.mount('/content/drive')
drive_root = Path(
    '/content/drive/MyDrive/PolicyFaultBench_Anthropic_Confirmatory_v2'
)
drive_root.mkdir(parents=True, exist_ok=True)

uploaded = files.upload()
archives = [
    name for name in uploaded
    if name == 'PolicyFaultBench_v0.5.0_ANTHROPIC_CONFIRMATORY_V2.zip'
]
assert len(archives) == 1, (
    'ارفع PolicyFaultBench_v0.5.0_ANTHROPIC_CONFIRMATORY_V2.zip فقط'
)

work = Path('/content/pfb_anthropic_v2_work')
if work.exists():
    shutil.rmtree(work)
work.mkdir(parents=True)
with zipfile.ZipFile(archives[0]) as archive:
    for item in archive.infolist():
        target = (work / item.filename).resolve()
        assert work.resolve() in target.parents or target == work.resolve(), (
            'مسار ZIP غير آمن'
        )
    archive.extractall(work)

root = work / 'PolicyFaultBench'
assert (root / 'pyproject.toml').is_file(), 'بنية الحزمة غير صحيحة'
print({'project_loaded': True, 'checkpoint': str(drive_root)})
"""
    ),
    code(
        """
value = userdata.get('ANTHROPIC_API_KEY')
assert value and len(value) >= 20, (
    'السر ANTHROPIC_API_KEY غير متاح؛ فعّل Notebook access ثم أعد الخلية'
)
env = os.environ.copy()
env['ANTHROPIC_API_KEY'] = value
env['PFB_LIVE_ENABLED'] = 'true'
env['PFB_STUDY_ENABLED'] = 'true'
env['PYTHONPATH'] = os.pathsep.join((str(root), str(root / 'src')))

protocol_path = root / 'config' / 'anthropic_confirmatory_protocol_v2.json'
protocol = json.loads(protocol_path.read_text())
assert protocol['status'] == 'frozen_before_live_execution'
assert protocol['provider'] == 'anthropic'
assert protocol['model'] == 'claude-sonnet-5'
assert protocol['design']['planned_trial_count'] == 400
assert protocol['budget']['hard_cap_usd'] == 4.0

config_path = root / 'config' / 'experiment.json'
config = json.loads(config_path.read_text())
config['experiment_id'] = 'pfb-anthropic-confirmatory-v2'
config['live_enabled'] = True
config['study_enabled'] = True
config['debug_only'] = True
config['models']['anthropic'] = protocol['model']
config['hard_budget_usd']['anthropic'] = 4.0
config['hard_budget_usd']['total'] = 4.0
config['pricing_usd_per_million_tokens']['anthropic'] = {
    'input': 2.0,
    'output': 10.0,
}
study = config['definitive_study']
study['experiment_id'] = 'pfb-anthropic-confirmatory-v2'
study['protocol_version'] = '2.0'
study['seed'] = 20260724
study['repetitions'] = 10
study['scenario_scope'] = 'all_40'
study['planned_trials_per_provider'] = 400
study['planned_trials_total'] = 400
study['provider_delay_seconds']['anthropic'] = 0.0
config_path.write_text(json.dumps(config, indent=2) + '\\n')

manifest = json.loads((root / 'manifests' / 'owned_assets.json').read_text())
assert manifest['synthetic_only'] is True
assert manifest['public_egress'] is False
print({
    'anthropic_key_present': True,
    'anthropic_key_printed': False,
    'protocol_id': protocol['protocol_id'],
    'model': protocol['model'],
    'hard_cap_usd': 4.0,
})
"""
    ),
    code(
        """
frozen_files = [
    'config/anthropic_confirmatory_protocol_v2.json',
    'config/study_protocol.json',
    'config/study_protocol_amendment_4.json',
    'config/model_registry.json',
    'scenarios/core_40.json',
    'policies/reference_policy.json',
    'manifests/owned_assets.json',
    'src/policyfaultbench/providers/base.py',
    'src/policyfaultbench/providers/anthropic.py',
    'src/policyfaultbench/conformance.py',
    'src/policyfaultbench/oracles.py',
    'src/policyfaultbench/runner.py',
    'src/policyfaultbench/study.py',
    'scripts/provider_conformance_gate.py',
    'scripts/analyze_anthropic_confirmatory_v2.py',
]
hashes = {
    relative: hashlib.sha256((root / relative).read_bytes()).hexdigest()
    for relative in frozen_files
}
freeze = {
    'schema_version': '1.0',
    'protocol_id': protocol['protocol_id'],
    'model': protocol['model'],
    'planned_trials': 400,
    'expected_schedule_hash':
        protocol['design']['expected_schedule_hash'],
    'frozen_file_sha256': hashes,
}
freeze_path = drive_root / 'anthropic_confirmatory_v2_freeze.json'
if freeze_path.is_file():
    prior = json.loads(freeze_path.read_text())
    assert prior == freeze, (
        'الحزمة الحالية لا تطابق الحزمة التي بدأ بها هذا التشغيل'
    )
else:
    freeze_path.write_text(
        json.dumps(freeze, indent=2, sort_keys=True) + '\\n'
    )
print({'freeze_verified': True, 'frozen_file_count': len(hashes)})
"""
    ),
    code(
        """
checks = [
    [sys.executable, '-m', 'unittest', 'discover',
     '-s', str(root / 'tests'), '-q'],
    [sys.executable, '-m', 'policyfaultbench.cli',
     '--root', str(root), 'validate'],
    [sys.executable, '-m', 'policyfaultbench.cli',
     '--root', str(root), 'study-plan', '--output-dir', str(drive_root)],
]
for command in checks:
    result = subprocess.run(command, env=env, text=True, capture_output=True)
    print(result.stdout)
    if result.returncode:
        print(result.stderr)
        raise RuntimeError('فشل التحقق المحلي قبل أي استدعاء مدفوع')

schedule = json.loads((drive_root / 'study_schedule.json').read_text())
expected_hash = protocol['design']['expected_schedule_hash']
assert schedule['schedule_hash'] == expected_hash, 'تغير الجدول المجمد'
assert schedule['trial_count'] == 400
print('نجحت الاختبارات والتحقق وثبات جدول الدراسة.')
"""
    ),
    markdown(
        """
## بوابة المطابقة المسبقة

لا تبدأ التجارب الـ400 إلا إذا طابق Claude الكائن الكامل في الحالات الاثنتي
عشرة. فشل البوابة نتيجة يجب الاحتفاظ بها، وليس مبررًا لتعديل المطالبة أو
المخطط.
"""
    ),
    code(
        """
gate_path = drive_root / 'anthropic_conformance_gate_v2.json'
gate_command = [
    sys.executable,
    str(root / 'scripts' / 'provider_conformance_gate.py'),
    'anthropic',
    '--root', str(root),
    '--output', str(gate_path),
    '--delay-seconds', '0',
]
gate_result = subprocess.run(
    gate_command, env=env, text=True, capture_output=True
)
print(gate_result.stdout)
if gate_result.stderr:
    print(gate_result.stderr)
gate = json.loads(gate_path.read_text())
assert gate['gate_passed'] is True and gate['passed'] == 12, (
    'فشلت بوابة 12/12؛ لن تبدأ التجربة التأكيدية'
)
print({'anthropic_preflight_gate': '12/12'})
"""
    ),
    code(
        """
def run_confirmatory(max_cycles=20):
    status_path = drive_root / 'study_status_anthropic.json'
    for cycle in range(1, max_cycles + 1):
        command = [
            sys.executable, '-m', 'policyfaultbench.cli',
            '--root', str(root), 'study-run', 'anthropic',
            '--output-dir', str(drive_root),
            '--delay-seconds', '0',
        ]
        result = subprocess.run(
            command, env=env, text=True, capture_output=True
        )
        print(result.stdout)
        if result.stderr:
            print(result.stderr[-2000:])
        assert status_path.is_file(), 'لم يُنشأ ملف حالة Anthropic'
        status = json.loads(status_path.read_text())
        print({
            'cycle': cycle,
            'primary_complete': status['primary_complete'],
            'successful_run_records': status['successful_run_records'],
            'terminal_conformance_records':
                status['terminal_conformance_records'],
            'remaining': status['remaining'],
            'containment_failures':
                status['invocation_containment_failures'],
            'cost_usd': status['completed_cost_usd'],
            'stop_reason': status['stop_reason'],
        })
        if status['invocation_containment_failures']:
            raise RuntimeError('توقف آمن بسبب فشل احتواء')
        if status['remaining'] == 0:
            return status
        reason = status.get('stop_reason', '')
        if reason.startswith('transient_abort:'):
            print('توقف عابر؛ انتظار 45 ثانية ثم الاستئناف...')
            time.sleep(45)
            continue
        raise RuntimeError(f'توقف غير عابر: {reason}')
    raise RuntimeError('تجاوز عدد دورات الاستئناف المحدد')

status = run_confirmatory()
assert status['primary_complete'] == 400
print({'anthropic_scheduled_trials_resolved': 400})
"""
    ),
    code(
        """
ledger = drive_root / 'pfb-anthropic-confirmatory-v2-anthropic.jsonl'
analysis_path = drive_root / 'anthropic_confirmatory_v2_analysis.json'
analysis_command = [
    sys.executable,
    str(root / 'scripts' / 'analyze_anthropic_confirmatory_v2.py'),
    '--root', str(root),
    '--ledger', str(ledger),
    '--schedule', str(drive_root / 'study_schedule.json'),
    '--output', str(analysis_path),
]
analysis_result = subprocess.run(
    analysis_command, env=env, text=True, capture_output=True
)
print(analysis_result.stdout)
if analysis_result.returncode:
    print(analysis_result.stderr)
    raise RuntimeError('فشل تحليل التشغيل التأكيدي')
analysis = json.loads(analysis_path.read_text())

audit_path = drive_root / 'anthropic_confirmatory_v2_audit.json'
audit_command = [
    sys.executable,
    str(root / 'scripts' / 'audit_proposal_conformance.py'),
    '--root', str(root),
    '--event-log', str(ledger),
    '--output', str(audit_path),
]
audit_result = subprocess.run(
    audit_command, env=env, text=True, capture_output=True
)
print(audit_result.stdout)
if audit_result.returncode:
    print(audit_result.stderr)
    raise RuntimeError('فشل تدقيق سلامة السجل')
audit = json.loads(audit_path.read_text())
assert audit['integrity_ok'] is True
assert analysis['scheduled_trials'] == 400
print({
    'strict_successes': analysis['strict_successes'],
    'strict_failures': analysis['strict_failures'],
    'containment_failures': analysis['containment_failures'],
    'provider_acceptance_rule_passed':
        analysis['provider_acceptance_rule_passed'],
})
"""
    ),
    code(
        """
config = json.loads(config_path.read_text())
config['live_enabled'] = False
config['study_enabled'] = False
config_path.write_text(json.dumps(config, indent=2) + '\\n')

evidence_files = [
    drive_root / 'anthropic_confirmatory_v2_freeze.json',
    drive_root / 'study_schedule.json',
    gate_path,
    ledger,
    drive_root / 'study_status_anthropic.json',
    analysis_path,
    audit_path,
]
evidence_manifest = {
    'schema_version': '1.0',
    'protocol_id': protocol['protocol_id'],
    'files': {
        path.name: hashlib.sha256(path.read_bytes()).hexdigest()
        for path in evidence_files
    },
    'acceptance_rule_passed':
        analysis['provider_acceptance_rule_passed'],
}
manifest_path = drive_root / 'EVIDENCE_MANIFEST.json'
manifest_path.write_text(
    json.dumps(evidence_manifest, indent=2, sort_keys=True) + '\\n'
)

archive = drive_root / 'PolicyFaultBench_Anthropic_Confirmatory_v2_results.zip'
with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as bundle:
    for path in evidence_files + [manifest_path]:
        bundle.write(path, arcname=path.name)
    bundle.write(
        protocol_path,
        arcname='anthropic_confirmatory_protocol_v2.json',
    )
    bundle.write(
        root / 'scripts' / 'analyze_anthropic_confirmatory_v2.py',
        arcname='analyze_anthropic_confirmatory_v2.py',
    )

print({
    'complete': True,
    'results_archive': str(archive),
    'acceptance_rule_passed':
        analysis['provider_acceptance_rule_passed'],
    'api_key_in_archive': False,
})
"""
    ),
]


notebook = {
    "cells": cells,
    "metadata": {
        "colab": {"provenance": []},
        "kernelspec": {
            "display_name": "Python 3",
            "language": "python",
            "name": "python3",
        },
        "language_info": {"name": "python"},
    },
    "nbformat": 4,
    "nbformat_minor": 5,
}

OUTPUT.write_text(
    json.dumps(notebook, indent=2, ensure_ascii=False) + "\n",
    encoding="utf-8",
)
print(OUTPUT)
