omnilane 0.42.5 → 0.42.7

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.
@@ -29,6 +29,10 @@ APPROVED_REGISTRY_SHA256 = "0782c87de123c02738c3ff60e4bc3c1cc10d110113e872b8f862
29
29
 
30
30
  IDENTITY_FIELDS = ("vendor", "model", "effort", "reasoning", "fallback")
31
31
  TRANSPORT_EVIDENCE_VENDORS = frozenset(("codex", "claude", "grok", "gemini"))
32
+ # How strongly a mapping's probe identified the responder. Reported, never
33
+ # enforced: dispatch turns on runtime_verified alone, as it did before the field
34
+ # existed, so a weaker tier can never refuse a lane that used to run.
35
+ TRANSPORT_EVIDENCE_TIERS = frozenset(("billed-model", "client-echo", "selector-only"))
32
36
  IDENTIFIER = re.compile(r"[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}\Z")
33
37
 
34
38
 
@@ -178,6 +182,7 @@ def apply_transport_overlay(registry: dict[str, Any]) -> None:
178
182
  _check(False, "transport contract evidence changed")
179
183
  stale_vendors.add(vendor)
180
184
  _check(bool(overlay.get("evidence")), "transport overlay requires local evidence")
185
+ tiers: dict[str, str] = {}
181
186
  for mapping in overlay.get("mappings", []):
182
187
  rows = [row for row in registry["scored_configs"] if row["id"] == mapping.get("config_id")]
183
188
  _check(len(rows) == 1, "unknown overlay config")
@@ -197,8 +202,11 @@ def apply_transport_overlay(registry: dict[str, Any]) -> None:
197
202
  _check(mapping["runtime_model"].endswith("-" + row["effort"]), "encoded effort does not match exact tuple")
198
203
  else:
199
204
  _check(mapping.get("runtime_model") == row["model"], "overlay model mismatch")
205
+ tier = mapping.get("evidence_tier", "selector-only")
206
+ _check(tier in TRANSPORT_EVIDENCE_TIERS, "unknown transport evidence tier")
200
207
  if row["vendor"] in stale_vendors:
201
208
  continue
209
+ tiers[row["id"]] = tier
202
210
  row["transport_mapping"].update(
203
211
  status="verified", runtime_verified=True,
204
212
  runtime_model=mapping["runtime_model"], runtime_effort=mapping["runtime_effort"],
@@ -208,6 +216,7 @@ def apply_transport_overlay(registry: dict[str, Any]) -> None:
208
216
  overlay_sha256=digest, overlay_host=overlay["host"],
209
217
  )
210
218
  registry["_stale_transport_vendors"] = sorted(stale_vendors)
219
+ registry["_transport_evidence_tiers"] = tiers
211
220
 
212
221
 
213
222
  def load_registry(path: str | Path, expected_sha256: str | None = None) -> tuple[dict[str, Any], str]:
@@ -332,7 +341,10 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
332
341
  if caller is None:
333
342
  base.update(
334
343
  code="missing-caller-context",
335
- message="provide --caller-context FILE or explicitly assert --operator-asserted-human",
344
+ message=("no caller identity: a model caller runs `omnilane whoami` and passes the "
345
+ "file it prints as --caller-context, which dispatch does itself when the "
346
+ "launching CLI names its model and effort; a human operator passes "
347
+ "--operator-asserted-human"),
336
348
  )
337
349
  return base
338
350
  base["caller_context_sha256"] = caller_sha256
@@ -27,7 +27,9 @@ def retry_args(directory):
27
27
  original_limit = min(rows[0]["score"], original["inherited_ceiling"])
28
28
  current_path = os.environ.get("OMNILANE_AA_CALLER_CONTEXT")
29
29
  current_human = os.environ.get("OMNILANE_AA_OPERATOR_ASSERTED_HUMAN") == "1"
30
- aa_policy._check(bool(current_path) != current_human, "retry requires one current caller context or explicit current human assertion")
30
+ aa_policy._check(bool(current_path) != current_human,
31
+ "retry requires one current caller context or explicit current human "
32
+ "assertion; a model caller gets one from `omnilane whoami`")
31
33
  if current_path:
32
34
  current, _ = aa_policy.load_caller(current_path, registry)
33
35
  rows = aa_policy._matching_rows(registry, current["caller"])
@@ -10,7 +10,9 @@ import argparse
10
10
  import hashlib
11
11
  import json
12
12
  import os
13
+ import shutil
13
14
  import socket
15
+ from collections import Counter
14
16
  from datetime import datetime, timezone
15
17
  from pathlib import Path
16
18
 
@@ -37,13 +39,13 @@ for effort in ["xhigh", "medium"]:
37
39
  PROVEN[f"codex/gpt-5-4-mini" + ("" if effort == "xhigh" else f"-{effort}")] = (
38
40
  "model_and_effort", "gpt-5.4-mini", f"cx-gpt-5_4-mini-{effort}")
39
41
 
40
- PROVEN["grok/grok-4-6"] = ("cli_reasoning_effort", "grok-4.6", "PRIOR:grok-effort-2026-09-07")
42
+ PROVEN["grok/grok-4-6"] = ("cli_reasoning_effort", "grok-4.6", "gk-grok-4_6-high")
41
43
  for effort in ["xhigh", "medium", "low"]:
42
44
  PROVEN[f"grok/grok-4-6-{effort}"] = ("cli_reasoning_effort", "grok-4.6", f"gk-grok-4_6-{effort}")
43
45
  PROVEN["grok/grok-4-5"] = ("cli_reasoning_effort", "grok-4.5", "gk-grok-4_5-high")
44
46
 
45
47
  for cid, rid, ev in [
46
- ("gemini/gemini-3-8-flash", "gemini-3.8-flash-high", "PRIOR:gemini-flash-high"),
48
+ ("gemini/gemini-3-8-flash", "gemini-3.8-flash-high", "agy-gemini-3_8-flash-high"),
47
49
  ("gemini/gemini-3-8-flash-medium", "gemini-3.8-flash-medium", "agy-gemini-3_8-flash-medium"),
48
50
  ("gemini/gemini-3-8-flash-low", "gemini-3.8-flash-low", "agy-gemini-3_8-flash-low"),
49
51
  ("gemini/gemini-3-7-flash", "gemini-3.7-flash-high", "agy-gemini-3_7-flash-high"),
@@ -83,16 +85,32 @@ for effort in ["max", "xhigh", "high", "medium", "low"]:
83
85
  PROVEN["claude/claude-fable-5"] = (
84
86
  "model_and_effort", "claude-fable-5", "cl-claude-fable-5-max")
85
87
 
86
- CORE_EVIDENCE = [
87
- (HOME / ".grok/downloads/grok-1.0.13-macos-aarch64", "grok"),
88
- (REPO / "scripts/runners/run-grok.sh", "grok"),
89
- (HOME / ".codex/packages/standalone/releases/0.153.4-aarch64-apple-darwin/bin/codex", "codex"),
90
- (REPO / "scripts/runners/run-codex.sh", "codex"),
91
- (HOME / ".local/share/claude/versions/2.1.263", "claude"),
92
- (REPO / "scripts/runners/run-claude.sh", "claude"),
93
- (HOME / ".local/bin/agy", "gemini"),
94
- (REPO / "scripts/runners/run-gemini.sh", "gemini"),
95
- ]
88
+ def cli_path(name: str) -> Path:
89
+ """Anchor the executable the runners resolve, not a version pinned here.
90
+
91
+ The runners invoke bare names, so a pinned path can name a binary that has
92
+ not run since the last self-update; the overlay must hash what answers.
93
+ aa_policy opens evidence with O_NOFOLLOW, so this resolves past the symlink.
94
+ """
95
+ found = shutil.which(name)
96
+ if not found:
97
+ raise SystemExit(f"cannot resolve the {name} CLI to anchor its evidence")
98
+ return Path(found).resolve()
99
+
100
+
101
+ def core_evidence() -> list[tuple[Path, str]]:
102
+ """Resolved when a build runs, not at import: a host missing one CLI can
103
+ still load this module to read PROVEN."""
104
+ return [
105
+ (cli_path("grok"), "grok"),
106
+ (REPO / "scripts/runners/run-grok.sh", "grok"),
107
+ (cli_path("codex"), "codex"),
108
+ (REPO / "scripts/runners/run-codex.sh", "codex"),
109
+ (cli_path("claude"), "claude"),
110
+ (REPO / "scripts/runners/run-claude.sh", "claude"),
111
+ (cli_path("agy"), "gemini"),
112
+ (REPO / "scripts/runners/run-gemini.sh", "gemini"),
113
+ ]
96
114
 
97
115
 
98
116
  def sha256(path: Path) -> str:
@@ -116,12 +134,12 @@ def main(argv: list[str] | None = None) -> None:
116
134
 
117
135
  manifest = {"probe_runs": {}}
118
136
  unproven = []
137
+ # Evidence written before 0.42.6 carries no tier; it proved the selector and
138
+ # nothing about who answered, which is exactly what selector-only records.
139
+ tiers: dict[str, str] = {}
119
140
  for cid, (_, _, ev) in sorted(PROVEN.items()):
120
- if ev.startswith("PRIOR:"):
121
- manifest["probe_runs"][cid] = {"source": ev, "note": "verified in the 2026-09-07 Codex run"}
122
- continue
123
141
  entry = {}
124
- for suffix in ("json", "stdout", "stderr"):
142
+ for suffix in ("json", "stdout", "stderr", "rollout", "cli_log"):
125
143
  path = root / "evidence" / f"{ev}.{suffix}"
126
144
  if path.exists():
127
145
  entry[suffix] = {"path": str(path), "sha256": sha256(path)}
@@ -143,6 +161,10 @@ def main(argv: list[str] | None = None) -> None:
143
161
  })
144
162
  # Visibility only: failed evidence must not enter the signed manifest.
145
163
  continue
164
+ tier = descriptor.get("evidence_tier", "selector-only")
165
+ if tier not in ("billed-model", "client-echo", "selector-only"):
166
+ raise SystemExit(f"unknown evidence tier for {cid}: {tier}")
167
+ tiers[cid] = tier
146
168
  manifest["probe_runs"][cid] = entry
147
169
  manifest_path = root / "probe-manifest.json"
148
170
  manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
@@ -159,6 +181,7 @@ def main(argv: list[str] | None = None) -> None:
159
181
  "runtime_effort": row["effort"],
160
182
  "selector_type": selector,
161
183
  "verification": "request-selector-contract",
184
+ "evidence_tier": tiers.get(cid, "selector-only"),
162
185
  }
163
186
  if selector == "cli_reasoning_effort":
164
187
  mapping["cli_flag"] = "--reasoning-effort"
@@ -166,7 +189,7 @@ def main(argv: list[str] | None = None) -> None:
166
189
 
167
190
  evidence = [
168
191
  {"path": str(path), "sha256": sha256(path), "vendor": vendor}
169
- for path, vendor in CORE_EVIDENCE
192
+ for path, vendor in core_evidence()
170
193
  ]
171
194
  evidence.append({"path": str(manifest_path), "sha256": sha256(manifest_path)})
172
195
 
@@ -182,7 +205,9 @@ def main(argv: list[str] | None = None) -> None:
182
205
  }
183
206
  out = root / "transport-contracts.local.json"
184
207
  out.write_text(json.dumps(overlay, indent=2, ensure_ascii=False) + "\n")
208
+ spread = Counter(m["evidence_tier"] for m in mappings)
185
209
  print(f"wrote {out} with {len(mappings)} mappings and {len(evidence)} evidence anchors")
210
+ print(" evidence tiers: " + ", ".join(f"{tier} {count}" for tier, count in sorted(spread.items())))
186
211
 
187
212
 
188
213
  if __name__ == "__main__":
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env python3
2
+ """Read the exact AA caller identity of the CLI this process runs under.
3
+
4
+ Walks up the process tree to the nearest vendor CLI, reads the model and effort
5
+ it was launched with, and maps them onto the one scored configuration they
6
+ select. Launch flags are the harness's request selector: the same class of
7
+ evidence the transport overlay carries, and unlike a hand-written caller-context
8
+ file, not something the model can edit.
9
+
10
+ Prints the path of a caller-context file for that identity. Exits 3 with the
11
+ reason on stderr when it cannot decide. It never guesses: a missing flag, an
12
+ alias, or an identity the frozen registry does not score exactly once is a
13
+ refusal, not a fallback.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import json
19
+ import os
20
+ import subprocess
21
+ import sys
22
+ from pathlib import Path
23
+ from typing import Callable, Optional
24
+
25
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
26
+ import aa_policy # noqa: E402
27
+
28
+ REPO = Path(__file__).resolve().parents[2]
29
+ MAX_DEPTH = 64
30
+ ENCODED_EFFORTS = ("xhigh", "high", "medium", "low")
31
+ Selector = tuple[str, Optional[str], Optional[str]]
32
+ Lookup = Callable[[int], Optional[tuple[int, list[str]]]]
33
+
34
+
35
+ def _vendor(executable: str) -> str | None:
36
+ path = Path(executable)
37
+ name = path.name
38
+ if name == "claude" or (path.parent.name == "versions" and path.parent.parent.name == "claude"):
39
+ return "claude"
40
+ if name == "codex":
41
+ return "codex"
42
+ if name == "grok" or (name.startswith("grok-") and path.parent.name == "downloads"):
43
+ return "grok"
44
+ if name == "agy":
45
+ return "gemini"
46
+ return None
47
+
48
+
49
+ def _flag(argv: list[str], *names: str) -> str | None:
50
+ """The last value given for any of names, as `--name value` or `--name=value`."""
51
+ value = None
52
+ for index, token in enumerate(argv):
53
+ for name in names:
54
+ if token == name and index + 1 < len(argv):
55
+ value = argv[index + 1]
56
+ elif token.startswith(name + "="):
57
+ value = token.split("=", 1)[1]
58
+ return value
59
+
60
+
61
+ def _codex_effort(argv: list[str]) -> str | None:
62
+ effort = None
63
+ for index, token in enumerate(argv[:-1]):
64
+ if token in ("-c", "--config"):
65
+ key, _, value = argv[index + 1].partition("=")
66
+ if key.strip() == "model_reasoning_effort":
67
+ effort = value.strip().strip("'\"")
68
+ return effort
69
+
70
+
71
+ def read_selector(argv: list[str]) -> Selector | None:
72
+ """(vendor, model, effort) when argv launches a vendor CLI, otherwise None."""
73
+ if not argv:
74
+ return None
75
+ vendor = _vendor(argv[0])
76
+ rest = argv[1:]
77
+ if vendor == "claude":
78
+ return vendor, _flag(rest, "--model"), _flag(rest, "--effort")
79
+ if vendor == "codex":
80
+ return vendor, _flag(rest, "-m", "--model"), _codex_effort(rest)
81
+ if vendor == "grok":
82
+ return vendor, _flag(rest, "-m", "--model"), _flag(rest, "--reasoning-effort")
83
+ if vendor == "gemini":
84
+ return vendor, _flag(rest, "--model", "-m"), None
85
+ return None
86
+
87
+
88
+ def resolve(registry: dict, vendor: str, model: str | None,
89
+ effort: str | None) -> tuple[dict | None, str]:
90
+ """The one scored row a launch selector lands on, or None and the reason."""
91
+ if not model:
92
+ return None, f"{vendor} was launched without a model flag"
93
+ if vendor == "gemini" and effort is None:
94
+ base, _, suffix = model.rpartition("-")
95
+ if suffix in ENCODED_EFFORTS:
96
+ model, effort = base, suffix
97
+ if vendor == "codex":
98
+ if effort is None:
99
+ return None, (f"codex was launched without model_reasoning_effort; its configured "
100
+ f"default is not read, so the effort of {model} is unknown")
101
+ if effort == "none":
102
+ effort = None
103
+ rows = [row for row in registry["scored_configs"]
104
+ if row["vendor"] == vendor and row["model"] == model and row["effort"] == effort]
105
+ excluded = []
106
+ if vendor == "claude":
107
+ # ADR-0046: --effort has no reasoning-off value, so a non-reasoning row
108
+ # can never be what a Claude launch selected.
109
+ excluded = [row for row in rows if row["reasoning"] == "non-reasoning"]
110
+ rows = [row for row in rows if row["reasoning"] != "non-reasoning"]
111
+ if len(rows) == 1:
112
+ return rows[0], ""
113
+ if rows:
114
+ return None, f"{vendor} {model} at effort {effort} matches {len(rows)} scored configurations"
115
+ if excluded:
116
+ return None, (f"the only scored {model} row at effort {effort} is non-reasoning, which a "
117
+ f"Claude launch cannot select")
118
+ if vendor == "claude" and effort is None:
119
+ return None, f"{model} was launched without --effort and no default is scored for it"
120
+ return None, f"no scored configuration for {vendor} {model} at effort {effort}"
121
+
122
+
123
+ def _process(pid: int) -> tuple[int, list[str]] | None:
124
+ """(ppid, argv) for pid. /proc keeps argv exact; ps joins it with spaces, so
125
+ argv[0] comes from `comm`, which keeps a path like `Application Support` whole."""
126
+ proc = Path(f"/proc/{pid}")
127
+ if proc.is_dir():
128
+ try:
129
+ argv = [part.decode(errors="replace")
130
+ for part in (proc / "cmdline").read_bytes().split(b"\0") if part]
131
+ ppid = int((proc / "stat").read_text().rsplit(")", 1)[1].split()[1])
132
+ except (OSError, ValueError, IndexError):
133
+ return None
134
+ return ppid, argv
135
+ try:
136
+ head = subprocess.run(["ps", "-o", "ppid=", "-o", "comm=", "-p", str(pid)],
137
+ capture_output=True, text=True, timeout=5).stdout.strip()
138
+ args = subprocess.run(["ps", "-o", "args=", "-p", str(pid)],
139
+ capture_output=True, text=True, timeout=5).stdout.strip()
140
+ except (OSError, subprocess.SubprocessError):
141
+ return None
142
+ parts = head.split(None, 1)
143
+ if len(parts) != 2 or not parts[0].isdigit():
144
+ return None
145
+ comm = parts[1].strip()
146
+ rest = args[len(comm):] if args.startswith(comm) else args.partition(" ")[2]
147
+ return int(parts[0]), [comm, *rest.split()]
148
+
149
+
150
+ def find_launcher(pid: int, lookup: Lookup = _process) -> tuple[int, Selector] | None:
151
+ """The nearest process at or above pid that is a vendor CLI, with its selector.
152
+
153
+ Nearest wins: a codex worker started by a Claude session is a codex caller.
154
+ """
155
+ seen: set[int] = set()
156
+ for _ in range(MAX_DEPTH):
157
+ if pid <= 0 or pid in seen:
158
+ return None
159
+ seen.add(pid)
160
+ entry = lookup(pid)
161
+ if entry is None:
162
+ return None
163
+ ppid, argv = entry
164
+ selector = read_selector(argv)
165
+ if selector is not None:
166
+ return pid, selector
167
+ pid = ppid
168
+ return None
169
+
170
+
171
+ def load_registry(path: str | Path) -> tuple[dict, str]:
172
+ """The approved registry without the transport overlay, which says nothing
173
+ about the caller and must not stop one from learning who it is."""
174
+ saved = {key: os.environ.pop(key)
175
+ for key in ("OMNILANE_AA_TRANSPORT_OVERLAY", "OMNILANE_AA_OVERLAY_SHA256")
176
+ if key in os.environ}
177
+ try:
178
+ return aa_policy.load_registry(path)
179
+ finally:
180
+ os.environ.update(saved)
181
+
182
+
183
+ def write_context(row: dict, registry: dict, home: Path) -> Path:
184
+ """One file per identity: every session launched the same way is the same caller."""
185
+ directory = Path(home) / "caller-context"
186
+ directory.mkdir(parents=True, exist_ok=True)
187
+ path = directory / (row["id"].replace("/", "--") + ".json")
188
+ text = json.dumps({
189
+ "schema_version": 1,
190
+ "snapshot_id": registry["snapshot"]["id"],
191
+ "kind": "model",
192
+ "caller": {key: row[key] for key in aa_policy.IDENTITY_FIELDS},
193
+ "inherited_ceiling": row["score"],
194
+ }, indent=2, sort_keys=True) + "\n"
195
+ try:
196
+ if path.read_text() == text:
197
+ return path
198
+ except OSError:
199
+ pass
200
+ staging = path.with_name(f".{path.name}.{os.getpid()}.tmp")
201
+ staging.write_text(text)
202
+ os.replace(staging, path)
203
+ return path
204
+
205
+
206
+ def main(argv: list[str] | None = None) -> int:
207
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
208
+ parser.add_argument("--registry",
209
+ default=os.environ.get("OMNILANE_AA_POLICY_FILE")
210
+ or str(REPO / "config" / "aa-model-policy.json"),
211
+ help="frozen AA registry (default: the repository copy)")
212
+ args = parser.parse_args(argv)
213
+ try:
214
+ registry, _ = load_registry(args.registry)
215
+ except (aa_policy.PolicyError, OSError, ValueError) as error:
216
+ print(f"omnilane: cannot read the AA registry: {error}", file=sys.stderr)
217
+ return 3
218
+ found = find_launcher(os.getpid())
219
+ if found is None:
220
+ print("omnilane: no vendor CLI among this process's ancestors; a model caller passes "
221
+ "--caller-context FILE and a human operator --operator-asserted-human",
222
+ file=sys.stderr)
223
+ return 3
224
+ pid, (vendor, model, effort) = found
225
+ row, reason = resolve(registry, vendor, model, effort)
226
+ if row is None:
227
+ print(f"omnilane: cannot read the caller identity from pid {pid}: {reason}", file=sys.stderr)
228
+ return 3
229
+ home = Path(os.environ.get("OMNILANE_HOME") or Path.home() / ".omnilane")
230
+ path = write_context(row, registry, home)
231
+ print(f"omnilane: caller is {row['id']} (score {row['score']}), read from pid {pid}",
232
+ file=sys.stderr)
233
+ print(path)
234
+ return 0
235
+
236
+
237
+ if __name__ == "__main__":
238
+ raise SystemExit(main())
@@ -68,17 +68,23 @@ def main() -> None:
68
68
  detail = "; ".join(offenders(Path(overlay_path))) or str(error)
69
69
  emit("FAIL", f"overlay rejected, every dispatch is refused: {error} ({detail})")
70
70
 
71
+ tiers = registry.get("_transport_evidence_tiers", {})
71
72
  verified = Counter()
72
73
  for row in registry["scored_configs"]:
73
74
  if row["transport_mapping"].get("runtime_verified") is True:
74
- verified[row["vendor"]] += 1
75
- summary = ", ".join(f"{v} {n}" for v, n in sorted(verified.items())) or "none"
75
+ verified[row["vendor"], tiers.get(row["id"], "selector-only")] += 1
76
+ summary = ", ".join(f"{vendor} {count} {tier}"
77
+ for (vendor, tier), count in sorted(verified.items())) or "none"
76
78
 
77
79
  import json
78
80
 
79
81
  overlay = json.loads(Path(overlay_path).read_text())
80
82
  unproven = overlay.get("unproven", [])
81
83
  extra = f"; {len(unproven)} config(s) recorded unproven" if unproven else ""
84
+ weak = sorted({vendor for (vendor, tier) in verified if tier == "selector-only"})
85
+ if weak:
86
+ extra += (f"; {', '.join(weak)} prove only the request selector, re-probe to "
87
+ "record who answered")
82
88
 
83
89
  stale = registry.get("_stale_transport_vendors", [])
84
90
  if stale: