gotchas.md: fellows remote shell is zsh — unmatched glob aborts the whole SSH command (nomatch), silently truncating chained monitoring probes
Highlight text on any card (body, plan, or an event) to anchor a comment, or leave a whole-task comment here. Mention @claude to summon a reply.
No comments yet.
Goal
Add a .claude/rules/gotchas.md entry for a remote-shell trap that makes SSH monitoring probes fail SILENTLY-ISH: the login shell on the fellows SLURM nodes (charmander) is zsh, and zsh's default nomatch aborts the ENTIRE remote command when ANY glob in it matches nothing — where bash would pass the unmatched pattern through and continue.
Why this matters (observed 2026-08-13, issue #1336)
A monitoring probe for a queued SLURM job ran, in ONE remote command:
ssh charmander "grep -hoE '<banner regex>' $S/logs/*.log $S/logs/issue1336_jobs/*.log | tail -3"
$S/logs/issue1336_jobs/*.log matched fine, but $S/logs/*.log matched NOTHING (no .log files at that level). zsh aborted the whole command with:
zsh:1: no matches found: /workspace/superkaiba/eps/issue-1336/logs/*.log
so the grep never ran against the directory that DID have files. The probe produced an error line where data was expected.
The dangerous shape is the compound remote command. When several probes are chained in one ssh "...; ...; ...", a nomatch abort in an early probe means the LATER probes never execute at all — and the caller sees a truncated/zero result that looks like "no signal" rather than "probe broken". In the incident this appeared alongside a genuinely-wrong second probe (an anchor mismatch reading done cells = 0 when 11 markers existed), and the pair together read as a plausible "the run lost its state" — the exact misdiagnosis the durable record has to not make. Both were probe defects; nothing was actually wrong with the run.
Requested change
One entry in .claude/rules/gotchas.md, sited near the existing SSH-remote ownership-probe entry (the pgrep -f '[p]attern' bracket rule) since it is the same family — probe composition traps whose failure mode is a wrong read, not a loud error. Content:
- Trap: remote login shell on the fellows cluster is zsh; unmatched glob ⇒
zsh:1: no matches foundand the whole remote command aborts (nomatchis on by default; bash's default is to pass the literal pattern through). - Why it bites: a chained multi-probe
ssh "a; b; c"losesbandcentirely, so the caller reads missing data as an absent signal. - Rule: in remote commands, prefer glob-free forms —
grep -r <pat> <dir>orfind <dir> -name '<pat>' -exec grep ... {} +(both take a DIRECTORY and cannot nomatch-abort). When a glob is genuinely wanted, eithersetopt +o nomatch/unsetopt nomatchfirst, or run each probe in its OWNsshcall so one abort cannot swallow its siblings. - Corollary (read-side): an empty/zero result from a remote probe is UNKNOWN until the probe itself is verified — never a substantive absence claim. Same posture as the existing
gcloudrc!=0-is-UNKNOWN-never-empty rule in the same file.
Note the byte-budget pressure on gotchas.md (the #2189 relocations): keep this to a single tight entry, and prefer siting it in the existing SSH-probe neighborhood over opening a new section.
Acceptance
gotchas.mdcarries the entry with the trap, the two glob-free forms, and the per-probe-isolation alternative.LESSONS.mdindex row forgotchas.mdneeds no new trigger (the existing "check cross-machine reads" / SSH-probe triggers already cover it) — confirm rather than assume, and update if the lint requires it.workflow_lint.py --check-lessons-indexpasses.
Provenance
Surfaced by the #1336 autonomous session while polling SLURM 12643 (fellows/charmander) during a queued wait; cost one 30-minute poll cycle of blind monitoring on an 8-GPU job. No experiment state was harmed — both probes were re-run corrected and the run's inherited state (11 done markers, 171 banked shards) verified intact.