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)
Alternative (Option B — if the inlined version is canonical)
Acceptance Criteria
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.
Why
tools/langchain_client.pyandtools/llm_provider.pyare sync-managed from this repo to consumers (.github/sync-manifest.yml:670and:667). Two consumers have forked these synced files to route model selection through a localtools/llm_registry.pythat does not exist in Workflows and is not in the sync-manifest — so the nextmaint-68sync will overwrite the consumer forks and orphan theirllm_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):tools/langchain_client.py:0references tollm_registry; slot logic is inlined (SlotDefinition(... model="gpt-5.4")atlangchain_client.py:98,build_chat_clientat:204).tools/llm_provider.pyhardcodesgpt-5.1-codex(:594,629) andclaude-sonnet-4-5-20250929(:660,705).Manager-DatabaseandTrend_Model_Project:langchain_client.pyhas 6llm_registryreferences each; both shiptools/llm_registry.pythat is byte-identical (md510527ff44035e70636dbfa9738433895) — a shared, registry-driven slot/model-selection module with blocked-model guards. (Travel-Plan-Permission carries only an emptyllm_registry.pyplaceholder; not forked.)tools/llm_registry.pyis 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_registryconfig +is_model_blockedguards) and is already duplicated identically across 2 consumers — the signature of something that should be source-owned.Non-Goals
Tasks (Option A — recommended)
tools/llm_registry.pyto this repo (adopt the consumer version, md510527ff…), and refactortools/langchain_client.py+tools/llm_provider.pyhere to import it (registry-driven slot/model selection +is_model_blocked), replacing the inlinedSlotDefinition/hardcoded models.tools/llm_registry.pyas a synced entry in.github/sync-manifest.yml(alongsidelangchain_client.py/llm_provider.py, same sync mode).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)
tools/llm_registry.py+ revertlangchain_client.py/llm_provider.pyin the affected consumers, and document why registry-driven routing was rejected.Acceptance Criteria
state_fingerprint/ sync-drift check showstools/langchain_client.py,tools/llm_provider.py, andtools/llm_registry.pyCLEAN (identical) between this repo and Manager-Database + Trend_Model_Project — i.e. no consumer fork remains.tools/llm_registry.pyis listed in.github/sync-manifest.yml(Option A) OR is absent from all consumers (Option B).build_chat_clientselects the configured slot model rather than a hardcoded default.llm_registrymanifest entry (Option A) makes the sync-drift check flaglangchain_client.pyas DRIFT against the two consumers; restoring it returns CLEAN.Implementation Notes
Audit baseline: Workflows
main, 2026-06-28; consumer clones at theirorigin/main. Manifest evidence:.github/sync-manifest.yml:667(llm_provider.py),:670(langchain_client.py),:673(embedding_provider.py). Cross-fleet footprint: forked instranske/Manager-Databaseandstranske/Trend_Model_Project(identicalllm_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 inscripts/langchain/followup_issue_generator.pyvsprogress_reviewer.py(build_chat_clientvs_llm_client.build_client) — worth folding into the same reconciliation.