Repository navigation
Conversation
why: A newer client can reach an older daemon, and the socket can change after a version probe. Refuse unsupported ordinary Server operations before requested effects while retaining existing incarnation and ownership fences. what: - Admit the daemon's complete patch-aware version; consult a fresh executable report only on an unused endpoint. Preserve standalone -V and -h diagnostics. - Prepend a native version guard without rewriting raw argv, batches, existing guards or stdin. Use -N after live admission and on absent non-starting paths. - Share bounded request execution with carrier probes without exposing a remote-carrier ProcessTransport instance. Retain request budgets, borrowed ownership and dispatch certainty. - Remove detached-size and prompt-inventory adaptations made obsolete by the 3.3a floor. Keep compatibility still needed inside the supported range. - Add admission, replacement, disappearance, malformed-version and carrier regressions. Update recording fixtures without weakening data batching, input cohort or native PID guard checks. - Regenerate the operations reference and Kotlin ABI for call-time compatibility preflight. Preserve JDK process-argument inspection with an ASCII-space native no-op.
why: Python builders and shells execute outside the Java dispatcher. A Java preflight alone cannot enforce the core floor through an obsolete installed Python libtmux backend. what: - Check the selected daemon, or the executable only when absent, before external builder and shell entry. - Require the Python backend's declared core floor to be at least 3.3a before loading builder or shell code. Repeat the handshake in every child process. - Report the selected interpreter and compatible backend requirement without inventing a release pin. The coordinated Python core change is PR779. - Remove the CLI's obsolete retry without detached session dimensions. - Cover old-client refusal, obsolete backend refusal before effects, qualified backend success and real tmuxp 1.74.0 extensions using the coordinated Python source.
why: Facade transports must distinguish admission from requested work so their lifecycle, cancellation and cohort assertions keep measuring the operation under test. what: - Answer exact daemon-version probes in Kotlin, Cats and workspace fixtures without counting them as application effects. - Inspect original commands after the separate native guard in MCP and fixture recording transports. - Retain the native wait-process readiness and cancellation assertions, staging-session cleanup and PID incarnation checks.
why: The supported matrix and user-facing requirements must agree with core admission. The extra admission probe also changes process-count guidance. what: - Remove 3.2a and unpatched 3.3 from required CI and local matrix lanes; keep the remaining supported and preview lanes. - Update JVM facade, example, workspace CLI and contributor requirements to 3.3a. - Describe version-probe reports and the extra process before ordinary command groups, captures and filtered reads. - Update benchmark generator explanations while leaving historical generated measurements at their recorded commit.
why: Users must upgrade the running daemon as well as the client, and external Python backends need their own command-level admission. what: - Describe daemon-first refusal, unused endpoints, diagnostics and full version-token handling. - Document call-time compatibility preflight and the bounded control- startup check without claiming endpoint pinning. - Link the unreleased Python core PR and distinguish its dispatcher guarantee from Java preflight. - State the requirement that configured command aliases preserve the native built-ins used for admission.
why: The raised daemon minimum changes which installations and Python backends can run JVM products. what: - Record the core 3.3a requirement under Unreleased, reference issue 67 and link the migration instructions.
why: tmux 3.3a prints its executable basename before the version. A renamed or symlinked supported binary must still pass cold admission. what: - Accept the exact configured basename or canonical tmux banner - Keep full version-token checks and bare daemon reports unchanged - Cover mismatched names, malformed releases and daemon authority
why: A delivered marker can cross terminal rows and disappear from a literal substring assertion even though both intended panes received it. what: - Join soft-wrapped rows in the shared typing capture helper - Reproduce wrapping with ready cat consumers at a fixed pane width - Retain effective-recipient and disabled-pane assertions
why: Released tmuxp pins Python libtmux before core admission, so the Python bridge correctly refuses the existing CI installation. what: - Install released tmuxp normally and overlay reviewed Python source - Pin the source commit and assert its import path and 3.3a floor - Apply the same qualification to JDK and supported tmux lanes
why: Cold admission and delivered-text assertions depend on native behavior that differs from a simple version or substring assumption. what: - Record renamed tmux 3.3a version banners from copies and symlinks - Record soft-wrap capture results on native 3.3a and 3.7d
why: The reviewed source overlay qualifies command admission without claiming a released or coherently installed tmuxp and libtmux pair. what: - Link the exact Python source used by the CI overlay - State the import-path check and pending tmuxp dependency update
why: A user may configure a renamed or symlinked tmux 3.3a executable when creating the first session on an unused endpoint. what: - Clarify that cold admission accepts configured executable names
why: A wrapped completion marker or output arriving before a wait's entry capture made JDK checks fail for unrelated fixture timing. what: - Join soft-wrapped completion capture and force that regression. - Release shell output after the real wait entry capture. - Preserve cold and warm echo assertions without a fixed delay.
why: Admission asked the daemon for `display-message -p '#{version}'`.
display-message fires a user's `after-display-message` hook on every
tmux release, so the probe itself had effects before a refusal could
stop anything.
what:
- Probe with `run-shell -C '<marker>#{version}'`, marker
`libtmux-version-<random hex>-`. The daemon expands the format and
fails to parse the result as a command, so the version is read from
`unknown command: <marker><version>` on stderr. run-shell has no
after-hook, and a parse failure inside its -C callback never reaches
command-error. The live endpoint still gets -N.
- Another request's marker, a plain success, or any other stderr is not
an answer: absent-endpoint wording still means an unused endpoint,
anything else is a rejected probe.
- Test doubles (core, MCP, workspace, junit5, integration, Kotlin and
Cats fake binaries) answer the new probe through VersionProbes;
FakeTmux answers it for fixtures and carriers.
- AdmissionHooksIntegrationTest arms after-display-message and, on
3.5+, command-error hooks, runs admitted calls and requires neither
to fire, with a control that fires each hook the ordinary way.
- Unit cases pin the probe shape, a foreign marker, `master` and other
unknown suffixes, and `next-3.9`.
Verified: AdmissionHooksIntegrationTest passes on 3.3a (command-error
case skipped, no such hook), 3.5, 3.6b and master (next-3.9). Restoring
display-message as the probe fails the after-display-message case on 3.3a
and 3.5 ("admission ran the user's after-display-message hook").
:libtmux, :libtmux-junit5, :libtmux-workspace and :libtmux-scala-cats
test tasks pass.
why: The operations guide said admission emits a display-message probe report, which is no longer the command sent. what: - Name run-shell and state that admission fires none of a user's after-* or command-error hooks.
why: JDK 25/27 and the 3.5 and master lanes failed four WaitingForTextTest cases with PRESENT_AT_ENTRY. Keys sent to a shell that is still starting are echoed by the terminal and the shell draws its prompt straight after that echo on the same row, so the echo is glued to the prompt and no longer stands apart as a typed line. That is not the case these tests pin. The previous follow-up replaced the fixtures with a capture-gated release that still sent keys into the starting shell and failed the same way. what: - Restore the trunk fixtures of WaitingForTextTest. - Wait for the pane to show something and hold still for half a second before typeAndSubmit and send write to it. Verified with 20 busy loops on a 10-core host, bash with a long prompt, tmux 3.5 lane. The trunk fixtures fail sendThenWaitDoesNotMatchTheEchoedCommandLine (PRESENT_AT_ENTRY) and the previous follow-up fails four cases with the same outcome; with the wait, RunningCommandsTest, TypingTest and WaitingForTextTest pass under the same load. Trunk's libtmux-mcp:test is restored FROM-CACHE in CI, so its own run never exercised these cases.
Records that admission reads the daemon version with run-shell -C and fires none of a user's hooks.
tony
force-pushed
the
bump-min-tmux-000
branch
from
October 17, 2026 09:06
48122c0 to
f4c28f4
Compare
Applies the project formatter to the capture call added by the settle wait; no behaviour change.
why: The stalled-control fixture wrapped tmux and blocked on a FIFO for
any argument equal to `-C`. The admission probe is now
`run-shell -C '<marker>#{version}'`, so the wrapper blocked the probe
and Server.cmd timed out before the control attach was ever reached
("cancelling control ends promptly and kills the stalled process"
failed with DispatchException$TimedOut). The process scan matched the
transient probe process the same way.
what:
- Block on `attach-session`, which only the control attach carries.
- Look for the stalled client by `-C` together with `attach-session`.
Verified: the case failed on this branch before the change and passes
after it (`:libtmux-kotlin:test --tests '*WaitsTest*'`).
why: aFilterThatMatchesNothingCostsOneFilteredRead counted the version probes as `display-message` requests. The probe is now `run-shell -C`, so the count was zero and the case failed on every real-tmux lane. what: - Count the `run-shell` probes; the total of eight requests, four of them probes, is unchanged. Verified on the tmux 3.3a lane (`--tests '*Pushdown*'`).
why: Two CatsLifecycleSuite programs ran under a one second `timeout` for the whole program. Every call now spends a version probe process before its own command; on the tmux 3.3a lane the full suite then exceeded the second while each test alone passed. The programs carry their own 800 ms per-wait deadlines, so a real hang still fails. what: - Raise the outer budget of the shared-wait and owned-release programs to five seconds. Verified: the lane failed both programs before the change and passes after it (`:integration-tests:test-tmux-3.3a`, whole lane).
why: The operating guide's observer snippet read `seen.get("display-message")`
and passed only because the admission probe was itself a display-message
request whose report put its first verb. The probe is now a run-shell
request, and the call's own report starts with the `if-shell` version
guard, so the key was never written and the documentation check failed.
what:
- Key the map by the last verb of each report, which is the requested
command for a call and `run-shell` for admission.
Verified with `:docs:test` after the change.
This was referenced Oct 17, 2026
why: WaitForIntegrationTest.aServerDyingUnderAPaneWaitIsNotATimeout
failed on the JDK 27 lane: the pane wait asked `isAlive()` while the
server was exiting, admission's version probe was refused with "server
exited unexpectedly", and the rejection escaped as an exception instead
of the documented false, so the wait reported an error and not
SERVER_GONE.
what:
- isAlive(Duration) answers false when tmux refuses the admission probe,
as it already does when tmux refuses its own pid read; transport
failures still throw, and a raw command is still rejected.
- A unit case covers a daemon that exits under the probe.
Verified: the case fails without the catch ("tmux version probe failed
(exit 1): server exited unexpectedly") and passes with it; the
WaitForIntegrationTest class passes three times on the 3.4 lane.
why: The admission floor should treat every version string tmux has reported the same way in every port: `next-X.Y < X.Y-rc < X.Y-rcN < X.Y < X.Ya`, bare `-rc` real and admitted, and forms no tmux reported (`3.3a-master`, `3.3a-dev`, `next-3.3a`, `next-3.9-master`) refused. TmuxVersion.compareTo rates a candidate equal to its release because feature gates measure what the candidate ships, so a policy floor cannot use it. what: - TmuxSupport.compareStrictly orders a candidate below its release and a bare rc below rc1; the 3.3a floor uses it, replacing a special case for the floor's own candidate. - VersionGrammarTest runs the vectors: admit, below the floor, unparseable, the release-train ordering, and the control-gate neighbours (`next-3.7` and `3.7-rc2` below 3.7; `3.8-rc2` and `next-3.8` above). Verified: making compareStrictly ignore candidates fails the ordering and the neighbour cases.
tony
force-pushed
the
bump-min-tmux-000
branch
from
October 17, 2026 11:51
e967af3 to
d34e6d0
Compare
why: TmuxVersion.compareTo rated `3.4-rc` equal to `3.4` while equals said they differ, so a sorted set collapsed them and Cats' Order reported Eq. Gates were split too: range gates (`atLeast`) counted a candidate as its release while exact gates used equals, so one candidate had the feature and not the bug. parse accepted any prefix (`3.3a garbage`, `3.3a-master`, `3.3abc`). what: - compareTo is the strict order `next-X.Y < X.Y-rc < X.Y-rcN < X.Y < X.Ya`, which agrees with equals. The support floor and the control gate use it directly; TmuxSupport.compareStrictly goes. - atLeast still counts a candidate as its release (a gate asks what the build ships); sameRelease does the same for gates on one release's own bug, and the `$`-escape and 3.7 break-pane gates use it. - parse is anchored to the canonical grammar with one patch letter. - VersionGrammarTest holds parse to the unparseable vectors and checks that the order, equals, atLeast and sameRelease agree as documented. Verified: the unit suites of the core, junit5, workspace and Cats modules pass.
… refuses why: Every call spent a version probe process before its own command, doubling process spawns, and a daemon replaced between the probe and the dispatch surfaced as TargetGoneException, so a caller that retries stale handles retried into the same refusal. what: - Admission remembers the version it read for each transport and endpoint. The fence every dispatch carries is what keeps that honest: a replaced daemon fails the fence before any command runs, the entry is dropped and the daemon is read again, so an older replacement raises the version error and a supported one is used. A daemon that has gone answers without running anything and is read again too. - A replacement between a fresh read and the dispatch still raises TargetGoneException, after one more read. - Cases: the second call reuses the first's admission; a refused fence reads again; a daemon replaced by 3.2a raises UnsupportedFeatureException with no effect. The tests that counted probes (snapshot, handle, fixture, field reads, filter pushdown, mirror rebuild) count one per daemon. The mirror case builds on a pane without a shell, so a prompt cannot retitle it. Verified: reading the daemon again is replaced by TargetGone in a deliberate break, which fails both new cases; the whole 3.3a lane passes.
…lane
why: Refusal below the floor was tested only against FakeTmux, so a
change in how `run-shell -C` fails on 3.2a or 3.3 would have passed CI.
The 3.2a and 3.3 lanes had simply been deleted, and there was no
released 3.8 lane for a 3.8-only failure to show in.
what:
- AdmissionLaneIntegrationTest starts the lane's own binary on a private
socket, makes a sentinel session, option and buffer with that
binary's client, then drives the library: below 3.3a every call (raw,
batch, typed, lenient list, buffers, kill) raises
UnsupportedFeatureException and the sentinels are unchanged; on a
supported release the same calls work.
- `rejectionLanes` (3.2a, 3.3) run only that class and belong to
testTmuxMatrix; the workflow builds them as "must be refused" lanes.
`3.8` joins the preview lanes beside 3.8-rc2 and master.
Verified on the real binaries: the class passes on 3.2a, 3.3 and 3.3a;
with the floor not enforced it fails on both 3.2a and 3.3 ("Expected
UnsupportedFeatureException to be thrown, but nothing was thrown").
…ides why: The batching guide cited "64 versus 5" processes from a benchmark that predates admission, and said every request costs two; two pages still named 3.2a as the start of the supported range. what: - State the cost without a ratio: one process per request once the daemon is known, and link the measured rows. - Say 3.3a through 3.7c in the tmux behaviour page, and cite only the releases the streaming measurement used.
Names compareTo, atLeast, sameRelease and the stricter parse for callers of TmuxVersion.
Notes that a known daemon is not probed again, the version error for an older replacement, and the strict order and parse. References issue #67.
…s send why: The cohort, typing and run cases asserted a version probe request between the last preflight and the send, or ahead of the snapshot. A known daemon is no longer probed again, so the send follows the preflight directly. what: - The send is the request right after the final preflight, and the cohort snapshot is the only request on an admitted daemon. Verified with :libtmux-mcp:test.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The minimum daemon version is tmux 3.3a across Java, Kotlin, Scala, MCP and workspace entry points. Ordinary reads, writes, raw commands and batches validate the connected daemon and carry an exact native version guard before requested effects. An unused endpoint validates the executable before creation; standalone version/help diagnostics remain available.
The admission probe is
run-shell -C '<marker>#{version}'.display-message -p '#{version}'fires a user'safter-display-messagehook on every tmux release, so the probe itself had effects before a refusal could stop anything.run-shellhas no after-hook, and the parse failure of its-Cargument carries the version on stderr asunknown command: <marker><version>without reachingcommand-error. Another request's marker, a plain success or any other stderr is not an answer.This removes obsolete detached-size and prompt-inventory adaptations while preserving incarnation fences, request deadlines, process ownership and compatibility required within the supported range. The CI matrix starts at 3.3a. External Python builders and shells require the coordinated Python core admission change; tmuxp alone does not provide it. CI explicitly qualifies released tmuxp 1.74.0 with Python source
26123fe7e4fc497a9ddb454ce654e468afe916abonPYTHONPATH, asserting the import path and declared floor. Released tmuxp still pins Python libtmux 0.61, so this overlay does not qualify a coherent installed package pair; the coordinated tmuxp dependency change remains pending.Validation, on this Linux/WSL host:
AdmissionHooksIntegrationTestarmsafter-display-messageand, from 3.5,command-error, runs admitted calls and requires neither to fire; a control call fires each hook the ordinary way. It passes on 3.3a (thecommand-errorcase is skipped, the hook does not exist there), 3.5, 3.6b and master (next-3.9). Restoringdisplay-messageas the probe fails theafter-display-messagecase on 3.3a and 3.5 ("admission ran the user's after-display-message hook").masterand other unknown suffixes, andnext-3.9; the test doubles of every module answer the new probe.VersionGrammarTestholds admission to the canonical version vectors (admit, below the floor, unparseable, and the ordernext-X.Y < X.Y-rc < X.Y-rcN < X.Y < X.Ya); the floor compares candidates strictly throughTmuxSupport.compareStrictly, whileTmuxVersion.compareTokeeps rating a candidate as its release for feature gates. Making the strict comparison ignore candidates fails the ordering and neighbour cases.isAliveanswers false when tmux refuses the admission probe (a daemon exiting under it), whichWaitForIntegrationTesthit on the JDK 27 lane.:libtmux,:libtmux-junit5,:libtmux-workspaceand:libtmux-scala-catstest tasks pass, as do:docs:testand the workspace CLIExecutionTestwith the Python source overlay.-Cargument (it blocked the probe), a probe count keyed bydisplay-message, a documentation snippet keyed by first verb, and two lifecycle programs whose one-second budget did not fit a probe per call.WaitingForTextTestcases failed on the JDK, 3.5 and master lanes withPRESENT_AT_ENTRY: keys sent to a shell that is still starting are echoed by the terminal and the prompt is drawn glued to that echo. Trunk'slibtmux-mcp:testis restoredFROM-CACHEin CI, so its own run never exercised them. With 20 busy loops on a 10-core host, bash and a long prompt, the trunk fixtures failsendThenWaitDoesNotMatchTheEchoedCommandLine; waiting for the pane to settle before typing makesRunningCommandsTest,TypingTestandWaitingForTextTestpass under the same load.Control acquisition has a bounded preflight; endpoint pinning and unsafe optional feature boundaries belong to the separate optional-feature change. Admission assumes native built-in semantics, including
if-shellandrun-shell; configurations redefining them throughcommand-aliasare outside this qualification. Reads that print a version withdisplay-messageinside an already admitted call (option decoding, printed text) are unchanged. Local evidence covers Linux/WSL; the other supported tmux releases, JDKs and macOS are CI qualification. Clojure draft PR20 is a separate integration follow-up.Closes #67.