### Task 10: Restore `can_use_tool` enforcement on the dispatch path

**Root cause (verified):** `task_handler.py:1379` (and the rotation-retry copy at `:1663`) set `permission_mode="bypassPermissions"`. Under that mode the SDK never invokes `can_use_tool` (it's still passed at `:1398`, but dead). Layers 1–2 of the six-layer defense — file-tool path sandbox, Bash path checks, exempt-command jail check, and the now-fixed dangerous-command blocklist — never fire in production. OS sandbox (Layer 4) still blocks *writes*, but dangerous non-write commands (`sudo`, `curl --upload-file` exfil) are unblocked.

**Prerequisite:** Task 9 merged (otherwise this denies benign commands).

**Files:**
- Modify: `claw_forge/orchestrator/task_handler.py:1379` and `:1663` (`bypassPermissions` → `"default"`)
- Test: `tests/orchestrator/test_dispatch_permission_mode.py` (create) + a callback round-trip smoke test.

**Interfaces:**
- Consumes: the `make_can_use_tool(...)` callback already constructed at `:1398`. In `"default"` mode the SDK calls it for every tool; the callback returns `PermissionResultAllow` for everything it does not explicitly deny, so non-dangerous work is unaffected.

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

The mode is a literal in option assembly. Assert both option-construction sites use `"default"`, and add a callback round-trip test proving a dangerous command is denied and a benign one allowed:

```python
# tests/orchestrator/test_dispatch_permission_mode.py
import inspect
from claw_forge.orchestrator import task_handler as th
from claw_forge.agent.permissions import make_can_use_tool


def test_dispatch_does_not_use_bypass_permissions():
    src = inspect.getsource(th)
    assert 'permission_mode="bypassPermissions"' not in src
    assert src.count('permission_mode="default"') >= 2


import pytest
from pathlib import Path


@pytest.mark.asyncio
async def test_callback_denies_sudo_allows_ls(tmp_path: Path):
    cb = make_can_use_tool(project_dir=tmp_path)

    class _Ctx:  # minimal ToolPermissionContext stand-in
        pass

    deny = await cb("Bash", {"command": "sudo rm -rf /"}, _Ctx())
    assert deny.behavior == "deny"
    allow = await cb("Bash", {"command": "ls -la"}, _Ctx())
    assert allow.behavior == "allow"
```

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

Run: `uv run pytest tests/orchestrator/test_dispatch_permission_mode.py -v`
Expected: FAIL — source still contains `bypassPermissions`.

- [ ] **Step 3: Flip the mode at both sites**

In `claw_forge/orchestrator/task_handler.py`, change line 1379 and line 1663 from `permission_mode="bypassPermissions",` to `permission_mode="default",`.

**Verify the nested-sandbox matrix is untouched:** this change does not alter `_make_sdk_sandbox_settings(isolation_active=…)` (`:1370`), so Layer-4/5 nesting rules (`memory/project_nested_sandbox_landmine.md`) are unaffected — `"default"` governs the SDK's *permission callback*, not its `SandboxSettings`.

- [ ] **Step 4: Run the tests to verify they pass**

Run: `uv run pytest tests/orchestrator/test_dispatch_permission_mode.py tests/orchestrator/ -q`
Expected: PASS.

- [ ] **Step 5: Manual smoke sanity (optional but recommended)**

Because `"default"` mode can prompt for tools the callback neither allows nor denies, confirm the callback's final `return PermissionResultAllow(...)` (`permissions.py:401` and the `_can_use_tool` tail) is the catch-all so no task stalls awaiting an interactive prompt. Grep: `uv run pytest tests/agent/test_permissions.py -q` in isolation.
Expected: PASS.

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

Run: `uv run ruff check claw_forge/ tests/`
```bash
git add claw_forge/orchestrator/task_handler.py tests/orchestrator/test_dispatch_permission_mode.py
git commit -m "fix(security): enforce can_use_tool on dispatch path (default mode, not bypassPermissions)"
```

---

