Skip to content

Read client_control_mode, not client_control - #10

Open
tony wants to merge 1 commit into
masterfrom
fix/is-control-client-wire-name
Open

Read client_control_mode, not client_control#10
tony wants to merge 1 commit into
masterfrom
fix/is-control-client-wire-name

Conversation

@tony

@tony tony commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Client.IsControlClient was unconditionally false — for every client, on every supported tmux version. Found while auditing comments in #8; investigated separately because it is a code defect, not a comment one.

The bug

public bool IsControlClient => ReadSnapshot("client_control") == "1";

ReadSnapshot is an exact TryGetValue against the snapshot dictionary. That dictionary is keyed by the wire names FormatCatalog requests, and the only client-control field it ever asks tmux for is client_control_mode. The lookup missed, returned null, and null == "1" is false.

client_control is not a tmux format token at all. Against a live control-mode client:

$ tmux list-clients -F 'control_mode=[#{client_control_mode}] client_control=[#{client_control}] invented=[#{zz_not_a_token}]'
control_mode=[1] client_control=[] invented=[]

The suspect renders identically to a token invented for the comparison. Repeated across every build in the compatibility matrix — 3.2a, 3.3a, 3.4, 3.5, 3.6, 3.7, 3.7a, 3.7b — with the same result on all eight.

Python libtmux, which this port tracks, records libtmux.neo:Obj.client_control_mode in docs/parity/python-public-api.json.

Why it survived

Two tests asserted on the property and both asserted false: ClientAdministrationTests and Component13ParityTests, each against a PTY-attached client, for which false is correct whether or not the field resolves. A property that can only return one value is invisible to tests that never assert the other.

QuerySemanticsTests asserted the literal "client_control" under the comment "The one that a naming rule would never produce." The odd spelling was read as deliberate evidence against the naming convention rather than as a typo, so it was locked in rather than questioned.

ControlModeClientScope — the test helper that finds a control client — has used #{client_control_mode} correctly all along. The right spelling was already in the repository.

The regression test

Control_client_reads_back_as_one attaches a real control client and asserts IsControlClient is true. Verified it fails without the fix and passes with it:

With the one-line fix reverted
Test run summary: Failed!
  total: 1
  failed: 1

Scope

The query surface carried the same wrong name but was not independently broken: QueryInterpreter.ReadMember resolves fields by CLR reflection, so a LINQ query inherited the broken property rather than adding a second fault. The exposure was to a third-party interpreter built against the published schema, which would send #{client_control} to tmux and get silent empty results.

The schema enum is corrected in place rather than versioned. src/LibTmux.Query.Json/README.md states the package is alpha and can change between prereleases without notice, and its PublicAPI.Shipped.txt is empty — nothing has crossed into shipped.

docs/decisions/evidence/0003/aot/libtmux-query-v1.schema.json is deliberately left alone: decision records quote what was run at the time and are not edited, per CONTRIBUTING.md.

Verification

gate result
dotnet build --warnaserror 0 warnings, 0 errors
verify_public_api.py pass
verify_capabilities.py pass
verify_workflows.py pass
sync_snippets.py --check pass
dump_tools.py --check pass
unit tests 297 total, 0 failed
ClientAdministrationTests 4 total, 0 failed
Component13ParityTests 18 total, 0 failed
pytest eng 1113 passed, 10 skipped

why: IsControlClient read "client_control", which is not a tmux format
token on any supported version -- it renders exactly like a token that
does not exist. The lookup missed, so the property was false for every
client, including one attached with `tmux -C`. Checked against a live
control client on 3.2a through 3.7b.

The same spelling sat in the query field catalog, the published JSON
schema and three READMEs. Python libtmux, which this port tracks,
records client_control_mode.

The schema enum is corrected in place rather than versioned: the
package documents itself as alpha that can change between prereleases,
and its PublicAPI.Shipped.txt is still empty.

what:
- Read client_control_mode, the only client-control field
  FormatCatalog ever asks tmux for
- Rename it in the field catalog generator, the query translator's
  example, and the three libtmux-query-v1 schema enums
- Correct the three READMEs that published the old spelling
- Assert a real control client reads back as one; the suite only
  asserted the false case, which a broken read also satisfies
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.

1 participant