The contract probe shipped in #3407 and its first dispatch failed exactly as designed — a contract gate that cannot observe must never look green. Then I could not tell which failure it was, because every line it printed went somewhere a CLI cannot reach.
run 31400567250 — dispatched on main immediately after merge Install the newest published CLI ................ success Report where the binary landed ................. success Derive the contract ............................ failure $ gh run view 31400567250 --log → only the ECHOED script lines $ gh api .../check-runs/… → output.summary is EMPTY
Two candidate exits — 1
drift, 2 CANNOT-OBSERVE — and no way to distinguish them without opening a browser. The
whole reason that layout step is unconditional was to answer this, and it answered it into a channel
the asker cannot read.
$GITHUB_STEP_SUMMARY renders in the web UI. It is not in
gh run view --log, and it is not in the check-run API's
output.summary. Writing diagnostics only there makes them invisible to every automated
consumer — including the agent that dispatched the run.
Same shape as the thirty-four defects this milestone exists to remove: the machinery ran, reported honestly, and reported into a void.
- } >> "$GITHUB_STEP_SUMMARY" + } | tee -a "$GITHUB_STEP_SUMMARY"
Both blocks now tee, so
the layout listing and the verdict land in the log and the summary. The derive step also emits
derive-cc-output-keys exit code: N explicitly, so exit 1 and exit 2 are distinguishable
from the log alone rather than inferred from a red X.
$ grep -c "tee -a \"$GITHUB_STEP_SUMMARY\"" file
0 ← the shell expanded the variable to EMPTY inside double quotes,
so this searched for `tee -a ""` and I nearly "re-fixed" a
working edit
$ grep -c 'tee -a' file
2 ← correct
A verification step that cannot observe
what it checks reports a false negative just as confidently as a false positive. Single-quote any
grep pattern containing a $.
Still unanswered, deliberately. Whether the runner populates
~/.local/share/claude/versions/ — the only path findBinary() searches — is
what the next dispatch will show, now that the listing reaches the log. I am not guessing at it here:
the install step succeeded and the derive step failed, which is consistent with both drift and
cannot-observe, and the difference decides whether the follow-up fixes the lookup path or commits a
regenerated snapshot.