Codex sessions were second-class: they ran, but the card had no idea what they were doing. The Codex hook now reports status through codexStatusFor and reportCodexStatus, wired up in codex/config.toml, so a Codex session drives the same running/waiting states as a Claude one and its card behaves like every other card.

Making that work meant threading the harness properly rather than assuming Claude everywhere. harnessActivityFields carries it through activity records, interactiveRespawnPlan and restoreInteractiveSession branch on it when rebuilding a session, and the web UI’s action handlers know which harness they’re talking to. respawnPlan got noticeably smaller in the process, which is usually a sign the abstraction was the right one.

I also wrote down how Codex resume actually works in docs/codex.md. It’s different enough from Claude’s that I’d re-derived it twice already.

One small fix: diff files now render in the same order the file tree lists them (orderFilesByTree), so clicking down the tree walks the diff in order instead of jumping around.