Typed operations, engines, workspace, query & MCP (#689)#690
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #690 +/- ##
===========================================
+ Coverage 52.45% 79.78% +27.33%
===========================================
Files 26 234 +208
Lines 3729 15906 +12177
Branches 747 1981 +1234
===========================================
+ Hits 1956 12691 +10735
- Misses 1469 2503 +1034
- Partials 304 712 +408 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
Code reviewFound 2 issues:
libtmux/src/libtmux/experimental/ops/plan.py Lines 81 to 97 in e115eaf
libtmux/src/libtmux/experimental/ops/_ops/save_buffer.py Lines 38 to 41 in e115eaf 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Code reviewFound 1 issue:
libtmux/src/libtmux/experimental/ops/plan.py Lines 214 to 219 in 2e0b112 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
1 similar comment
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
Code reviewNo issues found. Fresh review of the current HEAD ( 🤖 Generated with Claude Code |
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Record the experimental operations/engines layer for the upcoming release so the unreleased section tracks what landed. what: - Add a "What's new" deliverable under the unreleased 0.59.x section for the experimental operations and engines layer (#690) - Defer the release lead paragraph until the version is cut
why: Published examples need reproducible shell, home, and tmux state with reruns disabled. what: - Add per-example home and short tmux socket isolation - Make pytest the canonical documentation example runner - Test block isolation and author-facing failure locations
why: Give every experimental operation a stable, navigable API page with an executable example and explicit failure semantics. what: - Split experimental guidance into operations, engines, and plans - Add registry-backed Server, Session, Window, Pane, and Client pages - Test page coverage, navigation, rendering, and doctest execution
why: Activate gp-sphinx card styling and responsive layout rules for custom operation entries. what: - Wrap operation entries in the shared API card shell - Assert the rendered shell contract in the Sphinx integration test
why: Let users choose a query API by freshness, filtering boundary, and failure behavior instead of navigating one mixed topic. what: - Add hierarchy, QueryList, tmux-format, Neo, and snapshot guides - Test independent happy and sad examples plus styled API sections - Preserve traversal and filtering URLs with redirects
why: Keep the verified documentation extension and tests in the repository canonical format. what: - Apply ruff line wrapping to the operation domain and query tests
why: Operation cards flattened Python signatures into literal text, bypassing Sphinx Python-domain semantics and gp-sphinx API styling. what: - Render operation classes and constructors as native Python descriptions - Register public class and constructor inventory targets - Test RST and MyST rendering against semantic gp-sphinx markup
why: Wall-clock corrections can move backward and invalidate timeout measurements in retry_until and its tests. what: - Measure retry deadlines with the monotonic clock - Measure elapsed-time assertions with the same clock
why: Operation pages need real tmux proofs and API references that match the normal gp-sphinx presentation. what: - Replace mock operation examples with live typed outcomes - Add engine, tutorial, and result API references - Align operation cards, source links, parameters, and badges - Test documentation inventory, rendering, and tmux behavior
why: CI checks the documentation extension under a different package root and against Sphinx's installed domain annotations. what: - Use package-relative imports for both Sphinx and mypy discovery - Follow inherited Sphinx domain attribute typing - Inspect public constructor signatures without unsafe __init__ access
why: tmux releases disagree on whether list-clients includes a suspended client, making the documented output version-dependent. what: - Verify the real AckResult and empty command output - Preserve the portable session-survival assertion - Document client-list visibility as version-dependent
why: Deleting a control-owned session can race tmux's deferred global notifications and terminate supported tmux servers. what: - Attach control clients to safe existing sessions without updating the environment - Bootstrap empty or unsafe servers through tracked subprocess execution - Serialize lifecycle transitions without blocking dependent fallback commands - Cover live hook, concurrency, cancellation, and cross-version paths
why: CI type-checks against Python 3.10, where Task.cancelling is not available in the asyncio stubs. what: - Replace the version-specific cancellation probe with a portable task wait - Make the shared startup future's nullable type explicit - Align lifecycle test overrides and terminal paths with their contracts
why: Whole-file backups could be overwritten or unwound out of order, and malformed state could abort configuration recovery. what: - Preserve first backups and enforce per-config LIFO ordering - Checkpoint state before config writes and each successful revert - Fail closed on missing backups, corrupt state, and malformed configs - Cover repeat swaps, partial failures, and recovery diagnostics
why: Experimental operations, engines, and agent tools could diverge from their documented constructor, result, and command-boundary contracts. what: - Make Attributes the checked source for generated constructor API prose - Expose only tmux-supported targets across Python, MCP, and payloads - Preserve create results and tmux 3.7 composed-operation invariants - Gate executable MCP payloads across every executable tool path - Preserve literal arguments across every experimental tmux transport - Add the direct YAML dependency and tested failure guidance
why: Show how typed Python chains become folded tmux command sequences while one asynchronous control-mode client carries the work. what: - Add a tabbed live tutorial for forward references and planner folding - Replace simulated plan examples with real tmux execution - Test visible compiled commands against actual control-mode dispatches - Add API destinations and navigation for plan concepts
why: First-party record fields must render with complete semantic prose, while gp-sphinx a36 now owns documented-member deduplication. what: - Expand the runtime contract across supported record declarations - Define inheritance, ordering, and exemption rules in AGENTS.md - Remove the obsolete no-undoc-members workaround and source test
why: CI must type-check the untyped doctest dependency boundary and the heterogeneous results produced by a compiled operation plan. what: - Describe the consumed doctest finder interface with a protocol - Narrow the terminal plan result before reading message text
why: Operation's ten class variables were documented as a hand-written definition list under Notes, because an Attributes entry for a class variable used to be dropped from the build. gp-sphinx renders one now, with the annotation and value alongside the prose, so the workaround costs a reader the type and default it cannot state. what: - Move kind, command, scope, result_cls, chainable, primitive, safety, effects, min_version, and flag_version_map into the Attributes section, dropping the Notes list Requires a gp-sphinx release carrying the class-variable rendering; under the pinned 0.0.1a36 these descriptions do not render.
why: Engine users need transport-specific examples that expose real output and boundaries without treating mock results as server evidence. what: - Add one executable first-success example per concrete engine - Map every engine to a focused live or offline tutorial - Test tutorial ownership and transport boundaries
why: gp-sphinx removes tabs.js after rendering, leaving pages with a missing asset reference even though inline tabs operate through CSS. what: - Filter only tabs.js from Sphinx page contexts at late priority - Verify final tab markup and assets with a one-page Sphinx build
why: ruff's default rule set, adopted on master, enforces PLR0402. `import a.b as b` and `from a import b` bind the same name, and the from-form is the one the rest of the suite uses. what: - Rewrite the engines and ops submodule imports in the docs tests https://docs.astral.sh/ruff/rules/manual-from-import/
why: ruff's default rule set enforces FURB188. The conditional slice and `str.removeprefix` are equivalent for a single-character prefix, and the method says what the code is doing. what: - Replace the guarded slice in `ControlNotification.parse` https://docs.astral.sh/ruff/rules/slice-to-remove-prefix-or-suffix/
why: ruff's default rule set enforces PYI025. Bare `Set` reads as the `set` builtin at the use site, but it is the abstract collection; the annotation accepts any set-like, not just `set`. what: - Import `collections.abc.Set` as `AbstractSet` and use it in `get_objects`' docnames annotation https://docs.astral.sh/ruff/rules/unaliased-collections-abc-set-import/
why: ruff's default rule set enforces FLY002, which wants an f-string in
place of a static join. An f-string is the wrong shape here: tmux format
specifiers are `#{...}`, so every brace would need doubling, and the
eight fields would collapse onto one line. Binding the tuple keeps one
field per line and leaves the join non-static.
what:
- Extract the tmux format specifiers into `_DONE_FIELDS` and join that
`_DONE_FORMAT` is unchanged.
https://docs.astral.sh/ruff/rules/static-join-to-f-string/
why: ruff's default rule set enforces ISC004. Implicit concatenation inside a list literal reads like a missing comma between elements, which is how a segment silently merges into its neighbour. Explicit parens make each element's extent unambiguous. what: - Wrap the four multi-line instruction segments in parentheses The rendered instructions are byte-identical, with and without events. https://docs.astral.sh/ruff/rules/implicit-string-concatenation-in-collection-literal/
why: ruff's default rule set enforces PYI034. Annotating `__enter__`, `__aenter__`, and `__new__` with the concrete class loses the subclass: `with SubEngine() as e` inferred the base, so subclass-only attributes read as errors and the wrong type propagated to callers. what: - Return `Self` from `ControlModeEngine.__enter__`, `AsyncControlModeEngine.__aenter__`, and `CommandSeparator.__new__` - Same for the forged separator in the engine base tests - Import `Self` from `typing_extensions` under `TYPE_CHECKING`, matching the rest of the package's 3.10 backport pattern https://docs.astral.sh/ruff/rules/non-self-return-type/
why: ruff's default rule set enforces FURB192. Sorting a whole name set to read its first element states the intent less directly than asking for the minimum. what: - Use `min()` for the two suggested-server picks in the doctor output Ruff marks the fix unsafe because `sorted(x)[0]` raises `IndexError` on an empty sequence where `min(x)` raises `ValueError`. Both call sites sit behind an emptiness guard on the line above, so neither can be reached with an empty set. https://docs.astral.sh/ruff/rules/sorted-min-max/
why: ruff's default rule set enables BLE001, which fires at nine sites where catching everything is the contract rather than a mistake. Each handler records the failure for a caller instead of swallowing it, so narrowing the except clause would lose the failure mode it exists to report. what: - Scope per-file ignores, with the reason, to the async control-mode supervisor, the MCP event drainer, the error-result middleware, the schema fallbacks, and the safety-gate tier assertions The supervisor and reader tasks re-raise `CancelledError` before the catch-all, so cancellation still propagates. https://docs.astral.sh/ruff/rules/blind-except/
why: ruff's EXE001 fires on CI but never locally: it short-circuits on WSL, where every file reports executable, so a Linux runner sees a shebang on a mode-644 file that this machine cannot. Both scripts also declared PEP 723 dependencies their `python3` shebang could not satisfy, so `./scripts/mcp_swap.py` died on a missing import. what: - Set mode 100755 on `scripts/bench_engines.py` and `scripts/mcp_swap.py` - Point both shebangs at `uv run --script`, which resolves the inline dependency block `uv run scripts/<name>.py`, the form the docs use, is unaffected. https://docs.astral.sh/ruff/rules/shebang-not-executable/
Summary
Adds the typed experimental stack under
libtmux.experimental: operations,engines, eager/lazy/async objects, plans, declarative workspaces, live pane
queries, and an optional MCP server.
The work is additive and remains outside libtmux's stable-versioning policy. It
implements the architecture from #688 and #689 without changing the existing
public ORM API.
What ships
Typed operations and results
Pane, and Client scopes.
underlying tmux command.
incomplete composed-operation failures.
semicolon-folded, and
{marked}dispatch with identical result semantics.share the same constructor-field contract.
Engines and command boundaries
SubprocessEngineAsyncSubprocessEngineMockEngineAsyncMockEnginetmux -C)ControlModeEngineAsyncControlModeEngineImsgEngineEvery engine returns the same
CommandResultshape. Direct argv, control-modelines, and imsg frames preserve literal semicolons, newlines, carriage returns,
and leading-dash positional values. Typed separator provenance prevents user
data from becoming a second tmux command.
Objects, queries, and workspaces
operation spine.
panes()provides lazy filtering, ordering, limiting, mapping, and foldedper-pane commands against either a live engine or snapshots.
Workspacevalues compile into inspectable plans, support YAML,environment and option propagation, host-step fold boundaries, workspace
sets, and tmux 3.7 floating panes.
result omits the identifier required to construct the next object.
MCP server
The optional
libtmux[mcp]extra provides curated tools, one tool peroperation, plan tools, workspace tools, resources, prompts, and output
monitoring. Safety is evaluated from the concrete payload across direct,
per-operation, plan, workspace, and event paths. Executable shell,
configuration, environment, option, and active-format payloads require the
destructive tier; target-aware tools also protect the caller's own tmux
hierarchy.
Documentation and developer experience
Pane, and Client, with one generated API page per operation.
QueryList, tmux-format, Neo, and snapshotguides with API references, examples, happy paths, and failure paths.
MockEngineisreserved for explicitly offline engine/testing documentation.
Attributessections,and operation badges/cross-links use the normal gp-sphinx API presentation.
verifies the operation registry cannot drift from its pages.
Verification
uv run ruff check . --fix --show-fixesuv run ruff format .uv run ty checkuv run mypyuv run py.test --reruns 0 -vvv: 3,104 passed, 1 skippedjust build-docs: 141 pages built successfullycontrol-mode, async control-mode, and imsg transports.
Refs #688, #689.