{"repo": "billyrdavis1985-bot/mtca-research", "files": {"mtca-1/notebooks/MTCA1_Stage5_Pilot.ipynb": {"e6f61fbacc8b7f1cdf5d2e6ad164a8b49b43fc33": {"t": 1785745503.862822, "n": 29311, "h": "8da500320cc8cbe5", "c": "{\r\n \"cells\": [\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"# MTCA-1 Stage 5: Pilot Execution\\n\",\r\n \"\\n\",\r\n \"**Study identifier:** MTCA-1\\n\",\r\n \"**Stage:** 5 of 10 — Pilot validation\\n\",\r\n \"**Inputs:** Stage 3 design (frozen at SHA `6380e711bbaed3af`)\\n\",\r\n \"**Outputs:** 40 council responses (1 unit × 8 frames × 5 models) + validation report\\n\",\r\n \"\\n\",\r\n \"## Purpose\\n\",\r\n \"\\n\",\r\n \"Validate end-to-end wiring before committing to Stage 6's full 2,000-call execution. The pilot exercises every API client, every frame template, every storage path, and every parser on a small subset where failures are cheap.\\n\",\r\n \"\\n\",\r\n \"## Pilot scope\\n\",\r\n \"\\n\",\r\n \"- **One unit** from the Stage 3 sample (configurable; defaults to a C8 synthetic unit for clear signal)\\n\",\r\n \"- **All 8 frames** applied to that unit\\n\",\r\n \"- **All 5 council models** queried per frame\\n\",\r\n \"- **Total: 40 API calls**, ~$0.40-$1 in cost, 10-20 minutes wall-clock\\n\",\r\n \"\\n\",\r\n \"## Success criteria\\n\",\r\n \"\\n\",\r\n \"Pilot passes if:\\n\",\r\n \"1. All 5 API clients authenticate successfully\\n\",\r\n \"2. All 40 calls return responses (no timeouts, no auth failures)\\n\",\r\n \"3. ≥90% of responses parse as valid JSON with the 5 expected keys\\n\",\r\n \"4. Responses show meaningful variation across frames (sanity check, not statistical)\\n\",\r\n \"5. Storage structure handles all response shapes cleanly\\n\",\r\n \"\\n\",\r\n \"If any criterion fails, fix before Stage 6.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 1: Environment and Stage 3 design load\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"import sys\\n\",\r\n \"IN_COLAB = 'google.colab' in sys.modules\\n\",\r\n \"\\n\",\r\n \"if IN_COLAB:\\n\",\r\n \" from google.colab import drive, userdata\\n\",\r\n \" try:\\n\",\r\n \" drive.mount('/content/drive')\\n\",\r\n \" except Exception:\\n\",\r\n \" pass\\n\",\r\n \" PROJECT_ROOT = '/content/drive/MyDrive/MTCA-1'\\n\",\r\n \"else:\\n\",\r\n \" PROJECT_ROOT = './MTCA-1'\\n\",\r\n \" userdata = None\\n\",\r\n \"\\n\",\r\n \"import os\\n\",\r\n \"import json\\n\",\r\n \"import re\\n\",\r\n \"import time\\n\",\r\n \"import hashlib\\n\",\r\n \"from datetime import datetime, timezone\\n\",\r\n \"from dataclasses import dataclass, field, asdict\\n\",\r\n \"\\n\",\r\n \"# Output dirs\\n\",\r\n \"for subdir in ['stage5', 'stage5/responses', 'stage5/logs']:\\n\",\r\n \" os.makedirs(f'{PROJECT_ROOT}/{subdir}', exist_ok=True)\\n\",\r\n \"\\n\",\r\n \"print(f'Project root: {PROJECT_ROOT}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Load Stage 3 design + execution plan\\n\",\r\n \"stage3_dir = f'{PROJECT_ROOT}/stage3'\\n\",\r\n \"design_files = [f for f in os.listdir(stage3_dir) if f.startswith('stage3_design_')]\\n\",\r\n \"if not design_files:\\n\",\r\n \" raise FileNotFoundError('No Stage 3 design found. Run Stage 3 first.')\\n\",\r\n \"\\n\",\r\n \"design_path = f'{stage3_dir}/{design_files[0]}'\\n\",\r\n \"with open(design_path, 'r', encoding='utf-8') as f:\\n\",\r\n \" stage3_design = json.load(f)\\n\",\r\n \"\\n\",\r\n \"exec_files = [f for f in os.listdir(stage3_dir) if f.startswith('execution_plan_')]\\n\",\r\n \"exec_path = f'{stage3_dir}/{exec_files[0]}'\\n\",\r\n \"with open(exec_path, 'r', encoding='utf-8') as f:\\n\",\r\n \" execution_plan_doc = json.load(f)\\n\",\r\n \"\\n\",\r\n \"EXECUTION_PLAN = execution_plan_doc['calls']\\n\",\r\n \"DESIGN_SHA = stage3_design['design_sha256']\\n\",\r\n \"\\n\",\r\n \"print(f'Loaded Stage 3 design')\\n\",\r\n \"print(f'Design SHA256: {DESIGN_SHA}')\\n\",\r\n \"print(f'Total planned calls: {len(EXECUTION_PLAN)}')\\n\",\r\n \"print(f'Frames: {len(stage3_design[\\\"frames\\\"])}')\\n\",\r\n \"print(f'Council models: {[m[\\\"model_id\\\"] for m in stage3_design[\\\"council_models\\\"]]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 2: Install and import provider SDKs\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Install all required SDKs (no-op if already installed)\\n\",\r\n \"!pip install -q anthropic openai google-generativeai\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"from anthropic import Anthropic\\n\",\r\n \"from openai import OpenAI\\n\",\r\n \"import google.generativeai as genai\\n\",\r\n \"\\n\",\r\n \"# Pull API keys from Colab Secrets (or env vars locally)\\n\",\r\n \"def get_key(name):\\n\",\r\n \" if IN_COLAB and userdata is not None:\\n\",\r\n \" try:\\n\",\r\n \" return userdata.get(name)\\n\",\r\n \" except Exception:\\n\",\r\n \" pass\\n\",\r\n \" return os.environ.get(name)\\n\",\r\n \"\\n\",\r\n \"API_KEYS = {\\n\",\r\n \" 'anthropic': get_key('ANTHROPIC_API_KEY'),\\n\",\r\n \" 'openai': get_key('OPENAI_API_KEY'),\\n\",\r\n \" 'google': get_key('GOOGLE_API_KEY'),\\n\",\r\n \" 'xai': get_key('XAI_API_KEY'),\\n\",\r\n \" 'deepseek': get_key('DEEPSEEK_API_KEY'),\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"# Verify all keys present\\n\",\r\n \"missing = [k for k, v in API_KEYS.items() if not v]\\n\",\r\n \"if missing:\\n\",\r\n \" raise RuntimeError(f'Missing API keys: {missing}. Add to Colab Secrets.')\\n\",\r\n \"\\n\",\r\n \"print('All five API keys loaded.')\\n\",\r\n \"for provider in API_KEYS:\\n\",\r\n \" key = API_KEYS[provider]\\n\",\r\n \" print(f' {provider}: {key[:8]}... ({len(key)} chars)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Initialize clients\\n\",\r\n \"anthropic_client = Anthropic(api_key=API_KEYS['anthropic'])\\n\",\r\n \"openai_client = OpenAI(api_key=API_KEYS['openai'])\\n\",\r\n \"xai_client = OpenAI(api_key=API_KEYS['xai'], base_url='https://api.x.ai/v1')\\n\",\r\n \"deepseek_client = OpenAI(api_key=API_KEYS['deepseek'], base_url='https://api.deepseek.com')\\n\",\r\n \"\\n\",\r\n \"genai.configure(api_key=API_KEYS['google'])\\n\",\r\n \"\\n\",\r\n \"print('All five API clients initialized.')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 3: Response data structure\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"@dataclass\\n\",\r\n \"class CouncilResponse:\\n\",\r\n \" \\\"\\\"\\\"A single response from one model on one (unit, frame) pair.\\\"\\\"\\\"\\n\",\r\n \" # Provenance from the execution plan\\n\",\r\n \" call_id: str\\n\",\r\n \" unit_id: str\\n\",\r\n \" text_id: str\\n\",\r\n \" frame_id: str\\n\",\r\n \" frame_version: str\\n\",\r\n \" prompt_sha256: str\\n\",\r\n \" model_id: str\\n\",\r\n \" provider: str\\n\",\r\n \" api_model: str\\n\",\r\n \" \\n\",\r\n \" # Execution metadata\\n\",\r\n \" timestamp: str\\n\",\r\n \" wall_clock_seconds: float\\n\",\r\n \" \\n\",\r\n \" # Response\\n\",\r\n \" raw_response: str # exactly what the model returned\\n\",\r\n \" parsed_json: dict = field(default_factory=dict) # parsed if successful\\n\",\r\n \" parse_succeeded: bool = False\\n\",\r\n \" parse_error: str = ''\\n\",\r\n \" \\n\",\r\n \" # Token usage (for cost tracking)\\n\",\r\n \" input_tokens: int = 0\\n\",\r\n \" output_tokens: int = 0\\n\",\r\n \" \\n\",\r\n \" # Error tracking\\n\",\r\n \" error: str = ''\\n\",\r\n \" retry_count: int = 0\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def extract_json_from_response(raw: str) -> tuple:\\n\",\r\n \" \\\"\\\"\\\"Extract and parse JSON from a model response.\\n\",\r\n \" \\n\",\r\n \" Handles markdown code fences, leading/trailing whitespace, and common variations.\\n\",\r\n \" Returns (parsed_dict, success_bool, error_msg).\\n\",\r\n \" \\\"\\\"\\\"\\n\",\r\n \" cleaned = raw.strip()\\n\",\r\n \" \\n\",\r\n \" # Strip markdown code fences if present\\n\",\r\n \" if cleaned.startswith('```'):\\n\",\r\n \" cleaned = re.sub(r'^```(?:json)?\\\\s*', '', cleaned)\\n\",\r\n \" cleaned = re.sub(r'\\\\s*```$', '', cleaned)\\n\",\r\n \" \\n\",\r\n \" # Some models add a preamble - try to find the JSON block\\n\",\r\n \" json_start = cleaned.find('{')\\n\",\r\n \" json_end = cleaned.rfind('}')\\n\",\r\n \" \\n\",\r\n \" if json_start == -1 or json_end == -1:\\n\",\r\n \" return {}, False, 'No JSON object found in response'\\n\",\r\n \" \\n\",\r\n \" json_candidate = cleaned[json_start:json_end + 1]\\n\",\r\n \" \\n\",\r\n \" try:\\n\",\r\n \" parsed = json.loads(json_candidate)\\n\",\r\n \" # Validate expected keys present\\n\",\r\n \" expected_keys = {'communicative_function', 'implicit_claims',\\n\",\r\n \" 'coherence_assessment', 'conditions_for_usefulness',\\n\",\r\n \" 'conditions_for_misleading'}\\n\",\r\n \" found_keys = set(parsed.keys())\\n\",\r\n \" missing = expected_keys - found_keys\\n\",\r\n \" if missing:\\n\",\r\n \" return parsed, False, f'Missing keys: {missing}'\\n\",\r\n \" return parsed, True, ''\\n\",\r\n \" except json.JSONDecodeError as e:\\n\",\r\n \" return {}, False, f'JSONDecodeError: {str(e)[:100]}'\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"print('Response data structure defined.')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 4: Per-provider call dispatchers\\n\",\r\n \"\\n\",\r\n \"Each provider has its own SDK and quirks. Wrapping each into a uniform interface that returns `(raw_text, input_tokens, output_tokens, error_str)`.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"MAX_OUTPUT_TOKENS = 800 # generous for the 5-field JSON response\\n\",\r\n \"REQUEST_TIMEOUT = 60 # seconds\\n\",\r\n \"\\n\",\r\n \"def call_anthropic(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" \\\"\\\"\\\"Returns (raw_text, input_tokens, output_tokens, error_str).\\\"\\\"\\\"\\n\",\r\n \" try:\\n\",\r\n \" resp = anthropic_client.messages.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.content[0].text,\\n\",\r\n \" resp.usage.input_tokens,\\n\",\r\n \" resp.usage.output_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'Anthropic error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_openai(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = openai_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'OpenAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_xai(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = xai_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'xAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_deepseek(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = deepseek_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'DeepSeek error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_google(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" model = genai.GenerativeModel(api_model)\\n\",\r\n \" resp = model.generate_content(\\n\",\r\n \" prompt,\\n\",\r\n \" generation_config={'max_output_tokens': MAX_OUTPUT_TOKENS},\\n\",\r\n \" request_options={'timeout': REQUEST_TIMEOUT}\\n\",\r\n \" )\\n\",\r\n \" # Token counts via usage_metadata when available\\n\",\r\n \" in_tok = getattr(resp.usage_metadata, 'prompt_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\r\n \" out_tok = getattr(resp.usage_metadata, 'candidates_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\r\n \" return (resp.text, in_tok, out_tok, '')\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'Google error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"PROVIDER_DISPATCH = {\\n\",\r\n \" 'anthropic': call_anthropic,\\n\",\r\n \" 'openai': call_openai,\\n\",\r\n \" 'xai': call_xai,\\n\",\r\n \" 'deepseek': call_deepseek,\\n\",\r\n \" 'google': call_google,\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"print('Provider dispatchers defined for:', list(PROVIDER_DISPATCH.keys()))\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 5: Select pilot unit and filter execution plan\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Choose pilot unit. Default: first C8 unit (synthetic CBT, clear signal).\\n\",\r\n \"# Override by setting PILOT_UNIT_ID to any unit_id from the sample.\\n\",\r\n \"PILOT_UNIT_ID = None # set to a specific unit_id to override default\\n\",\r\n \"\\n\",\r\n \"if PILOT_UNIT_ID is None:\\n\",\r\n \" # Pick first C8 unit\\n\",\r\n \" c8_calls = [c for c in EXECUTION_PLAN if c['text_id'] == 'C8']\\n\",\r\n \" PILOT_UNIT_ID = c8_calls[0]['unit_id']\\n\",\r\n \"\\n\",\r\n \"pilot_calls = [c for c in EXECUTION_PLAN if c['unit_id'] == PILOT_UNIT_ID]\\n\",\r\n \"pilot_unit_text = pilot_calls[0]['unit_text']\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot unit: {PILOT_UNIT_ID}')\\n\",\r\n \"print(f'Pilot text: {pilot_unit_text}')\\n\",\r\n \"print(f'Pilot calls: {len(pilot_calls)} (expected 40: 1 unit × 8 frames × 5 models)')\\n\",\r\n \"\\n\",\r\n \"# Breakdown\\n\",\r\n \"from collections import Counter\\n\",\r\n \"by_frame = Counter(c['frame_id'] for c in pilot_calls)\\n\",\r\n \"by_model = Counter(c['model_id'] for c in pilot_calls)\\n\",\r\n \"print(f'\\\\nBy frame: {dict(by_frame)}')\\n\",\r\n \"print(f'By model: {dict(by_model)}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 6: Execute pilot calls\\n\",\r\n \"\\n\",\r\n \"Runs all 40 calls sequentially with brief pacing between requests. Stores each response immediately so a mid-execution failure doesn't lose completed work.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"PACING_SECONDS = 0.5 # brief pause between calls to avoid rate limits\\n\",\r\n \"\\n\",\r\n \"pilot_responses = []\\n\",\r\n \"pilot_start = time.time()\\n\",\r\n \"\\n\",\r\n \"for i, call in enumerate(pilot_calls, 1):\\n\",\r\n \" print(f'[{i:>2}/{len(pilot_calls)}] {call[\\\"frame_id\\\"]:24} | {call[\\\"model_id\\\"]:24} ... ', end='', flush=True)\\n\",\r\n \" \\n\",\r\n \" dispatcher = PROVIDER_DISPATCH[call['provider']]\\n\",\r\n \" call_start = time.time()\\n\",\r\n \" raw, in_tok, out_tok, error = dispatcher(call['api_model'], call['rendered_prompt'])\\n\",\r\n \" wall_clock = time.time() - call_start\\n\",\r\n \" \\n\",\r\n \" # Parse the response\\n\",\r\n \" parsed, parse_ok, parse_err = extract_json_from_response(raw) if raw else ({}, False, 'no response')\\n\",\r\n \" \\n\",\r\n \" response = CouncilResponse(\\n\",\r\n \" call_id=call['call_id'],\\n\",\r\n \" unit_id=call['unit_id'],\\n\",\r\n \" text_id=call['text_id'],\\n\",\r\n \" frame_id=call['frame_id'],\\n\",\r\n \" frame_version=call['frame_version'],\\n\",\r\n \" prompt_sha256=call['prompt_sha256'],\\n\",\r\n \" model_id=call['model_id'],\\n\",\r\n \" provider=call['provider'],\\n\",\r\n \" api_model=call['api_model'],\\n\",\r\n \" timestamp=datetime.now(timezone.utc).isoformat(),\\n\",\r\n \" wall_clock_seconds=wall_clock,\\n\",\r\n \" raw_response=raw,\\n\",\r\n \" parsed_json=parsed,\\n\",\r\n \" parse_succeeded=parse_ok,\\n\",\r\n \" parse_error=parse_err,\\n\",\r\n \" input_tokens=in_tok,\\n\",\r\n \" output_tokens=out_tok,\\n\",\r\n \" error=error,\\n\",\r\n \" retry_count=0\\n\",\r\n \" )\\n\",\r\n \" pilot_responses.append(response)\\n\",\r\n \" \\n\",\r\n \" # Print status\\n\",\r\n \" if error:\\n\",\r\n \" print(f'ERROR ({wall_clock:.1f}s)')\\n\",\r\n \" elif not parse_ok:\\n\",\r\n \" print(f'PARSE-FAIL ({wall_clock:.1f}s)')\\n\",\r\n \" else:\\n\",\r\n \" print(f'OK ({wall_clock:.1f}s, {in_tok}+{out_tok} tok)')\\n\",\r\n \" \\n\",\r\n \" # Save immediately so we don't lose progress on crash\\n\",\r\n \" with open(f'{PROJECT_ROOT}/stage5/responses/{call[\\\"call_id\\\"]}.json', 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(asdict(response), f, indent=2, ensure_ascii=False)\\n\",\r\n \" \\n\",\r\n \" time.sleep(PACING_SECONDS)\\n\",\r\n \"\\n\",\r\n \"pilot_duration = time.time() - pilot_start\\n\",\r\n \"print(f'\\\\nPilot complete in {pilot_duration:.1f}s ({pilot_duration/60:.1f} min)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 7: Pilot validation report\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Compute pass/fail against each success criterion\\n\",\r\n \"total = len(pilot_responses)\\n\",\r\n \"errors = [r for r in pilot_responses if r.error]\\n\",\r\n \"no_response = [r for r in pilot_responses if not r.raw_response and not r.error]\\n\",\r\n \"parse_failures = [r for r in pilot_responses if r.raw_response and not r.parse_succeeded]\\n\",\r\n \"successes = [r for r in pilot_responses if r.parse_succeeded]\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nPilot Validation Report')\\n\",\r\n \"print('=' * 60)\\n\",\r\n \"print(f'Total calls: {total}')\\n\",\r\n \"print(f'Successes (clean JSON parse): {len(successes)} ({100*len(successes)/total:.1f}%)')\\n\",\r\n \"print(f'Parse failures: {len(parse_failures)} ({100*len(parse_failures)/total:.1f}%)')\\n\",\r\n \"print(f'API errors: {len(errors)}')\\n\",\r\n \"print(f'No response: {len(no_response)}')\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nSuccess Criteria:')\\n\",\r\n \"print(f' 1. All API clients authenticate: ', end='')\\n\",\r\n \"providers_with_responses = set(r.provider for r in pilot_responses if r.raw_response)\\n\",\r\n \"providers_expected = set(r.provider for r in pilot_responses)\\n\",\r\n \"if providers_with_responses == providers_expected:\\n\",\r\n \" print('PASS')\\n\",\r\n \"else:\\n\",\r\n \" missing_providers = providers_expected - providers_with_responses\\n\",\r\n \" print(f'FAIL (missing: {missing_providers})')\\n\",\r\n \"\\n\",\r\n \"print(f' 2. All 40 calls return responses: ', end='')\\n\",\r\n \"if len(no_response) + len(errors) == 0:\\n\",\r\n \" print('PASS')\\n\",\r\n \"else:\\n\",\r\n \" print(f'FAIL ({len(errors) + len(no_response)} failed)')\\n\",\r\n \"\\n\",\r\n \"print(f' 3. ≥90% parse cleanly: ', end='')\\n\",\r\n \"parse_rate = len(successes) / total\\n\",\r\n \"if parse_rate >= 0.9:\\n\",\r\n \" print(f'PASS ({parse_rate*100:.1f}%)')\\n\",\r\n \"else:\\n\",\r\n \" print(f'FAIL ({parse_rate*100:.1f}%)')\\n\",\r\n \"\\n\",\r\n \"print(f' 4. Frame variation visible: (manual inspection below)')\\n\",\r\n \"print(f' 5. Storage handles all shapes: PASS (all responses written to disk)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Show errors and parse failures in detail (for debugging)\\n\",\r\n \"if errors:\\n\",\r\n \" print('\\\\n--- API ERRORS ---')\\n\",\r\n \" for r in errors:\\n\",\r\n \" print(f'\\\\n[{r.call_id}]')\\n\",\r\n \" print(f' Provider: {r.provider} | Model: {r.api_model}')\\n\",\r\n \" print(f' Error: {r.error}')\\n\",\r\n \"\\n\",\r\n \"if parse_failures:\\n\",\r\n \" print('\\\\n--- PARSE FAILURES ---')\\n\",\r\n \" for r in parse_failures[:5]: # show up to 5\\n\",\r\n \" print(f'\\\\n[{r.call_id}]')\\n\",\r\n \" print(f' Parse error: {r.parse_error}')\\n\",\r\n \" print(f' Raw response preview: {r.raw_response[:300]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Visual sanity check: how does the same model respond across frames?\\n\",\r\n \"# Pick one model and show all 8 frame responses\\n\",\r\n \"SANITY_MODEL = 'claude_sonnet_4_6'\\n\",\r\n \"model_responses = [r for r in pilot_responses if r.model_id == SANITY_MODEL]\\n\",\r\n \"model_responses.sort(key=lambda r: r.frame_id)\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nSanity check: {SANITY_MODEL} across all 8 frames')\\n\",\r\n \"print('=' * 70)\\n\",\r\n \"for r in model_responses:\\n\",\r\n \" print(f'\\\\n--- {r.frame_id} ---')\\n\",\r\n \" if r.parse_succeeded:\\n\",\r\n \" cf = r.parsed_json.get('communicative_function', '')\\n\",\r\n \" print(f'communicative_function: {cf[:200] if cf else \\\"(empty)\\\"}')\\n\",\r\n \" else:\\n\",\r\n \" print(f'(parse failed: {r.parse_error})')\\n\",\r\n \" print(f'raw: {r.raw_response[:200]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 8: Cost analysis\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Approximate per-million-token costs (as of mid-2026; verify with provider docs)\\n\",\r\n \"# Format: provider -> (input_per_M, output_per_M)\\n\",\r\n \"PRICING_USD = {\\n\",\r\n \" 'anthropic': (3.00, 15.00), # claude-sonnet-4-6\\n\",\r\n \" 'openai': (2.50, 10.00), # gpt-4o\\n\",\r\n \" 'google': (0.15, 0.60), # gemini-2.5-flash\\n\",\r\n \" 'xai': (3.00, 15.00), # grok-4 (estimate)\\n\",\r\n \" 'deepseek': (0.14, 0.28), # deepseek-chat\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"total_cost = 0\\n\",\r\n \"cost_by_provider = {}\\n\",\r\n \"tokens_by_provider = {}\\n\",\r\n \"\\n\",\r\n \"for r in pilot_responses:\\n\",\r\n \" if r.provider not in PRICING_USD:\\n\",\r\n \" continue\\n\",\r\n \" in_price, out_price = PRICING_USD[r.provider]\\n\",\r\n \" cost = (r.input_tokens / 1_000_000) * in_price + (r.output_tokens / 1_000_000) * out_price\\n\",\r\n \" total_cost += cost\\n\",\r\n \" cost_by_provider[r.provider] = cost_by_provider.get(r.provider, 0) + cost\\n\",\r\n \" if r.provider not in tokens_by_provider:\\n\",\r\n \" tokens_by_provider[r.provider] = {'in': 0, 'out': 0}\\n\",\r\n \" tokens_by_provider[r.provider]['in'] += r.input_tokens\\n\",\r\n \" tokens_by_provider[r.provider]['out'] += r.output_tokens\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot cost breakdown:')\\n\",\r\n \"print(f'{\\\"provider\\\":12} {\\\"in_tokens\\\":>10} {\\\"out_tokens\\\":>11} {\\\"cost USD\\\":>10}')\\n\",\r\n \"print('-' * 50)\\n\",\r\n \"for prov in sorted(cost_by_provider.keys()):\\n\",\r\n \" tok = tokens_by_provider[prov]\\n\",\r\n \" cost = cost_by_provider[prov]\\n\",\r\n \" print(f'{prov:12} {tok[\\\"in\\\"]:>10} {tok[\\\"out\\\"]:>11} ${cost:>9.4f}')\\n\",\r\n \"print('-' * 50)\\n\",\r\n \"print(f'{\\\"TOTAL\\\":12} {\\\"\\\":>10} {\\\"\\\":>11} ${total_cost:>9.4f}')\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nExtrapolation to Stage 6 (50x scale): ~${total_cost * 50:.2f}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 9: Save pilot summary\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"pilot_summary = {\\n\",\r\n \" 'stage': '5',\\n\",\r\n \" 'design_sha256': DESIGN_SHA,\\n\",\r\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\r\n \" 'pilot_unit_text': pilot_unit_text,\\n\",\r\n \" 'execution_start': datetime.fromtimestamp(pilot_start, tz=timezone.utc).isoformat(),\\n\",\r\n \" 'execution_duration_seconds': pilot_duration,\\n\",\r\n \" 'total_calls': total,\\n\",\r\n \" 'successes': len(successes),\\n\",\r\n \" 'parse_failures': len(parse_failures),\\n\",\r\n \" 'api_errors': len(errors),\\n\",\r\n \" 'parse_rate': parse_rate,\\n\",\r\n \" 'pilot_cost_usd': round(total_cost, 4),\\n\",\r\n \" 'stage6_extrapolated_cost_usd': round(total_cost * 50, 2),\\n\",\r\n \" 'cost_by_provider': {p: round(c, 4) for p, c in cost_by_provider.items()},\\n\",\r\n \" 'tokens_by_provider': tokens_by_provider,\\n\",\r\n \" 'errors_detail': [\\n\",\r\n \" {'call_id': r.call_id, 'provider': r.provider, 'model': r.api_model, 'error': r.error}\\n\",\r\n \" for r in errors\\n\",\r\n \" ],\\n\",\r\n \" 'parse_failures_detail': [\\n\",\r\n \" {'call_id': r.call_id, 'parse_error': r.parse_error}\\n\",\r\n \" for r in parse_failures\\n\",\r\n \" ]\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"summary_path = f'{PROJECT_ROOT}/outputs/stage5_pilot_summary.json'\\n\",\r\n \"with open(summary_path, 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(pilot_summary, f, indent=2, ensure_ascii=False)\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot summary saved: {summary_path}')\\n\",\r\n \"print(json.dumps(pilot_summary, indent=2))\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 10: Closeout and Stage 6 readiness\\n\",\r\n \"\\n\",\r\n \"**Pilot outputs:**\\n\",\r\n \"- `stage5/responses/{call_id}.json` — individual response files (40 total)\\n\",\r\n \"- `stage5/responses/_index.json` — summary of all pilot responses (next cell builds this)\\n\",\r\n \"- `outputs/stage5_pilot_summary.json` — pilot validation report\\n\",\r\n \"\\n\",\r\n \"**Decision point:**\\n\",\r\n \"\\n\",\r\n \"If all success criteria passed and pilot cost extrapolates to within budget, Stage 6 is ready to run.\\n\",\r\n \"\\n\",\r\n \"If any criterion failed:\\n\",\r\n \"- API authentication failures → fix Colab Secrets\\n\",\r\n \"- Parse failures → revisit `extract_json_from_response` or prompt wording\\n\",\r\n \"- Cost extrapolation over budget → adjust frame count or sample size before Stage 6\\n\",\r\n \"- No frame variation visible in responses → models may be ignoring framing, methodology concern\\n\",\r\n \"\\n\",\r\n \"**What Stage 6 does (next):**\\n\",\r\n \"- Same code path as Stage 5\\n\",\r\n \"- Iterates over the full execution plan (2,000 calls instead of 40)\\n\",\r\n \"- Same storage structure\\n\",\r\n \"- Run unattended; check back in 3-6 hours\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Build an index file for the pilot responses\\n\",\r\n \"index = {\\n\",\r\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\r\n \" 'design_sha256': DESIGN_SHA,\\n\",\r\n \" 'responses': [\\n\",\r\n \" {\\n\",\r\n \" 'call_id': r.call_id,\\n\",\r\n \" 'frame_id': r.frame_id,\\n\",\r\n \" 'model_id': r.model_id,\\n\",\r\n \" 'parse_succeeded': r.parse_succeeded,\\n\",\r\n \" 'has_error': bool(r.error),\\n\",\r\n \" 'wall_clock_seconds': r.wall_clock_seconds,\\n\",\r\n \" 'file': f'{r.call_id}.json'\\n\",\r\n \" }\\n\",\r\n \" for r in pilot_responses\\n\",\r\n \" ]\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"with open(f'{PROJECT_ROOT}/stage5/responses/_index.json', 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(index, f, indent=2, ensure_ascii=False)\\n\",\r\n \"\\n\",\r\n \"print('Pilot index saved.')\\n\",\r\n \"print(f'\\\\nStage 5 status: {\\\"READY FOR STAGE 6\\\" if parse_rate >= 0.9 and len(errors) == 0 else \\\"NEEDS FIXES BEFORE STAGE 6\\\"}')\"\r\n ]\r\n }\r\n ],\r\n \"metadata\": {\r\n \"kernelspec\": {\r\n \"display_name\": \"Python 3\",\r\n \"language\": \"python\",\r\n \"name\": \"python3\"\r\n },\r\n \"language_info\": {\r\n \"name\": \"python\",\r\n \"version\": \"3.10\"\r\n }\r\n },\r\n \"nbformat\": 4,\r\n \"nbformat_minor\": 4\r\n}\r\n"}, "fdb317ac52d05d5b840c2b5480c92ea5db15cc95": {"t": 1785753739.6426852, "n": 29311, "h": "8da500320cc8cbe5", "c": "{\r\n \"cells\": [\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"# MTCA-1 Stage 5: Pilot Execution\\n\",\r\n \"\\n\",\r\n \"**Study identifier:** MTCA-1\\n\",\r\n \"**Stage:** 5 of 10 — Pilot validation\\n\",\r\n \"**Inputs:** Stage 3 design (frozen at SHA `6380e711bbaed3af`)\\n\",\r\n \"**Outputs:** 40 council responses (1 unit × 8 frames × 5 models) + validation report\\n\",\r\n \"\\n\",\r\n \"## Purpose\\n\",\r\n \"\\n\",\r\n \"Validate end-to-end wiring before committing to Stage 6's full 2,000-call execution. The pilot exercises every API client, every frame template, every storage path, and every parser on a small subset where failures are cheap.\\n\",\r\n \"\\n\",\r\n \"## Pilot scope\\n\",\r\n \"\\n\",\r\n \"- **One unit** from the Stage 3 sample (configurable; defaults to a C8 synthetic unit for clear signal)\\n\",\r\n \"- **All 8 frames** applied to that unit\\n\",\r\n \"- **All 5 council models** queried per frame\\n\",\r\n \"- **Total: 40 API calls**, ~$0.40-$1 in cost, 10-20 minutes wall-clock\\n\",\r\n \"\\n\",\r\n \"## Success criteria\\n\",\r\n \"\\n\",\r\n \"Pilot passes if:\\n\",\r\n \"1. All 5 API clients authenticate successfully\\n\",\r\n \"2. All 40 calls return responses (no timeouts, no auth failures)\\n\",\r\n \"3. ≥90% of responses parse as valid JSON with the 5 expected keys\\n\",\r\n \"4. Responses show meaningful variation across frames (sanity check, not statistical)\\n\",\r\n \"5. Storage structure handles all response shapes cleanly\\n\",\r\n \"\\n\",\r\n \"If any criterion fails, fix before Stage 6.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 1: Environment and Stage 3 design load\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"import sys\\n\",\r\n \"IN_COLAB = 'google.colab' in sys.modules\\n\",\r\n \"\\n\",\r\n \"if IN_COLAB:\\n\",\r\n \" from google.colab import drive, userdata\\n\",\r\n \" try:\\n\",\r\n \" drive.mount('/content/drive')\\n\",\r\n \" except Exception:\\n\",\r\n \" pass\\n\",\r\n \" PROJECT_ROOT = '/content/drive/MyDrive/MTCA-1'\\n\",\r\n \"else:\\n\",\r\n \" PROJECT_ROOT = './MTCA-1'\\n\",\r\n \" userdata = None\\n\",\r\n \"\\n\",\r\n \"import os\\n\",\r\n \"import json\\n\",\r\n \"import re\\n\",\r\n \"import time\\n\",\r\n \"import hashlib\\n\",\r\n \"from datetime import datetime, timezone\\n\",\r\n \"from dataclasses import dataclass, field, asdict\\n\",\r\n \"\\n\",\r\n \"# Output dirs\\n\",\r\n \"for subdir in ['stage5', 'stage5/responses', 'stage5/logs']:\\n\",\r\n \" os.makedirs(f'{PROJECT_ROOT}/{subdir}', exist_ok=True)\\n\",\r\n \"\\n\",\r\n \"print(f'Project root: {PROJECT_ROOT}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Load Stage 3 design + execution plan\\n\",\r\n \"stage3_dir = f'{PROJECT_ROOT}/stage3'\\n\",\r\n \"design_files = [f for f in os.listdir(stage3_dir) if f.startswith('stage3_design_')]\\n\",\r\n \"if not design_files:\\n\",\r\n \" raise FileNotFoundError('No Stage 3 design found. Run Stage 3 first.')\\n\",\r\n \"\\n\",\r\n \"design_path = f'{stage3_dir}/{design_files[0]}'\\n\",\r\n \"with open(design_path, 'r', encoding='utf-8') as f:\\n\",\r\n \" stage3_design = json.load(f)\\n\",\r\n \"\\n\",\r\n \"exec_files = [f for f in os.listdir(stage3_dir) if f.startswith('execution_plan_')]\\n\",\r\n \"exec_path = f'{stage3_dir}/{exec_files[0]}'\\n\",\r\n \"with open(exec_path, 'r', encoding='utf-8') as f:\\n\",\r\n \" execution_plan_doc = json.load(f)\\n\",\r\n \"\\n\",\r\n \"EXECUTION_PLAN = execution_plan_doc['calls']\\n\",\r\n \"DESIGN_SHA = stage3_design['design_sha256']\\n\",\r\n \"\\n\",\r\n \"print(f'Loaded Stage 3 design')\\n\",\r\n \"print(f'Design SHA256: {DESIGN_SHA}')\\n\",\r\n \"print(f'Total planned calls: {len(EXECUTION_PLAN)}')\\n\",\r\n \"print(f'Frames: {len(stage3_design[\\\"frames\\\"])}')\\n\",\r\n \"print(f'Council models: {[m[\\\"model_id\\\"] for m in stage3_design[\\\"council_models\\\"]]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 2: Install and import provider SDKs\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Install all required SDKs (no-op if already installed)\\n\",\r\n \"!pip install -q anthropic openai google-generativeai\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"from anthropic import Anthropic\\n\",\r\n \"from openai import OpenAI\\n\",\r\n \"import google.generativeai as genai\\n\",\r\n \"\\n\",\r\n \"# Pull API keys from Colab Secrets (or env vars locally)\\n\",\r\n \"def get_key(name):\\n\",\r\n \" if IN_COLAB and userdata is not None:\\n\",\r\n \" try:\\n\",\r\n \" return userdata.get(name)\\n\",\r\n \" except Exception:\\n\",\r\n \" pass\\n\",\r\n \" return os.environ.get(name)\\n\",\r\n \"\\n\",\r\n \"API_KEYS = {\\n\",\r\n \" 'anthropic': get_key('ANTHROPIC_API_KEY'),\\n\",\r\n \" 'openai': get_key('OPENAI_API_KEY'),\\n\",\r\n \" 'google': get_key('GOOGLE_API_KEY'),\\n\",\r\n \" 'xai': get_key('XAI_API_KEY'),\\n\",\r\n \" 'deepseek': get_key('DEEPSEEK_API_KEY'),\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"# Verify all keys present\\n\",\r\n \"missing = [k for k, v in API_KEYS.items() if not v]\\n\",\r\n \"if missing:\\n\",\r\n \" raise RuntimeError(f'Missing API keys: {missing}. Add to Colab Secrets.')\\n\",\r\n \"\\n\",\r\n \"print('All five API keys loaded.')\\n\",\r\n \"for provider in API_KEYS:\\n\",\r\n \" key = API_KEYS[provider]\\n\",\r\n \" print(f' {provider}: {key[:8]}... ({len(key)} chars)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Initialize clients\\n\",\r\n \"anthropic_client = Anthropic(api_key=API_KEYS['anthropic'])\\n\",\r\n \"openai_client = OpenAI(api_key=API_KEYS['openai'])\\n\",\r\n \"xai_client = OpenAI(api_key=API_KEYS['xai'], base_url='https://api.x.ai/v1')\\n\",\r\n \"deepseek_client = OpenAI(api_key=API_KEYS['deepseek'], base_url='https://api.deepseek.com')\\n\",\r\n \"\\n\",\r\n \"genai.configure(api_key=API_KEYS['google'])\\n\",\r\n \"\\n\",\r\n \"print('All five API clients initialized.')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 3: Response data structure\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"@dataclass\\n\",\r\n \"class CouncilResponse:\\n\",\r\n \" \\\"\\\"\\\"A single response from one model on one (unit, frame) pair.\\\"\\\"\\\"\\n\",\r\n \" # Provenance from the execution plan\\n\",\r\n \" call_id: str\\n\",\r\n \" unit_id: str\\n\",\r\n \" text_id: str\\n\",\r\n \" frame_id: str\\n\",\r\n \" frame_version: str\\n\",\r\n \" prompt_sha256: str\\n\",\r\n \" model_id: str\\n\",\r\n \" provider: str\\n\",\r\n \" api_model: str\\n\",\r\n \" \\n\",\r\n \" # Execution metadata\\n\",\r\n \" timestamp: str\\n\",\r\n \" wall_clock_seconds: float\\n\",\r\n \" \\n\",\r\n \" # Response\\n\",\r\n \" raw_response: str # exactly what the model returned\\n\",\r\n \" parsed_json: dict = field(default_factory=dict) # parsed if successful\\n\",\r\n \" parse_succeeded: bool = False\\n\",\r\n \" parse_error: str = ''\\n\",\r\n \" \\n\",\r\n \" # Token usage (for cost tracking)\\n\",\r\n \" input_tokens: int = 0\\n\",\r\n \" output_tokens: int = 0\\n\",\r\n \" \\n\",\r\n \" # Error tracking\\n\",\r\n \" error: str = ''\\n\",\r\n \" retry_count: int = 0\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def extract_json_from_response(raw: str) -> tuple:\\n\",\r\n \" \\\"\\\"\\\"Extract and parse JSON from a model response.\\n\",\r\n \" \\n\",\r\n \" Handles markdown code fences, leading/trailing whitespace, and common variations.\\n\",\r\n \" Returns (parsed_dict, success_bool, error_msg).\\n\",\r\n \" \\\"\\\"\\\"\\n\",\r\n \" cleaned = raw.strip()\\n\",\r\n \" \\n\",\r\n \" # Strip markdown code fences if present\\n\",\r\n \" if cleaned.startswith('```'):\\n\",\r\n \" cleaned = re.sub(r'^```(?:json)?\\\\s*', '', cleaned)\\n\",\r\n \" cleaned = re.sub(r'\\\\s*```$', '', cleaned)\\n\",\r\n \" \\n\",\r\n \" # Some models add a preamble - try to find the JSON block\\n\",\r\n \" json_start = cleaned.find('{')\\n\",\r\n \" json_end = cleaned.rfind('}')\\n\",\r\n \" \\n\",\r\n \" if json_start == -1 or json_end == -1:\\n\",\r\n \" return {}, False, 'No JSON object found in response'\\n\",\r\n \" \\n\",\r\n \" json_candidate = cleaned[json_start:json_end + 1]\\n\",\r\n \" \\n\",\r\n \" try:\\n\",\r\n \" parsed = json.loads(json_candidate)\\n\",\r\n \" # Validate expected keys present\\n\",\r\n \" expected_keys = {'communicative_function', 'implicit_claims',\\n\",\r\n \" 'coherence_assessment', 'conditions_for_usefulness',\\n\",\r\n \" 'conditions_for_misleading'}\\n\",\r\n \" found_keys = set(parsed.keys())\\n\",\r\n \" missing = expected_keys - found_keys\\n\",\r\n \" if missing:\\n\",\r\n \" return parsed, False, f'Missing keys: {missing}'\\n\",\r\n \" return parsed, True, ''\\n\",\r\n \" except json.JSONDecodeError as e:\\n\",\r\n \" return {}, False, f'JSONDecodeError: {str(e)[:100]}'\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"print('Response data structure defined.')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 4: Per-provider call dispatchers\\n\",\r\n \"\\n\",\r\n \"Each provider has its own SDK and quirks. Wrapping each into a uniform interface that returns `(raw_text, input_tokens, output_tokens, error_str)`.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"MAX_OUTPUT_TOKENS = 800 # generous for the 5-field JSON response\\n\",\r\n \"REQUEST_TIMEOUT = 60 # seconds\\n\",\r\n \"\\n\",\r\n \"def call_anthropic(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" \\\"\\\"\\\"Returns (raw_text, input_tokens, output_tokens, error_str).\\\"\\\"\\\"\\n\",\r\n \" try:\\n\",\r\n \" resp = anthropic_client.messages.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.content[0].text,\\n\",\r\n \" resp.usage.input_tokens,\\n\",\r\n \" resp.usage.output_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'Anthropic error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_openai(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = openai_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'OpenAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_xai(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = xai_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'xAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_deepseek(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" resp = deepseek_client.chat.completions.create(\\n\",\r\n \" model=api_model,\\n\",\r\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\r\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\r\n \" timeout=REQUEST_TIMEOUT\\n\",\r\n \" )\\n\",\r\n \" return (\\n\",\r\n \" resp.choices[0].message.content,\\n\",\r\n \" resp.usage.prompt_tokens,\\n\",\r\n \" resp.usage.completion_tokens,\\n\",\r\n \" ''\\n\",\r\n \" )\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'DeepSeek error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"def call_google(api_model: str, prompt: str) -> tuple:\\n\",\r\n \" try:\\n\",\r\n \" model = genai.GenerativeModel(api_model)\\n\",\r\n \" resp = model.generate_content(\\n\",\r\n \" prompt,\\n\",\r\n \" generation_config={'max_output_tokens': MAX_OUTPUT_TOKENS},\\n\",\r\n \" request_options={'timeout': REQUEST_TIMEOUT}\\n\",\r\n \" )\\n\",\r\n \" # Token counts via usage_metadata when available\\n\",\r\n \" in_tok = getattr(resp.usage_metadata, 'prompt_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\r\n \" out_tok = getattr(resp.usage_metadata, 'candidates_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\r\n \" return (resp.text, in_tok, out_tok, '')\\n\",\r\n \" except Exception as e:\\n\",\r\n \" return ('', 0, 0, f'Google error: {type(e).__name__}: {str(e)[:200]}')\\n\",\r\n \"\\n\",\r\n \"\\n\",\r\n \"PROVIDER_DISPATCH = {\\n\",\r\n \" 'anthropic': call_anthropic,\\n\",\r\n \" 'openai': call_openai,\\n\",\r\n \" 'xai': call_xai,\\n\",\r\n \" 'deepseek': call_deepseek,\\n\",\r\n \" 'google': call_google,\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"print('Provider dispatchers defined for:', list(PROVIDER_DISPATCH.keys()))\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 5: Select pilot unit and filter execution plan\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Choose pilot unit. Default: first C8 unit (synthetic CBT, clear signal).\\n\",\r\n \"# Override by setting PILOT_UNIT_ID to any unit_id from the sample.\\n\",\r\n \"PILOT_UNIT_ID = None # set to a specific unit_id to override default\\n\",\r\n \"\\n\",\r\n \"if PILOT_UNIT_ID is None:\\n\",\r\n \" # Pick first C8 unit\\n\",\r\n \" c8_calls = [c for c in EXECUTION_PLAN if c['text_id'] == 'C8']\\n\",\r\n \" PILOT_UNIT_ID = c8_calls[0]['unit_id']\\n\",\r\n \"\\n\",\r\n \"pilot_calls = [c for c in EXECUTION_PLAN if c['unit_id'] == PILOT_UNIT_ID]\\n\",\r\n \"pilot_unit_text = pilot_calls[0]['unit_text']\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot unit: {PILOT_UNIT_ID}')\\n\",\r\n \"print(f'Pilot text: {pilot_unit_text}')\\n\",\r\n \"print(f'Pilot calls: {len(pilot_calls)} (expected 40: 1 unit × 8 frames × 5 models)')\\n\",\r\n \"\\n\",\r\n \"# Breakdown\\n\",\r\n \"from collections import Counter\\n\",\r\n \"by_frame = Counter(c['frame_id'] for c in pilot_calls)\\n\",\r\n \"by_model = Counter(c['model_id'] for c in pilot_calls)\\n\",\r\n \"print(f'\\\\nBy frame: {dict(by_frame)}')\\n\",\r\n \"print(f'By model: {dict(by_model)}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 6: Execute pilot calls\\n\",\r\n \"\\n\",\r\n \"Runs all 40 calls sequentially with brief pacing between requests. Stores each response immediately so a mid-execution failure doesn't lose completed work.\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"PACING_SECONDS = 0.5 # brief pause between calls to avoid rate limits\\n\",\r\n \"\\n\",\r\n \"pilot_responses = []\\n\",\r\n \"pilot_start = time.time()\\n\",\r\n \"\\n\",\r\n \"for i, call in enumerate(pilot_calls, 1):\\n\",\r\n \" print(f'[{i:>2}/{len(pilot_calls)}] {call[\\\"frame_id\\\"]:24} | {call[\\\"model_id\\\"]:24} ... ', end='', flush=True)\\n\",\r\n \" \\n\",\r\n \" dispatcher = PROVIDER_DISPATCH[call['provider']]\\n\",\r\n \" call_start = time.time()\\n\",\r\n \" raw, in_tok, out_tok, error = dispatcher(call['api_model'], call['rendered_prompt'])\\n\",\r\n \" wall_clock = time.time() - call_start\\n\",\r\n \" \\n\",\r\n \" # Parse the response\\n\",\r\n \" parsed, parse_ok, parse_err = extract_json_from_response(raw) if raw else ({}, False, 'no response')\\n\",\r\n \" \\n\",\r\n \" response = CouncilResponse(\\n\",\r\n \" call_id=call['call_id'],\\n\",\r\n \" unit_id=call['unit_id'],\\n\",\r\n \" text_id=call['text_id'],\\n\",\r\n \" frame_id=call['frame_id'],\\n\",\r\n \" frame_version=call['frame_version'],\\n\",\r\n \" prompt_sha256=call['prompt_sha256'],\\n\",\r\n \" model_id=call['model_id'],\\n\",\r\n \" provider=call['provider'],\\n\",\r\n \" api_model=call['api_model'],\\n\",\r\n \" timestamp=datetime.now(timezone.utc).isoformat(),\\n\",\r\n \" wall_clock_seconds=wall_clock,\\n\",\r\n \" raw_response=raw,\\n\",\r\n \" parsed_json=parsed,\\n\",\r\n \" parse_succeeded=parse_ok,\\n\",\r\n \" parse_error=parse_err,\\n\",\r\n \" input_tokens=in_tok,\\n\",\r\n \" output_tokens=out_tok,\\n\",\r\n \" error=error,\\n\",\r\n \" retry_count=0\\n\",\r\n \" )\\n\",\r\n \" pilot_responses.append(response)\\n\",\r\n \" \\n\",\r\n \" # Print status\\n\",\r\n \" if error:\\n\",\r\n \" print(f'ERROR ({wall_clock:.1f}s)')\\n\",\r\n \" elif not parse_ok:\\n\",\r\n \" print(f'PARSE-FAIL ({wall_clock:.1f}s)')\\n\",\r\n \" else:\\n\",\r\n \" print(f'OK ({wall_clock:.1f}s, {in_tok}+{out_tok} tok)')\\n\",\r\n \" \\n\",\r\n \" # Save immediately so we don't lose progress on crash\\n\",\r\n \" with open(f'{PROJECT_ROOT}/stage5/responses/{call[\\\"call_id\\\"]}.json', 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(asdict(response), f, indent=2, ensure_ascii=False)\\n\",\r\n \" \\n\",\r\n \" time.sleep(PACING_SECONDS)\\n\",\r\n \"\\n\",\r\n \"pilot_duration = time.time() - pilot_start\\n\",\r\n \"print(f'\\\\nPilot complete in {pilot_duration:.1f}s ({pilot_duration/60:.1f} min)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 7: Pilot validation report\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Compute pass/fail against each success criterion\\n\",\r\n \"total = len(pilot_responses)\\n\",\r\n \"errors = [r for r in pilot_responses if r.error]\\n\",\r\n \"no_response = [r for r in pilot_responses if not r.raw_response and not r.error]\\n\",\r\n \"parse_failures = [r for r in pilot_responses if r.raw_response and not r.parse_succeeded]\\n\",\r\n \"successes = [r for r in pilot_responses if r.parse_succeeded]\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nPilot Validation Report')\\n\",\r\n \"print('=' * 60)\\n\",\r\n \"print(f'Total calls: {total}')\\n\",\r\n \"print(f'Successes (clean JSON parse): {len(successes)} ({100*len(successes)/total:.1f}%)')\\n\",\r\n \"print(f'Parse failures: {len(parse_failures)} ({100*len(parse_failures)/total:.1f}%)')\\n\",\r\n \"print(f'API errors: {len(errors)}')\\n\",\r\n \"print(f'No response: {len(no_response)}')\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nSuccess Criteria:')\\n\",\r\n \"print(f' 1. All API clients authenticate: ', end='')\\n\",\r\n \"providers_with_responses = set(r.provider for r in pilot_responses if r.raw_response)\\n\",\r\n \"providers_expected = set(r.provider for r in pilot_responses)\\n\",\r\n \"if providers_with_responses == providers_expected:\\n\",\r\n \" print('PASS')\\n\",\r\n \"else:\\n\",\r\n \" missing_providers = providers_expected - providers_with_responses\\n\",\r\n \" print(f'FAIL (missing: {missing_providers})')\\n\",\r\n \"\\n\",\r\n \"print(f' 2. All 40 calls return responses: ', end='')\\n\",\r\n \"if len(no_response) + len(errors) == 0:\\n\",\r\n \" print('PASS')\\n\",\r\n \"else:\\n\",\r\n \" print(f'FAIL ({len(errors) + len(no_response)} failed)')\\n\",\r\n \"\\n\",\r\n \"print(f' 3. ≥90% parse cleanly: ', end='')\\n\",\r\n \"parse_rate = len(successes) / total\\n\",\r\n \"if parse_rate >= 0.9:\\n\",\r\n \" print(f'PASS ({parse_rate*100:.1f}%)')\\n\",\r\n \"else:\\n\",\r\n \" print(f'FAIL ({parse_rate*100:.1f}%)')\\n\",\r\n \"\\n\",\r\n \"print(f' 4. Frame variation visible: (manual inspection below)')\\n\",\r\n \"print(f' 5. Storage handles all shapes: PASS (all responses written to disk)')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Show errors and parse failures in detail (for debugging)\\n\",\r\n \"if errors:\\n\",\r\n \" print('\\\\n--- API ERRORS ---')\\n\",\r\n \" for r in errors:\\n\",\r\n \" print(f'\\\\n[{r.call_id}]')\\n\",\r\n \" print(f' Provider: {r.provider} | Model: {r.api_model}')\\n\",\r\n \" print(f' Error: {r.error}')\\n\",\r\n \"\\n\",\r\n \"if parse_failures:\\n\",\r\n \" print('\\\\n--- PARSE FAILURES ---')\\n\",\r\n \" for r in parse_failures[:5]: # show up to 5\\n\",\r\n \" print(f'\\\\n[{r.call_id}]')\\n\",\r\n \" print(f' Parse error: {r.parse_error}')\\n\",\r\n \" print(f' Raw response preview: {r.raw_response[:300]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Visual sanity check: how does the same model respond across frames?\\n\",\r\n \"# Pick one model and show all 8 frame responses\\n\",\r\n \"SANITY_MODEL = 'claude_sonnet_4_6'\\n\",\r\n \"model_responses = [r for r in pilot_responses if r.model_id == SANITY_MODEL]\\n\",\r\n \"model_responses.sort(key=lambda r: r.frame_id)\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nSanity check: {SANITY_MODEL} across all 8 frames')\\n\",\r\n \"print('=' * 70)\\n\",\r\n \"for r in model_responses:\\n\",\r\n \" print(f'\\\\n--- {r.frame_id} ---')\\n\",\r\n \" if r.parse_succeeded:\\n\",\r\n \" cf = r.parsed_json.get('communicative_function', '')\\n\",\r\n \" print(f'communicative_function: {cf[:200] if cf else \\\"(empty)\\\"}')\\n\",\r\n \" else:\\n\",\r\n \" print(f'(parse failed: {r.parse_error})')\\n\",\r\n \" print(f'raw: {r.raw_response[:200]}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 8: Cost analysis\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Approximate per-million-token costs (as of mid-2026; verify with provider docs)\\n\",\r\n \"# Format: provider -> (input_per_M, output_per_M)\\n\",\r\n \"PRICING_USD = {\\n\",\r\n \" 'anthropic': (3.00, 15.00), # claude-sonnet-4-6\\n\",\r\n \" 'openai': (2.50, 10.00), # gpt-4o\\n\",\r\n \" 'google': (0.15, 0.60), # gemini-2.5-flash\\n\",\r\n \" 'xai': (3.00, 15.00), # grok-4 (estimate)\\n\",\r\n \" 'deepseek': (0.14, 0.28), # deepseek-chat\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"total_cost = 0\\n\",\r\n \"cost_by_provider = {}\\n\",\r\n \"tokens_by_provider = {}\\n\",\r\n \"\\n\",\r\n \"for r in pilot_responses:\\n\",\r\n \" if r.provider not in PRICING_USD:\\n\",\r\n \" continue\\n\",\r\n \" in_price, out_price = PRICING_USD[r.provider]\\n\",\r\n \" cost = (r.input_tokens / 1_000_000) * in_price + (r.output_tokens / 1_000_000) * out_price\\n\",\r\n \" total_cost += cost\\n\",\r\n \" cost_by_provider[r.provider] = cost_by_provider.get(r.provider, 0) + cost\\n\",\r\n \" if r.provider not in tokens_by_provider:\\n\",\r\n \" tokens_by_provider[r.provider] = {'in': 0, 'out': 0}\\n\",\r\n \" tokens_by_provider[r.provider]['in'] += r.input_tokens\\n\",\r\n \" tokens_by_provider[r.provider]['out'] += r.output_tokens\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot cost breakdown:')\\n\",\r\n \"print(f'{\\\"provider\\\":12} {\\\"in_tokens\\\":>10} {\\\"out_tokens\\\":>11} {\\\"cost USD\\\":>10}')\\n\",\r\n \"print('-' * 50)\\n\",\r\n \"for prov in sorted(cost_by_provider.keys()):\\n\",\r\n \" tok = tokens_by_provider[prov]\\n\",\r\n \" cost = cost_by_provider[prov]\\n\",\r\n \" print(f'{prov:12} {tok[\\\"in\\\"]:>10} {tok[\\\"out\\\"]:>11} ${cost:>9.4f}')\\n\",\r\n \"print('-' * 50)\\n\",\r\n \"print(f'{\\\"TOTAL\\\":12} {\\\"\\\":>10} {\\\"\\\":>11} ${total_cost:>9.4f}')\\n\",\r\n \"\\n\",\r\n \"print(f'\\\\nExtrapolation to Stage 6 (50x scale): ~${total_cost * 50:.2f}')\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 9: Save pilot summary\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"pilot_summary = {\\n\",\r\n \" 'stage': '5',\\n\",\r\n \" 'design_sha256': DESIGN_SHA,\\n\",\r\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\r\n \" 'pilot_unit_text': pilot_unit_text,\\n\",\r\n \" 'execution_start': datetime.fromtimestamp(pilot_start, tz=timezone.utc).isoformat(),\\n\",\r\n \" 'execution_duration_seconds': pilot_duration,\\n\",\r\n \" 'total_calls': total,\\n\",\r\n \" 'successes': len(successes),\\n\",\r\n \" 'parse_failures': len(parse_failures),\\n\",\r\n \" 'api_errors': len(errors),\\n\",\r\n \" 'parse_rate': parse_rate,\\n\",\r\n \" 'pilot_cost_usd': round(total_cost, 4),\\n\",\r\n \" 'stage6_extrapolated_cost_usd': round(total_cost * 50, 2),\\n\",\r\n \" 'cost_by_provider': {p: round(c, 4) for p, c in cost_by_provider.items()},\\n\",\r\n \" 'tokens_by_provider': tokens_by_provider,\\n\",\r\n \" 'errors_detail': [\\n\",\r\n \" {'call_id': r.call_id, 'provider': r.provider, 'model': r.api_model, 'error': r.error}\\n\",\r\n \" for r in errors\\n\",\r\n \" ],\\n\",\r\n \" 'parse_failures_detail': [\\n\",\r\n \" {'call_id': r.call_id, 'parse_error': r.parse_error}\\n\",\r\n \" for r in parse_failures\\n\",\r\n \" ]\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"summary_path = f'{PROJECT_ROOT}/outputs/stage5_pilot_summary.json'\\n\",\r\n \"with open(summary_path, 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(pilot_summary, f, indent=2, ensure_ascii=False)\\n\",\r\n \"\\n\",\r\n \"print(f'Pilot summary saved: {summary_path}')\\n\",\r\n \"print(json.dumps(pilot_summary, indent=2))\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"markdown\",\r\n \"metadata\": {},\r\n \"source\": [\r\n \"## Section 10: Closeout and Stage 6 readiness\\n\",\r\n \"\\n\",\r\n \"**Pilot outputs:**\\n\",\r\n \"- `stage5/responses/{call_id}.json` — individual response files (40 total)\\n\",\r\n \"- `stage5/responses/_index.json` — summary of all pilot responses (next cell builds this)\\n\",\r\n \"- `outputs/stage5_pilot_summary.json` — pilot validation report\\n\",\r\n \"\\n\",\r\n \"**Decision point:**\\n\",\r\n \"\\n\",\r\n \"If all success criteria passed and pilot cost extrapolates to within budget, Stage 6 is ready to run.\\n\",\r\n \"\\n\",\r\n \"If any criterion failed:\\n\",\r\n \"- API authentication failures → fix Colab Secrets\\n\",\r\n \"- Parse failures → revisit `extract_json_from_response` or prompt wording\\n\",\r\n \"- Cost extrapolation over budget → adjust frame count or sample size before Stage 6\\n\",\r\n \"- No frame variation visible in responses → models may be ignoring framing, methodology concern\\n\",\r\n \"\\n\",\r\n \"**What Stage 6 does (next):**\\n\",\r\n \"- Same code path as Stage 5\\n\",\r\n \"- Iterates over the full execution plan (2,000 calls instead of 40)\\n\",\r\n \"- Same storage structure\\n\",\r\n \"- Run unattended; check back in 3-6 hours\"\r\n ]\r\n },\r\n {\r\n \"cell_type\": \"code\",\r\n \"execution_count\": null,\r\n \"metadata\": {},\r\n \"outputs\": [],\r\n \"source\": [\r\n \"# Build an index file for the pilot responses\\n\",\r\n \"index = {\\n\",\r\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\r\n \" 'design_sha256': DESIGN_SHA,\\n\",\r\n \" 'responses': [\\n\",\r\n \" {\\n\",\r\n \" 'call_id': r.call_id,\\n\",\r\n \" 'frame_id': r.frame_id,\\n\",\r\n \" 'model_id': r.model_id,\\n\",\r\n \" 'parse_succeeded': r.parse_succeeded,\\n\",\r\n \" 'has_error': bool(r.error),\\n\",\r\n \" 'wall_clock_seconds': r.wall_clock_seconds,\\n\",\r\n \" 'file': f'{r.call_id}.json'\\n\",\r\n \" }\\n\",\r\n \" for r in pilot_responses\\n\",\r\n \" ]\\n\",\r\n \"}\\n\",\r\n \"\\n\",\r\n \"with open(f'{PROJECT_ROOT}/stage5/responses/_index.json', 'w', encoding='utf-8') as f:\\n\",\r\n \" json.dump(index, f, indent=2, ensure_ascii=False)\\n\",\r\n \"\\n\",\r\n \"print('Pilot index saved.')\\n\",\r\n \"print(f'\\\\nStage 5 status: {\\\"READY FOR STAGE 6\\\" if parse_rate >= 0.9 and len(errors) == 0 else \\\"NEEDS FIXES BEFORE STAGE 6\\\"}')\"\r\n ]\r\n }\r\n ],\r\n \"metadata\": {\r\n \"kernelspec\": {\r\n \"display_name\": \"Python 3\",\r\n \"language\": \"python\",\r\n \"name\": \"python3\"\r\n },\r\n \"language_info\": {\r\n \"name\": \"python\",\r\n \"version\": \"3.10\"\r\n }\r\n },\r\n \"nbformat\": 4,\r\n \"nbformat_minor\": 4\r\n}\r\n"}, "3dbdb12873cef78bdb5b0901b7b5b59078b9ac96": {"t": 1785753741.3041124, "n": 28543, "h": "2c31cdcccfdd433b", "c": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# MTCA-1 Stage 5: Pilot Execution\\n\",\n \"\\n\",\n \"**Study identifier:** MTCA-1\\n\",\n \"**Stage:** 5 of 10 — Pilot validation\\n\",\n \"**Inputs:** Stage 3 design (frozen at SHA `6380e711bbaed3af`)\\n\",\n \"**Outputs:** 40 council responses (1 unit × 8 frames × 5 models) + validation report\\n\",\n \"\\n\",\n \"## Purpose\\n\",\n \"\\n\",\n \"Validate end-to-end wiring before committing to Stage 6's full 2,000-call execution. The pilot exercises every API client, every frame template, every storage path, and every parser on a small subset where failures are cheap.\\n\",\n \"\\n\",\n \"## Pilot scope\\n\",\n \"\\n\",\n \"- **One unit** from the Stage 3 sample (configurable; defaults to a C8 synthetic unit for clear signal)\\n\",\n \"- **All 8 frames** applied to that unit\\n\",\n \"- **All 5 council models** queried per frame\\n\",\n \"- **Total: 40 API calls**, ~$0.40-$1 in cost, 10-20 minutes wall-clock\\n\",\n \"\\n\",\n \"## Success criteria\\n\",\n \"\\n\",\n \"Pilot passes if:\\n\",\n \"1. All 5 API clients authenticate successfully\\n\",\n \"2. All 40 calls return responses (no timeouts, no auth failures)\\n\",\n \"3. ≥90% of responses parse as valid JSON with the 5 expected keys\\n\",\n \"4. Responses show meaningful variation across frames (sanity check, not statistical)\\n\",\n \"5. Storage structure handles all response shapes cleanly\\n\",\n \"\\n\",\n \"If any criterion fails, fix before Stage 6.\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 1: Environment and Stage 3 design load\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"import sys\\n\",\n \"IN_COLAB = 'google.colab' in sys.modules\\n\",\n \"\\n\",\n \"if IN_COLAB:\\n\",\n \" from google.colab import drive, userdata\\n\",\n \" try:\\n\",\n \" drive.mount('/content/drive')\\n\",\n \" except Exception:\\n\",\n \" pass\\n\",\n \" PROJECT_ROOT = '/content/drive/MyDrive/MTCA-1'\\n\",\n \"else:\\n\",\n \" PROJECT_ROOT = './MTCA-1'\\n\",\n \" userdata = None\\n\",\n \"\\n\",\n \"import os\\n\",\n \"import json\\n\",\n \"import re\\n\",\n \"import time\\n\",\n \"import hashlib\\n\",\n \"from datetime import datetime, timezone\\n\",\n \"from dataclasses import dataclass, field, asdict\\n\",\n \"\\n\",\n \"# Output dirs\\n\",\n \"for subdir in ['stage5', 'stage5/responses', 'stage5/logs']:\\n\",\n \" os.makedirs(f'{PROJECT_ROOT}/{subdir}', exist_ok=True)\\n\",\n \"\\n\",\n \"print(f'Project root: {PROJECT_ROOT}')\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Load Stage 3 design + execution plan\\n\",\n \"stage3_dir = f'{PROJECT_ROOT}/stage3'\\n\",\n \"design_files = [f for f in os.listdir(stage3_dir) if f.startswith('stage3_design_')]\\n\",\n \"if not design_files:\\n\",\n \" raise FileNotFoundError('No Stage 3 design found. Run Stage 3 first.')\\n\",\n \"\\n\",\n \"design_path = f'{stage3_dir}/{design_files[0]}'\\n\",\n \"with open(design_path, 'r', encoding='utf-8') as f:\\n\",\n \" stage3_design = json.load(f)\\n\",\n \"\\n\",\n \"exec_files = [f for f in os.listdir(stage3_dir) if f.startswith('execution_plan_')]\\n\",\n \"exec_path = f'{stage3_dir}/{exec_files[0]}'\\n\",\n \"with open(exec_path, 'r', encoding='utf-8') as f:\\n\",\n \" execution_plan_doc = json.load(f)\\n\",\n \"\\n\",\n \"EXECUTION_PLAN = execution_plan_doc['calls']\\n\",\n \"DESIGN_SHA = stage3_design['design_sha256']\\n\",\n \"\\n\",\n \"print(f'Loaded Stage 3 design')\\n\",\n \"print(f'Design SHA256: {DESIGN_SHA}')\\n\",\n \"print(f'Total planned calls: {len(EXECUTION_PLAN)}')\\n\",\n \"print(f'Frames: {len(stage3_design[\\\"frames\\\"])}')\\n\",\n \"print(f'Council models: {[m[\\\"model_id\\\"] for m in stage3_design[\\\"council_models\\\"]]}')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 2: Install and import provider SDKs\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Install all required SDKs (no-op if already installed)\\n\",\n \"!pip install -q anthropic openai google-generativeai\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"from anthropic import Anthropic\\n\",\n \"from openai import OpenAI\\n\",\n \"import google.generativeai as genai\\n\",\n \"\\n\",\n \"# Pull API keys from Colab Secrets (or env vars locally)\\n\",\n \"def get_key(name):\\n\",\n \" if IN_COLAB and userdata is not None:\\n\",\n \" try:\\n\",\n \" return userdata.get(name)\\n\",\n \" except Exception:\\n\",\n \" pass\\n\",\n \" return os.environ.get(name)\\n\",\n \"\\n\",\n \"API_KEYS = {\\n\",\n \" 'anthropic': get_key('ANTHROPIC_API_KEY'),\\n\",\n \" 'openai': get_key('OPENAI_API_KEY'),\\n\",\n \" 'google': get_key('GOOGLE_API_KEY'),\\n\",\n \" 'xai': get_key('XAI_API_KEY'),\\n\",\n \" 'deepseek': get_key('DEEPSEEK_API_KEY'),\\n\",\n \"}\\n\",\n \"\\n\",\n \"# Verify all keys present\\n\",\n \"missing = [k for k, v in API_KEYS.items() if not v]\\n\",\n \"if missing:\\n\",\n \" raise RuntimeError(f'Missing API keys: {missing}. Add to Colab Secrets.')\\n\",\n \"\\n\",\n \"print('All five API keys loaded.')\\n\",\n \"for provider in API_KEYS:\\n\",\n \" key = API_KEYS[provider]\\n\",\n \" print(f' {provider}: {key[:8]}... ({len(key)} chars)')\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Initialize clients\\n\",\n \"anthropic_client = Anthropic(api_key=API_KEYS['anthropic'])\\n\",\n \"openai_client = OpenAI(api_key=API_KEYS['openai'])\\n\",\n \"xai_client = OpenAI(api_key=API_KEYS['xai'], base_url='https://api.x.ai/v1')\\n\",\n \"deepseek_client = OpenAI(api_key=API_KEYS['deepseek'], base_url='https://api.deepseek.com')\\n\",\n \"\\n\",\n \"genai.configure(api_key=API_KEYS['google'])\\n\",\n \"\\n\",\n \"print('All five API clients initialized.')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 3: Response data structure\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"@dataclass\\n\",\n \"class CouncilResponse:\\n\",\n \" \\\"\\\"\\\"A single response from one model on one (unit, frame) pair.\\\"\\\"\\\"\\n\",\n \" # Provenance from the execution plan\\n\",\n \" call_id: str\\n\",\n \" unit_id: str\\n\",\n \" text_id: str\\n\",\n \" frame_id: str\\n\",\n \" frame_version: str\\n\",\n \" prompt_sha256: str\\n\",\n \" model_id: str\\n\",\n \" provider: str\\n\",\n \" api_model: str\\n\",\n \" \\n\",\n \" # Execution metadata\\n\",\n \" timestamp: str\\n\",\n \" wall_clock_seconds: float\\n\",\n \" \\n\",\n \" # Response\\n\",\n \" raw_response: str # exactly what the model returned\\n\",\n \" parsed_json: dict = field(default_factory=dict) # parsed if successful\\n\",\n \" parse_succeeded: bool = False\\n\",\n \" parse_error: str = ''\\n\",\n \" \\n\",\n \" # Token usage (for cost tracking)\\n\",\n \" input_tokens: int = 0\\n\",\n \" output_tokens: int = 0\\n\",\n \" \\n\",\n \" # Error tracking\\n\",\n \" error: str = ''\\n\",\n \" retry_count: int = 0\\n\",\n \"\\n\",\n \"\\n\",\n \"def extract_json_from_response(raw: str) -> tuple:\\n\",\n \" \\\"\\\"\\\"Extract and parse JSON from a model response.\\n\",\n \" \\n\",\n \" Handles markdown code fences, leading/trailing whitespace, and common variations.\\n\",\n \" Returns (parsed_dict, success_bool, error_msg).\\n\",\n \" \\\"\\\"\\\"\\n\",\n \" cleaned = raw.strip()\\n\",\n \" \\n\",\n \" # Strip markdown code fences if present\\n\",\n \" if cleaned.startswith('```'):\\n\",\n \" cleaned = re.sub(r'^```(?:json)?\\\\s*', '', cleaned)\\n\",\n \" cleaned = re.sub(r'\\\\s*```$', '', cleaned)\\n\",\n \" \\n\",\n \" # Some models add a preamble - try to find the JSON block\\n\",\n \" json_start = cleaned.find('{')\\n\",\n \" json_end = cleaned.rfind('}')\\n\",\n \" \\n\",\n \" if json_start == -1 or json_end == -1:\\n\",\n \" return {}, False, 'No JSON object found in response'\\n\",\n \" \\n\",\n \" json_candidate = cleaned[json_start:json_end + 1]\\n\",\n \" \\n\",\n \" try:\\n\",\n \" parsed = json.loads(json_candidate)\\n\",\n \" # Validate expected keys present\\n\",\n \" expected_keys = {'communicative_function', 'implicit_claims',\\n\",\n \" 'coherence_assessment', 'conditions_for_usefulness',\\n\",\n \" 'conditions_for_misleading'}\\n\",\n \" found_keys = set(parsed.keys())\\n\",\n \" missing = expected_keys - found_keys\\n\",\n \" if missing:\\n\",\n \" return parsed, False, f'Missing keys: {missing}'\\n\",\n \" return parsed, True, ''\\n\",\n \" except json.JSONDecodeError as e:\\n\",\n \" return {}, False, f'JSONDecodeError: {str(e)[:100]}'\\n\",\n \"\\n\",\n \"\\n\",\n \"print('Response data structure defined.')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 4: Per-provider call dispatchers\\n\",\n \"\\n\",\n \"Each provider has its own SDK and quirks. Wrapping each into a uniform interface that returns `(raw_text, input_tokens, output_tokens, error_str)`.\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"MAX_OUTPUT_TOKENS = 800 # generous for the 5-field JSON response\\n\",\n \"REQUEST_TIMEOUT = 60 # seconds\\n\",\n \"\\n\",\n \"def call_anthropic(api_model: str, prompt: str) -> tuple:\\n\",\n \" \\\"\\\"\\\"Returns (raw_text, input_tokens, output_tokens, error_str).\\\"\\\"\\\"\\n\",\n \" try:\\n\",\n \" resp = anthropic_client.messages.create(\\n\",\n \" model=api_model,\\n\",\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\n \" timeout=REQUEST_TIMEOUT\\n\",\n \" )\\n\",\n \" return (\\n\",\n \" resp.content[0].text,\\n\",\n \" resp.usage.input_tokens,\\n\",\n \" resp.usage.output_tokens,\\n\",\n \" ''\\n\",\n \" )\\n\",\n \" except Exception as e:\\n\",\n \" return ('', 0, 0, f'Anthropic error: {type(e).__name__}: {str(e)[:200]}')\\n\",\n \"\\n\",\n \"\\n\",\n \"def call_openai(api_model: str, prompt: str) -> tuple:\\n\",\n \" try:\\n\",\n \" resp = openai_client.chat.completions.create(\\n\",\n \" model=api_model,\\n\",\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\n \" timeout=REQUEST_TIMEOUT\\n\",\n \" )\\n\",\n \" return (\\n\",\n \" resp.choices[0].message.content,\\n\",\n \" resp.usage.prompt_tokens,\\n\",\n \" resp.usage.completion_tokens,\\n\",\n \" ''\\n\",\n \" )\\n\",\n \" except Exception as e:\\n\",\n \" return ('', 0, 0, f'OpenAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\n \"\\n\",\n \"\\n\",\n \"def call_xai(api_model: str, prompt: str) -> tuple:\\n\",\n \" try:\\n\",\n \" resp = xai_client.chat.completions.create(\\n\",\n \" model=api_model,\\n\",\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\n \" timeout=REQUEST_TIMEOUT\\n\",\n \" )\\n\",\n \" return (\\n\",\n \" resp.choices[0].message.content,\\n\",\n \" resp.usage.prompt_tokens,\\n\",\n \" resp.usage.completion_tokens,\\n\",\n \" ''\\n\",\n \" )\\n\",\n \" except Exception as e:\\n\",\n \" return ('', 0, 0, f'xAI error: {type(e).__name__}: {str(e)[:200]}')\\n\",\n \"\\n\",\n \"\\n\",\n \"def call_deepseek(api_model: str, prompt: str) -> tuple:\\n\",\n \" try:\\n\",\n \" resp = deepseek_client.chat.completions.create(\\n\",\n \" model=api_model,\\n\",\n \" messages=[{'role': 'user', 'content': prompt}],\\n\",\n \" max_tokens=MAX_OUTPUT_TOKENS,\\n\",\n \" timeout=REQUEST_TIMEOUT\\n\",\n \" )\\n\",\n \" return (\\n\",\n \" resp.choices[0].message.content,\\n\",\n \" resp.usage.prompt_tokens,\\n\",\n \" resp.usage.completion_tokens,\\n\",\n \" ''\\n\",\n \" )\\n\",\n \" except Exception as e:\\n\",\n \" return ('', 0, 0, f'DeepSeek error: {type(e).__name__}: {str(e)[:200]}')\\n\",\n \"\\n\",\n \"\\n\",\n \"def call_google(api_model: str, prompt: str) -> tuple:\\n\",\n \" try:\\n\",\n \" model = genai.GenerativeModel(api_model)\\n\",\n \" resp = model.generate_content(\\n\",\n \" prompt,\\n\",\n \" generation_config={'max_output_tokens': MAX_OUTPUT_TOKENS},\\n\",\n \" request_options={'timeout': REQUEST_TIMEOUT}\\n\",\n \" )\\n\",\n \" # Token counts via usage_metadata when available\\n\",\n \" in_tok = getattr(resp.usage_metadata, 'prompt_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\n \" out_tok = getattr(resp.usage_metadata, 'candidates_token_count', 0) if hasattr(resp, 'usage_metadata') else 0\\n\",\n \" return (resp.text, in_tok, out_tok, '')\\n\",\n \" except Exception as e:\\n\",\n \" return ('', 0, 0, f'Google error: {type(e).__name__}: {str(e)[:200]}')\\n\",\n \"\\n\",\n \"\\n\",\n \"PROVIDER_DISPATCH = {\\n\",\n \" 'anthropic': call_anthropic,\\n\",\n \" 'openai': call_openai,\\n\",\n \" 'xai': call_xai,\\n\",\n \" 'deepseek': call_deepseek,\\n\",\n \" 'google': call_google,\\n\",\n \"}\\n\",\n \"\\n\",\n \"print('Provider dispatchers defined for:', list(PROVIDER_DISPATCH.keys()))\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 5: Select pilot unit and filter execution plan\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Choose pilot unit. Default: first C8 unit (synthetic CBT, clear signal).\\n\",\n \"# Override by setting PILOT_UNIT_ID to any unit_id from the sample.\\n\",\n \"PILOT_UNIT_ID = None # set to a specific unit_id to override default\\n\",\n \"\\n\",\n \"if PILOT_UNIT_ID is None:\\n\",\n \" # Pick first C8 unit\\n\",\n \" c8_calls = [c for c in EXECUTION_PLAN if c['text_id'] == 'C8']\\n\",\n \" PILOT_UNIT_ID = c8_calls[0]['unit_id']\\n\",\n \"\\n\",\n \"pilot_calls = [c for c in EXECUTION_PLAN if c['unit_id'] == PILOT_UNIT_ID]\\n\",\n \"pilot_unit_text = pilot_calls[0]['unit_text']\\n\",\n \"\\n\",\n \"print(f'Pilot unit: {PILOT_UNIT_ID}')\\n\",\n \"print(f'Pilot text: {pilot_unit_text}')\\n\",\n \"print(f'Pilot calls: {len(pilot_calls)} (expected 40: 1 unit × 8 frames × 5 models)')\\n\",\n \"\\n\",\n \"# Breakdown\\n\",\n \"from collections import Counter\\n\",\n \"by_frame = Counter(c['frame_id'] for c in pilot_calls)\\n\",\n \"by_model = Counter(c['model_id'] for c in pilot_calls)\\n\",\n \"print(f'\\\\nBy frame: {dict(by_frame)}')\\n\",\n \"print(f'By model: {dict(by_model)}')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 6: Execute pilot calls\\n\",\n \"\\n\",\n \"Runs all 40 calls sequentially with brief pacing between requests. Stores each response immediately so a mid-execution failure doesn't lose completed work.\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"PACING_SECONDS = 0.5 # brief pause between calls to avoid rate limits\\n\",\n \"\\n\",\n \"pilot_responses = []\\n\",\n \"pilot_start = time.time()\\n\",\n \"\\n\",\n \"for i, call in enumerate(pilot_calls, 1):\\n\",\n \" print(f'[{i:>2}/{len(pilot_calls)}] {call[\\\"frame_id\\\"]:24} | {call[\\\"model_id\\\"]:24} ... ', end='', flush=True)\\n\",\n \" \\n\",\n \" dispatcher = PROVIDER_DISPATCH[call['provider']]\\n\",\n \" call_start = time.time()\\n\",\n \" raw, in_tok, out_tok, error = dispatcher(call['api_model'], call['rendered_prompt'])\\n\",\n \" wall_clock = time.time() - call_start\\n\",\n \" \\n\",\n \" # Parse the response\\n\",\n \" parsed, parse_ok, parse_err = extract_json_from_response(raw) if raw else ({}, False, 'no response')\\n\",\n \" \\n\",\n \" response = CouncilResponse(\\n\",\n \" call_id=call['call_id'],\\n\",\n \" unit_id=call['unit_id'],\\n\",\n \" text_id=call['text_id'],\\n\",\n \" frame_id=call['frame_id'],\\n\",\n \" frame_version=call['frame_version'],\\n\",\n \" prompt_sha256=call['prompt_sha256'],\\n\",\n \" model_id=call['model_id'],\\n\",\n \" provider=call['provider'],\\n\",\n \" api_model=call['api_model'],\\n\",\n \" timestamp=datetime.now(timezone.utc).isoformat(),\\n\",\n \" wall_clock_seconds=wall_clock,\\n\",\n \" raw_response=raw,\\n\",\n \" parsed_json=parsed,\\n\",\n \" parse_succeeded=parse_ok,\\n\",\n \" parse_error=parse_err,\\n\",\n \" input_tokens=in_tok,\\n\",\n \" output_tokens=out_tok,\\n\",\n \" error=error,\\n\",\n \" retry_count=0\\n\",\n \" )\\n\",\n \" pilot_responses.append(response)\\n\",\n \" \\n\",\n \" # Print status\\n\",\n \" if error:\\n\",\n \" print(f'ERROR ({wall_clock:.1f}s)')\\n\",\n \" elif not parse_ok:\\n\",\n \" print(f'PARSE-FAIL ({wall_clock:.1f}s)')\\n\",\n \" else:\\n\",\n \" print(f'OK ({wall_clock:.1f}s, {in_tok}+{out_tok} tok)')\\n\",\n \" \\n\",\n \" # Save immediately so we don't lose progress on crash\\n\",\n \" with open(f'{PROJECT_ROOT}/stage5/responses/{call[\\\"call_id\\\"]}.json', 'w', encoding='utf-8') as f:\\n\",\n \" json.dump(asdict(response), f, indent=2, ensure_ascii=False)\\n\",\n \" \\n\",\n \" time.sleep(PACING_SECONDS)\\n\",\n \"\\n\",\n \"pilot_duration = time.time() - pilot_start\\n\",\n \"print(f'\\\\nPilot complete in {pilot_duration:.1f}s ({pilot_duration/60:.1f} min)')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 7: Pilot validation report\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Compute pass/fail against each success criterion\\n\",\n \"total = len(pilot_responses)\\n\",\n \"errors = [r for r in pilot_responses if r.error]\\n\",\n \"no_response = [r for r in pilot_responses if not r.raw_response and not r.error]\\n\",\n \"parse_failures = [r for r in pilot_responses if r.raw_response and not r.parse_succeeded]\\n\",\n \"successes = [r for r in pilot_responses if r.parse_succeeded]\\n\",\n \"\\n\",\n \"print(f'\\\\nPilot Validation Report')\\n\",\n \"print('=' * 60)\\n\",\n \"print(f'Total calls: {total}')\\n\",\n \"print(f'Successes (clean JSON parse): {len(successes)} ({100*len(successes)/total:.1f}%)')\\n\",\n \"print(f'Parse failures: {len(parse_failures)} ({100*len(parse_failures)/total:.1f}%)')\\n\",\n \"print(f'API errors: {len(errors)}')\\n\",\n \"print(f'No response: {len(no_response)}')\\n\",\n \"\\n\",\n \"print(f'\\\\nSuccess Criteria:')\\n\",\n \"print(f' 1. All API clients authenticate: ', end='')\\n\",\n \"providers_with_responses = set(r.provider for r in pilot_responses if r.raw_response)\\n\",\n \"providers_expected = set(r.provider for r in pilot_responses)\\n\",\n \"if providers_with_responses == providers_expected:\\n\",\n \" print('PASS')\\n\",\n \"else:\\n\",\n \" missing_providers = providers_expected - providers_with_responses\\n\",\n \" print(f'FAIL (missing: {missing_providers})')\\n\",\n \"\\n\",\n \"print(f' 2. All 40 calls return responses: ', end='')\\n\",\n \"if len(no_response) + len(errors) == 0:\\n\",\n \" print('PASS')\\n\",\n \"else:\\n\",\n \" print(f'FAIL ({len(errors) + len(no_response)} failed)')\\n\",\n \"\\n\",\n \"print(f' 3. ≥90% parse cleanly: ', end='')\\n\",\n \"parse_rate = len(successes) / total\\n\",\n \"if parse_rate >= 0.9:\\n\",\n \" print(f'PASS ({parse_rate*100:.1f}%)')\\n\",\n \"else:\\n\",\n \" print(f'FAIL ({parse_rate*100:.1f}%)')\\n\",\n \"\\n\",\n \"print(f' 4. Frame variation visible: (manual inspection below)')\\n\",\n \"print(f' 5. Storage handles all shapes: PASS (all responses written to disk)')\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Show errors and parse failures in detail (for debugging)\\n\",\n \"if errors:\\n\",\n \" print('\\\\n--- API ERRORS ---')\\n\",\n \" for r in errors:\\n\",\n \" print(f'\\\\n[{r.call_id}]')\\n\",\n \" print(f' Provider: {r.provider} | Model: {r.api_model}')\\n\",\n \" print(f' Error: {r.error}')\\n\",\n \"\\n\",\n \"if parse_failures:\\n\",\n \" print('\\\\n--- PARSE FAILURES ---')\\n\",\n \" for r in parse_failures[:5]: # show up to 5\\n\",\n \" print(f'\\\\n[{r.call_id}]')\\n\",\n \" print(f' Parse error: {r.parse_error}')\\n\",\n \" print(f' Raw response preview: {r.raw_response[:300]}')\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Visual sanity check: how does the same model respond across frames?\\n\",\n \"# Pick one model and show all 8 frame responses\\n\",\n \"SANITY_MODEL = 'claude_sonnet_4_6'\\n\",\n \"model_responses = [r for r in pilot_responses if r.model_id == SANITY_MODEL]\\n\",\n \"model_responses.sort(key=lambda r: r.frame_id)\\n\",\n \"\\n\",\n \"print(f'\\\\nSanity check: {SANITY_MODEL} across all 8 frames')\\n\",\n \"print('=' * 70)\\n\",\n \"for r in model_responses:\\n\",\n \" print(f'\\\\n--- {r.frame_id} ---')\\n\",\n \" if r.parse_succeeded:\\n\",\n \" cf = r.parsed_json.get('communicative_function', '')\\n\",\n \" print(f'communicative_function: {cf[:200] if cf else \\\"(empty)\\\"}')\\n\",\n \" else:\\n\",\n \" print(f'(parse failed: {r.parse_error})')\\n\",\n \" print(f'raw: {r.raw_response[:200]}')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 8: Cost analysis\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Approximate per-million-token costs (as of mid-2026; verify with provider docs)\\n\",\n \"# Format: provider -> (input_per_M, output_per_M)\\n\",\n \"PRICING_USD = {\\n\",\n \" 'anthropic': (3.00, 15.00), # claude-sonnet-4-6\\n\",\n \" 'openai': (2.50, 10.00), # gpt-4o\\n\",\n \" 'google': (0.15, 0.60), # gemini-2.5-flash\\n\",\n \" 'xai': (3.00, 15.00), # grok-4 (estimate)\\n\",\n \" 'deepseek': (0.14, 0.28), # deepseek-chat\\n\",\n \"}\\n\",\n \"\\n\",\n \"total_cost = 0\\n\",\n \"cost_by_provider = {}\\n\",\n \"tokens_by_provider = {}\\n\",\n \"\\n\",\n \"for r in pilot_responses:\\n\",\n \" if r.provider not in PRICING_USD:\\n\",\n \" continue\\n\",\n \" in_price, out_price = PRICING_USD[r.provider]\\n\",\n \" cost = (r.input_tokens / 1_000_000) * in_price + (r.output_tokens / 1_000_000) * out_price\\n\",\n \" total_cost += cost\\n\",\n \" cost_by_provider[r.provider] = cost_by_provider.get(r.provider, 0) + cost\\n\",\n \" if r.provider not in tokens_by_provider:\\n\",\n \" tokens_by_provider[r.provider] = {'in': 0, 'out': 0}\\n\",\n \" tokens_by_provider[r.provider]['in'] += r.input_tokens\\n\",\n \" tokens_by_provider[r.provider]['out'] += r.output_tokens\\n\",\n \"\\n\",\n \"print(f'Pilot cost breakdown:')\\n\",\n \"print(f'{\\\"provider\\\":12} {\\\"in_tokens\\\":>10} {\\\"out_tokens\\\":>11} {\\\"cost USD\\\":>10}')\\n\",\n \"print('-' * 50)\\n\",\n \"for prov in sorted(cost_by_provider.keys()):\\n\",\n \" tok = tokens_by_provider[prov]\\n\",\n \" cost = cost_by_provider[prov]\\n\",\n \" print(f'{prov:12} {tok[\\\"in\\\"]:>10} {tok[\\\"out\\\"]:>11} ${cost:>9.4f}')\\n\",\n \"print('-' * 50)\\n\",\n \"print(f'{\\\"TOTAL\\\":12} {\\\"\\\":>10} {\\\"\\\":>11} ${total_cost:>9.4f}')\\n\",\n \"\\n\",\n \"print(f'\\\\nExtrapolation to Stage 6 (50x scale): ~${total_cost * 50:.2f}')\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 9: Save pilot summary\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"pilot_summary = {\\n\",\n \" 'stage': '5',\\n\",\n \" 'design_sha256': DESIGN_SHA,\\n\",\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\n \" 'pilot_unit_text': pilot_unit_text,\\n\",\n \" 'execution_start': datetime.fromtimestamp(pilot_start, tz=timezone.utc).isoformat(),\\n\",\n \" 'execution_duration_seconds': pilot_duration,\\n\",\n \" 'total_calls': total,\\n\",\n \" 'successes': len(successes),\\n\",\n \" 'parse_failures': len(parse_failures),\\n\",\n \" 'api_errors': len(errors),\\n\",\n \" 'parse_rate': parse_rate,\\n\",\n \" 'pilot_cost_usd': round(total_cost, 4),\\n\",\n \" 'stage6_extrapolated_cost_usd': round(total_cost * 50, 2),\\n\",\n \" 'cost_by_provider': {p: round(c, 4) for p, c in cost_by_provider.items()},\\n\",\n \" 'tokens_by_provider': tokens_by_provider,\\n\",\n \" 'errors_detail': [\\n\",\n \" {'call_id': r.call_id, 'provider': r.provider, 'model': r.api_model, 'error': r.error}\\n\",\n \" for r in errors\\n\",\n \" ],\\n\",\n \" 'parse_failures_detail': [\\n\",\n \" {'call_id': r.call_id, 'parse_error': r.parse_error}\\n\",\n \" for r in parse_failures\\n\",\n \" ]\\n\",\n \"}\\n\",\n \"\\n\",\n \"summary_path = f'{PROJECT_ROOT}/outputs/stage5_pilot_summary.json'\\n\",\n \"with open(summary_path, 'w', encoding='utf-8') as f:\\n\",\n \" json.dump(pilot_summary, f, indent=2, ensure_ascii=False)\\n\",\n \"\\n\",\n \"print(f'Pilot summary saved: {summary_path}')\\n\",\n \"print(json.dumps(pilot_summary, indent=2))\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## Section 10: Closeout and Stage 6 readiness\\n\",\n \"\\n\",\n \"**Pilot outputs:**\\n\",\n \"- `stage5/responses/{call_id}.json` — individual response files (40 total)\\n\",\n \"- `stage5/responses/_index.json` — summary of all pilot responses (next cell builds this)\\n\",\n \"- `outputs/stage5_pilot_summary.json` — pilot validation report\\n\",\n \"\\n\",\n \"**Decision point:**\\n\",\n \"\\n\",\n \"If all success criteria passed and pilot cost extrapolates to within budget, Stage 6 is ready to run.\\n\",\n \"\\n\",\n \"If any criterion failed:\\n\",\n \"- API authentication failures → fix Colab Secrets\\n\",\n \"- Parse failures → revisit `extract_json_from_response` or prompt wording\\n\",\n \"- Cost extrapolation over budget → adjust frame count or sample size before Stage 6\\n\",\n \"- No frame variation visible in responses → models may be ignoring framing, methodology concern\\n\",\n \"\\n\",\n \"**What Stage 6 does (next):**\\n\",\n \"- Same code path as Stage 5\\n\",\n \"- Iterates over the full execution plan (2,000 calls instead of 40)\\n\",\n \"- Same storage structure\\n\",\n \"- Run unattended; check back in 3-6 hours\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"metadata\": {},\n \"outputs\": [],\n \"source\": [\n \"# Build an index file for the pilot responses\\n\",\n \"index = {\\n\",\n \" 'pilot_unit_id': PILOT_UNIT_ID,\\n\",\n \" 'design_sha256': DESIGN_SHA,\\n\",\n \" 'responses': [\\n\",\n \" {\\n\",\n \" 'call_id': r.call_id,\\n\",\n \" 'frame_id': r.frame_id,\\n\",\n \" 'model_id': r.model_id,\\n\",\n \" 'parse_succeeded': r.parse_succeeded,\\n\",\n \" 'has_error': bool(r.error),\\n\",\n \" 'wall_clock_seconds': r.wall_clock_seconds,\\n\",\n \" 'file': f'{r.call_id}.json'\\n\",\n \" }\\n\",\n \" for r in pilot_responses\\n\",\n \" ]\\n\",\n \"}\\n\",\n \"\\n\",\n \"with open(f'{PROJECT_ROOT}/stage5/responses/_index.json', 'w', encoding='utf-8') as f:\\n\",\n \" json.dump(index, f, indent=2, ensure_ascii=False)\\n\",\n \"\\n\",\n \"print('Pilot index saved.')\\n\",\n \"print(f'\\\\nStage 5 status: {\\\"READY FOR STAGE 6\\\" if parse_rate >= 0.9 and len(errors) == 0 else \\\"NEEDS FIXES BEFORE STAGE 6\\\"}')\"\n ]\n }\n ],\n \"metadata\": {\n \"kernelspec\": {\n \"display_name\": \"Python 3\",\n \"language\": \"python\",\n \"name\": \"python3\"\n },\n \"language_info\": {\n \"name\": \"python\",\n \"version\": \"3.10\"\n }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 4\n}\n"}}, "mtca-2/MTCA2_Stage9_Unframed_Baseline.ipynb": {"e6f61fbacc8b7f1cdf5d2e6ad164a8b49b43fc33": {"t": 1785745512.4881785, "n": 13778, "h": "6bff227f1b8d8a42", "c": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# MTCA-2 · Stage 9 · Unframed Baseline (H10)\\n\",\n \"\\n\",\n \"**Pre-registered in Amendment 003 (filed before this collection runs).**\\n\",\n \"\\n\",\n \"**Purpose:** close the reflexive loop. Stage 8.5 asked each model what it would produce *unframed*; the models predicted \\\"a synthesis of both\\\" (Claude alone retaining a lean). That prediction was never measured. Stage 9 collects the actual unframed response and tests it.\\n\",\n \"\\n\",\n \"**Design:** 13 principles × 5 models × 1 **open, schema-free** prompt = **65 calls** (~$0.15, ~8 min).\\n\",\n \"\\n\",\n \"**Distinct from F0.** F0_neutral is a neutral instance of the *structured 5-field analysis task*. The Stage 9 prompt is an *open holistic-feedback task* — \\\"give your honest overall assessment\\\" — not bound to the analysis schema. Different cognitive task, genuinely new data. It doubles as an author-feedback artifact (the models' natural read on each principle).\\n\",\n \"\\n\",\n \"**H10 prediction (pre-registered):** for 4/5 models the unframed response embeds nearer the F1↔F2 midpoint than either pole (synthesis); Claude leans to its Stage 8.5-stated preference. Null (unframed ≈ F0, or single-frame lean for most) is reportable.\\n\",\n \"\\n\",\n \"**Analysis (Stage 9b, after collection):** embed each unframed response (`all-MiniLM-L6-v2`), compute cosine to that model's own F0 / F1_clinical / F2_metaphysical for the same principle; classify synthesis vs lean; compare to Stage 8.5 stated baseline for the 3 Layer-3 principles.\\n\",\n \"\\n\",\n \"**Language discipline:** the prompt asks for model behavior/feedback, bound by the same consent and no-framework-verdict discipline as all study artifacts.\\n\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-0 — Setup, load corpus + verify prereg amendment in place\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-0\\n\",\n \"!pip -q install anthropic openai google-generativeai\\n\",\n \"\\n\",\n \"import os, re, json, time, hashlib, sys, subprocess\\n\",\n \"from pathlib import Path\\n\",\n \"from datetime import datetime, timezone\\n\",\n \"\\n\",\n \"IN_COLAB = 'google.colab' in sys.modules\\n\",\n \"try:\\n\",\n \" from google.colab import userdata\\n\",\n \"except Exception:\\n\",\n \" userdata = None\\n\",\n \"\\n\",\n \"REPO = Path(\\\"/content/mtca-research\\\") if IN_COLAB else Path(\\\"./mtca-research\\\")\\n\",\n \"if not REPO.exists():\\n\",\n \" subprocess.run([\\\"git\\\",\\\"clone\\\",\\\"https://github.com/billyrdavis1985-bot/mtca-research.git\\\",str(REPO)], check=True)\\n\",\n \"else:\\n\",\n \" subprocess.run([\\\"git\\\",\\\"-C\\\",str(REPO),\\\"pull\\\",\\\"--ff-only\\\"], check=True)\\n\",\n \"\\n\",\n \"MTCA2 = REPO/\\\"mtca-2\\\"\\n\",\n \"CORPUS_PATH = MTCA2/\\\"corpus\\\"/\\\"SSP_v1_corpus.json\\\"\\n\",\n \"CORPUS_SHA = \\\"b917f798da06cd81c03afc9e1f70bd91a0646a0ad2486b5b83530c194f2cea58\\\"\\n\",\n \"assert hashlib.sha256(CORPUS_PATH.read_bytes()).hexdigest() == CORPUS_SHA, \\\"corpus drift\\\"\\n\",\n \"\\n\",\n \"# Confirm Amendment 003 (H10) is present in the committed prereg before collecting\\n\",\n \"prereg = (MTCA2/\\\"prereg\\\"/\\\"mtca2_prereg.md\\\").read_text(encoding=\\\"utf-8\\\")\\n\",\n \"assert \\\"H10 — Unframed-baseline hypothesis\\\" in prereg, \\\"H10 not in prereg — pull latest; Amendment 003 must be committed before Stage 9 runs\\\"\\n\",\n \"print(\\\"Amendment 003 / H10 present in committed prereg. Pre-registration precedes collection.\\\")\\n\",\n \"\\n\",\n \"corpus = json.loads(CORPUS_PATH.read_text(encoding=\\\"utf-8\\\"))\\n\",\n \"principles = {s[\\\"specimen_id\\\"]: s[\\\"principle_text\\\"] for s in corpus[\\\"specimens\\\"]}\\n\",\n \"print(f\\\"Loaded {len(principles)} principles\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-1 — Clients + dispatchers (Stage 6 config, unchanged)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-1\\n\",\n \"from anthropic import Anthropic\\n\",\n \"from openai import OpenAI\\n\",\n \"import google.generativeai as genai\\n\",\n \"\\n\",\n \"def get_key(*cands):\\n\",\n \" for n in cands:\\n\",\n \" v=None\\n\",\n \" if IN_COLAB and userdata is not None:\\n\",\n \" try: v=userdata.get(n)\\n\",\n \" except Exception: v=None\\n\",\n \" if not v: v=os.environ.get(n)\\n\",\n \" if v: return v\\n\",\n \" return None\\n\",\n \"\\n\",\n \"anthropic_client = Anthropic(api_key=get_key('ANTHROPIC_API_KEY'))\\n\",\n \"openai_client = OpenAI(api_key=get_key('OPENAI_API_KEY'))\\n\",\n \"xai_client = OpenAI(api_key=get_key('XAI_API_KEY'), base_url='https://api.x.ai/v1')\\n\",\n \"deepseek_client = OpenAI(api_key=get_key('DEEPSEEK_API_KEYS','DEEPSEEK_API_KEY'), base_url='https://api.deepseek.com')\\n\",\n \"genai.configure(api_key=get_key('GEMINI_API_KEY','GOOGLE_API_KEY'))\\n\",\n \"REQUEST_TIMEOUT=60\\n\",\n \"\\n\",\n \"# same per-model token calibrations as Stage 6 (Amendment 002)\\n\",\n \"DEFAULT_MAX=800; CLAUDE_MAX=2000; GEMINI_MAX=8000\\n\",\n \"\\n\",\n \"MODELS = [\\n\",\n \" {'model_id':'claude_sonnet_4_6','provider':'anthropic','api_model':'claude-sonnet-4-6'},\\n\",\n \" {'model_id':'gpt_4o','provider':'openai','api_model':'gpt-4o'},\\n\",\n \" {'model_id':'gemini_2_5_flash','provider':'google','api_model':'gemini-2.5-flash'},\\n\",\n \" {'model_id':'grok_4','provider':'xai','api_model':'grok-4'},\\n\",\n \" {'model_id':'deepseek_v3','provider':'deepseek','api_model':'deepseek-chat'},\\n\",\n \"]\\n\",\n \"\\n\",\n \"def parse_json(raw):\\n\",\n \" cleaned=(raw or '').strip()\\n\",\n \" if cleaned.startswith('```'):\\n\",\n \" cleaned=re.sub(r'^```(?:json)?\\\\s*','',cleaned); cleaned=re.sub(r'\\\\s*```$','',cleaned)\\n\",\n \" s,e=cleaned.find('{'),cleaned.rfind('}')\\n\",\n \" if s==-1 or e==-1: return {},False\\n\",\n \" try:\\n\",\n \" obj=json.loads(cleaned[s:e+1])\\n\",\n \" need={'overall_read','where_it_helps','where_it_could_mislead'}\\n\",\n \" return obj, need<=set(obj.keys())\\n\",\n \" except json.JSONDecodeError:\\n\",\n \" return {},False\\n\",\n \"\\n\",\n \"def call_model(m, prompt):\\n\",\n \" prov=m['provider']; api=m['api_model']\\n\",\n \" try:\\n\",\n \" if prov=='anthropic':\\n\",\n \" r=anthropic_client.messages.create(model=api,max_tokens=CLAUDE_MAX,\\n\",\n \" messages=[{'role':'user','content':prompt}],timeout=REQUEST_TIMEOUT)\\n\",\n \" return r.content[0].text,''\\n\",\n \" if prov in ('openai','xai','deepseek'):\\n\",\n \" cli={'openai':openai_client,'xai':xai_client,'deepseek':deepseek_client}[prov]\\n\",\n \" r=cli.chat.completions.create(model=api,messages=[{'role':'user','content':prompt}],\\n\",\n \" max_tokens=DEFAULT_MAX,timeout=REQUEST_TIMEOUT)\\n\",\n \" return r.choices[0].message.content,''\\n\",\n \" if prov=='google':\\n\",\n \" gm=genai.GenerativeModel(api)\\n\",\n \" r=gm.generate_content(prompt,generation_config={'max_output_tokens':GEMINI_MAX,\\n\",\n \" 'response_mime_type':'application/json'},request_options={'timeout':REQUEST_TIMEOUT})\\n\",\n \" try: return (r.text or ''),''\\n\",\n \" except Exception:\\n\",\n \" c=r.candidates[0] if getattr(r,'candidates',None) else None\\n\",\n \" return (''.join(getattr(p,'text','') or '' for p in c.content.parts) if c and c.content and c.content.parts else ''),''\\n\",\n \" except Exception as e:\\n\",\n \" return '', f'{prov} error: {type(e).__name__}: {str(e)[:200]}'\\n\",\n \" return '','unknown provider'\\n\",\n \"print(\\\"Dispatchers ready for 5 models.\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-2 — The unframed prompt (hash-logged, schema-free feedback task)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-2\\n\",\n \"# Open holistic-feedback prompt. No interpretive frame; not the 5-field analysis schema.\\n\",\n \"# Light JSON structure only for parseability. Prompt text is hashed into every response.\\n\",\n \"UNFRAMED_PROMPT_TEMPLATE = \\\"\\\"\\\"The author of the following statement has asked for your honest, overall assessment of it. \\\\\\n\",\n \"There is no particular lens or discipline you are being asked to apply — respond as you naturally would if someone \\\\\\n\",\n \"handed you this and asked \\\\\\\"what do you make of this?\\\\\\\"\\n\",\n \"\\n\",\n \"STATEMENT:\\n\",\n \"\\\"{PRINCIPLE_TEXT}\\\"\\n\",\n \"\\n\",\n \"Give your genuine overall read. Respond in JSON with exactly these three keys:\\n\",\n \"- \\\"overall_read\\\": your honest holistic assessment of the statement (what it is, what it is doing, how it lands) — a few sentences\\n\",\n \"- \\\"where_it_helps\\\": the situations or ways in which this statement would serve someone well (a few sentences or a short list)\\n\",\n \"- \\\"where_it_could_mislead\\\": the situations or ways in which this statement could be misread or lead someone astray (a few sentences or a short list)\\n\",\n \"\\n\",\n \"Respond in JSON only, no preamble.\\\"\\\"\\\"\\n\",\n \"\\n\",\n \"PROMPT_SHA = hashlib.sha256(UNFRAMED_PROMPT_TEMPLATE.encode()).hexdigest()\\n\",\n \"print(\\\"Unframed prompt SHA256:\\\", PROMPT_SHA[:16])\\n\",\n \"print(\\\"\\\\nSample render (SSP_P01):\\\\n\\\")\\n\",\n \"print(UNFRAMED_PROMPT_TEMPLATE.format(PRINCIPLE_TEXT=list(principles.values())[0])[:600])\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-3 — Execute (65 calls, resumable, cost gate)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-3\\n\",\n \"STAGE9 = MTCA2/\\\"stage9_unframed\\\"; (STAGE9/\\\"responses\\\").mkdir(parents=True, exist_ok=True)\\n\",\n \"\\n\",\n \"RUN = \\\"\\\" # type RUN = \\\"RUN\\\" to execute (cost gate)\\n\",\n \"plan = [(pid, m) for pid in sorted(principles) for m in MODELS]\\n\",\n \"print(f\\\"Plan: {len(plan)} calls (13 principles × 5 models), est ~$0.15\\\")\\n\",\n \"if RUN != \\\"RUN\\\":\\n\",\n \" print('\\\\nCost gate: set RUN = \\\"RUN\\\" in this cell to execute.')\\n\",\n \"else:\\n\",\n \" results=[]; t0=time.time()\\n\",\n \" for i,(pid,m) in enumerate(plan,1):\\n\",\n \" out = STAGE9/\\\"responses\\\"/f\\\"{pid}__unframed__{m['model_id']}.json\\\"\\n\",\n \" if out.exists():\\n\",\n \" prev=json.loads(out.read_text(encoding='utf-8'))\\n\",\n \" if prev.get('parse_succeeded'):\\n\",\n \" results.append(prev); print(f\\\"[{i:>2}/65] SKIP {pid} {m['model_id']}\\\"); continue\\n\",\n \" prompt = UNFRAMED_PROMPT_TEMPLATE.format(PRINCIPLE_TEXT=principles[pid])\\n\",\n \" ts=time.time(); raw,err=call_model(m,prompt); wall=time.time()-ts\\n\",\n \" parsed,ok = parse_json(raw) if raw else ({},False)\\n\",\n \" rec={'specimen_id':pid,'frame_id':'unframed','model_id':m['model_id'],\\n\",\n \" 'provider':m['provider'],'api_model':m['api_model'],\\n\",\n \" 'prompt_sha256':PROMPT_SHA,'prompt_actual':prompt,\\n\",\n \" 'raw_response':raw,'parsed_json':parsed,'parse_succeeded':ok,'error':err,\\n\",\n \" 'timestamp':datetime.now(timezone.utc).isoformat(),'wall_clock_seconds':round(wall,2),\\n\",\n \" 'response_sha256':hashlib.sha256((raw or '').encode()).hexdigest()}\\n\",\n \" out.write_text(json.dumps(rec,indent=2,ensure_ascii=False),encoding='utf-8')\\n\",\n \" results.append(rec)\\n\",\n \" st='OK ' if ok else ('ERR' if err else 'PFL')\\n\",\n \" print(f\\\"[{i:>2}/65] {st} | {pid} | {m['model_id']:18} | {wall:.1f}s\\\")\\n\",\n \" time.sleep(0.5)\\n\",\n \" ok=sum(1 for r in results if r['parse_succeeded'])\\n\",\n \" print(f\\\"\\\\nComplete: {ok}/{len(plan)} clean · {(time.time()-t0)/60:.1f} min\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-4 — Manifest + read a few unframed reads\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-4\\n\",\n \"if RUN == \\\"RUN\\\":\\n\",\n \" # per-response manifest\\n\",\n \" man=[]\\n\",\n \" for f in sorted(os.listdir(STAGE9/\\\"responses\\\")):\\n\",\n \" p=STAGE9/\\\"responses\\\"/f\\n\",\n \" man.append(f\\\"{hashlib.sha256(p.read_bytes()).hexdigest()} responses/{f}\\\")\\n\",\n \" (STAGE9/\\\"STAGE9_MANIFEST.sha256\\\").write_text(\\\"\\\\n\\\".join(man)+\\\"\\\\n\\\")\\n\",\n \" print(f\\\"Wrote STAGE9_MANIFEST.sha256 ({len(man)} responses)\\\\n\\\")\\n\",\n \"\\n\",\n \" print(\\\"=== Sample unframed reads (overall_read) ===\\\")\\n\",\n \" for pid in ['SSP_P05','SSP_P02','SSP_P03']: # the 3 Layer-3 principles\\n\",\n \" print(f\\\"\\\\n--- {pid} ---\\\")\\n\",\n \" for m in MODELS:\\n\",\n \" f=STAGE9/\\\"responses\\\"/f\\\"{pid}__unframed__{m['model_id']}.json\\\"\\n\",\n \" if not f.exists(): continue\\n\",\n \" r=json.loads(f.read_text(encoding='utf-8'))\\n\",\n \" print(f\\\" [{m['model_id']:18}] {str(r.get('parsed_json',{}).get('overall_read',''))[:180]}\\\")\\n\",\n \" print(\\\"\\\\nNext: zip stage9_unframed/, commit, then run Stage 9b semantic comparison (unframed vs F0/F1/F2).\\\")\\n\",\n \"else:\\n\",\n \" print('Set RUN = \\\"RUN\\\" in S9-3 and re-run to collect, then re-run this cell.')\"\n ]\n }\n ],\n \"metadata\": {\n \"colab\": {\n \"provenance\": []\n },\n \"kernelspec\": {\n \"name\": \"python3\",\n \"display_name\": \"Python 3\"\n },\n \"language_info\": {\n \"name\": \"python\"\n }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 0\n}"}, "bb5fd0a064b62e63d5b714ffcd9b00e221001bda": {"t": 1785753737.4896069, "n": 13778, "h": "6bff227f1b8d8a42", "c": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# MTCA-2 · Stage 9 · Unframed Baseline (H10)\\n\",\n \"\\n\",\n \"**Pre-registered in Amendment 003 (filed before this collection runs).**\\n\",\n \"\\n\",\n \"**Purpose:** close the reflexive loop. Stage 8.5 asked each model what it would produce *unframed*; the models predicted \\\"a synthesis of both\\\" (Claude alone retaining a lean). That prediction was never measured. Stage 9 collects the actual unframed response and tests it.\\n\",\n \"\\n\",\n \"**Design:** 13 principles × 5 models × 1 **open, schema-free** prompt = **65 calls** (~$0.15, ~8 min).\\n\",\n \"\\n\",\n \"**Distinct from F0.** F0_neutral is a neutral instance of the *structured 5-field analysis task*. The Stage 9 prompt is an *open holistic-feedback task* — \\\"give your honest overall assessment\\\" — not bound to the analysis schema. Different cognitive task, genuinely new data. It doubles as an author-feedback artifact (the models' natural read on each principle).\\n\",\n \"\\n\",\n \"**H10 prediction (pre-registered):** for 4/5 models the unframed response embeds nearer the F1↔F2 midpoint than either pole (synthesis); Claude leans to its Stage 8.5-stated preference. Null (unframed ≈ F0, or single-frame lean for most) is reportable.\\n\",\n \"\\n\",\n \"**Analysis (Stage 9b, after collection):** embed each unframed response (`all-MiniLM-L6-v2`), compute cosine to that model's own F0 / F1_clinical / F2_metaphysical for the same principle; classify synthesis vs lean; compare to Stage 8.5 stated baseline for the 3 Layer-3 principles.\\n\",\n \"\\n\",\n \"**Language discipline:** the prompt asks for model behavior/feedback, bound by the same consent and no-framework-verdict discipline as all study artifacts.\\n\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-0 — Setup, load corpus + verify prereg amendment in place\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-0\\n\",\n \"!pip -q install anthropic openai google-generativeai\\n\",\n \"\\n\",\n \"import os, re, json, time, hashlib, sys, subprocess\\n\",\n \"from pathlib import Path\\n\",\n \"from datetime import datetime, timezone\\n\",\n \"\\n\",\n \"IN_COLAB = 'google.colab' in sys.modules\\n\",\n \"try:\\n\",\n \" from google.colab import userdata\\n\",\n \"except Exception:\\n\",\n \" userdata = None\\n\",\n \"\\n\",\n \"REPO = Path(\\\"/content/mtca-research\\\") if IN_COLAB else Path(\\\"./mtca-research\\\")\\n\",\n \"if not REPO.exists():\\n\",\n \" subprocess.run([\\\"git\\\",\\\"clone\\\",\\\"https://github.com/billyrdavis1985-bot/mtca-research.git\\\",str(REPO)], check=True)\\n\",\n \"else:\\n\",\n \" subprocess.run([\\\"git\\\",\\\"-C\\\",str(REPO),\\\"pull\\\",\\\"--ff-only\\\"], check=True)\\n\",\n \"\\n\",\n \"MTCA2 = REPO/\\\"mtca-2\\\"\\n\",\n \"CORPUS_PATH = MTCA2/\\\"corpus\\\"/\\\"SSP_v1_corpus.json\\\"\\n\",\n \"CORPUS_SHA = \\\"b917f798da06cd81c03afc9e1f70bd91a0646a0ad2486b5b83530c194f2cea58\\\"\\n\",\n \"assert hashlib.sha256(CORPUS_PATH.read_bytes()).hexdigest() == CORPUS_SHA, \\\"corpus drift\\\"\\n\",\n \"\\n\",\n \"# Confirm Amendment 003 (H10) is present in the committed prereg before collecting\\n\",\n \"prereg = (MTCA2/\\\"prereg\\\"/\\\"mtca2_prereg.md\\\").read_text(encoding=\\\"utf-8\\\")\\n\",\n \"assert \\\"H10 — Unframed-baseline hypothesis\\\" in prereg, \\\"H10 not in prereg — pull latest; Amendment 003 must be committed before Stage 9 runs\\\"\\n\",\n \"print(\\\"Amendment 003 / H10 present in committed prereg. Pre-registration precedes collection.\\\")\\n\",\n \"\\n\",\n \"corpus = json.loads(CORPUS_PATH.read_text(encoding=\\\"utf-8\\\"))\\n\",\n \"principles = {s[\\\"specimen_id\\\"]: s[\\\"principle_text\\\"] for s in corpus[\\\"specimens\\\"]}\\n\",\n \"print(f\\\"Loaded {len(principles)} principles\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-1 — Clients + dispatchers (Stage 6 config, unchanged)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-1\\n\",\n \"from anthropic import Anthropic\\n\",\n \"from openai import OpenAI\\n\",\n \"import google.generativeai as genai\\n\",\n \"\\n\",\n \"def get_key(*cands):\\n\",\n \" for n in cands:\\n\",\n \" v=None\\n\",\n \" if IN_COLAB and userdata is not None:\\n\",\n \" try: v=userdata.get(n)\\n\",\n \" except Exception: v=None\\n\",\n \" if not v: v=os.environ.get(n)\\n\",\n \" if v: return v\\n\",\n \" return None\\n\",\n \"\\n\",\n \"anthropic_client = Anthropic(api_key=get_key('ANTHROPIC_API_KEY'))\\n\",\n \"openai_client = OpenAI(api_key=get_key('OPENAI_API_KEY'))\\n\",\n \"xai_client = OpenAI(api_key=get_key('XAI_API_KEY'), base_url='https://api.x.ai/v1')\\n\",\n \"deepseek_client = OpenAI(api_key=get_key('DEEPSEEK_API_KEYS','DEEPSEEK_API_KEY'), base_url='https://api.deepseek.com')\\n\",\n \"genai.configure(api_key=get_key('GEMINI_API_KEY','GOOGLE_API_KEY'))\\n\",\n \"REQUEST_TIMEOUT=60\\n\",\n \"\\n\",\n \"# same per-model token calibrations as Stage 6 (Amendment 002)\\n\",\n \"DEFAULT_MAX=800; CLAUDE_MAX=2000; GEMINI_MAX=8000\\n\",\n \"\\n\",\n \"MODELS = [\\n\",\n \" {'model_id':'claude_sonnet_4_6','provider':'anthropic','api_model':'claude-sonnet-4-6'},\\n\",\n \" {'model_id':'gpt_4o','provider':'openai','api_model':'gpt-4o'},\\n\",\n \" {'model_id':'gemini_2_5_flash','provider':'google','api_model':'gemini-2.5-flash'},\\n\",\n \" {'model_id':'grok_4','provider':'xai','api_model':'grok-4'},\\n\",\n \" {'model_id':'deepseek_v3','provider':'deepseek','api_model':'deepseek-chat'},\\n\",\n \"]\\n\",\n \"\\n\",\n \"def parse_json(raw):\\n\",\n \" cleaned=(raw or '').strip()\\n\",\n \" if cleaned.startswith('```'):\\n\",\n \" cleaned=re.sub(r'^```(?:json)?\\\\s*','',cleaned); cleaned=re.sub(r'\\\\s*```$','',cleaned)\\n\",\n \" s,e=cleaned.find('{'),cleaned.rfind('}')\\n\",\n \" if s==-1 or e==-1: return {},False\\n\",\n \" try:\\n\",\n \" obj=json.loads(cleaned[s:e+1])\\n\",\n \" need={'overall_read','where_it_helps','where_it_could_mislead'}\\n\",\n \" return obj, need<=set(obj.keys())\\n\",\n \" except json.JSONDecodeError:\\n\",\n \" return {},False\\n\",\n \"\\n\",\n \"def call_model(m, prompt):\\n\",\n \" prov=m['provider']; api=m['api_model']\\n\",\n \" try:\\n\",\n \" if prov=='anthropic':\\n\",\n \" r=anthropic_client.messages.create(model=api,max_tokens=CLAUDE_MAX,\\n\",\n \" messages=[{'role':'user','content':prompt}],timeout=REQUEST_TIMEOUT)\\n\",\n \" return r.content[0].text,''\\n\",\n \" if prov in ('openai','xai','deepseek'):\\n\",\n \" cli={'openai':openai_client,'xai':xai_client,'deepseek':deepseek_client}[prov]\\n\",\n \" r=cli.chat.completions.create(model=api,messages=[{'role':'user','content':prompt}],\\n\",\n \" max_tokens=DEFAULT_MAX,timeout=REQUEST_TIMEOUT)\\n\",\n \" return r.choices[0].message.content,''\\n\",\n \" if prov=='google':\\n\",\n \" gm=genai.GenerativeModel(api)\\n\",\n \" r=gm.generate_content(prompt,generation_config={'max_output_tokens':GEMINI_MAX,\\n\",\n \" 'response_mime_type':'application/json'},request_options={'timeout':REQUEST_TIMEOUT})\\n\",\n \" try: return (r.text or ''),''\\n\",\n \" except Exception:\\n\",\n \" c=r.candidates[0] if getattr(r,'candidates',None) else None\\n\",\n \" return (''.join(getattr(p,'text','') or '' for p in c.content.parts) if c and c.content and c.content.parts else ''),''\\n\",\n \" except Exception as e:\\n\",\n \" return '', f'{prov} error: {type(e).__name__}: {str(e)[:200]}'\\n\",\n \" return '','unknown provider'\\n\",\n \"print(\\\"Dispatchers ready for 5 models.\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-2 — The unframed prompt (hash-logged, schema-free feedback task)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-2\\n\",\n \"# Open holistic-feedback prompt. No interpretive frame; not the 5-field analysis schema.\\n\",\n \"# Light JSON structure only for parseability. Prompt text is hashed into every response.\\n\",\n \"UNFRAMED_PROMPT_TEMPLATE = \\\"\\\"\\\"The author of the following statement has asked for your honest, overall assessment of it. \\\\\\n\",\n \"There is no particular lens or discipline you are being asked to apply — respond as you naturally would if someone \\\\\\n\",\n \"handed you this and asked \\\\\\\"what do you make of this?\\\\\\\"\\n\",\n \"\\n\",\n \"STATEMENT:\\n\",\n \"\\\"{PRINCIPLE_TEXT}\\\"\\n\",\n \"\\n\",\n \"Give your genuine overall read. Respond in JSON with exactly these three keys:\\n\",\n \"- \\\"overall_read\\\": your honest holistic assessment of the statement (what it is, what it is doing, how it lands) — a few sentences\\n\",\n \"- \\\"where_it_helps\\\": the situations or ways in which this statement would serve someone well (a few sentences or a short list)\\n\",\n \"- \\\"where_it_could_mislead\\\": the situations or ways in which this statement could be misread or lead someone astray (a few sentences or a short list)\\n\",\n \"\\n\",\n \"Respond in JSON only, no preamble.\\\"\\\"\\\"\\n\",\n \"\\n\",\n \"PROMPT_SHA = hashlib.sha256(UNFRAMED_PROMPT_TEMPLATE.encode()).hexdigest()\\n\",\n \"print(\\\"Unframed prompt SHA256:\\\", PROMPT_SHA[:16])\\n\",\n \"print(\\\"\\\\nSample render (SSP_P01):\\\\n\\\")\\n\",\n \"print(UNFRAMED_PROMPT_TEMPLATE.format(PRINCIPLE_TEXT=list(principles.values())[0])[:600])\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-3 — Execute (65 calls, resumable, cost gate)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-3\\n\",\n \"STAGE9 = MTCA2/\\\"stage9_unframed\\\"; (STAGE9/\\\"responses\\\").mkdir(parents=True, exist_ok=True)\\n\",\n \"\\n\",\n \"RUN = \\\"\\\" # type RUN = \\\"RUN\\\" to execute (cost gate)\\n\",\n \"plan = [(pid, m) for pid in sorted(principles) for m in MODELS]\\n\",\n \"print(f\\\"Plan: {len(plan)} calls (13 principles × 5 models), est ~$0.15\\\")\\n\",\n \"if RUN != \\\"RUN\\\":\\n\",\n \" print('\\\\nCost gate: set RUN = \\\"RUN\\\" in this cell to execute.')\\n\",\n \"else:\\n\",\n \" results=[]; t0=time.time()\\n\",\n \" for i,(pid,m) in enumerate(plan,1):\\n\",\n \" out = STAGE9/\\\"responses\\\"/f\\\"{pid}__unframed__{m['model_id']}.json\\\"\\n\",\n \" if out.exists():\\n\",\n \" prev=json.loads(out.read_text(encoding='utf-8'))\\n\",\n \" if prev.get('parse_succeeded'):\\n\",\n \" results.append(prev); print(f\\\"[{i:>2}/65] SKIP {pid} {m['model_id']}\\\"); continue\\n\",\n \" prompt = UNFRAMED_PROMPT_TEMPLATE.format(PRINCIPLE_TEXT=principles[pid])\\n\",\n \" ts=time.time(); raw,err=call_model(m,prompt); wall=time.time()-ts\\n\",\n \" parsed,ok = parse_json(raw) if raw else ({},False)\\n\",\n \" rec={'specimen_id':pid,'frame_id':'unframed','model_id':m['model_id'],\\n\",\n \" 'provider':m['provider'],'api_model':m['api_model'],\\n\",\n \" 'prompt_sha256':PROMPT_SHA,'prompt_actual':prompt,\\n\",\n \" 'raw_response':raw,'parsed_json':parsed,'parse_succeeded':ok,'error':err,\\n\",\n \" 'timestamp':datetime.now(timezone.utc).isoformat(),'wall_clock_seconds':round(wall,2),\\n\",\n \" 'response_sha256':hashlib.sha256((raw or '').encode()).hexdigest()}\\n\",\n \" out.write_text(json.dumps(rec,indent=2,ensure_ascii=False),encoding='utf-8')\\n\",\n \" results.append(rec)\\n\",\n \" st='OK ' if ok else ('ERR' if err else 'PFL')\\n\",\n \" print(f\\\"[{i:>2}/65] {st} | {pid} | {m['model_id']:18} | {wall:.1f}s\\\")\\n\",\n \" time.sleep(0.5)\\n\",\n \" ok=sum(1 for r in results if r['parse_succeeded'])\\n\",\n \" print(f\\\"\\\\nComplete: {ok}/{len(plan)} clean · {(time.time()-t0)/60:.1f} min\\\")\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"## S9-4 — Manifest + read a few unframed reads\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"metadata\": {},\n \"execution_count\": null,\n \"outputs\": [],\n \"source\": [\n \"# S9-4\\n\",\n \"if RUN == \\\"RUN\\\":\\n\",\n \" # per-response manifest\\n\",\n \" man=[]\\n\",\n \" for f in sorted(os.listdir(STAGE9/\\\"responses\\\")):\\n\",\n \" p=STAGE9/\\\"responses\\\"/f\\n\",\n \" man.append(f\\\"{hashlib.sha256(p.read_bytes()).hexdigest()} responses/{f}\\\")\\n\",\n \" (STAGE9/\\\"STAGE9_MANIFEST.sha256\\\").write_text(\\\"\\\\n\\\".join(man)+\\\"\\\\n\\\")\\n\",\n \" print(f\\\"Wrote STAGE9_MANIFEST.sha256 ({len(man)} responses)\\\\n\\\")\\n\",\n \"\\n\",\n \" print(\\\"=== Sample unframed reads (overall_read) ===\\\")\\n\",\n \" for pid in ['SSP_P05','SSP_P02','SSP_P03']: # the 3 Layer-3 principles\\n\",\n \" print(f\\\"\\\\n--- {pid} ---\\\")\\n\",\n \" for m in MODELS:\\n\",\n \" f=STAGE9/\\\"responses\\\"/f\\\"{pid}__unframed__{m['model_id']}.json\\\"\\n\",\n \" if not f.exists(): continue\\n\",\n \" r=json.loads(f.read_text(encoding='utf-8'))\\n\",\n \" print(f\\\" [{m['model_id']:18}] {str(r.get('parsed_json',{}).get('overall_read',''))[:180]}\\\")\\n\",\n \" print(\\\"\\\\nNext: zip stage9_unframed/, commit, then run Stage 9b semantic comparison (unframed vs F0/F1/F2).\\\")\\n\",\n \"else:\\n\",\n \" print('Set RUN = \\\"RUN\\\" in S9-3 and re-run to collect, then re-run this cell.')\"\n ]\n }\n ],\n \"metadata\": {\n \"colab\": {\n \"provenance\": []\n },\n \"kernelspec\": {\n \"name\": \"python3\",\n \"display_name\": \"Python 3\"\n },\n \"language_info\": {\n \"name\": \"python\"\n }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 0\n}"}}}}