Skip to content

Gate unsafe optional tmux features independently - #140

Draft
tony wants to merge 9 commits into
bump-min-tmux-000from
bump-min-tmux-001
Draft

tony wants to merge 9 commits into
bump-min-tmux-000from
bump-min-tmux-001

Conversation

@tony

@tony tony commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Keep ordinary MCP tools on tmux 3.3a while refusing unsafe optional operations before their effects. This is stacked on the core minimum change.

Operation Required tmux
Input, pane capture, polling, completion channels, run_command, show_buffer and direct paste_buffer 3.3a
load_buffer (stages a named buffer) and delete_buffer (exact named deletion) 3.4, refused before dispatch; a 3.3a daemon creates no buffer
Nonempty paste_text (its temporary buffer needs exact named cleanup on failure) 3.4, refused before the buffer is staged
Literal select-layout on 3.3a Unknown names and malformed serialized headers refused before dispatch; valid layouts unchanged

load_buffer joined the 3.4 group after review: it staged a named buffer that a 3.3a daemon could never delete, and tmux limits only automatic buffers, so repeated calls grew the daemon. Owned subprocesses bypass the parent library's methods, so the dispatcher forwards each literal argv to libtmux's command policy (libtmux._internal.support.require_commands) and carries an optional minimum through the existing process budget. Startup and every tool refuse a libtmux without that function. Empty paste_text has no input effect on any release and returns before touching tmux.

Not applicable here, because the server has no such code: library-owned control acquisition (tools poll; nothing attaches a control client), captured run-shell stdout (run_command types into a pane), break-pane, a raw split-window -p, and a private control socket alias. Session and window renames on exact 3.7 reach tmux, which rejects : and . in names with no effect; a native probe confirmed both refusals leave the names unchanged. Per-feature support states are in the compatibility reference; none raises the server's minimum.

The package requires libtmux>=0.63.0 (see #139), and the development lock pins the implementation from Python feature PR780 (5df9cb3e) until that release exists.

Merge and release order: libtmux 0.63.0 is released first, from #779 and #780. This PR, stacked on #139, requires libtmux>=0.63.0, which no installer can satisfy until then, so it merges only after that release, in the same change that drops the development [tool.uv.sources] pin. Nothing in this PR tags or releases.

Validation:

  • The feature, buffer and version check tests pass on the installed tmux after the restack onto the renamed core (41 passed, 10 skipped, the native 3.2a and unpatched 3.3 refusal lanes not configured). Ruff format/lint, mypy and uv lock --check pass.
  • Hosted CI is green on the core base a2b4b3af (run); the restacked head ba573fee is not claimed green.
  • Deliberate breaks, each on tmux 3.3a. Removing the forwarded literal command policy from the dispatcher fails the named-buffer identity, delete-tool and layout cases (six failures among them). Removing the 3.4 minimum from paste_text staging fails test_managed_paste_checks_cleanup_before_staging. Removing the 3.4 minimum from load_buffer fails test_load_buffer_stages_only_where_it_can_be_deleted with DID NOT RAISE, which asserts that only the user's buffer remains. The unmodified tree passes.
  • The hook-free version probe inherited from the core change is covered by its own native test, which fails when a display-message call is put back into the probe.

Support is qualified on Linux/WSL by local native runs and the hosted Linux matrix; macOS and Windows are not claimed. Opaque tmux or shell programs and configured alias bodies keep native semantics, and library-owned metadata and guard commands assume native built-in semantics.

Closes #138.

@tony
tony force-pushed the bump-min-tmux-001 branch from f795558 to 0b2d32c Compare October 17, 2026 12:34
@codecov-commenter

codecov-commenter commented Oct 17, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.73%. Comparing base (a2b4b3a) to head (ba573fe).

Additional details and impacted files
@@                  Coverage Diff                  @@
##           bump-min-tmux-000     #140      +/-   ##
=====================================================
+ Coverage              86.52%   86.73%   +0.21%     
=====================================================
  Files                     46       46              
  Lines                   4053     4057       +4     
  Branches                 606      607       +1     
=====================================================
+ Hits                    3507     3519      +12     
+ Misses                   381      374       -7     
+ Partials                 165      164       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tony
tony force-pushed the bump-min-tmux-000 branch from 39cc1a7 to 918119a Compare October 17, 2026 12:40
@tony
tony force-pushed the bump-min-tmux-001 branch from 0b2d32c to 268e3cc Compare October 17, 2026 12:40
tony added 9 commits October 17, 2026 11:25
why: Matching package versions do not identify the new guards.

what:
- Pin the published policy-2 source in project metadata and lock.
- Retain the matching package range and other locked dependencies.
why: MCP-owned children bypass parent methods, and paste needs a safe
     cleanup path before it creates a native buffer.

what:
- Require policy 2 before helper version checks and forward literal checks.
- Carry optional minimums within existing owned-child time budgets.
- Require 3.4 for nonempty managed paste before native staging.
- Keep empty paste and ordinary buffer operations on tmux 3.3a.
- Exercise refusal, unchanged user buffers and retained layout behavior.
why: Tool availability depends on its operation and the daemon's version.

what:
- Document individual buffer, output and layout requirements.
- Explain the coordinated policy-2 source installation.
why: Callers need the operation-specific compatibility changes.

what:
- Record optional refusal, safe cleanup and retained baseline behavior.
load_buffer stages a named libtmux_mcp_* buffer. On a 3.3a daemon delete_buffer
is refused (exact named deletion needs 3.4) and paste_buffer has no
delete-after path, so every call left a buffer the agent could not remove, and
tmux limits only automatic buffers, so repeated calls grew the daemon without
bound. Contract 0002 asks to check staging before creating state whose cleanup
cannot be guaranteed: give load_buffer the same 3.4 minimum paste_text has, so
an older daemon refuses before the buffer exists.

Tests: workflows that stage a buffer skip below 3.4; the dedicated test
asserts the refusal and that only the user's buffer remains on 3.3a, and the
stage-read-delete path on 3.4 and newer. Removing the minimum fails the 3.3a
test with DID NOT RAISE.
libtmux no longer exposes an integer policy marker; the owned helpers need
libtmux._internal.support.require_commands. A backend without it is refused before any
native child starts, with LibTmuxException. The staging test now asserts that
no buffer is created on a daemon that cannot delete it.
load_buffer is no longer called inert: it stages a named buffer and needs 3.4,
like exact deletion. Replace the policy-marker wording with the
require_commands requirement.
Note that load_buffer joins paste_text and exact deletion at 3.4 and that the
backend contract is libtmux._internal.support.require_commands. Keep the release note
separate from runtime changes.
The owned helpers run libtmux's command policy, so window and session names
holding ':' or '.' are refused on 3.7 and pass on 3.7a with no extra code.
Removing the require_commands call in the fence fails the new test.
@tony
tony force-pushed the bump-min-tmux-000 branch 2 times, most recently from 653f6d5 to a2b4b3a Compare October 17, 2026 17:57
@tony
tony force-pushed the bump-min-tmux-001 branch from 268e3cc to ba573fe Compare October 17, 2026 17:58

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants