@team-agent/installer 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  use super::*;
2
2
  use crate::transport::test_support::OfflineTransport;
3
- use serial_test::serial;
4
3
  use serde_json::json;
4
+ use serial_test::serial;
5
5
 
6
6
  const QS_TEAM_MD: &str =
7
7
  "---\nname: quickteam\nobjective: Quick start.\nprovider: codex\n---\n\nQuick-start team.\n";
@@ -35,7 +35,32 @@ fn role_doc(id: &str) -> String {
35
35
  )
36
36
  }
37
37
 
38
- fn layout_pane(session: &str, window: &str, pane: &str, pane_index: u32) -> crate::transport::PaneInfo {
38
+ fn codex_identity_rollout(
39
+ workspace: &std::path::Path,
40
+ file_name: &str,
41
+ session_id: &str,
42
+ embedded_agent_id: &str,
43
+ ) -> PathBuf {
44
+ let path = workspace.join(file_name);
45
+ std::fs::write(
46
+ &path,
47
+ format!(
48
+ "{{\"session_meta\":{{\"payload\":{{\"id\":\"{session_id}\",\"cwd\":\"{}\"}}}}}}\n\
49
+ {{\"type\":\"turn_context\",\"payload\":{{}}}}\n\
50
+ {{\"type\":\"response_item\",\"payload\":{{\"content\":[{{\"type\":\"input_text\",\"text\":\"You are Team Agent worker `{embedded_agent_id}` with role `fixture`.\"}}]}}}}\n",
51
+ workspace.to_string_lossy()
52
+ ),
53
+ )
54
+ .unwrap();
55
+ path
56
+ }
57
+
58
+ fn layout_pane(
59
+ session: &str,
60
+ window: &str,
61
+ pane: &str,
62
+ pane_index: u32,
63
+ ) -> crate::transport::PaneInfo {
39
64
  crate::transport::PaneInfo {
40
65
  pane_id: crate::transport::PaneId::new(pane),
41
66
  session: crate::transport::SessionName::new(session),
@@ -232,17 +257,16 @@ fn quick_start_default_workspace_compiled_spec_uses_project_root() {
232
257
  let workspace = temp_ws();
233
258
  std::fs::create_dir_all(workspace.join("agents")).unwrap();
234
259
  std::fs::write(workspace.join("TEAM.md"), QS_TEAM_MD).unwrap();
235
- std::fs::write(workspace.join("agents").join("implementer.md"), QS_VALID_ROLE).unwrap();
260
+ std::fs::write(
261
+ workspace.join("agents").join("implementer.md"),
262
+ QS_VALID_ROLE,
263
+ )
264
+ .unwrap();
236
265
  seed_healthy_coordinator(&workspace);
237
266
  let transport = OfflineTransport::new();
238
267
 
239
268
  let report = quick_start_with_transport_in_workspace(
240
- &workspace,
241
- &workspace,
242
- None,
243
- true,
244
- None,
245
- &transport,
269
+ &workspace, &workspace, None, true, None, &transport,
246
270
  )
247
271
  .expect("quick-start workspace-root team should reach a report");
248
272
  assert!(
@@ -264,7 +288,11 @@ fn quick_start_default_workspace_compiled_spec_uses_project_root() {
264
288
  Some(workspace.to_string_lossy().as_ref()),
265
289
  "compiled team.workspace must be the project root, not its parent"
266
290
  );
267
- for agent in spec.get("agents").and_then(crate::model::yaml::Value::as_list).unwrap() {
291
+ for agent in spec
292
+ .get("agents")
293
+ .and_then(crate::model::yaml::Value::as_list)
294
+ .unwrap()
295
+ {
268
296
  assert_eq!(
269
297
  agent
270
298
  .get("working_directory")
@@ -1119,13 +1147,17 @@ fn adaptive_layout_plan_8_workers_is_3_3_2() {
1119
1147
  assert_eq!(
1120
1148
  windows,
1121
1149
  vec![
1122
- "team-w1", "team-w1", "team-w1", "team-w2", "team-w2", "team-w2", "team-w3",
1123
- "team-w3",
1150
+ "team-w1", "team-w1", "team-w1", "team-w2", "team-w2", "team-w2", "team-w3", "team-w3",
1124
1151
  ]
1125
1152
  );
1126
1153
  let pane_counts = ["team-w1", "team-w2", "team-w3"]
1127
1154
  .into_iter()
1128
- .map(|window| windows.iter().filter(|actual| actual.as_str() == window).count())
1155
+ .map(|window| {
1156
+ windows
1157
+ .iter()
1158
+ .filter(|actual| actual.as_str() == window)
1159
+ .count()
1160
+ })
1129
1161
  .collect::<Vec<_>>();
1130
1162
  assert_eq!(pane_counts, vec![3, 3, 2]);
1131
1163
  assert_eq!(
@@ -1158,9 +1190,12 @@ fn quick_start_default_adaptive_groups_workers_into_layout_panes() {
1158
1190
  .expect("quick_start_with_transport must reach Ready");
1159
1191
 
1160
1192
  let (launch, attach_commands, display_backend) = match report {
1161
- QuickStartReport::Ready { launch, attach_commands, display_backend, .. } => {
1162
- (*launch, attach_commands, display_backend)
1163
- }
1193
+ QuickStartReport::Ready {
1194
+ launch,
1195
+ attach_commands,
1196
+ display_backend,
1197
+ ..
1198
+ } => (*launch, attach_commands, display_backend),
1164
1199
  other => panic!("quick_start must reach Ready; got {other:?}"),
1165
1200
  };
1166
1201
  // 0.3.28 Step 4b: adaptive 3-pane tiling replaced with 1-window-per-agent
@@ -1183,7 +1218,9 @@ fn quick_start_default_adaptive_groups_workers_into_layout_panes() {
1183
1218
  .pane_title_records()
1184
1219
  .iter()
1185
1220
  .all(|(session, _, _, _)| Some(session.as_str())
1186
- == state.get("session_name").and_then(serde_json::Value::as_str)),
1221
+ == state
1222
+ .get("session_name")
1223
+ .and_then(serde_json::Value::as_str)),
1187
1224
  "pane titles must be configured inside the team session"
1188
1225
  );
1189
1226
  // Each worker lives in its OWN window named `agent_id` (Python parity).
@@ -1226,7 +1263,9 @@ fn quick_start_persists_selected_tmux_endpoint_and_attach_commands() {
1226
1263
  let report = quick_start_with_transport(&team, None, true, None, &transport)
1227
1264
  .expect("quick_start_with_transport must reach Ready");
1228
1265
  let attach_commands = match report {
1229
- QuickStartReport::Ready { attach_commands, .. } => attach_commands,
1266
+ QuickStartReport::Ready {
1267
+ attach_commands, ..
1268
+ } => attach_commands,
1230
1269
  other => panic!("quick_start must reach Ready; got {other:?}"),
1231
1270
  };
1232
1271
 
@@ -1244,7 +1283,10 @@ fn quick_start_persists_selected_tmux_endpoint_and_attach_commands() {
1244
1283
  assert_eq!(state["tmux_endpoint"], json!(endpoint));
1245
1284
  assert_eq!(state["tmux_socket"], json!(endpoint));
1246
1285
  assert_eq!(state["is_external_leader"], json!(false));
1247
- assert_eq!(state["teams"]["teamdir"]["is_external_leader"], json!(false));
1286
+ assert_eq!(
1287
+ state["teams"]["teamdir"]["is_external_leader"],
1288
+ json!(false)
1289
+ );
1248
1290
  }
1249
1291
 
1250
1292
  #[test]
@@ -1264,8 +1306,7 @@ fn annotate_runtime_tmux_endpoint_persists_workspace_socket_as_full_path() {
1264
1306
  "runtime endpoint state must persist the full tmux socket path, not the short -L name"
1265
1307
  );
1266
1308
  assert_eq!(
1267
- state["tmux_socket"],
1268
- state["tmux_endpoint"],
1309
+ state["tmux_socket"], state["tmux_endpoint"],
1269
1310
  "tmux_socket mirrors the canonical persisted endpoint"
1270
1311
  );
1271
1312
  }
@@ -1301,7 +1342,9 @@ fn quick_start_preserves_managed_leader_topology_and_emits_leader_attach_command
1301
1342
  let report = quick_start_with_transport(&team, None, true, None, &transport)
1302
1343
  .expect("quick_start_with_transport must reach Ready");
1303
1344
  let attach_commands = match report {
1304
- QuickStartReport::Ready { attach_commands, .. } => attach_commands,
1345
+ QuickStartReport::Ready {
1346
+ attach_commands, ..
1347
+ } => attach_commands,
1305
1348
  other => panic!("quick_start must reach Ready; got {other:?}"),
1306
1349
  };
1307
1350
 
@@ -1381,7 +1424,9 @@ fn quick_start_no_display_keeps_one_window_per_agent() {
1381
1424
  .expect("quick_start_with_transport must reach Ready");
1382
1425
 
1383
1426
  let display_backend = match report {
1384
- QuickStartReport::Ready { display_backend, .. } => display_backend,
1427
+ QuickStartReport::Ready {
1428
+ display_backend, ..
1429
+ } => display_backend,
1385
1430
  other => panic!("quick_start must reach Ready; got {other:?}"),
1386
1431
  };
1387
1432
  assert_eq!(display_backend, "none");
@@ -1690,9 +1735,7 @@ fn restart_allow_fresh_does_not_force_fresh_other_agents_when_one_session_captur
1690
1735
  std::fs::create_dir_all(&dated).unwrap();
1691
1736
  let alpha_session = "019ee540-37ed-7a20-a141-1d654224d209";
1692
1737
  std::fs::write(
1693
- dated.join(format!(
1694
- "rollout-2026-06-20T21-37-31-{alpha_session}.jsonl"
1695
- )),
1738
+ dated.join(format!("rollout-2026-06-20T21-37-31-{alpha_session}.jsonl")),
1696
1739
  "{}\n",
1697
1740
  )
1698
1741
  .unwrap();
@@ -1774,6 +1817,153 @@ fn restart_allow_fresh_does_not_force_fresh_other_agents_when_one_session_captur
1774
1817
  );
1775
1818
  }
1776
1819
 
1820
+ #[test]
1821
+ fn restart_allow_fresh_clears_codex_identity_mismatch_tuple_before_capture() {
1822
+ let ws = temp_ws().join("restartcrossbindallowfresh");
1823
+ std::fs::create_dir_all(ws.join("agents")).unwrap();
1824
+ std::fs::write(
1825
+ ws.join("TEAM.md"),
1826
+ "---\nname: restartcrossbindallowfresh\nobjective: Restart crossbind repair.\nprovider: codex\n---\n\nteam.\n",
1827
+ )
1828
+ .unwrap();
1829
+ std::fs::write(ws.join("agents").join("alpha.md"), DELEG_ROLE_ALPHA).unwrap();
1830
+ std::fs::write(ws.join("agents").join("bravo.md"), DELEG_ROLE_BRAVO).unwrap();
1831
+ let alpha_session = "019f3586-6eb4-7552-8680-c833b483a289";
1832
+ let alpha_rollout = codex_identity_rollout(&ws, "alpha-rollout.jsonl", alpha_session, "alpha");
1833
+ let spec = crate::compiler::compile_team(&ws).expect("compile crossbind team");
1834
+ std::fs::write(ws.join("team.spec.yaml"), crate::model::yaml::dumps(&spec)).unwrap();
1835
+ crate::state::persist::save_runtime_state(
1836
+ &ws,
1837
+ &json!({
1838
+ "session_name": "team-restartcrossbindallowfresh",
1839
+ "agents": {
1840
+ "alpha": {
1841
+ "status": "running",
1842
+ "provider": "codex",
1843
+ "window": "alpha",
1844
+ "first_send_at": "2026-07-06T03:45:00+00:00",
1845
+ "session_id": alpha_session,
1846
+ "rollout_path": alpha_rollout.to_string_lossy(),
1847
+ "captured_at": "2026-07-06T03:45:13.596763+00:00",
1848
+ "captured_via": "fs_watch",
1849
+ "attribution_confidence": "high",
1850
+ "spawn_cwd": ws.to_string_lossy()
1851
+ },
1852
+ "bravo": {
1853
+ "status": "running",
1854
+ "provider": "codex",
1855
+ "window": "bravo",
1856
+ "first_send_at": "2026-07-06T03:45:00+00:00",
1857
+ "session_id": alpha_session,
1858
+ "rollout_path": alpha_rollout.to_string_lossy(),
1859
+ "captured_at": "2026-07-06T03:45:13.596763+00:00",
1860
+ "captured_via": "fs_watch",
1861
+ "attribution_confidence": "high",
1862
+ "spawn_cwd": ws.to_string_lossy()
1863
+ }
1864
+ }
1865
+ }),
1866
+ )
1867
+ .unwrap();
1868
+ seed_healthy_coordinator(&ws);
1869
+ let transport = OfflineTransport::new();
1870
+
1871
+ let result = restart_with_transport(&ws, true, None, &transport);
1872
+
1873
+ assert!(
1874
+ matches!(result, Ok(RestartReport::Restarted { .. })),
1875
+ "allow-fresh restart should repair by fresh-spawning only poisoned bravo; got {result:?}"
1876
+ );
1877
+ let windows = transport.spawn_window_records();
1878
+ let records = transport.spawn_records();
1879
+ let bravo_idx = windows
1880
+ .iter()
1881
+ .position(|(_, window)| window == "bravo")
1882
+ .expect("bravo must spawn");
1883
+ assert!(
1884
+ !records[bravo_idx].1.iter().any(|arg| arg == "resume"),
1885
+ "poisoned bravo must fresh-start without codex resume argv; records={records:?}"
1886
+ );
1887
+
1888
+ let mut state = crate::state::persist::load_runtime_state(&ws).expect("load state");
1889
+ let bravo = state.pointer("/agents/bravo").expect("bravo");
1890
+ for field in [
1891
+ "session_id",
1892
+ "rollout_path",
1893
+ "captured_at",
1894
+ "captured_via",
1895
+ "attribution_confidence",
1896
+ "capture_state",
1897
+ ] {
1898
+ let value = bravo.get(field);
1899
+ assert!(
1900
+ value.is_none() || value == Some(&serde_json::Value::Null),
1901
+ "allow-fresh must clear poisoned bravo {field}; got {value:?} in {bravo}"
1902
+ );
1903
+ }
1904
+ if let Some(teams) = state.get("teams").and_then(serde_json::Value::as_object) {
1905
+ for (team_key, team_state) in teams {
1906
+ if let Some(team_bravo) = team_state.pointer("/agents/bravo") {
1907
+ for field in [
1908
+ "session_id",
1909
+ "rollout_path",
1910
+ "captured_at",
1911
+ "captured_via",
1912
+ "attribution_confidence",
1913
+ "capture_state",
1914
+ ] {
1915
+ let value = team_bravo.get(field);
1916
+ assert!(
1917
+ value.is_none() || value == Some(&serde_json::Value::Null),
1918
+ "allow-fresh must clear teams.{team_key}.agents.bravo {field}; got {value:?} in {team_bravo}"
1919
+ );
1920
+ }
1921
+ }
1922
+ }
1923
+ }
1924
+
1925
+ let fresh_session = "019f3587-bravo-fresh";
1926
+ let fresh_rollout =
1927
+ codex_identity_rollout(&ws, "bravo-fresh-rollout.jsonl", fresh_session, "bravo");
1928
+ let mut adapter_for = |provider| crate::provider::adapter::get_adapter(provider);
1929
+ crate::provider::session::capture::capture_missing_provider_sessions_once(
1930
+ &mut state,
1931
+ &mut adapter_for,
1932
+ true,
1933
+ 0,
1934
+ )
1935
+ .expect("fresh bravo capture should run");
1936
+ let bravo = state.pointer("/agents/bravo").expect("bravo after capture");
1937
+ assert_eq!(
1938
+ bravo.get("session_id").and_then(serde_json::Value::as_str),
1939
+ Some(fresh_session),
1940
+ "fresh bravo rollout should be capturable after allow-fresh clears poison; rollout={fresh_rollout:?} state={bravo}"
1941
+ );
1942
+ assert_eq!(
1943
+ bravo
1944
+ .get("rollout_path")
1945
+ .and_then(serde_json::Value::as_str),
1946
+ Some(fresh_rollout.to_string_lossy().as_ref())
1947
+ );
1948
+ let plan = crate::lifecycle::restart::classify_restart_plan_with_resume_validation(
1949
+ Some(&ws),
1950
+ &state,
1951
+ false,
1952
+ )
1953
+ .expect("classify after fresh capture");
1954
+ assert!(
1955
+ plan.unresumable.is_empty(),
1956
+ "next restart must not loop on session_identity_mismatch after fresh capture; got {:?}",
1957
+ plan.unresumable
1958
+ );
1959
+ let bravo_decision = plan
1960
+ .decisions
1961
+ .iter()
1962
+ .find(|decision| decision.agent_id.as_str() == "bravo")
1963
+ .expect("bravo decision");
1964
+ assert_eq!(bravo_decision.decision, ResumeDecision::Resume);
1965
+ }
1966
+
1777
1967
  #[test]
1778
1968
  fn restart_spawn_failure_isolated_to_partial_report() {
1779
1969
  let ws = restart_ws_two_resumable_workers();
@@ -2362,10 +2552,7 @@ fn fork_refuses_source_with_partial_tuple() {
2362
2552
  let src_id = crate::model::ids::AgentId::new("src");
2363
2553
  let dst_id = crate::model::ids::AgentId::new("clone");
2364
2554
  let result = crate::lifecycle::fork_agent_with_transport(
2365
- &ws,
2366
- &src_id,
2367
- &dst_id,
2368
- None, // label
2555
+ &ws, &src_id, &dst_id, None, // label
2369
2556
  false, // open_display
2370
2557
  None, // team
2371
2558
  &transport,
@@ -2433,7 +2620,10 @@ fn add_agent_adaptive_splits_last_non_full_layout_window() {
2433
2620
  "last non-full layout window should be split"
2434
2621
  );
2435
2622
  let (_raw, state) = raw_runtime_state(&team);
2436
- assert_eq!(state.pointer("/agents/w3/layout_window"), Some(&json!("team-w1")));
2623
+ assert_eq!(
2624
+ state.pointer("/agents/w3/layout_window"),
2625
+ Some(&json!("team-w1"))
2626
+ );
2437
2627
  assert_eq!(state.pointer("/agents/w3/pane_index"), Some(&json!(2)));
2438
2628
  }
2439
2629
 
@@ -2495,7 +2685,10 @@ fn add_agent_adaptive_creates_suffix_window_when_last_layout_full_and_name_colli
2495
2685
  "full last layout window should create next window with collision suffix"
2496
2686
  );
2497
2687
  let (_raw, state) = raw_runtime_state(&team);
2498
- assert_eq!(state.pointer("/agents/w4/layout_window"), Some(&json!("team-w2-2")));
2688
+ assert_eq!(
2689
+ state.pointer("/agents/w4/layout_window"),
2690
+ Some(&json!("team-w2-2"))
2691
+ );
2499
2692
  assert_eq!(state.pointer("/agents/w4/pane_index"), Some(&json!(0)));
2500
2693
  }
2501
2694
 
@@ -2508,7 +2701,11 @@ fn stop_agent_adaptive_kills_target_pane_not_shared_layout_window() {
2508
2701
  .collect::<Vec<_>>();
2509
2702
  let team = quick_start_team_dir_with_roles(&role_refs);
2510
2703
  let spec = crate::compiler::compile_team(&team).unwrap();
2511
- std::fs::write(team.join("team.spec.yaml"), crate::model::yaml::dumps(&spec)).unwrap();
2704
+ std::fs::write(
2705
+ team.join("team.spec.yaml"),
2706
+ crate::model::yaml::dumps(&spec),
2707
+ )
2708
+ .unwrap();
2512
2709
  let session = "team-layout-stop";
2513
2710
  crate::state::persist::save_runtime_state(
2514
2711
  &team,
@@ -2529,8 +2726,7 @@ fn stop_agent_adaptive_kills_target_pane_not_shared_layout_window() {
2529
2726
  ])
2530
2727
  .with_pane_presence("%2", true);
2531
2728
 
2532
- let report =
2533
- stop_agent_with_transport(&team, &AgentId::new("w2"), None, &transport).unwrap();
2729
+ let report = stop_agent_with_transport(&team, &AgentId::new("w2"), None, &transport).unwrap();
2534
2730
 
2535
2731
  assert!(report.stopped);
2536
2732
  assert_eq!(report.target, "%2");
@@ -2544,7 +2740,10 @@ fn stop_agent_adaptive_kills_target_pane_not_shared_layout_window() {
2544
2740
  );
2545
2741
  let (_raw, state) = raw_runtime_state(&team);
2546
2742
  assert_eq!(state.pointer("/agents/w1/pane_id"), Some(&json!("%1")));
2547
- assert_eq!(state.pointer("/agents/w1/layout_window"), Some(&json!("team-w1")));
2743
+ assert_eq!(
2744
+ state.pointer("/agents/w1/layout_window"),
2745
+ Some(&json!("team-w1"))
2746
+ );
2548
2747
  }
2549
2748
 
2550
2749
  #[test]
@@ -2587,7 +2786,10 @@ fn start_agent_adaptive_restarts_missing_pane_in_existing_layout_window() {
2587
2786
  "missing worker pane should be rebuilt in its existing layout window"
2588
2787
  );
2589
2788
  let (_raw, state) = raw_runtime_state(&ws);
2590
- assert_eq!(state.pointer("/agents/w1/layout_window"), Some(&json!("team-w1")));
2789
+ assert_eq!(
2790
+ state.pointer("/agents/w1/layout_window"),
2791
+ Some(&json!("team-w1"))
2792
+ );
2591
2793
  assert_eq!(state.pointer("/agents/w1/window"), Some(&json!("team-w1")));
2592
2794
  assert_eq!(state.pointer("/agents/w2/pane_id"), Some(&json!("%2")));
2593
2795
  }
@@ -2848,6 +3050,21 @@ fn quick_start_running_agent_state_shape_after_spawn_is_golden() {
2848
3050
  json!("%0"),
2849
3051
  "#252 RC2: launch must persist the real pane_id returned by the transport, not drop it when pane_pid is unavailable"
2850
3052
  );
3053
+ let events = crate::event_log::EventLog::new(workspace)
3054
+ .tail(0)
3055
+ .expect("read event log");
3056
+ let spawn_event = events
3057
+ .iter()
3058
+ .find(|event| {
3059
+ event.get("event").and_then(serde_json::Value::as_str)
3060
+ == Some("provider.worker.spawn_argv")
3061
+ && event.get("agent_id").and_then(serde_json::Value::as_str) == Some("implementer")
3062
+ })
3063
+ .unwrap_or_else(|| panic!("provider.worker.spawn_argv missing; events={events:?}"));
3064
+ assert_eq!(spawn_event["spawn_cwd"], json!(workspace.to_string_lossy()));
3065
+ assert_eq!(spawn_event["spawned_at"], json!(FIXED_SPAWNED_AT));
3066
+ assert_eq!(spawn_event["source"], json!("launch"));
3067
+ assert_eq!(spawn_event["spawn_epoch"], json!(0));
2851
3068
  }
2852
3069
 
2853
3070
  // Stage B2 — golden launch/core.py:171-173 writes paused workers as exactly
@@ -2945,12 +3162,12 @@ fn add_agent_resolves_to_persisted_endpoint_socket_not_workspace_hash() {
2945
3162
  )
2946
3163
  .unwrap();
2947
3164
 
2948
- let resolved = crate::lifecycle::restart::lifecycle_worker_tmux_backend_for_selected_state(
2949
- &team, None,
2950
- )
2951
- .expect("resolver must succeed when state is present");
3165
+ let resolved =
3166
+ crate::lifecycle::restart::lifecycle_worker_tmux_backend_for_selected_state(&team, None)
3167
+ .expect("resolver must succeed when state is present");
2952
3168
 
2953
- let endpoint = <crate::tmux_backend::TmuxBackend as crate::transport::Transport>::tmux_endpoint(&resolved);
3169
+ let endpoint =
3170
+ <crate::tmux_backend::TmuxBackend as crate::transport::Transport>::tmux_endpoint(&resolved);
2954
3171
  assert_eq!(
2955
3172
  endpoint.as_deref(),
2956
3173
  Some(live_endpoint.as_str()),
@@ -2973,12 +3190,12 @@ fn add_agent_resolver_falls_back_to_workspace_socket_when_no_persisted_endpoint(
2973
3190
  std::fs::create_dir_all(&team).unwrap();
2974
3191
  // NOTE: no save_runtime_state — cold workspace, no persisted endpoint.
2975
3192
 
2976
- let resolved = crate::lifecycle::restart::lifecycle_worker_tmux_backend_for_selected_state(
2977
- &team, None,
2978
- )
2979
- .expect("resolver must succeed (fall back to for_workspace) on cold workspace");
3193
+ let resolved =
3194
+ crate::lifecycle::restart::lifecycle_worker_tmux_backend_for_selected_state(&team, None)
3195
+ .expect("resolver must succeed (fall back to for_workspace) on cold workspace");
2980
3196
 
2981
- let endpoint = <crate::tmux_backend::TmuxBackend as crate::transport::Transport>::tmux_endpoint(&resolved);
3197
+ let endpoint =
3198
+ <crate::tmux_backend::TmuxBackend as crate::transport::Transport>::tmux_endpoint(&resolved);
2982
3199
  let fallback = <crate::tmux_backend::TmuxBackend as crate::transport::Transport>::tmux_endpoint(
2983
3200
  &crate::tmux_backend::TmuxBackend::for_workspace(&team),
2984
3201
  );
@@ -3044,7 +3261,9 @@ fn add_agent_reachability_gate_returns_error_when_spawn_pane_not_addressable() {
3044
3261
  );
3045
3262
  let err_msg = result.unwrap_err().to_string();
3046
3263
  assert!(
3047
- err_msg.contains("unreachable") || err_msg.contains("not addressable") || err_msg.contains("socket drift"),
3264
+ err_msg.contains("unreachable")
3265
+ || err_msg.contains("not addressable")
3266
+ || err_msg.contains("socket drift"),
3048
3267
  "0.3.24 reachability gate: error message must name the unreachable / \
3049
3268
  socket-drift symptom so operators can diagnose. Got: {err_msg}"
3050
3269
  );
@@ -3701,16 +3920,31 @@ fn e45_is_adaptive_layout_window_recognises_team_w_pattern_only() {
3701
3920
  assert!(is_adapt("team-w1"), "team-w1 must be adaptive");
3702
3921
  assert!(is_adapt("team-w2"), "team-w2 must be adaptive");
3703
3922
  assert!(is_adapt("team-w42"), "team-w42 must be adaptive");
3704
- assert!(is_adapt("team-w7-suffix"), "team-w7-suffix must be adaptive");
3923
+ assert!(
3924
+ is_adapt("team-w7-suffix"),
3925
+ "team-w7-suffix must be adaptive"
3926
+ );
3705
3927
 
3706
- assert!(!is_adapt("developer"), "developer is per-agent, not adaptive");
3707
- assert!(!is_adapt("architect"), "architect is per-agent, not adaptive");
3928
+ assert!(
3929
+ !is_adapt("developer"),
3930
+ "developer is per-agent, not adaptive"
3931
+ );
3932
+ assert!(
3933
+ !is_adapt("architect"),
3934
+ "architect is per-agent, not adaptive"
3935
+ );
3708
3936
  assert!(!is_adapt("demo-director"), "demo-director is per-agent");
3709
3937
  assert!(!is_adapt("leader"), "leader is not adaptive");
3710
3938
  assert!(!is_adapt(""), "empty is not adaptive");
3711
3939
  assert!(!is_adapt("team-w"), "team-w (no index) is not adaptive");
3712
- assert!(!is_adapt("team-w0"), "team-w0 (index 0 invalid post-subtract) is not adaptive");
3713
- assert!(!is_adapt("team-wfoo"), "team-wfoo (non-numeric) is not adaptive");
3940
+ assert!(
3941
+ !is_adapt("team-w0"),
3942
+ "team-w0 (index 0 invalid post-subtract) is not adaptive"
3943
+ );
3944
+ assert!(
3945
+ !is_adapt("team-wfoo"),
3946
+ "team-wfoo (non-numeric) is not adaptive"
3947
+ );
3714
3948
  }
3715
3949
 
3716
3950
  // ═════════════════════════════════════════════════════════════════════════════