Fleet changelogs · dev.ecs0.net
rdmsm4x-changelog-20260829-2312-agent-session-logger-terminal-spam

rdmsm4x — agent_session_logger.zsh v1.1.0 (terminal job-notice spam)

Session: 2026-08-29 23:01–23:14 EDT · rdmsm4x Project: ~/dev/fleet/telemetry-logging (Production mode)

Reported vs. actual

Reported as a "LogTTY/RTTy terminal telemetry hook", with a request to patch "the shell integration generator in apps/LogTTY". Misattributed. Neither logTTY nor RTTy contains any shell hook — greps for nc -u, 1514, add-zsh-hook, preexec, precmd return nothing live in either repo (RTTy's only 1514 hits are hex substrings inside exported-event UUIDs). Both repos were left untouched.

Actual producer: ~/.zshrc → ~/scripts/terminal_init.zsh → ~/scripts/agent_session_logger.zsh, canonical source ~/dev/fleet/telemetry-logging/scripts/agent_session_logger.zsh.

Cause

v1.0.0 backgrounded each UDP syslog forwarder with a plain &. A plain & registers a job-control entry; with MONITOR+NOTIFY (interactive zsh default) zsh announces completion at the next prompt. _syslog_stream runs from both preexec and precmd across two endpoints → four notices per command:

[3]  - done       ( print -rn -- | nc -u -w 1 "$endpoint" 1514 > /dev/null 2>&1; )

Reproduced under a real pty via Python pty.fork() (script(1) cannot allocate a pty from an agent session), and confirmed silent after the fix.

Fix — v1.1.1

  1. &! (background + disown) instead of & — never enters the job table.
  2. setopt localoptions nomonitor nonotify inside _syslog_stream.
  3. Guards: empty $msg, empty payload, empty/absent endpoint, missing nc (resolved once via ${commands[nc]}) — short-circuit instead of forking.
  4. local endpoint — v1.0.0 leaked endpoint globally on every command.
  5. TERM_SESSION_SYSLOG_ENDPOINTS / TERM_SESSION_SYSLOG_PORT overrides; empty endpoints disables remote streaming, keeping local syslog + file log.
  6. Session-file writes 2>/dev/null so a vanished log dir can't add new noise.

Reverted mid-session. An interim v1.1.0 also swapped trap _session_exit EXIT for add-zsh-hook zshexit. Measured through the shipped ~/.zshrc path that was a regression — zshexit fires in forked children of the interactive shell (zsh-autosuggestions' async worker), each running _session_exit and renaming the in-progress log away: 1 log file with trap, 2 with zshexit. Shipped v1.1.1 keeps trap ... EXIT, with the measurement recorded in the script. Caught by verification, not by review.

Verification (evidence, not assertion)

Deployment

v1.1.1, sha256 a5ae709b77c7222e, hash-verified per host after copy:

Host Result
rdmsm4x MATCH · syntax OK
rdmpw3265m MATCH · syntax OK
rdmpw3275m MATCH · syntax OK · pty smoke test silent
rdmbair13m5 MATCH · syntax OK
rdmbair15m5 MATCH · syntax OK · pty smoke test silent (via 100.74.59.4)

Backups at ~/scripts/agent_session_logger.zsh.bak-20260829-v1.0.0 on each updated host. An initial scp round silently failed on a quoting error and was caught by the hash check before being reported as done.

Files changed

Open

ISSUES.md TLOG-02 — push v1.1.0 to rdmbair15m5 when it is reachable.