62ec0a7d38
On a machine running Claude Code and Codex in the same repo, 3,224 Codex calls were booked against a Claude model and no OpenAI model was ever recorded at all. Two independent faults compounded. The hint is keyed by working directory, and only one writer existed: Claude Code's hook, which always tags its hint "claude-code". The reader took the model without ever comparing the hint's agent to the session's client. Two agents sharing a repo share a cwd, so Codex read whatever Claude last announced. That is worse than missing attribution — it prices a call at another vendor's rates and reports it as fact. The reader now adopts a model only when the hint's agent is consistent with the session's client. An unknown on either side still matches: a hint with no recorded client predates the field, and rejecting it would drop attribution that used to work. Two known names that disagree are proof the hint belongs elsewhere. The comparison normalises the two spellings of one harness — the hook knows "codex", the MCP session reports "codex-mcp-client". Codex sends the active model slug on every hook event and nothing was reading it, which is why the ledger held no OpenAI models. It is now captured on the session- and turn-scoped events; PreToolUse is excluded deliberately, since it fires hundreds of times a session and would turn a twelve-hour hint into a per-tool-call disk write for no freshness. Existing rows keep their bad attribution — the ledger is an append-only record of what was believed at the time. `gortex savings --reset` clears it for anyone who would rather start clean.