Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T01:52:40.979Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

omega_executor_disclosure.rs

224 lines · 9.6 KB · rust
1//! Who executed a thread. OMEGA-DELTA-0021.
2//!
3//! Omega presents one chat surface over three executor classes: its own
4//! in-process agent loop, out-of-process ACP agents such as `codex-acp`, and
5//! `omega-effectd` engine lanes. Without disclosure all three look identical to
6//! the reader — output appears in an Omega window and reads as Omega's own
7//! work. That is a false attribution claim, made silently.
8//!
9//! # The record lives in `omega_front_door`, and this is only the binding
10//!
11//! [`omega_front_door::ExecutorDisclosure`] is the typed record. That is
12//! omega#74's binding condition on the owner's identity decision: the agent
13//! does not sign with its own principal, *on the condition that disclosure is
14//! stored as a typed record that a label renders, never as a label string.*
15//! A record of parts can be handed to a signer later; a rendered line cannot,
16//! so storing the line would silently convert a reversible owner decision into
17//! an irreversible one.
18//!
19//! This module holds the part that record deliberately cannot: reading a live
20//! thread. `omega_front_door` is a leaf that depends on nothing, so it cannot
21//! see GPUI, `acp_thread`, or a connection. The extension trait below is that
22//! bridge, and it lives here rather than in `crates/acp_thread` so the upstream
23//! thread type carries no Omega state and a rebase cannot quietly drop it.
24//!
25//! # Why nothing new is persisted
26//!
27//! omega#77's falsifier names a *new* GPUI-owned durable store as a failure,
28//! and its deliverable says the disclosure persists through existing thread
29//! persistence. Every part of the record already has a durable home, so the
30//! record is a projection over them rather than a fourth copy that can drift:
31//!
32//! | Part | Durable home |
33//! | --- | --- |
34//! | class, agent id | the connection, rebuilt from `sidebar_threads.agent_id` |
35//! | provider, model | `DbThread.model`, restored by `Thread::from_db` |
36//! | run ref | `full-auto-host-correlation.json`, reloaded at startup |
37//!
38//! A projection cannot disagree with the thread it describes. A cached copy
39//! can, and a disclosure that disagrees with its executor is worse than none.
40
41use std::rc::Rc;
42
43use acp_thread::{AcpThread, AgentConnection};
44use agent::NativeAgentConnection;
45use agent_client_protocol::schema::v1 as acp;
46use agent_servers::AcpConnection;
47use gpui::App;
48use omega_front_door::{ExecutorClass, ExecutorDisclosure};
49
50/// Read a thread's executor disclosure.
51///
52/// An Omega extension trait over the shared thread type, rather than an
53/// inherent method on it and rather than a fork of it. A rebase that reshapes
54/// `AcpThread` cannot silently drop the disclosure: it would drop the `impl`
55/// below, and this crate would stop compiling.
56pub trait ThreadExecutorDisclosure {
57    /// Who executed this thread, before any engine-lane re-attribution.
58    fn omega_executor_disclosure(&self, cx: &App) -> ExecutorDisclosure;
59}
60
61impl ThreadExecutorDisclosure for AcpThread {
62    fn omega_executor_disclosure(&self, cx: &App) -> ExecutorDisclosure {
63        classify_connection(self.connection().clone(), self.session_id(), cx)
64    }
65}
66
67/// Re-attribute a disclosure to the engine run that owns the thread.
68///
69/// The executing agent's identity is kept. A host-bridge thread really is a
70/// `codex-acp` process underneath, and the honest reading is "this run
71/// delegated to this agent", not "a run did it".
72#[must_use]
73pub fn delegated_to_run(mut disclosure: ExecutorDisclosure, run_ref: String) -> ExecutorDisclosure {
74    disclosure.class = ExecutorClass::EngineLane;
75    disclosure.run_ref = Some(run_ref);
76    disclosure
77}
78
79/// Classify a connection by its concrete type.
80///
81/// A checked downcast, not a name comparison. `agent_id()` is a display-facing
82/// identifier — omega#75 is renaming Omega's own, and an extension can set its
83/// own to anything — so deciding *what ran* from it would make the disclosure a
84/// string match on a label, which is the failure mode this whole surface exists
85/// to avoid.
86///
87/// The fallback is [`ExecutorClass::ExternalAcp`] rather than the native loop,
88/// and that direction is deliberate: `NativeLoop` is the first-party claim, and
89/// an unrecognised connection defaulting to it would present somebody else's
90/// output as Omega's own. Guessing wrong towards "not ours" costs precision;
91/// guessing wrong towards "ours" is the dishonest attribution omega#77 exists
92/// to stop.
93fn classify_connection(
94    connection: Rc<dyn AgentConnection>,
95    session_id: &acp::SessionId,
96    cx: &App,
97) -> ExecutorDisclosure {
98    let agent_id = connection.agent_id().0.to_string();
99
100    if let Some(native) = connection.clone().downcast::<NativeAgentConnection>() {
101        let (provider, model) = native
102            .thread(session_id, cx)
103            .and_then(|thread| {
104                thread.read(cx).model().map(|model| {
105                    (
106                        Some(model.provider_id().0.to_string()),
107                        Some(model.id().0.to_string()),
108                    )
109                })
110            })
111            .unwrap_or((None, None));
112        return ExecutorDisclosure {
113            class: ExecutorClass::NativeLoop,
114            agent_id,
115            provider,
116            model,
117            run_ref: None,
118            route: crate::omega_router::recorded_route(session_id),
119        };
120    }
121
122    // `OMEGA-DELTA-0042`, omega#87. The Exo harness lane. Recognised by its
123    // concrete type for the same reason the native loop is: `agent_id()` on
124    // this connection is *derived from what Exo said about itself*, so
125    // classifying by it would let an Exo install decide its own class.
126    //
127    // Exo reports `ExternalAcp`. The reasoning — and the argument against a
128    // fourth class — is in `omega_exo_lane`'s module documentation. What is
129    // added here over the shared fallback below is the model: Exo does tell
130    // Omega which model served, so the lane says so instead of "not disclosed".
131    if let Some(exo) = connection
132        .clone()
133        .downcast::<crate::omega_exo_connection::ExoHarnessConnection>()
134    {
135        // `None` before Exo has been asked. An identity nobody observed is
136        // absent, never invented.
137        let identity = exo.identity();
138        return ExecutorDisclosure {
139            class: omega_exo_lane::EXO_EXECUTOR_CLASS,
140            agent_id: identity
141                .as_ref()
142                .map_or_else(|| agent_id.clone(), omega_exo_lane::ExoLaneIdentity::agent_id),
143            provider: identity.as_ref().and_then(|identity| identity.provider.clone()),
144            model: identity.and_then(|identity| identity.model),
145            run_ref: None,
146            route: crate::omega_router::recorded_route(session_id),
147        };
148    }
149
150    // `AcpConnection` shares the fallback, but is recognised explicitly so an
151    // unrecognised connection type leaves a trace instead of passing silently.
152    if connection.downcast::<AcpConnection>().is_none() {
153        log::debug!(
154            "OMEGA-DELTA-0021: disclosing {agent_id} as an external ACP agent; \
155             its connection type is not one this build recognises"
156        );
157    }
158
159    ExecutorDisclosure {
160        class: ExecutorClass::ExternalAcp,
161        agent_id,
162        provider: None,
163        model: None,
164        run_ref: None,
165        route: crate::omega_router::recorded_route(session_id),
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172
173    /// OMEGA-DELTA-0021. Delegating to a run keeps the agent that actually ran
174    /// the work, and produces a coherent record.
175    #[test]
176    fn delegating_to_a_run_keeps_the_executing_agent() {
177        let routed = ExecutorDisclosure {
178            class: ExecutorClass::ExternalAcp,
179            agent_id: "codex-acp".into(),
180            provider: None,
181            model: None,
182            run_ref: None,
183            route: Some(omega_front_door::RouteReason::PinHonored),
184        };
185        assert!(routed.is_coherent());
186
187        let delegated = delegated_to_run(routed, "operation.full-auto.77".into());
188        assert_eq!(delegated.class, ExecutorClass::EngineLane);
189        assert_eq!(delegated.agent_id, "codex-acp");
190        assert_eq!(delegated.run_ref.as_deref(), Some("operation.full-auto.77"));
191        assert!(delegated.is_coherent());
192
193        let line = delegated.label();
194        assert!(line.contains("codex-acp"), "{line:?}");
195        assert!(line.contains("engine_lane"), "{line:?}");
196        assert!(line.contains("operation.full-auto.77"), "{line:?}");
197    }
198
199    /// The honest-attribution rule as an oracle: only the native loop is
200    /// Omega's own output, so no routed or delegated record may carry the
201    /// first-party class.
202    #[test]
203    fn a_routed_or_delegated_record_never_claims_the_native_loop() {
204        for class in [ExecutorClass::ExternalAcp, ExecutorClass::EngineLane] {
205            let run_ref = (class == ExecutorClass::EngineLane).then(|| "run.1".to_string());
206            let disclosure = ExecutorDisclosure {
207                class,
208                agent_id: "codex-acp".into(),
209                provider: None,
210                model: None,
211                run_ref,
212                route: Some(omega_front_door::RouteReason::PinHonored),
213            };
214            assert!(disclosure.is_coherent(), "{class:?}");
215            assert_ne!(disclosure.class, ExecutorClass::NativeLoop);
216            assert!(
217                disclosure.label().starts_with(class.token()),
218                "the line must lead with the class that ran the work: {}",
219                disclosure.label()
220            );
221        }
222    }
223}
224
Served at tenant.openagents/omega Member data and write actions are omitted.