Skip to content

feat(llm): support profile slots so the chat path tracks reviewed selections - #1501

Merged
stranske merged 1 commit into
mainfrom
feat/profile-slot-support-track-reviewed-selections
Jul 31, 2026
Merged

feat(llm): support profile slots so the chat path tracks reviewed selections#1501
stranske merged 1 commit into
mainfrom
feat/profile-slot-support-track-reviewed-selections

Conversation

@stranske

Copy link
Copy Markdown
Owner

Why

Manager-Database was pinned to frozen model ids and would not pick up an advanced reviewed selection. Two independent causes, both verified against main:

  1. config/llm_slots.json pins don't track the registry. The shared resolver deliberately retains an unprofiled pin while the pinned model is still lifecycle: current (tools/llm_registry.py, the explicit_entry ... lifecycle == "current" branch). Probed with a registry whose selections had advanced:

    slot pinned resolved why
    slot1 openai gpt-5.4 gpt-5.4 pin still current → retained
    slot2 anthropic claude-sonnet-4-6 claude-sonnet-5 pin absent from registry → falls through to selection
    slot3 github-models codex-mini-latest codex-mini-latest pin still current → retained

    So only slot2 followed the selection, and only by accident of its pin being invalid.

  2. llm/client.py had no profile support. Workflows now ships config/llm_slots.json in profile form (no model pins). Verified: with that file set via LANGCHAIN_SLOT_CONFIG, _load_slot_config() returned [] and build_chat_client() returned None — the chat path would serve no model at all.

config/llm_slots.json is sync_mode: create_only in the Workflows manifest ("repos may customize provider preferences"), so it can only be changed here.

What changed

  • llm/client.py — an explicitly configured slot entry may now name a profile, resolved via llm_registry.select_model_for_profile, alongside the existing explicit model and legacy quality_tier/tier. An unresolvable profile is skipped (fails closed), never silently replaced by a default. This mirrors tools/llm_registry.load_slot_config semantics. The lifecycle/blocked eligibility checks from fix: enforce current registry models for chat #1490 are untouched.
  • config/llm_slots.json — migrated to the profile form, so all three slots resolve from the reviewed verifier-balanced selections.
  • tests/test_llm_client.py — the two tests that read the ambient config now assert the reviewed selection instead of hardcoding gpt-5.4 / claude-opus-4-6. A synced registry refresh was otherwise a guaranteed CI failure with no underlying defect. Hermetic tests that write their own registry/slot fixtures deliberately keep explicit ids.

Test gate

  • test_profile_slot_resolves_reviewed_selection — a profile-only slot resolves to the reviewed selection for that profile/provider.
  • test_profile_slot_with_unresolvable_profile_fails_closed — a profile with no matching selection serves nothing; the fake create_llm raises if reached.
  • Deliberate break → revert: neutralizing the profile read (profile = "") makes test_profile_slot_resolves_reviewed_selection FAIL; restoring it returns all 13 to green.

Verification

pytest tests/test_llm_client.py                  -> 13 passed
tools/check_model_registry_freshness.py          -> 0 blocking (profile slots accepted)
ruff check / ruff format --check                 -> clean
probe: profile slots + advanced registry -> slot1 gpt-5.6-terra, slot2 claude-sonnet-5, slot3 openai/gpt-5

Pairs with stranske/Workflows#2852, which advances the reviewed selections. Order-independent: this PR is correct against the current registry too (it resolves today's selections), and starts tracking the new ones as soon as the registry syncs.

🤖 Generated with Claude Code

…ections

Two changes so Manager-Database follows the fleet's reviewed model selections
instead of frozen model pins.

1. llm/client.py: an explicitly configured slot file may now name a `profile`
   (resolved through llm_registry.select_model_for_profile) in addition to an
   explicit `model` or legacy `quality_tier`/`tier`. Workflows now ships
   config/llm_slots.json in profile form with no model pins; before this change
   such a file resolved to ZERO slots here and the chat path served no model at
   all. An unresolvable profile fails closed rather than falling back.

2. config/llm_slots.json: migrate to the profile form. The pinned form did not
   track the registry: the shared resolver deliberately RETAINS an unprofiled
   pin while the pinned model is still lifecycle=current, so slot1 stayed on
   gpt-5.4 and slot3 on codex-mini-latest even after the reviewed selection
   advanced. Only slot2 followed the selection, and only because its pinned
   claude-sonnet-4-6 is absent from the registry. This file is
   sync_mode: create_only in the Workflows manifest, so it can only change here.

Also make the two tests that read the AMBIENT config assert the reviewed
selection rather than hardcoded ids, so a synced registry refresh is not a CI
failure. Hermetic tests that write their own fixtures keep explicit ids.

Verified: 13 tests pass; deliberate break (neutralizing the profile read) makes
test_profile_slot_resolves_reviewed_selection fail, and reverting restores it;
freshness gate reports 0 blocking with the profile-form slots; ruff clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 7 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cb70276d-4b13-484f-a545-450aedd5598a

📥 Commits

Reviewing files that changed from the base of the PR and between 4dc7dad and 82b9703.

📒 Files selected for processing (3)
  • config/llm_slots.json
  • llm/client.py
  • tests/test_llm_client.py

Comment @coderabbitai help to get the list of available commands.

@stranske
stranske merged commit 18e1704 into main Jul 31, 2026
17 checks passed
@stranske
stranske deleted the feat/profile-slot-support-track-reviewed-selections branch July 31, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant