Files
handbook/tasks/hr_crestwood_university_da394eac/tests/rubrics.json
T
2026-06-29 10:08:59 -07:00

143 lines
48 KiB
JSON
Raw 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.
[
{
"id": "e9e30a9b-fdae-4d1a-b35a-bce846762f57",
"sort_order": 0,
"rubric_text": "In `mailbox.json`, no sent emails must exist with `to_addr` set to `facilities@crestwood.edu`",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n violations = [e for e in emails if e.get(\"folder\", \"\").lower() == \"sent\" and \"facilities@crestwood.edu\" in str(e.get(\"to_addr\", \"\")).lower()]\n if violations:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Found {len(violations)} sent email(s) to facilities@crestwood.edu, expected none.\"}\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"No sent emails to facilities@crestwood.edu found.\"}",
"criterion_type": "incorrect_behavior"
},
{
"id": "e7bfa402-fa2a-4fc5-bdf6-b5099fa59d0a",
"sort_order": 1,
"rubric_text": "In `mailbox.json`, the email from `facilities@crestwood.edu` must be in the `general` 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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n from_facilities = [e for e in emails if \"facilities@crestwood.edu\" in str(e.get(\"from_addr\", \"\")).lower()]\n if not from_facilities:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email from facilities@crestwood.edu found.\"}\n for e in from_facilities:\n folder = e.get(\"folder\", \"\").lower()\n if \"general\" not in folder:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Email from facilities@crestwood.edu is in folder '{e.get('folder')}', expected 'general'.\"}\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"Email from facilities@crestwood.edu is in the general folder.\"}",
"criterion_type": "expected_output"
},
{
"id": "e7f91235-98e4-4389-95cf-2b7767dea2f1",
"sort_order": 2,
"rubric_text": "In `slack_data.json`, channel `#hr-general` must contain a message with text `[OUT OF SCOPE] - HR office light bulb out Main Campus rm 214`",
"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\": \"external_services_path is None; cannot check slack_data.json\"}\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 with open(slack_path) as f:\n data = json.load(f)\n channels = data.get(\"channels\", {})\n hr_general_id = None\n for cid, cdata in channels.items():\n if cdata.get(\"name\", \"\").lower().strip(\"#\") == \"hr-general\":\n hr_general_id = cid\n break\n if hr_general_id is None:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Channel #hr-general not found.\"}\n messages = data.get(\"messages\", {}).get(hr_general_id, [])\n\n def normalize_dashes(s):\n # Collapse any hyphen/en-dash/em-dash/minus to a single canonical '-'\n return (s.replace(\"\\u2014\", \"-\")\n .replace(\"\\u2013\", \"-\")\n .replace(\"\\u2212\", \"-\")\n .replace(\"-\", \"-\"))\n\n target = normalize_dashes(\"[OUT OF SCOPE] - HR office light bulb out - Main Campus rm 214\").lower()\n for msg in messages:\n text = normalize_dashes(msg.get(\"text\", \"\")).lower()\n if target in text:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found required message in #hr-general: '{msg.get('text')}'\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Message '[OUT OF SCOPE] - HR office light bulb out - Main Campus rm 214' (any dash variant) not found in #hr-general. Messages found: {[m.get('text') for m in messages]}\"}",
"criterion_type": "expected_output"
},
{
"id": "6059ef2b-9c84-4307-8785-3c9e1948af51",
"sort_order": 3,
"rubric_text": "In `mailbox.json`, the email from `l.fontaine@crestwood.edu` must be in the `leave` 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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n from_fontaine = [e for e in emails if \"l.fontaine@crestwood.edu\" in str(e.get(\"from_addr\", \"\")).lower()]\n if not from_fontaine:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email from l.fontaine@crestwood.edu found.\"}\n for e in from_fontaine:\n folder = e.get(\"folder\", \"\").lower()\n if \"leave\" not in folder:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Email from l.fontaine@crestwood.edu is in folder '{e.get('folder')}', expected 'leave'.\"}\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"Email from l.fontaine@crestwood.edu is in the leave folder.\"}",
"criterion_type": "expected_output"
},
{
"id": "fa6332bb-e59b-433e-b135-335bcb794eef",
"sort_order": 4,
"rubric_text": "In `mailbox.json`, a sent email to `l.fontaine@crestwood.edu` must exist with body containing PTO balance of 68 hours, accrual rate of 4.62 hours per pay period, and contact info for Patricia Huang at p.huang@crestwood.edu",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n candidates = [e for e in emails if \"l.fontaine@crestwood.edu\" in str(e.get(\"to_addr\", \"\")).lower()]\n if not candidates:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email to l.fontaine@crestwood.edu found.\"}\n required_phrases = [\"68 hours\", \"4.62\", \"p.huang@crestwood.edu\", \"04/07/2026\"]\n for e in candidates:\n body = e.get(\"body_text\", \"\").lower()\n if all(phrase.lower() in body for phrase in required_phrases):\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"Email to l.fontaine@crestwood.edu found with required PTO balance content.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Email to l.fontaine@crestwood.edu found but missing required content. Required: {required_phrases}. Bodies found: {[e.get('body_text','')[:200] for e in candidates]}\"}",
"criterion_type": "expected_output"
},
{
"id": "4ed6f0e7-1d75-45cc-a70d-a53741123f63",
"sort_order": 5,
"rubric_text": "In `mailbox.json`, a sent email to `p.huang@crestwood.edu` with CC `t.salazar@crestwood.edu` with subject `I-9 Urgent Reminder — Salazar, CU-1026` must exist with body mentioning Tomás Salazar, CU-1026, 04/08/2026 federal deadline, and Section 2 of I-9",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n\n # Find emails sent to p.huang@crestwood.edu\n candidates = []\n for e in emails:\n to_addr = e.get(\"to_addr\", \"\") or e.get(\"to\", \"\")\n if isinstance(to_addr, list):\n to_lower = [a.lower() for a in to_addr]\n else:\n to_lower = [str(to_addr).lower()]\n if any(\"p.huang@crestwood.edu\" in a for a in to_lower):\n candidates.append(e)\n\n if not candidates:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email to p.huang@crestwood.edu found.\"}\n\n # Filter for I-9 / Salazar / CU-1026 related subject\n salazar_emails = []\n for e in candidates:\n subj = e.get(\"subject\", \"\").lower()\n if \"salazar\" in subj or \"cu-1026\" in subj or \"i-9\" in subj or \"i9\" in subj:\n salazar_emails.append(e)\n\n if not salazar_emails:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"No I-9/Salazar-related email found among emails to p.huang@crestwood.edu. Subjects found: {[e.get('subject') for e in candidates]}\"}\n\n for e in salazar_emails:\n body = e.get(\"body_text\", \"\") or e.get(\"body\", \"\") or \"\"\n subject = e.get(\"subject\", \"\")\n full_text = (subject + \" \" + body).lower()\n\n # Check CC includes t.salazar@crestwood.edu\n cc = e.get(\"cc_addr\", \"\") or e.get(\"cc\", \"\") or \"\"\n if isinstance(cc, list):\n cc_lower = [a.lower() for a in cc]\n else:\n cc_lower = [str(cc).lower()]\n has_cc = any(\"t.salazar@crestwood.edu\" in c for c in cc_lower)\n\n # Check body mentions: Salazar (or Tomás Salazar), CU-1026, April 8 2026 deadline, Section 2\n has_salazar = \"salazar\" in full_text\n has_cu1026 = \"cu-1026\" in full_text or \"cu1026\" in full_text\n\n # Accept various date formats for April 8, 2026\n date_patterns = [\n \"04/08/2026\", \"4/8/2026\",\n ]\n has_date = any(p in full_text for p in date_patterns)\n\n # Section 2 check - be lenient\n has_section2 = \"section 2\" in full_text or \"section ii\" in full_text or \"section two\" in full_text or \"section-2\" in full_text\n\n if has_salazar and has_cu1026 and has_date and has_section2:\n if not has_cc:\n return {\"pass\": True, \"score\": 0.8, \"feedback\": f\"Found I-9 urgent reminder email to p.huang@crestwood.edu for Salazar CU-1026 with required content, but CC to t.salazar@crestwood.edu not confirmed. CC field: {cc}\"}\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found I-9 urgent reminder email to p.huang@crestwood.edu with CC t.salazar@crestwood.edu for Salazar CU-1026 with all required content (Tomás Salazar, CU-1026, April 8 2026 deadline, Section 2).\"}\n\n # Provide detailed failure info\n details = []\n for e in salazar_emails:\n body = e.get(\"body_text\", \"\") or e.get(\"body\", \"\") or \"\"\n full_text = (e.get(\"subject\", \"\") + \" \" + body).lower()\n cc = e.get(\"cc_addr\", \"\") or e.get(\"cc\", \"\") or \"\"\n missing = []\n if \"salazar\" not in full_text:\n missing.append(\"Salazar\")\n if \"cu-1026\" not in full_text and \"cu1026\" not in full_text:\n missing.append(\"CU-1026\")\n date_patterns = [\n \"april 8\", \"april 08\", \"04/08/2026\", \"4/8/2026\",\n \"2026-04-08\", \"apr 8\", \"apr 08\", \"april 8, 2026\",\n \"april 8th\", \"april 8th, 2026\", \"04-08-2026\",\n \"4-8-2026\", \"april 08, 2026\"\n ]\n if not any(p in full_text for p in date_patterns):\n missing.append(\"April 8 2026 date\")\n if \"section 2\" not in full_text and \"section ii\" not in full_text and \"section two\" not in full_text and \"section-2\" not in full_text:\n missing.append(\"Section 2\")\n details.append({\"subject\": e.get(\"subject\"), \"cc\": cc, \"missing\": missing, \"body_snippet\": full_text[:300]})\n\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"I-9 urgent reminder email found but missing required content. Details: {details}\"}\n",
"criterion_type": "expected_output"
},
{
"id": "559efc43-ae89-4956-8045-90ca9cb46fbb",
"sort_order": 6,
"rubric_text": "In `benefits_enrollment.xlsx`, cell C26 must be set to `Default Enrollment` and cell D26 must be set to `05/01/2026`",
"verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n wb_path = Path(workspace_path) / \"benefits_enrollment.xlsx\"\n if not wb_path.exists():\n # Try searching\n matches = list(Path(workspace_path).glob(\"**/benefits_enrollment.xlsx\"))\n if not matches:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"benefits_enrollment.xlsx not found in workspace.\"}\n wb_path = matches[0]\n wb = openpyxl.load_workbook(wb_path)\n ws = wb.active\n c26 = ws[\"C26\"].value\n d26 = ws[\"D26\"].value\n c26_str = str(c26).strip() if c26 is not None else \"\"\n d26_str = str(d26).strip() if d26 is not None else \"\"\n c26_ok = \"default enrollment\" in c26_str.lower()\n d26_ok = \"05/01/2026\" in d26_str or d26_str == \"05/01/2026\"\n # Also check if d26 is a date object\n import datetime\n if hasattr(d26, 'month') and hasattr(d26, 'year'):\n d26_ok = d26.month == 5 and d26.year == 2026 and d26.day == 1\n if c26_ok and d26_ok:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"C26='{c26}' (Default Enrollment) and D26='{d26}' (05/01/2026) correctly set.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"C26='{c26}' (expected 'Default Enrollment', ok={c26_ok}), D26='{d26}' (expected 05/01/2026, ok={d26_ok}).\"}",
"criterion_type": "expected_output"
},
{
"id": "4323ac49-9f39-4121-9b6d-13ab81d30ed0",
"sort_order": 7,
"rubric_text": "In `onboarding_checklist.xlsx`, cell E15 must be set to `05/01/2026` (Benefits Enrolled date)",
"verifier_code": "from pathlib import Path\nimport openpyxl\nimport datetime\n\ndef verify(workspace_path, external_services_path=None):\n wb_path = Path(workspace_path) / \"onboarding_checklist.xlsx\"\n if not wb_path.exists():\n matches = list(Path(workspace_path).glob(\"**/onboarding_checklist.xlsx\"))\n if not matches:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"onboarding_checklist.xlsx not found in workspace.\"}\n wb_path = matches[0]\n wb = openpyxl.load_workbook(wb_path)\n ws = wb.active\n e15 = ws[\"E15\"].value\n e15_str = str(e15).strip() if e15 is not None else \"\"\n ok = \"05/01/2026\" in e15_str\n if hasattr(e15, 'month') and hasattr(e15, 'year'):\n ok = e15.month == 5 and e15.year == 2026 and e15.day == 1\n if ok:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"E15='{e15}' correctly set to 05/01/2026 for Benefits Enrolled.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"E15='{e15}' does not match expected 05/01/2026.\"}",
"criterion_type": "expected_output"
},
{
"id": "f2b2962e-5acc-4346-a75d-c52075fa9e35",
"sort_order": 8,
"rubric_text": "In `employee_roster.xlsx`, cell L23 must be set to `Active`",
"verifier_code": "from pathlib import Path\nimport openpyxl\n\ndef verify(workspace_path, external_services_path=None):\n wb_path = Path(workspace_path) / \"employee_roster.xlsx\"\n if not wb_path.exists():\n matches = list(Path(workspace_path).glob(\"**/employee_roster.xlsx\"))\n if not matches:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"employee_roster.xlsx not found in workspace.\"}\n wb_path = matches[0]\n wb = openpyxl.load_workbook(wb_path)\n ws = wb.active\n l23 = ws[\"L23\"].value\n l23_str = str(l23).strip() if l23 is not None else \"\"\n if l23_str.lower() == \"active\":\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"L23='{l23}' correctly set to Active.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"L23='{l23}' does not match expected 'Active'.\"}",
"criterion_type": "expected_output"
},
{
"id": "efd47f2e-f94d-4e44-b54b-7b67ad1ba7fe",
"sort_order": 9,
"rubric_text": "In `slack_data.json`, channel `#hr-onboarding` must contain a message with exact text `ONBOARDING COMPLETE: William Trent, CU-1022, 04/07/2026`",
"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\": \"external_services_path is None; cannot check slack_data.json\"}\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 with open(slack_path) as f:\n data = json.load(f)\n channels = data.get(\"channels\", {})\n hr_onboarding_id = None\n for cid, cdata in channels.items():\n if cdata.get(\"name\", \"\").lower().strip(\"#\") == \"hr-onboarding\":\n hr_onboarding_id = cid\n break\n if hr_onboarding_id is None:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Channel #hr-onboarding not found.\"}\n messages = data.get(\"messages\", {}).get(hr_onboarding_id, [])\n target = \"ONBOARDING COMPLETE: William Trent, CU-1022, 04/07/2026\"\n for msg in messages:\n if target.lower() in msg.get(\"text\", \"\").lower():\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found required message in #hr-onboarding: '{msg.get('text')}'\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Message '{target}' not found in #hr-onboarding. Messages: {[m.get('text') for m in messages]}\"}",
"criterion_type": "expected_output"
},
{
"id": "62bb6384-ef1c-4030-b4d3-3dd3ff76d725",
"sort_order": 10,
"rubric_text": "In `mailbox.json`, a sent email to `w.trent@crestwood.edu` with subject `Default Benefits Enrollment Confirmation — Trent, CU-1022` must exist with body mentioning default enrollment, 04/02/2026 deadline, and 05/01/2026 effective date",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n candidates = [e for e in emails if \"w.trent@crestwood.edu\" in str(e.get(\"to_addr\", \"\")).lower()]\n if not candidates:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email to w.trent@crestwood.edu found.\"}\n subject_match = [e for e in candidates if \"cu-1022\" in e.get(\"subject\", \"\").lower() or \"trent\" in e.get(\"subject\", \"\").lower()]\n required_phrases = [\"04/02/2026\", \"05/01/2026\", \"default\"]\n for e in subject_match:\n body = e.get(\"body_text\", \"\")\n if all(phrase.lower() in body.lower() for phrase in required_phrases):\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found default benefits enrollment confirmation email to w.trent@crestwood.edu with required content.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Default benefits enrollment confirmation email to w.trent@crestwood.edu not found or missing required content. Required: {required_phrases}. Subjects: {[e.get('subject') for e in candidates]}\"}",
"criterion_type": "expected_output"
},
{
"id": "97c5f3d5-b336-4a10-b782-d15d710b62d8",
"sort_order": 11,
"rubric_text": "In `mailbox.json`, a sent email to `p.huang@crestwood.edu` with subject `FMLA Deadline Passed — CU-1023` must exist with body mentioning Meghan Cross FMLA Certification overdue",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n candidates = [e for e in emails if \"p.huang@crestwood.edu\" in str(e.get(\"to_addr\", \"\")).lower()]\n if not candidates:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email to p.huang@crestwood.edu found.\"}\n fmla_emails = [e for e in candidates if \"fmla\" in e.get(\"subject\", \"\").lower() and \"cu-1023\" in e.get(\"subject\", \"\").lower()]\n if not fmla_emails:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"No FMLA CU-1023 email to p.huang@crestwood.edu found. Subjects: {[e.get('subject') for e in candidates]}\"}\n for e in fmla_emails:\n body = e.get(\"body_text\", \"\")\n if \"cross\" in body.lower() or \"meghan\" in body.lower():\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found FMLA Deadline Passed email to p.huang@crestwood.edu for CU-1023 (Meghan Cross).\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"FMLA CU-1023 email to p.huang@crestwood.edu found but body missing 'Cross'/'Meghan'. Bodies: {[e.get('body_text','')[:200] for e in fmla_emails]}\"}",
"criterion_type": "expected_output"
},
{
"id": "342775db-78be-4cd8-a801-e523a0286686",
"sort_order": 12,
"rubric_text": "In `mailbox.json`, a sent email to `m.cross@crestwood.edu` with subject `FMLA Certification Overdue — Cross, CU-1023` OR `Template 18 — Cross, CU-1023` OR `Template 18 FMLA Certification Overdue — Cross, CU-1023` must exist with body mentioning due date 04/07/2026, FMLA Medical Certification Form, and contact info for Patricia Huang",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n # Find emails sent to m.cross@crestwood.edu\n candidates = [e for e in emails if \"m.cross@crestwood.edu\" in str(e.get(\"to_addr\", \"\")).lower()]\n if not candidates:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No email to m.cross@crestwood.edu found.\"}\n\n # Check subject matches one of the allowed patterns (loose matching)\n subject_keywords = [\"fmla\", \"template 18\", \"cross\", \"cu-1023\"]\n\n # Check body for required content\n # Due date: 04/07/2026 in various formats\n date_patterns = [\"04/07/2026\", \"4/7/2026\"]\n # FMLA Medical Certification Form\n fmla_form_patterns = [\"fmla medical certification\", \"fmla certification\", \"medical certification form\"]\n # Contact info for Patricia Huang - could be email, phone, or just name\n patricia_patterns = [\"patricia huang\", \"p.huang@crestwood.edu\", \"p. huang\"]\n\n for e in candidates:\n body = (e.get(\"body_text\", \"\") or \"\").lower()\n subject = (e.get(\"subject\", \"\") or \"\").lower()\n combined = subject + \" \" + body\n\n # Subject check: must relate to FMLA or Template 18 and Cross/CU-1023\n subject_ok = False\n if (\"fmla\" in subject or \"template 18\" in subject) and (\"cross\" in subject or \"cu-1023\" in subject):\n subject_ok = True\n\n if not subject_ok:\n continue\n\n # Date check\n date_ok = any(dp in combined for dp in date_patterns)\n\n # FMLA form check\n fmla_form_ok = any(fp in combined for fp in fmla_form_patterns)\n\n # Patricia Huang contact info check\n patricia_ok = any(pp in combined for pp in patricia_patterns)\n\n if date_ok and fmla_form_ok and patricia_ok:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found FMLA Certification Overdue email to m.cross@crestwood.edu with required content. Subject: {e.get('subject')}\"}\n\n # Collect what's missing for feedback\n missing = []\n if not date_ok:\n missing.append(\"due date (04/07/2026)\")\n if not fmla_form_ok:\n missing.append(\"FMLA Medical Certification Form reference\")\n if not patricia_ok:\n missing.append(\"Patricia Huang contact info\")\n\n # If we get here, no email matched fully\n all_subjects = [e.get('subject', '') for e in candidates]\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"FMLA Certification Overdue email to m.cross@crestwood.edu not found or missing required content. Need: due date 04/07/2026, FMLA Medical Certification Form mention, and Patricia Huang contact info. Candidate subjects: {all_subjects}\"}\n",
"criterion_type": "expected_output"
},
{
"id": "543a04a0-b8fa-4f83-96f1-70823791a25d",
"sort_order": 13,
"rubric_text": "In `slack_data.json`, channel `#hr-leave-requests` must contain a message with text `FMLA CERTIFICATION OVERDUE: Meghan Cross, CU-1023, Due: 04/07/2026` and mentioning overdue",
"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\": \"external_services_path is None; cannot check slack_data.json\"}\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 with open(slack_path) as f:\n data = json.load(f)\n channels = data.get(\"channels\", {})\n hr_leave_id = None\n for cid, cdata in channels.items():\n if cdata.get(\"name\", \"\").lower().strip(\"#\") == \"hr-leave-requests\":\n hr_leave_id = cid\n break\n if hr_leave_id is None:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Channel #hr-leave-requests not found.\"}\n messages = data.get(\"messages\", {}).get(hr_leave_id, [])\n required_phrases = [\"FMLA CERTIFICATION OVERDUE\", \"Meghan Cross\", \"CU-1023\", \"04/07/2026\"]\n for msg in messages:\n text = msg.get(\"text\", \"\")\n if all(phrase.lower() in text.lower() for phrase in required_phrases):\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found required FMLA overdue message in #hr-leave-requests: '{text}'\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Required FMLA overdue message not found in #hr-leave-requests. Required phrases: {required_phrases}. Messages: {[m.get('text') for m in messages]}\"}",
"criterion_type": "expected_output"
},
{
"id": "6b40093b-ab7a-46b8-9129-bcd2c58d223a",
"sort_order": 14,
"rubric_text": "In `jira_state.json`, issue `HR-7` must have comments containing all required entries for steps 11.3 and 11.4, and description appended with `Status — CLOSED`",
"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\": \"external_services_path is None; cannot check jira_state.json\"}\n jira_path = Path(external_services_path) / \"jira_state.json\"\n if not jira_path.exists():\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"jira_state.json not found\"}\n with open(jira_path) as f:\n data = json.load(f)\n\n def adf_to_text(node):\n \"\"\"Flatten an Atlassian Document Format node (dict/list) to plain text. Passthrough for strings.\"\"\"\n if node is None:\n return \"\"\n if isinstance(node, str):\n return node\n out = []\n def walk(n):\n if isinstance(n, dict):\n if n.get(\"type\") == \"text\":\n out.append(n.get(\"text\", \"\"))\n for c in n.get(\"content\", []) or []:\n walk(c)\n if n.get(\"type\") in (\"paragraph\", \"heading\", \"listItem\"):\n out.append(\"\\n\")\n elif isinstance(n, list):\n for x in n:\n walk(x)\n walk(node)\n return \"\".join(out).strip()\n\n # Navigate to issues\n issues = data.get(\"issues\", data) if isinstance(data, dict) else data\n\n trent_issue = None\n matched_key = None\n if isinstance(issues, dict):\n for key, val in issues.items():\n if \"trent\" in key.lower() and \"onboard\" in key.lower():\n trent_issue = val if isinstance(val, dict) else {\"raw\": val}\n matched_key = key\n break\n if trent_issue is None:\n for key, val in issues.items():\n combined = (key + \" \" + json.dumps(val, default=str)).lower()\n if \"trent\" in combined and \"onboard\" in combined:\n trent_issue = val if isinstance(val, dict) else {\"raw\": val}\n matched_key = key\n break\n elif isinstance(issues, list):\n for item in issues:\n if isinstance(item, dict):\n item_str = json.dumps(item, default=str).lower()\n if \"trent\" in item_str and \"onboard\" in item_str:\n trent_issue = item\n matched_key = item.get(\"key\", \"list_item\")\n break\n\n if trent_issue is None:\n all_keys = list(issues.keys()) if isinstance(issues, dict) else \"N/A (list)\"\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Issue HR-7 not found in jira_state.json. Available keys: {all_keys}\"}\n\n # Gather comments. Handle both schemas:\n # (a) comments nested inside the issue: issue[\"comments\"] = [...]\n # (b) comments stored in a parallel top-level dict: data[\"comments\"][issue_key] = [...]\n # Each comment's body may be a plain string OR an ADF dict.\n comments_raw = []\n nested = trent_issue.get(\"comments\")\n if isinstance(nested, list):\n comments_raw.extend(nested)\n if isinstance(data, dict):\n parallel = data.get(\"comments\", {})\n if isinstance(parallel, dict) and matched_key in parallel and isinstance(parallel[matched_key], list):\n comments_raw.extend(parallel[matched_key])\n\n comments_text_parts = []\n for c in comments_raw:\n if isinstance(c, dict):\n for field in (\"body\", \"text\", \"content\"):\n if field in c:\n comments_text_parts.append(adf_to_text(c[field]))\n else:\n comments_text_parts.append(str(c))\n comments_text = \" \".join(comments_text_parts)\n comments_text_lower = comments_text.lower()\n\n # Description. Handle both schemas:\n # (a) issue[\"description\"] directly (string or ADF)\n # (b) issue[\"fields\"][\"description\"] (string or ADF)\n description = trent_issue.get(\"description\")\n if description in (None, \"\") and isinstance(trent_issue.get(\"fields\"), dict):\n description = trent_issue[\"fields\"].get(\"description\")\n description_text = adf_to_text(description)\n desc_lower = description_text.lower()\n\n all_text_lower = comments_text_lower + \" \" + desc_lower\n\n required_comment_fragments = [\n (\"11.3\", [\"11.3\", \"step 11.3\", \"11-3\"]),\n (\"benefits_enrollment\", [\"benefits_enrollment\", \"benefits enrollment\", \"benefits-enrollment\"]),\n (\"Default Enrollment\", [\"default enrollment\", \"default enroll\"]),\n (\"05/01/2026\", [\"05/01/2026\", \"5/1/2026\"]),\n (\"Template 10\", [\"template 10\", \"template-10\", \"template_10\"]),\n (\"w.trent@crestwood.edu\", [\"w.trent@crestwood\", \"trent@crestwood\"]),\n (\"11.4\", [\"11.4\", \"step 11.4\", \"11-4\"]),\n (\"employee_roster\", [\"employee_roster\", \"employee roster\", \"employee-roster\"]),\n (\"Active\", [\"active\"]),\n (\"#hr-onboarding\", [\"hr-onboarding\", \"hr onboarding\", \"#hr-onboarding\"]),\n ]\n\n missing = []\n for label, variants in required_comment_fragments:\n if not any(v.lower() in all_text_lower for v in variants):\n missing.append(label)\n\n closed_patterns = [\n \"status — closed\",\n \"status closed\",\n \"status - closed\",\n \"status -- closed\",\n \"status—closed\",\n \"statusclosed\",\n \"status-closed\",\n \"status: closed\",\n \"status:closed\",\n ]\n closed_in_desc = any(pat in desc_lower for pat in closed_patterns)\n closed_anywhere = \"closed\" in all_text_lower\n\n feedback_parts = []\n score = 1.0\n passed = True\n\n if missing:\n passed = False\n score = max(0.0, 1.0 - len(missing) * 0.1)\n feedback_parts.append(f\"Missing comment/description fragments: {missing}\")\n\n if not closed_in_desc:\n if closed_anywhere:\n feedback_parts.append(f\"'CLOSED' found in comments but not clearly in description. Description: '{description_text[:200]}'\")\n passed = False\n score = min(score, 0.5)\n else:\n passed = False\n score = 0.0\n feedback_parts.append(f\"Description does not contain 'Status CLOSED' annotation. Description: '{description_text[:300]}'\")\n\n if passed:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"HR-7 (key: {matched_key}) has all required comment entries for 11.3 and 11.4, and description contains CLOSED status.\"}\n return {\"pass\": False, \"score\": score, \"feedback\": f\"Issue key: {matched_key}. Found {len(comments_raw)} comments. \" + \" | \".join(feedback_parts)}",
"criterion_type": "expected_output"
},
{
"id": "fd6fcf96-a025-43ef-b1ec-d6bd8023ec7d",
"sort_order": 15,
"rubric_text": "In `jira_state.json`, issue `HR-1` must have comments for Template 18 sent to m.cross@crestwood.edu, slack posted to #hr-leave-requests, email forwarded to p.huang@crestwood.edu, and waiting on Patricia Huang",
"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\": \"external_services_path is None; cannot check jira_state.json\"}\n jira_path = Path(external_services_path) / \"jira_state.json\"\n if not jira_path.exists():\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"jira_state.json not found\"}\n with open(jira_path) as f:\n data = json.load(f)\n\n def adf_to_text(node):\n if node is None:\n return \"\"\n if isinstance(node, str):\n return node\n out = []\n def walk(n):\n if isinstance(n, dict):\n if n.get(\"type\") == \"text\":\n out.append(n.get(\"text\", \"\"))\n for c in n.get(\"content\", []) or []:\n walk(c)\n if n.get(\"type\") in (\"paragraph\", \"heading\", \"listItem\"):\n out.append(\"\\n\")\n elif isinstance(n, list):\n for x in n:\n walk(x)\n walk(node)\n return \"\".join(out).strip()\n\n issues = data.get(\"issues\", data) if isinstance(data, dict) and \"issues\" in data else data\n\n cross_issue = None\n matched_key = None\n if isinstance(issues, dict):\n for key, val in issues.items():\n if \"cross\" in key.lower() and \"leave\" in key.lower():\n cross_issue = val if isinstance(val, dict) else {\"raw\": val}\n matched_key = key\n break\n elif isinstance(issues, list):\n for item in issues:\n if isinstance(item, dict):\n s = json.dumps(item, default=str).lower()\n if \"cross\" in s and \"leave\" in s:\n cross_issue = item\n matched_key = item.get(\"key\", \"list_item\")\n break\n\n if cross_issue is None:\n keys = list(issues.keys()) if isinstance(issues, dict) else \"N/A\"\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Issue HR-1 not found. Keys: {keys}\"}\n\n comments_raw = []\n nested = cross_issue.get(\"comments\")\n if isinstance(nested, list):\n comments_raw.extend(nested)\n if isinstance(data, dict):\n parallel = data.get(\"comments\", {})\n if isinstance(parallel, dict) and matched_key in parallel and isinstance(parallel[matched_key], list):\n comments_raw.extend(parallel[matched_key])\n\n parts = []\n for c in comments_raw:\n if isinstance(c, dict):\n for field in (\"body\", \"text\", \"content\"):\n if field in c:\n parts.append(adf_to_text(c[field]))\n else:\n parts.append(str(c))\n comments_text = \" \".join(parts)\n ct = comments_text.lower()\n\n required_fragments = [\"template 18\", \"m.cross@crestwood.edu\", \"hr-leave-requests\", \"p.huang@crestwood.edu\"]\n missing = [f for f in required_fragments if f.lower() not in ct]\n if missing:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": f\"HR-1 (key: {matched_key}) missing fragments: {missing}. Found {len(comments_raw)} comments. Text: '{comments_text[:400]}'\"}\n return {\"pass\": True, \"score\": 1.0,\n \"feedback\": f\"HR-1 (key: {matched_key}) has required fragments across {len(comments_raw)} comments.\"}",
"criterion_type": "expected_output"
},
{
"id": "0b596b96-db7e-445f-a83b-05ef87e66771",
"sort_order": 16,
"rubric_text": "In `jira_state.json`, issue `HR-6` must have a comment mentioning Template 6 sent to p.huang@crestwood.edu and step 11.2",
"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\": \"external_services_path is None; cannot check jira_state.json\"}\n jira_path = Path(external_services_path) / \"jira_state.json\"\n if not jira_path.exists():\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"jira_state.json not found\"}\n with open(jira_path) as f:\n data = json.load(f)\n\n def adf_to_text(node):\n \"\"\"Flatten Atlassian Document Format (dict/list) to plain text; passthrough for strings.\"\"\"\n if node is None:\n return \"\"\n if isinstance(node, str):\n return node\n out = []\n def walk(n):\n if isinstance(n, dict):\n if n.get(\"type\") == \"text\":\n out.append(n.get(\"text\", \"\"))\n for c in n.get(\"content\", []) or []:\n walk(c)\n if n.get(\"type\") in (\"paragraph\", \"heading\", \"listItem\"):\n out.append(\"\\n\")\n elif isinstance(n, list):\n for x in n:\n walk(x)\n walk(node)\n return \"\".join(out).strip()\n\n issues = data.get(\"issues\", data) if isinstance(data, dict) and \"issues\" in data else data\n\n salazar_issue = None\n matched_key = None\n if isinstance(issues, dict):\n for key, val in issues.items():\n if \"salazar\" in key.lower() and \"onboard\" in key.lower():\n salazar_issue = val if isinstance(val, dict) else {\"raw\": val}\n matched_key = key\n break\n if salazar_issue is None:\n for key, val in issues.items():\n combined = (key + \" \" + json.dumps(val, default=str)).lower()\n if \"salazar\" in combined and \"onboard\" in combined:\n salazar_issue = val if isinstance(val, dict) else {\"raw\": val}\n matched_key = key\n break\n elif isinstance(issues, list):\n for item in issues:\n if isinstance(item, dict):\n s = json.dumps(item, default=str).lower()\n if \"salazar\" in s and \"onboard\" in s:\n salazar_issue = item\n matched_key = item.get(\"key\", \"list_item\")\n break\n\n if salazar_issue is None:\n keys = list(issues.keys()) if isinstance(issues, dict) else \"N/A\"\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Issue HR-6 not found. Keys: {keys}\"}\n\n # Collect comments from both possible schemas.\n comments_raw = []\n nested = salazar_issue.get(\"comments\")\n if isinstance(nested, list):\n comments_raw.extend(nested)\n if isinstance(data, dict):\n parallel = data.get(\"comments\", {})\n if isinstance(parallel, dict) and matched_key in parallel and isinstance(parallel[matched_key], list):\n comments_raw.extend(parallel[matched_key])\n\n parts = []\n for c in comments_raw:\n if isinstance(c, dict):\n for field in (\"body\", \"text\", \"content\"):\n if field in c:\n parts.append(adf_to_text(c[field]))\n else:\n parts.append(str(c))\n comments_text = \" \".join(parts)\n ct = comments_text.lower()\n\n required_fragments = [\"11.2\", \"Template 6\", \"p.huang@crestwood.edu\"]\n missing = [f for f in required_fragments if f.lower() not in ct]\n if missing:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": f\"HR-6 (key: {matched_key}) missing comment fragments: {missing}. Found {len(comments_raw)} comments. Text: '{comments_text[:400]}'\"}\n return {\"pass\": True, \"score\": 1.0,\n \"feedback\": f\"HR-6 (key: {matched_key}) has required comment for Template 6 to p.huang@crestwood.edu across {len(comments_raw)} entries.\"}",
"criterion_type": "expected_output"
},
{
"id": "0968f22e-9afc-4fa9-8baf-f8ed52566e11",
"sort_order": 17,
"rubric_text": "In `mailbox.json`, there must be exactly 11 sent emails (emails with folder='Sent')",
"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\": \"external_services_path is None; cannot check mailbox.json\"}\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 with open(mailbox_path) as f:\n data = json.load(f)\n emails = data.get(\"emails\", [])\n sent = [e for e in emails if e.get(\"folder\", \"\").lower() == \"sent\"]\n if len(sent) == 11:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found exactly 11 sent emails. Subjects: {[e.get('subject') for e in sent]}\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Expected 11 sent emails, found {len(sent)}. Subjects: {[e.get('subject') for e in sent]}\"}",
"criterion_type": "incorrect_behavior"
},
{
"id": "9fa6493a-d029-4e8f-a6ab-fdade61b8c30",
"sort_order": 18,
"rubric_text": "In `slack_data.json`, each channel must have the exact number of messages: #hr-onboarding=15, #hr-offboarding=1, #hr-leave-requests=13, #hr-performance=2, #hr-recruiting=3, #hr-escalations=0, #hr-general=3",
"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\": \"external_services_path is None; cannot check slack_data.json\"}\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 with open(slack_path) as f:\n data = json.load(f)\n channels = data.get(\"channels\", {})\n messages = data.get(\"messages\", {})\n expected = {\n \"hr-onboarding\": 15,\n \"hr-offboarding\": 1,\n \"hr-leave-requests\": 13,\n \"hr-performance\": 2,\n \"hr-recruiting\": 3,\n \"hr-escalations\": 0,\n \"hr-general\": 3\n }\n name_to_id = {}\n for cid, cdata in channels.items():\n name = cdata.get(\"name\", \"\").lower().strip(\"#\")\n name_to_id[name] = cid\n failures = []\n for channel_name, expected_count in expected.items():\n cid = name_to_id.get(channel_name)\n if cid is None:\n if expected_count == 0:\n continue\n failures.append(f\"#{channel_name} not found (expected {expected_count} messages)\")\n continue\n actual_count = len(messages.get(cid, []))\n if actual_count != expected_count:\n failures.append(f\"#{channel_name}: expected {expected_count} messages, found {actual_count}\")\n if failures:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Message count mismatches: \" + \"; \".join(failures)}\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"All channels have the correct number of messages.\"}",
"criterion_type": "incorrect_behavior"
},
{
"id": "100b7c72-5bd9-4716-93ac-939303f7d470",
"sort_order": 19,
"rubric_text": "In `jira_state.json`, there must be exactly 8 issues",
"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\": \"external_services_path is None; cannot check jira_state.json\"}\n jira_path = Path(external_services_path) / \"jira_state.json\"\n if not jira_path.exists():\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"jira_state.json not found\"}\n with open(jira_path) as f:\n data = json.load(f)\n if isinstance(data, dict) and \"issues\" in data:\n issues = data[\"issues\"]\n else:\n issues = data\n if isinstance(issues, dict):\n count = len(issues)\n elif isinstance(issues, list):\n count = len(issues)\n else:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Unexpected issues format: {type(issues)}\"}\n if count == 8:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found exactly 8 issues in jira_state.json.\"}\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"Expected 8 issues in jira_state.json, found {count}.\"}",
"criterion_type": "incorrect_behavior"
}
]