{
  "filename": "src/useCancellation.js",
  "rule": "- name: optimistic-failure-restores-state\n  where: \"src/useCancellation.js\"\n  ensure: >-\n    When cancelOnServer rejects, the optimistic cancelling state must be replaced with the previous order before reporting the error.",
  "corrected": "import { useRef, useState } from \"react\";\n\nexport function useCancellation(initialOrder, cancelOnServer) {\n  const [order, setOrder] = useState(initialOrder);\n  const [error, setError] = useState(null);\n  const inFlight = useRef(false);\n  async function cancel() {\n    if (inFlight.current) return false;\n    inFlight.current = true;\n    const previous = order;\n    setError(null);\n    setOrder({...previous,status:\"cancelling\"});\n    try {\n      const confirmed = await cancelOnServer(previous.id, previous.version);\n      setOrder(confirmed);\n      return true;\n    } catch (failure) {\n      setOrder(previous);\n      setError(failure);\n      return false;\n    } finally {\n      inFlight.current = false;\n    }\n  }\n  return {order,error,cancel};\n}\n",
  "broken": "import { useRef, useState } from \"react\";\n\nexport function useCancellation(initialOrder, cancelOnServer) {\n  const [order, setOrder] = useState(initialOrder);\n  const [error, setError] = useState(null);\n  const inFlight = useRef(false);\n  async function cancel() {\n    if (inFlight.current) return false;\n    inFlight.current = true;\n    const previous = order;\n    setError(null);\n    setOrder({...previous,status:\"cancelling\"});\n    try {\n      const confirmed = await cancelOnServer(previous.id, previous.version);\n      setOrder(confirmed);\n      return true;\n    } catch (failure) {\n      setError(failure);\n      return false;\n    } finally {\n      inFlight.current = false;\n    }\n  }\n  return {order,error,cancel};\n}\n",
  "regression": [
    "      setOrder(previous);\n",
    ""
  ],
  "test_scenarios": [
    [
      "Server accepts",
      "Authoritative returned order shown"
    ],
    [
      "Server rejects stale version",
      "Previous local order restored and error shown"
    ],
    [
      "Double click",
      "Second mutation is not sent"
    ],
    [
      "Lost acknowledgement",
      "Caller must re-fetch authoritative state and prevent retry until reconciliation"
    ]
  ],
  "test_source": null,
  "test_command": "npx vitest run src/useCancellation.test.jsx"
}