[
  {
    "id": "0582f69f-6456-4e9f-a350-fc8a218496b6",
    "sort_order": 0,
    "rubric_text": "In file `quarantine_releases/REC-20260414-001_release.pdf`, the release PDF for REC-20260414-001 must exist in the quarantine_releases subfolder of the workspace.",
    "verifier_code": "from pathlib import Path\n\ndef verify(workspace_path, external_services_path=None):\n    pdf_path = Path(workspace_path) / 'quarantine_releases' / 'REC-20260414-001_release.pdf'\n    if pdf_path.exists():\n        return {'pass': True, 'score': 1.0, 'feedback': f'Found REC-20260414-001_release.pdf at {pdf_path}'}\n    # Also check workspace root in case folder structure differs\n    alt_path = Path(workspace_path) / 'REC-20260414-001_release.pdf'\n    if alt_path.exists():\n        return {'pass': True, 'score': 1.0, 'feedback': f'Found REC-20260414-001_release.pdf at {alt_path}'}\n    return {'pass': False, 'score': 0.0, 'feedback': f'REC-20260414-001_release.pdf not found at {pdf_path} or {alt_path}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "6907a45e-d40b-4af4-af23-242e15476550",
    "sort_order": 1,
    "rubric_text": "In file `quarantine_releases/REC-20260414-002_release.pdf`, this file must NOT exist (request was not actionable).",
    "verifier_code": "from pathlib import Path\n\ndef verify(workspace_path, external_services_path=None):\n    pdf_path = Path(workspace_path) / 'quarantine_releases' / 'REC-20260414-002_release.pdf'\n    alt_path = Path(workspace_path) / 'REC-20260414-002_release.pdf'\n    if pdf_path.exists() or alt_path.exists():\n        return {'pass': False, 'score': 0.0, 'feedback': f'REC-20260414-002_release.pdf should NOT exist (request was not actionable) but was found.'}\n    return {'pass': True, 'score': 1.0, 'feedback': 'REC-20260414-002_release.pdf correctly does not exist.'}",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "a773a42e-e1fe-4032-a1c8-31074ef3a0aa",
    "sort_order": 2,
    "rubric_text": "In file `inventory_master.xlsx`, row 8 must have: cell G8 = 285, cell M8 = 04/14/2026, cell N8 = 'REC-20260414-001', cell O8 = 0, cell P8 = blank, and cell S8 = 'HT-2026-0218, HT-2026-1803'.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\nfrom datetime import datetime, date\n\ndef verify(workspace_path, external_services_path=None):\n    candidates = list(Path(workspace_path).glob('inventory_master.xlsx'))\n    if not candidates:\n        candidates = list(Path(workspace_path).glob('*inventory_master*'))\n    if not candidates:\n        return {'pass': False, 'score': 0.0, 'feedback': 'inventory_master.xlsx not found in workspace'}\n    wb = openpyxl.load_workbook(candidates[0], data_only=True)\n    ws = wb.active\n    issues = []\n\n    # G8 = 285\n    g8 = ws['G8'].value\n    try:\n        g8_num = float(g8) if g8 is not None else None\n        if g8_num is None or abs(g8_num - 285) > 2.85:\n            issues.append(f'G8 expected 285, got {g8}')\n    except (TypeError, ValueError):\n        issues.append(f'G8 expected 285, got {g8}')\n\n    # M8 = 04/14/2026\n    m8 = ws['M8'].value\n    m8_ok = False\n    if m8 is not None:\n        if isinstance(m8, (datetime, date)):\n            dt = m8 if isinstance(m8, datetime) else datetime(m8.year, m8.month, m8.day)\n            if dt.month == 4 and dt.day == 14 and dt.year == 2026:\n                m8_ok = True\n        elif isinstance(m8, str):\n            m8_str = m8.strip()\n            if '04/14/2026' in m8_str or '4/14/2026' in m8_str or '2026-04-14' in m8_str:\n                m8_ok = True\n    if not m8_ok:\n        issues.append(f'M8 expected 04/14/2026, got {m8}')\n\n    # N8 = 'REC-20260414-001'\n    n8 = ws['N8'].value\n    if n8 is None or str(n8).strip() != 'REC-20260414-001':\n        issues.append(f'N8 expected REC-20260414-001, got {n8}')\n\n    # O8 = 0\n    o8 = ws['O8'].value\n    try:\n        o8_num = float(o8) if o8 is not None else None\n        if o8_num is None or abs(o8_num - 0) > 0.01:\n            issues.append(f'O8 expected 0, got {o8}')\n    except (TypeError, ValueError):\n        issues.append(f'O8 expected 0, got {o8}')\n\n    # P8 = blank\n    p8 = ws['P8'].value\n    if p8 is not None and str(p8).strip() != '':\n        issues.append(f'P8 expected blank, got {p8}')\n\n    # S8 = 'HT-2026-0218, HT-2026-1803'\n    s8 = ws['S8'].value\n    if s8 is None:\n        issues.append(f'S8 expected HT-2026-0218, HT-2026-1803, got None')\n    else:\n        s8_str = str(s8).strip()\n        if 'HT-2026-0218' not in s8_str or 'HT-2026-1803' not in s8_str:\n            issues.append(f'S8 expected to contain HT-2026-0218 and HT-2026-1803, got {s8_str}')\n\n    if issues:\n        return {'pass': False, 'score': 0.0, 'feedback': 'inventory_master.xlsx row 8 issues: ' + '; '.join(issues)}\n    return {'pass': True, 'score': 1.0, 'feedback': f'inventory_master.xlsx row 8 verified: G8={g8}, M8={m8}, N8={n8}, O8={o8}, P8={p8}, S8={s8}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "633b2dbd-6618-480b-bee1-843a9ad68813",
    "sort_order": 3,
    "rubric_text": "In file `inventory_master.xlsx`, the spreadsheet must have exactly 20 data rows (last data row on row 21).",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    candidates = list(Path(workspace_path).glob('inventory_master.xlsx'))\n    if not candidates:\n        candidates = list(Path(workspace_path).glob('*inventory_master*'))\n    if not candidates:\n        return {'pass': False, 'score': 0.0, 'feedback': 'inventory_master.xlsx not found in workspace'}\n    wb = openpyxl.load_workbook(candidates[0], data_only=True)\n    ws = wb.active\n    # Count non-empty rows starting from row 2 (assuming row 1 is header)\n    data_rows = 0\n    last_data_row = 1  # default to header row if no data\n    for row_idx, row in enumerate(ws.iter_rows(min_row=2), start=2):\n        if any(cell.value is not None and str(cell.value).strip() != '' for cell in row):\n            data_rows += 1\n            last_data_row = row_idx\n    \n    issues = []\n    passed = True\n    \n    if data_rows != 20:\n        passed = False\n        issues.append(f'Expected exactly 20 data rows, found {data_rows} non-empty data rows.')\n    \n    if last_data_row != 21:\n        passed = False\n        issues.append(f'Expected last data row on row 21, but last non-empty data row is on row {last_data_row}.')\n    \n    if passed:\n        return {'pass': True, 'score': 1.0, 'feedback': f'inventory_master.xlsx has exactly 20 data rows with last data row on row 21 as expected.'}\n    else:\n        return {'pass': False, 'score': 0.0, 'feedback': 'inventory_master.xlsx: ' + ' '.join(issues)}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "7056c0e4-718d-4ecf-b54b-abe1d1497bd2",
    "sort_order": 4,
    "rubric_text": "In file `receiving_log.xlsx`, row 10 must have: cell V10 = 'COC Received and Verified', cell W10 = 'Accepted', cell X10 = 'ACCEPTED', cell Z10 = date 04/23/2026 at or after 09:00 CST, cell AA10 = 'A-09-01', and cell AB10 = 'Putaway Complete'.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\nfrom datetime import datetime, date, time\n\ndef verify(workspace_path, external_services_path=None):\n    candidates = list(Path(workspace_path).glob('receiving_log.xlsx'))\n    if not candidates:\n        candidates = list(Path(workspace_path).glob('*receiving_log*'))\n    if not candidates:\n        return {'pass': False, 'score': 0.0, 'feedback': 'receiving_log.xlsx not found in workspace'}\n    wb = openpyxl.load_workbook(candidates[0], data_only=True)\n    ws = wb.active\n    issues = []\n\n    # V10\n    v10 = ws['V10'].value\n    if v10 is None or 'COC Received and Verified'.lower() not in str(v10).lower():\n        issues.append(f'V10 expected COC Received and Verified, got {v10}')\n\n    # W10\n    w10 = ws['W10'].value\n    if w10 is None or 'accepted' not in str(w10).lower():\n        issues.append(f'W10 expected Accepted, got {w10}')\n\n    # X10\n    x10 = ws['X10'].value\n    if x10 is None or 'ACCEPTED' not in str(x10).upper():\n        issues.append(f'X10 expected ACCEPTED, got {x10}')\n\n    # Z10 = 04/23/2026 at or after 09:00\n    z10 = ws['Z10'].value\n    z10_ok = False\n    if z10 is not None:\n        if isinstance(z10, datetime):\n            if z10.year == 2026 and z10.month == 4 and z10.day == 23:\n                if z10.hour > 9 or (z10.hour == 9 and z10.minute >= 0):\n                    z10_ok = True\n        elif isinstance(z10, date):\n            if z10.year == 2026 and z10.month == 4 and z10.day == 23:\n                z10_ok = True\n        elif isinstance(z10, str):\n            if '04/23/2026' in z10 or '4/23/2026' in z10 or '2026-04-23' in z10:\n                z10_ok = True\n    if not z10_ok:\n        issues.append(f'Z10 expected 04/23/2026 at or after 09:00, got {z10}')\n\n    # AA10\n    aa10 = ws['AA10'].value\n    if aa10 is None or str(aa10).strip().upper() != 'A-09-01':\n        issues.append(f'AA10 expected A-09-01, got {aa10}')\n\n    # AB10\n    ab10 = ws['AB10'].value\n    if ab10 is None or 'Putaway Complete'.lower() not in str(ab10).lower():\n        issues.append(f'AB10 expected Putaway Complete, got {ab10}')\n\n    if issues:\n        return {'pass': False, 'score': 0.0, 'feedback': 'receiving_log.xlsx row 10 issues: ' + '; '.join(issues)}\n    return {'pass': True, 'score': 1.0, 'feedback': f'receiving_log.xlsx row 10 verified: V10={v10}, W10={w10}, X10={x10}, Z10={z10}, AA10={aa10}, AB10={ab10}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "0fde1f50-a8ba-49af-aa77-2d7ed55ccded",
    "sort_order": 5,
    "rubric_text": "In file `receiving_log.xlsx`, the spreadsheet must have exactly 12 data rows (last data row on row 13).",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    candidates = list(Path(workspace_path).glob('receiving_log.xlsx'))\n    if not candidates:\n        candidates = list(Path(workspace_path).glob('*receiving_log*'))\n    if not candidates:\n        return {'pass': False, 'score': 0.0, 'feedback': 'receiving_log.xlsx not found in workspace'}\n    wb = openpyxl.load_workbook(candidates[0], data_only=True)\n    ws = wb.active\n    data_rows = 0\n    for row in ws.iter_rows(min_row=2):\n        if any(cell.value is not None and str(cell.value).strip() != '' for cell in row):\n            data_rows += 1\n    if data_rows == 12:\n        return {'pass': True, 'score': 1.0, 'feedback': f'receiving_log.xlsx has exactly 12 data rows as expected.'}\n    else:\n        return {'pass': False, 'score': 0.0, 'feedback': f'receiving_log.xlsx expected 12 data rows, found {data_rows} non-empty data rows.'}",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "9ed41faa-6e26-4966-b450-fb6f0739baa4",
    "sort_order": 6,
    "rubric_text": "In `ncr_log.xlsx`, cell L6 must remain 'Open' and cell L7 must remain 'Open' (no changes to the NCR log).",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    candidates = list(Path(workspace_path).glob('ncr_log.xlsx'))\n    if not candidates:\n        candidates = list(Path(workspace_path).glob('*ncr_log*'))\n    if not candidates:\n        return {'pass': False, 'score': 0.0, 'feedback': 'ncr_log.xlsx not found in workspace'}\n    wb = openpyxl.load_workbook(candidates[0], data_only=True)\n    ws = wb.active\n    issues = []\n    l6 = ws['L6'].value\n    if l6 is None or str(l6).strip().lower() != 'open':\n        issues.append(f'L6 expected Open, got {l6}')\n    l7 = ws['L7'].value\n    if l7 is None or str(l7).strip().lower() != 'open':\n        issues.append(f'L7 expected Open, got {l7}')\n    if issues:\n        return {'pass': False, 'score': 0.0, 'feedback': 'ncr_log.xlsx issues: ' + '; '.join(issues)}\n    return {'pass': True, 'score': 1.0, 'feedback': f'ncr_log.xlsx L6={l6}, L7={l7} both remain Open as expected.'}",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "20df59e2-389b-4eec-b36d-eb9e8bbb32b5",
    "sort_order": 7,
    "rubric_text": "In `mailbox.json` (external services), there should not be any replies to message_id = <msg0026@gearsystems-meridian.com> in the Sent folder.",
    "verifier_code": "from pathlib import Path\nimport json\n\ndef verify(workspace_path, external_services_path=None):\n    if external_services_path is None:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No external_services_path provided; cannot check mailbox.json for sent emails.'}\n    mailbox_path = Path(external_services_path) / 'mailbox.json'\n    if not mailbox_path.exists():\n        return {'pass': False, 'score': 0.0, 'feedback': 'mailbox.json not found in external services path.'}\n    with open(mailbox_path, 'r') as f:\n        data = json.load(f)\n    emails = data.get('emails', [])\n    sent_emails = [e for e in emails if str(e.get('folder', '')).lower() == 'sent']\n\n    target_message_id = '<msg0026@gearsystems-meridian.com>'\n\n    # Look for any sent email that is a reply to the target message_id.\n    # A reply could be indicated by:\n    #   - in_reply_to field matching the target message_id\n    #   - references field containing the target message_id\n    #   - reply_to_message_id field matching\n    # We check multiple common field names to be generous.\n    replies = []\n    for e in sent_emails:\n        in_reply_to = str(e.get('in_reply_to', '') or '')\n        references = str(e.get('references', '') or '')\n        reply_to_message_id = str(e.get('reply_to_message_id', '') or '')\n        # Also check if subject starts with Re: and references the message somehow\n        # Check body or headers for the message id as well\n        headers = e.get('headers', {})\n        header_in_reply_to = str(headers.get('In-Reply-To', '') or '') if isinstance(headers, dict) else ''\n        header_references = str(headers.get('References', '') or '') if isinstance(headers, dict) else ''\n\n        if (target_message_id in in_reply_to or\n            target_message_id in references or\n            target_message_id in reply_to_message_id or\n            target_message_id in header_in_reply_to or\n            target_message_id in header_references or\n            # Also check without angle brackets\n            'msg0026@gearsystems-meridian.com' in in_reply_to or\n            'msg0026@gearsystems-meridian.com' in references or\n            'msg0026@gearsystems-meridian.com' in reply_to_message_id or\n            'msg0026@gearsystems-meridian.com' in header_in_reply_to or\n            'msg0026@gearsystems-meridian.com' in header_references):\n            replies.append(e)\n\n    if len(replies) == 0:\n        return {\n            'pass': True,\n            'score': 1.0,\n            'feedback': f'No replies to {target_message_id} found in the Sent folder. Total sent emails: {len(sent_emails)}. Check passed.'\n        }\n    else:\n        reply_ids = [str(e.get('email_id', 'unknown')) for e in replies]\n        return {\n            'pass': False,\n            'score': 0.0,\n            'feedback': f'Found {len(replies)} reply/replies to {target_message_id} in the Sent folder (email_ids: {reply_ids}). There should not be any replies to this message.'\n        }\n",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "3366695a-2408-4dc6-b59c-5e73ca53d99f",
    "sort_order": 8,
    "rubric_text": "Calendar event evt-025 must exist with title unchanged (no '[COMPLETED]'). Description must contain the original phrase 'Theo Brandt to verify COC against MTR heat numbers: HT-2026-1184, HT-2026-1185, HT-2026-0997 for receipt REC-20260414-001 (NCR-MER-2026-0247)' AND must contain a partial-release annotation including 'FG-91144-A1 released' with quantity and destination, and 'Remaining on Q-HOLD' listing both AX-04827-B2 and AX-05512-C1 with their quarantined quantities (44 and 96 respectively).",
    "verifier_code": "from pathlib import Path\nimport json\nimport re\n\ndef verify(workspace_path, external_services_path=None):\n    if external_services_path is None:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No external_services_path provided; cannot check calendar_data.json.'}\n    cal_path = Path(external_services_path) / 'calendar_data.json'\n    if not cal_path.exists():\n        return {'pass': False, 'score': 0.0, 'feedback': 'calendar_data.json not found in external services path.'}\n    with open(cal_path, 'r') as f:\n        data = json.load(f)\n    events = data.get('events', {})\n    if 'evt-025' not in events:\n        return {'pass': False, 'score': 0.0, 'feedback': 'Event evt-025 is missing from calendar_data.json (may have been deleted).'}\n    evt = events['evt-025']\n    summary = evt.get('summary', '') or ''\n    description = evt.get('description', '') or ''\n    desc_lower = description.lower()\n    issues = []\n\n    # (1) Title must not contain [COMPLETED]\n    if '[COMPLETED]' in summary.upper():\n        issues.append(f'Title contains [COMPLETED]: {summary}')\n\n    # (2) Description must contain original heat-number phrase\n    heat_numbers = ['HT-2026-1184', 'HT-2026-1185', 'HT-2026-0997']\n    for hn in heat_numbers:\n        if hn not in description:\n            issues.append(f'Description missing original heat number {hn}')\n            break\n\n    # (3) Description must contain partial-release annotation with FG-91144-A1 released\n    has_partial_release = ('partial release' in desc_lower or 'partial-release' in desc_lower)\n    has_fg_released = ('fg-91144-a1' in desc_lower and 'released' in desc_lower)\n    if not has_partial_release:\n        issues.append('Description missing Partial release annotation')\n    if not has_fg_released:\n        issues.append('Description missing FG-91144-A1 released')\n\n    # (4) Description must contain Remaining on Q-HOLD with both AX-04827-B2 and AX-05512-C1\n    has_remaining = ('remaining on q-hold' in desc_lower)\n    if not has_remaining:\n        issues.append('Description missing Remaining on Q-HOLD')\n    if 'ax-04827-b2' not in desc_lower:\n        issues.append('Description missing AX-04827-B2 in remaining quarantine list')\n    if 'ax-05512-c1' not in desc_lower:\n        issues.append('Description missing AX-05512-C1 in remaining quarantine list')\n\n    # (5) Check that 44 and 96 appear in the annotation context\n    # Find the partial release annotation portion\n    partial_idx = desc_lower.find('partial release')\n    if partial_idx == -1:\n        partial_idx = desc_lower.find('partial-release')\n    if partial_idx >= 0:\n        annotation_text = desc_lower[partial_idx:]\n        if '44' not in annotation_text:\n            issues.append('Annotation missing quarantined quantity 44 for AX-04827-B2')\n        if '96' not in annotation_text:\n            issues.append('Annotation missing quarantined quantity 96 for AX-05512-C1')\n    else:\n        if '44' not in desc_lower or '96' not in desc_lower:\n            issues.append('Description missing quarantined quantities 44 and/or 96')\n\n    if issues:\n        return {'pass': False, 'score': 0.0, 'feedback': 'evt-025 issues: ' + '; '.join(issues) + f'. Description: {description[:500]}'}\n    return {'pass': True, 'score': 1.0, 'feedback': f'Event evt-025 verified: title has no [COMPLETED], description contains original heat-number phrase, partial-release annotation with FG-91144-A1 released, Remaining on Q-HOLD listing AX-04827-B2 (44) and AX-05512-C1 (96).'}\n",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "5de62afe-3687-426c-af6f-53d58dea3b01",
    "sort_order": 9,
    "rubric_text": "In slack_data.json (external services), the #receiving-dock channel must have the message containing 'QUARANTINE RELEASED: REC-20260414-001, SKU FG-91144-A1, qty 200 released from Q-HOLD to A-09-01. Authorization: Theo Brandt, 04/23/2026.'",
    "verifier_code": "from pathlib import Path\nimport json\nimport re\n\ndef verify(workspace_path, external_services_path=None):\n    if external_services_path is None:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No external_services_path provided; cannot check Slack data.'}\n    slack_path = Path(external_services_path) / 'slack_data.json'\n    if not slack_path.exists():\n        return {'pass': False, 'score': 0.0, 'feedback': 'slack_data.json not found in external services path.'}\n    with open(slack_path, 'r') as f:\n        data = json.load(f)\n    channels = data.get('channels', {})\n    # Find the #receiving-dock channel ID\n    dock_channel_id = None\n    for cid, cinfo in channels.items():\n        channel_name = cinfo.get('name', '').lower().replace('-', '').replace('_', '')\n        if channel_name in ['receivingdock']:\n            dock_channel_id = cid\n            break\n    if dock_channel_id is None:\n        return {'pass': False, 'score': 0.0, 'feedback': '#receiving-dock channel not found in slack_data.json. Available channels: ' + str([c.get('name') for c in channels.values()])}\n    messages_dict = data.get('messages', {})\n    msgs = messages_dict.get(dock_channel_id, [])\n    if not msgs:\n        return {'pass': False, 'score': 0.0, 'feedback': '#receiving-dock channel has no messages.'}\n\n    # Required wording (whitespace-insensitive match) and identifiers (must appear exactly)\n    required_text = 'QUARANTINE RELEASED: REC-20260414-001, SKU FG-91144-A1, qty 200 released from Q-HOLD to A-09-01. Authorization: Theo Brandt, 04/23/2026.'\n    required_exact_tokens = ['REC-20260414-001', 'FG-91144-A1', 'A-09-01']\n\n    def normalize_ws(s):\n        # Collapse any run of whitespace (spaces, tabs, newlines) into a single space, strip ends\n        return re.sub(r'\\s+', ' ', s).strip()\n\n    required_norm = normalize_ws(required_text)\n\n    # Check all messages in the channel for the required text (whitespace-insensitive)\n    found = False\n    found_text = ''\n    for msg in msgs:\n        msg_text = msg.get('text', '') or ''\n        msg_norm = normalize_ws(msg_text)\n        if required_norm in msg_norm:\n            # Also require the three identifiers to appear exactly in the original message text\n            missing = [tok for tok in required_exact_tokens if tok not in msg_text]\n            if missing:\n                return {'pass': False, 'score': 0.0,\n                        'feedback': f'#receiving-dock message matches the wording but is missing exact identifier(s): {missing}. Message: \"{msg_text[:300]}\"'}\n            found = True\n            found_text = msg_text\n            break\n\n    # Case-insensitive fallback for leniency (still whitespace-insensitive, still requires exact identifiers)\n    if not found:\n        for msg in msgs:\n            msg_text = msg.get('text', '') or ''\n            msg_norm = normalize_ws(msg_text)\n            if required_norm.lower() in msg_norm.lower():\n                missing = [tok for tok in required_exact_tokens if tok not in msg_text]\n                if missing:\n                    return {'pass': False, 'score': 0.0,\n                            'feedback': f'#receiving-dock message matches the wording (case-insensitive) but is missing exact identifier(s): {missing}. Message: \"{msg_text[:300]}\"'}\n                found = True\n                found_text = msg_text\n                break\n\n    if not found:\n        sorted_msgs = sorted(msgs, key=lambda m: float(m.get('ts', 0)))\n        recent_texts = [m.get('text', '')[:200] for m in sorted_msgs[-3:]]\n        return {'pass': False, 'score': 0.0,\n                'feedback': f'#receiving-dock channel does not contain required quarantine release message. Required text (whitespace-insensitive): \"{required_text}\". Last {len(recent_texts)} messages: {recent_texts}'}\n\n    return {'pass': True, 'score': 1.0, 'feedback': f'#receiving-dock channel contains the required quarantine release message: {found_text[:300]}'}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "rubric_1776321019779",
    "sort_order": 10,
    "rubric_text": "In file `inventory_master.xlsx`, cell O11 must be \"144\", P11 must be \"Quarantine - Tier 2 damage pending inspection (REC-20260414-002)\", O19 must be \"44\", P19 must be \"QUARANTINE — missing COC (REC-20260414-001)\", O21 must be \"144\", and P21 must be \"QUARANTINE — Tier 2 damage pending inspection (REC-20260414-002)\".",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    # Find inventory_master.xlsx\n    file_path = Path(workspace_path) / \"inventory_master.xlsx\"\n    \n    if not file_path.exists():\n        xlsx_files = list(Path(workspace_path).glob(\"**/inventory_master.xlsx\"))\n        if xlsx_files:\n            file_path = xlsx_files[0]\n        else:\n            return {\"pass\": False, \"score\": 0.0, \"feedback\": \"File `inventory_master.xlsx` not found in workspace.\"}\n    \n    try:\n        wb = openpyxl.load_workbook(file_path, data_only=True)\n    except Exception as e:\n        return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Could not open `inventory_master.xlsx`: {e}\"}\n    \n    ws = wb.active\n    if ws is None:\n        ws = wb.worksheets[0] if wb.worksheets else None\n    \n    if ws is None:\n        wb.close()\n        return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No worksheets found in `inventory_master.xlsx`.\"}\n    \n    feedback_parts = []\n    checks_passed = 0\n    total_checks = 6\n    \n    def cell_str(row, col):\n        val = ws.cell(row=row, column=col).value\n        if val is None:\n            return None\n        return str(val).strip()\n    \n    def normalize_dash(s):\n        if s is None:\n            return None\n        return s.replace('\\u2014', '-').replace('\\u2013', '-').replace('--', '-').lower().strip()\n    \n    def check_numeric(row, col, expected, label):\n        nonlocal checks_passed\n        val = cell_str(row, col)\n        # Accept numeric equivalence: \"144\" or \"144.0\" etc.\n        match = False\n        if val is not None:\n            try:\n                if float(val) == float(expected):\n                    match = True\n            except ValueError:\n                pass\n            if val == expected:\n                match = True\n        if match:\n            checks_passed += 1\n            feedback_parts.append(f\"PASS: {label} = '{val}' (expected '{expected}')\")\n        else:\n            feedback_parts.append(f\"FAIL: {label} = '{val}' (expected '{expected}')\")\n    \n    def check_text(row, col, expected, label):\n        nonlocal checks_passed\n        val = cell_str(row, col)\n        if val is not None and normalize_dash(val) == normalize_dash(expected):\n            checks_passed += 1\n            feedback_parts.append(f\"PASS: {label} = '{val}'\")\n        else:\n            feedback_parts.append(f\"FAIL: {label} = '{val}' (expected '{expected}')\")\n    \n    # O = column 15, P = column 16\n    \n    # Check O11 must be \"144\"\n    check_numeric(11, 15, \"144\", \"O11\")\n    \n    # Check P11 must be \"Quarantine - Tier 2 damage pending inspection (REC-20260414-002)\"\n    check_text(11, 16, \"Quarantine - Tier 2 damage pending inspection (REC-20260414-002)\", \"P11\")\n    \n    # Check O19 must be \"44\"\n    check_numeric(19, 15, \"44\", \"O19\")\n    \n    # Check P19 must be \"QUARANTINE \\u2014 missing COC (REC-20260414-001)\"\n    check_text(19, 16, \"QUARANTINE \\u2014 missing COC (REC-20260414-001)\", \"P19\")\n    \n    # Check O21 must be \"144\"\n    check_numeric(21, 15, \"144\", \"O21\")\n    \n    # Check P21 must be \"QUARANTINE \\u2014 Tier 2 damage pending inspection (REC-20260414-002)\"\n    check_text(21, 16, \"QUARANTINE \\u2014 Tier 2 damage pending inspection (REC-20260414-002)\", \"P21\")\n    \n    wb.close()\n    \n    score = checks_passed / total_checks\n    passed = checks_passed == total_checks\n    \n    summary = f\"{checks_passed}/{total_checks} checks passed. \" + \" | \".join(feedback_parts)\n    \n    return {\"pass\": passed, \"score\": score, \"feedback\": summary}\n",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "rubric_1776327435121",
    "sort_order": 11,
    "rubric_text": "In file `quarantine_releases/REC-20260414-001_release.pdf`, the content must include the following text: \"I've reviewed the COC submitted by Lakewood Precision Forgings this morning for the FG-91144-A1 line under REC-20260414-001.\", \"The COC is acceptable\", \"heat number HT-2026-1803 is confirmed and the documentation is complete.\", \"You are authorized to release FG-91144-A1 from Q-HOLD. Quantity: 200 units. Please proceed with the standard quarantine release procedure.\", and \"Theo Brandt\".",
    "verifier_code": "from pathlib import Path\nimport re\n\n\ndef verify(workspace_path, external_services_path=None):\n    \"\"\"\n    Verify that quarantine_releases/REC-20260414-001_release.pdf exists and\n    contains the required text phrases from the rubric.\n    \"\"\"\n    workspace_path = Path(workspace_path)\n    pdf_path = workspace_path / \"quarantine_releases\" / \"REC-20260414-001_release.pdf\"\n\n    if not pdf_path.exists():\n        return {\n            \"pass\": False,\n            \"score\": 0.0,\n            \"feedback\": f\"PDF file not found at {pdf_path}\",\n        }\n\n    # ---- Extract PDF text ----\n    pdf_text = \"\"\n    pdf_errors = []\n    try:\n        import pdfplumber\n        with pdfplumber.open(pdf_path) as pdf:\n            for page in pdf.pages:\n                t = page.extract_text()\n                if t:\n                    pdf_text += t + \"\\n\"\n    except Exception as e:\n        pdf_errors.append(f\"pdfplumber: {e}\")\n\n    if not pdf_text.strip():\n        try:\n            import PyPDF2\n            with open(pdf_path, \"rb\") as f:\n                reader = PyPDF2.PdfReader(f)\n                for page in reader.pages:\n                    t = page.extract_text()\n                    if t:\n                        pdf_text += t + \"\\n\"\n        except Exception as e:\n            pdf_errors.append(f\"PyPDF2: {e}\")\n\n    if not pdf_text.strip():\n        return {\n            \"pass\": False,\n            \"score\": 0.0,\n            \"feedback\": f\"Could not extract text from PDF at {pdf_path}. Errors: {pdf_errors}\",\n        }\n\n    # Normalize whitespace for matching (collapse all whitespace to single space)\n    pdf_text_normalized = re.sub(r\"\\s+\", \" \", pdf_text)\n\n    # ---- Required phrases from the rubric ----\n    required_phrases = [\n        \"I've reviewed the COC submitted by Lakewood Precision Forgings this morning for the FG-91144-A1 line under REC-20260414-001.\",\n        \"The COC is acceptable\",\n        \"heat number HT-2026-1803 is confirmed and the documentation is complete.\",\n        \"You are authorized to release FG-91144-A1 from Q-HOLD. Quantity: 200 units. Please proceed with the standard quarantine release procedure.\",\n        \"Theo Brandt\",\n    ]\n\n    found_phrases = []\n    missing_phrases = []\n\n    for phrase in required_phrases:\n        # Normalize the phrase the same way\n        phrase_normalized = re.sub(r\"\\s+\", \" \", phrase)\n        # Case-insensitive check\n        if phrase_normalized.lower() in pdf_text_normalized.lower():\n            found_phrases.append(phrase)\n        else:\n            # Try a more lenient check: compare significant words\n            # Extract words >= 3 chars from the phrase\n            phrase_words = [w.lower().strip(\".,;:!?()'\\\"\\u2014-\") for w in re.split(r\"\\s+\", phrase_normalized)]\n            phrase_words = [w for w in phrase_words if len(w) >= 3]\n            if phrase_words:\n                pdf_lower = pdf_text_normalized.lower()\n                words_found = sum(1 for w in phrase_words if w in pdf_lower)\n                ratio = words_found / len(phrase_words)\n                if ratio >= 0.9:\n                    found_phrases.append(phrase)\n                else:\n                    missing_phrases.append(f\"{phrase!r} (word match: {words_found}/{len(phrase_words)} = {ratio:.0%})\")\n            else:\n                missing_phrases.append(phrase)\n\n    total = len(required_phrases)\n    passed_count = len(found_phrases)\n    score = passed_count / total if total > 0 else 0.0\n    passed = passed_count == total\n\n    if passed:\n        feedback = (\n            f\"PDF at {pdf_path} contains all {total} required phrases. \"\n            f\"All checks passed.\"\n        )\n    else:\n        feedback = (\n            f\"PDF at {pdf_path} is missing {len(missing_phrases)}/{total} required phrases. \"\n            f\"Missing: {'; '.join(missing_phrases)}\"\n        )\n\n    return {\"pass\": passed, \"score\": score, \"feedback\": feedback}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "rubric_1776897621818",
    "sort_order": 12,
    "rubric_text": "In file `receiving_log.xlsx`, the Status column for rows 8 and 9 (cells AB8 and AB9) should contain the exact text \"Quarantined\".",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    file_path = Path(workspace_path) / \"receiving_log.xlsx\"\n    \n    if not file_path.exists():\n        return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"File 'receiving_log.xlsx' not found in workspace at {workspace_path}\"}\n    \n    try:\n        wb = openpyxl.load_workbook(str(file_path), data_only=True)\n        ws = wb.active\n    except Exception as e:\n        return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Error opening 'receiving_log.xlsx': {e}\"}\n    \n    results = {}\n    cells_to_check = {\"AB8\": 8, \"AB9\": 9}\n    \n    for cell_ref, row_num in cells_to_check.items():\n        cell_value = ws[cell_ref].value\n        if cell_value is not None:\n            cell_str = str(cell_value).strip()\n        else:\n            cell_str = None\n        results[cell_ref] = cell_str\n    \n    wb.close()\n    \n    passed = True\n    feedback_parts = []\n    \n    for cell_ref, actual_value in results.items():\n        if actual_value is not None and actual_value.lower() == \"quarantined\":\n            feedback_parts.append(f\"{cell_ref} = '{actual_value}' ✓\")\n        else:\n            passed = False\n            feedback_parts.append(f\"{cell_ref} = '{actual_value}' (expected 'Quarantined') ✗\")\n    \n    score = sum(1 for cell_ref, val in results.items() if val is not None and val.lower() == \"quarantined\") / len(cells_to_check)\n    \n    feedback = \"Checking receiving_log.xlsx cells AB8 and AB9 for 'Quarantined': \" + \"; \".join(feedback_parts)\n    \n    return {\"pass\": passed, \"score\": score, \"feedback\": feedback}\n",
    "criterion_type": "incorrect_behavior"
  }
]
