[
  {
    "id": "320d3875-c1d4-4b46-b2bf-916b3063a34f",
    "sort_order": 0,
    "rubric_text": "In file `Inventory_New_April2026.xlsx`, a row for stock N2049 must exist with VIN 5TFDY5F10RX904516, Year 2026, Make Toyota, Model Tundra, Trim SR5, In-Stock Date 04/15/2026 or 04/16/2026, Invoice Cost $34,600, Pack $500, Recon $0, Book Cost $35,100, Status indicating in stock, Floorplan Y, and FP Lender JM Family.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Inventory*New*April*.xlsx')) + list(Path(workspace_path).glob('*inventory*new*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Inventory*New*.xlsx')) + list(Path(workspace_path).glob('*inventory*new*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Inventory_New_April2026.xlsx file found in workspace'}\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    if 'n2049' not in row_joined and '5tfdy5f10rx904516' not in row_joined:\n                        continue\n                    \n                    checks = {}\n                    checks['vin'] = '5tfdy5f10rx904516' in row_joined\n                    checks['year'] = '2026' in row_joined\n                    checks['make'] = 'toyota' in row_joined\n                    checks['model'] = 'tundra' in row_joined\n                    checks['trim'] = 'sr5' in row_joined\n                    checks['instock_date'] = any(d in row_joined for d in ['04/15/2026', '04/16/2026', '2026-04-15', '2026-04-16', '4/15/2026', '4/16/2026'])\n                    checks['invoice_cost'] = any(abs(float(str(c).replace('$','').replace(',','').strip()) - 34600) <= 346 for c in row if str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() and abs(float(str(c).replace('$','').replace(',','').strip()) - 34600) <= 346) if any(str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() for c in row) else False\n                    checks['pack'] = any(abs(float(str(c).replace('$','').replace(',','').strip()) - 500) <= 5 for c in row if str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() and 490 <= float(str(c).replace('$','').replace(',','').strip()) <= 510) if True else False\n                    checks['book_cost'] = any(abs(float(str(c).replace('$','').replace(',','').strip()) - 35100) <= 351 for c in row if str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() and abs(float(str(c).replace('$','').replace(',','').strip()) - 35100) <= 351) if True else False\n                    checks['floorplan'] = any(str(c).strip().upper() in ['Y', 'YES', 'TRUE', '1'] for c in row)\n                    checks['lender'] = 'jm family' in row_joined\n                    checks['status'] = any(s in row_joined for s in ['in stock', 'instock', 'available', 'active'])\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'Found N2049 row in {xlsx_file.name} with all required fields.'}\n        except Exception as e:\n            continue\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'Could not find a valid N2049 row with required fields in any Inventory_New file. Files checked: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "76ccb981-4201-48d2-bd20-35954e66976a",
    "sort_order": 1,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, a row for stock N2049 must exist with VIN 5TFDY5F10RX904516, Vehicle 2026 Toyota Tundra SR5, Lender JM Family Enterprises, Advance Date 04/15/2026, Principal Balance $34,600, Status Active or In Stock, and Lot Status On lot.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found in workspace'}\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    if 'n2049' not in row_joined and '5tfdy5f10rx904516' not in row_joined:\n                        continue\n                    \n                    checks = {}\n                    checks['vin'] = '5tfdy5f10rx904516' in row_joined\n                    checks['vehicle'] = 'tundra' in row_joined and 'toyota' in row_joined\n                    checks['lender'] = 'jm family' in row_joined\n                    checks['advance_date'] = any(d in row_joined for d in ['04/15/2026', '2026-04-15', '4/15/2026'])\n                    checks['principal'] = any(abs(float(str(c).replace('$','').replace(',','').strip()) - 34600) <= 346 for c in row if str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() and abs(float(str(c).replace('$','').replace(',','').strip()) - 34600) <= 346)\n                    checks['status'] = any(s in row_joined for s in ['active', 'in stock', 'instock'])\n                    checks['lot'] = 'on lot' in row_joined or 'on-lot' in row_joined\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'Found N2049 row in floorplan worksheet with all required fields.'}\n        except Exception as e:\n            continue\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'Could not find a valid N2049 row in any Floorplan Worksheet file. Files checked: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "d023b7df-8326-43e9-a05e-1ca77d492d30",
    "sort_order": 2,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, a row for stock N2043 must exist with VIN 5TDJZRAH0RS504505, Vehicle 2026 Toyota Highlander XLE, Lender JM Family Enterprises, Advance Date 04/02/2026, Principal Balance $40,100, Status Active or Reinstated, Lot Status On lot, and notes indicating the unit was reinstated following Deal 4505 unwind.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    if 'n2043' not in row_joined and '5tdjzrah0rs504505' not in row_joined:\n                        continue\n                    \n                    checks = {}\n                    checks['vin'] = '5tdjzrah0rs504505' in row_joined\n                    checks['vehicle'] = 'highlander' in row_joined and 'toyota' in row_joined\n                    checks['lender'] = 'jm family' in row_joined\n                    checks['advance_date'] = any(d in row_joined for d in ['04/02/2026', '2026-04-02', '4/2/2026', '4/02/2026'])\n                    checks['principal'] = any(abs(float(str(c).replace('$','').replace(',','').strip()) - 40100) <= 401 for c in row if str(c).replace('$','').replace(',','').strip().replace('.','',1).isdigit() and abs(float(str(c).replace('$','').replace(',','').strip()) - 40100) <= 401)\n                    checks['status'] = any(s in row_joined for s in ['active', 'reinstated', 'in stock'])\n                    checks['lot'] = 'on lot' in row_joined or 'on-lot' in row_joined\n                    checks['unwind'] = any(s in row_joined for s in ['unwind', '4505', 'reinstated'])\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'Found N2043 reinstated row in floorplan worksheet with all required fields.'}\n        except Exception as e:\n            continue\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'Could not find a valid N2043 reinstated row in floorplan worksheet. Files checked: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "f180bd7d-137e-42dd-b929-788dbe67ee51",
    "sort_order": 3,
    "rubric_text": "In file Inventory_New_April2026.xlsx, stock N2043 must retain its original values unchanged: Invoice Cost $40,100, Pack $500, Book Cost $40,600, Floorplan Y, and status indicating the vehicle is back in stock. The model must not overwrite, remove, or alter this pre-existing row during reconciliation.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    # Search broadly for inventory new files\n    workspace = Path(workspace_path)\n    xlsx_files = []\n    for pattern in [\n        '*Inventory*New*April*.xlsx',\n        '*inventory*new*april*.xlsx',\n        '*Inventory*New*.xlsx',\n        '*inventory*new*.xlsx',\n        '*Inventory*.xlsx',\n        '*inventory*.xlsx',\n    ]:\n        xlsx_files.extend(workspace.glob(pattern))\n    # Also search subdirectories\n    for pattern in [\n        '**/*Inventory*New*April*.xlsx',\n        '**/*inventory*new*april*.xlsx',\n        '**/*Inventory*New*.xlsx',\n        '**/*inventory*new*.xlsx',\n    ]:\n        xlsx_files.extend(workspace.glob(pattern))\n    # Deduplicate\n    xlsx_files = list(set(xlsx_files))\n    \n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Inventory_New_April2026.xlsx (or similarly named) file found in workspace.'}\n    \n    all_feedback = []\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row_idx, row in enumerate(rows[1:], start=2):\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    # Look for N2043 by stock number or VIN\n                    if 'n2043' not in row_joined and '5tdjzrah0rs504505' not in row_joined:\n                        continue\n                    \n                    # Found the row for N2043\n                    numeric_vals = []\n                    for c in row:\n                        if c is None:\n                            continue\n                        try:\n                            v = float(str(c).replace('$', '').replace(',', '').strip())\n                            numeric_vals.append(v)\n                        except:\n                            pass\n                    \n                    checks = {}\n                    details = {}\n                    \n                    # Invoice Cost ~$40,100 (±1%)\n                    checks['invoice_cost'] = any(abs(v - 40100) <= 401 for v in numeric_vals)\n                    details['invoice_cost'] = [v for v in numeric_vals if abs(v - 40100) <= 5000]\n                    \n                    # Book Cost ~$40,600 (±1%)\n                    checks['book_cost'] = any(abs(v - 40600) <= 406 for v in numeric_vals)\n                    details['book_cost'] = [v for v in numeric_vals if abs(v - 40600) <= 5000]\n                    \n                    # Pack ~$500 (±1%)\n                    checks['pack'] = any(abs(v - 500) <= 50 for v in numeric_vals)\n                    details['pack'] = [v for v in numeric_vals if abs(v - 500) <= 200]\n                    \n                    # Floorplan Y\n                    checks['floorplan'] = any(str(c).strip().upper() in ['Y', 'YES', 'TRUE', '1'] for c in row if c is not None)\n                    \n                    # Status indicating back in stock\n                    checks['status'] = any(s in row_joined for s in ['in stock', 'instock', 'available', 'active', 'back in stock', 'reinstated', 'returned'])\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {\n                            'pass': True,\n                            'score': 1.0,\n                            'feedback': f'Found N2043 in {xlsx_file.name}, sheet \"{sheet_name}\", row {row_idx} with all required fields intact: Invoice Cost ~$40,100, Pack ~$500, Book Cost ~$40,600, Floorplan=Y, status=in stock. Numeric values found: {numeric_vals}. Row data: {row_str}'\n                        }\n                    else:\n                        all_feedback.append(\n                            f'Found N2043 in {xlsx_file.name}, sheet \"{sheet_name}\", row {row_idx}, but failed checks: {failed}. '\n                            f'Numeric values found: {numeric_vals}. Row data: {row_str}. '\n                            f'Check details - invoice_cost candidates: {details.get(\"invoice_cost\", [])}, '\n                            f'book_cost candidates: {details.get(\"book_cost\", [])}, '\n                            f'pack candidates: {details.get(\"pack\", [])}'\n                        )\n        except Exception as e:\n            all_feedback.append(f'Error reading {xlsx_file.name}: {str(e)}')\n            continue\n    \n    if all_feedback:\n        return {\n            'pass': False,\n            'score': 0.0,\n            'feedback': 'N2043 found but did not pass all checks. ' + ' | '.join(all_feedback)\n        }\n    \n    return {\n        'pass': False,\n        'score': 0.0,\n        'feedback': f'Could not find N2043 row in any Inventory_New file. Files checked: {[f.name for f in xlsx_files]}'\n    }\n",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "9bc87fa7-8634-4a54-a1a5-6023d52275f7",
    "sort_order": 4,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, the worksheet must contain exactly 10 units (N2041, N2043, N2046, N2047, N2048, N2049, U1087, U1090, U1092, U1093) matching the JM Family Enterprises statement, and the sum of all principal balances must equal $319,750 within a $100 tolerance.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n\n    required_stocks = {'n2041', 'n2043', 'n2046', 'n2047', 'n2048', 'n2049', 'u1087', 'u1090', 'u1092', 'u1093'}\n    expected_total = 319750\n\n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n\n                # Detect the Principal Balance column from the header row\n                header = [str(c).strip().lower() if c is not None else '' for c in rows[0]]\n                principal_col = None\n                for idx, col_name in enumerate(header):\n                    if 'principal' in col_name and 'balance' in col_name:\n                        principal_col = idx\n                        break\n                if principal_col is None:\n                    for idx, col_name in enumerate(header):\n                        if 'principal' in col_name or col_name in ('balance', 'fp balance', 'floorplan balance'):\n                            principal_col = idx\n                            break\n\n                found_stocks = set()\n                principal_total = 0.0\n\n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n\n                    for stock in required_stocks:\n                        if stock in row_joined:\n                            found_stocks.add(stock)\n                            # Extract principal from the identified column first\n                            extracted = False\n                            if principal_col is not None and principal_col < len(row):\n                                cell = row[principal_col]\n                                try:\n                                    v = float(str(cell).replace('$', '').replace(',', '').strip())\n                                    if v > 0:\n                                        principal_total += v\n                                        extracted = True\n                                except (ValueError, TypeError):\n                                    pass\n                            # Fallback: scan for a value in 10k-100k range\n                            if not extracted:\n                                for c in row:\n                                    try:\n                                        v = float(str(c).replace('$', '').replace(',', '').strip())\n                                        if 10000 <= v <= 100000:\n                                            principal_total += v\n                                            break\n                                    except (ValueError, TypeError):\n                                        pass\n\n                missing = required_stocks - found_stocks\n                total_diff = abs(principal_total - expected_total)\n\n                if len(missing) == 0 and total_diff <= 100:\n                    return {\n                        'pass': True,\n                        'score': 1.0,\n                        'feedback': f'Found {len(found_stocks)}/10 required stocks in {xlsx_file.name}. Total: ${principal_total:,.0f} vs expected ${expected_total:,}.'\n                    }\n        except Exception as e:\n            continue\n\n    return {'pass': False, 'score': 0.0, 'feedback': f'Floorplan worksheet does not contain all 10 required units or total does not match $319,750. Files: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "4e6e2fd8-4ad9-46c6-a1e5-fe07f75094ad",
    "sort_order": 5,
    "rubric_text": "In file Floorplan_Worksheet_April2026.xlsx, the N2048 row's Notes or Status field must be updated to include ALL of the following: (1) the phrase 'aged curtailment' or 'curtailment past due' explicitly indicating this is an aged curtailment per SOP 5.6, (2) the curtailment due date 02/11/2026, (3) the number of days the curtailment is past due (64+), (4) language indicating immediate escalation is required (e.g., 'immediate escalation', 'escalated to Marcus/Elena', 'requires immediate action'). Note: the 94 days on floor and $48,200 principal are pre-existing in the row and must not be altered.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n\n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n\n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n\n                    if 'n2048' not in row_joined:\n                        continue\n\n                    checks = {}\n\n                    # (1) Must use \"aged curtailment\" or \"curtailment past due\" language\n                    checks['aged_curtailment_phrase'] = 'aged curtailment' in row_joined  # mandated by Rules tab template\n\n                    # (2) Must reference curtailment due date 02/11/2026\n                    checks['curtailment_date'] = any(d in row_joined for d in [\n                        '02/11/2026', '2026-02-11', '2/11/2026', '02/11'\n                    ])\n\n                    # (3) Must state days past due (64+)\n                    checks['days_past_due'] = 'days past due' in row_joined\n\n                    # (4) Must indicate escalation action\n                    checks['escalation'] = 'escalated to marcus hale and elena brooks' in row_joined  # mandated by Rules tab template\n\n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {\n                            'pass': True,\n                            'score': 1.0,\n                            'feedback': f'N2048 row in {xlsx_file.name} has aged curtailment escalation with all 4 required elements.'\n                        }\n        except Exception as e:\n            continue\n\n    return {\n        'pass': False,\n        'score': 0.0,\n        'feedback': f'N2048 row not found or missing required aged curtailment annotation. Files: {[f.name for f in xlsx_files]}'\n    }",
    "criterion_type": "expected_output"
  },
  {
    "id": "483ccd6d-c64d-4134-82f4-31e3e54e1190",
    "sort_order": 6,
    "rubric_text": "A sent email must exist addressed to both marcus.hale@sunshineandsetauto.com and elena.brooks@sunshineandsetauto.com identifying N2048 as an aged curtailment per SOP §5.6 email template, with principal balance $48,200, curtailment due date 02/11/2026, days past due (64+), and days on floor (94).",
    "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 email'}\n\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'}\n\n    with open(mailbox_path) as f:\n        data = json.load(f)\n\n    sent_emails = [e for e in data.get('emails', []) if e.get('folder', '').lower() == 'sent']\n    marcus = 'marcus.hale@sunshineandsetauto.com'\n    elena  = 'elena.brooks@sunshineandsetauto.com'\n\n    for email in sent_emails:\n        to_addr  = str(email.get('to_addr', '') or '').lower()\n        cc_addr  = str(email.get('cc_addr', '') or '').lower()\n        all_recipients = to_addr + ' ' + cc_addr\n\n        if marcus not in all_recipients or elena not in all_recipients:\n            continue\n\n        body      = str(email.get('body_text', '') or '').lower()\n        subject   = str(email.get('subject',   '') or '').lower()\n        full_text = subject + ' ' + body\n        normalized = full_text.replace(',', '').replace('$', '')\n\n        checks = {}\n        checks['n2048']             = 'n2048' in full_text\n        checks['aged_curtailment']  = 'aged curtailment' in full_text          # mandated by SOP §5.6 email template\n        checks['principal_balance'] = 'principal balance' in full_text         # mandated by SOP §5.6 email template\n        checks['balance_amount']    = '48200' in normalized                    # filled-in value from template\n        checks['date']              = '02/11/2026' in full_text or '02/11' in full_text\n        checks['days_past_due']     = 'days past due' in full_text             # mandated by SOP §5.6 email template\n        checks['days_on_floor']     = 'days on floor' in full_text             # mandated by SOP §5.6 email template\n\n        failed = [k for k, v in checks.items() if not v]\n        if not failed:\n            return {'pass': True, 'score': 1.0, 'feedback': 'Found N2048 aged curtailment escalation email to Marcus and Elena with all required details.'}\n\n    return {'pass': False, 'score': 0.0, 'feedback': f'No valid N2048 aged curtailment email to both marcus.hale and elena.brooks found. {len(sent_emails)} sent emails checked.'}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "f634d74f-75f1-4d1e-84ba-a6b9708d45ac",
    "sort_order": 7,
    "rubric_text": "A Slack message must exist in channel C010 (#acct-floorplan) identifying N2048 as an aged curtailment with stock number N2048, days on floor (94), curtailment past due since 02/11/2026, and mentioning Marcus Hale and Elena Brooks.",
    "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 Slack'}\n    \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'}\n    \n    with open(slack_path) as f:\n        data = json.load(f)\n    \n    # Check channel C010\n    channel_messages = data.get('messages', {}).get('C010', [])\n    \n    if not channel_messages:\n        channels = data.get('channels', {})\n        for ch_id, ch_info in channels.items():\n            if 'acct-floorplan' in ch_info.get('name', '').lower() or 'floorplan' in ch_info.get('name', '').lower():\n                channel_messages = data.get('messages', {}).get(ch_id, [])\n                break\n    \n    if not channel_messages:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No messages found in channel C010 (#acct-floorplan)'}\n    \n    for msg in channel_messages:\n        text = str(msg.get('text', '')).lower()\n        \n        checks = {}\n        checks['n2048'] = 'n2048' in text\n        checks['curtailment'] = 'aged curtailment' in text\n        checks['days_on_floor'] = '94' in text\n        checks['date'] = any(d in text for d in ['02/11/2026', '2/11/2026', '02/11', 'february 11'])\n        checks['marcus'] = any(m in text for m in ['marcus', '@marcus', 'hale'])\n        checks['elena'] = any(e in text for e in ['elena', '@elena', 'brooks'])\n        \n        failed = [k for k, v in checks.items() if not v]\n        if len(failed) == 0:\n            return {'pass': True, 'score': 1.0, 'feedback': f'Found N2048 aged curtailment Slack message in C010 with all required details.'}\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'No Slack message in C010 with N2048 aged curtailment details (94 days, 02/11/2026, Marcus/Elena tags). {len(channel_messages)} messages checked.'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "61995f74-10c4-458f-86d8-2b07f3538069",
    "sort_order": 8,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, the N2041 row must indicate the unit is sold (Deal 4501, Robert Chen, deal date 03/31/2026), floorplan not yet paid off, late payoff interest of $185, payoff deadline 04/03/2026 exceeded, and the number of business days past due noted.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    if 'n2041' not in row_joined:\n                        continue\n                    \n                    checks = {}\n                    checks['sold'] = any(s in row_joined for s in ['sold', 'deal 4501', '4501'])\n                    checks['payoff_not_sent'] = 'payoff not sent' in row_joined  # mandated by Rules tab template\n                    checks['late_interest'] = '185' in row_joined\n                    checks['deadline'] = '3-business-day deadline' in row_joined or '04/03' in row_joined\n                    checks['days_past_due'] = 'business days past due' in row_joined  # mandated by Rules tab template\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'Found N2041 sold-not-paid row in {xlsx_file.name} with all required details.'}\n        except Exception as e:\n            continue\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'N2041 row not found or missing sold/late payoff details in floorplan worksheet. Files: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "1a7adc64-4ead-4905-b0d0-811c4bb50674",
    "sort_order": 9,
    "rubric_text": "A sent email must exist addressed to both marcus.hale@sunshineandsetauto.com and elena.brooks@sunshineandsetauto.com identifying N2041 as sold-not-paid per SOP section 5.6 email template, with Deal 4501, customer Robert Chen, payoff not sent, business days past due, late payoff interest of $185 per lender statement, AND concurrent collection issue notation including '$2,000' and 'NSF'.",
    "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 email'}\n\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'}\n\n    with open(mailbox_path) as f:\n        data = json.load(f)\n\n    sent_emails = [e for e in data.get('emails', []) if e.get('folder', '').lower() == 'sent']\n    marcus = 'marcus.hale@sunshineandsetauto.com'\n    elena  = 'elena.brooks@sunshineandsetauto.com'\n\n    for email in sent_emails:\n        to_addr  = str(email.get('to_addr', '') or '').lower()\n        cc_addr  = str(email.get('cc_addr', '') or '').lower()\n        all_recipients = to_addr + ' ' + cc_addr\n\n        if marcus not in all_recipients or elena not in all_recipients:\n            continue\n\n        body      = str(email.get('body_text', '') or '').lower()\n        subject   = str(email.get('subject',   '') or '').lower()\n        full_text = subject + ' ' + body\n\n        checks = {}\n        checks['n2041']              = 'n2041' in full_text\n        checks['sold_not_paid']      = 'sold-not-paid' in full_text            # mandated by SOP §5.6 email template\n        checks['payoff_not_sent']    = 'payoff not sent' in full_text          # mandated by SOP §5.6 email template\n        checks['deal_4501']          = '4501' in full_text\n        checks['robert_chen']        = 'robert chen' in full_text              # mandated by SOP §5.6 email template ([Customer Name])\n        checks['late_payoff_interest'] = 'late payoff interest' in full_text   # mandated by SOP §5.6 email template\n        checks['interest_amount']    = '185' in full_text                      # filled-in value from template\n        checks['business_days_past_due'] = 'business days past due' in full_text  # mandated by SOP §5.6 email template\n        checks['nsf_concurrent'] = any(s in full_text for s in ['concurrent collection', 'nsf', 'returned check']) and '2000' in full_text.replace(',', '')\n\n        failed = [k for k, v in checks.items() if not v]\n        if not failed:\n            return {'pass': True, 'score': 1.0, 'feedback': 'Found N2041 sold-not-paid escalation email to Marcus and Elena with all required details.'}\n\n    return {'pass': False, 'score': 0.0, 'feedback': f'No valid N2041 sold-not-paid email to both marcus.hale and elena.brooks found. {len(sent_emails)} sent emails checked.'}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "57304183-b7ac-4259-8f1e-1996b8ada7d1",
    "sort_order": 10,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, the U1087 row must reflect that the floorplan payoff has been confirmed received by the lender as of 04/10/2026, with status or notes indicating payoff complete or payoff confirmed by lender.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                for row in rows[1:]:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    if 'u1087' not in row_joined:\n                        continue\n                    \n                    has_confirmed = 'payoff confirmed by lender' in row_joined  # mandated by Rules tab template\n                    \n                    if has_confirmed:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'U1087 row in {xlsx_file.name} indicates payoff confirmed/complete.'}\n        except Exception as e:\n            continue\n    \n    return {'pass': False, 'score': 0.0, 'feedback': f'U1087 row not found or missing payoff confirmed status in floorplan worksheet. Files: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  },
  {
    "id": "27f91841-bc91-49c5-8d5c-67d642ca7987",
    "sort_order": 11,
    "rubric_text": "A sent email must exist addressed to marcus.hale@sunshineandsetauto.com in reply to his daily floorplan reconciliation request, confirming the reconciliation has been completed.",
    "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 email'}\n\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'}\n\n    with open(mailbox_path) as f:\n        data = json.load(f)\n\n    sent_emails = [e for e in data.get('emails', []) if e.get('folder', '').lower() == 'sent']\n    marcus = 'marcus.hale@sunshineandsetauto.com'\n\n    for email in sent_emails:\n        to_addr = str(email.get('to_addr', '') or '').lower()\n        cc_addr = str(email.get('cc_addr', '') or '').lower()\n        all_recipients = to_addr + ' ' + cc_addr\n\n        if marcus not in all_recipients:\n            continue\n\n        body = str(email.get('body_text', '') or '').lower()\n        subject = str(email.get('subject', '') or '').lower()\n        full_text = subject + ' ' + body\n\n        if any(s in full_text for s in ['floorplan', 'floor plan', 'reconcil']):\n            return {'pass': True, 'score': 1.0, 'feedback': 'Found sent email to Marcus Hale about floorplan reconciliation.'}\n\n    return {'pass': False, 'score': 0.0, 'feedback': f'No sent email to marcus.hale found about floorplan reconciliation. {len(sent_emails)} sent emails checked.'}\n",
    "criterion_type": "expected_output"
  },
  {
    "id": "8d7fe74b-b6c4-4fe1-93e4-0b1867bb1f7c",
    "sort_order": 12,
    "rubric_text": "In file Inventory_Used_April2026.xlsx, stock U1093 (2022 BMW 330i) must retain its pre-existing Recon of $2,800 and Book Cost of $33,050 (ACV $29,500 + Pack $750 + Recon $2,800). The model must not double-post Invoice SBP-4812 or otherwise alter these values during reconciliation.",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    # Search broadly for inventory used files\n    ws_path = Path(workspace_path)\n    xlsx_files = []\n    for f in ws_path.rglob('*.xlsx'):\n        fname_lower = f.name.lower()\n        if 'inventory' in fname_lower and 'used' in fname_lower:\n            xlsx_files.append(f)\n    \n    if not xlsx_files:\n        # Even broader search\n        xlsx_files = list(ws_path.rglob('*.xlsx'))\n    \n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No .xlsx files found in workspace'}\n    \n    found_u1093 = False\n    details = []\n    \n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            for sheet_name in wb.sheetnames:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n                \n                # Try to find header row to identify columns\n                header_row = None\n                header_idx = -1\n                for idx, row in enumerate(rows):\n                    row_str = ' '.join([str(c).strip().lower() if c is not None else '' for c in row])\n                    if 'stock' in row_str or 'recon' in row_str or 'book' in row_str or 'acv' in row_str:\n                        header_row = row\n                        header_idx = idx\n                        break\n                \n                # Find column indices if we have headers\n                recon_col = None\n                book_cost_col = None\n                acv_col = None\n                pack_col = None\n                if header_row:\n                    for ci, cell in enumerate(header_row):\n                        if cell is not None:\n                            cell_lower = str(cell).strip().lower()\n                            if 'recon' in cell_lower:\n                                recon_col = ci\n                            elif 'book' in cell_lower and ('cost' in cell_lower or 'value' in cell_lower):\n                                book_cost_col = ci\n                            elif 'book cost' in cell_lower:\n                                book_cost_col = ci\n                            elif cell_lower == 'acv' or 'acv' in cell_lower:\n                                acv_col = ci\n                            elif 'pack' in cell_lower:\n                                pack_col = ci\n                \n                for row in rows:\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n                    \n                    # Check if this row is about U1093 or 2022 BMW 330i\n                    is_u1093 = 'u1093' in row_joined\n                    is_bmw_330i = 'bmw' in row_joined and '330i' in row_joined\n                    \n                    if not is_u1093 and not is_bmw_330i:\n                        continue\n                    \n                    found_u1093 = True\n                    \n                    # Gather all numeric values from row\n                    numeric_vals = []\n                    for c in row:\n                        if c is not None:\n                            try:\n                                v = float(str(c).replace('$', '').replace(',', '').strip())\n                                numeric_vals.append(v)\n                            except:\n                                pass\n                    \n                    # Check specific columns if available, otherwise check all numeric values\n                    recon_ok = False\n                    book_cost_ok = False\n                    acv_ok = False\n                    \n                    actual_recon = None\n                    actual_book = None\n                    actual_acv = None\n                    \n                    # Try column-based checking first\n                    if recon_col is not None and recon_col < len(row):\n                        try:\n                            val = float(str(row[recon_col]).replace('$', '').replace(',', '').strip())\n                            actual_recon = val\n                            if abs(val - 2800) <= 100:  # ~3.5% tolerance\n                                recon_ok = True\n                        except:\n                            pass\n                    \n                    if book_cost_col is not None and book_cost_col < len(row):\n                        try:\n                            val = float(str(row[book_cost_col]).replace('$', '').replace(',', '').strip())\n                            actual_book = val\n                            if abs(val - 33050) <= 500:  # ~1.5% tolerance\n                                book_cost_ok = True\n                        except:\n                            pass\n                    \n                    if acv_col is not None and acv_col < len(row):\n                        try:\n                            val = float(str(row[acv_col]).replace('$', '').replace(',', '').strip())\n                            actual_acv = val\n                            if abs(val - 29500) <= 500:  # ~1.7% tolerance\n                                acv_ok = True\n                        except:\n                            pass\n                    \n                    # Fall back to scanning all numeric values\n                    if not recon_ok:\n                        for v in numeric_vals:\n                            if abs(v - 2800) <= 100:\n                                recon_ok = True\n                                if actual_recon is None:\n                                    actual_recon = v\n                                break\n                    \n                    if not book_cost_ok:\n                        for v in numeric_vals:\n                            if abs(v - 33050) <= 500:\n                                book_cost_ok = True\n                                if actual_book is None:\n                                    actual_book = v\n                                break\n                    \n                    if not acv_ok:\n                        for v in numeric_vals:\n                            if abs(v - 29500) <= 500:\n                                acv_ok = True\n                                if actual_acv is None:\n                                    actual_acv = v\n                                break\n                    \n                    # Also check for double-posting: recon should NOT be ~5600 (doubled)\n                    double_recon = any(abs(v - 5600) <= 200 for v in numeric_vals)\n                    double_book = any(abs(v - 35850) <= 500 for v in numeric_vals)\n                    \n                    if double_recon or double_book:\n                        return {\n                            'pass': False,\n                            'score': 0.0,\n                            'feedback': f'U1093 appears to have been double-posted (Invoice SBP-4812 applied twice). '\n                                       f'Found suspicious values suggesting doubled recon (~5600) or inflated book cost (~35850). '\n                                       f'Numeric values in row: {numeric_vals}. File: {xlsx_file.name}, Sheet: {sheet_name}'\n                        }\n                    \n                    checks = {\n                        'Recon ~$2,800': recon_ok,\n                        'Book Cost ~$33,050': book_cost_ok,\n                        'ACV ~$29,500': acv_ok\n                    }\n                    \n                    failed = [k for k, v in checks.items() if not v]\n                    \n                    if len(failed) <= 1 and recon_ok and book_cost_ok:\n                        # Primary requirement is recon and book cost; ACV is supporting info\n                        return {\n                            'pass': True,\n                            'score': 1.0,\n                            'feedback': f'U1093 (2022 BMW 330i) found in {xlsx_file.name}, sheet \"{sheet_name}\" '\n                                       f'with correct values: Recon={actual_recon}, Book Cost={actual_book}, ACV={actual_acv}. '\n                                       f'No double-posting of Invoice SBP-4812 detected.'\n                        }\n                    else:\n                        details.append(\n                            f'U1093 found in {xlsx_file.name}, sheet \"{sheet_name}\" but checks failed: {failed}. '\n                            f'Actual recon={actual_recon}, book_cost={actual_book}, acv={actual_acv}. '\n                            f'Numeric values: {numeric_vals}'\n                        )\n        except Exception as e:\n            details.append(f'Error reading {xlsx_file.name}: {str(e)}')\n            continue\n    \n    if not found_u1093:\n        return {\n            'pass': False,\n            'score': 0.0,\n            'feedback': f'Could not find stock U1093 (2022 BMW 330i) in any Inventory Used file. '\n                       f'Files checked: {[f.name for f in xlsx_files]}'\n        }\n    \n    return {\n        'pass': False,\n        'score': 0.0,\n        'feedback': f'Found U1093 but values do not match expected Recon=$2,800 and Book Cost=$33,050. '\n                   f'Details: {\" | \".join(details)}'\n    }\n",
    "criterion_type": "incorrect_behavior"
  },
  {
    "id": "rubric_1776285892379",
    "sort_order": 13,
    "rubric_text": "A Slack message must exist in channel C010 (#acct-floorplan) identifying N2041 as a sold-not-paid unit: stock number N2041, Deal 4501, sold but floorplan payoff not sent, mentioning or tagging Marcus Hale and Elena Brooks, AND including concurrent collection issue notation referencing '$2,000' and 'NSF'.",
    "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 Slack'}\n\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'}\n\n    with open(slack_path) as f:\n        data = json.load(f)\n\n    channel_messages = data.get('messages', {}).get('C010', [])\n\n    if not channel_messages:\n        channels = data.get('channels', {})\n        for ch_id, ch_info in channels.items():\n            if 'floorplan' in ch_info.get('name', '').lower():\n                channel_messages = data.get('messages', {}).get(ch_id, [])\n                break\n\n    if not channel_messages:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No messages found in channel C010 (#acct-floorplan)'}\n\n    for msg in channel_messages:\n        text = str(msg.get('text', '')).lower()\n\n        checks = {}\n        checks['n2041'] = 'n2041' in text\n        checks['sold_not_paid'] = 'sold-not-paid' in text  # mandated by SOP §5.6 Template FP-2\n        checks['deal_4501'] = '4501' in text\n        checks['marcus'] = any(m in text for m in ['marcus', '@marcus', 'hale', '<@u002>'])\n        checks['elena'] = any(e in text for e in ['elena', '@elena', 'brooks', '<@u001>'])\n        checks['nsf_concurrent'] = any(s in text for s in ['concurrent collection', 'nsf', 'returned check']) and '2000' in text.replace(',', '')\n\n        failed = [k for k, v in checks.items() if not v]\n        if len(failed) == 0:\n            return {\n                'pass': True,\n                'score': 1.0,\n                'feedback': 'Found N2041 sold-not-paid Slack message in C010 with all required details.'\n            }\n\n    return {\n        'pass': False,\n        'score': 0.0,\n        'feedback': f'No Slack message in C010 with N2041 sold-not-paid details (Deal 4501, Marcus/Elena tags). {len(channel_messages)} messages checked.'\n    }",
    "criterion_type": "expected_output"
  },
  {
    "id": "R15_exception_log_entry",
    "sort_order": 14,
    "rubric_text": "In file `Floorplan_Worksheet_April2026.xlsx`, the Exception Log sheet must contain an entry for stock N2041 documenting the five required facts per §9.3: deal number 4501, customer Robert Chen, stock N2041 or VIN 4T1G11AK6RU304501, variance amount referencing $28,250 or $185, source document referencing JM Family Enterprises lender statement, and a source classification of Accounting Error (not Timing, Data Entry, or Missing Document).",
    "verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n    xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*April*.xlsx')) + list(Path(workspace_path).glob('*floorplan*worksheet*april*.xlsx'))\n    if not xlsx_files:\n        xlsx_files = list(Path(workspace_path).glob('*Floorplan*Worksheet*.xlsx')) + list(Path(workspace_path).glob('*floorplan*.xlsx'))\n    if not xlsx_files:\n        return {'pass': False, 'score': 0.0, 'feedback': 'No Floorplan_Worksheet_April2026.xlsx file found'}\n\n    all_feedback = []\n    for xlsx_file in xlsx_files:\n        try:\n            wb = openpyxl.load_workbook(xlsx_file, data_only=True)\n            exception_sheets = [s for s in wb.sheetnames if 'exception' in s.lower() or 'discrepancy' in s.lower() or 'resolution' in s.lower()]\n            if not exception_sheets:\n                all_feedback.append(f'{xlsx_file.name}: no Exception Log sheet found (sheets: {wb.sheetnames})')\n                continue\n\n            for sheet_name in exception_sheets:\n                ws = wb[sheet_name]\n                rows = list(ws.iter_rows(values_only=True))\n                if not rows:\n                    continue\n\n                for row_idx, row in enumerate(rows[1:], start=2):\n                    row_str = [str(c).strip() if c is not None else '' for c in row]\n                    row_joined = ' '.join(row_str).lower()\n\n                    if 'n2041' not in row_joined and '4t1g11ak6ru304501' not in row_joined:\n                        continue\n\n                    checks = {}\n                    checks['deal_number'] = '4501' in row_joined\n                    checks['customer'] = 'robert chen' in row_joined or 'chen' in row_joined\n                    checks['stock_or_vin'] = 'n2041' in row_joined or '4t1g11ak6ru304501' in row_joined\n                    normalized = row_joined.replace(',', '').replace('$', '').replace(' ', '')\n                    checks['variance_amount'] = '28250' in normalized or '185' in row_joined\n                    checks['source_document'] = 'jm family' in row_joined or 'lender statement' in row_joined\n                    checks['classification'] = 'accounting error' in row_joined\n\n                    failed = [k for k, v in checks.items() if not v]\n                    if len(failed) == 0:\n                        return {'pass': True, 'score': 1.0, 'feedback': f'Found N2041 discrepancy resolution entry in {xlsx_file.name}, sheet \"{sheet_name}\", row {row_idx} with all five required facts and Accounting Error classification.'}\n                    else:\n                        all_feedback.append(f'N2041 entry found in {xlsx_file.name} sheet \"{sheet_name}\" row {row_idx} but failed: {failed}. Row: {row_str}')\n        except Exception as e:\n            all_feedback.append(f'Error reading {xlsx_file.name}: {str(e)}')\n            continue\n\n    if all_feedback:\n        return {'pass': False, 'score': 0.0, 'feedback': 'N2041 entry found but incomplete. ' + ' | '.join(all_feedback)}\n    return {'pass': False, 'score': 0.0, 'feedback': f'No N2041 discrepancy resolution entry found in any Exception Log sheet. Files checked: {[f.name for f in xlsx_files]}'}",
    "criterion_type": "expected_output"
  }
]
