@team-agent/installer 0.5.42 → 0.5.44

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 (156) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/crates/team-agent/src/cli/adapters.rs +129 -54
  4. package/crates/team-agent/src/cli/diagnose.rs +1 -2
  5. package/crates/team-agent/src/cli/emit.rs +1 -7
  6. package/crates/team-agent/src/cli/helpers.rs +3 -1
  7. package/crates/team-agent/src/cli/leader.rs +2 -1
  8. package/crates/team-agent/src/cli/mod.rs +126 -16
  9. package/crates/team-agent/src/cli/named_address.rs +14 -5
  10. package/crates/team-agent/src/cli/profile.rs +19 -7
  11. package/crates/team-agent/src/cli/send.rs +9 -3
  12. package/crates/team-agent/src/cli/status.rs +8 -30
  13. package/crates/team-agent/src/cli/status_port.rs +1341 -1272
  14. package/crates/team-agent/src/cli/tests/base.rs +738 -660
  15. package/crates/team-agent/src/cli/tests/compile.rs +45 -18
  16. package/crates/team-agent/src/cli/tests/divergence.rs +462 -444
  17. package/crates/team-agent/src/cli/tests/lane_c.rs +365 -282
  18. package/crates/team-agent/src/cli/tests/leader_watch.rs +356 -329
  19. package/crates/team-agent/src/cli/tests/main_preserved.rs +672 -564
  20. package/crates/team-agent/src/cli/tests/missing_subcommands.rs +284 -224
  21. package/crates/team-agent/src/cli/tests/mod.rs +17 -7
  22. package/crates/team-agent/src/cli/tests/named_address.rs +8 -2
  23. package/crates/team-agent/src/cli/tests/peer_allow.rs +10 -2
  24. package/crates/team-agent/src/cli/tests/run_delegation.rs +314 -273
  25. package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +26 -15
  26. package/crates/team-agent/src/cli/tests/status_send.rs +707 -629
  27. package/crates/team-agent/src/cli/tests/verb_install_skill.rs +20 -4
  28. package/crates/team-agent/src/cli/tests/verb_profile.rs +46 -17
  29. package/crates/team-agent/src/cli/tests/verb_validate.rs +15 -3
  30. package/crates/team-agent/src/codex_app_server.rs +2 -5
  31. package/crates/team-agent/src/compiler/tests.rs +139 -33
  32. package/crates/team-agent/src/compiler.rs +55 -22
  33. package/crates/team-agent/src/conpty/backend.rs +23 -33
  34. package/crates/team-agent/src/coordinator/backoff.rs +2 -7
  35. package/crates/team-agent/src/coordinator/conpty_shim.rs +55 -67
  36. package/crates/team-agent/src/coordinator/health.rs +46 -31
  37. package/crates/team-agent/src/coordinator/mod.rs +3 -3
  38. package/crates/team-agent/src/coordinator/orphan.rs +22 -10
  39. package/crates/team-agent/src/coordinator/steps/abnormal.rs +51 -56
  40. package/crates/team-agent/src/coordinator/tests/abnormal.rs +55 -19
  41. package/crates/team-agent/src/coordinator/tests/basics.rs +179 -41
  42. package/crates/team-agent/src/coordinator/tests/daemon.rs +53 -13
  43. package/crates/team-agent/src/coordinator/tests/health_sync.rs +78 -19
  44. package/crates/team-agent/src/coordinator/tests/main_preserved.rs +61 -11
  45. package/crates/team-agent/src/coordinator/tests/mod.rs +33 -39
  46. package/crates/team-agent/src/coordinator/tests/spine.rs +52 -12
  47. package/crates/team-agent/src/coordinator/tests/takeover.rs +73 -15
  48. package/crates/team-agent/src/coordinator/tests/tick_core.rs +50 -15
  49. package/crates/team-agent/src/coordinator/tests/watch.rs +74 -20
  50. package/crates/team-agent/src/db/message_store.rs +138 -30
  51. package/crates/team-agent/src/db/migration.rs +249 -61
  52. package/crates/team-agent/src/db/schema.rs +303 -82
  53. package/crates/team-agent/src/diagnose/comms.rs +9 -2
  54. package/crates/team-agent/src/diagnose/mod.rs +1 -3
  55. package/crates/team-agent/src/diagnose/orphans.rs +79 -61
  56. package/crates/team-agent/src/event_log.rs +70 -16
  57. package/crates/team-agent/src/layout/manager.rs +15 -4
  58. package/crates/team-agent/src/layout/mod.rs +4 -4
  59. package/crates/team-agent/src/layout/overlay.rs +10 -3
  60. package/crates/team-agent/src/layout/placement.rs +5 -1
  61. package/crates/team-agent/src/layout/recovery.rs +4 -2
  62. package/crates/team-agent/src/layout/runtime_sessions.rs +7 -7
  63. package/crates/team-agent/src/layout/sessions.rs +17 -9
  64. package/crates/team-agent/src/layout/tmux_endpoint.rs +1 -1
  65. package/crates/team-agent/src/layout/worker_env.rs +87 -19
  66. package/crates/team-agent/src/leader/helpers.rs +7 -1
  67. package/crates/team-agent/src/leader/lease.rs +199 -89
  68. package/crates/team-agent/src/leader/owner_bind.rs +55 -22
  69. package/crates/team-agent/src/leader/provider_attribution.rs +25 -6
  70. package/crates/team-agent/src/leader/rediscover/tests.rs +88 -24
  71. package/crates/team-agent/src/leader/rediscover.rs +74 -25
  72. package/crates/team-agent/src/leader/registry.rs +1 -1
  73. package/crates/team-agent/src/leader/start.rs +75 -54
  74. package/crates/team-agent/src/leader/takeover.rs +46 -11
  75. package/crates/team-agent/src/leader/tests/basics.rs +320 -167
  76. package/crates/team-agent/src/leader/tests/byte_findings.rs +361 -219
  77. package/crates/team-agent/src/leader/tests/identity.rs +428 -356
  78. package/crates/team-agent/src/leader/tests/idle.rs +285 -254
  79. package/crates/team-agent/src/leader/tests/lease_api.rs +338 -274
  80. package/crates/team-agent/src/leader/tests/lease_claim.rs +643 -593
  81. package/crates/team-agent/src/leader/tests/mod.rs +115 -99
  82. package/crates/team-agent/src/leader/tests/rediscover.rs +74 -22
  83. package/crates/team-agent/src/leader/tests/wake_start_owner.rs +237 -211
  84. package/crates/team-agent/src/lib.rs +4 -4
  85. package/crates/team-agent/src/lifecycle/display.rs +7 -3
  86. package/crates/team-agent/src/lifecycle/launch.rs +55 -15
  87. package/crates/team-agent/src/lifecycle/mod.rs +9 -1
  88. package/crates/team-agent/src/lifecycle/profile_launch.rs +77 -34
  89. package/crates/team-agent/src/lifecycle/profile_smoke.rs +3 -1
  90. package/crates/team-agent/src/lifecycle/restart/agent.rs +1 -6
  91. package/crates/team-agent/src/lifecycle/restart/common.rs +6 -2
  92. package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +1 -4
  93. package/crates/team-agent/src/lifecycle/restart/preflight.rs +6 -5
  94. package/crates/team-agent/src/lifecycle/restart/rebuild.rs +26 -22
  95. package/crates/team-agent/src/lifecycle/restart/remove.rs +45 -35
  96. package/crates/team-agent/src/lifecycle/restart/team_state.rs +63 -17
  97. package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +251 -84
  98. package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +198 -48
  99. package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +2 -1
  100. package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +152 -32
  101. package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +1 -5
  102. package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +3 -0
  103. package/crates/team-agent/src/lifecycle/tests.rs +2 -2
  104. package/crates/team-agent/src/main.rs +4 -4
  105. package/crates/team-agent/src/mcp_server/lifecycle_tools/agent_ops.rs +47 -20
  106. package/crates/team-agent/src/mcp_server/mod.rs +11 -2
  107. package/crates/team-agent/src/mcp_server/types.rs +14 -3
  108. package/crates/team-agent/src/mcp_server/wire.rs +230 -68
  109. package/crates/team-agent/src/messaging/delivery.rs +20 -18
  110. package/crates/team-agent/src/messaging/helpers.rs +25 -4
  111. package/crates/team-agent/src/messaging/leader_receiver.rs +4 -5
  112. package/crates/team-agent/src/messaging/mod.rs +2 -3
  113. package/crates/team-agent/src/messaging/selftest.rs +46 -26
  114. package/crates/team-agent/src/messaging/tests/main_preserved.rs +47 -12
  115. package/crates/team-agent/src/messaging/tests/runtime.rs +57 -22
  116. package/crates/team-agent/src/messaging/tests/spine.rs +154 -40
  117. package/crates/team-agent/src/messaging/tests/wave2.rs +31 -32
  118. package/crates/team-agent/src/messaging/trust.rs +25 -2
  119. package/crates/team-agent/src/messaging/watchers.rs +37 -9
  120. package/crates/team-agent/src/model/enums.rs +65 -16
  121. package/crates/team-agent/src/model/ids.rs +12 -3
  122. package/crates/team-agent/src/model/paths.rs +28 -7
  123. package/crates/team-agent/src/model/permissions.rs +176 -33
  124. package/crates/team-agent/src/model/routing.rs +66 -20
  125. package/crates/team-agent/src/model/spec.rs +365 -69
  126. package/crates/team-agent/src/model/task_graph.rs +36 -9
  127. package/crates/team-agent/src/model/yaml/tests.rs +24 -6
  128. package/crates/team-agent/src/model/yaml.rs +7 -6
  129. package/crates/team-agent/src/packaging/install.rs +23 -9
  130. package/crates/team-agent/src/packaging/migrate.rs +5 -7
  131. package/crates/team-agent/src/packaging/mod.rs +9 -1
  132. package/crates/team-agent/src/packaging/repair.rs +13 -6
  133. package/crates/team-agent/src/packaging/tests.rs +63 -16
  134. package/crates/team-agent/src/packaging/types.rs +22 -7
  135. package/crates/team-agent/src/platform/argv.rs +4 -1
  136. package/crates/team-agent/src/platform/file_lock.rs +22 -8
  137. package/crates/team-agent/src/platform/process.rs +54 -24
  138. package/crates/team-agent/src/provider/adapters/claude.rs +1 -3
  139. package/crates/team-agent/src/provider/approvals/parsing.rs +134 -26
  140. package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +13 -3
  141. package/crates/team-agent/src/provider/classify.rs +127 -42
  142. package/crates/team-agent/src/provider/faults.rs +17 -5
  143. package/crates/team-agent/src/provider/helpers.rs +6 -5
  144. package/crates/team-agent/src/provider/startup_prompt.rs +75 -27
  145. package/crates/team-agent/src/state/persist.rs +28 -0
  146. package/crates/team-agent/src/state/repository.rs +8 -3
  147. package/crates/team-agent/src/tmux_backend/tests.rs +1637 -1398
  148. package/crates/team-agent/src/tmux_backend.rs +80 -44
  149. package/crates/team-agent/src/topology.rs +40 -20
  150. package/crates/team-agent/src/transport/test_support.rs +20 -23
  151. package/crates/team-agent/src/transport/tests/behavior.rs +292 -293
  152. package/crates/team-agent/src/transport/tests/mod.rs +178 -187
  153. package/crates/team-agent/src/transport/tests/wire.rs +561 -525
  154. package/crates/team-agent/src/transport.rs +12 -17
  155. package/crates/team-agent/src/transport_factory.rs +29 -14
  156. package/package.json +4 -4
@@ -38,32 +38,86 @@ const INDEX_SQL: &[&str] = &[
38
38
 
39
39
  // 各表 required 列(`schema.py` 的 *_COLUMNS 集合;此处用有序数组,成员判定与集合等价)。
40
40
  const MESSAGE_COLUMNS: &[&str] = &[
41
- "owner_team_id", "message_id", "task_id", "sender", "recipient", "reply_to", "requires_ack",
42
- "status", "content", "artifact_refs", "created_at", "updated_at", "delivered_at",
43
- "acknowledged_at", "error", "delivery_attempts",
41
+ "owner_team_id",
42
+ "message_id",
43
+ "task_id",
44
+ "sender",
45
+ "recipient",
46
+ "reply_to",
47
+ "requires_ack",
48
+ "status",
49
+ "content",
50
+ "artifact_refs",
51
+ "created_at",
52
+ "updated_at",
53
+ "delivered_at",
54
+ "acknowledged_at",
55
+ "error",
56
+ "delivery_attempts",
57
+ ];
58
+ const RESULT_COLUMNS: &[&str] = &[
59
+ "owner_team_id",
60
+ "result_id",
61
+ "task_id",
62
+ "agent_id",
63
+ "envelope",
64
+ "status",
65
+ "created_at",
44
66
  ];
45
- const RESULT_COLUMNS: &[&str] =
46
- &["owner_team_id", "result_id", "task_id", "agent_id", "envelope", "status", "created_at"];
47
67
  const SCHEDULED_EVENT_COLUMNS: &[&str] = &[
48
- "id", "owner_team_id", "due_at", "target", "kind", "payload_json", "status", "created_at",
49
- "fired_at", "result_json",
68
+ "id",
69
+ "owner_team_id",
70
+ "due_at",
71
+ "target",
72
+ "kind",
73
+ "payload_json",
74
+ "status",
75
+ "created_at",
76
+ "fired_at",
77
+ "result_json",
50
78
  ];
51
79
  const DELIVERY_TOKEN_COLUMNS: &[&str] = &[
52
- "message_id", "unique_token", "injected_at", "visible_at", "consumed_at", "failed_at",
80
+ "message_id",
81
+ "unique_token",
82
+ "injected_at",
83
+ "visible_at",
84
+ "consumed_at",
85
+ "failed_at",
53
86
  "failure_reason",
54
87
  ];
55
88
  const AGENT_HEALTH_COLUMNS: &[&str] = &[
56
- "owner_team_id", "agent_id", "status", "last_output_at", "context_usage_pct", "current_task_id",
89
+ "owner_team_id",
90
+ "agent_id",
91
+ "status",
92
+ "last_output_at",
93
+ "context_usage_pct",
94
+ "current_task_id",
57
95
  "updated_at",
58
96
  ];
59
97
  const PEER_ALLOWLIST_COLUMNS: &[&str] = &["a", "b", "created_at"];
60
98
  const RESULT_WATCHER_COLUMNS: &[&str] = &[
61
- "owner_team_id", "watcher_id", "task_id", "agent_id", "message_id", "leader_id", "status",
62
- "created_at", "completed_at", "result_id", "notified_message_id", "error",
99
+ "owner_team_id",
100
+ "watcher_id",
101
+ "task_id",
102
+ "agent_id",
103
+ "message_id",
104
+ "leader_id",
105
+ "status",
106
+ "created_at",
107
+ "completed_at",
108
+ "result_id",
109
+ "notified_message_id",
110
+ "error",
63
111
  ];
64
112
  const LEADER_NOTIFICATION_LOG_COLUMNS: &[&str] = &[
65
- "result_id", "owner_team_id", "owner_epoch", "leader_session_uuid", "notified_message_id",
66
- "notified_at", "leader_pane_id_at_notify", "envelope_content_hash",
113
+ "result_id",
114
+ "owner_team_id",
115
+ "owner_epoch",
116
+ "leader_session_uuid",
117
+ "notified_message_id",
118
+ "notified_at",
119
+ "leader_pane_id_at_notify",
120
+ "envelope_content_hash",
67
121
  ];
68
122
 
69
123
  /// 打开 `team.db` 并设 pragmas(`core.py:60-61`:busy_timeout=30000 + WAL)。
@@ -91,7 +145,9 @@ fn retry_sqlite<T>(mut op: impl FnMut() -> rusqlite::Result<T>) -> Result<T, DbE
91
145
  }
92
146
  match last_error {
93
147
  Some(error) => Err(error.into()),
94
- None => Err(DbError::Schema("sqlite retry exhausted without an error".to_string())),
148
+ None => Err(DbError::Schema(
149
+ "sqlite retry exhausted without an error".to_string(),
150
+ )),
95
151
  }
96
152
  }
97
153
 
@@ -176,7 +232,10 @@ fn migrate_agent_health_owner_team_id(conn: &Connection) -> Result<(), DbError>
176
232
 
177
233
  /// `schema.py:initialize_schema`:建表 + 列迁移 + agent_health 重建 + 索引 + user_version。
178
234
  /// 一个事务内完成(对应 Python `with conn:`)。
179
- pub fn initialize_schema(conn: &Connection, db_path: Option<&std::path::Path>) -> Result<(), DbError> {
235
+ pub fn initialize_schema(
236
+ conn: &Connection,
237
+ db_path: Option<&std::path::Path>,
238
+ ) -> Result<(), DbError> {
180
239
  // Gap 46 入口门(`schema.py:117`):先检测/修复物理列序漂移(legacy DB)。
181
240
  // fresh DB 下 no-op(无 managed 表 → 无 diff);随后建表 + 列迁移在自己的事务里。
182
241
  crate::db::migration::ensure_table_layout(conn, SCHEMA_VERSION, db_path)?;
@@ -197,18 +256,53 @@ pub fn initialize_schema(conn: &Connection, db_path: Option<&std::path::Path>) -
197
256
  "messages",
198
257
  MESSAGE_COLUMNS,
199
258
  &[
200
- ("delivery_attempts", "alter table messages add column delivery_attempts integer not null default 0"),
201
- ("owner_team_id", "alter table messages add column owner_team_id text"),
259
+ (
260
+ "delivery_attempts",
261
+ "alter table messages add column delivery_attempts integer not null default 0",
262
+ ),
263
+ (
264
+ "owner_team_id",
265
+ "alter table messages add column owner_team_id text",
266
+ ),
202
267
  ],
203
268
  )?;
204
- ensure_table_columns(&tx, "results", RESULT_COLUMNS, &[("owner_team_id", "alter table results add column owner_team_id text")])?;
205
- ensure_table_columns(&tx, "scheduled_events", SCHEDULED_EVENT_COLUMNS, &[("owner_team_id", "alter table scheduled_events add column owner_team_id text")])?;
269
+ ensure_table_columns(
270
+ &tx,
271
+ "results",
272
+ RESULT_COLUMNS,
273
+ &[(
274
+ "owner_team_id",
275
+ "alter table results add column owner_team_id text",
276
+ )],
277
+ )?;
278
+ ensure_table_columns(
279
+ &tx,
280
+ "scheduled_events",
281
+ SCHEDULED_EVENT_COLUMNS,
282
+ &[(
283
+ "owner_team_id",
284
+ "alter table scheduled_events add column owner_team_id text",
285
+ )],
286
+ )?;
206
287
  ensure_table_columns(&tx, "delivery_tokens", DELIVERY_TOKEN_COLUMNS, &[])?;
207
288
  migrate_agent_health_owner_team_id(&tx)?;
208
289
  ensure_table_columns(&tx, "peer_allowlist", PEER_ALLOWLIST_COLUMNS, &[])?;
209
- ensure_table_columns(&tx, "result_watchers", RESULT_WATCHER_COLUMNS, &[("owner_team_id", "alter table result_watchers add column owner_team_id text")])?;
290
+ ensure_table_columns(
291
+ &tx,
292
+ "result_watchers",
293
+ RESULT_WATCHER_COLUMNS,
294
+ &[(
295
+ "owner_team_id",
296
+ "alter table result_watchers add column owner_team_id text",
297
+ )],
298
+ )?;
210
299
  tx.execute(CREATE_LEADER_NOTIFICATION_LOG, [])?;
211
- ensure_table_columns(&tx, "leader_notification_log", LEADER_NOTIFICATION_LOG_COLUMNS, &[])?;
300
+ ensure_table_columns(
301
+ &tx,
302
+ "leader_notification_log",
303
+ LEADER_NOTIFICATION_LOG_COLUMNS,
304
+ &[],
305
+ )?;
212
306
  ensure_schema_indexes(&tx)?;
213
307
  tx.execute_batch(&format!("pragma user_version = {SCHEMA_VERSION}"))?;
214
308
  tx.commit()?;
@@ -254,14 +348,17 @@ mod tests {
254
348
  ("results", "table"),
255
349
  ("scheduled_events", "table"),
256
350
  ];
257
- let got_ref: Vec<(&str, &str)> = got.iter().map(|(n, t)| (n.as_str(), t.as_str())).collect();
351
+ let got_ref: Vec<(&str, &str)> =
352
+ got.iter().map(|(n, t)| (n.as_str(), t.as_str())).collect();
258
353
  assert_eq!(got_ref, want);
259
354
  }
260
355
 
261
356
  #[test]
262
357
  fn user_version_is_three() {
263
358
  let conn = fresh();
264
- let v: i64 = conn.query_row("pragma user_version", [], |r| r.get(0)).unwrap();
359
+ let v: i64 = conn
360
+ .query_row("pragma user_version", [], |r| r.get(0))
361
+ .unwrap();
265
362
  assert_eq!(v, SCHEMA_VERSION);
266
363
  assert_eq!(v, 3);
267
364
  }
@@ -272,9 +369,22 @@ mod tests {
272
369
  assert_eq!(
273
370
  table_layout(&conn, "messages").unwrap(),
274
371
  vec![
275
- "message_id", "owner_team_id", "task_id", "sender", "recipient", "reply_to",
276
- "requires_ack", "status", "content", "artifact_refs", "created_at", "updated_at",
277
- "delivered_at", "acknowledged_at", "error", "delivery_attempts",
372
+ "message_id",
373
+ "owner_team_id",
374
+ "task_id",
375
+ "sender",
376
+ "recipient",
377
+ "reply_to",
378
+ "requires_ack",
379
+ "status",
380
+ "content",
381
+ "artifact_refs",
382
+ "created_at",
383
+ "updated_at",
384
+ "delivered_at",
385
+ "acknowledged_at",
386
+ "error",
387
+ "delivery_attempts",
278
388
  ]
279
389
  );
280
390
  }
@@ -286,7 +396,11 @@ mod tests {
286
396
  initialize_schema(&conn, None).unwrap();
287
397
  assert_eq!(table_layout(&conn, "messages").unwrap().len(), 16);
288
398
  let idx: i64 = conn
289
- .query_row("select count(*) from sqlite_master where type='index' and sql is not null", [], |r| r.get(0))
399
+ .query_row(
400
+ "select count(*) from sqlite_master where type='index' and sql is not null",
401
+ [],
402
+ |r| r.get(0),
403
+ )
290
404
  .unwrap();
291
405
  assert_eq!(idx, 6, "二次 init 后 6 个 named index 仍在");
292
406
  }
@@ -296,51 +410,126 @@ mod tests {
296
410
  fn per_column_table_info_all_eight_tables() {
297
411
  type Col = (&'static str, &'static str, i64, Option<&'static str>, i64);
298
412
  let golden: &[(&str, &[Col])] = &[
299
- ("messages", &[
300
- ("message_id","TEXT",0,None,1),("owner_team_id","TEXT",0,None,0),("task_id","TEXT",0,None,0),
301
- ("sender","TEXT",0,None,0),("recipient","TEXT",0,None,0),("reply_to","TEXT",0,None,0),
302
- ("requires_ack","INTEGER",0,None,0),("status","TEXT",0,None,0),("content","TEXT",0,None,0),
303
- ("artifact_refs","TEXT",0,None,0),("created_at","TEXT",0,None,0),("updated_at","TEXT",0,None,0),
304
- ("delivered_at","TEXT",0,None,0),("acknowledged_at","TEXT",0,None,0),("error","TEXT",0,None,0),
305
- ("delivery_attempts","INTEGER",1,Some("0"),0),
306
- ]),
307
- ("results", &[
308
- ("result_id","TEXT",0,None,1),("owner_team_id","TEXT",0,None,0),("task_id","TEXT",1,None,0),
309
- ("agent_id","TEXT",1,None,0),("envelope","TEXT",1,None,0),("status","TEXT",1,None,0),("created_at","TEXT",1,None,0),
310
- ]),
311
- ("scheduled_events", &[
312
- ("id","INTEGER",0,None,1),("owner_team_id","TEXT",0,None,0),("due_at","TEXT",1,None,0),
313
- ("target","TEXT",1,None,0),("kind","TEXT",1,None,0),("payload_json","TEXT",1,None,0),
314
- ("status","TEXT",1,None,0),("created_at","TEXT",1,None,0),("fired_at","TEXT",0,None,0),("result_json","TEXT",0,None,0),
315
- ]),
316
- ("delivery_tokens", &[
317
- ("message_id","TEXT",0,None,1),("unique_token","TEXT",1,None,0),("injected_at","TEXT",1,None,0),
318
- ("visible_at","TEXT",0,None,0),("consumed_at","TEXT",0,None,0),("failed_at","TEXT",0,None,0),("failure_reason","TEXT",0,None,0),
319
- ]),
320
- ("agent_health", &[
321
- ("owner_team_id","TEXT",0,None,0),("agent_id","TEXT",1,None,0),("status","TEXT",1,None,0),
322
- ("last_output_at","TEXT",0,None,0),("context_usage_pct","INTEGER",0,None,0),("current_task_id","TEXT",0,None,0),("updated_at","TEXT",1,None,0),
323
- ]),
324
- ("peer_allowlist", &[
325
- ("a","TEXT",1,None,1),("b","TEXT",1,None,2),("created_at","TEXT",1,None,0),
326
- ]),
327
- ("result_watchers", &[
328
- ("watcher_id","TEXT",0,None,1),("owner_team_id","TEXT",0,None,0),("task_id","TEXT",0,None,0),
329
- ("agent_id","TEXT",0,None,0),("message_id","TEXT",0,None,0),("leader_id","TEXT",1,None,0),
330
- ("status","TEXT",1,None,0),("created_at","TEXT",1,None,0),("completed_at","TEXT",0,None,0),
331
- ("result_id","TEXT",0,None,0),("notified_message_id","TEXT",0,None,0),("error","TEXT",0,None,0),
332
- ]),
333
- ("leader_notification_log", &[
334
- ("result_id","TEXT",1,None,1),("owner_team_id","TEXT",1,Some("''"),2),("owner_epoch","INTEGER",1,Some("0"),3),
335
- ("leader_session_uuid","TEXT",0,None,0),("notified_message_id","TEXT",1,None,0),("notified_at","TEXT",1,None,0),
336
- ("leader_pane_id_at_notify","TEXT",0,None,0),("envelope_content_hash","TEXT",0,None,0),
337
- ]),
413
+ (
414
+ "messages",
415
+ &[
416
+ ("message_id", "TEXT", 0, None, 1),
417
+ ("owner_team_id", "TEXT", 0, None, 0),
418
+ ("task_id", "TEXT", 0, None, 0),
419
+ ("sender", "TEXT", 0, None, 0),
420
+ ("recipient", "TEXT", 0, None, 0),
421
+ ("reply_to", "TEXT", 0, None, 0),
422
+ ("requires_ack", "INTEGER", 0, None, 0),
423
+ ("status", "TEXT", 0, None, 0),
424
+ ("content", "TEXT", 0, None, 0),
425
+ ("artifact_refs", "TEXT", 0, None, 0),
426
+ ("created_at", "TEXT", 0, None, 0),
427
+ ("updated_at", "TEXT", 0, None, 0),
428
+ ("delivered_at", "TEXT", 0, None, 0),
429
+ ("acknowledged_at", "TEXT", 0, None, 0),
430
+ ("error", "TEXT", 0, None, 0),
431
+ ("delivery_attempts", "INTEGER", 1, Some("0"), 0),
432
+ ],
433
+ ),
434
+ (
435
+ "results",
436
+ &[
437
+ ("result_id", "TEXT", 0, None, 1),
438
+ ("owner_team_id", "TEXT", 0, None, 0),
439
+ ("task_id", "TEXT", 1, None, 0),
440
+ ("agent_id", "TEXT", 1, None, 0),
441
+ ("envelope", "TEXT", 1, None, 0),
442
+ ("status", "TEXT", 1, None, 0),
443
+ ("created_at", "TEXT", 1, None, 0),
444
+ ],
445
+ ),
446
+ (
447
+ "scheduled_events",
448
+ &[
449
+ ("id", "INTEGER", 0, None, 1),
450
+ ("owner_team_id", "TEXT", 0, None, 0),
451
+ ("due_at", "TEXT", 1, None, 0),
452
+ ("target", "TEXT", 1, None, 0),
453
+ ("kind", "TEXT", 1, None, 0),
454
+ ("payload_json", "TEXT", 1, None, 0),
455
+ ("status", "TEXT", 1, None, 0),
456
+ ("created_at", "TEXT", 1, None, 0),
457
+ ("fired_at", "TEXT", 0, None, 0),
458
+ ("result_json", "TEXT", 0, None, 0),
459
+ ],
460
+ ),
461
+ (
462
+ "delivery_tokens",
463
+ &[
464
+ ("message_id", "TEXT", 0, None, 1),
465
+ ("unique_token", "TEXT", 1, None, 0),
466
+ ("injected_at", "TEXT", 1, None, 0),
467
+ ("visible_at", "TEXT", 0, None, 0),
468
+ ("consumed_at", "TEXT", 0, None, 0),
469
+ ("failed_at", "TEXT", 0, None, 0),
470
+ ("failure_reason", "TEXT", 0, None, 0),
471
+ ],
472
+ ),
473
+ (
474
+ "agent_health",
475
+ &[
476
+ ("owner_team_id", "TEXT", 0, None, 0),
477
+ ("agent_id", "TEXT", 1, None, 0),
478
+ ("status", "TEXT", 1, None, 0),
479
+ ("last_output_at", "TEXT", 0, None, 0),
480
+ ("context_usage_pct", "INTEGER", 0, None, 0),
481
+ ("current_task_id", "TEXT", 0, None, 0),
482
+ ("updated_at", "TEXT", 1, None, 0),
483
+ ],
484
+ ),
485
+ (
486
+ "peer_allowlist",
487
+ &[
488
+ ("a", "TEXT", 1, None, 1),
489
+ ("b", "TEXT", 1, None, 2),
490
+ ("created_at", "TEXT", 1, None, 0),
491
+ ],
492
+ ),
493
+ (
494
+ "result_watchers",
495
+ &[
496
+ ("watcher_id", "TEXT", 0, None, 1),
497
+ ("owner_team_id", "TEXT", 0, None, 0),
498
+ ("task_id", "TEXT", 0, None, 0),
499
+ ("agent_id", "TEXT", 0, None, 0),
500
+ ("message_id", "TEXT", 0, None, 0),
501
+ ("leader_id", "TEXT", 1, None, 0),
502
+ ("status", "TEXT", 1, None, 0),
503
+ ("created_at", "TEXT", 1, None, 0),
504
+ ("completed_at", "TEXT", 0, None, 0),
505
+ ("result_id", "TEXT", 0, None, 0),
506
+ ("notified_message_id", "TEXT", 0, None, 0),
507
+ ("error", "TEXT", 0, None, 0),
508
+ ],
509
+ ),
510
+ (
511
+ "leader_notification_log",
512
+ &[
513
+ ("result_id", "TEXT", 1, None, 1),
514
+ ("owner_team_id", "TEXT", 1, Some("''"), 2),
515
+ ("owner_epoch", "INTEGER", 1, Some("0"), 3),
516
+ ("leader_session_uuid", "TEXT", 0, None, 0),
517
+ ("notified_message_id", "TEXT", 1, None, 0),
518
+ ("notified_at", "TEXT", 1, None, 0),
519
+ ("leader_pane_id_at_notify", "TEXT", 0, None, 0),
520
+ ("envelope_content_hash", "TEXT", 0, None, 0),
521
+ ],
522
+ ),
338
523
  ];
339
524
  let conn = fresh();
340
525
  for (table, cols) in golden {
341
- let mut stmt = conn.prepare(&format!("pragma table_info({table})")).unwrap();
526
+ let mut stmt = conn
527
+ .prepare(&format!("pragma table_info({table})"))
528
+ .unwrap();
342
529
  let got: Vec<(String, String, i64, Option<String>, i64)> = stmt
343
- .query_map([], |r| Ok((r.get(1)?, r.get(2)?, r.get(3)?, r.get(4)?, r.get(5)?)))
530
+ .query_map([], |r| {
531
+ Ok((r.get(1)?, r.get(2)?, r.get(3)?, r.get(4)?, r.get(5)?))
532
+ })
344
533
  .unwrap()
345
534
  .collect::<Result<_, _>>()
346
535
  .unwrap();
@@ -358,7 +547,9 @@ mod tests {
358
547
  let mut stmt = conn.prepare("select name, sql from sqlite_master where type='index' and sql is not null order by name").unwrap();
359
548
  let idx: Vec<(String, String)> = stmt
360
549
  .query_map([], |r| Ok((r.get(0)?, r.get(1)?)))
361
- .unwrap().collect::<Result<_, _>>().unwrap();
550
+ .unwrap()
551
+ .collect::<Result<_, _>>()
552
+ .unwrap();
362
553
  let want: Vec<(&str, &str)> = vec![
363
554
  ("idx_agent_health_owner_team_id", "CREATE INDEX idx_agent_health_owner_team_id on agent_health(owner_team_id)"),
364
555
  ("idx_leader_notification_log_team_epoch", "CREATE INDEX idx_leader_notification_log_team_epoch on leader_notification_log(owner_team_id, owner_epoch, notified_at)"),
@@ -371,13 +562,26 @@ mod tests {
371
562
  assert_eq!(got, want);
372
563
  // 7 个 sqlite_autoindex(每个有 pk/unique 约束的表各一)。
373
564
  let auto: Vec<String> = conn
374
- .prepare("select name from sqlite_master where type='index' and sql is null order by name").unwrap()
375
- .query_map([], |r| r.get(0)).unwrap().collect::<Result<_, _>>().unwrap();
376
- assert_eq!(auto, vec![
377
- "sqlite_autoindex_agent_health_1", "sqlite_autoindex_delivery_tokens_1",
378
- "sqlite_autoindex_leader_notification_log_1", "sqlite_autoindex_messages_1",
379
- "sqlite_autoindex_peer_allowlist_1", "sqlite_autoindex_result_watchers_1", "sqlite_autoindex_results_1",
380
- ]);
565
+ .prepare(
566
+ "select name from sqlite_master where type='index' and sql is null order by name",
567
+ )
568
+ .unwrap()
569
+ .query_map([], |r| r.get(0))
570
+ .unwrap()
571
+ .collect::<Result<_, _>>()
572
+ .unwrap();
573
+ assert_eq!(
574
+ auto,
575
+ vec![
576
+ "sqlite_autoindex_agent_health_1",
577
+ "sqlite_autoindex_delivery_tokens_1",
578
+ "sqlite_autoindex_leader_notification_log_1",
579
+ "sqlite_autoindex_messages_1",
580
+ "sqlite_autoindex_peer_allowlist_1",
581
+ "sqlite_autoindex_result_watchers_1",
582
+ "sqlite_autoindex_results_1",
583
+ ]
584
+ );
381
585
  }
382
586
 
383
587
  #[test]
@@ -388,9 +592,13 @@ mod tests {
388
592
  let path = dir.join("team.db");
389
593
  let _ = std::fs::remove_file(&path);
390
594
  let conn = open_db(&path).unwrap();
391
- let jm: String = conn.query_row("pragma journal_mode", [], |r| r.get(0)).unwrap();
595
+ let jm: String = conn
596
+ .query_row("pragma journal_mode", [], |r| r.get(0))
597
+ .unwrap();
392
598
  assert_eq!(jm.to_lowercase(), "wal");
393
- let bt: i64 = conn.query_row("pragma busy_timeout", [], |r| r.get(0)).unwrap();
599
+ let bt: i64 = conn
600
+ .query_row("pragma busy_timeout", [], |r| r.get(0))
601
+ .unwrap();
394
602
  assert_eq!(bt, 30000);
395
603
  }
396
604
 
@@ -398,13 +606,26 @@ mod tests {
398
606
  fn ensure_table_columns_unsupported_missing_errors_with_sorted_names() {
399
607
  // results 只建了 result_id → 缺 owner_team_id(有 migration)+ 其余(无 migration,unsupported)。
400
608
  let conn = Connection::open_in_memory().unwrap();
401
- conn.execute("create table results (result_id text primary key)", []).unwrap();
609
+ conn.execute("create table results (result_id text primary key)", [])
610
+ .unwrap();
402
611
  let err = ensure_table_columns(
403
612
  &conn,
404
613
  "results",
405
- &["owner_team_id", "result_id", "task_id", "agent_id", "envelope", "status", "created_at"],
406
- &[("owner_team_id", "alter table results add column owner_team_id text")],
407
- ).unwrap_err();
614
+ &[
615
+ "owner_team_id",
616
+ "result_id",
617
+ "task_id",
618
+ "agent_id",
619
+ "envelope",
620
+ "status",
621
+ "created_at",
622
+ ],
623
+ &[(
624
+ "owner_team_id",
625
+ "alter table results add column owner_team_id text",
626
+ )],
627
+ )
628
+ .unwrap_err();
408
629
  assert_eq!(
409
630
  err.to_string(),
410
631
  "schema: team.db table results is missing required column(s): agent_id, created_at, envelope, status, task_id"
@@ -96,7 +96,10 @@ fn receiver_binding_snapshot(workspace: &Path, team: Option<&TeamKey>) -> Value
96
96
  .or_else(|| crate::state::ownership::read_owner_value(&state, "").cloned())
97
97
  .and_then(|v| v.get("pane_id").cloned())
98
98
  .unwrap_or(Value::Null);
99
- let caller_pane_id = std::env::var("TMUX_PANE").ok().map(Value::String).unwrap_or(Value::Null);
99
+ let caller_pane_id = std::env::var("TMUX_PANE")
100
+ .ok()
101
+ .map(Value::String)
102
+ .unwrap_or(Value::Null);
100
103
  let pane_id = receiver
101
104
  .and_then(|r| r.get("pane_id"))
102
105
  .cloned()
@@ -140,7 +143,11 @@ fn receiver_binding_snapshot(workspace: &Path, team: Option<&TeamKey>) -> Value
140
143
  fn receiver_pane_stale(socket: &str, pane_id: &str) -> bool {
141
144
  crate::tmux_backend::TmuxBackend::for_tmux_endpoint(socket)
142
145
  .list_targets()
143
- .map(|targets| !targets.iter().any(|target| target.pane_id.as_str() == pane_id))
146
+ .map(|targets| {
147
+ !targets
148
+ .iter()
149
+ .any(|target| target.pane_id.as_str() == pane_id)
150
+ })
144
151
  .unwrap_or(true)
145
152
  }
146
153
 
@@ -2,9 +2,7 @@
2
2
 
3
3
  use std::path::Path;
4
4
 
5
- use crate::packaging::types::{
6
- Blocker, BlockerSource, DoctorGate, PackagingError,
7
- };
5
+ use crate::packaging::types::{Blocker, BlockerSource, DoctorGate, PackagingError};
8
6
 
9
7
  pub mod comms;
10
8
  pub mod orphans;