@team-agent/installer 0.5.60 → 0.5.62
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 +49 -3
- package/crates/team-agent/src/cli/attach_app_server_leader.rs +1 -0
- package/crates/team-agent/src/cli/diagnose.rs +184 -0
- package/crates/team-agent/src/cli/emit.rs +104 -21
- package/crates/team-agent/src/cli/helpers.rs +1 -0
- package/crates/team-agent/src/cli/leader.rs +14 -2
- package/crates/team-agent/src/cli/leaders.rs +2 -0
- package/crates/team-agent/src/cli/mod.rs +296 -8
- package/crates/team-agent/src/cli/named_address.rs +26 -2
- package/crates/team-agent/src/cli/profile.rs +2 -1
- package/crates/team-agent/src/cli/send/coordinator.rs +1 -0
- package/crates/team-agent/src/cli/send/mailbox.rs +3 -0
- package/crates/team-agent/src/cli/send/persist.rs +1 -0
- package/crates/team-agent/src/cli/send/presentation.rs +3 -0
- package/crates/team-agent/src/cli/send/resolve.rs +206 -1
- package/crates/team-agent/src/cli/send.rs +2 -1
- package/crates/team-agent/src/cli/spec.rs +5 -1
- package/crates/team-agent/src/cli/status.rs +2 -1
- package/crates/team-agent/src/cli/status_port/compact.rs +1 -0
- package/crates/team-agent/src/cli/status_port/format.rs +1 -0
- package/crates/team-agent/src/cli/status_port/inbox.rs +1 -0
- package/crates/team-agent/src/cli/status_port/store.rs +7 -3
- package/crates/team-agent/src/cli/tests/named_address.rs +65 -0
- package/crates/team-agent/src/cli/tests/verb_profile.rs +38 -0
- package/crates/team-agent/src/cli/types.rs +36 -2
- package/crates/team-agent/src/communication_mode/mod.rs +54 -0
- package/crates/team-agent/src/compiler/tests.rs +5 -5
- package/crates/team-agent/src/compiler.rs +54 -1
- package/crates/team-agent/src/conpty/backend.rs +1 -0
- package/crates/team-agent/src/conpty/mod.rs +1 -0
- package/crates/team-agent/src/coordinator/backoff.rs +5 -8
- package/crates/team-agent/src/coordinator/conpty_shim.rs +3 -2
- package/crates/team-agent/src/coordinator/health.rs +1 -0
- package/crates/team-agent/src/coordinator/mod.rs +2 -2
- package/crates/team-agent/src/coordinator/orphan.rs +4 -116
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +1 -0
- package/crates/team-agent/src/coordinator/runtime_observation.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +6 -5
- package/crates/team-agent/src/coordinator/steps/delivery.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/health_sync.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/mod.rs +2 -0
- package/crates/team-agent/src/coordinator/steps/persist.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +1 -0
- package/crates/team-agent/src/coordinator/steps/session_gate.rs +1 -0
- package/crates/team-agent/src/coordinator/tests/abnormal.rs +0 -174
- package/crates/team-agent/src/coordinator/tests/api_error_recovery.rs +0 -9
- package/crates/team-agent/src/coordinator/tests/basics.rs +0 -184
- package/crates/team-agent/src/coordinator/tests/mod.rs +2 -17
- package/crates/team-agent/src/coordinator/tests/tick_core.rs +0 -42
- package/crates/team-agent/src/coordinator/tick.rs +24 -28
- package/crates/team-agent/src/coordinator/types.rs +3 -176
- package/crates/team-agent/src/db/agent_health_capture.rs +1 -0
- package/crates/team-agent/src/db/message_store.rs +47 -2
- package/crates/team-agent/src/db/migration.rs +5 -4
- package/crates/team-agent/src/db/mod.rs +1 -0
- package/crates/team-agent/src/db/schema.rs +1 -0
- package/crates/team-agent/src/diagnose/comms.rs +2 -1
- package/crates/team-agent/src/diagnose/mod.rs +1 -0
- package/crates/team-agent/src/diagnose/orphans.rs +1 -0
- package/crates/team-agent/src/fake_worker.rs +21 -1
- package/crates/team-agent/src/layout/manager.rs +3 -7
- package/crates/team-agent/src/layout/mod.rs +2 -2
- package/crates/team-agent/src/layout/overlay.rs +6 -1
- package/crates/team-agent/src/layout/placement.rs +1 -0
- package/crates/team-agent/src/layout/recovery.rs +3 -0
- package/crates/team-agent/src/layout/runtime_sessions.rs +8 -3
- package/crates/team-agent/src/layout/sessions.rs +8 -1
- package/crates/team-agent/src/layout/tmux_endpoint.rs +3 -0
- package/crates/team-agent/src/layout/worker_env.rs +3 -0
- package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
- package/crates/team-agent/src/leader/helpers.rs +1 -0
- package/crates/team-agent/src/leader/incident.rs +1 -0
- package/crates/team-agent/src/leader/lease.rs +27 -22
- package/crates/team-agent/src/leader/mod.rs +2 -3
- package/crates/team-agent/src/leader/owner_bind.rs +13 -3
- package/crates/team-agent/src/leader/provider_attribution.rs +1 -0
- package/crates/team-agent/src/leader/rediscover.rs +4 -17
- package/crates/team-agent/src/leader/registry.rs +3 -15
- package/crates/team-agent/src/leader/start.rs +1072 -186
- package/crates/team-agent/src/leader/takeover.rs +10 -232
- package/crates/team-agent/src/leader/tests/claim_leader_mailbox_flush_contract.rs +544 -0
- package/crates/team-agent/src/leader/tests/historical_inventory_upgrade_gate_red.rs +624 -0
- package/crates/team-agent/src/leader/tests/identity.rs +71 -59
- package/crates/team-agent/src/leader/tests/identity_session_names.rs +42 -0
- package/crates/team-agent/src/leader/tests/idle.rs +0 -193
- package/crates/team-agent/src/leader/tests/lease_api.rs +0 -45
- package/crates/team-agent/src/leader/tests/mod.rs +4 -41
- package/crates/team-agent/src/leader/tests/rehomed_env.rs +83 -0
- package/crates/team-agent/src/leader/tests/team_in_team_state_scope_red.rs +1273 -0
- package/crates/team-agent/src/leader/tests/terminal_and_replay_vs_rerender_invariants_red.rs +417 -0
- package/crates/team-agent/src/leader/tests/wake_start_owner.rs +22 -103
- package/crates/team-agent/src/leader/types.rs +1 -28
- package/crates/team-agent/src/lib.rs +7 -0
- package/crates/team-agent/src/lifecycle/display.rs +7 -1
- package/crates/team-agent/src/lifecycle/helpers.rs +3 -1
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +2 -2
- package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +1 -1
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +2 -2
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +4 -26
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +0 -27
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +2 -28
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +4 -32
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +1 -0
- package/crates/team-agent/src/lifecycle/launch.rs +11 -12
- package/crates/team-agent/src/lifecycle/mod.rs +2 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +4 -4
- package/crates/team-agent/src/lifecycle/restart/common.rs +1 -1
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +2 -2
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +13 -5
- package/crates/team-agent/src/lifecycle/restart/remove.rs +1 -1
- package/crates/team-agent/src/lifecycle/restart/selection.rs +3 -3
- package/crates/team-agent/src/lifecycle/restart.rs +13 -11
- package/crates/team-agent/src/lifecycle/tests/acceptance_b_batch_red.rs +1007 -0
- package/crates/team-agent/src/lifecycle/tests/b0_legacy_snapshot_nonauthority_contract.rs +265 -0
- package/crates/team-agent/src/lifecycle/tests/b0_reader_hideone_audit_contract.rs +459 -0
- package/crates/team-agent/src/lifecycle/tests/behavioral_diff_264_red.rs +849 -0
- package/crates/team-agent/src/lifecycle/tests/claude_compatible_config_red.rs +323 -0
- package/crates/team-agent/src/lifecycle/tests/claude_profile_launch_red.rs +423 -0
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +737 -0
- package/crates/team-agent/src/lifecycle/tests/codex_mcp_approval_inheritance_red.rs +1187 -0
- package/crates/team-agent/src/lifecycle/tests/codex_weak_window_attribution_red.rs +683 -0
- package/crates/team-agent/src/lifecycle/tests/communication_mode_runtime_contract_red.rs +394 -0
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +1856 -0
- package/crates/team-agent/src/lifecycle/tests/core_034_real_red.rs +917 -0
- package/crates/team-agent/src/lifecycle/tests/display_adaptive_red.rs +481 -0
- package/crates/team-agent/src/lifecycle/tests/f032_startup_prompt_best_effort_red.rs +301 -0
- package/crates/team-agent/src/lifecycle/tests/harvest2_a_batch_red.rs +516 -0
- package/crates/team-agent/src/lifecycle/tests/host_cotenant_death_p0_contract.rs +986 -0
- package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +651 -0
- package/crates/team-agent/src/lifecycle/tests/main_preserved.rs +2 -0
- package/crates/team-agent/src/lifecycle/tests/quick_start_worker_readiness_red.rs +332 -0
- package/crates/team-agent/src/lifecycle/tests/realmachine_clusters_1_6_red.rs +846 -0
- package/crates/team-agent/src/lifecycle/tests/realmachine_residual_g1_g4_red.rs +648 -0
- package/crates/team-agent/src/lifecycle/tests/restart_build_before_destroy_0540_contract.rs +910 -0
- package/crates/team-agent/src/lifecycle/tests/restart_liveness_red.rs +630 -0
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +1083 -0
- package/crates/team-agent/src/lifecycle/tests/restart_session_capture_red.rs +1677 -0
- package/crates/team-agent/src/lifecycle/tests/resume_recover_red.rs +410 -0
- package/crates/team-agent/src/lifecycle/tests/stale_team_saveconflict_contract.rs +428 -0
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +1032 -0
- package/crates/team-agent/src/lifecycle/tests/status_credential_redaction_contract.rs +869 -0
- package/crates/team-agent/src/lifecycle/tests/subprep_codex_trust_roundtrip_red.rs +1249 -0
- package/crates/team-agent/src/lifecycle/tests/swallow_batch4_semantics_red.rs +342 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_identity_scope_red.rs +542 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_sibling_quick_start_red.rs +1103 -0
- package/crates/team-agent/src/lifecycle/tests/team_in_team_state_scope_red.rs +1276 -0
- package/crates/team-agent/src/lifecycle/tests/team_key_retirement_roster_red.rs +145 -0
- package/crates/team-agent/src/lifecycle/tests/team_key_retirement_txn_red.rs +603 -0
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +837 -0
- package/crates/team-agent/src/lifecycle/tests/upgrade_compat_0211_red.rs +928 -0
- package/crates/team-agent/src/lifecycle/tests/verify_rs031_window_consistency_red.rs +951 -0
- package/crates/team-agent/src/lifecycle/tests/worker_dangerous_bypass_argv_red.rs +327 -0
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +760 -0
- package/crates/team-agent/src/lifecycle/tests.rs +59 -0
- package/crates/team-agent/src/lifecycle/types.rs +0 -9
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +29 -11
- package/crates/team-agent/src/mcp_server/helpers.rs +1 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/mod.rs +1 -0
- package/crates/team-agent/src/mcp_server/lifecycle_tools/state_status.rs +1 -0
- package/crates/team-agent/src/mcp_server/mod.rs +1 -0
- package/crates/team-agent/src/mcp_server/normalize.rs +5 -3
- package/crates/team-agent/src/mcp_server/tests/send.rs +26 -0
- package/crates/team-agent/src/mcp_server/tests/wire.rs +1 -1
- package/crates/team-agent/src/mcp_server/tools.rs +101 -66
- package/crates/team-agent/src/mcp_server/types.rs +6 -18
- package/crates/team-agent/src/mcp_server/wire.rs +32 -26
- package/crates/team-agent/src/messaging/activity.rs +1 -0
- package/crates/team-agent/src/messaging/address.rs +1 -0
- package/crates/team-agent/src/messaging/delivery.rs +109 -41
- package/crates/team-agent/src/messaging/helpers.rs +2 -1
- package/crates/team-agent/src/messaging/leader_channel.rs +34 -10
- package/crates/team-agent/src/messaging/leader_receiver.rs +42 -24
- package/crates/team-agent/src/messaging/mod.rs +10 -14
- package/crates/team-agent/src/messaging/peers.rs +2 -0
- package/crates/team-agent/src/messaging/persist.rs +3 -1
- package/crates/team-agent/src/messaging/presentation.rs +111 -1
- package/crates/team-agent/src/messaging/results.rs +166 -17
- package/crates/team-agent/src/messaging/scheduler.rs +1 -0
- package/crates/team-agent/src/messaging/selftest.rs +1 -1
- package/crates/team-agent/src/messaging/send.rs +135 -89
- package/crates/team-agent/src/messaging/tests/leader_channel.rs +6 -6
- package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +187 -0
- package/crates/team-agent/src/messaging/tests/mod.rs +5 -0
- package/crates/team-agent/src/messaging/tests/runtime.rs +13 -6
- package/crates/team-agent/src/messaging/types.rs +7 -2
- package/crates/team-agent/src/messaging/watchers.rs +24 -13
- package/crates/team-agent/src/model/enums.rs +1 -0
- package/crates/team-agent/src/model/errors.rs +1 -0
- package/crates/team-agent/src/model/ids.rs +1 -0
- package/crates/team-agent/src/model/mod.rs +2 -0
- package/crates/team-agent/src/model/name_similarity.rs +1 -0
- package/crates/team-agent/src/model/pane_authority_refusal.rs +359 -0
- package/crates/team-agent/src/model/paths.rs +1 -0
- package/crates/team-agent/src/model/permissions.rs +3 -2
- package/crates/team-agent/src/model/routing.rs +1 -0
- package/crates/team-agent/src/model/spec.rs +17 -0
- package/crates/team-agent/src/model/task_graph.rs +1 -0
- package/crates/team-agent/src/model/yaml/tests.rs +1 -0
- package/crates/team-agent/src/model/yaml.rs +1 -0
- package/crates/team-agent/src/packaging/install.rs +9 -147
- package/crates/team-agent/src/packaging/migrate.rs +2 -0
- package/crates/team-agent/src/packaging/mod.rs +1 -0
- package/crates/team-agent/src/packaging/repair.rs +2 -0
- package/crates/team-agent/src/packaging/tests.rs +29 -218
- package/crates/team-agent/src/packaging/types.rs +8 -15
- package/crates/team-agent/src/platform/argv.rs +4 -0
- package/crates/team-agent/src/platform/errors.rs +10 -1
- package/crates/team-agent/src/platform/file_lock.rs +4 -157
- package/crates/team-agent/src/platform/mod.rs +0 -61
- package/crates/team-agent/src/platform/process.rs +1 -0
- package/crates/team-agent/src/provider/adapter.rs +1 -0
- package/crates/team-agent/src/provider/adapters/claude.rs +1 -0
- package/crates/team-agent/src/provider/adapters/claude_fork.rs +1 -0
- package/crates/team-agent/src/provider/adapters/codex.rs +1 -0
- package/crates/team-agent/src/provider/adapters/copilot.rs +1 -0
- package/crates/team-agent/src/provider/adapters/copilot_fork.rs +1 -0
- package/crates/team-agent/src/provider/adapters/fake.rs +1 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +1 -0
- package/crates/team-agent/src/provider/approvals/mod.rs +1 -0
- package/crates/team-agent/src/provider/approvals/parsing.rs +2 -5
- package/crates/team-agent/src/provider/approvals/runtime_prompts.rs +6 -5
- package/crates/team-agent/src/provider/classify.rs +1 -0
- package/crates/team-agent/src/provider/faults.rs +1 -26
- package/crates/team-agent/src/provider/helpers.rs +1 -0
- package/crates/team-agent/src/provider/mod.rs +1 -1
- package/crates/team-agent/src/provider/session/capture.rs +41 -22
- package/crates/team-agent/src/provider/session/context_fork/claude.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork/codex.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork/outcome.rs +1 -0
- package/crates/team-agent/src/provider/session/context_fork.rs +1 -0
- package/crates/team-agent/src/provider/session/mod.rs +2 -4
- package/crates/team-agent/src/provider/session/resume.rs +2 -209
- package/crates/team-agent/src/provider/session_scan/claude.rs +93 -3
- package/crates/team-agent/src/provider/session_scan/codex.rs +1 -0
- package/crates/team-agent/src/provider/session_scan/common.rs +24 -7
- package/crates/team-agent/src/provider/session_scan/copilot.rs +1 -0
- package/crates/team-agent/src/provider/session_scan.rs +6 -42
- package/crates/team-agent/src/provider/startup_prompt.rs +1 -0
- package/crates/team-agent/src/provider/types.rs +1 -0
- package/crates/team-agent/src/provider/wire.rs +1 -0
- package/crates/team-agent/src/state/identity.rs +16 -5
- package/crates/team-agent/src/state/identity_keys.rs +1 -0
- package/crates/team-agent/src/state/mod.rs +2 -0
- package/crates/team-agent/src/state/owner_gate.rs +5 -0
- package/crates/team-agent/src/state/ownership.rs +10 -4
- package/crates/team-agent/src/state/paths.rs +12 -0
- package/crates/team-agent/src/state/persist.rs +9 -3
- package/crates/team-agent/src/state/projection.rs +15 -2
- package/crates/team-agent/src/state/repository/intent.rs +1 -0
- package/crates/team-agent/src/state/repository/tests.rs +1 -0
- package/crates/team-agent/src/state/repository.rs +7 -0
- package/crates/team-agent/src/state/selector.rs +1 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +39 -0
- package/crates/team-agent/src/tmux_backend.rs +63 -0
- package/crates/team-agent/src/topology.rs +3 -0
- package/crates/team-agent/src/transport.rs +15 -0
- package/package.json +4 -4
- package/skills/team-agent/command-coverage.json +379 -0
- package/crates/team-agent/src/leader/inject.rs +0 -33
- package/crates/team-agent/src/provider/command.rs +0 -80
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! Typed presentation metadata shared by message and result ingress.
|
|
2
3
|
|
|
3
4
|
use serde::{Deserialize, Serialize};
|
|
@@ -98,6 +99,12 @@ pub struct PresentationDecision {
|
|
|
98
99
|
pub policy_version: String,
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
103
|
+
pub struct SendPresentationInput {
|
|
104
|
+
pub request: PresentationRequest,
|
|
105
|
+
pub deprecation: Option<String>,
|
|
106
|
+
}
|
|
107
|
+
|
|
101
108
|
impl Default for PresentationRequest {
|
|
102
109
|
fn default() -> Self {
|
|
103
110
|
Self {
|
|
@@ -177,7 +184,80 @@ pub fn normalize_report_presentation(
|
|
|
177
184
|
(request, None)
|
|
178
185
|
}
|
|
179
186
|
|
|
180
|
-
|
|
187
|
+
/// Normalize the one-bit send surface and the temporary S-011 compatibility
|
|
188
|
+
/// input into the existing presentation disposition primitive.
|
|
189
|
+
///
|
|
190
|
+
/// S-011 sensitive: if the compatibility period is ended by a hard-cut
|
|
191
|
+
/// decision, replace this table with one uniform legacy-input refusal.
|
|
192
|
+
pub fn normalize_send_presentation(
|
|
193
|
+
mailbox: Option<&Value>,
|
|
194
|
+
legacy_presentation: Option<&Value>,
|
|
195
|
+
) -> Result<SendPresentationInput, String> {
|
|
196
|
+
if mailbox.is_some() && legacy_presentation.is_some() {
|
|
197
|
+
return Err("mailbox_conflicts_with_deprecated_presentation".to_string());
|
|
198
|
+
}
|
|
199
|
+
if let Some(mailbox) = mailbox {
|
|
200
|
+
let Some(mailbox) = mailbox.as_bool() else {
|
|
201
|
+
return Err("mailbox_must_be_boolean".to_string());
|
|
202
|
+
};
|
|
203
|
+
return Ok(SendPresentationInput {
|
|
204
|
+
request: PresentationRequest {
|
|
205
|
+
sink: if mailbox {
|
|
206
|
+
PresentationSink::Casefile
|
|
207
|
+
} else {
|
|
208
|
+
PresentationSink::Leader
|
|
209
|
+
},
|
|
210
|
+
class: PresentationClass::Message,
|
|
211
|
+
case_id: None,
|
|
212
|
+
},
|
|
213
|
+
deprecation: None,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
let Some(legacy) = legacy_presentation else {
|
|
217
|
+
return Ok(SendPresentationInput {
|
|
218
|
+
request: PresentationRequest::default(),
|
|
219
|
+
deprecation: None,
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
let Some(object) = legacy.as_object() else {
|
|
223
|
+
return Err("malformed_presentation".to_string());
|
|
224
|
+
};
|
|
225
|
+
let Some(class) = object.get("class").and_then(Value::as_str) else {
|
|
226
|
+
return Err("missing_class".to_string());
|
|
227
|
+
};
|
|
228
|
+
let Some(class) = PresentationClass::parse(class) else {
|
|
229
|
+
return Err(format!("unknown_class:{class}"));
|
|
230
|
+
};
|
|
231
|
+
let sink = match class {
|
|
232
|
+
PresentationClass::Message | PresentationClass::Blocking | PresentationClass::Timeout => {
|
|
233
|
+
PresentationSink::Leader
|
|
234
|
+
}
|
|
235
|
+
PresentationClass::Progress => PresentationSink::Casefile,
|
|
236
|
+
PresentationClass::StageResult
|
|
237
|
+
| PresentationClass::StagePass
|
|
238
|
+
| PresentationClass::Bounce
|
|
239
|
+
| PresentationClass::FinalReview => {
|
|
240
|
+
return Err(format!(
|
|
241
|
+
"deprecated_message_class:{}_requires_result_route",
|
|
242
|
+
class.as_str()
|
|
243
|
+
));
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
Ok(SendPresentationInput {
|
|
247
|
+
request: PresentationRequest {
|
|
248
|
+
sink,
|
|
249
|
+
class: PresentationClass::Message,
|
|
250
|
+
case_id: None,
|
|
251
|
+
},
|
|
252
|
+
deprecation: Some(format!(
|
|
253
|
+
"message-class={} is deprecated; use mailbox={} instead",
|
|
254
|
+
class.as_str(),
|
|
255
|
+
sink != PresentationSink::Leader
|
|
256
|
+
)),
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
pub(crate) fn normalize_presentation(value: Option<&Value>) -> (PresentationRequest, Option<String>) {
|
|
181
261
|
let Some(value) = value else {
|
|
182
262
|
return (PresentationRequest::default(), None);
|
|
183
263
|
};
|
|
@@ -304,4 +384,34 @@ mod tests {
|
|
|
304
384
|
"send normalization remains unchanged"
|
|
305
385
|
);
|
|
306
386
|
}
|
|
387
|
+
|
|
388
|
+
#[test]
|
|
389
|
+
fn send_mailbox_and_s011_compatibility_map_to_one_bit() {
|
|
390
|
+
let mailbox = normalize_send_presentation(Some(&json!(true)), None).unwrap();
|
|
391
|
+
assert_eq!(mailbox.request.sink, PresentationSink::Casefile);
|
|
392
|
+
assert_eq!(mailbox.deprecation, None);
|
|
393
|
+
|
|
394
|
+
for (class, sink) in [
|
|
395
|
+
("message", PresentationSink::Leader),
|
|
396
|
+
("progress", PresentationSink::Casefile),
|
|
397
|
+
("blocking", PresentationSink::Leader),
|
|
398
|
+
("timeout", PresentationSink::Leader),
|
|
399
|
+
] {
|
|
400
|
+
let legacy = json!({"sink": "silent", "class": class});
|
|
401
|
+
let mapped = normalize_send_presentation(None, Some(&legacy)).unwrap();
|
|
402
|
+
assert_eq!(mapped.request.sink, sink, "{class}");
|
|
403
|
+
assert!(mapped.deprecation.is_some(), "{class}");
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
#[test]
|
|
408
|
+
fn s011_stage_classes_require_result_route() {
|
|
409
|
+
for class in ["stage_result", "stage_pass", "bounce", "final_review"] {
|
|
410
|
+
let legacy = json!({"sink": "leader", "class": class});
|
|
411
|
+
assert_eq!(
|
|
412
|
+
normalize_send_presentation(None, Some(&legacy)).unwrap_err(),
|
|
413
|
+
format!("deprecated_message_class:{class}_requires_result_route")
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
307
417
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//!
|
|
1
2
|
//! results.py — collect + report_result + envelope 校验编排 (card §66/§67)。
|
|
2
3
|
|
|
3
4
|
use std::path::{Path, PathBuf};
|
|
@@ -14,6 +15,95 @@ use super::MessagingError;
|
|
|
14
15
|
use crate::model::ids::TaskId;
|
|
15
16
|
use crate::state::projection::OwnerTeamResolution;
|
|
16
17
|
|
|
18
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
19
|
+
pub enum ResultRoute {
|
|
20
|
+
Leader,
|
|
21
|
+
Pipeline,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl ResultRoute {
|
|
25
|
+
pub const ALL: [Self; 2] = [Self::Leader, Self::Pipeline];
|
|
26
|
+
|
|
27
|
+
pub const fn as_str(self) -> &'static str {
|
|
28
|
+
match self {
|
|
29
|
+
Self::Leader => "leader",
|
|
30
|
+
Self::Pipeline => "pipeline",
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pub fn parse(value: &str) -> Option<Self> {
|
|
35
|
+
match value {
|
|
36
|
+
"leader" => Some(Self::Leader),
|
|
37
|
+
"pipeline" => Some(Self::Pipeline),
|
|
38
|
+
_ => None,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
impl Default for ResultRoute {
|
|
44
|
+
fn default() -> Self {
|
|
45
|
+
Self::Leader
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub fn results_for_case(
|
|
50
|
+
workspace: &Path,
|
|
51
|
+
case_id: &str,
|
|
52
|
+
owner_team_id: Option<&str>,
|
|
53
|
+
requested_owner_team_id: Option<&str>,
|
|
54
|
+
) -> Result<Vec<serde_json::Value>, MessagingError> {
|
|
55
|
+
let current_db = workspace.join(".team/runtime/team.db");
|
|
56
|
+
let legacy_db = workspace.join(".team/team.db");
|
|
57
|
+
if current_db.exists() {
|
|
58
|
+
return results_for_case_in_db(
|
|
59
|
+
¤t_db,
|
|
60
|
+
case_id,
|
|
61
|
+
owner_team_id,
|
|
62
|
+
requested_owner_team_id,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if legacy_db.exists() {
|
|
66
|
+
return results_for_case_in_db(&legacy_db, case_id, owner_team_id, requested_owner_team_id);
|
|
67
|
+
}
|
|
68
|
+
Ok(Vec::new())
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
fn results_for_case_in_db(
|
|
72
|
+
db_path: &Path,
|
|
73
|
+
case_id: &str,
|
|
74
|
+
owner_team_id: Option<&str>,
|
|
75
|
+
requested_owner_team_id: Option<&str>,
|
|
76
|
+
) -> Result<Vec<serde_json::Value>, MessagingError> {
|
|
77
|
+
let conn = crate::db::schema::open_db(db_path)?;
|
|
78
|
+
// The second predicate works around
|
|
79
|
+
// `.team/bugs/BUG-caseid-writable-when-route-undeclared-20260730.md`;
|
|
80
|
+
// it is not design intent.
|
|
81
|
+
let case_predicate = "task_id = ?1 or json_extract(envelope,'$.presentation.case_id') = ?1";
|
|
82
|
+
let sql = match owner_team_id {
|
|
83
|
+
Some(_) => format!(
|
|
84
|
+
"select envelope from results where ({case_predicate}) \
|
|
85
|
+
and (owner_team_id = ?2 or owner_team_id = ?3) \
|
|
86
|
+
order by created_at, result_id"
|
|
87
|
+
),
|
|
88
|
+
None => format!(
|
|
89
|
+
"select envelope from results where {case_predicate} order by created_at, result_id"
|
|
90
|
+
),
|
|
91
|
+
};
|
|
92
|
+
let mut stmt = conn.prepare(&sql)?;
|
|
93
|
+
let row_mapper = |row: &rusqlite::Row<'_>| row.get::<_, String>(0);
|
|
94
|
+
let rows = match (owner_team_id, requested_owner_team_id) {
|
|
95
|
+
(Some(team), Some(requested_team)) => {
|
|
96
|
+
stmt.query_map(params![case_id, team, requested_team], row_mapper)
|
|
97
|
+
}
|
|
98
|
+
(Some(team), None) => stmt.query_map(params![case_id, team, team], row_mapper),
|
|
99
|
+
(None, _) => stmt.query_map(params![case_id], row_mapper),
|
|
100
|
+
}?
|
|
101
|
+
.collect::<Result<Vec<_>, _>>()?;
|
|
102
|
+
rows.into_iter()
|
|
103
|
+
.map(|envelope| serde_json::from_str(&envelope).map_err(MessagingError::from))
|
|
104
|
+
.collect()
|
|
105
|
+
}
|
|
106
|
+
|
|
17
107
|
/// `collect` (`results.py:45`):投递 pending、捞 uncollected results、校验 envelope、更新任务态、
|
|
18
108
|
/// 写 team_state、ensure coordinator。CLI `collect` + coordinator tick 调。
|
|
19
109
|
pub fn collect(
|
|
@@ -627,18 +717,12 @@ fn report_result_for_owner_team_inner(
|
|
|
627
717
|
explicit_owner_team: Option<&str>,
|
|
628
718
|
fallback_primary_error: Option<&str>,
|
|
629
719
|
) -> Result<serde_json::Value, MessagingError> {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
return Err(MessagingError::Validation(format!(
|
|
635
|
-
"invalid presentation: {error}"
|
|
636
|
-
)));
|
|
720
|
+
if envelope.get("result_route").is_some() {
|
|
721
|
+
return Err(MessagingError::Validation(
|
|
722
|
+
"report_result result_route is task-owned and cannot be set by a worker".to_string(),
|
|
723
|
+
));
|
|
637
724
|
}
|
|
638
|
-
|
|
639
|
-
&presentation_request,
|
|
640
|
-
super::presentation::PresentationSource::ReportResult,
|
|
641
|
-
);
|
|
725
|
+
validate_result_envelope(envelope)?;
|
|
642
726
|
let store = MessageStore::open(workspace)?;
|
|
643
727
|
let result_id = envelope
|
|
644
728
|
.get("result_id")
|
|
@@ -656,12 +740,6 @@ fn report_result_for_owner_team_inner(
|
|
|
656
740
|
);
|
|
657
741
|
}
|
|
658
742
|
}
|
|
659
|
-
if let Some(obj) = stored.as_object_mut() {
|
|
660
|
-
obj.insert(
|
|
661
|
-
"presentation".to_string(),
|
|
662
|
-
serde_json::to_value(&presentation)?,
|
|
663
|
-
);
|
|
664
|
-
}
|
|
665
743
|
let conn = crate::db::schema::open_db(store.db_path())?;
|
|
666
744
|
let state_for_owner =
|
|
667
745
|
crate::state::persist::load_runtime_state(workspace).unwrap_or(serde_json::json!({}));
|
|
@@ -669,6 +747,42 @@ fn report_result_for_owner_team_inner(
|
|
|
669
747
|
.filter(|team| !team.is_empty())
|
|
670
748
|
.map(str::to_string)
|
|
671
749
|
.unwrap_or_else(|| super::leader_receiver::active_team_key(workspace, &state_for_owner));
|
|
750
|
+
let (result_route, route_declared) = task_result_route(&state_for_owner, &owner_team, task_id)?;
|
|
751
|
+
let presentation = if route_declared {
|
|
752
|
+
let request = super::presentation::PresentationRequest {
|
|
753
|
+
sink: match result_route {
|
|
754
|
+
ResultRoute::Leader => super::presentation::PresentationSink::Leader,
|
|
755
|
+
ResultRoute::Pipeline => super::presentation::PresentationSink::Casefile,
|
|
756
|
+
},
|
|
757
|
+
class: match result_route {
|
|
758
|
+
ResultRoute::Leader => super::presentation::PresentationClass::Message,
|
|
759
|
+
ResultRoute::Pipeline => super::presentation::PresentationClass::StageResult,
|
|
760
|
+
},
|
|
761
|
+
case_id: (result_route == ResultRoute::Pipeline).then(|| task_id.to_string()),
|
|
762
|
+
};
|
|
763
|
+
super::presentation::decide_presentation(
|
|
764
|
+
&request,
|
|
765
|
+
super::presentation::PresentationSource::ReportResult,
|
|
766
|
+
)
|
|
767
|
+
} else {
|
|
768
|
+
let (request, error) =
|
|
769
|
+
super::presentation::normalize_report_presentation(envelope.get("presentation"));
|
|
770
|
+
if let Some(error) = error {
|
|
771
|
+
return Err(MessagingError::Validation(format!(
|
|
772
|
+
"invalid presentation: {error}"
|
|
773
|
+
)));
|
|
774
|
+
}
|
|
775
|
+
super::presentation::decide_presentation(
|
|
776
|
+
&request,
|
|
777
|
+
super::presentation::PresentationSource::ReportResult,
|
|
778
|
+
)
|
|
779
|
+
};
|
|
780
|
+
if let Some(obj) = stored.as_object_mut() {
|
|
781
|
+
obj.insert(
|
|
782
|
+
"presentation".to_string(),
|
|
783
|
+
serde_json::to_value(&presentation)?,
|
|
784
|
+
);
|
|
785
|
+
}
|
|
672
786
|
let inserted = insert_result_if_absent(
|
|
673
787
|
&conn,
|
|
674
788
|
&result_id,
|
|
@@ -968,6 +1082,8 @@ fn report_result_for_owner_team_inner(
|
|
|
968
1082
|
let leader_notified = matches!(outcome.status, crate::messaging::DeliveryStatus::Delivered);
|
|
969
1083
|
let notification_status_wire = if leader_notified {
|
|
970
1084
|
"delivered"
|
|
1085
|
+
} else if outcome.channel.as_deref() == Some("leader_receipt_source_unavailable") {
|
|
1086
|
+
"injected_awaiting_receipt"
|
|
971
1087
|
} else if outcome.channel.as_deref() == Some("leader_acceptance_pending") {
|
|
972
1088
|
"submitted_pending_acceptance"
|
|
973
1089
|
} else if outcome.channel.as_deref() == Some("rebind_required")
|
|
@@ -1045,6 +1161,39 @@ fn report_result_for_owner_team_inner(
|
|
|
1045
1161
|
Ok(serde_json::Value::Object(out))
|
|
1046
1162
|
}
|
|
1047
1163
|
|
|
1164
|
+
fn task_result_route(
|
|
1165
|
+
state: &serde_json::Value,
|
|
1166
|
+
owner_team: &str,
|
|
1167
|
+
task_id: &str,
|
|
1168
|
+
) -> Result<(ResultRoute, bool), MessagingError> {
|
|
1169
|
+
let scoped_tasks = state
|
|
1170
|
+
.get("teams")
|
|
1171
|
+
.and_then(|teams| teams.get(owner_team))
|
|
1172
|
+
.and_then(|team| team.get("tasks"))
|
|
1173
|
+
.and_then(serde_json::Value::as_array);
|
|
1174
|
+
let top_level_tasks = state.get("tasks").and_then(serde_json::Value::as_array);
|
|
1175
|
+
let task = scoped_tasks
|
|
1176
|
+
.into_iter()
|
|
1177
|
+
.flatten()
|
|
1178
|
+
.chain(top_level_tasks.into_iter().flatten())
|
|
1179
|
+
.find(|task| task.get("id").and_then(serde_json::Value::as_str) == Some(task_id));
|
|
1180
|
+
let Some(route) = task.and_then(|task| task.get("result_route")) else {
|
|
1181
|
+
return Ok((ResultRoute::default(), false));
|
|
1182
|
+
};
|
|
1183
|
+
let route = route.as_str().ok_or_else(|| {
|
|
1184
|
+
MessagingError::Validation(format!(
|
|
1185
|
+
"task {task_id} has non-string result_route and cannot accept results"
|
|
1186
|
+
))
|
|
1187
|
+
})?;
|
|
1188
|
+
ResultRoute::parse(route)
|
|
1189
|
+
.map(|route| (route, true))
|
|
1190
|
+
.ok_or_else(|| {
|
|
1191
|
+
MessagingError::Validation(format!(
|
|
1192
|
+
"task {task_id} has unknown result_route {route:?} and cannot accept results"
|
|
1193
|
+
))
|
|
1194
|
+
})
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1048
1197
|
fn copy_report_attribution_fields(
|
|
1049
1198
|
envelope: &serde_json::Value,
|
|
1050
1199
|
out: &mut serde_json::Map<String, serde_json::Value>,
|
|
@@ -291,7 +291,7 @@ fn message_owner_team(db_path: &Path, message_id: &str) -> Result<Option<String>
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
/// `evaluate_idle_behavior` (`diagnose/comms.py:50`):idle 分类准确性评估。零 token,走 driver。
|
|
294
|
-
pub fn evaluate_idle_behavior(
|
|
294
|
+
pub(crate) fn evaluate_idle_behavior(
|
|
295
295
|
workspace: &Path,
|
|
296
296
|
agent_id: &str,
|
|
297
297
|
claimed_status: &str,
|