Skip to content

feat(llm): model-registry freshness gate (maint-77) — stop old models ossifying as primary - #2709

Merged
stranske merged 5 commits into
mainfrom
model-registry-freshness-gate
Jun 29, 2026
Merged

feat(llm): model-registry freshness gate (maint-77) — stop old models ossifying as primary#2709
stranske merged 5 commits into
mainfrom
model-registry-freshness-gate

Conversation

@stranske

@stranske stranske commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Source: Issue #2708

Closes #2708

Automated Status Summary

Scope

tools/langchain_client.py and tools/llm_provider.py are sync-managed from this repo to consumers (.github/sync-manifest.yml:670 and :667). Two consumers have forked these synced files to route model selection through a local tools/llm_registry.py that does not exist in Workflows and is not in the sync-manifest — so the next maint-68 sync will overwrite the consumer forks and orphan their llm_registry.py, silently reverting registry-driven model selection and blocked-model guards fleet-wide.

Verified 2026-06-28 (against local clones + this repo's main):

  • Workflows canonical tools/langchain_client.py: 0 references to llm_registry; slot logic is inlined (SlotDefinition(... model="gpt-5.4") at langchain_client.py:98, build_chat_client at :204). tools/llm_provider.py hardcodes gpt-5.1-codex (:594,629) and claude-sonnet-4-5-20250929 (:660,705).
  • Consumer forks Manager-Database and Trend_Model_Project: langchain_client.py has 6 llm_registry references each; both ship tools/llm_registry.py that is byte-identical (md5 10527ff44035e70636dbfa9738433895) — a shared, registry-driven slot/model-selection module with blocked-model guards. (Travel-Plan-Permission carries only an empty llm_registry.py placeholder; not forked.)
  • tools/llm_registry.py is absent from this repo (find → none) and has 0 entries in .github/sync-manifest.yml.

So the canonical synced files and the consumer copies have diverged, with the consumer version being the more capable one (registry + blocked-model guards) and the dependency it needs (llm_registry.py) living only in consumers and outside the sync system.

Tasks

  • Audit baseline: Workflows main, 2026-06-28; consumer clones at their origin/main. Manifest evidence: .github/sync-manifest.yml:667 (llm_provider.py), :670 (langchain_client.py), :673 (embedding_provider.py). Cross-fleet footprint: forked in stranske/Manager-Database and stranske/Trend_Model_Project (identical llm_registry.py). Surfaced by the Manager-Database full audit (Code/Audits/Manager-Database/2026-06-28-03-sync-drift.md). Related smaller drift in the same audit: tools/requirements-llm.txt (template_sync: exact, consumer pins ahead) and opposite-direction drift in scripts/langchain/followup_issue_generator.py vs progress_reviewer.py (build_chat_client vs _llm_client.build_client) — worth folding into the same reconciliation.

Acceptance criteria

  • After the change, a state_fingerprint / sync-drift check shows tools/langchain_client.py, tools/llm_provider.py, and tools/llm_registry.py CLEAN (identical) between this repo and Manager-Database + Trend_Model_Project — i.e. no consumer fork remains.
  • tools/llm_registry.py is listed in .github/sync-manifest.yml (Option A) OR is absent from all consumers (Option B).
  • A test asserts model routing honors the registry/blocked-model guards (Option A) and that build_chat_client selects the configured slot model rather than a hardcoded default.
  • Deliberate-break demonstration: removing the llm_registry manifest entry (Option A) makes the sync-drift check flag langchain_client.py as DRIFT against the two consumers; restoring it returns CLEAN.

Head SHA: 55750bd
Latest Runs: ✅ success — Gate
Required: gate: ✅ success

Workflow / Job Result Logs
Gate ✅ success View run
Health 40 Sweep ✅ success View run
Health 44 Gate Branch Protection ✅ success View run
Health 45 Agents Guard ✅ success View run
Health 50 Security Scan ✅ success View run
Health 51 Actions SAST (zizmor) ✅ success View run
Health 52 Semgrep Scan ✅ success View run
Health 72 Template Sync ✅ success View run
Health 73 Template Completeness ✅ success View run
Maint 52 Validate Workflows ✅ success View run
Maint 77 Model Registry Freshness ✅ success View run
PR 11 - Minimal invariant CI ✅ success View run
Selftest CI ✅ success View run
Validate Sync Manifest ✅ success View run

Summary by CodeRabbit

  • New Features
    • Added an offline “model registry freshness” gate that detects overdue reviews, blocked/unknown pins, and dominated pinned models.
    • Introduced a scheduled/manual CI workflow that runs the gate and blocks pull requests with findings.
    • Scheduled runs create/refresh a labeled tracking issue with the results.
  • Configuration
    • Added review_interval_days and review_by settings to the model registry.
  • Tests & Documentation
    • Added unit coverage for gate behavior and updated workflow documentation.

Detects when the canonical LLM model config has gone stale so old models do not
get stuck as the primary ones indefinitely. Offline/stdlib-only check over
config/model_registry.json + config/llm_slots.json; flags review_overdue,
blocked_pin, unknown_pin, and dominated_pin (a pin the registry's own quality
scores already rate below a newer same-provider model).

- tools/check_model_registry_freshness.py (+ tests, 10 cases)
- config/model_registry.json: add review_interval_days + review_by
- .github/workflows/maint-77-*: weekly schedule + PR gate; opens/refreshes one
  tracking issue on staleness (no provider API calls, no secrets)
- sync-manifest: ship the gate to consumers (copy)

Does not change model selection and does not touch maint-68's sync core;
validate_template_sync.py still passes. On real config today it correctly flags
the registry review overdue + slot2 (sonnet-4-6) dominated by opus-4-6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an offline CLI freshness check for the model registry and slot config, a new GitHub Actions workflow to run it on schedule, manual dispatch, and relevant PRs, plus registry metadata updates, tests, sync-manifest registration, and workflow docs.

Changes

Model Registry Freshness Gate

Layer / File(s) Summary
evaluate() logic and CLI entrypoint
tools/check_model_registry_freshness.py
Defines freshness findings, provider/model normalization, tier-aware quality comparison, registry/slot evaluation, JSON loading, CLI argument handling, and exit codes.
Registry metadata and tests
config/model_registry.json, tests/test_check_model_registry_freshness.py
Adds registry review metadata and test coverage for overdue review detection, pin validation, dominance checks, real repo parsing, and CLI exit codes.
Workflow wiring and documentation
.github/workflows/maint-77-model-registry-freshness.yml, .github/sync-manifest.yml, docs/ci/WORKFLOWS.md, docs/ci/WORKFLOW_SYSTEM.md, tests/workflows/test_workflow_naming.py
Registers the tool in sync metadata, adds the new workflow, documents it, and updates the workflow naming test mapping.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions as GitHub Actions
  participant CheckTool as check_model_registry_freshness.py
  participant GitHubCLI as gh
  participant IssueTracker as Tracking Issue
  GitHubActions->>CheckTool: run freshness check on schedule/PR/dispatch
  CheckTool-->>GitHubActions: findings JSON and exit code
  GitHubActions->>GitHubCLI: search/create/update tracking issue
  GitHubCLI->>IssueTracker: comment or create issue
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #2710: This PR implements the model-registry freshness gate and checker described by the issue for keeping stale or blocked model pins from remaining primary.

Suggested labels

maintenance, automation, github:actions, sync

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds a freshness gate, but #2708 requires reconciling llm_registry sync drift and syncing the client/provider changes. Add tools/llm_registry.py to the repo and sync manifest, or remove the consumer forks and verify the sync-drift check passes.
Out of Scope Changes check ⚠️ Warning Most changes implement a new freshness workflow and checker, which are unrelated to the linked sync-drift reconciliation work in #2708. Remove the freshness-gate changes from this PR or retarget the PR to the linked sync-drift reconciliation task.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main feature: a model-registry freshness gate to stop stale models from staying primary.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch model-registry-freshness-gate

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

@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 03:28 — with GitHub Actions Inactive
Comment thread .github/workflows/maint-77-model-registry-freshness.yml Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1d6364797

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/maint-77-model-registry-freshness.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/maint-77-model-registry-freshness.yml:
- Around line 45-50: The freshness gate step in the workflow is treating every
non-zero result from check_model_registry_freshness.py as staleness, but rc=2
must remain a hard error. Update the logic around the gate/handling steps so the
workflow only follows the stale-finding path when the gate exits 1, and fails
the job immediately for 2 or any other unexpected exit code; use the existing
gate id and the freshness.json handling to preserve the checker’s exit-code
contract.
- Around line 23-25: The freshness-check job is exposing a write-scoped workflow
token while running PR-controlled code, and it also treats every nonzero exit as
stale. Update the job that runs `actions/checkout` and
`tools/check_model_registry_freshness.py` to disable persisted checkout
credentials, keep the `issues: write` permission off the PR-executed path, and
adjust the exit-code handling so only `1` is reported as “stale” while `2` is
handled separately.

In `@tools/check_model_registry_freshness.py`:
- Around line 197-198: The CLI path in check_model_registry_freshness.main
should treat an invalid --today as a config/usage error instead of letting
_parse_date(args.today) raise a traceback. Wrap the today parsing in the same
error-handling path used for other CLI/config validation, catch the ValueError
from _parse_date, and exit with the documented code 2 before calling evaluate.
- Around line 146-160: The dominated_pin check in
check_model_registry_freshness.py is comparing models using headline quality
across all tiers, which can flag valid tier-specific pins as dominated. Update
the logic around the pinned_q/better computation to use slot["quality_tier"]
when it exists, and only fall back to _headline_quality for pins without a tier.
Make sure the comparison against by_provider, _headline_quality, and the
generated findings message all reflect the slot’s requested tier so
dominated_pin only reports true regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b18663c3-963a-4561-83cd-e475ad5852e4

📥 Commits

Reviewing files that changed from the base of the PR and between a39db6e and a1d6364.

📒 Files selected for processing (5)
  • .github/sync-manifest.yml
  • .github/workflows/maint-77-model-registry-freshness.yml
  • config/model_registry.json
  • tests/test_check_model_registry_freshness.py
  • tools/check_model_registry_freshness.py

Comment thread .github/workflows/maint-77-model-registry-freshness.yml Outdated
Comment thread .github/workflows/maint-77-model-registry-freshness.yml Outdated
Comment thread tools/check_model_registry_freshness.py Outdated
Comment thread tools/check_model_registry_freshness.py Outdated
@stranske-keepalive

stranske-keepalive Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Automated Status Summary

Head SHA: accfd30
Latest Runs: ⏳ pending — Gate
Required contexts: Gate / gate, Health 45 Agents Guard / guard
Required: core tests (3.12): ⏳ pending, core tests (3.13): ⏳ pending, docker smoke: ⏳ pending, gate: ⏳ pending

Workflow / Job Result Logs
(no jobs reported) ⏳ pending

Coverage Overview

  • Coverage history entries: 1

Coverage Trend

Metric Value
Current 75.67%
Baseline 85.00%
Delta -9.33%
Minimum 70.00%
Status ✅ Pass

Top Coverage Hotspots (lowest coverage)

File Coverage Missing
scripts/issue_dedup_smoke.py 0.0% 4
scripts/runner_lib/__main__.py 0.0% 3
scripts/validate_template_sync.py 0.0% 77
scripts/langchain/topic_splitter.py 19.1% 57
tools/codex_log_analyzer.py 19.6% 140
scripts/repo_review_round2_runner.py 25.1% 344
scripts/prune_agent_stubs.py 39.7% 26
scripts/repo_review_round1_runner.py 40.7% 133
tools/ensure_workflow_timeout_variables.py 42.1% 74
scripts/sync_label_docs.py 42.9% 64
tools/ci_failure_triage.py 44.2% 123
scripts/repo_review_backlog_scan.py 45.3% 116
scripts/repo_review_body_writer.py 46.5% 86
tools/codex_session_analyzer.py 47.9% 59
scripts/create_verifier_labels.py 48.3% 58

Low Coverage Files (<50.0%)

File Coverage Missing
scripts/issue_dedup_smoke.py 0.0% 4
scripts/runner_lib/__main__.py 0.0% 3
scripts/validate_template_sync.py 0.0% 77
scripts/langchain/topic_splitter.py 19.1% 57
tools/codex_log_analyzer.py 19.6% 140
scripts/repo_review_round2_runner.py 25.1% 344
scripts/prune_agent_stubs.py 39.7% 26
scripts/repo_review_round1_runner.py 40.7% 133
tools/ensure_workflow_timeout_variables.py 42.1% 74
scripts/sync_label_docs.py 42.9% 64
tools/ci_failure_triage.py 44.2% 123
scripts/repo_review_backlog_scan.py 45.3% 116
scripts/repo_review_body_writer.py 46.5% 86
tools/codex_session_analyzer.py 47.9% 59
scripts/create_verifier_labels.py 48.3% 58

Updated automatically; will refresh on subsequent CI/Docker completions.


Keepalive checklist

Scope

tools/langchain_client.py and tools/llm_provider.py are sync-managed from this repo to consumers (.github/sync-manifest.yml:670 and :667). Two consumers have forked these synced files to route model selection through a local tools/llm_registry.py that does not exist in Workflows and is not in the sync-manifest — so the next maint-68 sync will overwrite the consumer forks and orphan their llm_registry.py, silently reverting registry-driven model selection and blocked-model guards fleet-wide.

Verified 2026-06-28 (against local clones + this repo's main):

  • Workflows canonical tools/langchain_client.py: 0 references to llm_registry; slot logic is inlined (SlotDefinition(... model="gpt-5.4") at langchain_client.py:98, build_chat_client at :204). tools/llm_provider.py hardcodes gpt-5.1-codex (:594,629) and claude-sonnet-4-5-20250929 (:660,705).
  • Consumer forks Manager-Database and Trend_Model_Project: langchain_client.py has 6 llm_registry references each; both ship tools/llm_registry.py that is byte-identical (md5 10527ff44035e70636dbfa9738433895) — a shared, registry-driven slot/model-selection module with blocked-model guards. (Travel-Plan-Permission carries only an empty llm_registry.py placeholder; not forked.)
  • tools/llm_registry.py is absent from this repo (find → none) and has 0 entries in .github/sync-manifest.yml.

So the canonical synced files and the consumer copies have diverged, with the consumer version being the more capable one (registry + blocked-model guards) and the dependency it needs (llm_registry.py) living only in consumers and outside the sync system.

Tasks

  • Audit baseline: Workflows main, 2026-06-28; consumer clones at their origin/main. Manifest evidence: .github/sync-manifest.yml:667 (llm_provider.py), :670 (langchain_client.py), :673 (embedding_provider.py). Cross-fleet footprint: forked in stranske/Manager-Database and stranske/Trend_Model_Project (identical llm_registry.py). Surfaced by the Manager-Database full audit (Code/Audits/Manager-Database/2026-06-28-03-sync-drift.md). Related smaller drift in the same audit: tools/requirements-llm.txt (template_sync: exact, consumer pins ahead) and opposite-direction drift in scripts/langchain/followup_issue_generator.py vs progress_reviewer.py (build_chat_client vs _llm_client.build_client) — worth folding into the same reconciliation.

Acceptance criteria

  • After the change, a state_fingerprint / sync-drift check shows tools/langchain_client.py, tools/llm_provider.py, and tools/llm_registry.py CLEAN (identical) between this repo and Manager-Database + Trend_Model_Project — i.e. no consumer fork remains.
  • tools/llm_registry.py is listed in .github/sync-manifest.yml (Option A) OR is absent from all consumers (Option B).
  • A test asserts model routing honors the registry/blocked-model guards (Option A) and that build_chat_client selects the configured slot model rather than a hardcoded default.
  • Deliberate-break demonstration: removing the llm_registry manifest entry (Option A) makes the sync-drift check flag langchain_client.py as DRIFT against the two consumers; restoring it returns CLEAN.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Runner dispatch state for codex on PR #2709. Do not edit.

@stranske
stranske temporarily deployed to agent-standard June 29, 2026 03:40 — with GitHub Actions Inactive
@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 03:40 — with GitHub Actions Inactive
@stranske
stranske temporarily deployed to agent-standard June 29, 2026 03:41 — with GitHub Actions Inactive
@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 20:28 — with GitHub Actions Inactive
@stranske

Copy link
Copy Markdown
Owner Author

Closer pass pushed a824ea2 to address the current CI/review blockers on this PR.

Changes made:

  • Split maint-77-model-registry-freshness.yml into a read-only PR gate plus a scheduled/manual tracking-issue job with issues: write only off the PR path.
  • Set persist-credentials: false on both checkout steps.
  • Preserved checker exit code 2 as a hard configuration/usage failure; only exit code 1 is treated as stale model-registry findings.
  • Made dominated_pin compare quality on the slot's requested quality_tier and added invalid --today handling.
  • Added the new workflow to naming/inventory tests and both workflow docs inventories.

Validation run locally from a disposable /tmp checkout:

  • python -m pytest tests/test_check_model_registry_freshness.py tests/workflows/test_workflow_naming.py::test_inventory_docs_list_all_workflows tests/workflows/test_workflow_naming.py::test_workflow_names_match_filename_convention tests/workflows/test_disable_legacy_workflows.py::test_canonical_workflow_names_match_expected_mapping -q -> 14 passed
  • python -m ruff check tools/check_model_registry_freshness.py tests/test_check_model_registry_freshness.py tests/workflows/test_workflow_naming.py tests/workflows/test_disable_legacy_workflows.py -> passed
  • python -m black --check tools/check_model_registry_freshness.py tests/test_check_model_registry_freshness.py tests/workflows/test_workflow_naming.py tests/workflows/test_disable_legacy_workflows.py -> passed
  • YAML parse for .github/workflows/maint-77-model-registry-freshness.yml -> passed
  • git diff --check -> passed

Post-push readback: PR head is a824ea2d1b23bcf5c8bb304d0fa4356ab006eadd; fresh GitHub checks and CodeRabbit are pending.

@stranske

Copy link
Copy Markdown
Owner Author

Follow-up push 5a794ee fixes the freshness gate's own stale-data failure:

  • Bumped the registry review window to last_updated=2026-06-29 / review_by=2026-08-28.
  • Aligned codex-mini-latest with the github-models provider used by slot3 and runtime provider normalization.
  • Changed the Anthropic slot from a pinned Sonnet model to quality_tier: T5, so it resolves through the registry instead of remaining ossified on a dominated pin.

Local validation after this commit:

  • python3 tools/check_model_registry_freshness.py --json -> fresh true / rc 0
  • Focused pytest/ruff/black/YAML parse/git diff --check remained passing as listed above.

Post-push readback: head 5a794ee773277f763ae22e8c9caaaea99d525577, zero unresolved review threads, fresh GitHub checks pending.

@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 20:32 — with GitHub Actions Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/maint-77-model-registry-freshness.yml (1)

38-46: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin both external actions to commit SHAs in both jobs. actions/checkout@v7 and actions/setup-python@v6 are still mutable tags here, so an upstream retag or compromise could change behavior across synced repos. Lines 38-46 and 83-91.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/maint-77-model-registry-freshness.yml around lines 38 -
46, Pin the external GitHub Actions used in both jobs to immutable commit SHAs
instead of version tags: replace the uses of actions/checkout and
actions/setup-python in the workflow with their corresponding commit-pinned
references. Update both the first job and the second job so the Checkout and
Setup Python steps are fixed to SHAs, keeping the same inputs like
persist-credentials and python-version unchanged.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/ci/WORKFLOWS.md`:
- Line 205: Update the workflow description for
maint-77-model-registry-freshness.yml so it also mentions the PR trigger for
changes to tools/check_model_registry_freshness.py. The current text in the
docs/ci/WORKFLOWS.md entry understates the trigger set by only calling out
registry/slot changes; revise that sentence so it reflects both PRs for
registry/slot changes and PRs that modify the checker path, while keeping the
rest of the checker summary intact.

---

Outside diff comments:
In @.github/workflows/maint-77-model-registry-freshness.yml:
- Around line 38-46: Pin the external GitHub Actions used in both jobs to
immutable commit SHAs instead of version tags: replace the uses of
actions/checkout and actions/setup-python in the workflow with their
corresponding commit-pinned references. Update both the first job and the second
job so the Checkout and Setup Python steps are fixed to SHAs, keeping the same
inputs like persist-credentials and python-version unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0e934599-5b9a-4906-8ff5-282476fe5ba9

📥 Commits

Reviewing files that changed from the base of the PR and between a1d6364 and a824ea2.

📒 Files selected for processing (6)
  • .github/workflows/maint-77-model-registry-freshness.yml
  • docs/ci/WORKFLOWS.md
  • docs/ci/WORKFLOW_SYSTEM.md
  • tests/test_check_model_registry_freshness.py
  • tests/workflows/test_workflow_naming.py
  • tools/check_model_registry_freshness.py

Comment thread docs/ci/WORKFLOWS.md Outdated
@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 21:25 — with GitHub Actions Inactive
@stranske

Copy link
Copy Markdown
Owner Author

Closer follow-up pushed two commits on model-registry-freshness-gate:

  • 24aa4039 keeps configured slot fallback behavior when a test/consumer supplies a partial model registry, and updates the Anthropic fallback expectation for the real T5 slot selection.
  • 55750bd1 addresses the docs review thread by documenting the checker-path PR trigger for maint-77-model-registry-freshness.yml.

Validation run locally with Python 3.12 tooling:

  • /opt/anaconda3/bin/python -m pytest tests/tools/test_langchain_client.py tests/test_check_model_registry_freshness.py tests/workflows/test_workflow_naming.py -q -> 79 passed
  • /opt/anaconda3/bin/ruff check tools/llm_registry.py tests/tools/test_langchain_client.py tools/check_model_registry_freshness.py tests/test_check_model_registry_freshness.py -> passed
  • /opt/anaconda3/bin/black --check --target-version py312 tools/llm_registry.py tests/tools/test_langchain_client.py tools/check_model_registry_freshness.py tests/test_check_model_registry_freshness.py -> passed
  • /opt/anaconda3/bin/python tools/check_model_registry_freshness.py --json -> fresh: true
  • git diff --check -> passed

Post-push readback: head is 55750bd1202a100bb8219cce2f9713a9ab84ad68; all prior review threads are resolved. Fresh CI and CodeRabbit are running on the new head.

@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 21:26 — with GitHub Actions Inactive
@stranske
stranske merged commit accfd30 into main Jun 29, 2026
106 of 107 checks passed
@stranske
stranske deleted the model-registry-freshness-gate branch June 29, 2026 22:22
@stranske stranske added the verify:compare Compare multiple LLM evaluations label Jun 29, 2026
@stranske
stranske temporarily deployed to agent-standard June 29, 2026 22:23 — with GitHub Actions Inactive
@stranske
stranske temporarily deployed to agent-high-privilege June 29, 2026 22:23 — with GitHub Actions Inactive
@stranske
stranske temporarily deployed to agent-standard June 29, 2026 22:23 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

Provider Comparison Report

Provider Summary

Provider Model Verdict Confidence Summary
openai gpt-5.4 CONCERNS 83% This merge appears to add infrastructure for detecting model-registry sync drift: a new llm_registry file, manifest entry, freshness-check script, workflow, and tests around that checker. That is u...
anthropic claude-sonnet-4-6 FAIL 82% The PR introduces a model-registry freshness gate workflow and checker tool, adds llm_registry.py to the sync manifest, and provides tests for the freshness checker. However, it fails to address th...
📋 Full Provider Details (click to expand)

openai

  • Model: gpt-5.4
  • Verdict: CONCERNS
  • Confidence: 83%
  • Scores:
    • Correctness: 6.0/10
    • Completeness: 5.0/10
    • Quality: 7.0/10
    • Testing: 7.0/10
    • Risks: 6.0/10
  • Summary: This merge appears to add infrastructure for detecting model-registry sync drift: a new llm_registry file, manifest entry, freshness-check script, workflow, and tests around that checker. That is useful and generally good quality. However, based on the changed-file summary, it does not clearly implement the substantive canonical-code reconciliation required by the acceptance criteria. In particular, there is no visible update to tools/langchain_client.py or tools/llm_provider.py to adopt registry-driven model selection and blocked-model guards, and the test changes outside the checker are too small to demonstrate the required routing behavior. So the PR looks like a strong partial fix focused on detection/prevention, but not enough evidence of full functional completion.
  • Concerns:
    • The PR adds tools/llm_registry.py to Workflows and to .github/sync-manifest.yml, but the summarized diff does not show the required reconciliation of tools/langchain_client.py or tools/llm_provider.py to actually consume the registry. Acceptance explicitly called for registry-driven routing and blocked-model guards, plus build_chat_client selecting the configured slot model instead of a hardcoded default.
    • The only visible product-code additions are the new freshness checker, workflow, manifest entry, and a tiny llm_registry.py file. Without corresponding changes in langchain_client.py and llm_provider.py, the core drift/root-cause described in the issue appears only partially addressed.
    • Acceptance required a test asserting model routing honors registry/blocked-model guards and that build_chat_client selects the configured slot model rather than a hardcoded default. The diff summary shows only a 2-line change in tests/tools/test_langchain_client.py, which is unlikely to cover that behavior in any meaningful way.
    • Acceptance required a deliberate-break demonstration: removing the llm_registry manifest entry should make the sync-drift check flag langchain_client.py as DRIFT, restoring it should return CLEAN. The added tests for tools/check_model_registry_freshness.py likely validate the checker itself, but the summary does not show evidence that this exact end-to-end scenario against the affected files/consumers is asserted.
    • The new maint-77 freshness gate improves detection of future drift, but detection alone is not equivalent to making Workflows canonical files identical to Manager-Database and Trend_Model_Project. The acceptance criteria specifically required the files to be CLEAN after the change.

anthropic

  • Model: claude-sonnet-4-6
  • Verdict: FAIL
  • Confidence: 82%
  • Scores:
    • Correctness: 4.0/10
    • Completeness: 3.0/10
    • Quality: 7.0/10
    • Testing: 5.0/10
    • Risks: 6.0/10
  • Summary: The PR introduces a model-registry freshness gate workflow and checker tool, adds llm_registry.py to the sync manifest, and provides tests for the freshness checker. However, it fails to address the core acceptance criteria: tools/langchain_client.py and tools/llm_provider.py are not modified to align with consumer forks (or vice versa), so the sync drift between Workflows canonical files and Manager-Database/Trend_Model_Project consumers remains unresolved. The llm_registry.py added is a stub (+6 lines) rather than the full registry implementation. AC1 (CLEAN state across repos) and AC3 (model routing honors registry) are not satisfied by the code changes present in this diff.
  • Concerns:
    • tools/langchain_client.py is not modified — it still has 0 llm_registry references while consumers have 6 each; AC1 (CLEAN state) cannot be satisfied without reconciling this file
    • tools/llm_provider.py is not modified — hardcoded model strings remain; sync drift with consumers persists
    • tools/llm_registry.py adds only +6 lines, almost certainly a stub rather than the full byte-identical registry (md5 10527ff44035e70636dbfa9738433895) from consumers; this means the file content will still differ post-sync
    • AC1 is fundamentally unmet: the PR adds a freshness detection tool but does not reconcile the canonical Workflows files with consumer forks, so sync drift remains
    • AC3 is only partially met: tests cover the freshness checker script but do not assert that build_chat_client selects the configured slot model via registry rather than a hardcoded default
    • AC4 (deliberate-break demonstration) appears untested — no test removes the manifest entry and verifies langchain_client.py is flagged as DRIFT
    • The PR solves a monitoring/detection problem (maint-77 freshness gate) but does not solve the underlying sync-drift reconciliation problem described in the issue scope

Agreement

  • Quality: scores within 1 point (avg 7.0/10, range 7.0-7.0)
  • Risks: scores within 1 point (avg 6.0/10, range 6.0-6.0)

Disagreement

Dimension openai anthropic
Verdict CONCERNS FAIL
Correctness 6.0/10 4.0/10
Completeness 5.0/10 3.0/10
Testing 7.0/10 5.0/10

Unique Insights

  • openai: The PR adds tools/llm_registry.py to Workflows and to .github/sync-manifest.yml, but the summarized diff does not show the required reconciliation of tools/langchain_client.py or tools/llm_provider.py to actually consume the registry. Acceptance explicitly called for registry-driven routing and blocked-model guards, plus build_chat_client selecting the configured slot model instead of a hardcoded default.; The only visible product-code additions are the new freshness checker, workflow, manifest entry, and a tiny llm_registry.py file. Without corresponding changes in langchain_client.py and llm_provider.py, the core drift/root-cause described in the issue appears only partially addressed.; Acceptance required a test asserting model routing honors registry/blocked-model guards and that build_chat_client selects the configured slot model rather than a hardcoded default. The diff summary shows only a 2-line change in tests/tools/test_langchain_client.py, which is unlikely to cover that behavior in any meaningful way.; Acceptance required a deliberate-break demonstration: removing the llm_registry manifest entry should make the sync-drift check flag langchain_client.py as DRIFT, restoring it should return CLEAN. The added tests for tools/check_model_registry_freshness.py likely validate the checker itself, but the summary does not show evidence that this exact end-to-end scenario against the affected files/consumers is asserted.; The new maint-77 freshness gate improves detection of future drift, but detection alone is not equivalent to making Workflows canonical files identical to Manager-Database and Trend_Model_Project. The acceptance criteria specifically required the files to be CLEAN after the change.
  • anthropic: tools/langchain_client.py is not modified — it still has 0 llm_registry references while consumers have 6 each; AC1 (CLEAN state) cannot be satisfied without reconciling this file; tools/llm_provider.py is not modified — hardcoded model strings remain; sync drift with consumers persists; tools/llm_registry.py adds only +6 lines, almost certainly a stub rather than the full byte-identical registry (md5 10527ff44035e70636dbfa9738433895) from consumers; this means the file content will still differ post-sync; AC1 is fundamentally unmet: the PR adds a freshness detection tool but does not reconcile the canonical Workflows files with consumer forks, so sync drift remains; AC3 is only partially met: tests cover the freshness checker script but do not assert that build_chat_client selects the configured slot model via registry rather than a hardcoded default; AC4 (deliberate-break demonstration) appears untested — no test removes the manifest entry and verifies langchain_client.py is flagged as DRIFT; The PR solves a monitoring/detection problem (maint-77 freshness gate) but does not solve the underlying sync-drift reconciliation problem described in the issue scope

🔍 LangSmith Traces

@stranske

Copy link
Copy Markdown
Owner Author

Closer verifier disposition for the 2026-06-29 provider comparison report: treating the non-PASS result as a false positive against current main, not opening a follow-up PR.

Evidence checked on live main after merge:

  • tools/langchain_client.py imports and uses tools.llm_registry (load_slot_config, ENV_SLOT_CONFIG, ENV_MODEL_REGISTRY_CONFIG) and build_chat_client() resolves configured slots.
  • tools/llm_provider.py calls configured_model_for_provider() from tools.llm_registry for both OpenAI and Anthropic provider selection.
  • tools/llm_registry.py is a full helper module (300 lines on live main), not the 6-line stub described by the Anthropic verifier.
  • .github/sync-manifest.yml includes tools/llm_provider.py, tools/langchain_client.py, and tools/llm_registry.py.
  • Source issue [Sync drift] tools/llm_registry.py forked in consumers but absent from Workflows + sync-manifest (langchain_client/llm_provider clobber risk) #2708 was already closed before this merge with live-main evidence that the original sync-drift claim came from a stale Dropbox checkout; this PR added the forward-looking maint-77 freshness gate and tests.

The verifier appears to have judged the stale original issue text/diff summary instead of the post-merge live-main state and the issue-owner disposition. No bounded code follow-up is required for #2709.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autofix:escalated verify:compare Compare multiple LLM evaluations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Sync drift] tools/llm_registry.py forked in consumers but absent from Workflows + sync-manifest (langchain_client/llm_provider clobber risk)

2 participants