@team-agent/installer 0.5.98 → 0.5.100
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.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/src/cli/adapters.rs +1 -163
- package/crates/team-agent/src/cli/diagnose.rs +3 -19
- package/crates/team-agent/src/cli/emit.rs +20 -204
- package/crates/team-agent/src/cli/mod.rs +138 -205
- package/crates/team-agent/src/cli/send/coordinator.rs +2 -2
- package/crates/team-agent/src/cli/spec.rs +41 -67
- package/crates/team-agent/src/cli/tests/main_preserved.rs +2 -186
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +9 -10
- package/crates/team-agent/src/cli/tests/run_delegation.rs +0 -3
- package/crates/team-agent/src/cli/tests/verb_validate.rs +0 -1
- package/crates/team-agent/src/cli/triage.rs +1 -1
- package/crates/team-agent/src/cli/types.rs +0 -55
- package/crates/team-agent/src/compiler/tests.rs +5 -8
- package/crates/team-agent/src/compiler.rs +6 -14
- package/crates/team-agent/src/leader/lease.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +5 -25
- package/crates/team-agent/src/lifecycle/launch/identity.rs +2 -18
- package/crates/team-agent/src/lifecycle/launch/layout.rs +7 -29
- package/crates/team-agent/src/lifecycle/launch/leader_context.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/ownership.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/pi_mcp.rs +7 -7
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +12 -49
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +3 -9
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +2 -61
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +2 -15
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +3 -7
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch.rs +3 -4
- package/crates/team-agent/src/lifecycle/mod.rs +0 -8
- package/crates/team-agent/src/lifecycle/restart/agent.rs +62 -8
- package/crates/team-agent/src/lifecycle/restart/common.rs +0 -32
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +6 -15
- package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +1 -2
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +0 -1
- package/crates/team-agent/src/lifecycle/tests/core.rs +0 -213
- package/crates/team-agent/src/lifecycle/tests/issue238_codex_effort_contract.rs +96 -0
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +1 -0
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +31 -77
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +4 -8
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +16 -9
- package/crates/team-agent/src/lifecycle/tests/pi_executable_mcp_red.rs +1 -1
- package/crates/team-agent/src/lifecycle/tests/realmachine_clusters_1_6_red.rs +0 -60
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +3 -4
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests.rs +1 -2
- package/crates/team-agent/src/lifecycle/types.rs +3 -133
- package/crates/team-agent/src/messaging/send.rs +2 -2
- package/crates/team-agent/src/model/enums.rs +21 -71
- package/crates/team-agent/src/model/spec.rs +5 -20
- package/crates/team-agent/src/provider/adapters/codex.rs +2 -2
- package/crates/team-agent/src/provider/types.rs +7 -6
- package/crates/team-agent/src/state/repository.rs +0 -5
- package/examples/team.spec.yaml +0 -1
- package/package.json +4 -4
- package/schemas/team.schema.json +2 -2
- package/skills/team-agent/SKILL.md +1 -1
- package/skills/team-agent/references/recovery-runbook.md +2 -2
- package/skills/team-agent/references/team-agent-operator.md +3 -10
- package/skills/team-agent/references/team-in-team.md +0 -6
- package/crates/team-agent/src/lifecycle/display.rs +0 -550
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +0 -884
- package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +0 -481
|
@@ -1382,13 +1382,12 @@ fn quick_start_default_adaptive_groups_workers_into_layout_panes() {
|
|
|
1382
1382
|
let report = quick_start_with_transport(&team, None, true, None, &transport)
|
|
1383
1383
|
.expect("quick_start_with_transport must reach Ready");
|
|
1384
1384
|
|
|
1385
|
-
let (launch, attach_commands
|
|
1385
|
+
let (launch, attach_commands) = match report {
|
|
1386
1386
|
QuickStartReport::Ready {
|
|
1387
1387
|
launch,
|
|
1388
1388
|
attach_commands,
|
|
1389
|
-
display_backend,
|
|
1390
1389
|
..
|
|
1391
|
-
} => (*launch, attach_commands
|
|
1390
|
+
} => (*launch, attach_commands),
|
|
1392
1391
|
other => panic!("quick_start must reach Ready; got {other:?}"),
|
|
1393
1392
|
};
|
|
1394
1393
|
// 0.3.28 Step 4b: adaptive 3-pane tiling replaced with 1-window-per-agent
|
|
@@ -1424,7 +1423,6 @@ fn quick_start_default_adaptive_groups_workers_into_layout_panes() {
|
|
|
1424
1423
|
attach_commands.iter().any(|cmd| cmd.contains(":w1")),
|
|
1425
1424
|
"attach commands must include the per-agent windows: {attach_commands:?}"
|
|
1426
1425
|
);
|
|
1427
|
-
let _ = display_backend; // display_backend value preserved by upstream
|
|
1428
1426
|
}
|
|
1429
1427
|
|
|
1430
1428
|
#[test]
|
|
@@ -1602,50 +1600,6 @@ fn attach_window_names_for_state_agents_include_managed_leader_and_layout_window
|
|
|
1602
1600
|
assert_eq!(windows, vec!["leader", "team-w1", "team-w2"]);
|
|
1603
1601
|
}
|
|
1604
1602
|
|
|
1605
|
-
#[test]
|
|
1606
|
-
#[serial(env)]
|
|
1607
|
-
fn quick_start_no_display_keeps_one_window_per_agent() {
|
|
1608
|
-
let _hermetic = enter_hermetic("launch-spawn-no-display");
|
|
1609
|
-
let roles = ["w1", "w2"]
|
|
1610
|
-
.into_iter()
|
|
1611
|
-
.map(|id| (format!("{id}.md"), role_doc(id)))
|
|
1612
|
-
.collect::<Vec<_>>();
|
|
1613
|
-
let role_refs = roles
|
|
1614
|
-
.iter()
|
|
1615
|
-
.map(|(file, doc)| (file.as_str(), doc.as_str()))
|
|
1616
|
-
.collect::<Vec<_>>();
|
|
1617
|
-
let team = quick_start_team_dir_with_roles(&role_refs);
|
|
1618
|
-
let workspace = team.parent().expect("team_workspace(team_dir) = parent");
|
|
1619
|
-
seed_healthy_coordinator(workspace);
|
|
1620
|
-
let transport = OfflineTransport::new();
|
|
1621
|
-
|
|
1622
|
-
let report = quick_start_with_transport_in_workspace_with_display(
|
|
1623
|
-
workspace, &team, None, true, None, &transport, false,
|
|
1624
|
-
)
|
|
1625
|
-
.expect("quick_start_with_transport must reach Ready");
|
|
1626
|
-
|
|
1627
|
-
let display_backend = match report {
|
|
1628
|
-
QuickStartReport::Ready {
|
|
1629
|
-
display_backend, ..
|
|
1630
|
-
} => display_backend,
|
|
1631
|
-
other => panic!("quick_start must reach Ready; got {other:?}"),
|
|
1632
|
-
};
|
|
1633
|
-
assert_eq!(display_backend, "none");
|
|
1634
|
-
assert_eq!(
|
|
1635
|
-
transport
|
|
1636
|
-
.spawn_records()
|
|
1637
|
-
.iter()
|
|
1638
|
-
.map(|(kind, _)| kind.as_str())
|
|
1639
|
-
.collect::<Vec<_>>(),
|
|
1640
|
-
vec!["spawn_first", "spawn_into"],
|
|
1641
|
-
"--no-display must use the legacy one-worker-window spawn path"
|
|
1642
|
-
);
|
|
1643
|
-
let (_raw, state) = raw_runtime_state(workspace);
|
|
1644
|
-
assert_eq!(state["display_backend"], json!("none"));
|
|
1645
|
-
assert_eq!(state.pointer("/agents/w1/window"), Some(&json!("w1")));
|
|
1646
|
-
assert_eq!(state.pointer("/agents/w1/layout_window"), None);
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
1603
|
// REAL-MACHINE residency boundary (acceptance framework): the PUBLIC quick_start (real TmuxBackend +
|
|
1650
1604
|
// real start_coordinator) on a fresh ws must leave a LIVE tmux session AND a ps-verifiable resident
|
|
1651
1605
|
// coordinator daemon (start_coordinator -> live pid). The framework verifies residency via ps; here we
|
|
@@ -2778,6 +2732,7 @@ fn fork_refuses_source_with_partial_tuple() {
|
|
|
2778
2732
|
}
|
|
2779
2733
|
|
|
2780
2734
|
#[test]
|
|
2735
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
2781
2736
|
fn add_agent_adaptive_splits_last_non_full_layout_window() {
|
|
2782
2737
|
let roles = [("w1.md", role_doc("w1")), ("w2.md", role_doc("w2"))];
|
|
2783
2738
|
let role_refs = roles
|
|
@@ -2790,7 +2745,7 @@ fn add_agent_adaptive_splits_last_non_full_layout_window() {
|
|
|
2790
2745
|
&team,
|
|
2791
2746
|
&json!({
|
|
2792
2747
|
"session_name": session,
|
|
2793
|
-
"
|
|
2748
|
+
"legacy_display_key": "adaptive",
|
|
2794
2749
|
"active_team_key": "teamdir",
|
|
2795
2750
|
"agents": {
|
|
2796
2751
|
"w1": {"status": "running", "provider": "codex", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 0, "pane_id": "%1"},
|
|
@@ -2835,6 +2790,7 @@ fn add_agent_adaptive_splits_last_non_full_layout_window() {
|
|
|
2835
2790
|
}
|
|
2836
2791
|
|
|
2837
2792
|
#[test]
|
|
2793
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
2838
2794
|
fn add_agent_adaptive_creates_suffix_window_when_last_layout_full_and_name_collides() {
|
|
2839
2795
|
let roles = [
|
|
2840
2796
|
("w1.md", role_doc("w1")),
|
|
@@ -2851,7 +2807,7 @@ fn add_agent_adaptive_creates_suffix_window_when_last_layout_full_and_name_colli
|
|
|
2851
2807
|
&team,
|
|
2852
2808
|
&json!({
|
|
2853
2809
|
"session_name": session,
|
|
2854
|
-
"
|
|
2810
|
+
"legacy_display_key": "adaptive",
|
|
2855
2811
|
"active_team_key": "teamdir",
|
|
2856
2812
|
"agents": {
|
|
2857
2813
|
"w1": {"status": "running", "provider": "codex", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 0, "pane_id": "%1"},
|
|
@@ -2918,7 +2874,7 @@ fn stop_agent_adaptive_kills_target_pane_not_shared_layout_window() {
|
|
|
2918
2874
|
&team,
|
|
2919
2875
|
&json!({
|
|
2920
2876
|
"session_name": session,
|
|
2921
|
-
"
|
|
2877
|
+
"legacy_display_key": "adaptive",
|
|
2922
2878
|
"agents": {
|
|
2923
2879
|
"w1": {"status": "running", "provider": "codex", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 0, "pane_id": "%1"},
|
|
2924
2880
|
"w2": {"status": "running", "provider": "codex", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 1, "pane_id": "%2"}
|
|
@@ -2954,13 +2910,14 @@ fn stop_agent_adaptive_kills_target_pane_not_shared_layout_window() {
|
|
|
2954
2910
|
}
|
|
2955
2911
|
|
|
2956
2912
|
#[test]
|
|
2913
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
2957
2914
|
fn start_agent_adaptive_restarts_missing_pane_in_existing_layout_window() {
|
|
2958
2915
|
let ws = temp_ws();
|
|
2959
2916
|
crate::state::persist::save_runtime_state(
|
|
2960
2917
|
&ws,
|
|
2961
2918
|
&json!({
|
|
2962
2919
|
"session_name": "team-layout-restart",
|
|
2963
|
-
"
|
|
2920
|
+
"legacy_display_key": "adaptive",
|
|
2964
2921
|
"agents": {
|
|
2965
2922
|
"w1": {"status": "running", "provider": "codex", "role": "w1", "model": "gpt-5.5", "auth_mode": "subscription", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 0, "pane_id": "%1"},
|
|
2966
2923
|
"w2": {"status": "running", "provider": "codex", "role": "w2", "model": "gpt-5.5", "auth_mode": "subscription", "window": "team-w1", "layout_window": "team-w1", "layout_index": 0, "pane_index": 1, "pane_id": "%2"}
|
|
@@ -3050,9 +3007,9 @@ fn quick_start_seeds_tasks_key_from_compiled_spec() {
|
|
|
3050
3007
|
}
|
|
3051
3008
|
|
|
3052
3009
|
// Stage A — golden launch/core.py:62-71 seeded top-level runtime state in insertion order:
|
|
3053
|
-
// spec_path, workspace, team_dir, team_key, session_name, leader, agents, tasks
|
|
3010
|
+
// spec_path, workspace, team_dir, team_key, session_name, leader, agents, tasks.
|
|
3054
3011
|
//
|
|
3055
|
-
//
|
|
3012
|
+
// The runtime state is tmux-only; no display backend is persisted.
|
|
3056
3013
|
// NEW (Bug 1/2 — team-in-team state scope, see tests/team_in_team_state_scope_red.rs):
|
|
3057
3014
|
// `active_team_key` and `teams` are appended at the tail so the runtime can carry the
|
|
3058
3015
|
// nested team-in-team scope alongside the original flat fields. Owner-binding fields
|
|
@@ -3065,11 +3022,10 @@ fn quick_start_seeds_tasks_key_from_compiled_spec() {
|
|
|
3065
3022
|
// R1: topology is explicit; fresh managed teams carry `is_external_leader=false`
|
|
3066
3023
|
// before the team-in-team suffix. Canonical `team_key` is seeded before owner
|
|
3067
3024
|
// binding; the remaining order stays the golden prefix + topology marker + new
|
|
3068
|
-
// suffix (active_team_key, teams).
|
|
3069
|
-
// (default adaptive), not the raw optional spec field.
|
|
3025
|
+
// suffix (active_team_key, teams).
|
|
3070
3026
|
#[test]
|
|
3071
3027
|
#[serial(env)]
|
|
3072
|
-
fn
|
|
3028
|
+
fn quick_start_state_seeds_spec_path_workspace_leader() {
|
|
3073
3029
|
let _hermetic = enter_hermetic("launch-spawn-state-seeds");
|
|
3074
3030
|
// Bug 2 owner team-scope: top-level owner triple is dropped when the seeded
|
|
3075
3031
|
// pane is empty; an ambient TMUX_PANE (tests run inside the dev's tmux session)
|
|
@@ -3106,7 +3062,6 @@ fn quick_start_state_seeds_spec_path_workspace_leader_display_backend() {
|
|
|
3106
3062
|
"leader",
|
|
3107
3063
|
"agents",
|
|
3108
3064
|
"tasks",
|
|
3109
|
-
"display_backend",
|
|
3110
3065
|
"is_external_leader",
|
|
3111
3066
|
// 0.5.x Phase 1d hot-path 接线 (裁决1 msg_76e1d98202b8):
|
|
3112
3067
|
// `transport = { kind, source }` inserted here by
|
|
@@ -3155,11 +3110,6 @@ fn quick_start_state_seeds_spec_path_workspace_leader_display_backend() {
|
|
|
3155
3110
|
"existing tasks value must remain seeded from compiled spec; got {:?}",
|
|
3156
3111
|
state["tasks"]
|
|
3157
3112
|
);
|
|
3158
|
-
assert_eq!(
|
|
3159
|
-
state["display_backend"],
|
|
3160
|
-
json!("adaptive"),
|
|
3161
|
-
"adaptive layout directive: resolve_display_backend(None, source='launch') defaults to adaptive"
|
|
3162
|
-
);
|
|
3163
3113
|
assert_eq!(state["is_external_leader"], json!(false));
|
|
3164
3114
|
}
|
|
3165
3115
|
|
|
@@ -3602,7 +3552,7 @@ fn add_agent_reachability_gate_passes_when_spawn_pane_addressable() {
|
|
|
3602
3552
|
// ═════════════════════════════════════════════════════════════════════════════
|
|
3603
3553
|
// E43 add-agent window layout drift (0.3.24 bug#3, demo-director startup blocker).
|
|
3604
3554
|
//
|
|
3605
|
-
// Root cause (architect res_f27ff9b29957): with `
|
|
3555
|
+
// Root cause (architect res_f27ff9b29957): with `legacy_display_key=adaptive` in
|
|
3606
3556
|
// state AND stale `agents.<id>.layout_window="team-w2"` residue, the existing
|
|
3607
3557
|
// `adaptive_placement_for_agent` validates a layout_window claim by checking
|
|
3608
3558
|
// whether the existing agent's `pane_id` is in `live_panes` — but it does NOT
|
|
@@ -3641,7 +3591,7 @@ fn e43_adaptive_placement_skips_existing_agent_whose_live_pane_window_name_diffe
|
|
|
3641
3591
|
use crate::transport::{SessionName, WindowName};
|
|
3642
3592
|
|
|
3643
3593
|
let state = json!({
|
|
3644
|
-
"
|
|
3594
|
+
"legacy_display_key": "adaptive",
|
|
3645
3595
|
"session_name": "team-iso",
|
|
3646
3596
|
"agents": {
|
|
3647
3597
|
"architect": {
|
|
@@ -3698,13 +3648,14 @@ fn e43_adaptive_placement_skips_existing_agent_whose_live_pane_window_name_diffe
|
|
|
3698
3648
|
/// behaviour (groups the new agent into that window). This is the canonical
|
|
3699
3649
|
/// adaptive 1-window-multiple-panes use case.
|
|
3700
3650
|
#[test]
|
|
3651
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
3701
3652
|
fn e43_adaptive_placement_groups_into_layout_window_when_live_pane_matches_claim() {
|
|
3702
3653
|
use crate::lifecycle::launch::adaptive_placement_for_agent;
|
|
3703
3654
|
use crate::model::ids::AgentId;
|
|
3704
3655
|
use crate::transport::{SessionName, WindowName};
|
|
3705
3656
|
|
|
3706
3657
|
let state = json!({
|
|
3707
|
-
"
|
|
3658
|
+
"legacy_display_key": "adaptive",
|
|
3708
3659
|
"session_name": "team-iso",
|
|
3709
3660
|
"agents": {
|
|
3710
3661
|
"alpha": {
|
|
@@ -3750,13 +3701,14 @@ fn e43_adaptive_placement_groups_into_layout_window_when_live_pane_matches_claim
|
|
|
3750
3701
|
/// agent_id itself — so the subsequent spawn opens a new window, not a split
|
|
3751
3702
|
/// of a phantom.
|
|
3752
3703
|
#[test]
|
|
3704
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
3753
3705
|
fn e43_adaptive_existing_placement_falls_back_to_agent_id_window_when_claim_missing_from_live() {
|
|
3754
3706
|
use crate::lifecycle::launch::adaptive_existing_placement_for_agent;
|
|
3755
3707
|
use crate::model::ids::AgentId;
|
|
3756
3708
|
use crate::transport::{SessionName, WindowName};
|
|
3757
3709
|
|
|
3758
3710
|
let state = json!({
|
|
3759
|
-
"
|
|
3711
|
+
"legacy_display_key": "adaptive",
|
|
3760
3712
|
"session_name": "team-iso",
|
|
3761
3713
|
"agents": {
|
|
3762
3714
|
"demo-director": {
|
|
@@ -3814,13 +3766,14 @@ fn e43_adaptive_existing_placement_falls_back_to_agent_id_window_when_claim_miss
|
|
|
3814
3766
|
/// (return a starts_window=false placement that splits into the existing
|
|
3815
3767
|
/// window).
|
|
3816
3768
|
#[test]
|
|
3769
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
3817
3770
|
fn e43_adaptive_existing_placement_keeps_starts_window_false_when_claim_in_live_windows() {
|
|
3818
3771
|
use crate::lifecycle::launch::adaptive_existing_placement_for_agent;
|
|
3819
3772
|
use crate::model::ids::AgentId;
|
|
3820
3773
|
use crate::transport::{SessionName, WindowName};
|
|
3821
3774
|
|
|
3822
3775
|
let state = json!({
|
|
3823
|
-
"
|
|
3776
|
+
"legacy_display_key": "adaptive",
|
|
3824
3777
|
"session_name": "team-iso",
|
|
3825
3778
|
"agents": {
|
|
3826
3779
|
"alpha": {
|
|
@@ -3861,7 +3814,7 @@ fn e43_adaptive_existing_placement_keeps_starts_window_false_when_claim_in_live_
|
|
|
3861
3814
|
|
|
3862
3815
|
/// **RED — Fix C end-to-end**: `add_agent` end-to-end must NOT emit a
|
|
3863
3816
|
/// spawn_split with the stale window name. With state carrying
|
|
3864
|
-
/// `
|
|
3817
|
+
/// `legacy_display_key=adaptive` + stale `layout_window=team-w2` residue and
|
|
3865
3818
|
/// live tmux windows named per-agent, the spawn must be a `spawn_into`
|
|
3866
3819
|
/// (new window) — NOT `spawn_split` against the missing 'team-w2'.
|
|
3867
3820
|
#[test]
|
|
@@ -3885,7 +3838,7 @@ fn e43_add_agent_does_not_split_against_phantom_layout_window() {
|
|
|
3885
3838
|
&team,
|
|
3886
3839
|
&json!({
|
|
3887
3840
|
"session_name": "team-iso",
|
|
3888
|
-
"
|
|
3841
|
+
"legacy_display_key": "adaptive",
|
|
3889
3842
|
"agents": {
|
|
3890
3843
|
"architect": {
|
|
3891
3844
|
"status": "running",
|
|
@@ -3939,7 +3892,7 @@ fn e43_add_agent_does_not_split_against_phantom_layout_window() {
|
|
|
3939
3892
|
// E45 per-agent window drift (0.3.24 task#326 P0).
|
|
3940
3893
|
//
|
|
3941
3894
|
// Surfaced AFTER E43 (c5ed576) fixed the team-w2 phantom split. New repro:
|
|
3942
|
-
// state has
|
|
3895
|
+
// state has legacy_display_key=adaptive + an existing `developer` worker whose
|
|
3943
3896
|
// state row carries `layout_window=developer, layout_index=0, pane_id=%519`,
|
|
3944
3897
|
// live tmux shows `developer` window with that pane. add-agent demo-director
|
|
3945
3898
|
// resolves placement via `adaptive_placement_for_agent`, which finds the
|
|
@@ -3971,7 +3924,7 @@ fn e45_adaptive_placement_returns_none_when_no_real_team_w_window_present_in_sta
|
|
|
3971
3924
|
// literally `developer` (per-agent name, NOT team-wN), pane_id %519
|
|
3972
3925
|
// lives under the `developer` window.
|
|
3973
3926
|
let state = json!({
|
|
3974
|
-
"
|
|
3927
|
+
"legacy_display_key": "adaptive",
|
|
3975
3928
|
"session_name": "team-iso",
|
|
3976
3929
|
"agents": {
|
|
3977
3930
|
"developer": {
|
|
@@ -4014,7 +3967,7 @@ fn e45_adaptive_placement_returns_none_when_no_real_team_w_window_present_in_sta
|
|
|
4014
3967
|
"E45 (0.3.24 bug#4): placement must return None when the live \
|
|
4015
3968
|
session has NO real `team-w<N>` adaptive window. Per-agent windows \
|
|
4016
3969
|
like `developer` are NOT adaptive layout windows — they are \
|
|
4017
|
-
per-agent topology, even if
|
|
3970
|
+
per-agent topology, even if legacy_display_key=adaptive lingers in \
|
|
4018
3971
|
state. With no real adaptive layout, the caller falls back to \
|
|
4019
3972
|
opening a new per-agent window named after agent_id. Got \
|
|
4020
3973
|
{placement:?} — must be None to prevent split-window -t :developer \
|
|
@@ -4033,7 +3986,7 @@ fn e45_adaptive_existing_placement_returns_none_when_claim_is_per_agent_window()
|
|
|
4033
3986
|
use crate::transport::{SessionName, WindowName};
|
|
4034
3987
|
|
|
4035
3988
|
let state = json!({
|
|
4036
|
-
"
|
|
3989
|
+
"legacy_display_key": "adaptive",
|
|
4037
3990
|
"session_name": "team-iso",
|
|
4038
3991
|
"agents": {
|
|
4039
3992
|
"developer": {
|
|
@@ -4087,14 +4040,14 @@ fn e45_add_agent_opens_new_window_does_not_split_into_per_agent_window() {
|
|
|
4087
4040
|
let role_file = team.join("worker2-role.md");
|
|
4088
4041
|
std::fs::write(&role_file, DELEG_ROLE_WORKER2).unwrap();
|
|
4089
4042
|
|
|
4090
|
-
// Real-machine state:
|
|
4043
|
+
// Real-machine state: legacy_display_key=adaptive, but the existing
|
|
4091
4044
|
// `developer` worker carries per-agent layout_window=developer with
|
|
4092
4045
|
// layout_index=0. macmini-equivalent state shape.
|
|
4093
4046
|
crate::state::persist::save_runtime_state(
|
|
4094
4047
|
&team,
|
|
4095
4048
|
&json!({
|
|
4096
4049
|
"session_name": "team-iso",
|
|
4097
|
-
"
|
|
4050
|
+
"legacy_display_key": "adaptive",
|
|
4098
4051
|
"agents": {
|
|
4099
4052
|
"developer": {
|
|
4100
4053
|
"status": "running",
|
|
@@ -4159,13 +4112,14 @@ fn e45_add_agent_opens_new_window_does_not_split_into_per_agent_window() {
|
|
|
4159
4112
|
/// existing E43+adaptive grouping behaviour is preserved (split into team-w1
|
|
4160
4113
|
/// as before). E45 only changes behaviour for per-agent windows.
|
|
4161
4114
|
#[test]
|
|
4115
|
+
#[ignore = "legacy adaptive display layout contract removed; runtime is silent tmux only"]
|
|
4162
4116
|
fn e45_real_team_w_adaptive_layout_still_groups_into_layout_window() {
|
|
4163
4117
|
use crate::lifecycle::launch::adaptive_placement_for_agent;
|
|
4164
4118
|
use crate::model::ids::AgentId;
|
|
4165
4119
|
use crate::transport::{SessionName, WindowName};
|
|
4166
4120
|
|
|
4167
4121
|
let state = json!({
|
|
4168
|
-
"
|
|
4122
|
+
"legacy_display_key": "adaptive",
|
|
4169
4123
|
"session_name": "team-iso",
|
|
4170
4124
|
"agents": {
|
|
4171
4125
|
"alpha": {
|
|
@@ -350,10 +350,10 @@ fn reset_agent_discard_session_syncs_projection_epoch_inputs_for_restart_agent_c
|
|
|
350
350
|
};
|
|
351
351
|
let outcome =
|
|
352
352
|
reset_agent_with_transport(&ws, &AgentId::new("alpha"), true, false, None, &transport)
|
|
353
|
-
.expect("reset-agent alpha --discard-session
|
|
353
|
+
.expect("reset-agent alpha --discard-session");
|
|
354
354
|
assert!(
|
|
355
355
|
matches!(outcome, ResetAgentOutcome::Reset { .. }),
|
|
356
|
-
"restart-agent alpha --discard-session
|
|
356
|
+
"restart-agent alpha --discard-session must complete reset; got {outcome:?}"
|
|
357
357
|
);
|
|
358
358
|
|
|
359
359
|
let state = crate::state::persist::load_runtime_state(&ws).expect("reload state");
|
|
@@ -47,14 +47,13 @@ fn concurrent_reset_discard_session_serializes() {
|
|
|
47
47
|
seed_healthy_coordinator(&workspace);
|
|
48
48
|
|
|
49
49
|
let launch_transport = codex_ready_transport();
|
|
50
|
-
let quick_start =
|
|
50
|
+
let quick_start = quick_start_with_transport_in_workspace(
|
|
51
51
|
&workspace,
|
|
52
52
|
&team,
|
|
53
53
|
None,
|
|
54
54
|
true,
|
|
55
55
|
None,
|
|
56
56
|
&launch_transport,
|
|
57
|
-
false,
|
|
58
57
|
)
|
|
59
58
|
.expect("quick-start fixture");
|
|
60
59
|
assert!(
|
|
@@ -484,14 +483,13 @@ fn breal_workspace() -> (PathBuf, PathBuf) {
|
|
|
484
483
|
let workspace = team.parent().expect("team workspace").to_path_buf();
|
|
485
484
|
seed_healthy_coordinator(&workspace);
|
|
486
485
|
let launch_transport = codex_ready_transport();
|
|
487
|
-
|
|
486
|
+
quick_start_with_transport_in_workspace(
|
|
488
487
|
&workspace,
|
|
489
488
|
&team,
|
|
490
489
|
None,
|
|
491
490
|
true,
|
|
492
491
|
None,
|
|
493
492
|
&launch_transport,
|
|
494
|
-
false,
|
|
495
493
|
)
|
|
496
494
|
.expect("quick-start breal fixture");
|
|
497
495
|
(workspace, team)
|
|
@@ -503,14 +501,13 @@ fn breal_one_worker_workspace() -> (PathBuf, PathBuf) {
|
|
|
503
501
|
let workspace = team.parent().expect("team workspace").to_path_buf();
|
|
504
502
|
seed_healthy_coordinator(&workspace);
|
|
505
503
|
let launch_transport = codex_ready_transport();
|
|
506
|
-
|
|
504
|
+
quick_start_with_transport_in_workspace(
|
|
507
505
|
&workspace,
|
|
508
506
|
&team,
|
|
509
507
|
None,
|
|
510
508
|
true,
|
|
511
509
|
None,
|
|
512
510
|
&launch_transport,
|
|
513
|
-
false,
|
|
514
511
|
)
|
|
515
512
|
.expect("quick-start breal one-worker fixture");
|
|
516
513
|
(workspace, team)
|
|
@@ -550,14 +547,13 @@ fn add_fixture() -> (PathBuf, PathBuf, PathBuf, OfflineTransport) {
|
|
|
550
547
|
let workspace = team.parent().expect("team workspace").to_path_buf();
|
|
551
548
|
seed_healthy_coordinator(&workspace);
|
|
552
549
|
let launch_transport = codex_ready_transport();
|
|
553
|
-
|
|
550
|
+
quick_start_with_transport_in_workspace(
|
|
554
551
|
&workspace,
|
|
555
552
|
&team,
|
|
556
553
|
Some("teamdir"),
|
|
557
554
|
true,
|
|
558
555
|
None,
|
|
559
556
|
&launch_transport,
|
|
560
|
-
false,
|
|
561
557
|
)
|
|
562
558
|
.expect("quick-start add fixture");
|
|
563
559
|
let role = workspace.join("w2-role.md");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use super::launch_spawn::seed_healthy_coordinator;
|
|
2
2
|
use super::*;
|
|
3
3
|
use crate::cli::{
|
|
4
|
-
|
|
4
|
+
cmd_doctor, cmd_send, cmd_status, lifecycle_port, CmdOutput, CmdResult, DoctorArgs,
|
|
5
5
|
SendArgs, StatusArgs,
|
|
6
6
|
};
|
|
7
7
|
use crate::transport::test_support::OfflineTransport;
|
|
@@ -97,6 +97,7 @@ fn hermetic_caller_envs() -> &'static [&'static str] {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
#[test]
|
|
100
|
+
#[ignore = "legacy display-backed phase golden fixture superseded by silent tmux runtime"]
|
|
100
101
|
#[serial_test::serial(env)]
|
|
101
102
|
fn phase_b_golden_events_state_status_zero_drift() {
|
|
102
103
|
let baseline = phase_fixture_path("phase_b").join("golden.json");
|
|
@@ -113,6 +114,7 @@ fn phase_b_golden_events_state_status_zero_drift() {
|
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
#[test]
|
|
117
|
+
#[ignore = "legacy display-backed phase golden fixture superseded by silent tmux runtime"]
|
|
116
118
|
#[serial_test::serial(env)]
|
|
117
119
|
fn phase_c_golden_events_state_status_zero_drift() {
|
|
118
120
|
let baseline = phase_fixture_path("phase_c").join("golden.json");
|
|
@@ -129,6 +131,7 @@ fn phase_c_golden_events_state_status_zero_drift() {
|
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
#[test]
|
|
134
|
+
#[ignore = "legacy display-backed phase golden fixture superseded by silent tmux runtime"]
|
|
132
135
|
#[serial_test::serial(env)]
|
|
133
136
|
fn phase_d_golden_events_state_status_zero_drift() {
|
|
134
137
|
let baseline = phase_fixture_path("phase_d").join("golden.json");
|
|
@@ -145,6 +148,7 @@ fn phase_d_golden_events_state_status_zero_drift() {
|
|
|
145
148
|
}
|
|
146
149
|
|
|
147
150
|
#[test]
|
|
151
|
+
#[ignore = "legacy display-backed phase golden fixture superseded by silent tmux runtime"]
|
|
148
152
|
#[serial_test::serial(env)]
|
|
149
153
|
fn phase_e_golden_events_state_status_zero_drift() {
|
|
150
154
|
let baseline = phase_fixture_path("phase_e").join("golden.json");
|
|
@@ -161,6 +165,7 @@ fn phase_e_golden_events_state_status_zero_drift() {
|
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
#[test]
|
|
168
|
+
#[ignore = "legacy display-backed phase golden fixture superseded by silent tmux runtime"]
|
|
164
169
|
#[serial_test::serial(env)]
|
|
165
170
|
fn phase_f_golden_events_state_status_zero_drift() {
|
|
166
171
|
let baseline = phase_fixture_path("phase_f").join("golden.json");
|
|
@@ -244,14 +249,13 @@ fn run_phase_golden(spec: PhaseGolden) -> Value {
|
|
|
244
249
|
leader_env: BTreeMap::new(),
|
|
245
250
|
}])
|
|
246
251
|
.with_pane_current_command("%caller", "codex");
|
|
247
|
-
let quick_start =
|
|
252
|
+
let quick_start = quick_start_with_transport_in_workspace(
|
|
248
253
|
&workspace,
|
|
249
254
|
&team,
|
|
250
255
|
None,
|
|
251
256
|
true,
|
|
252
257
|
None,
|
|
253
258
|
&launch_transport,
|
|
254
|
-
false,
|
|
255
259
|
);
|
|
256
260
|
let status_compact = cmd_status(&StatusArgs {
|
|
257
261
|
agent: None,
|
|
@@ -446,7 +450,6 @@ fn quick_start_value(result: Result<QuickStartReport, LifecycleError>) -> Value
|
|
|
446
450
|
Ok(QuickStartReport::Ready {
|
|
447
451
|
session_name,
|
|
448
452
|
launch,
|
|
449
|
-
display_backend,
|
|
450
453
|
worker_readiness,
|
|
451
454
|
..
|
|
452
455
|
}) => {
|
|
@@ -460,7 +463,6 @@ fn quick_start_value(result: Result<QuickStartReport, LifecycleError>) -> Value
|
|
|
460
463
|
"start_mode": format!("{:?}", started.start_mode),
|
|
461
464
|
"session_id": started.session_id.as_ref().map(|id| id.as_str().to_string()),
|
|
462
465
|
"rollout_path": started.rollout_path.as_ref().map(|path| path.as_path().to_string_lossy().to_string()),
|
|
463
|
-
"layout_window": started.layout_window.as_ref().map(|window| window.as_str().to_string()),
|
|
464
466
|
})
|
|
465
467
|
})
|
|
466
468
|
.collect::<Vec<_>>();
|
|
@@ -468,7 +470,6 @@ fn quick_start_value(result: Result<QuickStartReport, LifecycleError>) -> Value
|
|
|
468
470
|
"ok": true,
|
|
469
471
|
"status": "ready",
|
|
470
472
|
"session_name": session_name.as_str(),
|
|
471
|
-
"display_backend": display_backend,
|
|
472
473
|
"worker_readiness": format!("{worker_readiness:?}"),
|
|
473
474
|
"started": agents,
|
|
474
475
|
})
|
|
@@ -542,14 +543,13 @@ fn run_diagnose_after_quick_start() -> Value {
|
|
|
542
543
|
let workspace = team.parent().expect("workspace").to_path_buf();
|
|
543
544
|
seed_healthy_coordinator(&workspace);
|
|
544
545
|
let launch_transport = codex_ready_transport();
|
|
545
|
-
|
|
546
|
+
quick_start_with_transport_in_workspace(
|
|
546
547
|
&workspace,
|
|
547
548
|
&team,
|
|
548
549
|
None,
|
|
549
550
|
true,
|
|
550
551
|
None,
|
|
551
552
|
&launch_transport,
|
|
552
|
-
false,
|
|
553
553
|
)
|
|
554
554
|
.expect("tombstone fixture must quick-start");
|
|
555
555
|
let mut state = crate::state::persist::load_runtime_state(&workspace)
|
|
@@ -582,10 +582,17 @@ fn run_diagnose_after_quick_start() -> Value {
|
|
|
582
582
|
.is_some(),
|
|
583
583
|
"index-missing diagnose requires a persisted seeded owner"
|
|
584
584
|
);
|
|
585
|
-
let diagnose =
|
|
585
|
+
let diagnose = cmd_doctor(&DoctorArgs {
|
|
586
586
|
workspace,
|
|
587
587
|
json: true,
|
|
588
588
|
team: Some("teamdir".to_string()),
|
|
589
|
+
spec: None,
|
|
590
|
+
gate: None,
|
|
591
|
+
comms: false,
|
|
592
|
+
fix: false,
|
|
593
|
+
fix_schema: false,
|
|
594
|
+
cleanup_orphans: false,
|
|
595
|
+
confirm: false,
|
|
589
596
|
});
|
|
590
597
|
match cmd_value(diagnose) {
|
|
591
598
|
Value::Object(map) => map
|
|
@@ -720,7 +720,7 @@ fn pi_materializer_and_worker_routes_body(hermetic: &HermeticTestEnv) {
|
|
|
720
720
|
std::fs::create_dir_all(spec_path.parent().expect("worker Pi spec parent"))
|
|
721
721
|
.expect("create worker Pi spec parent");
|
|
722
722
|
let spec = crate::model::yaml::loads(
|
|
723
|
-
"team:\n name: team-a\nruntime:\n session_name: team-workers\
|
|
723
|
+
"team:\n name: team-a\nruntime:\n session_name: team-workers\nagents:\n - id: worker-a\n role: Worker A\n provider: pi\n model: team-agent/qwen3.8-27b\n auth_mode: subscription\n dangerously_skip_permissions: false\n tools:\n - mcp_team\n - id: worker-b\n role: Worker B\n provider: pi\n model: team-agent/qwen3.8-27b\n auth_mode: subscription\n dangerously_skip_permissions: false\n tools:\n - mcp_team\n",
|
|
724
724
|
)
|
|
725
725
|
.expect("parse worker Pi spec");
|
|
726
726
|
std::fs::write(&spec_path, crate::model::yaml::dumps(&spec)).expect("write worker Pi spec");
|
|
@@ -272,66 +272,6 @@ fn c1_runtime_commands_resolve_active_team_for_status_send_and_collect() {
|
|
|
272
272
|
);
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
#[test]
|
|
276
|
-
#[ignore = "real-machine: command-file gate uses real team-agent binary/lifecycle"]
|
|
277
|
-
fn c2_stop_team_level_command_exists_and_keeps_state_while_stopping_runtime() {
|
|
278
|
-
let ws = tmp_dir("c2-stop");
|
|
279
|
-
seed_runtime_state(&ws);
|
|
280
|
-
|
|
281
|
-
let out = run(
|
|
282
|
-
&["stop", "--workspace", ws.to_str().unwrap(), "--json"],
|
|
283
|
-
&ws,
|
|
284
|
-
);
|
|
285
|
-
let err = String::from_utf8_lossy(&out.stderr);
|
|
286
|
-
assert!(
|
|
287
|
-
!err.contains("invalid choice: 'stop'"),
|
|
288
|
-
"CR-005: canonical `team-agent stop --workspace <ws> --json` must be a registered team-level stop verb, not argparse invalid-choice; stderr={err:?}"
|
|
289
|
-
);
|
|
290
|
-
assert_eq!(
|
|
291
|
-
out.status.code(),
|
|
292
|
-
Some(0),
|
|
293
|
-
"CR-005: stop should stop the runtime while keeping state on a valid workspace; stdout={} stderr={}",
|
|
294
|
-
String::from_utf8_lossy(&out.stdout),
|
|
295
|
-
err
|
|
296
|
-
);
|
|
297
|
-
let value = stdout_json(&out);
|
|
298
|
-
assert_eq!(
|
|
299
|
-
value["ok"],
|
|
300
|
-
json!(true),
|
|
301
|
-
"stop must return a successful JSON envelope"
|
|
302
|
-
);
|
|
303
|
-
assert!(
|
|
304
|
-
team_agent::state::persist::runtime_state_path(&ws).exists(),
|
|
305
|
-
"stop keeps runtime state for later restart"
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
#[test]
|
|
310
|
-
#[ignore = "real-machine: command-file gate uses real team-agent binary/lifecycle"]
|
|
311
|
-
fn c2_canonical_verbs_expose_help_instead_of_invalid_choice() {
|
|
312
|
-
let cwd = tmp_dir("c2-help-verbs");
|
|
313
|
-
let mut failures = Vec::new();
|
|
314
|
-
for verb in ["start", "restart-agent", "purge-agent"] {
|
|
315
|
-
let out = run(&[verb, "--help"], &cwd);
|
|
316
|
-
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
317
|
-
let stderr = String::from_utf8_lossy(&out.stderr);
|
|
318
|
-
if out.status.code() != Some(0)
|
|
319
|
-
|| stderr.contains("invalid choice:")
|
|
320
|
-
|| !(stdout.contains("usage") || stderr.contains("usage"))
|
|
321
|
-
{
|
|
322
|
-
failures.push(format!(
|
|
323
|
-
"{verb}: code={:?} stdout={stdout:?} stderr={stderr:?}",
|
|
324
|
-
out.status.code()
|
|
325
|
-
));
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
assert!(
|
|
329
|
-
failures.is_empty(),
|
|
330
|
-
"CR-030/032/035/063: canonical lifecycle verbs must be registered and expose help, not invalid-choice:\n{}",
|
|
331
|
-
failures.join("\n")
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
275
|
#[test]
|
|
336
276
|
#[ignore = "real-machine: command-file gate uses real team-agent binary/lifecycle"]
|
|
337
277
|
fn c2_quick_start_help_is_zero_token_help_only_and_does_not_compile_workspace() {
|
|
@@ -44,8 +44,8 @@ use serial_test::serial;
|
|
|
44
44
|
use team_agent::coordinator::{MetadataSource, Pid, WorkspacePath};
|
|
45
45
|
use team_agent::event_log::EventLog;
|
|
46
46
|
use team_agent::lifecycle::{
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
quick_start_with_transport_in_workspace, restart_with_transport_with_readiness_deadline,
|
|
48
|
+
QuickStartReport, RestartReport,
|
|
49
49
|
};
|
|
50
50
|
use team_agent::message_store::MessageStore;
|
|
51
51
|
use team_agent::model::paths::{runtime_dir, runtime_spec_path};
|
|
@@ -364,14 +364,13 @@ fn restart_and_launch_emit_structured_latency_events_without_fake_ready() {
|
|
|
364
364
|
|
|
365
365
|
let launch_case = LaunchLatencyCase::new("events-launch", 2);
|
|
366
366
|
let launch_transport = StartupLatencyTransport::new();
|
|
367
|
-
let quick_start =
|
|
367
|
+
let quick_start = quick_start_with_transport_in_workspace(
|
|
368
368
|
&launch_case.workspace,
|
|
369
369
|
&launch_case.team_dir,
|
|
370
370
|
None,
|
|
371
371
|
true,
|
|
372
372
|
Some(TEAM),
|
|
373
373
|
&launch_transport,
|
|
374
|
-
false,
|
|
375
374
|
)
|
|
376
375
|
.expect("event setup: quick-start should complete");
|
|
377
376
|
assert!(
|
|
@@ -80,7 +80,7 @@ fn quick_start_workspace_override_is_not_dropped_before_runtime_state_write() {
|
|
|
80
80
|
let quick_start_args = source_section(
|
|
81
81
|
&cli_types,
|
|
82
82
|
"pub struct QuickStartArgs",
|
|
83
|
-
"pub struct
|
|
83
|
+
"pub struct SendArgs",
|
|
84
84
|
);
|
|
85
85
|
assert!(
|
|
86
86
|
quick_start_args.contains("pub workspace: PathBuf"),
|
|
@@ -97,7 +97,7 @@ fn quick_start_workspace_override_is_not_dropped_before_runtime_state_write() {
|
|
|
97
97
|
|
|
98
98
|
let emit =
|
|
99
99
|
std::fs::read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/src/cli/emit.rs")).unwrap();
|
|
100
|
-
let quick_start_args_fn = source_section(&emit, "fn quick_start_args", "fn
|
|
100
|
+
let quick_start_args_fn = source_section(&emit, "fn quick_start_args", "fn resolve_cli_path");
|
|
101
101
|
assert!(
|
|
102
102
|
quick_start_args_fn.contains("workspace: workspace.clone()")
|
|
103
103
|
|| quick_start_args_fn.contains("workspace,"),
|