[ { "id": "db9c9307-5b47-4b7f-9d39-10d4f1f24e54", "sort_order": 0, "rubric_text": "In mailbox.json, a sent email to hannah.price@sunshineandsetauto.com must exist for the April 1-15 payroll submission containing: (a) commission line items for the 6 in-period deals (4502, 4503, 4504, 4506, 4508, 4509) per Section 7.1; (b) a prior-period adjustment row for Deal 4501 (Derek Vaughn, $1,450) with the Section 7.3 fields: original pay period (March 16-31), original amount ($0), corrected amount ($1,450), variance, and a brief explanation.", "verifier_code": "from pathlib import Path\nimport json\nimport re\n\n\ndef verify(workspace_path, external_services_path=None):\n if external_services_path is None:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"external_services_path is None; cannot check mailbox\"}\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\") == \"Sent\"]\n hannah_emails = [\n e for e in sent_emails\n if \"hannah.price@sunshineandsetauto.com\" in (e.get(\"to_addr\") or \"\")\n ]\n\n if not hannah_emails:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"No sent email found to hannah.price@sunshineandsetauto.com\"}\n\n april_emails = []\n for e in hannah_emails:\n body = (e.get(\"body_text\") or \"\").lower()\n subj = (e.get(\"subject\") or \"\").lower()\n combined = body + \" \" + subj\n if \"april\" in combined and (\"1-15\" in combined or \"1–15\" in combined or \"april 1\" in combined):\n april_emails.append(e)\n\n if not april_emails:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"No April 1-15 commission email to Hannah Price found\"}\n\n required_inperiod_deals = [\"4502\", \"4503\", \"4504\", \"4506\", \"4508\", \"4509\"]\n\n # Section 7.3 field markers for the prior-period adjustment\n march_period_re = re.compile(\n r\"march\\s*16[\\s\\-\\u2013]+31|\"\n r\"03[/\\-]31|3/31|march\\s*31|\"\n r\"post\\s*date[^\\n]{0,30}(?:03[/\\-]31|3/31|march\\s*31)\",\n re.IGNORECASE,\n )\n original_amount_re = re.compile(r\"original\\s+amount|original\\s*\\$?0\\b\", re.IGNORECASE)\n corrected_amount_re = re.compile(r\"corrected\\s+amount|corrected\\s*\\$?1,?450\", re.IGNORECASE)\n variance_re = re.compile(r\"variance|\\+\\s*\\$?1,?450\", re.IGNORECASE)\n explanation_re = re.compile(\n r\"prior[\\s\\-]period|missed|outside|wrong\\s+period|\"\n r\"section\\s*7\\.?[13]|7\\.?3|adjustment|recalculated\",\n re.IGNORECASE,\n )\n\n best_score = 0.0\n best_subject = \"\"\n best_failed = []\n best_notes = []\n\n for email in april_emails:\n body_raw = email.get(\"body_text\") or \"\"\n body_lower = body_raw.lower()\n\n checks = {}\n notes = []\n\n # 1. All 6 in-period deals appear (SOP 7.1)\n deals_missing = [d for d in required_inperiod_deals if d not in body_lower]\n checks[\"all_6_inperiod_deals\"] = len(deals_missing) == 0\n if deals_missing:\n notes.append(f\"Missing in-period deals: {deals_missing}\")\n\n # 2. Prior-period adjustment row for Deal 4501 with SOP 7.3 fields\n # Find a window around 4501 / 1450 / Derek and check for the 5 required fields\n adj_window = \"\"\n idx_4501 = body_lower.find(\"4501\")\n if idx_4501 != -1:\n adj_window = body_lower[max(0, idx_4501 - 400):idx_4501 + 600]\n\n has_4501 = \"4501\" in body_lower\n has_1450 = bool(re.search(r\"1,?450\", adj_window))\n has_derek = \"derek\" in adj_window\n has_march_period = bool(march_period_re.search(adj_window))\n has_original = bool(original_amount_re.search(adj_window))\n has_corrected = bool(corrected_amount_re.search(adj_window))\n has_variance = bool(variance_re.search(adj_window))\n has_explanation = bool(explanation_re.search(adj_window))\n\n adj_field_count = sum([has_march_period, has_original, has_corrected,\n has_variance, has_explanation])\n\n # Require: 4501 + $1,450 + Derek + at least 4 of the 5 SOP 7.3 fields present\n checks[\"prior_period_adjustment_4501\"] = (\n has_4501 and has_1450 and has_derek and adj_field_count >= 4\n )\n if not checks[\"prior_period_adjustment_4501\"]:\n field_status = {\n \"march_period\": has_march_period,\n \"original_amount\": has_original,\n \"corrected_amount\": has_corrected,\n \"variance\": has_variance,\n \"explanation\": has_explanation,\n }\n notes.append(\n f\"Prior-period adjustment row missing required Section 7.3 fields. \"\n f\"Has 4501={has_4501}, $1,450={has_1450}, Derek={has_derek}, \"\n f\"7.3 fields present: {field_status}\"\n )\n\n passed = [k for k, v in checks.items() if v]\n failed = [k for k, v in checks.items() if not v]\n score = len(passed) / len(checks)\n\n if all(checks.values()):\n return {\n \"pass\": True,\n \"score\": 1.0,\n \"feedback\": (\n f\"Email '{email.get('subject')}' - all checks passed: \"\n \"6 in-period commission line items present (Section 7.1), \"\n \"and Deal 4501 prior-period adjustment row contains the required \"\n \"Section 7.3 fields (original pay period, original amount, \"\n \"corrected amount, variance, explanation).\"\n ),\n }\n\n if score > best_score:\n best_score = score\n best_subject = email.get(\"subject\") or \"\"\n best_failed = failed\n best_notes = notes\n\n feedback = (\n f\"Best email '{best_subject}' failed canonical April-payroll structure. \"\n f\"Failed checks: {best_failed}.\"\n )\n if best_notes:\n feedback += \" \" + \" \".join(best_notes)\n return {\"pass\": False, \"score\": round(min(best_score, 0.5), 2), \"feedback\": feedback}\n", "criterion_type": "expected_output" }, { "id": "fba884ec-c68c-4410-a3ce-ca9abc8d3737", "sort_order": 1, "rubric_text": "In mailbox.json, a sent email to megan.price@sunshineandsetauto.com must exist CC'd to marcus.hale@sunshineandsetauto.com and hannah.price@sunshineandsetauto.com, containing chargeback amount $1,400, originating deal 4492 or Patricia Dunn, offset calculation showing earned commission $1,050 vs chargeback $1,400, $350 shortfall carried forward, and statement of right to dispute", "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\"}\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\") == \"Sent\"]\n \n megan_emails = [e for e in sent_emails if \"megan.price@sunshineandsetauto.com\" in (e.get(\"to_addr\") or \"\")]\n \n if not megan_emails:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No sent email found to megan.price@sunshineandsetauto.com\"}\n \n for email in megan_emails:\n body = (email.get(\"body_text\") or \"\").lower()\n cc = (email.get(\"cc_addr\") or \"\").lower()\n \n has_marcus_cc = \"marcus.hale@sunshineandsetauto.com\" in cc\n has_hannah_cc = \"hannah.price@sunshineandsetauto.com\" in cc\n \n has_1400 = \"1,400\" in body or \"1400\" in body.replace(\",\", \"\")\n has_deal_4492 = \"4492\" in body\n has_patricia = \"patricia\" in body or \"dunn\" in body\n has_1050 = \"1,050\" in body or \"1050\" in body.replace(\",\", \"\")\n has_350_shortfall = \"350\" in body and (\"shortfall\" in body or \"carry\" in body or \"next pay\" in body or \"forward\" in body)\n has_dispute = any(word in body for word in [\"dispute\", \"contest\", \"challenge\"]) or (\"incorrect\" in body and any(w in body for w in [\"reply\", \"review\", \"respond\", \"contact\"]))\n \n checks = {\n \"CC marcus.hale\": has_marcus_cc,\n \"CC hannah.price\": has_hannah_cc,\n \"Chargeback $1,400\": has_1400,\n \"Deal 4492 or Patricia Dunn\": (has_deal_4492 or has_patricia),\n \"Earned commission $1,050\": has_1050,\n \"$350 shortfall carry forward\": has_350_shortfall,\n \"Right to dispute\": has_dispute\n }\n \n passed = [k for k, v in checks.items() if v]\n failed = [k for k, v in checks.items() if not v]\n \n if len(failed) == 0:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Found complete chargeback notification email to Megan Price with all required elements: {passed}\"}\n \n # Return best partial result across all megan emails\n best_failed = None\n for email in megan_emails:\n body = (email.get(\"body_text\") or \"\").lower()\n cc = (email.get(\"cc_addr\") or \"\").lower()\n checks = {\n \"CC marcus.hale\": \"marcus.hale@sunshineandsetauto.com\" in cc,\n \"CC hannah.price\": \"hannah.price@sunshineandsetauto.com\" in cc,\n \"Chargeback $1,400\": \"1,400\" in body or \"1400\" in body.replace(\",\", \"\"),\n \"Deal 4492 or Patricia Dunn\": (\"4492\" in body or \"patricia\" in body or \"dunn\" in body),\n \"Earned commission $1,050\": \"1,050\" in body or \"1050\" in body.replace(\",\", \"\"),\n \"$350 shortfall carry forward\": \"350\" in body and (\"shortfall\" in body or \"carry\" in body or \"next pay\" in body or \"forward\" in body),\n \"Right to dispute\": any(word in body for word in [\"dispute\", \"contest\", \"challenge\"]) or (\"incorrect\" in body and any(w in body for w in [\"reply\", \"review\", \"respond\", \"contact\"]))\n }\n failed = [k for k, v in checks.items() if not v]\n if best_failed is None or len(failed) < len(best_failed):\n best_failed = failed\n return {\"pass\": False, \"score\": 0.3, \"feedback\": f\"Email to Megan Price found but missing: {best_failed}\"}", "criterion_type": "expected_output" }, { "id": "58425502-4353-4134-b74f-4fd25e1490cc", "sort_order": 2, "rubric_text": "In slack_data.json, a message in channel #acct-payroll-commissions must exist flagging Deal 4505 as unwound/reversed and Deal 4507 as not posted in the deal log, and Olivia Mercer must be notified (via Slack or email) that these two deals must be removed from her commission sheet", "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\"}\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 # Find #acct-payroll-commissions channel\n channels = data.get(\"channels\", {})\n target_channel_id = None\n for cid, cinfo in channels.items():\n if \"acct-payroll-commissions\" in (cinfo.get(\"name\") or \"\").lower():\n target_channel_id = cid\n break\n \n if target_channel_id is None:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Channel #acct-payroll-commissions not found in slack_data.json\"}\n \n messages_dict = data.get(\"messages\", {})\n channel_messages = messages_dict.get(target_channel_id, [])\n \n if not channel_messages:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": f\"No messages found in #acct-payroll-commissions (channel id: {target_channel_id})\"}\n \n all_text = \" \".join((m.get(\"text\") or \"\").lower() for m in channel_messages)\n \n has_4505 = \"4505\" in all_text\n has_4507 = \"4507\" in all_text\n has_unwound_or_reversed = any(word in all_text for word in [\"unwound\", \"reversed\", \"reversal\", \"unwind\", \"void\", \"voided\"])\n has_not_posted = any(phrase in all_text for phrase in [\"not posted\", \"not in deal log\", \"not in the deal log\", \"missing from deal log\", \"no deal log\"])\n has_payroll_exclusion = any(phrase in all_text for phrase in [\"cannot be included\", \"not include\", \"exclude\", \"cannot include\", \"can't include\"])\n \n # Check for Olivia Mercer notification (Slack or email)\n olivia_notified_slack = \"olivia\" in all_text or \"mercer\" in all_text\n \n # Also check email notification to Olivia\n olivia_notified_email = False\n if external_services_path:\n mailbox_path = Path(external_services_path) / \"mailbox.json\"\n if mailbox_path.exists():\n with open(mailbox_path) as f:\n mail_data = json.load(f)\n sent = [e for e in mail_data.get(\"emails\", []) if e.get(\"folder\") == \"Sent\"]\n for email in sent:\n to = (email.get(\"to_addr\") or \"\").lower()\n body = (email.get(\"body_text\") or \"\").lower()\n if \"olivia\" in to or \"mercer\" in to or (\"olivia\" in body and (\"4505\" in body or \"4507\" in body)):\n olivia_notified_email = True\n break\n \n # Also check all slack messages for DM to Olivia\n olivia_notified_dm = False\n for cid, msgs in messages_dict.items():\n for msg in msgs:\n txt = (msg.get(\"text\") or \"\").lower()\n if (\"olivia\" in txt or \"mercer\" in txt) and (\"4505\" in txt or \"4507\" in txt) and (\"remove\" in txt or \"remov\" in txt or \"cannot\" in txt or \"not include\" in txt):\n olivia_notified_dm = True\n break\n \n olivia_notified = olivia_notified_slack or olivia_notified_email or olivia_notified_dm\n \n checks = {\n \"Deal 4505 mentioned\": has_4505,\n \"Deal 4507 mentioned\": has_4507,\n \"Unwound/reversed mentioned for 4505\": has_unwound_or_reversed,\n \"Not posted in deal log for 4507\": has_not_posted,\n \"Payroll exclusion stated\": has_payroll_exclusion,\n \"Olivia Mercer notified\": olivia_notified\n }\n \n failed = [k for k, v in checks.items() if not v]\n passed = [k for k, v in checks.items() if v]\n \n if len(failed) == 0:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": f\"Slack message in #acct-payroll-commissions correctly flags deals 4505 and 4507, and Olivia Mercer is notified. Checks passed: {passed}\"}\n \n # Partial pass: if both deals mentioned and at least some context\n if has_4505 and has_4507:\n score = 0.6\n return {\"pass\": False, \"score\": score, \"feedback\": f\"Both deals mentioned in #acct-payroll-commissions but missing: {failed}\"}\n \n return {\"pass\": False, \"score\": 0.1, \"feedback\": f\"Slack message in #acct-payroll-commissions incomplete. Failed checks: {failed}\"}\n", "criterion_type": "expected_output" }, { "id": "fdc1758d-fc52-4701-bc55-a2fdb15b20fe", "sort_order": 3, "rubric_text": "In mailbox.json, the sent email to hannah.price@sunshineandsetauto.com must contain the chargeback offset detail for Megan Price showing: Deal 4492, chargeback $1,400, earned commission $1,050 fully offset, net commission $0, and $350 shortfall carried to next pay period", "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\"}\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\") == \"Sent\"]\n hannah_emails = [e for e in sent_emails if \"hannah.price@sunshineandsetauto.com\" in (e.get(\"to_addr\") or \"\")]\n \n if not hannah_emails:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"No sent email to hannah.price@sunshineandsetauto.com found\"}\n \n best_passed = []\n best_failed = None\n best_subject = \"\"\n \n for email in hannah_emails:\n body = (email.get(\"body_text\") or \"\").lower()\n \n has_4492 = \"4492\" in body\n has_1400 = \"1,400\" in body or \"1400\" in body.replace(\",\", \"\")\n has_1050 = \"1,050\" in body or \"1050\" in body.replace(\",\", \"\")\n has_350_carryforward = \"350\" in body and (\"carri\" in body or \"carry\" in body or \"next pay\" in body or \"forward\" in body or \"shortfall\" in body)\n has_chargeback_context = \"chargeback\" in body or \"offset\" in body\n \n has_chargeback_amount = has_1400 or (has_1050 and has_350_carryforward and has_chargeback_context)\n \n has_explicit_zero = \"megan\" in body and (\"$0\" in body or \"$0.00\" in body)\n has_implied_zero = \"megan\" in body and has_1050 and has_chargeback_context and has_350_carryforward\n has_megan_zero = has_explicit_zero or has_implied_zero\n \n checks = {\n \"Deal 4492\": has_4492,\n \"Chargeback amount ($1,400 explicit or $1,050+$350 implied)\": has_chargeback_amount,\n \"Earned commission $1,050\": has_1050,\n \"Megan net $0\": has_megan_zero,\n \"$350 carryforward\": has_350_carryforward\n }\n \n passed = [k for k, v in checks.items() if v]\n failed = [k for k, v in checks.items() if not v]\n \n if len(failed) == 0:\n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"Hannah Price payroll email contains all required chargeback offset details for Megan Price\"}\n \n if best_failed is None or len(failed) < len(best_failed):\n best_failed = failed\n best_passed = passed\n best_subject = email.get(\"subject\", \"\")\n \n score = round(len(best_passed) / (len(best_passed) + len(best_failed)), 2)\n return {\"pass\": False, \"score\": min(score, 0.5), \"feedback\": f\"Hannah email '{best_subject}' — passed: {best_passed}, failed: {best_failed}\"}", "criterion_type": "expected_output" }, { "id": "aa30c6fc-f82f-48ea-80bd-60c1d3db0508", "sort_order": 4, "rubric_text": "In mailbox.json, no sent email may escalate Deal 4504 for the $75 recap variance (desk recap $6,275 vs posted $6,200)", "verifier_code": "from pathlib import Path\nimport json\n\ndef verify(workspace_path, external_services_path=None):\n # Check sent emails for escalation about 4504 variance\n escalation_found = False\n \n if external_services_path:\n mailbox_path = Path(external_services_path) / \"mailbox.json\"\n if mailbox_path.exists():\n with open(mailbox_path) as mf:\n mail_data = json.load(mf)\n sent = [e for e in mail_data.get(\"emails\", []) if e.get(\"folder\") == \"Sent\"]\n for email in sent:\n body = (email.get(\"body_text\") or \"\").lower()\n subject = (email.get(\"subject\") or \"\").lower()\n to_addr = (email.get(\"to_addr\") or \"\").lower()\n combined = body + \" \" + subject\n \n # Only flag if an email was sent TO someone about escalating 4504\n # Mentioning the variance for documentation purposes is fine\n if \"4504\" in combined and \"escalat\" in combined:\n if \"75\" in combined or \"variance\" in combined or \"6,275\" in combined or \"6275\" in combined:\n escalation_found = True\n break\n \n if escalation_found:\n return {\"pass\": False, \"score\": 0.0, \"feedback\": \"Escalation for Deal 4504 $75 variance found in sent email, but per SOP this variance should NOT be escalated; Deal 4504 should be processed at posted amount $6,200\"}\n \n return {\"pass\": True, \"score\": 1.0, \"feedback\": \"No improper escalation found for Deal 4504 $75 recap variance. Deal correctly processed without escalation.\"}", "criterion_type": "incorrect_behavior" }, { "id": "rubric_1776224326530", "sort_order": 5, "rubric_text": "In mailbox.json, the sent April payroll email to hannah.price@sunshineandsetauto.com must not include Deal 4505 (Carlos Vega) or Deal 4507 (Derek Vaughn) as a regular commission line item with a paid dollar amount; they may only appear in an exclusion note (e.g., 'excluded', 'unwound', 'not posted').", "verifier_code": "from pathlib import Path\nimport json\nimport re\n\n\ndef verify(workspace_path, external_services_path=None):\n if external_services_path is None:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"external_services_path is None; cannot check mailbox\"}\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\") == \"Sent\"]\n hannah_emails = [\n e for e in sent_emails\n if \"hannah.price@sunshineandsetauto.com\" in (e.get(\"to_addr\") or \"\")\n ]\n\n if not hannah_emails:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"No sent email to hannah.price@sunshineandsetauto.com found\"}\n\n # Find an April email\n april_email = None\n for email in hannah_emails:\n body = (email.get(\"body_text\") or \"\").lower()\n if \"april\" in body and (\"commission\" in body or \"payroll\" in body):\n april_email = email\n break\n\n if april_email is None:\n return {\"pass\": False, \"score\": 0.0,\n \"feedback\": \"No April payroll/commission email found to Hannah Price\"}\n\n body = (april_email.get(\"body_text\") or \"\").lower()\n\n excluded_deals = {\n \"4505\": \"unwound / posting reversed\",\n \"4507\": \"not posted in deal log\",\n }\n\n improperly_included = []\n properly_excluded = []\n\n for deal, reason in excluded_deals.items():\n if deal not in body:\n properly_excluded.append(f\"Deal {deal} ({reason}): not mentioned\")\n continue\n\n lines_with_deal = [line for line in body.split(\"\\n\") if deal in line]\n is_commission_line = False\n is_exclusion_note = False\n for line in lines_with_deal:\n has_dollar = bool(re.search(r\"\\$[\\d,]+\", line))\n has_exclusion_language = any(\n w in line for w in [\n \"exclud\", \"remov\", \"unwound\", \"unwind\", \"reversed\",\n \"not posted\", \"not include\", \"cannot\", \"ineligible\",\n \"outside\", \"note:\", \"(note\", \"withheld\", \"held\"\n ]\n )\n if has_exclusion_language:\n is_exclusion_note = True\n elif has_dollar and not has_exclusion_language:\n is_commission_line = True\n\n if is_commission_line and not is_exclusion_note:\n improperly_included.append(f\"Deal {deal} ({reason})\")\n else:\n properly_excluded.append(f\"Deal {deal} ({reason})\")\n\n if not improperly_included:\n return {\"pass\": True, \"score\": 1.0,\n \"feedback\": f\"Both 4505 and 4507 correctly kept out of commission line items: {properly_excluded}\"}\n\n score = round(len(properly_excluded) / len(excluded_deals), 2)\n return {\n \"pass\": False,\n \"score\": min(score, 0.5),\n \"feedback\": (\n f\"Deal(s) improperly included as commission line items: {improperly_included}. \"\n f\"Correctly excluded: {properly_excluded}\"\n ),\n }\n", "criterion_type": "incorrect_behavior" } ]