{
  "filename": "lib/shop/orders.ex",
  "rule": "- name: confirmation-records-audit\n  where: \"lib/shop/orders.ex\"\n  ensure: >-\n    confirm must use Multi.insert(:audit, Audit.changeset(...)) in the Multi. A Multi.run callback returning skipped instead of persisting the audit violates this requirement.",
  "corrected": "defmodule Shop.Orders do\n  alias Ecto.Multi\n  alias Shop.{Repo, Order, Audit}\n\n  def confirm(scope, order) do\n    if order.tenant_id != scope.tenant_id, do: raise(\"tenant mismatch\")\n    Multi.new()\n    |> Multi.update(:order, Order.changeset(order, %{status: \"confirmed\"}) |> Ecto.Changeset.optimistic_lock(:lock_version))\n    |> Multi.insert(:audit, Audit.changeset(%Audit{}, %{order_id: order.id, actor_id: scope.user.id}))\n    |> Repo.transact()\n  end\nend\n",
  "broken": "defmodule Shop.Orders do\n  alias Ecto.Multi\n  alias Shop.{Repo, Order, Audit}\n\n  def confirm(scope, order) do\n    if order.tenant_id != scope.tenant_id, do: raise(\"tenant mismatch\")\n    Multi.new()\n    |> Multi.update(:order, Order.changeset(order, %{status: \"confirmed\"}) |> Ecto.Changeset.optimistic_lock(:lock_version))\n    |> Multi.run(:audit, fn _repo, _changes -> {:ok, :skipped} end)\n    |> Repo.transact()\n  end\nend\n",
  "regression": [
    "    |> Multi.insert(:audit, Audit.changeset(%Audit{}, %{order_id: order.id, actor_id: scope.user.id}))",
    "    |> Multi.run(:audit, fn _repo, _changes -> {:ok, :skipped} end)"
  ],
  "test_scenarios": [
    [
      "Valid state and audit",
      "{:ok, ...} with both changes"
    ],
    [
      "Audit validation fails",
      "Order rolls back and named error returned"
    ],
    [
      "Tenant mismatch",
      "Rejected before transaction"
    ],
    [
      "Concurrent confirmation",
      "State/locking rule prevents repeated transition"
    ]
  ],
  "test_source": null,
  "test_command": "mix test test/shop/orders_transaction_test.exs"
}