Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a3a24ae
feat: add durable provider bootstrap coordinator
seonghobae Aug 19, 2026
7ccfd92
test: lock atomic provider bootstrap contracts
seonghobae Aug 19, 2026
90d4154
ci: sync provider credentials and model inventory
seonghobae Aug 19, 2026
d12f8c8
docs: record provider bootstrap trust boundary
seonghobae Aug 19, 2026
77e9544
fix(ci): hash-pin provider sync dependencies
seonghobae Aug 20, 2026
8ea3a06
fix: distinguish selected and durably enabled provider agents
seonghobae Aug 20, 2026
4f7b6d4
docs: distinguish candidate selection from durable activation
seonghobae Aug 20, 2026
c92d81d
fix: exclude non-chat catalog models from serving pool
seonghobae Aug 20, 2026
e74e4d0
fix: keep provider bootstrap capability-neutral
seonghobae Aug 20, 2026
7cec2fa
test: prohibit model-name capability inference
seonghobae Aug 20, 2026
8c7686a
docs: prohibit capability inference from model names
seonghobae Aug 20, 2026
fe06058
feat: persist provider models with last-known-good recovery
seonghobae Aug 20, 2026
4e27d52
ci: verify provider catalog normalization repair
seonghobae Aug 20, 2026
a30c390
test: define honest provider-diverse discovery bootstrap
seonghobae Aug 20, 2026
6578dc5
test: bind NIM keys to one provider family
seonghobae Aug 20, 2026
1ca4015
fix: rank unknown prices honestly and diversify bootstrap providers
seonghobae Aug 20, 2026
9632f53
fix: normalize durable provider catalog authority
seonghobae Aug 20, 2026
91fab32
docs: record strict 3NF provider catalog boundary
seonghobae Aug 20, 2026
fd6a8af
docs: add normalized provider catalog to database design
seonghobae Aug 20, 2026
dc19672
docs: keep provider catalog ADR at 0015
seonghobae Aug 20, 2026
6b25f19
refactor: expose colocated credential database DSN safely
seonghobae Aug 20, 2026
4d81411
refactor: use credential backend database contract
seonghobae Aug 20, 2026
06da0c0
fix(discovery): wire provider-diverse bootstrap into CLI
seonghobae Aug 20, 2026
a063113
test(discovery): expose ambiguous price and duplicate pool gaps
seonghobae Aug 20, 2026
2539ad5
fix(discovery): reject untrusted duplicate price evidence
seonghobae Aug 20, 2026
a78d3a6
fix(discovery): keep duplicate evidence comparison total
seonghobae Aug 20, 2026
75e15af
test(discovery): expose overflow, corrupt-row, and currency gaps
seonghobae Aug 20, 2026
183e7a8
fix(discovery): fail closed on malformed and incomparable price evidence
seonghobae Aug 20, 2026
c01733b
fix(cost): reject corrupt persisted price rows
seonghobae Aug 20, 2026
7f725cd
test(bootstrap): expose overbroad provider secret trimming
seonghobae Aug 20, 2026
2a360f9
fix(bootstrap): preserve provider secret bytes outside mounted line e…
seonghobae Aug 20, 2026
db4134c
test(catalog): expose failed credential promotion and LKG mismatch
seonghobae Aug 20, 2026
f4f1b4a
fix(bootstrap): restore credentials after failed promotion
seonghobae Aug 20, 2026
854d7a2
test(bootstrap): require rollback on unexpected discovery failure
seonghobae Aug 20, 2026
0777e14
test(cost): reject persisted partial price rows
seonghobae Aug 20, 2026
55814b9
fix(bootstrap): roll back promoted credentials on unexpected failure
seonghobae Aug 20, 2026
386c9a0
fix: reject incomplete persisted price rows
seonghobae Aug 20, 2026
6c10b49
Merge embedding capability isolation into discovery stack
seonghobae Aug 20, 2026
c8632d0
Merge remote-tracking branch 'origin/fix/discovery-bootstrap-selectio…
seonghobae Aug 20, 2026
6b603ef
docs: ground provider-diverse routing in research
seonghobae Aug 20, 2026
4f94e0d
docs: align catalog rollback schema
seonghobae Aug 20, 2026
d693ace
fix: normalize workflow secret leak guard
seonghobae Aug 20, 2026
8afe847
fix: report durable provider registrations
seonghobae Aug 20, 2026
ea5ab0e
docs: define durable registration evidence
seonghobae Aug 20, 2026
7494f22
docs: remove trailing blank line
seonghobae Aug 21, 2026
074f0e4
Merge pull request #764 from ContextualWisdomLab/feat/current-main-pr…
seonghobae Aug 21, 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
105 changes: 105 additions & 0 deletions .github/workflows/provider-catalog-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Provider catalog sync

on:
workflow_dispatch:
schedule:
- cron: "17 * * * *"

permissions:
contents: read

concurrency:
group: provider-catalog-sync
cancel-in-progress: false

jobs:
sync:
name: Bootstrap durable provider KV and model catalog
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
timeout-minutes: 15
steps:
- name: Checkout protected default branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # actions/setup-python@v6
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: Register credentials and refresh normalized model catalog
shell: bash
env:
CONTEXTUAL_ORCHESTRATOR_KV_BACKEND: postgres
CONTEXTUAL_ORCHESTRATOR_KV_DSN: ${{ secrets.CONTEXTUAL_ORCHESTRATOR_KV_DSN }}
CONTEXTUAL_ORCHESTRATOR_KV_PASSPHRASE: ${{ secrets.CONTEXTUAL_ORCHESTRATOR_KV_PASSPHRASE }}
NVIDIA_NIM_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }}
NVIDIA_NIM_API_KEY_SUB: ${{ secrets.NVIDIA_NIM_API_KEY_SUB }}
BYTEZ_API_KEY: ${{ secrets.BYTEZ_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
set -euo pipefail
test -n "${CONTEXTUAL_ORCHESTRATOR_KV_DSN}"
test -n "${CONTEXTUAL_ORCHESTRATOR_KV_PASSPHRASE}"
python -m contextual_orchestrator.provider_catalog_bootstrap --model-limit 24 > provider-bootstrap-report.json
python - <<'PY'
import json
from pathlib import Path

report = json.loads(Path('provider-bootstrap-report.json').read_text(encoding='utf-8'))
expected = {
'NVIDIA_NIM_API_KEY',
'NVIDIA_NIM_API_KEY_SUB',
'BYTEZ_API_KEY',
'OPENROUTER_API_KEY',
'OPENAI_API_KEY',
}
registered = set(report['registered_credentials'])
if registered != expected:
raise SystemExit(f'credential inventory mismatch: {sorted(expected - registered)}')
if report['catalog_backend'] != 'postgres':
raise SystemExit('provider catalog is not durable PostgreSQL')
if report['catalog_model_count'] < 1 or report['eligible_model_count'] < 1:
raise SystemExit('provider catalog has no compatible serving model')
if not report['selected_agent_ids']:
raise SystemExit('provider catalog produced no serving candidates')
if report['enabled_agent_ids'] or report['durable_agent_pool']:
raise SystemExit('ephemeral Actions sync must not claim agent-pool activation')
print(json.dumps({
'registered_credentials': sorted(registered),
'live_discovered_model_count': report['live_discovered_model_count'],
'catalog_model_count': report['catalog_model_count'],
'last_known_good_model_count': report['last_known_good_model_count'],
'selected_agent_count': len(report['selected_agent_ids']),
'catalog_refresh_failure_count': report['catalog_refresh_failure_count'],
'providers_with_errors': report['providers_with_errors'],
}, sort_keys=True))
PY
python - <<'PY'
import os
from pathlib import Path

report = Path('provider-bootstrap-report.json').read_text(encoding='utf-8')
names = (
'NVIDIA_NIM_API_KEY',
'NVIDIA_NIM_API_KEY_SUB',
'BYTEZ_API_KEY',
'OPENROUTER_API_KEY',
'OPENAI_API_KEY',
)
leaked = [
name
for name in names
if os.environ[name].rstrip('\r\n')
and os.environ[name].rstrip('\r\n') in report
]
if leaked:
raise SystemExit(f'provider bootstrap report leaked secret values for: {leaked}')
PY
6 changes: 3 additions & 3 deletions contextual_orchestrator/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
agent_id_for,
discover_all_models,
refresh_price_book,
select_top_n_cheapest_discovered_agents,
select_bootstrap_discovered_agents,
)
from .orchestrator import (
CONTEXTUAL_ORCHESTRATOR_CONTRACT_V1,
Expand Down Expand Up @@ -211,7 +211,7 @@ def _discover_models_command(argv: list[str]) -> None:
type=_non_negative_int,
default=0,
metavar="N",
help="Enable the N cheapest discovered agents in --agents-db (auto-optimization bootstrap; "
help="Enable a price-honest, provider-diverse discovered agent pool in --agents-db (auto-optimization bootstrap; "
"requires --agents-db; 0 disables, the default, leaving every discovered agent inert).",
)
args = parser.parse_args(argv)
Expand All @@ -229,7 +229,7 @@ def _discover_models_command(argv: list[str]) -> None:
)
bootstrap.sync_discovered_agents([agent_from_discovered(model) for model in discovered])
if args.enable_cheapest:
for model in select_top_n_cheapest_discovered_agents(discovered, price_book, args.enable_cheapest):
for model in select_bootstrap_discovered_agents(discovered, price_book, args.enable_cheapest):
agent_id = agent_id_for(model)
bootstrap.patch_agent("default", agent_id, {"status": "active"})
enabled_agent_ids.append(agent_id)
Comment on lines 231 to 235

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: --enable-cheapest flag now performs provider-diverse selection despite its name

The CLI flag --enable-cheapest (main.py) now drives select_bootstrap_discovered_agents, which prefers one candidate per provider family before taking a second from an already-represented family. So --enable-cheapest N no longer strictly enables the N globally-cheapest agents; it enables a provider-diverse pool ordered by cost. The help text was updated to describe this, but the flag name retains 'cheapest', which may surprise operators expecting pure cost ordering. Behavioral change is intentional per the PR.

Open in Devin Review

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

Expand Down
24 changes: 22 additions & 2 deletions contextual_orchestrator/cost_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import threading
from dataclasses import dataclass, field
from decimal import ROUND_HALF_UP, Decimal
import math
import time
from typing import Any, Dict, List, Optional, Protocol
import uuid
Expand Down Expand Up @@ -162,11 +163,30 @@ def get_price(self, provider: str, model: str) -> Optional[PriceEntry]:
raw = self._config.get(_PRICE_CATEGORY, _price_key(provider, "*"), None)
if raw is None:
return None
if not isinstance(raw, dict):
return None
try:
if (
"prompt_price_per_1k" not in raw
or "completion_price_per_1k" not in raw
):
return None
prompt_price = float(raw["prompt_price_per_1k"])
completion_price = float(raw["completion_price_per_1k"])
except (OverflowError, TypeError, ValueError):
return None
if (
not math.isfinite(prompt_price)
or not math.isfinite(completion_price)
or prompt_price < 0
or completion_price < 0
):
return None
Comment on lines +166 to +184

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: get_price now returns None for partial/corrupt rows, changing compute_cost for those rows

PriceBook.get_price (cost_ledger.py) now returns None whenever a stored row is not a dict, is missing either prompt_price_per_1k/completion_price_per_1k, or has a non-finite/negative/unparseable component. Previously a partial row defaulted the missing component to 0.0 and returned a usable entry. This is a behavior change for compute_cost: a partial price row now yields the unpriced fallback (0.0) for the whole request rather than costing only the present component. In practice refresh_price_book and PriceEntry/set_price always persist both components, so only manually-written/corrupted KV rows are affected — hence not flagged as a bug. Worth confirming no production path writes single-component price rows.

Open in Devin Review

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

Comment on lines 163 to +184

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: get_price does not fall back to wildcard entry when the specific row is corrupt

In PriceBook.get_price (cost_ledger.py), the provider-wildcard fallback ("{provider}:*") is only consulted when the specific provider:model key is entirely absent. If the specific key exists but is corrupt/partial, the new validation returns None without attempting the wildcard default. This matches the pre-PR behavior (which also used the specific row without consulting the wildcard) so it is not a regression, but operators relying on a wildcard default price could be surprised when a corrupt specific row shadows it.

(Refers to this code)

Open in Devin Review

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

return PriceEntry(
provider_name=raw.get("provider_name", provider),
model_name=raw.get("model_name", model),
prompt_price_per_1k=float(raw.get("prompt_price_per_1k", 0.0)),
completion_price_per_1k=float(raw.get("completion_price_per_1k", 0.0)),
prompt_price_per_1k=prompt_price,
completion_price_per_1k=completion_price,
currency_code=raw.get("currency_code", self.default_currency),
)

Expand Down
34 changes: 34 additions & 0 deletions contextual_orchestrator/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def set(self, name: str, value: str) -> None:
"""Register (or replace) the secret stored under ``name``."""
...

def delete(self, name: str) -> None:
"""Remove one credential after an unvalidated candidate promotion."""
...


class InMemoryCredentialBackend:
"""Process-local credential registry for dev and tests (no Postgres needed)."""
Expand All @@ -68,6 +72,11 @@ def set(self, name: str, value: str) -> None:
with self._lock:
self._store[name] = value

def delete(self, name: str) -> None:
"""Remove ``name`` from the in-memory credential registry if present."""
with self._lock:
self._store.pop(name, None)


# --- Postgres pgcrypto-encrypted credential registry ------------------------
#
Expand Down Expand Up @@ -112,6 +121,15 @@ def __init__(self, dsn: str, passphrase: str) -> None:
self._passphrase = passphrase
self._ensured = False

@property
def connection_dsn(self) -> str:
"""Return the bootstrap DSN for a colocated metadata store.

Callers must treat this as connection material: never include it in logs,
reports, traces, or exceptions. Provider API keys remain inaccessible.
"""
return self._dsn

@classmethod
def from_env(cls) -> "PostgresCredentialBackend":
"""Build the backend from bootstrap transport env vars (the only allowed env use).
Expand Down Expand Up @@ -173,6 +191,17 @@ def set(self, name: str, value: str) -> None: # pragma: no cover - requires a l
)
conn.commit()

def delete(self, name: str) -> None: # pragma: no cover - requires a live Postgres
"""Delete one encrypted credential after a failed candidate promotion."""
with self._connect() as conn:
self._ensure_schema(conn)
with conn.cursor() as cur:
cur.execute(
"DELETE FROM provider_credentials WHERE credential_name = %s",
(name,),
)
conn.commit()


_backend: CredentialBackend | None = None
_backend_lock = threading.Lock()
Expand Down Expand Up @@ -216,3 +245,8 @@ def get_credential(name: str) -> str | None:
def register_credential(name: str, value: str) -> None:
"""Register a named secret into the KV (used by the bootstrap CLI)."""
get_backend().set(name, value)


def delete_credential(name: str) -> None:
"""Remove a named credential from the KV after an unvalidated promotion."""
get_backend().delete(name)
Loading