<reasoning_content>
*   Extend a `JobQueue` class.
    *   Method: `process_job(job_id: str, processor: Callable) -> bool`.
    *   `processor` takes `data` (retrieved from the initial `add_job`).
    *   Retry logic:
        *   Max 4 attempts (1 initial + 3 retries).
        *   Exception handling: Catch any exception from `processor`.
        *   Exponential backoff: Delays of 1s, 2s, 4s.
        *   Constraint: Do *not* actually sleep; record delays in the data dictionary.
        *   Return `True` on success, `False` on failure after all retries.
    *   `add_job(job_id, data)` is mentioned as the way jobs are added.
    *   Standard library only.
    *   No explanations, just code.

    *   `JobQueue` needs a storage mechanism for jobs (likely a dictionary mapping `job_id` to `data`).
    *   `add_job(job_id: str, data: dict)`: Stores data.
    *   `process_job(job_id: str, processor: Callable) -> bool`:
        *   Get `data` for `job_id`.
        *   Loop for up to 4 attempts.
        *   Inside loop:
            *   Try `processor(data)`.
            *   If successful, return `True`.
            *   If `Exception`:
                *   Check if we have retries left.
                *   Calculate delay: $2^{\text{attempt\_index}-1}$ or specific sequence (1, 2, 4).
                *   Add delay to `data['delays']` (need to initialize if not exists).
                *   Increment retry count? Actually, the prompt says "Track the retry count per job" and "record the delays as data". It doesn't explicitly say to store a `retry_count` key in data, but implies tracking. Let's use a key like `retries` or just rely on the loop index.
                *   Wait, "record the delays as data". If the processor is called, it might modify `data`.

    *   `self.jobs = {}`
    *   `add_job(job_id, data)`: `self.jobs[job_id] = data`
    *   `process_job(job_id, processor)`:
        ```python
        data = self.jobs.get(job_id)
        if data is None: return False # Or raise error, but False is safer
        
        delays = [] # or use data['delays'] if it's meant to persist in the job object
        
        for attempt in range(4):
            try:
                processor(data)
                return True
            except Exception:
                if attempt < 3: # 0, 1, 2 (total 3 retries)
                    delay = 2 ** attempt # 1, 2, 4
                    if 'delays' not in data:
                        data['delays'] = []
                    data['delays'].append(delay)
                else:
                    return False
        ```

    *   "Track the retry count per job". This could mean a private attribute or inside the data dict. Since the prompt says "record the delays as data", I'll put the delays in the `data` dictionary.
    *   Backoff sequence: 1s, 2s, 4s.
        *   Attempt 0: Success or Fail. If Fail, delay 1s.
        *   Attempt 1: Success or Fail. If Fail, delay 2s.
        *   Attempt 2: Success or Fail. If Fail, delay 4s.
        *   Attempt 3: Success or Fail. If Fail, return False.
    *   Total attempts = 4.
    *   Retries = 3.

    *   "record the delays as data" -> `data['delays'] = [1, 2, 4]`.
    *   Wait, if it succeeds on attempt 2, `data['delays']` should have `[1]`.

    ```python
    from typing import Callable, Dict, Any

    class JobQueue:
        def __init__(self):
            self.jobs: Dict[str, Dict[str, Any]] = {}

        def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
            self.jobs[job_id] = data

        def process_job(self, job_id: str, processor: Callable) -> bool:
            if job_id not in self.jobs:
                return False
            
            data = self.jobs[job_id]
            # Initialize delays if not present to avoid KeyError
            if 'delays' not in data:
                data['delays'] = []
                
            max_attempts = 4
            for attempt in range(max_attempts):
                try:
                    processor(data)
                    return True
                except Exception:
                    # If it's the last attempt, don't record a delay for a future that won't happen
                    if attempt < max_attempts - 1:
                        delay = 2 ** attempt # 2^0=1, 2^1=2, 2^2=4
                        data['delays'].append(delay)
                    else:
                        return False
            return False
    ```

    *   `processor(data)`: Yes.
    *   Retry up to 4 total attempts: Yes.
    *   Exponential backoff (1, 2, 4): Yes.
    *   Do NOT sleep: Yes.
    *   Record delays as data: Yes.
    *   Return True on success, False on all 4 fails: Yes.
    *   Standard library only: Yes.
    *   Python code only: Yes.

    One edge case: Does "Track the retry count per job" mean I need a separate field? The prompt says "Track the retry count per job" AND "record the delays as data". I will add `data['retry_count']` to be safe, or maybe the count is implicit in the length of `delays`. Usually, in these coding challenges, if they say "record X as data", they want the side effect on the passed dict.

    Let's look at the "Track the retry count per job" requirement again.
    If I add `data['retry_count'] = attempt` (if failed), that satisfies it.

    Revised loop:
    ```python
    for attempt in range(4):
        try:
            processor(data)
            return True
        except Exception:
            if attempt < 3:
                delay = 2 ** attempt
                if 'delays' not in data:
                    data['delays'] = []
                data['delays'].append(delay)
                data['retry_count'] = attempt + 1
            else:
                return False
    ```

    Actually, if the prompt says "Track the retry count per job", and the instruction "record the delays as data" follows, it's likely that the metadata should live in the `data` dictionary.

    Wait, if I use `range(4)`:
    Attempt 0: Fail -> `data['delays'].append(1)`, `attempt` is 0.
    Attempt 1: Fail -> `data['delays'].append(2)`, `attempt` is 1.
    Attempt 2: Fail -> `data['delays'].append(4)`, `attempt` is 2.
    Attempt 3: Fail -> return False.

    Total attempts: 4.
    Retries performed: 3.

    Let's ensure `retry_count` is correctly updated.
    If attempt 0 fails, we have 1 retry pending.
    If attempt 1 fails, we have 2 retries pending.

    Wait, the instruction is "Track the retry count per job". I'll use `data['retry_count']`.

    Let's refine the `retry_count` logic.
    If `processor` fails:
    Attempt 0 (Initial): `retry_count` becomes 1.
    Attempt 1 (Retry 1): `retry_count` becomes 2.
    Attempt 2 (Retry 2): `retry_count` becomes 3.
    Attempt 3 (Retry 3): `retry_count` becomes 4? No, that's the 4th attempt.
    Usually, "retry count" means "how many times have we retried?".
    If it fails the first time, retry count = 1.

    Let's keep it simple and follow the "record delays as data" literally.

    ```python
    from typing import Callable, Dict, Any

    class JobQueue:
        def __init__(self):
            self.jobs: Dict[str, Dict[str, Any]] = {}

        def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
            self.jobs[job_id] = data

        def process_job(self, job_id: str, processor: Callable) -> bool:
            if job_id not in self.jobs:
                return False
            
            data = self.jobs[job_id]
            if 'delays' not in data:
                data['delays'] = []
            if 'retry_count' not in data:
                data['retry_count'] = 0

            for attempt in range(4):
                try:
                    processor(data)
                    return True
                except Exception:
                    if attempt < 3:
                        delay = 2 ** attempt
                        data['delays'].append(delay)
                        data['retry_count'] += 1
                    else:
                        return False
            return False
    ```

    Wait, if I call `process_job` once and it fails 4 times, `retry_count` will be 3.
    If it succeeds on the 2nd attempt (1st retry), `retry_count` will be 1.
    This seems logical.

    Final check on requirements:
    1. Call `processor(data)`: Yes.
    2. Max 4 attempts: Yes.
    3. Track retry count + exponential backoff (1, 2, 4): Yes.
    4. Do not sleep, record delays as data: Yes.
    5. Return True on success, False on all 4 fails: Yes.

    One detail: `data` passed to `add_job` is the same dict that gets modified. This is standard Python behavior.

    One more thing: "Track the retry count per job". I'll use `data['retry_count']`.

    Wait, if the user calls `process_job` multiple times for the same job? The prompt doesn't specify, but usually, it's a one-shot process or the job is removed. I'll stick to the provided requirements.

    ```python
    from typing import Callable, Dict, Any

    class JobQueue:
        def __init__(self):
            self.jobs: Dict[str, Dict[str, Any]] = {}

        def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
            self.jobs[job_id] = data

        def process_job(self, job_id: str, processor: Callable) -> bool:
            if job_id not in self.jobs:
                return False
            
            data = self.jobs[job_id]
            if 'delays' not in data:
                data['delays'] = []
            if 'retry_count' not in data:
                data['retry_count'] = 0
                
            for attempt in range(4):
                try:
                    processor(data)
                    return True
                except Exception:
                    if attempt < 3:
                        delay = 2 ** attempt
                        data['delays'].append(delay)
                        data['retry_count'] += 1
                    else:
                        return False
            return False
    ```

    Is `2**attempt` correct for 1, 2, 4?
    attempt 0: $2^0 = 1$
    attempt 1: $2^1 = 2$
    attempt 2: $2^2 = 4$
    Yes.

    Is `range(4)` correct?
    0, 1, 2, 3.
    If attempt 3 (the 4th attempt) fails, `if attempt < 3` is false, it hits `else: return False`.
    Correct.

    Wait, if `processor` succeeds on the very first try (attempt 0), `retry_count` is 0.
    If it succeeds on attempt 1 (first retry), `retry_count` is 1.
    This is correct.

    Final code structure:
    ```python
    from typing import Callable, Dict, Any

    class JobQueue:
        def __init__(self):
            self.jobs = {}

        def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
            self.jobs[job_id] = data

        def process_job(self, job_id: str, processor: Callable) -> bool:
            if job_id not in self.jobs:
                return False
            
            data = self.jobs[job_id]
            if 'delays' not in data:
                data['delays'] = []
            if 'retry_count' not in data:
                data['retry_count'] = 0
                
            for attempt in range(4):
                try:
                    processor(data)
                    return True
                except Exception:
                    if attempt < 3:
                        delay = 2 ** attempt
                        data['delays'].append(delay)
                        data['retry_count'] += 1
                    else:
                        return False
            return False
    ```

    Wait, the prompt asks to "Extend the JobQueue class". It implies `JobQueue` is already defined or I should provide the full definition. Since I must "Write only the Python code", I will provide the complete class.

    One small nuance: `data['retry_count']` is only incremented if there is a retry *planned*. If the 4th attempt fails, the loop exits via the `else` block. This is correct.

    Actually, I'll make sure `data['delays']` and `data['retry_count']` are updated exactly as requested.

    Wait, looking at the prompt again:
    "Track the retry count per job. Use exponential backoff... record the delays as data."
    It's slightly ambiguous if `retry_count` should be a key in `data` or if it just means I need to keep track of it during the loop. Given "record the delays as data", it's extremely likely `retry_count` should also be in `data`.

    Final check:
    `processor` signature: `processor(data)`.
    `add_job` signature: `add_job(job_id, data)`.
    Return value: `True` or `False`.

    What if `processor` modifies `data` in a way that affects subsequent attempts? That's expected in this type of pattern.

    ```python
    from typing import Callable, Dict, Any

    class JobQueue:
        def __init__(self):
            self.jobs: Dict[str, Dict[str, Any]] = {}

        def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
            self.jobs[job_id] = data

        def process_job(self, job_id: str, processor: Callable) -> bool:
            if job_id not in self.jobs:
                return False
            
            data = self.jobs[job_id]
            if 'delays' not in data:
                data['delays'] = []
            if 'retry_count' not in data:
                data['retry_count'] = 0
                
            for attempt in range(4):
                try:
                    processor(data)
                    return True
                except Exception:
                    if attempt < 3:
                        delay = 2 ** attempt
                        data['delays'].append(delay)
                        data['retry_count'] += 1
                    else:
                        return False
            return False
    ```
    This looks solid.
</reasoning_content>

<content>
```python
from typing import Callable, Dict, Any

class JobQueue:
    def __init__(self):
        self.jobs: Dict[str, Dict[str, Any]] = {}

    def add_job(self, job_id: str, data: Dict[str, Any]) -> None:
        self.jobs[job_id] = data

    def process_job(self, job_id: str, processor: Callable) -> bool:
        if job_id not in self.jobs:
            return False

        data = self.jobs[job_id]
        if 'delays' not in data:
            data['delays'] = []
        if 'retry_count' not in data:
            data['retry_count'] = 0

        for attempt in range(4):
            try:
                processor(data)
                return True
            except Exception:
                if attempt < 3:
                    delay = 2 ** attempt
                    data['delays'].append(delay)
                    data['retry_count'] += 1
                else:
                    return False
        return False
```
</content>