Skip to repository content292 lines · 11.8 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:05:09.828Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
pin.rs
1//! Which Exo. `OMEGA-DELTA-0042`, omega#87.
2//!
3//! Exo declares itself unstable and writes the house rule "do not write
4//! fallback code or handle backwards compatibility" into its own `AGENTS.md`.
5//! `0.1.0`, no tags, nothing published. A lane that said "whatever `exo` is on
6//! `PATH`" would be a lane whose behaviour is decided by somebody else's next
7//! push.
8//!
9//! So the lane names an exact commit, and it names the tree that commit points
10//! at. Both, for the same reason `omega-effectd` is pinned by release tag *and*
11//! asset digest in `script/prove-omega-rc-install`: a commit id alone is
12//! satisfied by a force-pushed branch that still answers to the same forty
13//! characters in a clone nobody re-fetched, and a tree alone produces a refusal
14//! nobody can act on.
15//!
16//! # What this file does and does not pin
17//!
18//! [`EXO_PIN`] is an **identity**: upstream, commit, tree, version. It is the
19//! same on every machine, it is checked in, and it is what a reader compares a
20//! clone against.
21//!
22//! The **bytes that actually run** are a different fact, because Exo has no
23//! release artifact — the install path is `curl setup.sh | bash`, which clones
24//! and builds from source, so two hosts at the same commit hold two different
25//! binaries. Those bytes go through the mechanism that already exists for
26//! exactly this: [`omega_harness::HarnessPinLedger`], under the harness id
27//! [`EXO_HARNESS_ID`], holding a [`MeasuredDigest`] the host computed from the
28//! binary it is about to run.
29//!
30//! [`MeasuredDigest`]: omega_harness::MeasuredDigest
31//!
32//! That split is the whole point. The identity is a claim anyone can check
33//! against upstream; the digest is a measurement only this host can make. They
34//! must not share a type and they must not share a file.
35
36use omega_harness::MeasuredDigest;
37
38/// The harness id the Exo lane is frozen under in the pin ledger.
39///
40/// The same namespace `codex-acp` uses, because Exo is the same kind of thing:
41/// an external harness Omega runs and does not own.
42pub const EXO_HARNESS_ID: &str = "exo";
43
44/// The Exo this lane drives.
45///
46/// **The maintained `OpenAgentsInc/exo` fork of `exoharness/exo`**, the
47/// recursive-self-improvement agent harness. This is not exo labs'
48/// `exo-explore/exo` cluster-inference appliance. The fork contains the ACP
49/// transport that Omega needs while the upstream change is under review.
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51pub struct ExoPin {
52 /// The repository, in full. See the type documentation for why.
53 pub upstream: &'static str,
54 /// The exact commit the lane was audited and driven against.
55 pub source_commit: &'static str,
56 /// The tree that commit points at.
57 pub source_tree: &'static str,
58 /// The workspace version at that commit, for a message a person can read.
59 pub version: &'static str,
60}
61
62/// The pin. Audited in the openagents teardown
63/// `docs/teardowns/2026-07-25-exoharness-exo-teardown.md` and driven for real
64/// by omega#87.
65pub const EXO_PIN: ExoPin = ExoPin {
66 upstream: "https://github.com/OpenAgentsInc/exo",
67 source_commit: "cd7c0d29db869e953fb7261d8390ca93007d36a6",
68 source_tree: "c61846e3f44daaf445930d1a499432ca9b069306",
69 version: "0.1.0",
70};
71
72/// Why a local Exo checkout is not the pinned one.
73#[derive(Clone, Copy, Debug, PartialEq, Eq)]
74pub enum ExoPinMismatch {
75 /// The clone is a different repository. This is the omega#86 failure: the
76 /// other Exo.
77 Upstream,
78 /// The checkout is at a different commit.
79 Commit,
80 /// The checkout is at the pinned commit and the tree underneath it is not
81 /// the pinned tree — a rewritten history, a dirty tree, or a substituted
82 /// object store.
83 Tree,
84 /// The bytes about to run are not the bytes the owner froze.
85 Bytes,
86}
87
88impl std::fmt::Display for ExoPinMismatch {
89 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 formatter.write_str(match self {
91 Self::Upstream => "the Exo checkout is not the maintained exoharness/exo fork",
92 Self::Commit => "the Exo checkout is not at the pinned commit",
93 Self::Tree => "the Exo checkout's tree is not the pinned tree",
94 Self::Bytes => "the Exo binary is not the bytes frozen in the pin ledger",
95 })
96 }
97}
98
99impl std::error::Error for ExoPinMismatch {}
100
101/// What a host observed about a local Exo checkout.
102///
103/// Every field is something the host read: `git config --get remote.origin.url`,
104/// `git rev-parse HEAD`, `git rev-parse HEAD^{tree}`. A record of observations,
105/// which is why it is a separate type from [`ExoPin`], which is a record of
106/// decisions.
107#[derive(Clone, Debug, PartialEq, Eq)]
108pub struct ObservedExoCheckout {
109 /// The remote the checkout came from.
110 pub upstream: String,
111 /// `HEAD`.
112 pub commit: String,
113 /// `HEAD^{tree}`.
114 pub tree: String,
115}
116
117impl ExoPin {
118 /// Whether an observed checkout is the Exo this lane admits.
119 ///
120 /// Upstream is compared after normalising a trailing `.git` and a trailing
121 /// slash, because `https://github.com/exoharness/exo.git` and
122 /// `https://github.com/exoharness/exo` are the same repository and refusing
123 /// one of them would be a cosmetic refusal. `git@github.com:exoharness/exo`
124 /// is *not* normalised into the same string; it is compared by its
125 /// `owner/name` suffix, which is the part that carries the identity.
126 ///
127 /// # Errors
128 ///
129 /// Returns the first thing that differed, most-identifying first: a
130 /// checkout of the wrong repository is reported as the wrong repository
131 /// even though its commit also differs.
132 pub fn admits(&self, observed: &ObservedExoCheckout) -> Result<(), ExoPinMismatch> {
133 if !same_repository(self.upstream, &observed.upstream) {
134 return Err(ExoPinMismatch::Upstream);
135 }
136 if !self
137 .source_commit
138 .eq_ignore_ascii_case(observed.commit.trim())
139 {
140 return Err(ExoPinMismatch::Commit);
141 }
142 if !self.source_tree.eq_ignore_ascii_case(observed.tree.trim()) {
143 return Err(ExoPinMismatch::Tree);
144 }
145 Ok(())
146 }
147}
148
149/// Whether the bytes this host measured are the bytes the owner froze.
150///
151/// Takes the frozen digest as a `&str` and the live one as a [`MeasuredDigest`]
152/// for the reason that type exists: a pin read back from a file is a recorded
153/// claim about a past measurement, and this process did not make it.
154///
155/// An **unfrozen** Exo is admitted, and that is deliberate rather than an
156/// oversight. `codex-acp` behaves the same way: a pin is the owner freezing a
157/// version, not a precondition for running anything at all. What is refused is
158/// a *disagreement* — the case where the owner said "these bytes" and the host
159/// is holding different ones.
160///
161/// # Errors
162///
163/// [`ExoPinMismatch::Bytes`] when a pin exists and the measurement differs.
164pub fn admits_bytes(frozen: Option<&str>, measured: &MeasuredDigest) -> Result<(), ExoPinMismatch> {
165 match frozen {
166 Some(frozen) if !measured.matches_recorded(frozen) => Err(ExoPinMismatch::Bytes),
167 Some(_) | None => Ok(()),
168 }
169}
170
171/// Whether two remote strings name the same repository.
172fn same_repository(pinned: &str, observed: &str) -> bool {
173 normalize_remote(pinned) == normalize_remote(observed)
174}
175
176/// `owner/name`, lowercased, with the transport, host, trailing slash and
177/// `.git` suffix removed.
178fn normalize_remote(remote: &str) -> String {
179 let remote = remote.trim().trim_end_matches('/');
180 let remote = remote.strip_suffix(".git").unwrap_or(remote);
181 let tail = remote.rsplit(['/', ':']).take(2).collect::<Vec<_>>();
182 tail.into_iter()
183 .rev()
184 .collect::<Vec<_>>()
185 .join("/")
186 .to_ascii_lowercase()
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 fn pinned_checkout() -> ObservedExoCheckout {
194 ObservedExoCheckout {
195 upstream: EXO_PIN.upstream.to_string(),
196 commit: EXO_PIN.source_commit.to_string(),
197 tree: EXO_PIN.source_tree.to_string(),
198 }
199 }
200
201 /// The commit and tree are forty hex characters each. A pin that had been
202 /// filled in with a branch name, a tag, or a truncated id would name
203 /// something that can move, which is the whole thing the pin exists to
204 /// stop.
205 #[test]
206 fn the_pin_names_an_exact_commit_and_an_exact_tree() {
207 for value in [EXO_PIN.source_commit, EXO_PIN.source_tree] {
208 assert_eq!(value.len(), 40, "{value} is not a full object id");
209 assert!(
210 value
211 .chars()
212 .all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase()),
213 "{value} is not a lowercase hexadecimal object id"
214 );
215 }
216 assert_ne!(
217 EXO_PIN.source_commit, EXO_PIN.source_tree,
218 "a commit and the tree it points at are different objects"
219 );
220 }
221
222 /// omega#86's failure, as a test. The two Exos share a name and nothing
223 /// else, and the one this lane drives is the harness.
224 #[test]
225 fn the_pin_names_the_harness_exo_and_not_the_cluster_one() {
226 assert_eq!(EXO_PIN.upstream, "https://github.com/OpenAgentsInc/exo");
227 let cluster = ObservedExoCheckout {
228 upstream: "https://github.com/exo-explore/exo".into(),
229 ..pinned_checkout()
230 };
231 assert_eq!(EXO_PIN.admits(&cluster), Err(ExoPinMismatch::Upstream));
232 }
233
234 #[test]
235 fn the_pinned_checkout_is_admitted() {
236 assert_eq!(EXO_PIN.admits(&pinned_checkout()), Ok(()));
237 }
238
239 /// A remote that differs only in `.git`, a trailing slash, case, or SSH
240 /// versus HTTPS transport is the same repository, and refusing it would be
241 /// a refusal about punctuation.
242 #[test]
243 fn the_same_repository_written_four_ways_is_the_same_repository() {
244 for spelling in [
245 "https://github.com/OpenAgentsInc/exo.git",
246 "https://github.com/OpenAgentsInc/exo/",
247 "https://GitHub.com/OpenAgentsInc/Exo",
248 "git@github.com:OpenAgentsInc/exo.git",
249 ] {
250 let observed = ObservedExoCheckout {
251 upstream: spelling.into(),
252 ..pinned_checkout()
253 };
254 assert_eq!(EXO_PIN.admits(&observed), Ok(()), "{spelling}");
255 }
256 }
257
258 /// A moved branch that keeps the commit id it answers to is exactly the
259 /// substitution a commit-only pin cannot see, so the tree is checked too.
260 #[test]
261 fn the_pinned_commit_over_a_different_tree_is_refused() {
262 let rewritten = ObservedExoCheckout {
263 tree: "0000000000000000000000000000000000000000".into(),
264 ..pinned_checkout()
265 };
266 assert_eq!(EXO_PIN.admits(&rewritten), Err(ExoPinMismatch::Tree));
267 }
268
269 #[test]
270 fn a_different_commit_is_refused() {
271 let moved = ObservedExoCheckout {
272 commit: "1111111111111111111111111111111111111111".into(),
273 ..pinned_checkout()
274 };
275 assert_eq!(EXO_PIN.admits(&moved), Err(ExoPinMismatch::Commit));
276 }
277
278 /// The bytes half. An unfrozen harness runs; a frozen one that changed
279 /// underneath the owner does not.
280 #[test]
281 fn frozen_bytes_that_changed_are_refused_and_unfrozen_bytes_run() {
282 let measured = MeasuredDigest::measure(b"the exo binary this host built");
283 assert_eq!(admits_bytes(None, &measured), Ok(()));
284 assert_eq!(admits_bytes(Some(measured.as_str()), &measured), Ok(()));
285 let other = MeasuredDigest::measure(b"a different exo binary");
286 assert_eq!(
287 admits_bytes(Some(other.as_str()), &measured),
288 Err(ExoPinMismatch::Bytes)
289 );
290 }
291}
292