omnilane 0.41.1 → 0.42.1

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,473 @@
1
+ #!/usr/bin/env python3
2
+ """Frozen exact-AA downward-delegation decision engine.
3
+
4
+ This module is intentionally provider-free. It validates one explicit caller
5
+ assertion against the frozen registry, resolves only runtime-verified target
6
+ mappings, and emits a structured allow/deny decision. The JSON context is
7
+ cooperative workflow metadata, not operating-system authentication.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import hashlib
14
+ import json
15
+ import os
16
+ from pathlib import Path
17
+ import re
18
+ import stat
19
+ import tempfile
20
+ import socket
21
+ import sys
22
+ from typing import Any
23
+
24
+
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"
29
+
30
+ IDENTITY_FIELDS = ("vendor", "model", "effort", "reasoning", "fallback")
31
+ IDENTIFIER = re.compile(r"[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}\Z")
32
+
33
+
34
+ class PolicyError(ValueError):
35
+ """A public, non-sensitive policy validation error."""
36
+
37
+
38
+ def _check(condition: bool, message: str) -> None:
39
+ if not condition:
40
+ raise PolicyError(message)
41
+
42
+
43
+ def _unique_object(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
44
+ result: dict[str, Any] = {}
45
+ for key, value in pairs:
46
+ _check(key not in result, "duplicate JSON key")
47
+ result[key] = value
48
+ return result
49
+
50
+
51
+ def _read_bytes(path: str | Path) -> bytes:
52
+ fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
53
+ with os.fdopen(fd, "rb") as stream:
54
+ info = os.fstat(stream.fileno())
55
+ _check(stat.S_ISREG(info.st_mode), "policy input must be a regular file")
56
+ _check(info.st_size <= MAX_BYTES, "policy input is too large")
57
+ data = stream.read(MAX_BYTES + 1)
58
+ _check(len(data) <= MAX_BYTES, "policy input is too large")
59
+ return data
60
+
61
+
62
+ def _read_json(path: str | Path) -> tuple[dict[str, Any], str]:
63
+ data = _read_bytes(path)
64
+ try:
65
+ value = json.loads(
66
+ data.decode("utf-8"),
67
+ object_pairs_hook=_unique_object,
68
+ parse_constant=lambda _: (_ for _ in ()).throw(PolicyError("invalid JSON number")),
69
+ )
70
+ except (UnicodeError, json.JSONDecodeError) as error:
71
+ raise PolicyError("invalid JSON input") from error
72
+ _check(isinstance(value, dict), "policy input must be a JSON object")
73
+ return value, hashlib.sha256(data).hexdigest()
74
+
75
+
76
+ def _exact_fields(value: dict[str, Any], required: set[str]) -> None:
77
+ _check(set(value) == required, "missing or unknown caller-context fields")
78
+
79
+
80
+ def _identity(value: Any, label: str) -> dict[str, Any]:
81
+ _check(isinstance(value, dict), f"{label} must be a JSON object")
82
+ _exact_fields(value, set(IDENTITY_FIELDS))
83
+ for key in ("vendor", "model", "reasoning"):
84
+ field = value[key]
85
+ _check(isinstance(field, str) and bool(IDENTIFIER.fullmatch(field)),
86
+ f"invalid {label}.{key}")
87
+ for key in ("effort", "fallback"):
88
+ field = value[key]
89
+ _check(field is None or (isinstance(field, str) and bool(IDENTIFIER.fullmatch(field))),
90
+ f"invalid {label}.{key}")
91
+ return {key: value[key] for key in IDENTITY_FIELDS}
92
+
93
+
94
+ def _validate_registry(value: dict[str, Any]) -> dict[str, Any]:
95
+ required = {
96
+ "schema_version", "snapshot", "policy", "scored_configs",
97
+ "unknown_configs", "reference_configs", "aliases", "coverage",
98
+ }
99
+ _check(required <= set(value) <= required | {"schema_notes"},
100
+ "unsupported AA registry schema")
101
+ _check(type(value["schema_version"]) is int and value["schema_version"] == 1,
102
+ "unsupported AA registry version")
103
+ snapshot = value["snapshot"]
104
+ _check(isinstance(snapshot, dict), "invalid AA registry snapshot")
105
+ for key in ("id", "benchmark_version", "as_of", "frozen"):
106
+ _check(key in snapshot, "incomplete AA registry snapshot")
107
+ _check(snapshot["benchmark_version"] == "4.2"
108
+ and snapshot["as_of"] == "2026-09-07"
109
+ and snapshot["frozen"] is True,
110
+ "AA registry is not frozen v4.2 dated 2026-09-07")
111
+ policy = value["policy"]
112
+ _check(isinstance(policy, dict)
113
+ and policy.get("decision") == "target_score <= min(caller_score, inherited_ceiling)"
114
+ and policy.get("same_score_allowed") is True
115
+ and policy.get("unknown") == "deny"
116
+ and policy.get("transport_mapping_requires_runtime_verification") is True,
117
+ "AA registry policy contract mismatch")
118
+ rows = value["scored_configs"]
119
+ _check(isinstance(rows, list) and rows, "AA registry has no scored configurations")
120
+ seen: set[str] = set()
121
+ for row in rows:
122
+ _check(isinstance(row, dict), "invalid AA scored configuration")
123
+ for key in (*IDENTITY_FIELDS, "id", "score", "estimated", "benchmark_version",
124
+ "as_of", "transport_mapping"):
125
+ _check(key in row, "incomplete AA scored configuration")
126
+ _check(isinstance(row["id"], str) and row["id"] not in seen,
127
+ "duplicate AA scored configuration")
128
+ seen.add(row["id"])
129
+ _identity({key: row[key] for key in IDENTITY_FIELDS}, "registry identity")
130
+ _check(type(row["score"]) is int and 0 <= row["score"] <= 100,
131
+ "invalid AA score")
132
+ _check(type(row["estimated"]) is bool, "invalid AA estimated flag")
133
+ _check(row["benchmark_version"] == "4.2" and row["as_of"] == "2026-09-07",
134
+ "mixed AA registry snapshot")
135
+ _check(isinstance(row["transport_mapping"], dict), "invalid transport mapping")
136
+ return value
137
+
138
+
139
+ def apply_transport_overlay(registry: dict[str, Any]) -> None:
140
+ """Host-local request selector proof, independent of frozen AA scores."""
141
+ path = os.environ.get("OMNILANE_AA_TRANSPORT_OVERLAY")
142
+ if not path:
143
+ return
144
+ overlay, digest = _read_json(path)
145
+ expected = os.environ.get("OMNILANE_AA_OVERLAY_SHA256")
146
+ _check(not expected or expected == digest, "transport overlay changed after initial decision")
147
+ _check(overlay.get("schema_version") == 1, "unsupported transport overlay")
148
+ _check(overlay.get("snapshot_id") == registry["snapshot"]["id"], "transport overlay snapshot mismatch")
149
+ _check(overlay.get("host") == socket.gethostname(), "transport overlay host mismatch")
150
+ for evidence in overlay.get("evidence", []):
151
+ fd = os.open(evidence["path"], os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
152
+ with os.fdopen(fd, "rb") as stream:
153
+ _check(stat.S_ISREG(os.fstat(stream.fileno()).st_mode), "invalid transport evidence file")
154
+ digest_file = hashlib.sha256()
155
+ for block in iter(lambda: stream.read(1024 * 1024), b""):
156
+ digest_file.update(block)
157
+ _check(digest_file.hexdigest() == evidence["sha256"], "transport contract evidence changed")
158
+ _check(bool(overlay.get("evidence")), "transport overlay requires local evidence")
159
+ for mapping in overlay.get("mappings", []):
160
+ rows = [row for row in registry["scored_configs"] if row["id"] == mapping.get("config_id")]
161
+ _check(len(rows) == 1, "unknown overlay config")
162
+ row = rows[0]
163
+ _check(mapping.get("identity") == _row_identity(row), "overlay exact identity mismatch")
164
+ _check(mapping.get("verification") == "request-selector-contract", "unsupported overlay verification")
165
+ _check(mapping.get("runtime_effort") == row["effort"], "overlay effort mismatch")
166
+ selector_type = mapping.get("selector_type", "model_and_effort")
167
+ _check(selector_type in ("model_and_effort", "model_id_encoded_effort"), "unknown selector type")
168
+ if selector_type == "model_id_encoded_effort":
169
+ _check(row["vendor"] == "gemini", "unsupported encoded-effort vendor")
170
+ _check(mapping.get("runtime_model") in row["transport_mapping"].get("candidate_model_ids", []), "unproven encoded model selector")
171
+ _check(mapping["runtime_model"].endswith("-" + row["effort"]), "encoded effort does not match exact tuple")
172
+ else:
173
+ _check(mapping.get("runtime_model") == row["model"], "overlay model mismatch")
174
+ row["transport_mapping"].update(
175
+ status="verified", runtime_verified=True,
176
+ runtime_model=mapping["runtime_model"], runtime_effort=mapping["runtime_effort"],
177
+ selector_type=selector_type,
178
+ verification="request-selector-contract", upstream_identity_verified=False,
179
+ overlay_sha256=digest, overlay_host=overlay["host"],
180
+ )
181
+
182
+
183
+ def load_registry(path: str | Path, expected_sha256: str | None = None) -> tuple[dict[str, Any], str]:
184
+ value, digest = _read_json(path)
185
+ _check(digest == APPROVED_REGISTRY_SHA256, "unapproved AA registry; use the approved frozen snapshot byte-for-byte")
186
+ if expected_sha256:
187
+ _check(digest == expected_sha256, "AA registry changed after initial decision")
188
+ registry = _validate_registry(value)
189
+ apply_transport_overlay(registry)
190
+ return registry, digest
191
+
192
+
193
+ def load_caller(path: str | Path, registry: dict[str, Any],
194
+ expected_sha256: str | None = None) -> tuple[dict[str, Any], str]:
195
+ value, digest = _read_json(path)
196
+ if expected_sha256:
197
+ _check(digest == expected_sha256, "caller context changed after initial decision")
198
+ _check(type(value.get("schema_version")) is int and value["schema_version"] == 1,
199
+ "unsupported caller-context version")
200
+ _check(value.get("snapshot_id") == registry["snapshot"]["id"],
201
+ "caller-context snapshot does not match frozen registry")
202
+ _check(value.get("kind") == "model", "unsupported caller-context kind")
203
+ _exact_fields(value, {"schema_version", "snapshot_id", "kind", "caller", "inherited_ceiling"})
204
+ value["caller"] = _identity(value["caller"], "caller")
205
+ ceiling = value["inherited_ceiling"]
206
+ _check(type(ceiling) is int and 0 <= ceiling <= 100,
207
+ "invalid inherited caller ceiling")
208
+ return value, digest
209
+
210
+
211
+ def _row_identity(row: dict[str, Any]) -> dict[str, Any]:
212
+ return {key: row[key] for key in IDENTITY_FIELDS}
213
+
214
+
215
+ def _matching_rows(registry: dict[str, Any], identity: dict[str, Any]) -> list[dict[str, Any]]:
216
+ return [row for row in registry["scored_configs"] if _row_identity(row) == identity]
217
+
218
+
219
+ def _unknown_reason(registry: dict[str, Any], identity: dict[str, Any]) -> str | None:
220
+ for row in registry["unknown_configs"]:
221
+ if all(row.get(key) == identity[key] for key in IDENTITY_FIELDS):
222
+ return row.get("reason")
223
+ return None
224
+
225
+
226
+ def _runtime_target(registry: dict[str, Any], vendor: str, model: str,
227
+ effort: str | None, target_config: str | None) -> tuple[dict[str, Any] | None, str, dict[str, Any]]:
228
+ exact_id = [row for row in registry["scored_configs"] if row["id"] == target_config] if target_config else registry["scored_configs"]
229
+ if target_config and not exact_id:
230
+ return None, "unknown-target-config", {"target_config": target_config}
231
+ vendor_rows = [row for row in exact_id if row["vendor"] == vendor]
232
+ candidates: list[dict[str, Any]] = []
233
+ unresolved: list[str] = []
234
+ for row in vendor_rows:
235
+ mapping = row["transport_mapping"]
236
+ model_ids = mapping.get("candidate_model_ids", [])
237
+ runtime_model = mapping.get("runtime_model")
238
+ runtime_effort = mapping.get("runtime_effort", row["effort"])
239
+ model_match = model == runtime_model if runtime_model is not None else model in model_ids
240
+ encoded_effort = mapping.get("selector_type") == "model_id_encoded_effort"
241
+ if not model_match:
242
+ continue
243
+ if encoded_effort and effort not in (None, runtime_effort):
244
+ return None, "encoded-effort-conflict", {"model": model, "effort": effort, "encoded_effort": runtime_effort}
245
+ if not encoded_effort and effort != runtime_effort:
246
+ continue
247
+ if mapping.get("runtime_verified") is True and mapping.get("status") in ("verified", "resolved"):
248
+ candidates.append(row)
249
+ else:
250
+ unresolved.append(row["id"])
251
+ if vendor == "grok" and candidates:
252
+ # The checked-in Grok runner accepts EFFORT for interface parity but
253
+ # discards it. A scored reasoning/effort row therefore cannot be
254
+ # proven by that runtime surface.
255
+ return None, "runtime-effort-discarded", {"vendor": vendor, "model": model, "effort": effort}
256
+ if len(candidates) == 1:
257
+ return candidates[0], "runtime-mapping-verified", {}
258
+ if len(candidates) > 1:
259
+ return None, "ambiguous-runtime-mapping", {"candidate_config_ids": [row["id"] for row in candidates]}
260
+ if unresolved:
261
+ return None, "runtime-mapping-unverified", {"candidate_config_ids": unresolved}
262
+ return None, "unknown-target-runtime", {"vendor": vendor, "model": model, "effort": effort}
263
+
264
+
265
+ def decide(registry: dict[str, Any], registry_sha256: str, *,
266
+ vendor: str, model: str, effort: str | None,
267
+ caller: dict[str, Any] | None, caller_sha256: str | None,
268
+ operator_asserted_human: bool = False,
269
+ target_config: str | None = None) -> dict[str, Any]:
270
+ base: dict[str, Any] = {
271
+ "schema_version": 1,
272
+ "snapshot_id": registry["snapshot"]["id"],
273
+ "registry_sha256": registry_sha256,
274
+ "allowed": False,
275
+ "code": "deny",
276
+ "message": "AA policy denied dispatch",
277
+ "caller_kind": "operator-asserted-human" if operator_asserted_human else "model",
278
+ "target_request": {"vendor": vendor, "model": model, "effort": effort},
279
+ "target_config_id": target_config,
280
+ "caller_score": None,
281
+ "inherited_ceiling": None,
282
+ "effective_ceiling": None,
283
+ "target_score": None,
284
+ "target_estimated": None,
285
+ "child_context": None,
286
+ "evidence_limit": "workflow metadata and selected model arguments do not prove actual provider identity",
287
+ }
288
+ if operator_asserted_human:
289
+ base.update(
290
+ allowed=True,
291
+ code="operator-asserted-human-exemption",
292
+ message="explicit operator assertion bypassed model-level AA ceiling",
293
+ evidence_limit="operator assertion is cooperative metadata, not authentication or provider-identity proof",
294
+ )
295
+ return base
296
+ if caller is None:
297
+ base.update(
298
+ code="missing-caller-context",
299
+ message="provide --caller-context FILE or explicitly assert --operator-asserted-human",
300
+ )
301
+ return base
302
+ base["caller_context_sha256"] = caller_sha256
303
+ caller_identity = caller["caller"]
304
+ caller_rows = _matching_rows(registry, caller_identity)
305
+ if len(caller_rows) != 1:
306
+ detail = _unknown_reason(registry, caller_identity)
307
+ base.update(
308
+ code="unknown-caller-config" if not caller_rows else "ambiguous-caller-config",
309
+ message=detail or "caller exact vendor/model/effort/reasoning/fallback is not uniquely scored",
310
+ caller=caller_identity,
311
+ )
312
+ return base
313
+ caller_row = caller_rows[0]
314
+ effective = min(caller_row["score"], caller["inherited_ceiling"])
315
+ base.update(
316
+ caller=caller_identity,
317
+ caller_score=caller_row["score"],
318
+ inherited_ceiling=caller["inherited_ceiling"],
319
+ effective_ceiling=effective,
320
+ )
321
+ target_row, mapping_code, detail = _runtime_target(
322
+ registry, vendor, model, effort, target_config
323
+ )
324
+ if target_row is None:
325
+ base.update(code=mapping_code, message="target runtime cannot be mapped to one verified exact AA configuration", **detail)
326
+ return base
327
+ target_score = target_row["score"]
328
+ target_identity = _row_identity(target_row)
329
+ base.update(
330
+ target_config_id=target_row["id"],
331
+ target=target_identity,
332
+ target_score=target_score,
333
+ target_estimated=target_row["estimated"],
334
+ )
335
+ if target_score > effective:
336
+ base.update(
337
+ code="target-above-effective-ceiling",
338
+ message=f"target score {target_score} exceeds effective caller ceiling {effective}",
339
+ )
340
+ return base
341
+ child_context = {
342
+ "schema_version": 1,
343
+ "snapshot_id": registry["snapshot"]["id"],
344
+ "kind": "model",
345
+ "caller": target_identity,
346
+ "inherited_ceiling": effective,
347
+ }
348
+ base.update(
349
+ allowed=True,
350
+ code="same-score-allowed" if target_score == effective else "downward-allowed",
351
+ message="target exact AA score is at or below effective caller ceiling",
352
+ child_context=child_context,
353
+ )
354
+ return base
355
+
356
+
357
+ def _normalized_effort(value: str) -> str | None:
358
+ return None if value in ("", "-") else value
359
+
360
+
361
+ def _json_line(value: dict[str, Any]) -> str:
362
+ return json.dumps(value, ensure_ascii=False, separators=(",", ":")) + "\n"
363
+
364
+
365
+ def atomic_bytes(path: Path, content: bytes) -> None:
366
+ """Publish private metadata without exposing a partial file."""
367
+ fd, name = tempfile.mkstemp(prefix=".aa-", dir=path.parent)
368
+ try:
369
+ with os.fdopen(fd, "wb") as stream:
370
+ stream.write(content)
371
+ stream.flush()
372
+ os.fsync(stream.fileno())
373
+ os.replace(name, path)
374
+ finally:
375
+ if os.path.exists(name):
376
+ os.unlink(name)
377
+
378
+
379
+ def atomic_json(path: Path, value: dict[str, Any]) -> None:
380
+ atomic_bytes(path, _json_line(value).encode("utf-8"))
381
+
382
+
383
+ def publish_context(directory: str | Path, registry: dict[str, Any],
384
+ caller: dict[str, Any] | None, decision: dict[str, Any],
385
+ registry_source: str | Path | None = None) -> dict[str, Any]:
386
+ """Keep immutable-by-convention authorizer and a distinct narrowed child identity.
387
+
388
+ This is lineage metadata, not authentication. The frozen registry content is
389
+ copied so later retries cannot silently select a different score snapshot.
390
+ """
391
+ root = Path(directory)
392
+ _check(root.is_dir() and not root.is_symlink(), "invalid context publication directory")
393
+ _check(decision.get("allowed") is True, "cannot publish a denied decision")
394
+ source = Path(registry_source) if registry_source else Path(__file__).resolve().parents[2] / "config/aa-model-policy.json"
395
+ source_bytes = _read_bytes(source)
396
+ _check(hashlib.sha256(source_bytes).hexdigest() == APPROVED_REGISTRY_SHA256, "unapproved AA registry snapshot publication")
397
+ atomic_bytes(root / "aa-registry.json", source_bytes)
398
+ registry_sha = hashlib.sha256((root / "aa-registry.json").read_bytes()).hexdigest()
399
+ if caller is not None:
400
+ atomic_json(root / "aa-authorizer.json", caller)
401
+ child = decision.get("child_context")
402
+ if child is not None:
403
+ atomic_json(root / "aa-child-context.json", child)
404
+ lineage = {
405
+ "schema_version": 1,
406
+ "registry_sha256": registry_sha,
407
+ "authorizer_sha256": hashlib.sha256((root / "aa-authorizer.json").read_bytes()).hexdigest() if caller else None,
408
+ "operator_asserted_human": decision["caller_kind"] == "operator-asserted-human",
409
+ "target_config_id": decision["target_config_id"],
410
+ "target_request": decision["target_request"],
411
+ "effective_ceiling": decision["effective_ceiling"],
412
+ "child_context": child,
413
+ }
414
+ overlay_path = os.environ.get("OMNILANE_AA_TRANSPORT_OVERLAY")
415
+ if overlay_path:
416
+ overlay, _ = _read_json(overlay_path)
417
+ atomic_json(root / "aa-transport-overlay.json", overlay)
418
+ lineage["transport_overlay_sha256"] = hashlib.sha256((root / "aa-transport-overlay.json").read_bytes()).hexdigest()
419
+ atomic_json(root / "aa-lineage.json", lineage)
420
+ atomic_json(root / "aa-decision.json", decision)
421
+ return lineage
422
+
423
+
424
+ def main(argv: list[str] | None = None) -> int:
425
+ parser = argparse.ArgumentParser(description=__doc__)
426
+ parser.add_argument("--registry", required=True)
427
+ parser.add_argument("--expected-registry-sha256")
428
+ source = parser.add_mutually_exclusive_group()
429
+ source.add_argument("--caller-context")
430
+ source.add_argument("--operator-asserted-human", action="store_true")
431
+ parser.add_argument("--expected-caller-sha256")
432
+ parser.add_argument("--vendor", required=True)
433
+ parser.add_argument("--model", required=True)
434
+ parser.add_argument("--effort", required=True)
435
+ parser.add_argument("--target-config")
436
+ parser.add_argument("--publish-dir")
437
+ args = parser.parse_args(argv)
438
+ try:
439
+ registry, registry_sha = load_registry(args.registry, args.expected_registry_sha256)
440
+ caller = None
441
+ caller_sha = None
442
+ if args.caller_context:
443
+ caller, caller_sha = load_caller(
444
+ args.caller_context, registry, args.expected_caller_sha256
445
+ )
446
+ result = decide(
447
+ registry,
448
+ registry_sha,
449
+ vendor=args.vendor,
450
+ model=args.model,
451
+ effort=_normalized_effort(args.effort),
452
+ caller=caller,
453
+ caller_sha256=caller_sha,
454
+ operator_asserted_human=args.operator_asserted_human,
455
+ target_config=args.target_config,
456
+ )
457
+ if args.publish_dir and result["allowed"]:
458
+ publish_context(args.publish_dir, registry, caller, result, args.registry)
459
+ print(_json_line(result), end="")
460
+ return 0 if result["allowed"] else 3
461
+ except (PolicyError, OSError, RecursionError, TypeError, KeyError) as error:
462
+ message = str(error) if isinstance(error, PolicyError) else "invalid or inaccessible AA policy input"
463
+ print(_json_line({
464
+ "schema_version": 1,
465
+ "allowed": False,
466
+ "code": "invalid-policy-input",
467
+ "message": message,
468
+ }), end="")
469
+ return 2
470
+
471
+
472
+ if __name__ == "__main__":
473
+ sys.exit(main())
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env python3
2
+ """Reconstruct only a validated job-owned authorizer; never borrow retry shell identity."""
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+ import sys
7
+ import aa_policy
8
+
9
+
10
+ def retry_args(directory):
11
+ root = Path(directory)
12
+ os.environ.pop("OMNILANE_AA_TRANSPORT_OVERLAY", None)
13
+ os.environ.pop("OMNILANE_AA_OVERLAY_SHA256", None)
14
+ lineage, _ = aa_policy._read_json(root / "aa-lineage.json")
15
+ aa_policy._check(lineage.get("schema_version") == 1, "unsupported retry lineage")
16
+ registry_path = root / "aa-registry.json"
17
+ registry, _ = aa_policy.load_registry(registry_path, lineage["registry_sha256"])
18
+ result = ["--aa-policy", str(registry_path)]
19
+ original = None
20
+ original_limit = 100
21
+ if lineage.get("operator_asserted_human") is not True:
22
+ context = root / "aa-authorizer.json"
23
+ aa_policy._check(isinstance(lineage.get("authorizer_sha256"), str), "missing retry authorizer hash")
24
+ original, _ = aa_policy.load_caller(context, registry, lineage["authorizer_sha256"])
25
+ rows = aa_policy._matching_rows(registry, original["caller"])
26
+ aa_policy._check(len(rows) == 1, "unknown original retry authorizer")
27
+ original_limit = min(rows[0]["score"], original["inherited_ceiling"])
28
+ current_path = os.environ.get("OMNILANE_AA_CALLER_CONTEXT")
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")
31
+ if current_path:
32
+ current, _ = aa_policy.load_caller(current_path, registry)
33
+ rows = aa_policy._matching_rows(registry, current["caller"])
34
+ aa_policy._check(len(rows) == 1, "unknown current retry caller")
35
+ narrowed = dict(current)
36
+ narrowed["inherited_ceiling"] = min(original_limit, current["inherited_ceiling"], rows[0]["score"])
37
+ digest = aa_policy.hashlib.sha256(aa_policy._json_line(narrowed).encode()).hexdigest()
38
+ context = root / ("aa-retry-authorizer-" + digest + ".json")
39
+ aa_policy.atomic_json(context, narrowed)
40
+ result += ["--caller-context", str(context)]
41
+ elif original is not None:
42
+ result += ["--caller-context", str(root / "aa-authorizer.json")]
43
+ else:
44
+ result += ["--operator-asserted-human"]
45
+ if lineage.get("transport_overlay_sha256"):
46
+ overlay = root / "aa-transport-overlay.json"
47
+ _, digest = aa_policy._read_json(overlay)
48
+ aa_policy._check(digest == lineage["transport_overlay_sha256"], "retry transport overlay changed")
49
+ result += ["--transport-overlay", str(overlay)]
50
+ config = lineage.get("target_config_id")
51
+ if config:
52
+ aa_policy._check(isinstance(config, str) and aa_policy.IDENTIFIER.fullmatch(config), "invalid retry target config")
53
+ result += ["--target-config", config]
54
+ return result
55
+
56
+
57
+ def metadata_fields(directory):
58
+ value, _ = aa_policy._read_json(Path(directory) / "meta.json")
59
+ keys = ("lane", "vendor", "model", "effort", "timeout", "job_timeout", "mode", "workdir")
60
+ aa_policy._check(value.get("mode") in ("advise", "work"), "invalid retry mode")
61
+ aa_policy._check(type(value.get("timeout")) is int and value["timeout"] > 0, "invalid retry timeout")
62
+ aa_policy._check(value.get("job_timeout") is None or (type(value["job_timeout"]) is int and value["job_timeout"] > 0), "invalid retry job timeout")
63
+ result = []
64
+ for key in keys:
65
+ field = value[key]
66
+ text = "null" if field is None else str(field)
67
+ aa_policy._check("\n" not in text and "\r" not in text and "\x00" not in text, "invalid retry metadata value")
68
+ result.append(text)
69
+ return result
70
+
71
+
72
+ if __name__ == "__main__":
73
+ try:
74
+ print("\n".join(metadata_fields(sys.argv[2]) if sys.argv[1] == "--metadata" else retry_args(sys.argv[1])))
75
+ except (aa_policy.PolicyError, OSError, KeyError, TypeError):
76
+ print("omnilane: retry requires intact AA lineage; current caller is missing or original authorizer/registry is changed", file=sys.stderr)
77
+ sys.exit(3)
@@ -82,6 +82,65 @@ file_sha256() {
82
82
  fi
83
83
  }
84
84
 
85
+ # Re-run the same provider-free AA decision immediately before a runner or one
86
+ # of its internal constituents/retries. Inputs are cooperative workflow
87
+ # metadata; hashes detect mutation after dispatch but do not authenticate the
88
+ # operator or prove the provider's actual model identity.
89
+ aa_policy_gate() {
90
+ local vendor="$1" model="$2" effort="$3" target_config="${4:-${OMNILANE_AA_TARGET_CONFIG:-}}"
91
+ local policy_file="${OMNILANE_AA_POLICY_FILE:-$OMNILANE_REPO/config/aa-model-policy.json}" output rc=0
92
+ local authorizer="${OMNILANE_AA_AUTHORIZER_CONTEXT-${OMNILANE_AA_CALLER_CONTEXT:-}}"
93
+ local authorizer_sha="${OMNILANE_AA_AUTHORIZER_SHA256-${OMNILANE_AA_CALLER_SHA256:-}}"
94
+ local args=()
95
+ if [[ "$vendor" == "vote" && "${OMNILANE_AA_VOTE_PREFLIGHT:-0}" == "1" ]]; then
96
+ return 0
97
+ fi
98
+ [[ -n "$policy_file" ]] || {
99
+ echo 'omnilane: AA policy metadata missing before provider invocation' >&2
100
+ return 3
101
+ }
102
+ args=(--registry "$policy_file" --vendor "$vendor" --model "$model" --effort "$effort")
103
+ [[ -z "${OMNILANE_AA_REGISTRY_SHA256:-}" ]] ||
104
+ args+=(--expected-registry-sha256 "$OMNILANE_AA_REGISTRY_SHA256")
105
+ [[ -z "$target_config" ]] || args+=(--target-config "$target_config")
106
+ if [[ "${OMNILANE_AA_AUTHORIZER_HUMAN-${OMNILANE_AA_OPERATOR_ASSERTED_HUMAN:-0}}" == "1" ]]; then
107
+ args+=(--operator-asserted-human)
108
+ elif [[ -n "$authorizer" ]]; then
109
+ args+=(--caller-context "$authorizer")
110
+ [[ -z "$authorizer_sha" ]] ||
111
+ args+=(--expected-caller-sha256 "$authorizer_sha")
112
+ fi
113
+ output="$(python3 "$OMNILANE_REPO/scripts/lib/aa_policy.py" "${args[@]}")" || rc=$?
114
+ if [[ "$rc" -ne 0 ]]; then
115
+ printf '%s\n' "$output" >&2
116
+ return "$rc"
117
+ fi
118
+ if [[ -n "${OMNILANE_AA_CONTEXT_DIR:-}" ]]; then
119
+ local child_path
120
+ child_path="$(python3 - "$OMNILANE_REPO" "$OMNILANE_AA_CONTEXT_DIR" "$output" <<'AA_CHILD'
121
+ import hashlib, json, sys
122
+ from pathlib import Path
123
+ sys.path.insert(0, str(Path(sys.argv[1]) / "scripts/lib"))
124
+ import aa_policy
125
+ decision = json.loads(sys.argv[3])
126
+ child = decision.get("child_context")
127
+ if child is not None:
128
+ name = "aa-child-" + hashlib.sha256(aa_policy._json_line(child).encode()).hexdigest() + ".json"
129
+ path = Path(sys.argv[2]) / name
130
+ aa_policy.atomic_json(path, child)
131
+ print(path)
132
+ AA_CHILD
133
+ )" || return $?
134
+ export OMNILANE_AA_CALLER_CONTEXT="$child_path"
135
+ export OMNILANE_AA_CALLER_SHA256=""
136
+ if [[ -n "$child_path" ]]; then
137
+ OMNILANE_AA_CALLER_SHA256="$(file_sha256 "$child_path")"
138
+ export OMNILANE_AA_CALLER_SHA256
139
+ fi
140
+ fi
141
+ return 0
142
+ }
143
+
85
144
  resolve_timeout_cmd() {
86
145
  if command -v timeout &>/dev/null; then echo "timeout";
87
146
  elif command -v gtimeout &>/dev/null; then echo "gtimeout";
@@ -43,6 +43,7 @@ emit_mode_notice() {
43
43
 
44
44
  run_single_shot() {
45
45
  local notice="$1" rc
46
+ aa_policy_gate "$VENDOR" "$MODEL" "$EFFORT" || return $?
46
47
  set +e
47
48
  (
48
49
  unset OMNILANE_INBOX
@@ -310,6 +311,7 @@ fi
310
311
 
311
312
  write_current_pid_file "$HOLDER_PID_FILE"
312
313
  export OMNILANE_INBOX="$RUNNER_INBOX_FIFO"
314
+ aa_policy_gate "$VENDOR" "$MODEL" "$EFFORT" || exit $?
313
315
  "$RUNNER" "$MODE" "$WORKDIR" "$MODEL" "$EFFORT" "$PROMPT_FILE" "$OUTPUT_FILE" 6<&- 7>&- &
314
316
  runner_pid=$!
315
317