Skip to repository content
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T00:55:22.008Z 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.gitRevision diff
a39c3cd4 → 40e567f1diff --git a/script/review-omega-candidate b/script/review-omega-candidate
index b5811d35f0..4e16687a2b 100755
--- a/script/review-omega-candidate
+++ b/script/review-omega-candidate
@@ -7,7 +7,8 @@ producer *claim*, then reproduces every check itself and compares.
77
88 The distinction matters: reading the producer's JSON and confirming it parses
99 is not review, it is proofreading. Everything below is recomputed from the
10-artifact and the installed application.
10+artifact itself. The application it checks is the one inside the candidate
11+disk image, not whatever is installed.
1112
1213 Independence is structural, not declared:
1314
@@ -23,7 +24,7 @@ Independence is structural, not declared:
2324 Usage:
2425 OMEGA_REVIEWER_KEY_FILE=~/work/.secrets/omega-independent-reviewer.env \\
2526 review-omega-candidate \\
26- --candidate-dmg <dmg> --app /Applications/Omega.app \\
27+ --candidate-dmg <dmg> \\
2728 --producer-claim <claim.json> --output <receipt.json>
2829 """
2930
@@ -35,6 +36,8 @@ import json
3536 import os
3637 import subprocess
3738 import sys
39+import tempfile
40+from contextlib import contextmanager
3841 from datetime import datetime, timezone
3942 from pathlib import Path
4043 from typing import Any
@@ -103,6 +106,38 @@ def load_reviewer_key() -> tuple[str, str]:
103106 return secret, public
104107
105108
109+def signing_package_root() -> Path:
110+ """Locate the package whose `node_modules` carry the signing curves.
111+
112+ This was derived from the script's own location, three parents up plus
113+ `openagents/packages/sarah`. That holds only when the reviewer runs from
114+ the canonical omega checkout beside a canonical openagents checkout — and
115+ an independent reviewer is supposed to run from an isolated worktree,
116+ where it raises `FileNotFoundError` from inside `subprocess`. A reviewer
117+ that cannot sign from an isolated tree pushes reviews back into the
118+ producer's directory layout, which is the opposite of the point.
119+
120+ Candidates are tried in order and the first that exists wins, so an
121+ unusual layout can be handled by setting the environment variable rather
122+ than by moving the checkout.
123+ """
124+ override = os.environ.get("OMEGA_REVIEW_SIGNING_PACKAGE")
125+ candidates = [Path(override).expanduser()] if override else []
126+ here = Path(__file__).resolve()
127+ candidates += [
128+ here.parent.parent.parent / "openagents" / "packages" / "sarah",
129+ Path.home() / "work" / "openagents" / "packages" / "sarah",
130+ ]
131+ for candidate in candidates:
132+ if (candidate / "node_modules").is_dir():
133+ return candidate
134+ raise ReviewError(
135+ "cannot find a package providing the signing curves; set "
136+ "OMEGA_REVIEW_SIGNING_PACKAGE to a directory whose node_modules has "
137+ "@noble/curves"
138+ )
139+
140+
106141 def sign(message_hex: str, secret_hex: str) -> str:
107142 """Schnorr-sign the evidence digest with the reviewer key."""
108143 result = subprocess.run(
@@ -121,7 +156,7 @@ def sign(message_hex: str, secret_hex: str) -> str:
121156 ],
122157 capture_output=True,
123158 text=True,
124- cwd=str(Path(__file__).resolve().parent.parent.parent / "openagents" / "packages" / "sarah"),
159+ cwd=str(signing_package_root()),
125160 )
126161 if result.returncode != 0 or len(result.stdout.strip()) != 128:
127162 raise ReviewError(f"reviewer signature failed: {result.stderr.strip()[:200]}")
@@ -137,10 +172,45 @@ def observe(command: list[str]) -> tuple[bool, str]:
137172 return True, (result.stdout + result.stderr)
138173
139174
175+@contextmanager
176+def mounted_candidate(dmg: Path):
177+ """Yield the `Omega.app` inside `dmg`, mounted read-only.
178+
179+ Every check must bind to one artifact. This existed as `--app`, defaulting
180+ to `/Applications/Omega.app`, and two of the four checks read it while the
181+ other two read the disk image. An independent review run exactly as
182+ documented then returned `accepted` with zero disagreements while
183+ `notarization` and `forbidden_strings` were reading a *different candidate*
184+ that happened to be installed — the reviewer caught it only by comparing
185+ `CFBundleVersion`, the host binary digest and the CDHash by hand.
186+
187+ A review that can pass against an artifact nobody named is worse than no
188+ review, so the app is no longer an input. It comes out of the disk image
189+ the claim is about.
190+ """
191+ mount_point = Path(tempfile.mkdtemp(prefix="omega-review-"))
192+ attach = subprocess.run(
193+ ["hdiutil", "attach", "-nobrowse", "-readonly", "-quiet",
194+ "-mountpoint", str(mount_point), str(dmg)],
195+ capture_output=True, text=True,
196+ )
197+ if attach.returncode != 0:
198+ raise ReviewError(f"cannot mount the candidate: {attach.stderr.strip()[:200]}")
199+ try:
200+ apps = sorted(mount_point.glob("*.app"))
201+ if len(apps) != 1:
202+ raise ReviewError(
203+ f"expected exactly one application in the candidate, found {len(apps)}"
204+ )
205+ yield apps[0]
206+ finally:
207+ subprocess.run(["hdiutil", "detach", str(mount_point), "-quiet"],
208+ capture_output=True)
209+
210+
140211 def main() -> int:
141212 parser = argparse.ArgumentParser()
142213 parser.add_argument("--candidate-dmg", type=Path, required=True)
143- parser.add_argument("--app", type=Path, default=Path("/Applications/Omega.app"))
144214 parser.add_argument("--producer-claim", type=Path, required=True)
145215 parser.add_argument("--obligation", default="omega#16")
146216 parser.add_argument("--output", type=Path, required=True)
@@ -186,47 +256,51 @@ def main() -> int:
186256 claim.get("artifactSha256", ""),
187257 )
188258
189- # 2. Gatekeeper's own verdict on the installed application.
190- ran, output = observe(["spctl", "-a", "-vvv", "-t", "exec", str(args.app)])
191- if not ran:
192- inconclusive = True
193- else:
194- notarized = "source=Notarized Developer ID" in output
195- record(
196- "notarization",
197- f"spctl -a -vvv -t exec {args.app}",
198- "notarized" if notarized else "not_notarized",
199- claim.get("notarization", ""),
200- )
259+ # Checks 2 to 4 bind to the application inside the candidate, never to
260+ # whatever happens to be installed. See mounted_candidate().
261+ with mounted_candidate(args.candidate_dmg) as app:
262+ binary = app / "Contents" / "MacOS" / "omega"
263+
264+ # 2. Gatekeeper's own verdict on the candidate's application.
265+ ran, output = observe(["spctl", "-a", "-vvv", "-t", "exec", str(app)])
266+ if not ran:
267+ inconclusive = True
268+ else:
269+ notarized = "source=Notarized Developer ID" in output
270+ record(
271+ "notarization",
272+ f"spctl -a -vvv -t exec <candidate>/{app.name}",
273+ "notarized" if notarized else "not_notarized",
274+ claim.get("notarization", ""),
275+ )
201276
202- # 3. The stapled ticket, checked against the artifact rather than the app,
203- # because the bundler staples the disk image.
204- ran, output = observe(["xcrun", "stapler", "validate", str(args.candidate_dmg)])
205- if not ran:
206- inconclusive = True
207- else:
208- stapled = "The validate action worked" in output
209- record(
210- "stapled_ticket",
211- f"xcrun stapler validate {args.candidate_dmg.name}",
212- "stapled" if stapled else "not_stapled",
213- claim.get("stapled", ""),
214- )
277+ # 3. The stapled ticket on the disk image, because the bundler staples
278+ # the image. The application inside it is stapled separately.
279+ ran, output = observe(["xcrun", "stapler", "validate", str(args.candidate_dmg)])
280+ if not ran:
281+ inconclusive = True
282+ else:
283+ stapled = "The validate action worked" in output
284+ record(
285+ "stapled_ticket",
286+ f"xcrun stapler validate {args.candidate_dmg.name}",
287+ "stapled" if stapled else "not_stapled",
288+ claim.get("stapled", ""),
289+ )
215290
216- # 4. Forbidden strings, scanned from the shipped binary. This is the check
217- # that caught two Zed surfaces a source review had passed.
218- binary = args.app / "Contents" / "MacOS" / "omega"
219- ran, output = observe(["strings", str(binary)])
220- if not ran:
221- inconclusive = True
222- else:
223- found = sorted({needle for needle in FORBIDDEN_STRINGS if needle in output})
224- record(
225- "forbidden_strings",
226- f"strings {binary} | grep -F <forbidden>",
227- ",".join(found) if found else "none",
228- claim.get("forbiddenStrings", ""),
229- )
291+ # 4. Forbidden strings, scanned from the shipped binary. This is the
292+ # check that caught two Zed surfaces a source review had passed.
293+ ran, output = observe(["strings", str(binary)])
294+ if not ran:
295+ inconclusive = True
296+ else:
297+ found = sorted({needle for needle in FORBIDDEN_STRINGS if needle in output})
298+ record(
299+ "forbidden_strings",
300+ f"strings <candidate>/{app.name}/Contents/MacOS/omega | grep -F <forbidden>",
301+ ",".join(found) if found else "none",
302+ claim.get("forbiddenStrings", ""),
303+ )
230304
231305 if inconclusive:
232306 outcome = "inconclusive"