{
  "kind": "original-bounded-choice-workflow",
  "version": 1,
  "scope": "Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.",
  "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
  "choices": [
    "Cleanup",
    "Gap",
    "Notongoing",
    "Unclear"
  ],
  "actions": {
    "Cleanup": {
      "action": "preview_jev_react_effect_cleanup",
      "payload": {
        "decision": "Cleanup"
      },
      "pending": true
    },
    "Gap": {
      "action": "preview_jev_react_effect_cleanup",
      "payload": {
        "decision": "Gap"
      },
      "pending": true
    },
    "Notongoing": {
      "action": "preview_jev_react_effect_cleanup",
      "payload": {
        "decision": "Notongoing"
      },
      "pending": true
    },
    "Unclear": {
      "action": "preview_jev_react_effect_cleanup",
      "payload": {
        "decision": "Unclear"
      },
      "pending": true
    }
  },
  "samples": [
    {
      "id": "case-1",
      "label": "Interval cleared",
      "expected": "Cleanup",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => { const id = setInterval(tick, 1000); return () => clearInterval(id); }, []);\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    },
    {
      "id": "case-2",
      "label": "Listener left active",
      "expected": "Gap",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => { window.addEventListener(\\\"resize\\\", onResize); }, []);\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    },
    {
      "id": "case-3",
      "label": "Matching listener",
      "expected": "Cleanup",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => { window.addEventListener(\\\"resize\\\", onResize); return () => window.removeEventListener(\\\"resize\\\", onResize); }, []);\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    },
    {
      "id": "case-4",
      "label": "Title assignment",
      "expected": "Notongoing",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => { document.title = title; }, [title]);\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    },
    {
      "id": "case-5",
      "label": "Unknown wrapper",
      "expected": "Unclear",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => connectToFeed(), []);\",\n    \"helper\": \"connectToFeed implementation unavailable\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    },
    {
      "id": "case-6",
      "label": "Wrong timer cleared",
      "expected": "Gap",
      "request": {
        "context": "{\n  \"task\": \"Check whether a shown React effect pairs an ongoing resource with the corresponding cleanup.\",\n  \"evidence\": {\n    \"code\": \"useEffect(() => { const active = setInterval(tick, 1000); return () => clearInterval(oldTimer); }, []);\",\n    \"context\": \"oldTimer is a different timer; no other cleanup exists\"\n  }\n}",
        "question": "Review the effect and supplied helper contracts: Cleanup when ongoing timers, listeners or subscriptions have matching cleanup; Gap when a shown ongoing resource has no ending path; Notongoing when the effect starts no persistent resource. Use Unclear for missing helper behavior or incomplete lifecycle code. A cleanup for a different resource does not count. This is static review, not a measured memory leak.",
        "choices": [
          "Cleanup",
          "Gap",
          "Notongoing",
          "Unclear"
        ]
      }
    }
  ],
  "consumer": "preview_choice_workflow.py"
}
