Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/billyrdavis1985-bot_mtca-research.json

1 line
125 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"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}"}}}}