CLAUDE_ENV_FILE reaches the shell, not the next hook

#3806 · measured on Claude Code 2.1.251, claude -p, --settings hooks, loopback Messages API, zero spend · 2026-08-30

The claim, and the measurement

src/hooks/README.md said:

Hook appends: export ORK_DEBUG=1
    ↓
CC reads the file after hook exits
    ↓
All subsequent hooks see
process.env.ORK_DEBUG === '1'      <- never measured

a SessionStart hook wrote one line, four observers looked:

observersees PROBE_EXPORTED
SessionStart hook (the writer)n/a
PostToolUse hook (Bash)unset
Stop hookunset
Bash tool command echo ${PROBE_EXPORTED}yes

Same result for a plugin hook (async), for a sub-hook inside the sync sync-session-dispatcher, and with the runner invoked directly with CLAUDE_ENV_FILE set (the file was written correctly every time). The export is a Bash-facing channel. Hook-to-hook state goes through files.

Who is reading? Pick a reader

sees the export

Consumer audit, decided per consumer

sitewas it broken?what changed
config-change/settings-reload writes export ORK_DEBUG=1 on /debugnoit also wrote ~/.claude/logs/ork/debug-mode.flag, which lib/env.ts getLogLevel() already read as step 4. The comments called the dead channel "primary" and the live one "fallback"; they now name the reader each channel serves. The env append is kept: a shell command Claude runs does see $ORK_DEBUG.
lib/env.ts resolution order commentnostep 3 no longer claims the export arrives; step 4 is the working hook path, not a fallback
prompt/cache-break-detector header: "persisted via CLAUDE_ENV_FILE"nothe code has always used a turn-state file; the comment now says so
lifecycle/session-env-setupnowrites JSON state files, never an export; it was only the probe vehicle
every other ORK_* variable a hook reads (31 names)nooperator-set in the shell or settings env, never a session export
lib/sandbox-posture.ts (#3322)would have beendesigned on the claim, measured dead before shipping, replaced by a direct settings read. That is how #3806 was found.

No code path changed in this PR. The defect was a documented contract nobody had measured, and the one consumer survived it by having two channels. Whether hook-side blindness is a CC bug or the feature's intended scope is unsettled upstream; the observer table above is the repro either way.