from __future__ import annotations

import json
from pathlib import Path


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 — إعادة Gemini المصححة (البروتوكول 1.1)

هذا الدفتر ينفذ المعالجة العلمية الكاملة للحادثة السابقة:

- يحتفظ بسجل Gemini الأصلي ذي 14 محاولة كدليل تشخيصي مُبطَل، ولا يدمجه في النتائج التأكيدية.
- يدقق سجل OpenAI المضمّن وسجل Claude المحفوظ في Drive قبل اعتمادهما.
- يشغّل بوابة مطابقة حية على 12 حالة متنوعة.
- لا يبدأ تجربة Gemini الجديدة إلا إذا نجحت البوابة 12/12.
- يعيد Gemini وحده من الصفر: 40 حالة اصطناعية × 10 تكرارات = 400 تجربة.
- يحفظ نقاط الاستئناف في Google Drive ولا يطبع مفتاح API.

لا يستهدف أي منصة أو حساب أو جهاز حقيقي. جميع العمليات محصورة في صندوق
اصطناعي محلي مغلق دون خروج عام إلى الإنترنت، باستثناء استدعاء نموذج Gemini نفسه.

## ما يلزمك

1. فعّل سر `GEMINI_API_KEY` لهذا الدفتر.
2. اضغط **Run all**.
3. ارفع `PolicyFaultBench_v0.3.2_GEMINI_V1P1_FIXED.zip` عندما تظهر نافذة الرفع.
4. وافق على ربط Google Drive.

لا حاجة إلى مفتاح Claude في هذا الدفتر، ولن يعاد تشغيل Claude أو OpenAI.
"""
    ),
    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')
old_root = Path('/content/drive/MyDrive/PolicyFaultBench_Definitive_v1')
drive_root = Path('/content/drive/MyDrive/PolicyFaultBench_Definitive_v1_1')
drive_root.mkdir(parents=True, exist_ok=True)

uploaded = files.upload()
archives = [
    name for name in uploaded
    if name.endswith('.zip') and 'v0.3.2_GEMINI_V1P1_FIXED' in name
]
assert len(archives) == 1, (
    'ارفع حزمة PolicyFaultBench_v0.3.2_GEMINI_V1P1_FIXED.zip فقط'
)

work = Path('/content/pfb_v1p1_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,
    'version': '0.3.2',
    'new_drive_checkpoint': str(drive_root),
})
"""
    ),
    code(
        """
key = userdata.get('GEMINI_API_KEY')
assert key and len(key) >= 20, (
    'السر GEMINI_API_KEY غير متاح لهذا الدفتر؛ فعّل Notebook access ثم أعد الخلية'
)

env = os.environ.copy()
env['GEMINI_API_KEY'] = key
env['PFB_LIVE_ENABLED'] = 'true'
env['PFB_STUDY_ENABLED'] = 'true'
env['PYTHONPATH'] = str(root / 'src')

config_path = root / 'config' / 'experiment.json'
config = json.loads(config_path.read_text())
config['live_enabled'] = True
config['study_enabled'] = True
config['debug_only'] = False
config['models']['gemini'] = 'gemini-3.6-flash'
study = config['definitive_study']
study['experiment_id'] = 'pfb-definitive-v1p1'
study['protocol_version'] = '1.1'
study['seed'] = 20260724
study['repetitions'] = 10
study['planned_trials_per_provider'] = 400
study['provider_delay_seconds']['gemini'] = 15.5
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({
    'gates_ready': True,
    'gemini_key_present': True,
    'key_printed': False,
    'protocol_version': '1.1',
})
"""
    ),
    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 = (
    '57f6535f87a7ecf0025e8ae625bb7ae3ed3aad8c8ff801e92499b6bea6ee2374'
)
assert schedule['schedule_hash'] == expected_hash, 'تغير الجدول المجمد'
print('نجحت الاختبارات والتحقق وثبات جدول التجربة.')
"""
    ),
    markdown(
        """
## تدقيق النتائج السابقة

هذه الخطوة لا تستدعي أي نموذج ولا تكلف رصيدًا. وهي تمنع ضم أي سجل سابق إلى
الدراسة ما لم تكن سلامة أحداثه صحيحة وتمثل اقتراحاته العمليات المجمدة حرفيًا.
"""
    ),
    code(
        """
audit_script = root / 'scripts' / 'audit_proposal_conformance.py'

def audit_log(label, event_log, output, require_conformant):
    assert event_log.is_file(), f'السجل المطلوب غير موجود: {event_log}'
    command = [
        sys.executable, str(audit_script),
        '--root', str(root),
        '--event-log', str(event_log),
        '--output', str(output),
    ]
    if require_conformant:
        command.append('--require-conformant')
    result = subprocess.run(command, env=env, text=True, capture_output=True)
    print(result.stdout)
    if result.stderr:
        print(result.stderr)
    if result.returncode:
        raise RuntimeError(f'فشل تدقيق {label}')
    report = json.loads(output.read_text())
    assert report['integrity_ok'] is True
    return report

openai_log = root / 'study' / 'final' / 'pfb-definitive-v1-openai.jsonl'
openai_audit = audit_log(
    'OpenAI',
    openai_log,
    drive_root / 'openai_v1_conformance_audit.json',
    True,
)
assert openai_audit['audited_proposal_count'] == 400

anthropic_log = old_root / 'pfb-definitive-v1-anthropic.jsonl'
anthropic_audit = audit_log(
    'Claude',
    anthropic_log,
    drive_root / 'anthropic_v1_conformance_audit.json',
    True,
)
assert anthropic_audit['audited_proposal_count'] == 400

old_gemini_log = old_root / 'pfb-definitive-v1-gemini.jsonl'
invalidated_dir = drive_root / 'invalidated_original_gemini_v1'
invalidated_dir.mkdir(parents=True, exist_ok=True)
invalidated_copy = invalidated_dir / old_gemini_log.name
shutil.copy2(old_gemini_log, invalidated_copy)
gemini_invalidated_audit = audit_log(
    'Gemini الأصلي',
    invalidated_copy,
    invalidated_dir / 'gemini_invalidated_v1_audit.json',
    False,
)
assert gemini_invalidated_audit['audited_proposal_count'] == 14
assert gemini_invalidated_audit['proposal_conformance_failed'] == 14

shutil.copy2(
    root / 'config' / 'study_protocol_amendment_1.json',
    drive_root / 'study_protocol_amendment_1.json',
)
shutil.copy2(
    root / 'reports' / 'GEMINI_STOP_AUDIT_AND_AMENDMENT.md',
    drive_root / 'GEMINI_STOP_AUDIT_AND_AMENDMENT.md',
)
print({
    'openai_retained': '400/400 conformant',
    'anthropic_retained': '400/400 conformant',
    'original_gemini': '14/14 invalidated and preserved separately',
})
"""
    ),
    markdown(
        """
## بوابة Gemini قبل التجربة

تستهلك هذه الخطوة 12 استدعاء فقط. إذا أخفق أي استدعاء في المطابقة، يتوقف
الدفتر ولا تبدأ التجربة ذات 400 حالة.
"""
    ),
    code(
        """
gate_path = drive_root / 'gemini_conformance_gate_v1p1.json'
gate_command = [
    sys.executable,
    str(root / 'scripts' / 'gemini_conformance_gate.py'),
    '--root', str(root),
    '--output', str(gate_path),
    '--delay-seconds', '15.5',
]
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)
if gate_result.returncode:
    raise RuntimeError(
        'لم تنجح بوابة Gemini؛ لم تبدأ التجربة الأساسية ولم تُخلط النتائج'
    )
gate = json.loads(gate_path.read_text())
assert gate['gate_passed'] is True and gate['passed'] == 12
print('نجحت بوابة Gemini: 12/12. ستبدأ الآن التجربة الأساسية الجديدة.')
"""
    ),
    code(
        """
def run_gemini(max_cycles=20):
    status_path = drive_root / 'study_status_gemini.json'
    for cycle in range(1, max_cycles + 1):
        command = [
            sys.executable, '-m', 'policyfaultbench.cli',
            '--root', str(root), 'study-run', 'gemini',
            '--output-dir', str(drive_root),
            '--delay-seconds', '15.5',
        ]
        result = subprocess.run(
            command, env=env, text=True, capture_output=True
        )
        print(result.stdout)
        if result.stderr:
            print(result.stderr[-1500:])
        assert status_path.is_file(), 'لم يُنشأ ملف حالة Gemini'
        status = json.loads(status_path.read_text())
        print({
            'cycle': cycle,
            'complete': status['primary_complete'],
            'remaining': status['remaining'],
            'conformance_failures':
                status['model_conformance_failure_count'],
            'containment_failures':
                status['invocation_containment_failures'],
            '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('توقف عابر؛ انتظار 90 ثانية ثم الاستئناف من آخر نقطة...')
            time.sleep(90)
            continue
        raise RuntimeError(f'توقف غير عابر في Gemini: {reason}')
    raise RuntimeError('تجاوز عدد دورات الاستئناف التلقائي المسموح')

gemini_status = run_gemini()
assert gemini_status['remaining'] == 0
print({
    'gemini_primary_complete': gemini_status['primary_complete'],
    'successful_records': gemini_status['successful_run_records'],
    'terminal_conformance_records':
        gemini_status['terminal_conformance_records'],
})
"""
    ),
    code(
        """
new_gemini_log = (
    drive_root / 'pfb-definitive-v1p1-gemini.jsonl'
)
gemini_final_audit = audit_log(
    'Gemini 1.1',
    new_gemini_log,
    drive_root / 'gemini_v1p1_final_audit.json',
    True,
)
assert gemini_final_audit['audited_proposal_count'] == 400
assert gemini_final_audit['containment_failure_count'] == 0

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

result_manifest = {
    'schema_version': '1.0',
    'study': 'pfb-definitive-v1p1',
    'protocol_version': '1.1',
    'disposition': {
        'openai_v1': 'retained after 400/400 exact-conformance audit',
        'anthropic_v1': 'retained after 400/400 exact-conformance audit',
        'gemini_v1_first_14': (
            'preserved but excluded as configuration-diagnostic evidence'
        ),
        'gemini_v1p1': 'fresh 400-trial replacement ledger',
    },
    'gemini_status': gemini_status,
    'files': {},
}
for path in sorted(drive_root.rglob('*')):
    if path.is_file():
        relative = str(path.relative_to(drive_root))
        result_manifest['files'][relative] = {
            'bytes': path.stat().st_size,
            'sha256': hashlib.sha256(path.read_bytes()).hexdigest(),
        }
(drive_root / 'RESULT_MANIFEST_V1P1.json').write_text(
    json.dumps(result_manifest, indent=2, sort_keys=True) + '\\n'
)

archive_base = '/content/PolicyFaultBench_GEMINI_V1P1_results'
archive_path = shutil.make_archive(archive_base, 'zip', drive_root)
print({
    'result_archive': archive_path,
    'live_gates_relocked': True,
    'send_this_file': Path(archive_path).name,
})
files.download(archive_path)
"""
    ),
    markdown(
        """
## بعد اكتمال التشغيل

سينزل الملف:

`PolicyFaultBench_GEMINI_V1P1_results.zip`

أرسله هنا كاملًا. إذا انقطع Colab، افتح الدفتر نفسه واضغط **Run all**؛ سيعيد
بوابة المطابقة القصيرة ثم يقرأ نقطة الاستئناف من Drive ويتابع التجارب المتبقية
دون إعادة التجارب المكتملة.
"""
    ),
]

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

output = (
    Path(__file__).resolve().parents[2]
    / "PolicyFaultBench_Colab_GEMINI_V1P1_FIXED.ipynb"
)
output.write_text(
    json.dumps(notebook, indent=2, ensure_ascii=False) + "\n",
    encoding="utf-8",
)
print(output)
