1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! The nested-session guard's name/id resolver + duplicate-name tie-break
//! (#2157 item 4, #3714).
//!
//! Why: extracted from `guided.rs` (issue #3714 line-cap follow-up — the
//! finding-1/finding-2 review round pushed `guided.rs` to 533 SLOC, over the
//! 500-SLOC production cap) so the resolver logic and its extensive tie-break
//! documentation live in their own file, mirroring the existing
//! `guided_autostart`/`guided_inplace`/`guided_launch`/`guided_resume`
//! sibling-module convention this crate already uses for `guided.rs`'s other
//! extracted concerns. Pure code motion — no behavior change; see each
//! function's doc for the full rationale (unchanged from the pre-move
//! version).
//! What: [`nested_managed_match`] — does any known managed record belong to
//! the pane bare `tm` is currently running inside, matched by tmux session
//! name or `TM_MANAGED_SESSION_ID`? [`pick_least_ambiguous`] — the tie-break
//! tiers applied when more than one record matches (a duplicated tmux
//! session name, #3692/#3714). [`print_ambiguous_match_notice`] — the
//! full-session-id disambiguation listing printed when every tier is
//! exhausted and a tie remains.
//! Test: `guided_resolver_tests.rs` (moved here from `tests_behavior_c_tests.rs`
//! in the same #3714 line-cap follow-up, for the identical reason).
/// Pure predicate: does ANY record in `records` belong to the pane bare `tm`
/// is currently running inside?
///
/// Why: isolating the match rule from the daemon round-trip and the tmux
/// shell-out makes the actual guard DECISION exhaustively unit-testable
/// without a live daemon or tmux server.
///
/// #2790 code-critic HIGH: tmux SESSION NAMES ARE RECYCLED after a session is
/// decommissioned (`session_manager::manager`'s name-reuse policy) — a plain
/// `.find()` over ALL candidates (including tombstones) can therefore return a
/// STALE `Decommissioned` record for a name that a genuinely LIVE session now
/// also owns, which would drive `RelaunchInPlace` against the wrong (dead)
/// record while a live session sharing that name sits in a sibling pane — the
/// exact hijack class #2456/#2680 fixed elsewhere.
/// [`SessionManager::capture_pane_by_tmux_name`] (`session_manager/manager.rs`)
/// already carries the identical guard for the same reason (idle-reaper pane
/// capture) — this mirrors it.
/// What: collects every record matching `current_session_name` OR
/// `env_session_id`, then prefers the most-recently-created (`created_at`,
/// RFC3339 — lexicographically sortable) NON-`Decommissioned` match. Only when
/// NO candidate is non-`Decommissioned` does it fall back to the
/// most-recently-created `Decommissioned` candidate — the legitimate #2777
/// repro case (a decommissioned session's OWN, not-yet-recycled name). `None`
/// when both inputs are `None`/non-matching, which includes the "not inside
/// tmux" case (callers pass `current_session_name: None` then).
/// Test: `nested_managed_match_by_session_name`,
/// `nested_managed_match_by_env_id`, `nested_managed_match_none_when_no_match`,
/// `nested_managed_match_none_when_both_inputs_absent`,
/// `nested_managed_match_prefers_live_over_recycled_decommissioned_name`,
/// `nested_managed_match_falls_back_to_decommissioned_when_no_live_candidate`,
/// `nested_managed_match_prefers_most_recent_live_among_multiple`,
/// `nested_managed_match_prefers_own_pane_identity_over_recency` (#3714),
/// `nested_managed_match_prefers_verifiably_alive_pane_over_dead_duplicate`
/// (#3714), `nested_managed_match_refuses_and_lists_ids_when_still_tied`
/// (#3714) — see [`pick_least_ambiguous`] for the tie-break tiers.
pub
/// Break a tie among several candidates [`nested_managed_match`] found by
/// name/env-id (#3714) — a duplicated tmux session name can legitimately
/// produce more than one match here (the exact #3692/#3714 condition).
///
/// Why: the pre-#3714 tie-break was a single `max_by_key(created_at)` over
/// every non-decommissioned candidate — deterministic, but blind to which
/// candidate's pane is ACTUALLY alive. A stale duplicate created AFTER the
/// genuinely live session (an entirely plausible ordering — the live session
/// long predates the stale one in the reported issue) would win purely on
/// recency, stranding the operator against a dead-pane refusal while sitting
/// inside their own live session.
/// What: applies FOUR tiers, strongest signal first, returning as soon as
/// one produces a single winner: (1) the invoking process's OWN tmux pane —
/// `pane_id` is never shared between two records, so a match here is proof,
/// not a heuristic; (2) among the remainder, prefer candidates whose `state`
/// reads `"active"` (server-reconciled PANE-scoped liveness, #3714 part 3 —
/// no longer a bare name-string check) over ones that don't; (3) — ONLY when
/// tier (2) is empty — prefer any NON-`"decommissioned"` candidate (e.g.
/// `"stopped"`/`"errored"`) over a decommissioned tombstone, EXACTLY
/// mirroring the pre-#3714 `state != "decommissioned"` tie-break (#3714
/// review finding 1: an earlier revision collapsed tiers 2 and 3 into a
/// single `state == "active"` filter, which let a genuinely `"stopped"`
/// record LOSE to a newer decommissioned tombstone — a real behavior
/// regression from the pre-#3714 code, not just a doc inaccuracy); falling
/// back to EVERY candidate only when tier (3) is also empty (every
/// candidate is decommissioned — the legitimate #2777 case); (4) within the
/// surviving tier, the most-recently-created candidate (the prior sole
/// tie-break, now the weakest and last resort). Returns `Ok(single winner)`
/// as soon as exactly one candidate survives a tier; `Err(tied)` — the
/// tier's full surviving set — when candidates remain tied even after tier
/// (4), so the caller can print every tied id rather than guess.
/// Test: see [`nested_managed_match`]'s test list.
pub
/// Print the operator-facing disambiguation notice for
/// [`nested_managed_match`]'s refusal path (#3714) — every tied candidate's
/// FULL session id, never a truncated/ambiguous name.
///
/// Why: the whole point of refusing here is that a name/short identifier is
/// not enough to pick safely; the notice must give the operator the one
/// thing that IS unambiguous — the full id — so they can act with an
/// explicit `tm sessions resume <id>`.
/// What: writes one header line naming the ambiguous key, then one line per
/// tied candidate (`id`, `name`, `state`) to stderr.
/// Test: `nested_managed_match_refuses_and_lists_ids_when_still_tied`
/// asserts the returned `None`; this pure formatter's exact text is not
/// itself unit-asserted (stderr side effect), matching `guided.rs`'s own
/// convention for `print_project_context`/`print_non_tty_hint`.