feat(terminal): auto-detect tab icon from running command
The tab icon was hard-coded to `terminal`, which made multiple tabs
visually indistinguishable. Detect the running command from the OSC 2
title set by the shell's `preexec` (and from TUI tools that rewrite
their own title) and pick a per-command icon.
Detector pipeline (`WorktreeTerminalState`):
- Per-surface debounce on title changes — a candidate must hold the
title for ~1.5 s before being treated as a long-running command,
so transient titles set by `ls`/`git status` etc. don't cause icon
flicker.
- Idle-prompt suppression: shell prompts (`user@host:path`,
`~/path`, …) are filtered both by shape heuristics (bootstrap) and
by learning the first title that arrives after each
`command_finished` (per-surface adaptive set).
- Per-cycle dedupe: once a `[live]` icon is reported for a surface,
further title changes within the same command run (claude's
spinner cycling through `✳ Claude Code` → `⠐ Claude Code`) are
ignored until the next `command_finished` clears the guard.
- Substring path: TUI tools that rewrite their own title bypass the
debounce and the per-cycle guard so a branded title can refine the
icon set by the initial command name.
- Selection-2 semantics: the icon stays after the command exits, so
the tab keeps a long-lived "what is this for" hint. User-locked
icons (`isIconLocked`) and non-focused surfaces in a split tab are
never overridden.
Mapping & extensibility:
- `TabIconSource` is a struct with a required `systemSymbol` and an
optional `assetName`. `assetName` is the reserved entry point for
per-tool PNG/SVG artwork (claude, docker, npm, …); rendering still
paints `systemSymbol` until the icon-rendering call sites are
taught to read `assetName` (recipe documented on the type).
- `CommandIconMap` ships ~30 first-token entries (editors, package
managers, build tools, containers, network, system viewers, db,
logs, coding agents) and a substring entry for `claude code`.
The detector currently emits log lines under the `CommandDetect`
category to make further tuning observable.