omnilane 0.42.9 → 0.44.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +177 -1
- package/README.ja.md +169 -20
- package/README.ko.md +169 -20
- package/README.md +270 -61
- package/README.zh-CN.md +169 -19
- package/README.zh-TW.md +159 -41
- package/VERSION +1 -1
- package/bin/omnilane +29 -0
- package/completions/_omnilane +1 -1
- package/completions/omnilane.bash +1 -1
- package/completions/omnilane.fish +2 -0
- package/docs/native-executor.md +59 -0
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/dispatch.sh +54 -4
- package/scripts/doctor.sh +7 -1
- package/scripts/lib/aa_lanes.py +135 -0
- package/scripts/lib/aa_policy.py +154 -1
- package/scripts/lib/build_overlay.py +45 -18
- package/scripts/lib/caller_identity.py +75 -13
- package/scripts/lib/cli_provenance.py +82 -0
- package/scripts/lib/native.py +107 -2
- package/scripts/lib/native_context.py +145 -0
- package/scripts/lib/overlay_health.py +24 -2
- package/scripts/lib/probe.py +2 -0
- package/scripts/lib/probe_sweep.py +176 -0
- package/scripts/lib/resign.py +475 -0
- package/scripts/release-audit.sh +31 -0
- package/skills/omnilane/SKILL.md +375 -467
package/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://antigravity.google/schemas/v1/plugin.json",
|
|
3
3
|
"name": "omnilane",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.44.0",
|
|
5
5
|
"description": "One routing table, every harness: classify subtasks into lanes and delegate through compatible caller-owned native agents or vendor CLIs with exact-AA downward policy and supervised jobs."
|
|
6
6
|
}
|
package/scripts/dispatch.sh
CHANGED
|
@@ -35,7 +35,7 @@ MODE="advise"; WORKDIR="$PWD"; BACKGROUND=0; DRY_RUN=0
|
|
|
35
35
|
OVERRIDE_VENDOR=""; OVERRIDE_MODEL=""; OVERRIDE_EFFORT=""; OVERRIDE_TIMEOUT=""
|
|
36
36
|
OVERRIDE_JOB_TIMEOUT=""; OVERRIDE_IDLE_TIMEOUT=""; SESSION_REQUEST="auto"
|
|
37
37
|
THREAD_NAME=""; THREAD_MODE=""; THREAD_ID=""; THREAD_TURN=""; THREAD_CREATED=""
|
|
38
|
-
EXECUTOR="auto"; NATIVE_CONTEXT=""; RESOLVE_WITH_CONTEXT=0
|
|
38
|
+
EXECUTOR="auto"; NATIVE_CONTEXT=""; RESOLVE_WITH_CONTEXT=0; INHERIT=0
|
|
39
39
|
SELECTED_EXECUTOR="cli"; EXECUTOR_REASON="no-native-context"
|
|
40
40
|
AA_POLICY_FILE="${OMNILANE_AA_POLICY_FILE:-$OMNILANE_REPO/config/aa-model-policy.json}"
|
|
41
41
|
AA_CALLER_CONTEXT="${OMNILANE_AA_CALLER_CONTEXT:-}"
|
|
@@ -67,6 +67,8 @@ flags:
|
|
|
67
67
|
before any provider call or job state
|
|
68
68
|
--executor auto|native|cli caller-owned native handoff or legacy CLI
|
|
69
69
|
--native-context FILE explicit JSON capabilities; native is not a binary
|
|
70
|
+
--inherit native worker on the caller's own model and effort; resolves no
|
|
71
|
+
lane target, needs --native-context with inherits_caller_runtime
|
|
70
72
|
--caller-context FILE exact model caller identity plus inherited ceiling
|
|
71
73
|
--operator-asserted-human explicit AA model-ceiling exemption; assertion only
|
|
72
74
|
--aa-policy FILE frozen AA policy registry (default: repo config)
|
|
@@ -368,6 +370,18 @@ routing_candidate_available() {
|
|
|
368
370
|
fi
|
|
369
371
|
}
|
|
370
372
|
|
|
373
|
+
aa_print_refusal() {
|
|
374
|
+
# Refusal JSON on stderr, with the lanes this caller can still reach appended.
|
|
375
|
+
local helper="$OMNILANE_REPO/scripts/lib/aa_lanes.py"
|
|
376
|
+
if [[ -n "$AA_LAST_DECISION" && -r "$helper" ]] && command -v python3 >/dev/null 2>&1; then
|
|
377
|
+
printf '%s\n' "$AA_LAST_DECISION" | python3 "$helper" --registry "$AA_POLICY_FILE" --lane "${LANE:-}" \
|
|
378
|
+
--routing "$OMNILANE_HOME/routing.local.yaml" --routing "$OMNILANE_REPO/routing.yaml" >&2 \
|
|
379
|
+
|| printf '%s\n' "$AA_LAST_DECISION" >&2
|
|
380
|
+
else
|
|
381
|
+
printf '%s\n' "$AA_LAST_DECISION" >&2
|
|
382
|
+
fi
|
|
383
|
+
}
|
|
384
|
+
|
|
371
385
|
aa_policy_decide() {
|
|
372
386
|
# vendor model effort [target-config] -> structured JSON in AA_LAST_DECISION
|
|
373
387
|
local vendor="$1" model="$2" effort="$3" target_config="${4:-}" rc=0
|
|
@@ -712,6 +726,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
712
726
|
}
|
|
713
727
|
SESSION_REQUEST="single-shot"; shift ;;
|
|
714
728
|
--dry-run) DRY_RUN=1; shift ;;
|
|
729
|
+
--inherit) INHERIT=1; shift ;;
|
|
715
730
|
--operator-asserted-human)
|
|
716
731
|
AA_OPERATOR_ASSERTED_HUMAN=1; shift ;;
|
|
717
732
|
--mode|--workdir|--vendor|--model|--effort|--timeout|--job-timeout|--idle-timeout|--thread|--executor|--native-context|--caller-context|--aa-policy|--target-config|--transport-overlay)
|
|
@@ -823,6 +838,34 @@ case "$EXECUTOR" in
|
|
|
823
838
|
esac
|
|
824
839
|
|
|
825
840
|
CHAIN="$(raw_lane_line "$LANE")" || { echo "omnilane: unknown lane '$LANE' (try --list)" >&2; exit 2; }
|
|
841
|
+
if [[ "$INHERIT" -eq 1 ]]; then
|
|
842
|
+
# A worker that inherits this caller's own model and effort runs inside the
|
|
843
|
+
# harness: no lane target is resolved, no vendor CLI or transport overlay is
|
|
844
|
+
# involved, and the lane is only a label for what the work is.
|
|
845
|
+
[[ -z "$OVERRIDE_VENDOR$OVERRIDE_MODEL$OVERRIDE_EFFORT$AA_TARGET_CONFIG" ]] || {
|
|
846
|
+
echo "omnilane: --inherit takes no --vendor, --model, --effort or --target-config; it overrides nothing" >&2
|
|
847
|
+
exit 2
|
|
848
|
+
}
|
|
849
|
+
[[ "$EXECUTOR" != "cli" ]] || { echo "omnilane: --inherit is native only" >&2; exit 2; }
|
|
850
|
+
command -v python3 >/dev/null 2>&1 || { echo "omnilane: native protocol requires Python 3" >&2; exit 2; }
|
|
851
|
+
INHERIT_TIMEOUT="${OVERRIDE_TIMEOUT:-${OMNILANE_TIMEOUT:-600}}"
|
|
852
|
+
[[ "$INHERIT_TIMEOUT" =~ ^[1-9][0-9]*$ ]] || {
|
|
853
|
+
echo "omnilane: invalid timeout (want a positive integer of seconds)" >&2; exit 2
|
|
854
|
+
}
|
|
855
|
+
INHERIT_ARGS=(route --inherit --home "$OMNILANE_HOME" --executor native --lane "$LANE"
|
|
856
|
+
--workdir "$WORKDIR" --mode "$MODE" --task="$TASK" --session "$SESSION_REQUEST"
|
|
857
|
+
--thread "$THREAD_NAME" --policy "$AA_POLICY_FILE" --timeout "$INHERIT_TIMEOUT"
|
|
858
|
+
--job-timeout "${OVERRIDE_JOB_TIMEOUT:-}" --idle-timeout "${OVERRIDE_IDLE_TIMEOUT:-}")
|
|
859
|
+
[[ -z "$NATIVE_CONTEXT" ]] || INHERIT_ARGS+=(--context "$NATIVE_CONTEXT")
|
|
860
|
+
if [[ "$AA_OPERATOR_ASSERTED_HUMAN" == "1" ]]; then
|
|
861
|
+
INHERIT_ARGS+=(--operator-asserted-human)
|
|
862
|
+
elif [[ -n "$AA_CALLER_CONTEXT" ]]; then
|
|
863
|
+
INHERIT_ARGS+=(--caller-context "$AA_CALLER_CONTEXT")
|
|
864
|
+
fi
|
|
865
|
+
[[ "$BACKGROUND" -eq 0 ]] || INHERIT_ARGS+=(--background)
|
|
866
|
+
[[ "$DRY_RUN" -eq 0 ]] || INHERIT_ARGS+=(--dry-run)
|
|
867
|
+
exec python3 "$OMNILANE_REPO/scripts/lib/native.py" "${INHERIT_ARGS[@]}"
|
|
868
|
+
fi
|
|
826
869
|
if [[ -n "$OVERRIDE_VENDOR" ]]; then
|
|
827
870
|
if resolve_chain "$CHAIN" "$OVERRIDE_VENDOR"; then
|
|
828
871
|
:
|
|
@@ -835,7 +878,7 @@ if [[ -n "$OVERRIDE_VENDOR" ]]; then
|
|
|
835
878
|
exit 4
|
|
836
879
|
;;
|
|
837
880
|
6)
|
|
838
|
-
|
|
881
|
+
aa_print_refusal
|
|
839
882
|
exit 3
|
|
840
883
|
;;
|
|
841
884
|
5)
|
|
@@ -852,11 +895,11 @@ else
|
|
|
852
895
|
resolve_rc=0
|
|
853
896
|
resolve_chain "$CHAIN" || resolve_rc=$?
|
|
854
897
|
if [[ "$resolve_rc" -eq 6 ]]; then
|
|
855
|
-
|
|
898
|
+
aa_print_refusal
|
|
856
899
|
exit 3
|
|
857
900
|
elif [[ "$resolve_rc" -ne 0 ]]; then
|
|
858
901
|
echo "omnilane: no eligible available target for lane '$LANE' (chain:$CHAIN)." >&2
|
|
859
|
-
[[ -z "$AA_LAST_DECISION" ]] ||
|
|
902
|
+
[[ -z "$AA_LAST_DECISION" ]] || aa_print_refusal
|
|
860
903
|
exit 4
|
|
861
904
|
fi
|
|
862
905
|
fi
|
|
@@ -1110,6 +1153,13 @@ if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
|
1110
1153
|
fi
|
|
1111
1154
|
|
|
1112
1155
|
printf 'omnilane: executor=cli reason=%s\n' "$EXECUTOR_REASON" >&2
|
|
1156
|
+
if [[ "$EXECUTOR_REASON" == "no-native-context" && -n "$AA_CALLER_CONTEXT" && -r "$AA_CALLER_CONTEXT" ]]; then
|
|
1157
|
+
CALLER_VENDOR="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["caller"]["vendor"])' "$AA_CALLER_CONTEXT" 2>/dev/null || true)"
|
|
1158
|
+
if [[ -n "$CALLER_VENDOR" && "$CALLER_VENDOR" == "$VENDOR" ]]; then
|
|
1159
|
+
# Same vendor is not same model, so this is an offer, never a silent switch.
|
|
1160
|
+
echo "omnilane: the target is this harness's own vendor, yet it goes out through an external CLI because no capability file was given. To use your own sub-agent tool: omnilane native-context --workdir \"$WORKDIR\", then pass --native-context FILE (or --inherit for a worker on your own model and effort)" >&2
|
|
1161
|
+
fi
|
|
1162
|
+
fi
|
|
1113
1163
|
mkdir -p "$OMNILANE_HOME"
|
|
1114
1164
|
if [[ ! -d "$JOBS_ROOT" ]]; then
|
|
1115
1165
|
mkdir -m 700 "$JOBS_ROOT"
|
package/scripts/doctor.sh
CHANGED
|
@@ -419,7 +419,13 @@ overlay_path="$(
|
|
|
419
419
|
printf '%s' "${OMNILANE_AA_TRANSPORT_OVERLAY:-}"
|
|
420
420
|
)"
|
|
421
421
|
if [[ -z "$overlay_path" ]]; then
|
|
422
|
-
|
|
422
|
+
# Only a model caller needs the overlay; a host whose operator asserts the human
|
|
423
|
+
# exemption is complete without one, and --strict must not fail it.
|
|
424
|
+
if [[ "${OMNILANE_AA_OPERATOR_ASSERTED_HUMAN:-0}" == "1" ]]; then
|
|
425
|
+
report PASS transport-overlay "no overlay configured; fine for a human operator, but a model caller would be refused on every lane (README, 'Let your AI assistant drive omnilane')"
|
|
426
|
+
else
|
|
427
|
+
report WARN transport-overlay "no overlay configured, so a model caller is refused on every lane (runtime-mapping-unverified). First install: probe_sweep.py --root ROOT, build_overlay.py --root ROOT, then export OMNILANE_AA_TRANSPORT_OVERLAY in local.sh; see the README, 'Let your AI assistant drive omnilane'"
|
|
428
|
+
fi
|
|
423
429
|
elif ! command -v python3 >/dev/null 2>&1; then
|
|
424
430
|
report WARN transport-overlay "python3 is absent; cannot load the AA transport overlay"
|
|
425
431
|
elif [[ ! -r "$OVERLAY_HEALTH" ]]; then
|
|
@@ -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())
|
package/scripts/lib/aa_policy.py
CHANGED
|
@@ -239,7 +239,13 @@ def load_caller(path: str | Path, registry: dict[str, Any],
|
|
|
239
239
|
_check(value.get("snapshot_id") == registry["snapshot"]["id"],
|
|
240
240
|
"caller-context snapshot does not match frozen registry")
|
|
241
241
|
_check(value.get("kind") == "model", "unsupported caller-context kind")
|
|
242
|
+
# effort_unverified marks a caller degraded to its model's lowest-scored row
|
|
243
|
+
# because the launching harness recorded no effort; it may only be true.
|
|
244
|
+
unverified = value.pop("effort_unverified", None)
|
|
245
|
+
_check(unverified is None or unverified is True, "invalid caller-context effort_unverified")
|
|
242
246
|
_exact_fields(value, {"schema_version", "snapshot_id", "kind", "caller", "inherited_ceiling"})
|
|
247
|
+
if unverified:
|
|
248
|
+
value["effort_unverified"] = True
|
|
243
249
|
value["caller"] = _identity(value["caller"], "caller")
|
|
244
250
|
ceiling = value["inherited_ceiling"]
|
|
245
251
|
_check(type(ceiling) is int and 0 <= ceiling <= 100,
|
|
@@ -345,10 +351,15 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
|
|
|
345
351
|
"file it prints as --caller-context, which dispatch does itself when the "
|
|
346
352
|
"launching CLI names its model and effort; a human operator passes "
|
|
347
353
|
"--operator-asserted-human"),
|
|
354
|
+
failed_gate="caller-identity",
|
|
355
|
+
reason="no caller identity reached the gate",
|
|
356
|
+
next_command="omnilane whoami",
|
|
348
357
|
)
|
|
349
358
|
return base
|
|
350
359
|
base["caller_context_sha256"] = caller_sha256
|
|
351
360
|
caller_identity = caller["caller"]
|
|
361
|
+
degraded = caller.get("effort_unverified") is True
|
|
362
|
+
base["caller_degraded"] = degraded
|
|
352
363
|
caller_rows = _matching_rows(registry, caller_identity)
|
|
353
364
|
if len(caller_rows) != 1:
|
|
354
365
|
detail = _unknown_reason(registry, caller_identity)
|
|
@@ -356,9 +367,24 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
|
|
|
356
367
|
code="unknown-caller-config" if not caller_rows else "ambiguous-caller-config",
|
|
357
368
|
message=detail or "caller exact vendor/model/effort/reasoning/fallback is not uniquely scored",
|
|
358
369
|
caller=caller_identity,
|
|
370
|
+
failed_gate="caller-identity",
|
|
371
|
+
reason="the caller context names a configuration the frozen registry does not score exactly once",
|
|
372
|
+
next_command="omnilane whoami",
|
|
359
373
|
)
|
|
360
374
|
return base
|
|
361
375
|
caller_row = caller_rows[0]
|
|
376
|
+
model_rows = [row for row in registry["scored_configs"]
|
|
377
|
+
if row["vendor"] == caller_row["vendor"] and row["model"] == caller_row["model"]]
|
|
378
|
+
if degraded and caller_row["score"] != min(row["score"] for row in model_rows):
|
|
379
|
+
base.update(
|
|
380
|
+
code="invalid-degraded-caller",
|
|
381
|
+
message="an effort-unverified caller must name its model's lowest-scored row",
|
|
382
|
+
caller=caller_identity,
|
|
383
|
+
failed_gate="caller-identity",
|
|
384
|
+
reason="effort_unverified was set on a row above the model's floor",
|
|
385
|
+
next_command="omnilane whoami",
|
|
386
|
+
)
|
|
387
|
+
return base
|
|
362
388
|
effective = min(caller_row["score"], caller["inherited_ceiling"])
|
|
363
389
|
base.update(
|
|
364
390
|
caller=caller_identity,
|
|
@@ -370,7 +396,14 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
|
|
|
370
396
|
registry, vendor, model, effort, target_config
|
|
371
397
|
)
|
|
372
398
|
if target_row is None:
|
|
373
|
-
base.update(
|
|
399
|
+
base.update(
|
|
400
|
+
code=mapping_code,
|
|
401
|
+
message="target runtime cannot be mapped to one verified exact AA configuration",
|
|
402
|
+
failed_gate="target-transport",
|
|
403
|
+
reason=("the caller is identified; this host's transport overlay does not currently "
|
|
404
|
+
f"verify {vendor} {model} at effort {effort}"),
|
|
405
|
+
next_command="omnilane resign --check",
|
|
406
|
+
**detail)
|
|
374
407
|
return base
|
|
375
408
|
target_score = target_row["score"]
|
|
376
409
|
target_identity = _row_identity(target_row)
|
|
@@ -381,9 +414,30 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
|
|
|
381
414
|
target_estimated=target_row["estimated"],
|
|
382
415
|
)
|
|
383
416
|
if target_score > effective:
|
|
417
|
+
reaching = sorted((row for row in model_rows if row["score"] >= target_score),
|
|
418
|
+
key=lambda row: (row["score"], row["id"]))
|
|
419
|
+
required = reaching[0]["effort"] or "none" if reaching else None
|
|
420
|
+
if caller["inherited_ceiling"] < caller_row["score"]:
|
|
421
|
+
reason = ("this worker inherited a ceiling below the target; only the session that "
|
|
422
|
+
"dispatched it, or a human operator, can reach this target")
|
|
423
|
+
required = None
|
|
424
|
+
elif required is None:
|
|
425
|
+
reason = (f"no scored effort of {caller_row['model']} reaches {target_score}; a "
|
|
426
|
+
"stronger caller model or a human operator has to dispatch this target")
|
|
427
|
+
elif degraded:
|
|
428
|
+
reason = (f"the launching harness recorded no effort, so the caller was held to "
|
|
429
|
+
f"{caller_row['model']}'s floor of {effective}; relaunch the session with an "
|
|
430
|
+
f"explicit effort of {required} or higher")
|
|
431
|
+
else:
|
|
432
|
+
reason = (f"relaunch the calling session at effort {required} or higher, or have a "
|
|
433
|
+
"human operator dispatch this target")
|
|
384
434
|
base.update(
|
|
385
435
|
code="target-above-effective-ceiling",
|
|
386
436
|
message=f"target score {target_score} exceeds effective caller ceiling {effective}",
|
|
437
|
+
failed_gate="downward-ceiling",
|
|
438
|
+
reason=reason,
|
|
439
|
+
required_caller_effort=required,
|
|
440
|
+
next_command="omnilane list",
|
|
387
441
|
)
|
|
388
442
|
return base
|
|
389
443
|
child_context = {
|
|
@@ -402,6 +456,105 @@ def decide(registry: dict[str, Any], registry_sha256: str, *,
|
|
|
402
456
|
return base
|
|
403
457
|
|
|
404
458
|
|
|
459
|
+
def decide_inherited(registry: dict[str, Any], registry_sha256: str, *,
|
|
460
|
+
caller: dict[str, Any] | None, caller_sha256: str | None,
|
|
461
|
+
operator_asserted_human: bool = False,
|
|
462
|
+
host_asserted: dict[str, str] | None = None) -> dict[str, Any]:
|
|
463
|
+
"""A native worker that inherits the caller's own model and effort unchanged.
|
|
464
|
+
|
|
465
|
+
It runs what the caller runs, so it scores what the caller scores and cannot
|
|
466
|
+
be an upward dispatch, whether or not the caller's effort is known. There is
|
|
467
|
+
no external CLI, so no transport mapping is involved. It is nobody's lane
|
|
468
|
+
target: the decision names no target configuration and must not be reported
|
|
469
|
+
as satisfying one.
|
|
470
|
+
|
|
471
|
+
None of that rests on knowing who the caller is, so a caller whose identity
|
|
472
|
+
cannot be read still gets an inherited worker, on the host's word for its
|
|
473
|
+
vendor and model. That decision is marked unverified, carries no ceiling and
|
|
474
|
+
publishes no child context: a worker that tried to dispatch would have no
|
|
475
|
+
identity to dispatch with.
|
|
476
|
+
"""
|
|
477
|
+
base: dict[str, Any] = {
|
|
478
|
+
"schema_version": 1,
|
|
479
|
+
"snapshot_id": registry["snapshot"]["id"],
|
|
480
|
+
"registry_sha256": registry_sha256,
|
|
481
|
+
"allowed": False,
|
|
482
|
+
"code": "deny",
|
|
483
|
+
"message": "AA policy denied dispatch",
|
|
484
|
+
"caller_kind": "operator-asserted-human" if operator_asserted_human else "model",
|
|
485
|
+
"target_request": {"vendor": None, "model": None, "effort": None, "inherit": True},
|
|
486
|
+
"target_config_id": None,
|
|
487
|
+
"caller_score": None,
|
|
488
|
+
"inherited_ceiling": None,
|
|
489
|
+
"effective_ceiling": None,
|
|
490
|
+
"target_score": None,
|
|
491
|
+
"target_estimated": None,
|
|
492
|
+
"child_context": None,
|
|
493
|
+
"evidence_limit": ("the host asserts that a sub-agent spawned without a model override "
|
|
494
|
+
"inherits the caller's runtime; omnilane cannot observe it"),
|
|
495
|
+
}
|
|
496
|
+
if operator_asserted_human:
|
|
497
|
+
base.update(code="inherit-requires-model-caller",
|
|
498
|
+
message="only a model running inside a harness has a runtime to inherit",
|
|
499
|
+
failed_gate="caller-identity",
|
|
500
|
+
reason="a human operator has no sub-agent tool; dispatch a lane instead",
|
|
501
|
+
next_command="omnilane list")
|
|
502
|
+
return base
|
|
503
|
+
if caller is None and host_asserted is not None:
|
|
504
|
+
base.update(allowed=True, code="native-inherited-unverified-caller",
|
|
505
|
+
message="the worker inherits the caller's own runtime, so it cannot score above it; "
|
|
506
|
+
"the caller's vendor and model are the host's statement, not a verified identity",
|
|
507
|
+
caller_kind="model-unverified", caller_identity_verified=False,
|
|
508
|
+
caller_identity_source="host-asserted",
|
|
509
|
+
target={"inherit": True, "vendor": host_asserted["vendor"],
|
|
510
|
+
"model": host_asserted["model"]})
|
|
511
|
+
return base
|
|
512
|
+
if caller is None:
|
|
513
|
+
base.update(code="missing-caller-context",
|
|
514
|
+
message="no caller identity: an inherited worker still has to know whose runtime it inherits",
|
|
515
|
+
failed_gate="caller-identity",
|
|
516
|
+
reason="no caller identity reached the gate and the capability file names no current_model",
|
|
517
|
+
next_command="omnilane whoami # if that cannot read this harness: omnilane "
|
|
518
|
+
"native-context --vendor VENDOR --model MODEL --inherits-caller-runtime")
|
|
519
|
+
return base
|
|
520
|
+
base["caller_context_sha256"] = caller_sha256
|
|
521
|
+
base["caller_identity_verified"] = True
|
|
522
|
+
base["caller_identity_source"] = "caller-context"
|
|
523
|
+
identity = caller["caller"]
|
|
524
|
+
degraded = caller.get("effort_unverified") is True
|
|
525
|
+
rows = _matching_rows(registry, identity)
|
|
526
|
+
if len(rows) != 1:
|
|
527
|
+
base.update(code="unknown-caller-config" if not rows else "ambiguous-caller-config",
|
|
528
|
+
message=_unknown_reason(registry, identity)
|
|
529
|
+
or "caller exact vendor/model/effort/reasoning/fallback is not uniquely scored",
|
|
530
|
+
caller=identity, failed_gate="caller-identity",
|
|
531
|
+
reason="the caller context names a configuration the frozen registry does not score exactly once",
|
|
532
|
+
next_command="omnilane whoami")
|
|
533
|
+
return base
|
|
534
|
+
row = rows[0]
|
|
535
|
+
floor = min(r["score"] for r in registry["scored_configs"]
|
|
536
|
+
if r["vendor"] == row["vendor"] and r["model"] == row["model"])
|
|
537
|
+
if degraded and row["score"] != floor:
|
|
538
|
+
base.update(code="invalid-degraded-caller",
|
|
539
|
+
message="an effort-unverified caller must name its model's lowest-scored row",
|
|
540
|
+
caller=identity, failed_gate="caller-identity",
|
|
541
|
+
reason="effort_unverified was set on a row above the model's floor",
|
|
542
|
+
next_command="omnilane whoami")
|
|
543
|
+
return base
|
|
544
|
+
effective = min(row["score"], caller["inherited_ceiling"])
|
|
545
|
+
child = {"schema_version": 1, "snapshot_id": registry["snapshot"]["id"], "kind": "model",
|
|
546
|
+
"caller": identity, "inherited_ceiling": effective}
|
|
547
|
+
if degraded:
|
|
548
|
+
child["effort_unverified"] = True
|
|
549
|
+
base.update(allowed=True, code="native-inherited-allowed",
|
|
550
|
+
message="the worker inherits the caller's own runtime, so it cannot score above it",
|
|
551
|
+
caller=identity, caller_degraded=degraded, caller_score=row["score"],
|
|
552
|
+
inherited_ceiling=caller["inherited_ceiling"], effective_ceiling=effective,
|
|
553
|
+
target={"inherit": True, "vendor": row["vendor"], "model": row["model"]},
|
|
554
|
+
child_context=child)
|
|
555
|
+
return base
|
|
556
|
+
|
|
557
|
+
|
|
405
558
|
def _normalized_effort(value: str) -> str | None:
|
|
406
559
|
return None if value in ("", "-") else value
|
|
407
560
|
|
|
@@ -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
|
-
|
|
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
|
|
@@ -98,19 +104,21 @@ def cli_path(name: str) -> Path:
|
|
|
98
104
|
return Path(found).resolve()
|
|
99
105
|
|
|
100
106
|
|
|
107
|
+
RUNNERS = {"grok": "run-grok.sh", "codex": "run-codex.sh", "claude": "run-claude.sh",
|
|
108
|
+
"gemini": "run-gemini.sh"}
|
|
109
|
+
CLI_NAMES = {"grok": "grok", "codex": "codex", "claude": "claude", "gemini": "agy"}
|
|
110
|
+
|
|
111
|
+
|
|
101
112
|
def core_evidence() -> list[tuple[Path, str]]:
|
|
102
113
|
"""Resolved when a build runs, not at import: a host missing one CLI can
|
|
103
114
|
still load this module to read PROVEN."""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(cli_path("agy"), "gemini"),
|
|
112
|
-
(REPO / "scripts/runners/run-gemini.sh", "gemini"),
|
|
113
|
-
]
|
|
115
|
+
anchors = []
|
|
116
|
+
for vendor in ("grok", "codex", "claude", "gemini"):
|
|
117
|
+
if shutil.which(CLI_NAMES[vendor]) is None:
|
|
118
|
+
continue # not installed here: main() signs nothing for it
|
|
119
|
+
anchors += [(cli_path(CLI_NAMES[vendor]), vendor),
|
|
120
|
+
(REPO / "scripts/runners" / RUNNERS[vendor], vendor)]
|
|
121
|
+
return anchors
|
|
114
122
|
|
|
115
123
|
|
|
116
124
|
def sha256(path: Path) -> str:
|
|
@@ -129,6 +137,12 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
129
137
|
default=DEFAULT_ROOT,
|
|
130
138
|
help=f"probe sweep root (default: {DEFAULT_ROOT})",
|
|
131
139
|
)
|
|
140
|
+
parser.add_argument(
|
|
141
|
+
"--source",
|
|
142
|
+
default=os.environ.get("OMNILANE_TRANSPORT_SOURCE")
|
|
143
|
+
or f"{socket.gethostname()} / build_overlay {datetime.now(timezone.utc).date().isoformat()}",
|
|
144
|
+
help="free-text provenance recorded in the overlay",
|
|
145
|
+
)
|
|
132
146
|
args = parser.parse_args(argv)
|
|
133
147
|
root = args.root.expanduser()
|
|
134
148
|
|
|
@@ -144,7 +158,11 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
144
158
|
if path.exists():
|
|
145
159
|
entry[suffix] = {"path": str(path), "sha256": sha256(path)}
|
|
146
160
|
if "json" not in entry:
|
|
147
|
-
|
|
161
|
+
# A vendor nobody is logged in to was never probed; that is a gap in this
|
|
162
|
+
# host's overlay, not a reason to refuse to sign the vendors that were.
|
|
163
|
+
unproven.append({"config_id": cid, "verdict_reason": "not probed on this host",
|
|
164
|
+
"observed_model": None, "probed_at": None})
|
|
165
|
+
continue
|
|
148
166
|
descriptor_path = Path(entry["json"]["path"])
|
|
149
167
|
descriptor = json.loads(descriptor_path.read_text())
|
|
150
168
|
if not isinstance(descriptor, dict):
|
|
@@ -169,11 +187,18 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
169
187
|
manifest_path = root / "probe-manifest.json"
|
|
170
188
|
manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
|
|
171
189
|
|
|
190
|
+
anchors = core_evidence()
|
|
191
|
+
anchored = {vendor for _, vendor in anchors}
|
|
172
192
|
mappings = []
|
|
173
193
|
for cid, (selector, runtime_model, _) in sorted(PROVEN.items()):
|
|
174
194
|
if cid not in manifest["probe_runs"]:
|
|
175
195
|
continue
|
|
176
196
|
row = ROWS[cid]
|
|
197
|
+
if row["vendor"] not in anchored:
|
|
198
|
+
# Evidence with no executable to pin it to verifies nothing.
|
|
199
|
+
unproven.append({"config_id": cid, "verdict_reason": "vendor CLI is not installed",
|
|
200
|
+
"observed_model": None, "probed_at": None})
|
|
201
|
+
continue
|
|
177
202
|
mapping = {
|
|
178
203
|
"config_id": cid,
|
|
179
204
|
"identity": {key: row[key] for key in IDENTITY_FIELDS},
|
|
@@ -187,18 +212,20 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
187
212
|
mapping["cli_flag"] = "--reasoning-effort"
|
|
188
213
|
mappings.append(mapping)
|
|
189
214
|
|
|
190
|
-
evidence = [
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
215
|
+
evidence = []
|
|
216
|
+
for path, vendor in anchors:
|
|
217
|
+
anchor = {"path": str(path), "sha256": sha256(path), "vendor": vendor}
|
|
218
|
+
if path.name != RUNNERS[vendor]:
|
|
219
|
+
# The signer an unattended re-sign is later held to; see cli_provenance.
|
|
220
|
+
anchor["codesign"] = cli_provenance.facts(path)
|
|
221
|
+
evidence.append(anchor)
|
|
194
222
|
evidence.append({"path": str(manifest_path), "sha256": sha256(manifest_path)})
|
|
195
223
|
|
|
196
224
|
overlay = {
|
|
197
225
|
"schema_version": 1,
|
|
198
226
|
"snapshot_id": REGISTRY["snapshot"]["id"],
|
|
199
227
|
"host": socket.gethostname(),
|
|
200
|
-
"source":
|
|
201
|
-
"gemini selectors re-probed 2026-09-09 after agy 1.1.27 -> 1.1.28"),
|
|
228
|
+
"source": args.source,
|
|
202
229
|
"evidence": evidence,
|
|
203
230
|
"mappings": mappings,
|
|
204
231
|
"unproven": unproven,
|