interactive: treat Cursor and opencode shell tools as non-interactive
Commit
Cursor's shell tool sets CURSOR_AGENT=1 in the child env, and opencode sets OPENCODE=1 on its own process so every child inherits it. Neither was a sentinel, so an entire command an agent ran there fell through to the CI check and the /dev/tty probe and could still put up a prompt nobody can answer.
Both were verified against the shipped agents rather than inferred: opencode's three added vars (AGENT, OPENCODE, OPENCODE_PID) by running it and diffing the child env against a baseline, plus its source (packages/opencode/src/index.ts sets them; the V2 bash tool adds no env of its own); Cursor's from its bundled shell-tool spawn, which builds {CURSOR_AGENT:"1"} and adds CURSOR_CONVERSATION_ID and AGENT_TRANSCRIPTS.
The list moves into one slice, agentSubprocessEnvVars, because it was spelled in four places and one of them was a rot trap: the negative test hand-cleared three of the sentinels to stay hermetic, so adding a fourth without touching that list makes mise run test fail for anyone running it from inside the new agent. The tests now enumerate and clear the slice, so adding a vendor is a one-line change that stays covered.
Deliberately not added: bare AGENT (opencode sets it too, but the name is generic enough that unrelated tooling would trip the guard) and CLAUDECODE (a real sentinel, but adopting it withdraws prompts from the largest agent population at once — a product call, not a detection fix).
GIT_TERMINAL_PROMPT stays out of the slice: it is a tri-state where only the exact value "0" counts, while the rest are presence checks.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com Entire-Checkpoint: 01M203G90ZN9HGK1JD24PMV909