### Task 1: Fix `run_agent()` — crashes on every non-dispatcher call

**Root cause (verified):** `claude_agent_sdk/_internal/client.py:54-58` raises `ValueError` when `options.can_use_tool` is set **and** the prompt is not an `AsyncIterable` (streaming mode). `runner.py:242` unconditionally sets `can_use_tool=make_can_use_tool(...)`, and `run_agent(prompt: str, …)` at `runner.py:32-33` passes a plain string to `query(prompt=prompt, …)` at `runner.py:257`. Every caller of `run_agent`/`collect_result`/`collect_structured_result` (`claw-forge fix`, `boundaries apply`, the boundaries classifier) dies before any API call. Secondary bug: `runner.py:128-129` exports `env["CLAUDE_OAUTH_TOKEN"]` — a var the CLI never reads (correct var is `ANTHROPIC_AUTH_TOKEN`, per `task_handler.py:409`).

**Files:**
- Modify: `claw_forge/agent/runner.py` (string→AsyncIterable wrap near line 257; OAuth env var near line 128)
- Test: `tests/agent/test_runner_streaming.py` (create)

**Interfaces:**
- Consumes: `claude_agent_sdk.query`, `ClaudeAgentOptions` (already imported in `runner.py`).
- Produces: `run_agent()` that runs with a string prompt without raising `ValueError`; the SDK message format for a streaming prompt is `{"type": "user", "message": {"role": "user", "content": <prompt>}}`.

- [ ] **Step 1: Write the failing test**

The `ValueError` fires at option-assembly time, before any network call, so no API mock is needed. Assert that `run_agent` gets *past* SDK validation (it will fail later on transport/auth, which is fine — we only need to prove the `can_use_tool`+string-prompt `ValueError` is gone).

```python
# tests/agent/test_runner_streaming.py
import pytest
from claw_forge.agent import runner


@pytest.mark.asyncio
async def test_run_agent_string_prompt_does_not_raise_can_use_tool_valueerror():
    """A string prompt + can_use_tool must NOT raise the SDK streaming-mode
    ValueError. It may fail later (no creds/transport), but not with that."""
    gen = runner.run_agent("say hi", cwd=None, project_dir=None)
    try:
        async for _ in gen:
            break  # got at least one message → definitely past validation
    except ValueError as exc:
        if "can_use_tool callback requires streaming mode" in str(exc):
            pytest.fail("run_agent still passes a non-streaming prompt with can_use_tool")
    except Exception:
        pass  # transport/auth failure is acceptable — validation was passed
```

- [ ] **Step 2: Run test to verify it fails**

Run: `uv run pytest tests/agent/test_runner_streaming.py -v`
Expected: FAIL — `run_agent still passes a non-streaming prompt with can_use_tool`.

- [ ] **Step 3: Wrap the prompt in a one-item async iterator**

In `claw_forge/agent/runner.py`, immediately before `raw_stream = query(prompt=prompt, options=options)` (line 257), convert a string prompt into the SDK's streaming message form:

```python
    if isinstance(prompt, str):
        _prompt_text = prompt

        async def _single_message_stream() -> Any:
            yield {
                "type": "user",
                "message": {"role": "user", "content": _prompt_text},
            }

        stream_prompt: Any = _single_message_stream()
    else:
        stream_prompt = prompt

    raw_stream = query(prompt=stream_prompt, options=options)
```

- [ ] **Step 4: Fix the OAuth env var**

In `claw_forge/agent/runner.py` near line 128, change the wrong var name:

```python
        if getattr(provider_config, "oauth_token", None):
            env["ANTHROPIC_AUTH_TOKEN"] = provider_config.oauth_token  # type: ignore[assignment]
```

- [ ] **Step 5: Run the test to verify it passes**

Run: `uv run pytest tests/agent/test_runner_streaming.py -v`
Expected: PASS.

- [ ] **Step 6: Lint + commit**

Run: `uv run ruff check claw_forge/ tests/`
```bash
git add claw_forge/agent/runner.py tests/agent/test_runner_streaming.py
git commit -m "fix(runner): stream string prompts so can_use_tool works; correct OAuth env var"
```

---

