1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! The session-control seam the SM drives its fleet through (DOC-14 §2.6).
//!
//! Why: SM-8's delegation loop (§3.4) and the SM-STDIO adapter (§1A.1) both need
//! to drive managed sessions — launch, observe, send, stop — WITHOUT carrying
//! session-lifecycle business logic and WITHOUT a real tmux/workspace in tests.
//! Hiding that surface behind a narrow trait (Dependency Inversion) lets the
//! delegation loop and the dispatcher depend on the trait while production wires
//! the real `DaemonSessionControl` (in `daemon::sm_stdio`) and tests inject a
//! deterministic mock. SM-STDIO originally defined this trait under
//! `daemon::sm_stdio`; SM-8 RELOCATES it here (a feature-independent core
//! location) so the agent-side delegation loop can depend on it too, with
//! `sm_stdio` re-exporting it so its public surface is unchanged.
//! What: [`LaunchParams`] (the launch inputs), [`SessionControlError`] (the typed
//! failure), and [`SessionControl`] — the seven async verbs the spec's session
//! methods need, each returning a plain `serde_json::Value` (the wire result
//! body) or a [`SessionControlError`]. The production `DaemonSessionControl`
//! impl lives in `daemon::sm_stdio::control` (it needs daemon-internal handles);
//! the agent-side mock lives in `agent/delegate/mock_control.rs`.
//! Test: the dispatcher's `sm.sessions.*` round-trips and the SM-8 delegation
//! tests both inject mock impls of this trait.
use async_trait;
/// Inputs for `sessions.launch` (§1A.1: `{ workdir, model?, prompt?, goal_id? }`).
///
/// Why: the spec's launch params differ from the managed-session `SpawnParams`
/// shape (`{ repo_url, ref, task }`); keeping the adapter's own owned input
/// struct lets callers (the dispatcher AND the SM-8 delegation loop) parse the
/// spec params once and hand them to ANY [`SessionControl`] impl (real or mock)
/// without re-deriving the mapping at the call site.
/// What: `workdir` (the directory/repo the session launches against, mapped to
/// the managed `repo_url`), an optional `model` (runtime selector), an optional
/// `prompt` (the task/intent, mapped to the managed `task`), and an optional
/// `goal_id` the caller wants the new session linked to (§9.3).
/// Test: `tests.rs::launch_round_trips` and `delegate` tests construct this.
/// A failure surfaced by a [`SessionControl`] operation.
///
/// Why: callers map these onto JSON-RPC error responses (the dispatcher) or onto
/// goal-link failures (the SM-8 loop); a typed enum lets them choose
/// `INVALID_PARAMS` (bad id) vs `INTERNAL_ERROR` (control failure) by VARIANT
/// rather than string-matching, and keeps the adapter panic-free per the
/// workspace convention.
/// What: [`NotFound`](SessionControlError::NotFound) is reserved for a malformed
/// session id (UUID parse failure) OR a genuinely-absent session
/// (`ManagedError::SessionNotFound`); [`Backend`](SessionControlError::Backend)
/// for any other control-surface failure (provision/tmux/store/invalid-state).
/// Test: `sm_stdio::tests` mock returns both variants; the dispatcher asserts the
/// mapped JSON-RPC code.
/// The narrow session-control surface the SM drives its fleet through (§2.6).
///
/// Why: keeps both `sm.sessions.*` (a thin translation) AND the SM-8 delegation
/// loop decoupled from the concrete managed-session surface. Callers depend on
/// this trait (Dependency Inversion) so production wires `DaemonSessionControl`
/// (the real managed-session surface) while tests wire a deterministic mock with
/// NO tmux/workspace. Every method returns the wire `result` body directly so the
/// dispatcher does no shaping.
/// What: `launch` → `{ session_id }`; `list` → `{ sessions: [...] }`; `get` →
/// the full record JSON; `send` → `{ ok }`; `stop`/`resume`/`kill` → `{ ok }`.
/// All are `Send + Sync` to live behind `Arc<dyn SessionControl>`.
/// Test: `sm_stdio::tests` mock; the SM-8 `delegate` tests mock; the real
/// `DaemonSessionControl` via the managed integration tests.