@team-agent/installer 0.5.59 → 0.5.61

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.
Files changed (68) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +44 -1
  4. package/crates/team-agent/src/cli/diagnose.rs +183 -0
  5. package/crates/team-agent/src/cli/emit.rs +63 -14
  6. package/crates/team-agent/src/cli/leader.rs +8 -1
  7. package/crates/team-agent/src/cli/mod.rs +263 -5
  8. package/crates/team-agent/src/cli/named_address.rs +18 -1
  9. package/crates/team-agent/src/cli/send/presentation.rs +2 -0
  10. package/crates/team-agent/src/cli/spec.rs +4 -1
  11. package/crates/team-agent/src/cli/status_port/store.rs +7 -3
  12. package/crates/team-agent/src/cli/tests/named_address.rs +65 -0
  13. package/crates/team-agent/src/cli/types.rs +33 -0
  14. package/crates/team-agent/src/communication_mode/mod.rs +53 -0
  15. package/crates/team-agent/src/compiler/tests.rs +5 -5
  16. package/crates/team-agent/src/compiler.rs +53 -1
  17. package/crates/team-agent/src/coordinator/tick.rs +21 -8
  18. package/crates/team-agent/src/db/message_store.rs +45 -1
  19. package/crates/team-agent/src/fake_worker.rs +21 -1
  20. package/crates/team-agent/src/leader/start.rs +732 -94
  21. package/crates/team-agent/src/leader/tests/identity.rs +64 -57
  22. package/crates/team-agent/src/leader/tests/identity_session_names.rs +42 -0
  23. package/crates/team-agent/src/lib.rs +4 -0
  24. package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +58 -0
  25. package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +57 -51
  26. package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +148 -8
  27. package/crates/team-agent/src/lifecycle/launch/fork_state.rs +5 -0
  28. package/crates/team-agent/src/lifecycle/launch/spawn.rs +1 -1
  29. package/crates/team-agent/src/lifecycle/launch.rs +1 -1
  30. package/crates/team-agent/src/lifecycle/restart/agent.rs +1 -1
  31. package/crates/team-agent/src/lifecycle/restart/common.rs +1 -1
  32. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +35 -1
  33. package/crates/team-agent/src/lifecycle/types.rs +1 -0
  34. package/crates/team-agent/src/lifecycle/worker_command_context.rs +29 -11
  35. package/crates/team-agent/src/mcp_server/normalize.rs +1 -0
  36. package/crates/team-agent/src/mcp_server/tests/send.rs +26 -0
  37. package/crates/team-agent/src/mcp_server/tests/wire.rs +1 -1
  38. package/crates/team-agent/src/mcp_server/tools.rs +100 -66
  39. package/crates/team-agent/src/mcp_server/types.rs +5 -0
  40. package/crates/team-agent/src/mcp_server/wire.rs +27 -21
  41. package/crates/team-agent/src/messaging/delivery.rs +105 -38
  42. package/crates/team-agent/src/messaging/leader_channel.rs +33 -10
  43. package/crates/team-agent/src/messaging/leader_receiver.rs +40 -23
  44. package/crates/team-agent/src/messaging/presentation.rs +109 -0
  45. package/crates/team-agent/src/messaging/results.rs +165 -17
  46. package/crates/team-agent/src/messaging/send.rs +94 -81
  47. package/crates/team-agent/src/messaging/tests/leader_channel.rs +6 -6
  48. package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +187 -0
  49. package/crates/team-agent/src/messaging/tests/runtime.rs +13 -6
  50. package/crates/team-agent/src/messaging/types.rs +5 -0
  51. package/crates/team-agent/src/messaging/watchers.rs +5 -0
  52. package/crates/team-agent/src/model/mod.rs +1 -0
  53. package/crates/team-agent/src/model/pane_authority_refusal.rs +358 -0
  54. package/crates/team-agent/src/model/spec.rs +16 -0
  55. package/crates/team-agent/src/provider/adapter.rs +57 -0
  56. package/crates/team-agent/src/provider/adapters/claude_fork.rs +10 -2
  57. package/crates/team-agent/src/provider/session/capture.rs +69 -34
  58. package/crates/team-agent/src/provider/session/context_fork/codex.rs +386 -9
  59. package/crates/team-agent/src/provider/session/context_fork/outcome.rs +3 -14
  60. package/crates/team-agent/src/provider/session/context_fork.rs +7 -2
  61. package/crates/team-agent/src/provider/session/mod.rs +3 -2
  62. package/crates/team-agent/src/provider/session_scan/claude.rs +92 -3
  63. package/crates/team-agent/src/provider/session_scan/codex.rs +28 -0
  64. package/crates/team-agent/src/provider/session_scan/common.rs +34 -8
  65. package/crates/team-agent/src/provider/session_scan.rs +8 -0
  66. package/crates/team-agent/src/topology.rs +3 -0
  67. package/package.json +4 -4
  68. package/skills/team-agent/command-coverage.json +379 -0
@@ -4,12 +4,40 @@ pub(super) fn parse_spawned_at(raw: &str) -> Option<std::time::SystemTime> {
4
4
  .map(|dt| std::time::SystemTime::from(dt.with_timezone(&chrono::Utc)))
5
5
  }
6
6
 
7
+ pub(super) fn truncate_to_uuid_precision(
8
+ timestamp: std::time::SystemTime,
9
+ ) -> Option<std::time::SystemTime> {
10
+ let since_epoch = timestamp
11
+ .duration_since(std::time::SystemTime::UNIX_EPOCH)
12
+ .ok()?;
13
+ std::time::SystemTime::UNIX_EPOCH.checked_add(std::time::Duration::from_millis(
14
+ u64::try_from(since_epoch.as_millis()).ok()?,
15
+ ))
16
+ }
17
+
7
18
  pub(super) fn rollout_created_at(path: &std::path::Path) -> Option<std::time::SystemTime> {
8
19
  created_at_from_rollout_uuid(path)
9
20
  .or_else(|| created_at_from_rollout_head(path))
10
21
  .or_else(|| created_at_from_rollout_filename(path))
11
22
  }
12
23
 
24
+ pub(super) fn apply_expected_session_filter(
25
+ context: &super::CaptureSessionContext,
26
+ mut out: Vec<super::CapturedSessionCandidate>,
27
+ ) -> Vec<super::CapturedSessionCandidate> {
28
+ let Some(expected) = context.expected_session_id.as_ref() else {
29
+ return out;
30
+ };
31
+ out.retain(|candidate| {
32
+ candidate
33
+ .captured
34
+ .session_id
35
+ .as_ref()
36
+ .is_some_and(|session| session.as_str() == expected.as_str())
37
+ });
38
+ out
39
+ }
40
+
13
41
  pub(super) fn retain_spawn_cwd(
14
42
  context: &super::CaptureSessionContext,
15
43
  out: &mut Vec<super::CapturedSessionCandidate>,
@@ -26,25 +26,36 @@ pub(super) fn candidate_session_files(
26
26
  ) -> Result<Vec<SessionCandidate>, ProviderError> {
27
27
  let mut out = Vec::new();
28
28
  if let Some(root) = context.provider_projects_root.as_ref() {
29
- collect_optional_candidate_files(root, &context.agent_id, &mut out)?;
29
+ let allowed_team_root =
30
+ matches!(provider, Provider::Claude | Provider::ClaudeCode).then_some(root.as_path());
31
+ collect_optional_candidate_files(root, &context.agent_id, allowed_team_root, &mut out)?;
30
32
  }
31
- collect_candidate_files(&context.spawn_cwd, &context.agent_id, 0, false, &mut out)?;
33
+ collect_candidate_files(
34
+ &context.spawn_cwd,
35
+ &context.agent_id,
36
+ 0,
37
+ false,
38
+ None,
39
+ &mut out,
40
+ )?;
32
41
  if let Some(home) = std::env::var_os("HOME").map(PathBuf::from) {
33
42
  match provider {
34
43
  Provider::Codex => {
35
44
  collect_optional_candidate_files(
36
45
  &home.join(".codex").join("sessions"),
37
46
  &context.agent_id,
47
+ None,
38
48
  &mut out,
39
49
  )?;
40
50
  }
41
51
  Provider::Claude | Provider::ClaudeCode => {
42
52
  if let Some(dir) = super::claude::projects_dir_for_cwd(&home, &context.spawn_cwd) {
43
- collect_optional_candidate_files(&dir, &context.agent_id, &mut out)?;
53
+ collect_optional_candidate_files(&dir, &context.agent_id, None, &mut out)?;
44
54
  }
45
55
  collect_optional_candidate_files(
46
56
  &home.join(".claude").join("projects"),
47
57
  &context.agent_id,
58
+ None,
48
59
  &mut out,
49
60
  )?;
50
61
  }
@@ -146,13 +157,23 @@ pub(super) fn apply_spawned_at_filter(
146
157
  out.clear();
147
158
  return;
148
159
  };
160
+ let codex_spawned_at =
161
+ if matches!(provider, Provider::Codex) && context.expected_session_id.is_some() {
162
+ let Some(timestamp) = super::codex::truncate_to_uuid_precision(spawned_at) else {
163
+ out.clear();
164
+ return;
165
+ };
166
+ timestamp
167
+ } else {
168
+ spawned_at
169
+ };
149
170
  out.retain(|candidate| {
150
171
  let Some(path) = candidate.captured.rollout_path.as_ref() else {
151
172
  return false;
152
173
  };
153
174
  if matches!(provider, Provider::Codex) {
154
175
  return super::codex::rollout_created_at(path.as_path())
155
- .is_some_and(|created_at| created_at >= spawned_at);
176
+ .is_some_and(|created_at| created_at >= codex_spawned_at);
156
177
  }
157
178
  candidate_mtime(path.as_path()).is_some_and(|mtime| mtime >= spawned_at)
158
179
  });
@@ -265,10 +286,11 @@ fn complete_head_text(bytes: &[u8]) -> String {
265
286
  fn collect_optional_candidate_files(
266
287
  dir: &Path,
267
288
  agent_id: &str,
289
+ allowed_team_root: Option<&Path>,
268
290
  out: &mut Vec<SessionCandidate>,
269
291
  ) -> Result<(), ProviderError> {
270
292
  if dir.exists() {
271
- let _ = collect_candidate_files(dir, agent_id, 0, true, out);
293
+ let _ = collect_candidate_files(dir, agent_id, 0, true, allowed_team_root, out);
272
294
  }
273
295
  Ok(())
274
296
  }
@@ -278,6 +300,7 @@ fn collect_candidate_files(
278
300
  agent_id: &str,
279
301
  depth: usize,
280
302
  requires_cwd_match: bool,
303
+ allowed_team_root: Option<&Path>,
281
304
  out: &mut Vec<SessionCandidate>,
282
305
  ) -> Result<(), ProviderError> {
283
306
  if depth > 4 {
@@ -299,9 +322,10 @@ fn collect_candidate_files(
299
322
  agent_id,
300
323
  depth.saturating_add(1),
301
324
  requires_cwd_match,
325
+ allowed_team_root,
302
326
  out,
303
327
  )?;
304
- } else if looks_like_session_file(&path, agent_id) {
328
+ } else if looks_like_session_file(&path, agent_id, allowed_team_root) {
305
329
  out.push(SessionCandidate {
306
330
  path,
307
331
  requires_cwd_match,
@@ -311,8 +335,10 @@ fn collect_candidate_files(
311
335
  Ok(())
312
336
  }
313
337
 
314
- fn looks_like_session_file(path: &Path, agent_id: &str) -> bool {
315
- if path_is_under_team_runtime(path) {
338
+ fn looks_like_session_file(path: &Path, agent_id: &str, allowed_team_root: Option<&Path>) -> bool {
339
+ if path_is_under_team_runtime(path)
340
+ && !allowed_team_root.is_some_and(|root| path.starts_with(root))
341
+ {
316
342
  return false;
317
343
  }
318
344
  let Some(name) = path.file_name().and_then(|s| s.to_str()) else {
@@ -61,6 +61,11 @@ pub(crate) fn scan_session_candidates_once(
61
61
  if matches!(provider, Provider::Copilot) {
62
62
  return Ok(copilot::scan_session_store(context));
63
63
  }
64
+ if matches!(provider, Provider::Claude | Provider::ClaudeCode)
65
+ && context.expected_session_id.is_some()
66
+ {
67
+ return Ok(claude::scan_expected_session(context));
68
+ }
64
69
 
65
70
  let candidates = common::candidate_session_files(provider, context)?;
66
71
  let mut out = common::parse_candidate_files(provider, context, candidates);
@@ -72,6 +77,9 @@ pub(crate) fn scan_session_candidates_once(
72
77
  if matches!(provider, Provider::Claude | Provider::ClaudeCode) {
73
78
  return claude::apply_expected_session_filter(context, out);
74
79
  }
80
+ if matches!(provider, Provider::Codex) {
81
+ out = codex::apply_expected_session_filter(context, out);
82
+ }
75
83
 
76
84
  common::apply_spawn_time_window_if_unique(provider, context, &mut out);
77
85
  common::sort_expected_first_if_needed(context, &mut out);
@@ -399,6 +399,9 @@ fn append_worker_pane_binding_issues(
399
399
  let Some(agents) = state.get("agents").and_then(Value::as_object) else {
400
400
  return;
401
401
  };
402
+ if agents.is_empty() {
403
+ return;
404
+ }
402
405
  let Ok(live_targets) = backend.list_targets() else {
403
406
  return;
404
407
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.5.59",
3
+ "version": "0.5.61",
4
4
  "description": "npx installer for Team Agent",
5
5
  "keywords": [
6
6
  "codex",
@@ -20,9 +20,9 @@
20
20
  "team-agent-installer": "npm/install.mjs"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@team-agent/cli-darwin-arm64": "0.5.59",
24
- "@team-agent/cli-darwin-x64": "0.5.59",
25
- "@team-agent/cli-linux-x64": "0.5.59"
23
+ "@team-agent/cli-darwin-arm64": "0.5.61",
24
+ "@team-agent/cli-darwin-x64": "0.5.61",
25
+ "@team-agent/cli-linux-x64": "0.5.61"
26
26
  },
27
27
  "scripts": {
28
28
  "postinstall": "node npm/bincheck.mjs",
@@ -0,0 +1,379 @@
1
+ {
2
+ "schema_version": "team-agent-skill-command-coverage-v3",
3
+ "commands": [
4
+ {
5
+ "command": "team-agent add-agent <agent> --role-file <file>",
6
+ "bucket": "declared_gap",
7
+ "covered": false,
8
+ "owner": "runtime-owner:lifecycle",
9
+ "plan": "Execute the documented argv in an isolated add-agent fixture and bind assertions to the CLI result and created roster/window."
10
+ },
11
+ {
12
+ "command": "team-agent add-agent reviewer --role-file .team/current/agents/reviewer.md --workspace .",
13
+ "bucket": "declared_gap",
14
+ "covered": false,
15
+ "owner": "runtime-owner:lifecycle",
16
+ "plan": "Execute the exact reviewer argv in an isolated fixture and assert the reviewer state, role provenance, and worker window."
17
+ },
18
+ {
19
+ "command": "team-agent approvals",
20
+ "bucket": "declared_gap",
21
+ "covered": false,
22
+ "owner": "runtime-owner:approvals",
23
+ "plan": "Execute the default approvals view and bind assertions to its exit and approval-list output."
24
+ },
25
+ {
26
+ "command": "team-agent approvals <agent_id>",
27
+ "bucket": "declared_gap",
28
+ "covered": false,
29
+ "owner": "runtime-owner:approvals",
30
+ "plan": "Execute a representative agent_id filter and assert the bound CLI result contains only that agent's approvals."
31
+ },
32
+ {
33
+ "command": "team-agent approvals [coder]",
34
+ "bucket": "declared_gap",
35
+ "covered": false,
36
+ "owner": "runtime-owner:approvals",
37
+ "plan": "Execute the literal coder representative and assert the bound CLI result's target-filter behavior."
38
+ },
39
+ {
40
+ "command": "team-agent attach-leader",
41
+ "bucket": "declared_gap",
42
+ "covered": false,
43
+ "owner": "runtime-owner:leader-channel",
44
+ "plan": "Execute in a hermetic caller-pane fixture and bind assertions to either the persisted receiver binding or the precise zero-write refusal."
45
+ },
46
+ {
47
+ "command": "team-agent claim-leader",
48
+ "bucket": "declared_gap",
49
+ "covered": false,
50
+ "owner": "runtime-owner:leader-channel",
51
+ "plan": "Execute in a hermetic leader fixture and bind assertions to owner/receiver persistence or a precise zero-write refusal."
52
+ },
53
+ {
54
+ "command": "team-agent claude",
55
+ "bucket": "declared_gap",
56
+ "covered": false,
57
+ "owner": "runtime-owner:provider-launcher",
58
+ "plan": "Use a per-call hermetic PATH shim for claude, then assert the shim's exact provider argv log and the bound CLI exit/output."
59
+ },
60
+ {
61
+ "command": "team-agent clone-agent <source> --as <new>",
62
+ "bucket": "declared_gap",
63
+ "covered": false,
64
+ "owner": "runtime-owner:provider-lifecycle",
65
+ "plan": "Use an isolated provider/session fixture or authorized subscription gate and bind assertions to clone success or its exact rollback refusal."
66
+ },
67
+ {
68
+ "command": "team-agent codex",
69
+ "bucket": "declared_gap",
70
+ "covered": false,
71
+ "owner": "runtime-owner:provider-launcher",
72
+ "plan": "Use a per-call hermetic PATH shim for codex, then assert the shim's exact provider argv log and the bound CLI exit/output."
73
+ },
74
+ {
75
+ "command": "team-agent codex --dangerously-bypass-approvals-and-sandbox",
76
+ "bucket": "declared_gap",
77
+ "covered": false,
78
+ "owner": "runtime-owner:provider-launcher",
79
+ "plan": "Use a per-call hermetic codex PATH shim and assert the exact dangerous flag argv log plus the bound CLI exit/output without invoking a real provider."
80
+ },
81
+ {
82
+ "command": "team-agent collect",
83
+ "bucket": "declared_gap",
84
+ "covered": false,
85
+ "owner": "runtime-owner:results",
86
+ "plan": "Execute the exact human collect argv after a worker result and bind assertions to presentation and consumption of that same result."
87
+ },
88
+ {
89
+ "command": "team-agent doctor",
90
+ "bucket": "declared_gap",
91
+ "covered": false,
92
+ "owner": "runtime-owner:diagnostics",
93
+ "plan": "Execute the exact human doctor argv and bind assertions to its exit and key diagnostic checks."
94
+ },
95
+ {
96
+ "command": "team-agent fork-agent <source> --as <new>",
97
+ "bucket": "declared_gap",
98
+ "covered": false,
99
+ "owner": "runtime-owner:provider-lifecycle",
100
+ "plan": "Use an isolated provider/session fixture or authorized subscription gate and bind assertions to fork success or its exact rollback refusal."
101
+ },
102
+ {
103
+ "command": "team-agent inbox",
104
+ "bucket": "declared_gap",
105
+ "covered": false,
106
+ "owner": "runtime-owner:messaging",
107
+ "plan": "Execute the exact default inbox argv and bind assertions to its selected recipient and message or empty-state output."
108
+ },
109
+ {
110
+ "command": "team-agent inbox coder",
111
+ "bucket": "declared_gap",
112
+ "covered": false,
113
+ "owner": "runtime-owner:messaging",
114
+ "plan": "Execute the exact coder inbox argv and bind assertions to recipient filtering and delivery fields."
115
+ },
116
+ {
117
+ "command": "team-agent profile doctor <name> --workspace . --json",
118
+ "bucket": "declared_gap",
119
+ "covered": false,
120
+ "owner": "runtime-owner:profiles",
121
+ "plan": "Execute a representative local profile doctor argv and bind assertions to its JSON validation result and write isolation."
122
+ },
123
+ {
124
+ "command": "team-agent profile init <name> --auth-mode subscription --workspace .",
125
+ "bucket": "declared_gap",
126
+ "covered": false,
127
+ "owner": "runtime-owner:profiles",
128
+ "plan": "Execute a representative local profile init and assert the bound result plus persisted profile identity and subscription auth mode."
129
+ },
130
+ {
131
+ "command": "team-agent profile init claude-default --auth-mode subscription --workspace .",
132
+ "bucket": "declared_gap",
133
+ "covered": false,
134
+ "owner": "runtime-owner:profiles",
135
+ "plan": "Execute the exact local init argv and assert the bound result plus claude-default subscription profile fields without launching Claude."
136
+ },
137
+ {
138
+ "command": "team-agent profile init codex-default --auth-mode subscription --workspace .",
139
+ "bucket": "declared_gap",
140
+ "covered": false,
141
+ "owner": "runtime-owner:profiles",
142
+ "plan": "Execute the exact local init argv and assert the bound result plus codex-default subscription profile fields without launching Codex."
143
+ },
144
+ {
145
+ "command": "team-agent profile init deepseek --auth-mode compatible_api --workspace .",
146
+ "bucket": "declared_gap",
147
+ "covered": false,
148
+ "owner": "runtime-owner:profiles",
149
+ "plan": "Execute the exact local init argv and assert the bound result plus compatible_api profile schema without network access."
150
+ },
151
+ {
152
+ "command": "team-agent profile show <name> --workspace . --json",
153
+ "bucket": "declared_gap",
154
+ "covered": false,
155
+ "owner": "runtime-owner:profiles",
156
+ "plan": "Show a profile created in the same fixture and bind field-by-field round-trip assertions to the CLI result."
157
+ },
158
+ {
159
+ "command": "team-agent profile show deepseek --workspace . --json",
160
+ "bucket": "declared_gap",
161
+ "covered": false,
162
+ "owner": "runtime-owner:profiles",
163
+ "plan": "Show the isolated deepseek profile and bind exact identity/auth-mode assertions to the CLI result."
164
+ },
165
+ {
166
+ "command": "team-agent quick-start",
167
+ "bucket": "declared_gap",
168
+ "covered": false,
169
+ "owner": "runtime-owner:lifecycle",
170
+ "plan": "Execute the exact argv from a hermetic project root and bind assertions to canonical runtime, team, and session identity."
171
+ },
172
+ {
173
+ "command": "team-agent quick-start ./roles --team-id alpha",
174
+ "bucket": "declared_gap",
175
+ "covered": false,
176
+ "owner": "runtime-owner:lifecycle",
177
+ "plan": "Execute against an isolated legacy roles fixture and bind assertions to the alpha team identity and unique runtime."
178
+ },
179
+ {
180
+ "command": "team-agent quick-start .team/alpha",
181
+ "bucket": "declared_gap",
182
+ "covered": false,
183
+ "owner": "runtime-owner:lifecycle",
184
+ "plan": "Execute against an isolated team directory and bind assertions proving the directory literal cannot split canonical team identity."
185
+ },
186
+ {
187
+ "command": "team-agent quick-start .team/current",
188
+ "bucket": "covered",
189
+ "cases": ["lnch_001_quick_start_basic"],
190
+ "evidence": {
191
+ "case": "lnch_001_quick_start_basic",
192
+ "source_file": "crates/team-agent/tests/e2e/cases/lnch_001_quick_start_basic.rs",
193
+ "invocation": {
194
+ "runner": "run_ta",
195
+ "line": 30,
196
+ "documented_argv": ["team-agent", "quick-start", ".team/current"],
197
+ "literal_argv": ["quick-start", ".team/current"]
198
+ },
199
+ "binding": {
200
+ "name": "out",
201
+ "line": 30
202
+ },
203
+ "assertion": {
204
+ "macro_name": "assert",
205
+ "line": 41,
206
+ "operand": "condition",
207
+ "behavior_fact": "stdout",
208
+ "failure_marker": "quick-start did not launch the team"
209
+ },
210
+ "negative_twin": {
211
+ "env_key": "TEAM_AGENT_COVERAGE_NEGATIVE_TWIN",
212
+ "env_value": "quick-start-status",
213
+ "operation": "remove_text_literal",
214
+ "remove_literal": "status: leader_receiver_unbound",
215
+ "replacement": "negative_twin_removed"
216
+ }
217
+ }
218
+ },
219
+ {
220
+ "command": "team-agent quick-start <dir>",
221
+ "bucket": "covered",
222
+ "cases": ["lnch_001_quick_start_basic"],
223
+ "evidence": {
224
+ "case": "lnch_001_quick_start_basic",
225
+ "source_file": "crates/team-agent/tests/e2e/cases/lnch_001_quick_start_basic.rs",
226
+ "invocation": {
227
+ "runner": "run_ta",
228
+ "line": 30,
229
+ "documented_argv": ["team-agent", "quick-start", "<dir>"],
230
+ "literal_argv": ["quick-start", ".team/current"]
231
+ },
232
+ "binding": {
233
+ "name": "out",
234
+ "line": 30
235
+ },
236
+ "assertion": {
237
+ "macro_name": "assert",
238
+ "line": 69,
239
+ "operand": "condition",
240
+ "behavior_fact": "stdout",
241
+ "failure_marker": "public output must expose the canonical session name"
242
+ },
243
+ "negative_twin": {
244
+ "env_key": "TEAM_AGENT_COVERAGE_NEGATIVE_TWIN",
245
+ "env_value": "quick-start-session-name",
246
+ "operation": "remove_text_literal",
247
+ "remove_literal": "session_name: ",
248
+ "replacement": "negative_twin_removed"
249
+ }
250
+ }
251
+ },
252
+ {
253
+ "command": "team-agent remove-agent <agent> --workspace . --confirm",
254
+ "bucket": "declared_gap",
255
+ "covered": false,
256
+ "owner": "runtime-owner:lifecycle",
257
+ "plan": "Execute the exact argv in a dedicated hermetic lifecycle fixture and bind assertions to roster/window removal and sibling preservation."
258
+ },
259
+ {
260
+ "command": "team-agent reset-agent <agent> --discard-session",
261
+ "bucket": "declared_gap",
262
+ "covered": false,
263
+ "owner": "runtime-owner:lifecycle",
264
+ "plan": "Execute the exact argv in a dedicated hermetic fixture and bind assertions to session discard and worker state."
265
+ },
266
+ {
267
+ "command": "team-agent restart",
268
+ "bucket": "declared_gap",
269
+ "covered": false,
270
+ "owner": "runtime-owner:restart",
271
+ "plan": "Execute from an isolated single-team cwd and bind assertions to the restarted session and roster."
272
+ },
273
+ {
274
+ "command": "team-agent restart .",
275
+ "bucket": "declared_gap",
276
+ "covered": false,
277
+ "owner": "runtime-owner:restart",
278
+ "plan": "Execute the exact argv including final dot and bind assertions to canonical team selection and restart outcome."
279
+ },
280
+ {
281
+ "command": "team-agent restart . --allow-fresh",
282
+ "bucket": "declared_gap",
283
+ "covered": false,
284
+ "owner": "runtime-owner:restart",
285
+ "plan": "Execute in a dedicated hermetic rebuild fixture and bind assertions to the new session, agent state, and allow-fresh audit."
286
+ },
287
+ {
288
+ "command": "team-agent restart . --team <session_name_or_team_name>",
289
+ "bucket": "declared_gap",
290
+ "covered": false,
291
+ "owner": "runtime-owner:restart",
292
+ "plan": "Execute a representative team selector and bind assertions to selected-team restart and sibling preservation."
293
+ },
294
+ {
295
+ "command": "team-agent send --task task_initial \"Start\"",
296
+ "bucket": "declared_gap",
297
+ "covered": false,
298
+ "owner": "runtime-owner:messaging",
299
+ "plan": "Execute the exact task argv in an isolated task fixture and bind assertions to task/message attribution and durable row state."
300
+ },
301
+ {
302
+ "command": "team-agent send --watch-result",
303
+ "bucket": "declared_gap",
304
+ "covered": false,
305
+ "owner": "runtime-owner:messaging",
306
+ "plan": "Execute the exact incomplete argv and bind assertions to its nonzero usage error and zero message/result writes."
307
+ },
308
+ {
309
+ "command": "team-agent send --watch-result coder \"Do the bounded task\"",
310
+ "bucket": "declared_gap",
311
+ "covered": false,
312
+ "owner": "runtime-owner:messaging",
313
+ "plan": "Execute the exact argv in an isolated coder fixture and bind assertions to blocked-before-watch or the same-message result closure."
314
+ },
315
+ {
316
+ "command": "team-agent send reviewer \"Review this change\"",
317
+ "bucket": "declared_gap",
318
+ "covered": false,
319
+ "owner": "runtime-owner:messaging",
320
+ "plan": "Execute the exact argv against a fake reviewer and bind recipient, delivered, original result, and collect assertions."
321
+ },
322
+ {
323
+ "command": "team-agent shutdown --workspace . --keep-logs",
324
+ "bucket": "declared_gap",
325
+ "covered": false,
326
+ "owner": "runtime-owner:shutdown",
327
+ "plan": "Execute the exact argv only in a dedicated hermetic fixture and bind assertions to scoped session removal, kept logs, and sibling preservation."
328
+ },
329
+ {
330
+ "command": "team-agent start-agent <agent>",
331
+ "bucket": "declared_gap",
332
+ "covered": false,
333
+ "owner": "runtime-owner:lifecycle",
334
+ "plan": "Execute a representative exact argv for a stopped fake agent and bind assertions to status, pane, and window creation."
335
+ },
336
+ {
337
+ "command": "team-agent start-agent <agent_id> --workspace .",
338
+ "bucket": "declared_gap",
339
+ "covered": false,
340
+ "owner": "runtime-owner:lifecycle",
341
+ "plan": "Execute a representative exact workspace-dot argv and bind assertions to the same agent's lifecycle result."
342
+ },
343
+ {
344
+ "command": "team-agent start-agent coder --workspace .",
345
+ "bucket": "declared_gap",
346
+ "covered": false,
347
+ "owner": "runtime-owner:lifecycle",
348
+ "plan": "Execute in an isolated coder fixture and bind assertions that the selected coder, not a sibling namesake, starts."
349
+ },
350
+ {
351
+ "command": "team-agent status",
352
+ "bucket": "declared_gap",
353
+ "covered": false,
354
+ "owner": "runtime-owner:status",
355
+ "plan": "Execute the exact human status argv and bind assertions to selected team and agent output."
356
+ },
357
+ {
358
+ "command": "team-agent status --detail --json",
359
+ "bucket": "declared_gap",
360
+ "covered": false,
361
+ "owner": "runtime-owner:status",
362
+ "plan": "Execute the exact argv and bind assertions to detail-only coordinator, readiness, and tmux fields."
363
+ },
364
+ {
365
+ "command": "team-agent status --json",
366
+ "bucket": "declared_gap",
367
+ "covered": false,
368
+ "owner": "runtime-owner:status",
369
+ "plan": "Execute the exact argv and bind assertions to the compact status schema and absence of detail-only fields."
370
+ },
371
+ {
372
+ "command": "team-agent status coder",
373
+ "bucket": "declared_gap",
374
+ "covered": false,
375
+ "owner": "runtime-owner:status",
376
+ "plan": "Execute the exact coder status argv and bind assertions to coder-only presentation without sibling leakage."
377
+ }
378
+ ]
379
+ }