{
  "filename": "src/worker.rs",
  "rule": "- name: worker-has-shutdown-branch\n  where: \"src/worker.rs\"\n  ensure: >-\n    run_worker must select on stop.cancelled and break on cancellation, rather than wait indefinitely for another message.",
  "corrected": "use tokio::sync::mpsc;\nuse tokio_util::sync::CancellationToken;\n\npub async fn run_worker(mut jobs: mpsc::Receiver<String>, stop: CancellationToken) {\n    loop {\n        tokio::select! {\n            _ = stop.cancelled() => break,\n            message = jobs.recv() => {\n                match message {\n                    Some(job) => {\n                        if stop.is_cancelled() { break; }\n                        process(job).await;\n                    },\n                    None => break,\n                }\n            }\n        }\n    }\n}\n\nasync fn process(_job: String) {\n    tokio::task::yield_now().await;\n}\n",
  "broken": "use tokio::sync::mpsc;\nuse tokio_util::sync::CancellationToken;\n\npub async fn run_worker(mut jobs: mpsc::Receiver<String>, stop: CancellationToken) {\n    loop {\n        tokio::select! {\n            message = jobs.recv() => {\n                match message {\n                    Some(job) => {\n                        if stop.is_cancelled() { break; }\n                        process(job).await;\n                    },\n                    None => break,\n                }\n            }\n        }\n    }\n}\n\nasync fn process(_job: String) {\n    tokio::task::yield_now().await;\n}\n",
  "regression": [
    "            _ = stop.cancelled() => break,\n",
    ""
  ],
  "test_scenarios": [
    [
      "Worker blocked with no jobs",
      "Cancellation ends loop"
    ],
    [
      "Sender drops",
      "None ends loop"
    ],
    [
      "Pending delivery when shutdown arrives",
      "Delivery-specific timeout/recovery policy applies"
    ],
    [
      "Process exits",
      "JoinHandle awaited, no detached worker"
    ]
  ],
  "test_source": null,
  "test_command": "cargo test worker_shutdown"
}