chore(ci): advance the vendored orchestrator pin to 012beaac and guard unattested providers - #2137
chore(ci): advance the vendored orchestrator pin to 012beaac and guard unattested providers#2137seonghobae wants to merge 1 commit into
Conversation
…d unattested providers Advance the central review sidecar's pinned contextual-orchestrator revision from 414f2297 to 012beaac (175 commits, a clean ancestor of CO main: ahead_by=175, behind_by=0), synchronously across all four locations that carry it, and close the latent outage the advance would otherwise create. The advance is gated on executed evidence, not on reading the range: - requirements.lock is byte-identical across all 175 commits, so the `--require-hashes --no-deps` install resolves the same wheels. pyproject's fast-mlsirm spec did move from a release tarball to a git+https commit pin, but the sidecar never runs `pip install -e .`, so it is not on this path. - The sidecar's own `python - <<'PY'` startup contract -- which subclasses ModelClient, overrides proxy_send, calls the private _mock_raw, drives build_server over loopback, and asserts the 413 envelope, a 64 KiB+ accepted body, and byte-exact tool-description passthrough -- was extracted and executed unmodified against a 012beaac worktree, and passes. That is the check that matters: orchestrator.py changed +1092/-251 in the range and the block depends on a private method. - All eleven symbols the sidecar and launcher import were resolved and signature-inspected at the target. DiscoveredModel is purely additive (one new supports_parallel_tool_calls field) and the launcher reads every discovery field through getattr with a default. - ModelClient.__init__'s timeout default is now `float | None = None` rather than `int = 90`, so the vendored runtime no longer carries the implicit per-request wall-clock cap ADR-0003's 2026-08-31 amendment forbids. That removal landed upstream in contextual-orchestrator#1118 (merged 2026-09-10), not in the still-open contextual-orchestrator#1053 this pin was previously recorded as waiting on. Three range changes are the reason to take it rather than incidental to it: build_review_orchestrator now builds ModelClient() instead of ModelClient(max_output_tokens=32768), with the new effective_max_output_tokens(agent) resolving the cap request-scope -> client -> the agent's provider-published ceiling; error payloads and the request_failed log line now carry a request_id, the correlation field whose absence made #2000's caller-retry question unanswerable; and the range carries 8586e9aa "fix(discovery): recover usable Bytez chat models" plus several OpenRouter/models.dev discovery fixes, against a free pool whose last five recorded preflights admitted only nvidia_nim/nvidia_nim_sub routes with Bytez failing discovery at http_status_500 every time (#1915). The guard: 012beaac ships two new provider sources, opencode_zen and opencode_go, both keyed on an optional OPENCODE_ZEN_API_KEY, and review_gateway.REVIEW_CREDENTIAL_NAMES now defaults to PROVIDER_ACCEPTED_CREDENTIAL_NAMES, so the launcher's register_review_credentials(os.environ) would register that key straight out of the job environment if it were ever present. scripts/ci/zdr_policy.py has no entry for either provider, and parse_discovery_report *raises* PolicyError for an unregistered provider rather than skipping the row -- so adding that one secret to a workflow's env: would have failed every central review sidecar closed, on a provider nobody asked to route to. The secret is not seeded today, so nothing is failing; the exposure is latent and one line of workflow YAML away. _report_rows now drops a discovered row whose provider is absent from the org ZDR policy table and prints a bounded `discovery_row_skipped_unattested_provider provider=<name> model=<id>` diagnostic to stderr. The safety property is unchanged and is the point: an unattested provider still never serves review traffic, and parse_discovery_report keeps its fail-closed contract verbatim for rows that are submitted. Attesting OpenCode Zen/Go for the free pool needs a real retention-posture determination for opencode.ai and is deliberately not granted here. Also repairs a sentence in ADR-0003 that f8823a5 (#1364) split: it inserted the requirements.lock sentences after "into RUNNER_TEMP. The", orphaning the pre-existing "runtime entry (...) registers the five provider secrets" line from its subject. Restored from that commit's parent text. Tests: tests/test_contextual_orchestrator_review_unattested_provider_skip.py (6 cases, including one pinning that parse_discovery_report still raises for a row that does reach it, so the launcher guard cannot be mistaken for a policy relaxation). Full suite: 3045 passed, 1 skipped; coverage 100%; interrogate 100%. Refs #1915, #2000, contextual-orchestrator#1118. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KPmJErfkcHer4UVEgrQxUX
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hold: production evidence shows this pin removes a bound nothing replacesI found this after opening the PR, while root-causing #1884's What I claimed in the PR body. Under "Evidence the advance is safe" I listed, as a reason to take the pin: It is doing a lot. #1884 head Eight of ten land on exactly 90.0 s. Roughly 720 of the 907 seconds is that default expiring against endpoints that never respond. The cap is what turns a black-holed provider socket into a bounded, diagnosable failure. Nothing below six hours replaces it at the target pin.
So this PR, as written, would convert #1884's failure mode from "15 minutes, bounded, 503, full attempt trace" into a single open attempt that can hold a review runner for hours with no verdict. Every central review job inherits that. I am not proposing to re-add a timeout. Passing an explicit Two smaller corrections to this PR's body, since they were part of my case for the advance and one of them was wrong:
Where that leaves this PR. The rest of the change stands on its evidence — the byte-identical lockfile, the startup contract executing green against
I lean (1), and (3) is a cheap consolation if #2139 will take a while — the unattested-provider guard closes its own latent outage and does not depend on the pin moving. Say the word and I will split it. Not merging past this on my own judgment. Generated by Claude Code |
Correction: the CodeQL diagnosis above was wrong, and this PR is nearly greenMy standing-down comment said these checks "turn green when the publication credential does" and that nothing on my side unblocks them. Both wrong. Current state:
24 success, 1 failure, 1 in progress, 1 queued. Where I went wrong. I cited run 34733576667 as a What the wake step actually does. The
Same run, same credentials, same repository, opposite outcomes — which rules out the permission cap I hypothesised. On the re-run I said I was saving. With the race passed it became informative, so I used it — and GitHub refused: What this does not change. #2139 stands untouched. The occupancy exposure is about What I got right and am not re-litigating: the cross-repo half. For naruon and contextual-orchestrator the wake exits at Generated by Claude Code |
The python CodeQL scan on this head is clean — the red is a false verdictThe re-run I queued came back failure again, but with a different reason than before, and it is worth being precise because the wording is alarming and wrong: There is no such SARIF evidence. In dispatch run 34734286494, job The job's conclusion is For this PR specifically: CodeQL found nothing in the diff. That is now positive evidence rather than an open question, which is the one useful thing the re-run bought. On the re-run budget. This was the second failure of that shard, so by my own statement I am not re-running it again — a third attempt would produce the same false verdict from the same clean scan. Nothing here is fixable inside this PR: the defect is in Status of this PR is unchanged in substance: 25 success, this one false red, Generated by Claude Code |
Advances the central review sidecar's pinned
contextual-orchestratorrevision from414f2297to012beaacd0631f8cd3391c77744eeb626269b5de— 175 commits, a clean ancestor of COmain(ahead_by=175, behind_by=0) — synchronously across all four locations that carry it, and closes the latent outage the advance would otherwise create.Why now
The pin was recorded as waiting on
contextual-orchestrator#1053("fix(gateway): remove implicit model request timeout"). That premise was wrong, and I am correcting it here rather than leaving it in the record: co#1053 is still open, but its substance landed via35a428cain contextual-orchestrator#1118, merged 2026-09-10.ModelClient.__init__'stimeoutdefault isfloat | None = Noneat the target andint = 90at the current pin, so the implicit per-request wall-clock cap that ADR-0003's 2026-08-31 amendment forbids is already gone from the vendored runtime. The blocking condition is satisfied in substance; the form it was recorded in never happened.Three changes in the range are the reason to take it rather than incidental to it:
build_review_orchestratornow buildsModelClient()instead ofModelClient(max_output_tokens=32768), and the neweffective_max_output_tokens(agent)resolves request-scope → client → the selected agent's provider-publishedmax_output_tokens. A flat 32768 both over-asked models whose published ceiling is lower — a provider400, which reads as a routing failure — and under-used models with a higher one.request_idcorrelation. Error payloads and therequest_failedlog line now carry arequest_id. That is the exact field whose absence made Strix run ended "cancelled" at 6h with no verdict: 909 provider attempts, 92% on one route, 0 exhaustion events, request identity absent from evidence #2000's caller-retry question unanswerable from the evidence: with no request identity, a caller re-selecting a dead route is indistinguishable from concurrent requests.8586e9aa fix(discovery): recover usable Bytez chat modelsplus several OpenRouter/models.dev union fixes. The last five recorded free-pool preflights admitted onlynvidia_nim/nvidia_nim_subroutes, with Bytez failing discovery athttp_status_500every time ([CO owner] eliminate orchestrator/free provider-family SPOF before gateway release #1915). This does not by itself prove the SPOF is fixed — it makes the next preflight census worth reading.Evidence the advance is safe
A 175-commit jump on the pin that decides which code the sidecar executes with five provider secrets in its KV should not rest on reading the range. Four properties were executed against the target, not inferred:
git diff 414f2297..012beaac -- requirements.lock--require-hashes --no-depsresolves the same wheels012beaacworktreeModelClient.__init__timeout defaultfloat | None = None(wasint = 90)On the lockfile:
pyproject.toml'sfast-mlsirmspec did move (release tarball →git+httpscommit pin), but the sidecar never runspip install -e .— it installsrequirements.lockand setsPYTHONPATH— so that spec is not on this execution path.On the startup contract: this is the check that actually matters, because
contextual_orchestrator/orchestrator.pychanged +1092/-251 in the range and the sidecar'spython - <<'PY'block subclassesModelClient, overridesproxy_send, and calls the private_mock_raw. I extracted the heredoc verbatim and ran it withPYTHONPATHpointed at a012beaacworktree: the 413 envelope, the 64 KiB+ accepted body, and the byte-exact tool-description passthrough all still hold. Note this also survives a real format change — therequest_failedlog line gainedrequest_id=…, and the contract's substring assertion still matches.On the discovery shape:
DiscoveredModelis purely additive (one newsupports_parallel_tool_callsfield, all existing fields unchanged and in order), and the launcher reads every discovery field throughgetattrwith a default.The risk the advance creates, and the guard
012beaacships two new provider sources —opencode_zenandopencode_go, both keyed on an optionalOPENCODE_ZEN_API_KEY— andreview_gateway.REVIEW_CREDENTIAL_NAMESnow defaults toPROVIDER_ACCEPTED_CREDENTIAL_NAMES. The launcher callsregister_review_credentials(os.environ)with the full process environment, so that key would be registered straight out of the job environment if it were ever present.scripts/ci/zdr_policy.pyhas no entry for either provider, andcontextual_orchestrator_review_policy.parse_discovery_reportraisesPolicyErrorfor an unregistered provider rather than skipping the row. So adding that one secret to a workflow'senv:would have failed every central review sidecar closed — on a provider nobody had asked to route to.The secret is not seeded today, so nothing is failing. The exposure is latent and one line of workflow YAML away, which is why it is fixed in the same change that creates it.
_report_rowsnow drops a discovered row whose provider is absent from the org ZDR policy table, with a boundeddiscovery_row_skipped_unattested_provider provider=<name> model=<id>stderr diagnostic. The safety property is unchanged and is the point: an unattested provider still never serves review traffic, andparse_discovery_reportkeeps its fail-closed contract verbatim for rows that are submitted — one of the six new tests pins exactly that, so the launcher guard cannot later be mistaken for a policy relaxation. Attesting OpenCode Zen/Go for the free pool needs a real retention-posture determination foropencode.ai; it is deliberately not granted here and must not be inferred from this PR.Also in this change
ADR-0003 item 1 has been broken prose since
f8823a54(#1364): that commit inserted therequirements.locksentences after"into RUNNER_TEMP. The", orphaning the pre-existing"runtime entry (…) registers the five provider secrets"line from its subject. Restored from that commit's parent text — I am amending this exact ADR item, so leaving the sentence broken underneath the amendment was not an option.Verification
New:
tests/test_contextual_orchestrator_review_unattested_provider_skip.py(6 cases).Not in this change
mainand I did not repair it here.# Changelogsits at line 162, with 161 lines of entries prepended above the file title, plus a duplicate## [Unreleased]at line 70 and a dated release section at 155 stranded between them. Successive PRs have been prepending to line 1 rather than under the real## [Unreleased]at line 170. My entry follows the established (wrong) convention so it sits with its peers and the eventual repair stays one coherent change; filing separately.contextual_orchestrator/review_gateway.pyat012beaacannotatesreview_pool_admissions(agents: Sequence[Any])without importingAny. Inert at runtime underfrom __future__ import annotations, but it breakstyping.get_type_hints(). Upstream nit, filing on CO.Refs #1915, #2000, ContextualWisdomLab/contextual-orchestrator#1118.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KPmJErfkcHer4UVEgrQxUX
Generated by Claude Code