# Session Workspace Binding

CTM sessions have three related concepts that must not be conflated:

- Launch/restore `cwd`: where CTM started or resumed the PTY/provider process. This can be stale after an agent changes directory or moves work.
- Current runtime context: a provider/CTM-observed working directory signal, such as `update-session-cwd` or a future provider-native cwd hook/status event.
- Workspace binding: the verified project/worktree CTM should use for branch badges, worktree attention, and finish gates.

The binding resolver intentionally treats launch/restore metadata and current runtime context differently. A durable identity should win over a plain restored repo-root cwd, but an explicitly observed current runtime cwd should win over old identity because it describes where the live session is now.

The workspace binding is resolved from the strongest verified source available:

1. Confirmed current runtime context (`session._runtimeWorkContext`) when its cwd/worktree path maps to a known git worktree, or to a canonical agent worktree path.
2. Runtime `worktree_path` or `cwd` captured at launch/restore when it maps to a known git worktree.
3. `ctm_sessions.project_path` / `ctm_sessions.cwd` when they point at an agent worktree.
4. Linked `agent_sessions.project_path` rows, ordered by recency.
5. Runtime branch only when it can be verified against the runtime path.

If sources conflict, CTM marks the binding ambiguous and hides the raw runtime branch badge instead of showing a misleading branch. This prevents a stale runtime branch such as `phone-*` from appearing on unrelated active sessions.

Branch refresh is now a verifier. It probes the confirmed current runtime context first; only sessions without that signal fall back to their resolved workspace binding. It may persist `startup_tasks.branch/worktree_path` after git verifies the branch, but it should not let an arbitrary restored cwd silently become session identity. Restore prefers a verified durable binding when one exists, so split-brain sessions recover into their intended worktree rather than falling back to the repo root.

`startup_tasks.cwd`, `startup_tasks.branch`, and `startup_tasks.worktree_path` remain lifecycle/restore state, not a second durable identity table. Current runtime provenance is kept in memory on the session object and is recalculated from provider/CTM signals after restart. If CTM needs this to survive restart later, add explicit provenance fields instead of overloading `agent_sessions.project_path`.

Do not infer current worktree by scraping terminal text. Prefer explicit host/provider signals:

- Claude Code exposes workspace cwd/worktree in status-line and hook data, including cwd-change hooks.
- Codex/Cursor-style integrations should use their app-server/session metadata or CTM-side cwd update messages when available.
- Shell text remains presentation, not authority.

## UI Contract

The active sidebar and tab strip use `workspaceBinding.displayBranch` first, then fall back to the raw `branch` only when the binding does not say the runtime branch is unverified. Worktree attention badges continue to come from `worktreeStatus`, but that status is computed against the resolved workspace binding.
