Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 40 additions & 21 deletions docs/adr/0003-contextual-orchestrator-vendored-free-zdr.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,44 @@ all five, and auto-optimize routing by cost.
transport only; request-time credential reads go through the KV.
2. **Auto model discovery + governed virtual pools**: discovery runs with the
orchestrator's own `discover_all_models()` against the KV credentials.
OpenCode and Noema admit only zero-priced routes. Strix admits provider-
diverse priced routes only when discovery supplies finite, nonnegative
prompt and completion prices plus an explicit currency; missing or malformed
price evidence fails closed. The gateway's
OpenCode and Noema admit only zero-priced routes. Strix admits two explicit
evidence tiers: zero-priced first, then routes with finite,
nonnegative prompt and completion prices plus an explicit currency. Routes
without a complete published price vector remain counted for audit but are
not admitted to CI review. A missing pair is never relabeled free or
price-attested; a partial price vector, malformed numeric value, conflicting
free marker, or missing currency for a published vector fails closed. The gateway's
`orchestrator/free` virtual id fails closed (`400 invalid_model`) unless an
enabled zero-cost agent exists. Strix uses `orchestrator/auto`; its catalog
may admit priced routes only through the same evidence-bearing policy, never
through a direct-provider model identifier.
3. **ZDR-first selection**: `scripts/ci/zdr_policy.py` defines ZDR the way
OpenRouter does ("a provider will not store your data for any period of
time"; zero retention also implies no training) and is deliberately
may admit priced routes only through this evidence-bearing
policy, never through a direct-provider model identifier.
The auto pool probes the free catalog first. Only when every selected free
route rejects the real runtime request contract does it rebuild once from
fully price-attested routes and record the rejected primary attempt. This is
evidence-triggered failover, not an arbitrary free/paid mixing ratio.
Both stages share one twelve-route startup budget: no more than eight routes
enter the free primary stage and only its remaining capacity may enter priced
fallback. Full discovery counts remain in policy evidence, and the transient
priced catalog is removed immediately after loading.
3. **ZDR-first within each cost tier**: `scripts/ci/zdr_policy.py` defines ZDR
the way OpenRouter does ("a provider will not store your data for any period
of time"; zero retention also implies no training) and is deliberately
conservative: any provider whose zero-retention guarantee cannot be
attested from a machine-readable, dated source is treated as non-ZDR,
mirroring OpenRouter's stance on unascertained policies. The
OpenRouter `/api/v1/endpoints/zdr` feed (documented, auto-updated) is
fetched when egress allows it and is authoritative for the `openrouter`
scope; otherwise the dated static attestation table is used, never a
fabricated policy.
`scripts/ci/contextual_orchestrator_review_policy.py` turns the price-
evidenced discovery report into a ZDR-prioritized, provider-family-diverse agents
catalog (primary/secondary NVIDIA keys share one outage-domain family),
capped in size, in the orchestrator's own `ModelAgent` schema.
For private targets, ZDR admission is applied before choosing the cost tier.
A discovered but non-ZDR free route therefore cannot suppress an attested
priced route; when an admitted free tier exists it remains the exclusive
primary, and the admitted priced tier remains fallback-only.
`scripts/ci/contextual_orchestrator_review_policy.py` turns the discovery
report into a free-first, cost-evidence-ranked, ZDR-prioritized,
provider-family-diverse agents catalog (primary/secondary NVIDIA keys share
one outage-domain family), capped in size, in the orchestrator's own
`ModelAgent` schema.
4. **Wiring**: `pr-review-autofix.yml` and the Required OpenCode dispatch
provision the sidecar with the five secrets before OpenCode runs and point
every model/diagnosis candidate at `contextual-orchestrator/orchestrator/free`;
Expand All @@ -66,17 +82,18 @@ all five, and auto-optimize routing by cost.
discovered free routes all shared the OpenRouter outage domain, which the
gateway correctly collapsed to one provider attempt. Strix therefore uses
the provider-diverse pool supplied by all five configured credentials.
Provider diversity and provider cost evidence remain delegated to the
Provider diversity and cost-evidence classification remain delegated to the
gateway rather than embedding a second routing policy in GitHub Actions.
Strix has no external fallback and private targets pass
visibility through to the gateway's ZDR requirement. Noema reviewer identity
remains `NOEMA_REVIEW_TOKEN` / GitHub App / OIDC and is still never
`github.token`; Autofix mutation still requires `PR_REVIEW_MERGE_TOKEN` /
Strix has no external fallback and private targets pass visibility through
to the gateway's ZDR requirement. Noema reviewer identity remains
`NOEMA_REVIEW_TOKEN` / GitHub App / OIDC and is still never `github.token`;
Autofix mutation still requires `PR_REVIEW_MERGE_TOKEN` /
`OPENCODE_APPROVE_TOKEN` / the exchanged OpenCode app token, never
`github.token`; model subprocesses still run with
`GITHUB_TOKEN`/`GH_TOKEN`/OIDC request env stripped.
5. **Evidence**: the sidecar writes a discovery report, the policy report (pool,
counts, ZDR sources, feed-used flag, selected routes), and exports
total/free/priced/unknown counts, selected counts by admitted cost tier, ZDR
sources, feed-used flag, selected routes), and exports
`CONTEXTUAL_ORCHESTRATOR_EVIDENCE`; these are auditable per run.
6. **Review request envelope**: the library keeps its generic 64 KiB default,
while this loopback, bearer-authenticated, per-job sidecar configures a
Expand All @@ -91,10 +108,12 @@ all five, and auto-optimize routing by cost.
- The autofix/OpenCode review paths no longer hard-code any provider base URL
or model id; upstream model selection is delegated to the orchestrator's
discovery under the zero-cost pool. Strix uses the separately governed auto
pool without treating absent price metadata as paid-route evidence.
pool without treating absent price metadata as either free or paid-route
evidence.
- Strix delegates selection to `orchestrator/auto`. Its correctness-first pool
remains distinct from the zero-cost OpenCode/Noema pool, while private-target
ZDR admission remains fail-closed.
ZDR admission remains fail-closed. Unknown-cost routes remain auditable but
ineligible; free and fully price-attested routes are the only review routes.
- Workers need egress to the five provider model-list hosts and, when reachable,
`https://openrouter.ai/api/v1/endpoints/zdr`; the feed failure path is
graceful (static table).
Expand Down
179 changes: 176 additions & 3 deletions scripts/ci/contextual_orchestrator_review_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
# for a required CI gate. With at most twelve sequential candidates, startup is
# bounded below the sidecar's three-minute readiness deadline.
REVIEW_PREFLIGHT_TIMEOUT_SECONDS = 10
REVIEW_PREFLIGHT_MAX_TOTAL_ROUTES = 12
REVIEW_PREFLIGHT_PRIMARY_ROUTE_LIMIT = 8


class ReviewPreflightError(RuntimeError):
Expand Down Expand Up @@ -222,13 +224,106 @@ def _preflight_review_agents(
return viable, report


def _preflight_with_fallback(
primary_agents: list[object], fallback_agents: list[object], *, client: Any
) -> tuple[list[object], dict[str, object], bool]:
"""Use the priced catalog only after every primary route rejects."""
try:
viable, report = _preflight_review_agents(primary_agents, client=client)
return viable, report, False
except ReviewPreflightError as primary_error:
if not fallback_agents:
raise
try:
viable, report = _preflight_review_agents(fallback_agents, client=client)
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
except ReviewPreflightError as fallback_error:
fallback_error.report["primary_attempt"] = primary_error.report
raise
report["primary_attempt"] = primary_error.report
report["fallback_reason"] = "primary_routes_unavailable"
return viable, report, True


def _write_json(path: str, payload: object) -> None:
"""Write one deterministic UTF-8 JSON evidence file."""
Path(path).write_text(
json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)


def _bounded_primary_catalog_limit(
requested_limit: int, *, pool: str, has_free_rows: bool
) -> int:
"""Return the primary-stage route limit within one startup budget."""
if requested_limit < 1:
raise ValueError("ORCHESTRATOR_CATALOG_LIMIT must be positive")
total_limit = min(requested_limit, REVIEW_PREFLIGHT_MAX_TOTAL_ROUTES)
if pool == "auto" and has_free_rows:
return min(total_limit, REVIEW_PREFLIGHT_PRIMARY_ROUTE_LIMIT)
return total_limit


def _bounded_fallback_catalog_limit(
requested_limit: int, *, primary_count: int
) -> int:
"""Return remaining priced-fallback capacity after primary selection."""
if requested_limit < 1:
raise ValueError("ORCHESTRATOR_CATALOG_LIMIT must be positive")
total_limit = min(requested_limit, REVIEW_PREFLIGHT_MAX_TOTAL_ROUTES)
if primary_count < 0 or primary_count > total_limit:
raise ValueError("primary route count exceeds the preflight budget")
return total_limit - primary_count


def _with_discovery_counts(
report: dict[str, object], rows: list[dict[str, Any]]
) -> dict[str, object]:
"""Copy a stage report while restoring full discovery-tier counts."""
enriched = dict(report)
enriched.update(
{
"total_routes": len(rows),
"total_free_routes": sum(row.get("cost_evidence") == "free" for row in rows),
"total_priced_routes": sum(row.get("cost_evidence") == "priced" for row in rows),
"total_unknown_routes": sum(row.get("cost_evidence") == "unknown" for row in rows),
}
)
return enriched


def _zdr_admitted_rows(
rows: list[dict[str, Any]],
*,
require_zdr: bool,
zdr_endpoints: frozenset[str],
checker: Any,
) -> list[dict[str, Any]]:
"""Return rows that can enter the selected privacy boundary."""
if not require_zdr:
return list(rows)
return [
row
for row in rows
if checker(
str(row["provider"]),
model=str(row["model"]),
zdr_endpoints=zdr_endpoints,
)
]


def _load_temporary_agents(
path: str, catalog_agents: list[dict[str, Any]], *, loader: Any
) -> list[object]:
"""Load one transient catalog and remove it on every exit path."""
catalog_path = Path(path)
_write_json(str(catalog_path), {"agents": catalog_agents})
try:
return list(loader(str(catalog_path)))
finally:
catalog_path.unlink(missing_ok=True)


def main(argv: list[str] | None = None) -> int:
"""Bootstrap the KV, discover and preflight free models, then serve.

Expand Down Expand Up @@ -269,8 +364,10 @@ def main(argv: list[str] | None = None) -> int:
)
from contextual_orchestrator.server import SecurityConfig, serve
from scripts.ci.contextual_orchestrator_review_policy import (
PolicyError,
_load_zdr_endpoints,
build_zdr_prioritized_catalog,
is_zdr_model,
parse_discovery_report,
)

Expand Down Expand Up @@ -306,32 +403,108 @@ def main(argv: list[str] | None = None) -> int:
rows = _report_rows(selected_models, free_route_identities)
_write_json(args.discovery_out, {"models": rows})
zdr_endpoints = _load_zdr_endpoints(args.zdr_endpoints)
normalized_rows = parse_discovery_report({"models": rows})
free_rows = [
row for row in normalized_rows if row.get("cost_evidence") == "free"
]
priced_rows = [
row for row in normalized_rows if row.get("cost_evidence") == "priced"
]
admitted_free_rows = _zdr_admitted_rows(
free_rows,
require_zdr=args.require_zdr,
zdr_endpoints=zdr_endpoints,
checker=is_zdr_model,
)
admitted_priced_rows = _zdr_admitted_rows(
priced_rows,
require_zdr=args.require_zdr,
zdr_endpoints=zdr_endpoints,
checker=is_zdr_model,
)
requested_catalog_limit = int(os.environ.get("ORCHESTRATOR_CATALOG_LIMIT", "12"))
primary_limit = _bounded_primary_catalog_limit(
requested_catalog_limit, pool=args.pool, has_free_rows=bool(admitted_free_rows)
)
primary_rows = (
(admitted_free_rows or admitted_priced_rows)
if args.pool == "auto"
else normalized_rows
)
result = build_zdr_prioritized_catalog(
parse_discovery_report({"models": rows}),
limit=int(os.environ.get("ORCHESTRATOR_CATALOG_LIMIT", "12")),
primary_rows,
limit=primary_limit,
family_cap=int(os.environ.get("ORCHESTRATOR_CATALOG_FAMILY_CAP", "4")),
zdr_endpoints=zdr_endpoints,
require_zdr=args.require_zdr,
pool=args.pool,
)
result["report"] = _with_discovery_counts(result["report"], normalized_rows)
Path(args.catalog_out).write_text(
json.dumps({"agents": result["agents"]}, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
_write_json(args.report_out, result["report"])

agents = load_agents(args.catalog_out)
primary_report = result["report"]
fallback_result = None
fallback_agents: list[object] = []
fallback_limit = _bounded_fallback_catalog_limit(
requested_catalog_limit, primary_count=len(result["agents"])
)
Comment on lines +453 to +455

@devin-ai-integration devin-ai-integration Bot Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Budget tracks actual probes

Fallback capacity subtracts selected primary agents, not discovered rows. Family-cap exclusions never reach preflight, so both stages remain within twelve requests.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

if (
args.pool == "auto"
and admitted_free_rows
and admitted_priced_rows
and fallback_limit
):
try:
fallback_result = build_zdr_prioritized_catalog(
admitted_priced_rows,
limit=fallback_limit,
family_cap=int(os.environ.get("ORCHESTRATOR_CATALOG_FAMILY_CAP", "4")),
zdr_endpoints=zdr_endpoints,
require_zdr=args.require_zdr,
pool="auto",
)
except PolicyError:
fallback_result = None
if fallback_result is not None:
fallback_result["report"] = _with_discovery_counts(
fallback_result["report"], normalized_rows
)
fallback_result["report"]["primary_selected_count"] = primary_report[
"selected_count"
]
fallback_result["report"]["primary_selection"] = primary_report["selected"]
Comment on lines +473 to +480

@devin-ai-integration devin-ai-integration Bot Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Fallback evidence keeps global totals

The fallback report restores counts across all normalized rows while retaining priced-stage selections. Primary selections remain separately recorded for audit.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

fallback_agents = _load_temporary_agents(
f"{args.catalog_out}.priced",
fallback_result["agents"],
loader=load_agents,
)
client = ModelClient(
timeout=REVIEW_PREFLIGHT_TIMEOUT_SECONDS,
max_output_tokens=REVIEW_MAX_OUTPUT_TOKENS,
max_retries=0,
temperature=REVIEW_TEMPERATURE,
)
try:
agents, preflight_report = _preflight_review_agents(agents, client=client)
agents, preflight_report, fallback_used = _preflight_with_fallback(
agents, fallback_agents, client=client
)
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
except ReviewPreflightError as exc:
_write_json(args.preflight_out, exc.report)
raise SystemExit(f"review sidecar preflight failed: {exc}") from None
if fallback_used and fallback_result is not None:
Path(args.catalog_out).write_text(
json.dumps({"agents": fallback_result["agents"]}, indent=2, sort_keys=True)
+ "\n",
encoding="utf-8",
)
result = fallback_result
result["report"]["fallback_reason"] = "primary_routes_unavailable"
_write_json(args.report_out, result["report"])
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
_write_json(args.preflight_out, preflight_report)

client = ModelClient(
Expand Down
Loading
Loading