Skip to content

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

Description

@stranske

Why

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.

Scope

Reconcile the LLM-client sync boundary so a sync cannot clobber registry-driven model routing. This is a canonical-behavior decision (owner): the evidence favors upstreaming the consumer fork, but confirm before executing.

Recommended direction (Option A — upstream the fork)

The consumer fork is strictly more capable (external llm_registry config + is_model_blocked guards) and is already duplicated identically across 2 consumers — the signature of something that should be source-owned.

Non-Goals

  • Do NOT "fix" this only inside a consumer repo — that violates the consumer-repo rule and will be re-clobbered on next sync. The durable fix is in this repo.
  • Do NOT silently drop the blocked-model guard behavior when reconciling.

Tasks (Option A — recommended)

  • Add tools/llm_registry.py to this repo (adopt the consumer version, md5 10527ff…), and refactor tools/langchain_client.py + tools/llm_provider.py here to import it (registry-driven slot/model selection + is_model_blocked), replacing the inlined SlotDefinition/hardcoded models.
  • Add tools/llm_registry.py as a synced entry in .github/sync-manifest.yml (alongside langchain_client.py/llm_provider.py, same sync mode).
  • Re-sync consumers (maint-68) so Manager-Database / Trend_Model_Project converge on the upstreamed version instead of carrying a fork.

Alternative (Option B — if the inlined version is canonical)

  • Then the consumer forks are the drift: remove tools/llm_registry.py + revert langchain_client.py/llm_provider.py in the affected consumers, and document why registry-driven routing was rejected.

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.

Implementation Notes

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.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions