omnilane 0.42.9 → 0.45.0

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.
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env python3
2
+ """Add eligible_lanes to a refused AA decision.
3
+
4
+ A refusal that only says no leaves a model caller guessing. This reads the
5
+ decision on stdin and appends the lanes whose chain still holds a target at or
6
+ below the caller's effective ceiling, by registry score alone: no CLI is probed
7
+ and nothing is dispatched. Output is one JSON line, the decision plus the list.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import json
13
+ import shlex
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
18
+ import aa_policy # noqa: E402
19
+ import caller_identity # noqa: E402
20
+
21
+
22
+ def lanes(paths: list[Path]) -> dict[str, list[list[str]]]:
23
+ """Lane -> chain segments; the first file naming a lane wins, as in dispatch."""
24
+ table: dict[str, list[list[str]]] = {}
25
+ for path in paths:
26
+ try:
27
+ text = path.read_text(encoding="utf-8")
28
+ except OSError:
29
+ continue
30
+ for line in text.splitlines():
31
+ line = line.split("#", 1)[0]
32
+ if not line.strip() or line[0] in " \t" or ":" not in line:
33
+ continue
34
+ name, chain = line.split(":", 1)
35
+ name = name.strip()
36
+ if not name or name in table or not chain.strip():
37
+ continue
38
+ segments = []
39
+ for segment in chain.split("|"):
40
+ try:
41
+ fields = shlex.split(segment)
42
+ except ValueError:
43
+ fields = []
44
+ if fields:
45
+ segments.append(fields)
46
+ table[name] = segments
47
+ return table
48
+
49
+
50
+ def eligible(registry: dict, table: dict[str, list[list[str]]], ceiling: int) -> list[dict]:
51
+ found = []
52
+ for lane, segments in table.items():
53
+ for fields in segments:
54
+ vendor = fields[0]
55
+ if vendor in ("off", "vote") or len(fields) < 2:
56
+ continue
57
+ effort = fields[2] if len(fields) > 2 and fields[2] != "-" else None
58
+ row, _ = caller_identity.resolve(registry, vendor, fields[1], effort)
59
+ if row is None or row["score"] > ceiling:
60
+ continue
61
+ found.append({
62
+ "lane": lane,
63
+ "target": row["id"],
64
+ "score": row["score"],
65
+ "transport_verified": row["transport_mapping"].get("runtime_verified") is True,
66
+ })
67
+ break
68
+ return found
69
+
70
+
71
+ def lane_requirement(registry: dict, segments: list[list[str]], caller: dict | None) -> dict | None:
72
+ """The cheapest target in one lane, and the caller effort that would reach it."""
73
+ rows = []
74
+ for fields in segments:
75
+ if fields[0] in ("off", "vote") or len(fields) < 2:
76
+ continue
77
+ effort = fields[2] if len(fields) > 2 and fields[2] != "-" else None
78
+ row, _ = caller_identity.resolve(registry, fields[0], fields[1], effort)
79
+ if row is not None:
80
+ rows.append(row)
81
+ if not rows:
82
+ return None
83
+ cheapest = min(rows, key=lambda row: (row["score"], row["id"]))
84
+ required = None
85
+ if isinstance(caller, dict):
86
+ reaching = sorted((row for row in registry["scored_configs"]
87
+ if row["vendor"] == caller.get("vendor") and row["model"] == caller.get("model")
88
+ and row["score"] >= cheapest["score"]),
89
+ key=lambda row: (row["score"], row["id"]))
90
+ if reaching:
91
+ required = reaching[0]["effort"] or "none"
92
+ return {"target": cheapest["id"], "score": cheapest["score"], "required_caller_effort": required}
93
+
94
+
95
+ def main(argv: list[str] | None = None) -> int:
96
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
97
+ parser.add_argument("--registry", required=True)
98
+ parser.add_argument("--routing", action="append", default=[], type=Path,
99
+ help="routing file, highest precedence first; may repeat")
100
+ parser.add_argument("--lane", help="the lane that was refused")
101
+ args = parser.parse_args(argv)
102
+ raw = sys.stdin.read()
103
+ try:
104
+ decision = json.loads(raw)
105
+ ceiling = decision.get("effective_ceiling")
106
+ if decision.get("allowed") is False and type(ceiling) is int:
107
+ registry, _ = aa_policy.load_registry(args.registry)
108
+ table = lanes(args.routing)
109
+ decision["eligible_lanes"] = eligible(registry, table, ceiling)
110
+ if args.lane in table and decision.get("code") == "target-above-effective-ceiling":
111
+ # The decision describes the last candidate tried; the lane may hold a cheaper one.
112
+ need = lane_requirement(registry, table[args.lane], decision.get("caller"))
113
+ if need is not None:
114
+ decision["lane_requirement"] = dict(need, lane=args.lane)
115
+ if decision.get("inherited_ceiling") == decision.get("caller_score"):
116
+ decision["required_caller_effort"] = need["required_caller_effort"]
117
+ effort = need["required_caller_effort"]
118
+ held = (" The harness recorded no effort, so this caller is held to its "
119
+ "model's floor." if decision.get("caller_degraded") else "")
120
+ decision["reason"] = (
121
+ f"lane {args.lane}'s cheapest target {need['target']} scores "
122
+ f"{need['score']}, above this caller's ceiling of {ceiling}.{held} "
123
+ + (f"Relaunch the calling session at effort {effort} or higher, or have "
124
+ "a human operator dispatch it." if effort else
125
+ "No effort of the caller's model reaches it; a stronger caller model "
126
+ "or a human operator has to dispatch it."))
127
+ sys.stdout.write(json.dumps(decision, ensure_ascii=False, separators=(",", ":")) + "\n")
128
+ except (ValueError, OSError, aa_policy.PolicyError, KeyError, TypeError):
129
+ # Guidance is best effort; the refusal itself must always get through.
130
+ sys.stdout.write(raw if raw.endswith("\n") else raw + "\n")
131
+ return 0
132
+
133
+
134
+ if __name__ == "__main__":
135
+ raise SystemExit(main())
@@ -23,9 +23,12 @@ from typing import Any
23
23
 
24
24
 
25
25
  MAX_BYTES = 1_048_576
26
- # Approval anchor for the frozen AA v4.2 2026-09-07 source bytes. Updating this
27
- # constant is a governance change, never a caller argument/environment override.
28
- APPROVED_REGISTRY_SHA256 = "0782c87de123c02738c3ff60e4bc3c1cc10d110113e872b8f8627212861cdaab"
26
+ # Approval anchor for the frozen AA source bytes. Updating these constants is a
27
+ # governance change, never a caller argument/environment override.
28
+ # scripts/aa_rebaseline.py regenerates the registry; it never touches this pin.
29
+ APPROVED_BENCHMARK_VERSION = "4.3.2"
30
+ APPROVED_AS_OF = "2026-09-22"
31
+ APPROVED_REGISTRY_SHA256 = "a1109913b9928d943bc440787d26caaf7818e40abdaae32899750d65e5eb5fdd"
29
32
 
30
33
  IDENTITY_FIELDS = ("vendor", "model", "effort", "reasoning", "fallback")
31
34
  TRANSPORT_EVIDENCE_VENDORS = frozenset(("codex", "claude", "grok", "gemini"))
@@ -109,10 +112,10 @@ def _validate_registry(value: dict[str, Any]) -> dict[str, Any]:
109
112
  _check(isinstance(snapshot, dict), "invalid AA registry snapshot")
110
113
  for key in ("id", "benchmark_version", "as_of", "frozen"):
111
114
  _check(key in snapshot, "incomplete AA registry snapshot")
112
- _check(snapshot["benchmark_version"] == "4.2"
113
- and snapshot["as_of"] == "2026-09-07"
115
+ _check(snapshot["benchmark_version"] == APPROVED_BENCHMARK_VERSION
116
+ and snapshot["as_of"] == APPROVED_AS_OF
114
117
  and snapshot["frozen"] is True,
115
- "AA registry is not frozen v4.2 dated 2026-09-07")
118
+ f"AA registry is not frozen v{APPROVED_BENCHMARK_VERSION} dated {APPROVED_AS_OF}")
116
119
  policy = value["policy"]
117
120
  _check(isinstance(policy, dict)
118
121
  and policy.get("decision") == "target_score <= min(caller_score, inherited_ceiling)"
@@ -135,7 +138,8 @@ def _validate_registry(value: dict[str, Any]) -> dict[str, Any]:
135
138
  _check(type(row["score"]) is int and 0 <= row["score"] <= 100,
136
139
  "invalid AA score")
137
140
  _check(type(row["estimated"]) is bool, "invalid AA estimated flag")
138
- _check(row["benchmark_version"] == "4.2" and row["as_of"] == "2026-09-07",
141
+ _check(row["benchmark_version"] == APPROVED_BENCHMARK_VERSION
142
+ and row["as_of"] == APPROVED_AS_OF,
139
143
  "mixed AA registry snapshot")
140
144
  _check(isinstance(row["transport_mapping"], dict), "invalid transport mapping")
141
145
  return value
@@ -239,7 +243,13 @@ def load_caller(path: str | Path, registry: dict[str, Any],
239
243
  _check(value.get("snapshot_id") == registry["snapshot"]["id"],
240
244
  "caller-context snapshot does not match frozen registry")
241
245
  _check(value.get("kind") == "model", "unsupported caller-context kind")
246
+ # effort_unverified marks a caller degraded to its model's lowest-scored row
247
+ # because the launching harness recorded no effort; it may only be true.
248
+ unverified = value.pop("effort_unverified", None)
249
+ _check(unverified is None or unverified is True, "invalid caller-context effort_unverified")
242
250
  _exact_fields(value, {"schema_version", "snapshot_id", "kind", "caller", "inherited_ceiling"})
251
+ if unverified:
252
+ value["effort_unverified"] = True
243
253
  value["caller"] = _identity(value["caller"], "caller")
244
254
  ceiling = value["inherited_ceiling"]
245
255
  _check(type(ceiling) is int and 0 <= ceiling <= 100,
@@ -345,10 +355,15 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
345
355
  "file it prints as --caller-context, which dispatch does itself when the "
346
356
  "launching CLI names its model and effort; a human operator passes "
347
357
  "--operator-asserted-human"),
358
+ failed_gate="caller-identity",
359
+ reason="no caller identity reached the gate",
360
+ next_command="omnilane whoami",
348
361
  )
349
362
  return base
350
363
  base["caller_context_sha256"] = caller_sha256
351
364
  caller_identity = caller["caller"]
365
+ degraded = caller.get("effort_unverified") is True
366
+ base["caller_degraded"] = degraded
352
367
  caller_rows = _matching_rows(registry, caller_identity)
353
368
  if len(caller_rows) != 1:
354
369
  detail = _unknown_reason(registry, caller_identity)
@@ -356,9 +371,24 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
356
371
  code="unknown-caller-config" if not caller_rows else "ambiguous-caller-config",
357
372
  message=detail or "caller exact vendor/model/effort/reasoning/fallback is not uniquely scored",
358
373
  caller=caller_identity,
374
+ failed_gate="caller-identity",
375
+ reason="the caller context names a configuration the frozen registry does not score exactly once",
376
+ next_command="omnilane whoami",
359
377
  )
360
378
  return base
361
379
  caller_row = caller_rows[0]
380
+ model_rows = [row for row in registry["scored_configs"]
381
+ if row["vendor"] == caller_row["vendor"] and row["model"] == caller_row["model"]]
382
+ if degraded and caller_row["score"] != min(row["score"] for row in model_rows):
383
+ base.update(
384
+ code="invalid-degraded-caller",
385
+ message="an effort-unverified caller must name its model's lowest-scored row",
386
+ caller=caller_identity,
387
+ failed_gate="caller-identity",
388
+ reason="effort_unverified was set on a row above the model's floor",
389
+ next_command="omnilane whoami",
390
+ )
391
+ return base
362
392
  effective = min(caller_row["score"], caller["inherited_ceiling"])
363
393
  base.update(
364
394
  caller=caller_identity,
@@ -370,7 +400,14 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
370
400
  registry, vendor, model, effort, target_config
371
401
  )
372
402
  if target_row is None:
373
- base.update(code=mapping_code, message="target runtime cannot be mapped to one verified exact AA configuration", **detail)
403
+ base.update(
404
+ code=mapping_code,
405
+ message="target runtime cannot be mapped to one verified exact AA configuration",
406
+ failed_gate="target-transport",
407
+ reason=("the caller is identified; this host's transport overlay does not currently "
408
+ f"verify {vendor} {model} at effort {effort}"),
409
+ next_command="omnilane resign --check",
410
+ **detail)
374
411
  return base
375
412
  target_score = target_row["score"]
376
413
  target_identity = _row_identity(target_row)
@@ -381,9 +418,30 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
381
418
  target_estimated=target_row["estimated"],
382
419
  )
383
420
  if target_score > effective:
421
+ reaching = sorted((row for row in model_rows if row["score"] >= target_score),
422
+ key=lambda row: (row["score"], row["id"]))
423
+ required = reaching[0]["effort"] or "none" if reaching else None
424
+ if caller["inherited_ceiling"] < caller_row["score"]:
425
+ reason = ("this worker inherited a ceiling below the target; only the session that "
426
+ "dispatched it, or a human operator, can reach this target")
427
+ required = None
428
+ elif required is None:
429
+ reason = (f"no scored effort of {caller_row['model']} reaches {target_score}; a "
430
+ "stronger caller model or a human operator has to dispatch this target")
431
+ elif degraded:
432
+ reason = (f"the launching harness recorded no effort, so the caller was held to "
433
+ f"{caller_row['model']}'s floor of {effective}; relaunch the session with an "
434
+ f"explicit effort of {required} or higher")
435
+ else:
436
+ reason = (f"relaunch the calling session at effort {required} or higher, or have a "
437
+ "human operator dispatch this target")
384
438
  base.update(
385
439
  code="target-above-effective-ceiling",
386
440
  message=f"target score {target_score} exceeds effective caller ceiling {effective}",
441
+ failed_gate="downward-ceiling",
442
+ reason=reason,
443
+ required_caller_effort=required,
444
+ next_command="omnilane list",
387
445
  )
388
446
  return base
389
447
  child_context = {
@@ -402,6 +460,105 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
402
460
  return base
403
461
 
404
462
 
463
+ def decide_inherited(registry: dict[str, Any], registry_sha256: str, *,
464
+ caller: dict[str, Any] | None, caller_sha256: str | None,
465
+ operator_asserted_human: bool = False,
466
+ host_asserted: dict[str, str] | None = None) -> dict[str, Any]:
467
+ """A native worker that inherits the caller's own model and effort unchanged.
468
+
469
+ It runs what the caller runs, so it scores what the caller scores and cannot
470
+ be an upward dispatch, whether or not the caller's effort is known. There is
471
+ no external CLI, so no transport mapping is involved. It is nobody's lane
472
+ target: the decision names no target configuration and must not be reported
473
+ as satisfying one.
474
+
475
+ None of that rests on knowing who the caller is, so a caller whose identity
476
+ cannot be read still gets an inherited worker, on the host's word for its
477
+ vendor and model. That decision is marked unverified, carries no ceiling and
478
+ publishes no child context: a worker that tried to dispatch would have no
479
+ identity to dispatch with.
480
+ """
481
+ base: dict[str, Any] = {
482
+ "schema_version": 1,
483
+ "snapshot_id": registry["snapshot"]["id"],
484
+ "registry_sha256": registry_sha256,
485
+ "allowed": False,
486
+ "code": "deny",
487
+ "message": "AA policy denied dispatch",
488
+ "caller_kind": "operator-asserted-human" if operator_asserted_human else "model",
489
+ "target_request": {"vendor": None, "model": None, "effort": None, "inherit": True},
490
+ "target_config_id": None,
491
+ "caller_score": None,
492
+ "inherited_ceiling": None,
493
+ "effective_ceiling": None,
494
+ "target_score": None,
495
+ "target_estimated": None,
496
+ "child_context": None,
497
+ "evidence_limit": ("the host asserts that a sub-agent spawned without a model override "
498
+ "inherits the caller's runtime; omnilane cannot observe it"),
499
+ }
500
+ if operator_asserted_human:
501
+ base.update(code="inherit-requires-model-caller",
502
+ message="only a model running inside a harness has a runtime to inherit",
503
+ failed_gate="caller-identity",
504
+ reason="a human operator has no sub-agent tool; dispatch a lane instead",
505
+ next_command="omnilane list")
506
+ return base
507
+ if caller is None and host_asserted is not None:
508
+ base.update(allowed=True, code="native-inherited-unverified-caller",
509
+ message="the worker inherits the caller's own runtime, so it cannot score above it; "
510
+ "the caller's vendor and model are the host's statement, not a verified identity",
511
+ caller_kind="model-unverified", caller_identity_verified=False,
512
+ caller_identity_source="host-asserted",
513
+ target={"inherit": True, "vendor": host_asserted["vendor"],
514
+ "model": host_asserted["model"]})
515
+ return base
516
+ if caller is None:
517
+ base.update(code="missing-caller-context",
518
+ message="no caller identity: an inherited worker still has to know whose runtime it inherits",
519
+ failed_gate="caller-identity",
520
+ reason="no caller identity reached the gate and the capability file names no current_model",
521
+ next_command="omnilane whoami # if that cannot read this harness: omnilane "
522
+ "native-context --vendor VENDOR --model MODEL --inherits-caller-runtime")
523
+ return base
524
+ base["caller_context_sha256"] = caller_sha256
525
+ base["caller_identity_verified"] = True
526
+ base["caller_identity_source"] = "caller-context"
527
+ identity = caller["caller"]
528
+ degraded = caller.get("effort_unverified") is True
529
+ rows = _matching_rows(registry, identity)
530
+ if len(rows) != 1:
531
+ base.update(code="unknown-caller-config" if not rows else "ambiguous-caller-config",
532
+ message=_unknown_reason(registry, identity)
533
+ or "caller exact vendor/model/effort/reasoning/fallback is not uniquely scored",
534
+ caller=identity, failed_gate="caller-identity",
535
+ reason="the caller context names a configuration the frozen registry does not score exactly once",
536
+ next_command="omnilane whoami")
537
+ return base
538
+ row = rows[0]
539
+ floor = min(r["score"] for r in registry["scored_configs"]
540
+ if r["vendor"] == row["vendor"] and r["model"] == row["model"])
541
+ if degraded and row["score"] != floor:
542
+ base.update(code="invalid-degraded-caller",
543
+ message="an effort-unverified caller must name its model's lowest-scored row",
544
+ caller=identity, failed_gate="caller-identity",
545
+ reason="effort_unverified was set on a row above the model's floor",
546
+ next_command="omnilane whoami")
547
+ return base
548
+ effective = min(row["score"], caller["inherited_ceiling"])
549
+ child = {"schema_version": 1, "snapshot_id": registry["snapshot"]["id"], "kind": "model",
550
+ "caller": identity, "inherited_ceiling": effective}
551
+ if degraded:
552
+ child["effort_unverified"] = True
553
+ base.update(allowed=True, code="native-inherited-allowed",
554
+ message="the worker inherits the caller's own runtime, so it cannot score above it",
555
+ caller=identity, caller_degraded=degraded, caller_score=row["score"],
556
+ inherited_ceiling=caller["inherited_ceiling"], effective_ceiling=effective,
557
+ target={"inherit": True, "vendor": row["vendor"], "model": row["model"]},
558
+ child_context=child)
559
+ return base
560
+
561
+
405
562
  def _normalized_effort(value: str) -> str | None:
406
563
  return None if value in ("", "-") else value
407
564
 
@@ -6,6 +6,8 @@ corresponds to a probe run under the selected evidence root whose raw
6
6
  stdout/stderr is hashed into the manifest, so the overlay's evidence[] anchors
7
7
  the whole set.
8
8
  """
9
+ from __future__ import annotations
10
+
9
11
  import argparse
10
12
  import hashlib
11
13
  import json
@@ -14,9 +16,13 @@ import shutil
14
16
  import socket
15
17
  from collections import Counter
16
18
  from datetime import datetime, timezone
19
+ import sys
17
20
  from pathlib import Path
18
21
 
19
- REPO = Path(os.environ.get("OMNILANE_REPO", "/Users/vincentw/dev/omnilane"))
22
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
23
+ import cli_provenance # noqa: E402
24
+
25
+ REPO = Path(os.environ.get("OMNILANE_REPO") or Path(__file__).resolve().parents[2])
20
26
  HOME = Path.home()
21
27
  SWEEP_ID = os.environ.get("OMNILANE_TRANSPORT_SWEEP_ID", "overlay-reprobe-20260909")
22
28
  DEFAULT_ROOT = HOME / ".omnilane" / "transport-evidence" / SWEEP_ID
@@ -43,6 +49,9 @@ PROVEN["grok/grok-4-6"] = ("cli_reasoning_effort", "grok-4.6", "gk-grok-4_6-high
43
49
  for effort in ["xhigh", "medium", "low"]:
44
50
  PROVEN[f"grok/grok-4-6-{effort}"] = ("cli_reasoning_effort", "grok-4.6", f"gk-grok-4_6-{effort}")
45
51
  PROVEN["grok/grok-4-5"] = ("cli_reasoning_effort", "grok-4.5", "gk-grok-4_5-high")
52
+ # AA scores grok-4.7 at xhigh and high only; its base row is the xhigh one.
53
+ PROVEN["grok/grok-4-7"] = ("cli_reasoning_effort", "grok-4.7", "gk-grok-4_7-xhigh")
54
+ PROVEN["grok/grok-4-7-high"] = ("cli_reasoning_effort", "grok-4.7", "gk-grok-4_7-high")
46
55
 
47
56
  for cid, rid, ev in [
48
57
  ("gemini/gemini-3-8-flash", "gemini-3.8-flash-high", "agy-gemini-3_8-flash-high"),
@@ -75,6 +84,12 @@ for cid, model in [("claude/claude-sonnet-5", "claude-sonnet-5"),
75
84
  ("claude/claude-opus-4-6-adaptive", "claude-opus-4-6"),
76
85
  ("claude/claude-sonnet-4-6-adaptive", "claude-sonnet-4-6")]:
77
86
  PROVEN[cid] = ("model_and_effort", model, f"cl-{model}-max")
87
+ # Targets resolve on vendor/model/effort alone, so claude-sonnet-5-non-reasoning
88
+ # (also effort high) must never be listed here: two verified rows at one
89
+ # selector make every sonnet-5 high dispatch ambiguous-runtime-mapping.
90
+ for effort in ["xhigh", "high", "medium", "low"]:
91
+ PROVEN[f"claude/claude-sonnet-5-{effort}"] = (
92
+ "model_and_effort", "claude-sonnet-5", f"cl-claude-sonnet-5-{effort}")
78
93
 
79
94
  # Fable is listed so its failures reach unproven[] rather than vanishing. Its
80
95
  # probes were refused for quota on 2026-09-07 and again on 2026-09-09; the
@@ -98,19 +113,21 @@ def cli_path(name: str) -> Path:
98
113
  return Path(found).resolve()
99
114
 
100
115
 
116
+ RUNNERS = {"grok": "run-grok.sh", "codex": "run-codex.sh", "claude": "run-claude.sh",
117
+ "gemini": "run-gemini.sh"}
118
+ CLI_NAMES = {"grok": "grok", "codex": "codex", "claude": "claude", "gemini": "agy"}
119
+
120
+
101
121
  def core_evidence() -> list[tuple[Path, str]]:
102
122
  """Resolved when a build runs, not at import: a host missing one CLI can
103
123
  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
- ]
124
+ anchors = []
125
+ for vendor in ("grok", "codex", "claude", "gemini"):
126
+ if shutil.which(CLI_NAMES[vendor]) is None:
127
+ continue # not installed here: main() signs nothing for it
128
+ anchors += [(cli_path(CLI_NAMES[vendor]), vendor),
129
+ (REPO / "scripts/runners" / RUNNERS[vendor], vendor)]
130
+ return anchors
114
131
 
115
132
 
116
133
  def sha256(path: Path) -> str:
@@ -129,6 +146,12 @@ def main(argv: list[str] | None = None) -> None:
129
146
  default=DEFAULT_ROOT,
130
147
  help=f"probe sweep root (default: {DEFAULT_ROOT})",
131
148
  )
149
+ parser.add_argument(
150
+ "--source",
151
+ default=os.environ.get("OMNILANE_TRANSPORT_SOURCE")
152
+ or f"{socket.gethostname()} / build_overlay {datetime.now(timezone.utc).date().isoformat()}",
153
+ help="free-text provenance recorded in the overlay",
154
+ )
132
155
  args = parser.parse_args(argv)
133
156
  root = args.root.expanduser()
134
157
 
@@ -144,7 +167,11 @@ def main(argv: list[str] | None = None) -> None:
144
167
  if path.exists():
145
168
  entry[suffix] = {"path": str(path), "sha256": sha256(path)}
146
169
  if "json" not in entry:
147
- raise SystemExit(f"missing probe evidence for {cid}: {ev}")
170
+ # A vendor nobody is logged in to was never probed; that is a gap in this
171
+ # host's overlay, not a reason to refuse to sign the vendors that were.
172
+ unproven.append({"config_id": cid, "verdict_reason": "not probed on this host",
173
+ "observed_model": None, "probed_at": None})
174
+ continue
148
175
  descriptor_path = Path(entry["json"]["path"])
149
176
  descriptor = json.loads(descriptor_path.read_text())
150
177
  if not isinstance(descriptor, dict):
@@ -169,11 +196,18 @@ def main(argv: list[str] | None = None) -> None:
169
196
  manifest_path = root / "probe-manifest.json"
170
197
  manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
171
198
 
199
+ anchors = core_evidence()
200
+ anchored = {vendor for _, vendor in anchors}
172
201
  mappings = []
173
202
  for cid, (selector, runtime_model, _) in sorted(PROVEN.items()):
174
203
  if cid not in manifest["probe_runs"]:
175
204
  continue
176
205
  row = ROWS[cid]
206
+ if row["vendor"] not in anchored:
207
+ # Evidence with no executable to pin it to verifies nothing.
208
+ unproven.append({"config_id": cid, "verdict_reason": "vendor CLI is not installed",
209
+ "observed_model": None, "probed_at": None})
210
+ continue
177
211
  mapping = {
178
212
  "config_id": cid,
179
213
  "identity": {key: row[key] for key in IDENTITY_FIELDS},
@@ -187,18 +221,20 @@ def main(argv: list[str] | None = None) -> None:
187
221
  mapping["cli_flag"] = "--reasoning-effort"
188
222
  mappings.append(mapping)
189
223
 
190
- evidence = [
191
- {"path": str(path), "sha256": sha256(path), "vendor": vendor}
192
- for path, vendor in core_evidence()
193
- ]
224
+ evidence = []
225
+ for path, vendor in anchors:
226
+ anchor = {"path": str(path), "sha256": sha256(path), "vendor": vendor}
227
+ if path.name != RUNNERS[vendor]:
228
+ # The signer an unattended re-sign is later held to; see cli_provenance.
229
+ anchor["codesign"] = cli_provenance.facts(path)
230
+ evidence.append(anchor)
194
231
  evidence.append({"path": str(manifest_path), "sha256": sha256(manifest_path)})
195
232
 
196
233
  overlay = {
197
234
  "schema_version": 1,
198
235
  "snapshot_id": REGISTRY["snapshot"]["id"],
199
236
  "host": socket.gethostname(),
200
- "source": ("claude-code / MacStudio / operator-directed full sweep 2026-09-07; "
201
- "gemini selectors re-probed 2026-09-09 after agy 1.1.27 -> 1.1.28"),
237
+ "source": args.source,
202
238
  "evidence": evidence,
203
239
  "mappings": mappings,
204
240
  "unproven": unproven,