Skip to content
Draft
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0f307a7
fix(tests): restore main's test signal; re-apply dropped OpenRouter a…
seonghobae Sep 26, 2026
343bf7f
fix(embeddings): preserve unbounded provider wait
seonghobae Sep 26, 2026
ea1ac22
docs: record unbounded embedding wait repair
seonghobae Sep 26, 2026
86d4e83
docs: bind protected-main test recovery evidence
seonghobae Sep 26, 2026
6e70a19
fix(ci): bind rustfmt and clippy to pinned toolchain
seonghobae Sep 26, 2026
824959a
docs(changelog): record pinned Rust components
seonghobae Sep 26, 2026
227d6f6
docs(gap): record pinned Rust gate repair
seonghobae Sep 26, 2026
e8ea56c
fix(route): restore request-local policy and candidate evidence
seonghobae Sep 26, 2026
740096d
fix(route): keep streaming and quality evidence on one revision
seonghobae Sep 26, 2026
96de901
fix(ci): restore pinned runtime and baseline test gates
seonghobae Sep 26, 2026
097036e
fix(provider): retain typed allowlist rejection
seonghobae Sep 26, 2026
f882ee7
fix(provider): preserve transport on allowlist failures
seonghobae Sep 26, 2026
e76d3b3
test(uptime): bound provider telemetry response
seonghobae Sep 26, 2026
9cf335a
fix(uptime): bound provider telemetry response
seonghobae Sep 26, 2026
34adc97
docs(changelog): record bounded uptime telemetry
seonghobae Sep 26, 2026
122a4f3
docs(gap): bind bounded uptime telemetry
seonghobae Sep 26, 2026
2eceb64
test(embeddings): carry default HTTP wait contracts
seonghobae Sep 26, 2026
ca5efdc
docs(gap): bind #1269 fixture carryover
seonghobae Sep 26, 2026
f56e10d
test(route): preserve each same-agent attempt in receipt
seonghobae Sep 26, 2026
9188e23
fix(route): retain every same-agent attempt
seonghobae Sep 26, 2026
cad76d4
docs(gap): bind retry receipt repair
seonghobae Sep 26, 2026
bd3d83d
fix(route): restore exact source after blob transfer
seonghobae Sep 26, 2026
ea48d4e
docs(gap): restore full receipt baseline
seonghobae Sep 26, 2026
2748f4f
test(route): isolate final provider error from storm admission
seonghobae Sep 27, 2026
9e547ed
fix(security): bind decision window IDs in static SQL
seonghobae Sep 27, 2026
2a4bd55
Merge remote-tracking branch 'origin/pr1278-stack' into fix/1266-stat…
seonghobae Sep 27, 2026
c601373
fix(routing): release observation lock during embedding
seonghobae Sep 27, 2026
24dd161
fix(review): verify bounded waits and preserve candidate validation
seonghobae Sep 27, 2026
3a52f03
fix(security): audit hashed runtime lock separately
seonghobae Sep 27, 2026
0186b74
fix(security): consume audited fast-mlsirm release
seonghobae Sep 27, 2026
f436d2a
Merge protected routing repairs into test-signal successor
seonghobae Sep 27, 2026
df836dc
Merge structured quota recovery and failure receipts
seonghobae Sep 27, 2026
ef72301
Merge protected multimodal and runner allocation repairs
seonghobae Sep 27, 2026
515ee5b
fix(tests): declare DIF controls in sample-size boundary regressions
seonghobae Sep 27, 2026
d6f2761
fix(batch): preserve reviewed shutdown and durable cancellation repairs
seonghobae Sep 27, 2026
b6f6ced
fix: preserve provider-owned quota timing across routing paths
seonghobae Sep 27, 2026
a0b5592
merge: integrate protected main and preserve provider timing authority
seonghobae Sep 27, 2026
bfdb2b0
fix: require provider timing for mixed-pool quota recovery
seonghobae Sep 27, 2026
3a11454
Merge remote-tracking branch 'origin/main' into fix/1266-main-integra…
seonghobae Sep 27, 2026
e1fbed0
test: preserve provider-owned timing across main integration
seonghobae Sep 27, 2026
1aa88da
test: align shutdown and unknown quota timing regressions
seonghobae Sep 27, 2026
b920dab
fix(rate-limit): restore the finite assumed cooldown for 429s without…
seonghobae Sep 27, 2026
bd51c93
build(deps): make anyio 4.14.2 a security floor instead of an exact pin
seonghobae Sep 27, 2026
8d11d75
Merge remote-tracking branch 'origin/main' into fix/1266-main-refresh…
seonghobae Sep 27, 2026
8ec5471
fix(gateway): preserve newer quota cooldown after older success
seonghobae Sep 27, 2026
263dbdc
test(ci): match no-build-isolation wheel build in NIM workflow contract
seonghobae Sep 28, 2026
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
18 changes: 14 additions & 4 deletions .github/workflows/nim-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ jobs:
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install pinned runtime
run: |
python -m pip install --require-hashes -r requirements.lock
python -m pip install --no-deps -e .
uv sync --locked --extra api --extra db --extra queue
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Run dry benchmark
env:
Expand Down Expand Up @@ -104,10 +109,15 @@ jobs:
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install pinned runtime
run: |
python -m pip install --require-hashes -r requirements.lock
python -m pip install --no-deps -e .
uv sync --locked --extra api --extra db --extra queue
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Resolve live parameters
id: live_params
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/opencode-hourly-loop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,16 @@ jobs:
with:
node-version: "22"

- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install pinned runtime dependencies
timeout-minutes: 10
run: python -m pip install --require-hashes -r requirements.lock
run: |
uv sync --locked --extra api --extra db --extra queue
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Install OpenCode CLI
timeout-minutes: 10
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/provider-catalog-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,15 @@ jobs:
with:
python-version: "3.12"

- name: Install hash-pinned runtime dependencies
run: python -m pip install --disable-pip-version-check --no-input --require-hashes -r requirements.lock
- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install pinned runtime dependencies
run: |
uv sync --locked --extra api --extra db --extra queue
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Select durable or run-scoped PostgreSQL KV
shell: bash
Expand Down
31 changes: 22 additions & 9 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ jobs:

- name: Install hash-locked quality tools
run: |
python -m pip install --require-hashes -r requirements.lock
python -m pip install --require-hashes -r requirements-opencode-review-ci.txt
uv pip install --python .venv/bin/python --require-hashes -r requirements-opencode-review-ci.txt
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Prove complete benchmark coverage and public docstrings
run: |
Expand All @@ -95,9 +95,9 @@ jobs:
run: |
set -euo pipefail
rm -rf dist "$RUNNER_TEMP/nim-wheel-site"
python -m pip wheel --no-deps --no-build-isolation . --wheel-dir dist
uv build --wheel --out-dir dist
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
python scripts/verify_decision_wheel_manifest.py dist/contextual_orchestrator-*.whl "$RUNNER_TEMP"/decision-wheels/*.whl
python -m pip install --no-deps \
uv pip install --python .venv/bin/python --no-deps \
--target "$RUNNER_TEMP/nim-wheel-site" \
dist/contextual_orchestrator-*.whl "$RUNNER_TEMP"/decision-wheels/*.whl
cd "$RUNNER_TEMP"
Expand All @@ -123,8 +123,16 @@ jobs:
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install fuzz dependencies
run: python -m pip install --require-hashes -r requirements.lock -r fuzz/requirements-property.txt -r fuzz/requirements-atheris.txt
run: |
uv sync --locked --extra api --extra db --extra queue --group dev
uv pip install --python .venv/bin/python --require-hashes -r fuzz/requirements-property.txt -r fuzz/requirements-atheris.txt
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"

- name: Run property-based fuzz tests
run: python -m pytest tests/fuzz -q
Expand Down Expand Up @@ -266,17 +274,22 @@ jobs:
with:
python-version: "3.12"

- name: Set up uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"

- name: Install audit and project dependencies
run: |
python -m pip install --require-hashes -r requirements-security-ci.txt
python -m pip install --require-hashes -r requirements.lock
python -m pip install --no-deps -e .
uv sync --locked --extra api --extra db --extra queue --group dev

- name: Audit pinned dependencies and generate SBOM
run: |
set -euo pipefail
python -m pip_audit -r requirements.lock
cyclonedx-py environment --output-format json --output-file cyclonedx-sbom.json
python -m pip_audit --require-hashes -r requirements.lock
python -m pip_audit --path .venv/lib/python3.12/site-packages
Comment thread
seonghobae marked this conversation as resolved.
cyclonedx-py environment .venv/bin/python --output-format json --output-file cyclonedx-sbom.json

- name: Upload CycloneDX SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # actions/upload-artifact@v7.0.1
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.d/provider-owned-quota-timing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Honor provider-declared retry timing that is already carried on a classified provider error (chat, passthrough and structured requests), stop replaying the same agent after an explicit quota rejection, and let a fresh successful provider call clear that agent's cooldown. A 429 without `Retry-After`/`x-ratelimit-reset*` still records the finite, administrator-owned `rate_limit_unknown_cooldown_seconds` assumed cooldown (`cooldown_source: assumed`), exactly as on `main`: the agent is skipped only while that cooldown runs and becomes selectable again once it elapses. An intermediate revision had recorded such a 429 as an infinite cooldown, which excluded the agent permanently whenever an alternative existed; that regression is fixed and covered by a test.
7 changes: 7 additions & 0 deletions CHANGELOG.d/restore-test-signal-main.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Restore the OpenRouter availability collector's separation from the answer-quality ledger. The restack merge for #1074 (`3078949c`) had silently reverted `openrouter_uptime.py` to its pre-`b3be48e3` form, so uptime polls once again rewrote the quality router's prior and blended in the benchmark quality prior. The collector now updates only the transport ledger again. The fixed `_UPTIME_FETCH_TIMEOUT_SECONDS` bound from #971 is kept. Also repair test drift that stopped the hosted `Tests and package quality` job at collection or kept suites red: the renamed provider-embedding claim-lease constant, a fake HTTP connection without `connect()`/`sock`, fingerprinted discovered-agent ids, a fake binary response without `headers.get`, and a stale batch-retention assertion that contradicted the unbounded-execution contract. Provider embedding waits now accept the application default `None` as an unbounded deadline, matching the synchronous endpoint contract instead of raising `TypeError` before provider completion.
Bind `rustfmt` and `clippy` to the repository's pinned Rust 1.97.1 toolchain. The minimal rustup profile does not include either component, so the hosted Rust gate previously selected the directory override and failed before formatting or linting could run.
Bound the untrusted OpenRouter uptime response to the same 8 MiB provider-response ceiling and reject oversized JSON before parsing, while preserving valid endpoint telemetry.
Preserve one deployment identity entry for every real same-agent retry in deterministic selection receipts, so replay evidence no longer understates provider calls.
Keep provider-backed contextual embedding outside the psychometric persistence lock while revalidating the deployment on both sides of the call, so an unbounded provider wait cannot block observation persistence or Agent-pool edits.
Repair the OpenRouter bounded-read test double and the finite embedding-wait fixture so both tests exercise their intended production boundary without a swallowed `TypeError` or a timer-driven race.
Restore the required hash-locked `requirements.lock` supply-chain audit alongside the installed-environment audit. Replace the obsolete fast-mlsirm VCS pin with immutable released `fast-mlsirm==0.11.4`, declare an `anyio>=4.14.2` security floor and upgrade the locks from vulnerable `anyio==4.14.1` to fixed `anyio==4.14.2`, align the constrained fuzz locks, migrate the held-out DIF benchmark to the release's non-deprecated API, remove an inactive pytest-asyncio option, and keep the environment-derived CycloneDX SBOM as a separate artifact.
4 changes: 4 additions & 0 deletions contextual_orchestrator/batch_job_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ def lock(
*,
lease_seconds: float | None = None,
renew_until_epoch: float | None = None,
renew_while: Callable[[], bool] | None = None,
):
"""Return an atomic shard claim with bounded lease and acquisition wait."""
lock_name = f"batch_job_registry:{name}:claim:{key}"
Expand Down Expand Up @@ -245,6 +246,9 @@ def acquired_claim():
def renew_claim() -> None:
interval = _claim_renewal_interval_seconds(lease_seconds)
while not stop_renewal.wait(interval):
if renew_while is not None and not renew_while():
lease.mark_lost()
return
remaining = renew_until_epoch - time.time()
if remaining <= 0:
lease.mark_lost()
Expand Down
82 changes: 54 additions & 28 deletions contextual_orchestrator/batch_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,17 @@ def __init__(

def close(self) -> None:
"""Release the bounded worker pool owned by this backend."""
self._closed.set()
with self._executor_lock:
self._closed.set()
executor, self._executor = self._executor, None
for job_id, event in list(self._terminal_events.items()):
if self._registry.durable:
# The next backend can reclaim persisted work after this worker exits.
event.set()
else:
self.cancel(
BatchJob(job_id=job_id, backend=self.name), reason="backend closed"
)
if executor is not None:
executor.shutdown(wait=False, cancel_futures=True)

Expand Down Expand Up @@ -1164,6 +1172,7 @@ def _run_job(self, job_id: str) -> None:
job_id,
lease_seconds=self._claim_lease_seconds,
renew_until_epoch=deadline_epoch,
renew_while=lambda: not self._closed.is_set(),
) as execution_claim:
self._run_claimed_job(job_id, execution_claim)
except ClaimNotAcquired:
Expand Down Expand Up @@ -1255,6 +1264,8 @@ def _run_claimed_job(self, job_id: str, execution_claim: Any) -> None:
requests = list(self._requests[job_id])
try:
vectors, prompt_tokens = self._runner(requests)
if self._closed.is_set():
execution_claim.mark_lost()
execution_claim.ensure_owned()
if time.time() >= self._execution_deadline(job_id):
self._publish_terminal(
Expand Down Expand Up @@ -1295,6 +1306,9 @@ def _run_claimed_job(self, job_id: str, execution_claim: Any) -> None:
except ClaimNotAcquired:
raise
except Exception as exc: # noqa: BLE001 - polling exposes bounded failure metadata
if self._closed.is_set():
execution_claim.mark_lost()
execution_claim.ensure_owned()
error = {
"error_type": type(exc).__name__,
"http_status": getattr(
Expand All @@ -1320,32 +1334,36 @@ def _publish_terminal(
usage: Any = None,
error: Any = None,
) -> None:
"""Publish terminal state atomically for durable registries."""
if self._registry.durable:
self._registry.publish_provider_embedding_terminal(
execution_claim,
job_id,
status=status,
results=results,
usage=usage,
error=error,
)
return
with self._registry.lock(
"provider_embedding_job_states",
job_id,
lease_seconds=self._claim_lease_seconds,
):
"""Fence shutdown and publish one terminal outcome under the lifecycle lock."""
with self._executor_lock:
if self._closed.is_set():
execution_claim.mark_lost()
execution_claim.ensure_owned()
if self._states.get(job_id) not in {"queued", "running"}:
raise ClaimNotAcquired("provider embedding job is already terminal")
if results is not None:
self._results[job_id] = results
if usage is not None:
self._usage[job_id] = usage
if error is not None:
self._errors[job_id] = error
self._states[job_id] = status
if self._registry.durable:
self._registry.publish_provider_embedding_terminal(
execution_claim,
job_id,
status=status,
results=results,
usage=usage,
error=error,
)
return
with self._registry.lock(
"provider_embedding_job_states",
job_id,
lease_seconds=self._claim_lease_seconds,
):
execution_claim.ensure_owned()
if self._states.get(job_id) not in {"queued", "running"}:
raise ClaimNotAcquired("provider embedding job is already terminal")
if results is not None:
self._results[job_id] = results
if usage is not None:
self._usage[job_id] = usage
if error is not None:
self._errors[job_id] = error
self._states[job_id] = status

def wait(self, job: BatchJob, *, timeout: float | None) -> Dict[str, Any]:
"""Wait within the caller's explicit deadline for a terminal state.
Expand All @@ -1354,10 +1372,18 @@ def wait(self, job: BatchJob, *, timeout: float | None) -> Dict[str, Any]:
wall-clock deadline (contextual-orchestrator's no-implicit-deadline
default). ``threading.Event.wait`` raises ``OverflowError`` for a
non-finite timeout on CPython, so both forms are translated to ``None``
(block indefinitely) rather than passed through.
(block indefinitely) rather than passed through. Durable unbounded waits
observe shared terminal state at the backend's existing claim cadence;
another process cannot signal this process's local event.
"""
event = self._terminal_events.get(job.job_id)
if event is not None:
if event is not None and self._registry.durable and (
timeout is None or not math.isfinite(timeout)
):
while not self._closed.is_set() and not self.poll(job)["is_complete"]:
if event.wait(self.poll_after_ms / 1000):
break
elif event is not None:
event.wait(
timeout=(
timeout
Expand Down
11 changes: 10 additions & 1 deletion contextual_orchestrator/openrouter_uptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
# uptime update -- so it keeps its own fixed, independent bound instead.
_UPTIME_FETCH_TIMEOUT_SECONDS = 10.0

# Match the inference response boundary: telemetry is untrusted provider input
# and must not consume unbounded memory before JSON validation.
_OPENROUTER_UPTIME_RESPONSE_MAX_BYTES = 8 * 1024 * 1024


class OpenRouterUptimeCollector:
"""Periodically fold upstream availability into the transport prior."""
Expand Down Expand Up @@ -159,7 +163,12 @@ def _fetch_uptime(self, model_id: str) -> float | None:
with urllib.request.urlopen(
request, timeout=_UPTIME_FETCH_TIMEOUT_SECONDS
) as response:
payload = json.loads(response.read().decode("utf-8"))
response_body = response.read(
_OPENROUTER_UPTIME_RESPONSE_MAX_BYTES + 1
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
if len(response_body) > _OPENROUTER_UPTIME_RESPONSE_MAX_BYTES:
raise ValueError("OpenRouter uptime response exceeds byte limit")
payload = json.loads(response_body.decode("utf-8"))
endpoints = payload.get("data", {}).get("endpoints", [])
uptimes = [
endpoint["uptime_last_30m"]
Expand Down
Loading
Loading