ntm v1.32.0
Pane liveness and launch safety, anchored failure evidence, durable activity state, and the Gemini 3.8 Antigravity pin (GitHub issues #283, #288, #292, #294, #295, #297, #299, #300, #301, #302, #303; PRs #290, #291).
Added
- Durable activity state (#301):
ntm activityreconciles each pane's classified state against a watermark scoped to the pane lifetime (session, pane ID, pane PID), sostate_sinceand the duration grow across one-shot invocations instead of resetting to "now". Transient TUI markers are classified from the visible viewport, not the scrollback, so a spinner that scrolled away hours ago no longer pins a pane to THINKING. - Agent Mail probe budget (#295):
NTM_AGENT_MAIL_PROBE_BUDGET(a Go duration) overrides the 1250 ms availability budget, a cheap unauthenticated/healthliveness probe decides availability before falling back to the MCP health tool, and every reservation verb (lock,unlock,locks,renew,force-release) reports the probe's actual error instead of a bare "Agent Mail server unavailable". - Ready counts bound to direct tracker evidence (#283): the work-readiness model derives the complete ready count and the capped preview from one
br ready --jsonresult, and blocked snapshots keep blocker IDs, blocker counts, priority and issue type instead of title-only rows. - Typed composer blockers (#300):
--clear-inputreports whether a composer is held by stranded text, queued messages or a modal dialog, and how many clearing rounds ran, soCOMPOSER_NOT_CLEAREDtells the operator whether to inspect, wait or answer a dialog.
Changed
- Antigravity default model is Gemini 3.8 Flash (High) (
gemini-3.8-flash): the required-model pin, the session-resume model, the registry alias, flag help and the spawn wizards all move from 3.7, matching ACFS'sagy-lockedlauncher and model guard. - Spawn never launches into an occupied pane (#291): every agent pane of a batch is preflighted before any launch, the exact pane is re-read immediately before
send-keys, and an occupied, missing or unreadable pane fails closed with the running command named and a pointer tontm add. Previously only Grok launches checked, and the launch line (including--dangerously-skip-permissions) could be typed into a live agent or editor.
Fixed
- Pane liveness is judged by the terminal's foreground process group, not the command name: a job other than the pane's root shell owning the tty is the "agent took over the pane" signal, so agents started as
sh -c ...and non-exec'ing wrapper scripts count as live while only a bare interactive shell counts as dead (PANE_AGENT_DEAD). Fresh panes get a 3 s settle window (tmux reports itself as the foreground command for about 300 ms before the shell execs), and the post-launch stable-process wait now runs for every agent type, not only Grok, so a prompt is never dispatched into a shell the agent has not yet replaced. - Wrapped composer clear (#300): the whole bordered composer block (marker row plus wrapped continuation rows) is verified empty, and a pane with no composer marker at all is reported as unverifiable rather than as blocked on a modal.
- Anchored failure evidence (#297, #299): prose about failure ("the planted negative failed as expected", a 20000 ms timeout mentioned in a plan, a SHA-256 that contains "429") no longer marks a pane ERROR or degrades a session. Only anchored runtime signatures, structured status codes (case-insensitive) and process outcomes count, for alerts, robot health and handoff text alike; named exception lines such as
ValueError: bad inputare recognised. - A fresh
--robot-statusprocess no longer reports every agent busy (#288): a first observation only records a baseline; without an in-process clock the durable output sequence is used, a pane resting at its prompt is idle and never "stalled", and no clock plus no decisive tail yields unknown, never busy. - Assignment rail (#294, #302): pre-actuation dispatch refusals (dead CLI, unsupported protocol, composer not ready or not clearable) are retried behind the idempotency barrier with bounded exponential backoff instead of permanently failing the assignment; reservation candidates must resolve inside the repository, so prose like
13714/2mor2026/09/03no longer becomes an Agent Mail lease; occupied-target refusals name the owning bead with its status, age and assignment time. brwrite-lock timeouts are retried (#290) with jittered, deadline-bounded backoff, so one contendedbr readyduringntm assign --watchis no longer a hard failure; otherCONFIG_ERRORs stay terminal.- Audit JSONL honours
XDG_DATA_HOME(#292) the same way resilience manifests and monitor logs already did. - Checkpoint pane resolution on tmux 3.6: the session's selected pane is resolved with the
=name:target form (tmux 3.6 answers=namewith empty output) and an empty answer is logged instead of silently recording the last window's active pane. - E2E hygiene (#303):
ntm-tmux-test-*servers leaked by a killed run are reaped at suite start, age-guarded and never the suite's own socket root.
Assets
Archives follow the upgrade contract (ntm_<version>_<os>_<arch>.tar.gz, zip on Windows) with unversioned aliases, a .sha256 sidecar per asset and SHA256SUMS; ntm-vscode-1.32.0.vsix is the VS Code extension (code --install-extension). Built and published by dsr on Linux (Go cross-compilation, CGO_ENABLED=0); ntm upgrade, install.sh, brew install dicklesworthstone/tap/ntm and scoop install dicklesworthstone/ntm all serve this version.
Full changelog: https://github.com/Dicklesworthstone/ntm/blob/main/CHANGELOG.md