Full event evidence
{
"id": "a32815f7-971b-4ed0-82db-7c26068f7b3b",
"timestamp": "2026-10-18T19:59:08.652301",
"source": "agent",
"parent_id": "a0cddd3f-fc15-462c-94d4-3d82c8ad9232",
"thought": [],
"reasoning_content": null,
"thinking_blocks": [],
"action": {
"command": "create",
"path": "/Users/instructor/Code/harness-engineering/experiments/workshop4-substitutes-20261018/runs/ledger-flash-01/workspace/test_ledger.py",
"file_text": "import unittest\n\nfrom ledger import balance\n\nA = \"alice\"\nB = \"bob\"\n\n\ndef ev(id_, seq, account, kind, cents=None, target=None):\n e = {\"id\": id_, \"seq\": seq, \"account\": account, \"kind\": kind}\n if cents is not None:\n e[\"cents\"] = cents\n if target is not None:\n e[\"target\"] = target\n return e\n\n\nclass TestNormalBehavior(unittest.TestCase):\n def test_empty_input_returns_zero(self):\n self.assertEqual(balance([], A), 0)\n\n def test_input_is_unordered_processed_by_ascending_seq(self):\n events = [\n ev(\"d\", 4, A, \"debit\", 5),\n ev(\"c\", 1, A, \"credit\", 100),\n ev(\"c2\", 7, A, \"credit\", 25),\n ]\n self.assertEqual(balance(events, A), 120)\n\n def test_credit_debit_sum_for_requested_account(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"c2\", 2, A, \"credit\", 250),\n ev(\"d1\", 3, A, \"debit\", 75),\n ]\n self.assertEqual(balance(events, A), 275)\n\n def test_other_accounts_share_the_ledger_but_not_the_balance(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"c2\", 2, B, \"credit\", 9999),\n ev(\"d1\", 3, A, \"debit\", 25),\n ]\n self.assertEqual(balance(events, A), 75)\n self.assertEqual(balance(events, B), 9999)\n\n def test_exact_duplicate_delivery_retries_count_once(self):\n dup = ev(\"c1\", 1, A, \"credit\", 100)\n events = [dup, dict(dup), ev(\"d1\", 3, A, \"debit\", 20)]\n self.assertEqual(balance(events, A), 80)\n\n def test_exact_duplicate_of_reversal_counts_once(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ]\n self.assertEqual(balance(events, A), 0)\n\n def test_reversal_cancels_target_signed_amount(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"d1\", 2, A, \"debit\", 40),\n ev(\"r1\", 3, A, \"reverse\", target=\"c1\"),\n ev(\"r2\", 4, A, \"reverse\", target=\"d1\"),\n ]\n self.assertEqual(balance(events, A), 0)\n\n def test_reversal_in_other_account_does_not_touch_balance(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"c2\", 2, B, \"credit\", 50),\n ev(\"r1\", 3, B, \"reverse\", target=\"c2\"),\n ]\n self.assertEqual(balance(events, A), 100)\n\n def test_input_is_not_mutated(self):\n events = [\n ev(\"c1\", 2, A, \"credit\", 100),\n ev(\"d1\", 1, A, \"debit\", 3),\n ]\n snapshot = [dict(e) for e in events]\n balance(events, A)\n self.assertEqual(events, snapshot)\n\n def test_return_value_is_plain_integer(self):\n self.assertIsInstance(balance([ev(\"c1\", 1, A, \"credit\", 10)], A), int)\n\n\nclass TestValidation(unittest.TestCase):\n def test_reverse_does_not_read_cents(self):\n # Old code did total -= e['cents'] on reversals, which has no cents key.\n events = [\n ev(\"c1\", 1, A, \"credit\", 100),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ]\n self.assertEqual(balance(events, A), 0)\n\n def test_reused_id_with_different_content_raises(self):\n events = [\n ev(\"x\", 1, A, \"credit\", 10),\n ev(\"x\", 2, A, \"credit\", 20),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_reused_id_with_different_content_on_another_account_raises(self):\n events = [\n ev(\"x\", 1, A, \"credit\", 10),\n ev(\"x\", 2, B, \"credit\", 10),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_unknown_kind_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, A, \"bonus\", 5)], A)\n\n def test_unknown_kind_in_other_account_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, B, \"bonus\", 5)], A)\n\n def test_negative_cents_raises(self):\n for cents in (-1, -100):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, A, \"credit\", cents)], A)\n\n def test_float_cents_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, A, \"credit\", 1.5)], A)\n\n def test_bool_cents_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, A, \"credit\", True)], A)\n\n def test_decimal_string_cents_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"x\", 1, A, \"credit\", \"12\")], A)\n\n def test_duplicate_seq_across_distinct_events_raises(self):\n events = [\n ev(\"a\", 1, A, \"credit\", 10),\n ev(\"b\", 1, A, \"credit\", 20),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_duplicate_seq_reversal_target_pair_raises(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 10),\n ev(\"r1\", 1, A, \"reverse\", target=\"c1\"),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_reversal_target_missing_raises(self):\n with self.assertRaises(ValueError):\n balance([ev(\"r1\", 1, A, \"reverse\", target=\"ghost\")], A)\n\n def test_reversal_target_later_raises(self):\n events = [\n ev(\"r1\", 1, A, \"reverse\", target=\"c1\"),\n ev(\"c1\", 2, A, \"credit\", 10),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_reversal_target_another_reversal_raises(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 10),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ev(\"r2\", 3, A, \"reverse\", target=\"r1\"),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_reversal_target_in_another_account_raises(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 10),\n ev(\"r1\", 2, B, \"reverse\", target=\"c1\"),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_already_reversed_target_raises(self):\n events = [\n ev(\"c1\", 1, A, \"credit\", 10),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ev(\"r2\", 3, A, \"reverse\", target=\"c1\"),\n ]\n with self.assertRaises(ValueError):\n balance(events, A)\n\n def test_duplicate_id_retry_that_would_alias_a_reversal_is_safe(self):\n # Delivery retry of the reversal must not count as a second reversal.\n base = [\n ev(\"c1\", 1, A, \"credit\", 10),\n ev(\"r1\", 2, A, \"reverse\", target=\"c1\"),\n ev(\"c2\", 3, A, \"credit\", 10),\n ]\n retry = base + [dict(base[1])]\n self.assertEqual(balance(base, A), 10)\n self.assertEqual(balance(retry, A), 10)\n\n\nif __name__ == \"__main__\":\n unittest.main()",
"kind": "FileEditorAction"
},
"tool_name": "file_editor",
"tool_call_id": "call_e9c1e5bd486a4ff682539029",
"tool_call": {
"id": "call_e9c1e5bd486a4ff682539029",
"name": "file_editor",
"arguments": "{\"command\": \"create\", \"path\": \"/Users/instructor/Code/harness-engineering/experiments/workshop4-substitutes-20261018/runs/ledger-flash-01/workspace/test_ledger.py\", \"file_text\": \"import unittest\\n\\nfrom ledger import balance\\n\\nA = \\\"alice\\\"\\nB = \\\"bob\\\"\\n\\n\\ndef ev(id_, seq, account, kind, cents=None, target=None):\\n e = {\\\"id\\\": id_, \\\"seq\\\": seq, \\\"account\\\": account, \\\"kind\\\": kind}\\n if cents is not None:\\n e[\\\"cents\\\"] = cents\\n if target is not None:\\n e[\\\"target\\\"] = target\\n return e\\n\\n\\nclass TestNormalBehavior(unittest.TestCase):\\n def test_empty_input_returns_zero(self):\\n self.assertEqual(balance([], A), 0)\\n\\n def test_input_is_unordered_processed_by_ascending_seq(self):\\n events = [\\n ev(\\\"d\\\", 4, A, \\\"debit\\\", 5),\\n ev(\\\"c\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 7, A, \\\"credit\\\", 25),\\n ]\\n self.assertEqual(balance(events, A), 120)\\n\\n def test_credit_debit_sum_for_requested_account(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, A, \\\"credit\\\", 250),\\n ev(\\\"d1\\\", 3, A, \\\"debit\\\", 75),\\n ]\\n self.assertEqual(balance(events, A), 275)\\n\\n def test_other_accounts_share_the_ledger_but_not_the_balance(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, B, \\\"credit\\\", 9999),\\n ev(\\\"d1\\\", 3, A, \\\"debit\\\", 25),\\n ]\\n self.assertEqual(balance(events, A), 75)\\n self.assertEqual(balance(events, B), 9999)\\n\\n def test_exact_duplicate_delivery_retries_count_once(self):\\n dup = ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100)\\n events = [dup, dict(dup), ev(\\\"d1\\\", 3, A, \\\"debit\\\", 20)]\\n self.assertEqual(balance(events, A), 80)\\n\\n def test_exact_duplicate_of_reversal_counts_once(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reversal_cancels_target_signed_amount(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"d1\\\", 2, A, \\\"debit\\\", 40),\\n ev(\\\"r1\\\", 3, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 4, A, \\\"reverse\\\", target=\\\"d1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reversal_in_other_account_does_not_touch_balance(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, B, \\\"credit\\\", 50),\\n ev(\\\"r1\\\", 3, B, \\\"reverse\\\", target=\\\"c2\\\"),\\n ]\\n self.assertEqual(balance(events, A), 100)\\n\\n def test_input_is_not_mutated(self):\\n events = [\\n ev(\\\"c1\\\", 2, A, \\\"credit\\\", 100),\\n ev(\\\"d1\\\", 1, A, \\\"debit\\\", 3),\\n ]\\n snapshot = [dict(e) for e in events]\\n balance(events, A)\\n self.assertEqual(events, snapshot)\\n\\n def test_return_value_is_plain_integer(self):\\n self.assertIsInstance(balance([ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10)], A), int)\\n\\n\\nclass TestValidation(unittest.TestCase):\\n def test_reverse_does_not_read_cents(self):\\n # Old code did total -= e['cents'] on reversals, which has no cents key.\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reused_id_with_different_content_raises(self):\\n events = [\\n ev(\\\"x\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"x\\\", 2, A, \\\"credit\\\", 20),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reused_id_with_different_content_on_another_account_raises(self):\\n events = [\\n ev(\\\"x\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"x\\\", 2, B, \\\"credit\\\", 10),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_unknown_kind_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"bonus\\\", 5)], A)\\n\\n def test_unknown_kind_in_other_account_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, B, \\\"bonus\\\", 5)], A)\\n\\n def test_negative_cents_raises(self):\\n for cents in (-1, -100):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", cents)], A)\\n\\n def test_float_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", 1.5)], A)\\n\\n def test_bool_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", True)], A)\\n\\n def test_decimal_string_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", \\\"12\\\")], A)\\n\\n def test_duplicate_seq_across_distinct_events_raises(self):\\n events = [\\n ev(\\\"a\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"b\\\", 1, A, \\\"credit\\\", 20),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_duplicate_seq_reversal_target_pair_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_missing_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"ghost\\\")], A)\\n\\n def test_reversal_target_later_raises(self):\\n events = [\\n ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"c1\\\", 2, A, \\\"credit\\\", 10),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_another_reversal_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 3, A, \\\"reverse\\\", target=\\\"r1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_in_another_account_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, B, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_already_reversed_target_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 3, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_duplicate_id_retry_that_would_alias_a_reversal_is_safe(self):\\n # Delivery retry of the reversal must not count as a second reversal.\\n base = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"c2\\\", 3, A, \\\"credit\\\", 10),\\n ]\\n retry = base + [dict(base[1])]\\n self.assertEqual(balance(base, A), 10)\\n self.assertEqual(balance(retry, A), 10)\\n\\n\\nif __name__ == \\\"__main__\\\":\\n unittest.main()\"}",
"origin": "completion"
},
"llm_response_id": "gen-1792371526-KpoEQAnA3cLDitVHhkXn",
"security_risk": "UNKNOWN",
"summary": "file_editor: {\"command\": \"create\", \"path\": \"/Users/instructor/Code/harness-engineering/experiments/workshop4-substitutes-20261018/runs/ledger-flash-01/workspace/test_ledger.py\", \"file_text\": \"import unittest\\n\\nfrom ledger import balance\\n\\nA = \\\"alice\\\"\\nB = \\\"bob\\\"\\n\\n\\ndef ev(id_, seq, account, kind, cents=None, target=None):\\n e = {\\\"id\\\": id_, \\\"seq\\\": seq, \\\"account\\\": account, \\\"kind\\\": kind}\\n if cents is not None:\\n e[\\\"cents\\\"] = cents\\n if target is not None:\\n e[\\\"target\\\"] = target\\n return e\\n\\n\\nclass TestNormalBehavior(unittest.TestCase):\\n def test_empty_input_returns_zero(self):\\n self.assertEqual(balance([], A), 0)\\n\\n def test_input_is_unordered_processed_by_ascending_seq(self):\\n events = [\\n ev(\\\"d\\\", 4, A, \\\"debit\\\", 5),\\n ev(\\\"c\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 7, A, \\\"credit\\\", 25),\\n ]\\n self.assertEqual(balance(events, A), 120)\\n\\n def test_credit_debit_sum_for_requested_account(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, A, \\\"credit\\\", 250),\\n ev(\\\"d1\\\", 3, A, \\\"debit\\\", 75),\\n ]\\n self.assertEqual(balance(events, A), 275)\\n\\n def test_other_accounts_share_the_ledger_but_not_the_balance(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, B, \\\"credit\\\", 9999),\\n ev(\\\"d1\\\", 3, A, \\\"debit\\\", 25),\\n ]\\n self.assertEqual(balance(events, A), 75)\\n self.assertEqual(balance(events, B), 9999)\\n\\n def test_exact_duplicate_delivery_retries_count_once(self):\\n dup = ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100)\\n events = [dup, dict(dup), ev(\\\"d1\\\", 3, A, \\\"debit\\\", 20)]\\n self.assertEqual(balance(events, A), 80)\\n\\n def test_exact_duplicate_of_reversal_counts_once(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reversal_cancels_target_signed_amount(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"d1\\\", 2, A, \\\"debit\\\", 40),\\n ev(\\\"r1\\\", 3, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 4, A, \\\"reverse\\\", target=\\\"d1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reversal_in_other_account_does_not_touch_balance(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"c2\\\", 2, B, \\\"credit\\\", 50),\\n ev(\\\"r1\\\", 3, B, \\\"reverse\\\", target=\\\"c2\\\"),\\n ]\\n self.assertEqual(balance(events, A), 100)\\n\\n def test_input_is_not_mutated(self):\\n events = [\\n ev(\\\"c1\\\", 2, A, \\\"credit\\\", 100),\\n ev(\\\"d1\\\", 1, A, \\\"debit\\\", 3),\\n ]\\n snapshot = [dict(e) for e in events]\\n balance(events, A)\\n self.assertEqual(events, snapshot)\\n\\n def test_return_value_is_plain_integer(self):\\n self.assertIsInstance(balance([ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10)], A), int)\\n\\n\\nclass TestValidation(unittest.TestCase):\\n def test_reverse_does_not_read_cents(self):\\n # Old code did total -= e['cents'] on reversals, which has no cents key.\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 100),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n self.assertEqual(balance(events, A), 0)\\n\\n def test_reused_id_with_different_content_raises(self):\\n events = [\\n ev(\\\"x\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"x\\\", 2, A, \\\"credit\\\", 20),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reused_id_with_different_content_on_another_account_raises(self):\\n events = [\\n ev(\\\"x\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"x\\\", 2, B, \\\"credit\\\", 10),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_unknown_kind_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"bonus\\\", 5)], A)\\n\\n def test_unknown_kind_in_other_account_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, B, \\\"bonus\\\", 5)], A)\\n\\n def test_negative_cents_raises(self):\\n for cents in (-1, -100):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", cents)], A)\\n\\n def test_float_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", 1.5)], A)\\n\\n def test_bool_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", True)], A)\\n\\n def test_decimal_string_cents_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"x\\\", 1, A, \\\"credit\\\", \\\"12\\\")], A)\\n\\n def test_duplicate_seq_across_distinct_events_raises(self):\\n events = [\\n ev(\\\"a\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"b\\\", 1, A, \\\"credit\\\", 20),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_duplicate_seq_reversal_target_pair_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_missing_raises(self):\\n with self.assertRaises(ValueError):\\n balance([ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"ghost\\\")], A)\\n\\n def test_reversal_target_later_raises(self):\\n events = [\\n ev(\\\"r1\\\", 1, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"c1\\\", 2, A, \\\"credit\\\", 10),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_another_reversal_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 3, A, \\\"reverse\\\", target=\\\"r1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_reversal_target_in_another_account_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, B, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_already_reversed_target_raises(self):\\n events = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"r2\\\", 3, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ]\\n with self.assertRaises(ValueError):\\n balance(events, A)\\n\\n def test_duplicate_id_retry_that_would_alias_a_reversal_is_safe(self):\\n # Delivery retry of the reversal must not count as a second reversal.\\n base = [\\n ev(\\\"c1\\\", 1, A, \\\"credit\\\", 10),\\n ev(\\\"r1\\\", 2, A, \\\"reverse\\\", target=\\\"c1\\\"),\\n ev(\\\"c2\\\", 3, A, \\\"credit\\\", 10),\\n ]\\n retry = base + [dict(base[1])]\\n self.assertEqual(balance(base, A), 10)\\n self.assertEqual(balance(retry, A), 10)\\n\\n\\nif __name__ == \\\"__main__\\\":\\n unittest.main()\"}",
"kind": "ActionEvent"
}