Move provider × base_url validation patterns from llm_runner.py to
factory.py's ProviderSpec, implementing the architecture improvement
suggested in docs/architecture/orchestrator-validation.md.
Changes:
- Add base_url_patterns field to ProviderSpec dataclass
- Split ollama and openrouter into separate ProviderSpec entries
(previously shared openai's spec with dynamic provider selection)
- Add validate_provider_base_url() function in factory for reusable validation
- Simplify LLMRunner._detect_provider_mismatch() to delegate to factory
- Update architecture doc with change log and implementation notes
Benefits:
- Single source of truth for provider configuration
- Easier maintenance when adding/updating providers
- Reduced code duplication (llm_runner.py: -39 lines, factory.py: +84 lines)
- Factory validation can be tested independently
All 28 orchestrator validation tests pass, including 6 provider mismatch tests.
The repository state has moved well past the oldest migration drafts: backend public payloads are already contract-first in several paths, research provenance now spans runner/live/full-state logs, and the offline trace/A-B toolchain is part of the normal maintainer workflow. This doc update records what is already true on mainline versus what remains target-state, so future changes stop treating stale design notes as the current architecture.\n\nConstraint: Reflect only behavior that is already present on mainline; avoid documenting unrecovered worker-only experiments as current reality\nRejected: Collapse everything into README | maintainer-facing migration/provenance details would become harder to keep precise and reviewable\nConfidence: high\nScope-risk: narrow\nDirective: When changing backend public fields or profiling semantics, update AGENTS.md and the linked docs in the same change set so maintainer guidance does not drift behind code again\nTested: git diff --check on updated documentation set\nNot-tested: No runtime/code-path changes in this docs-only commit
The provenance guide already documented the guard semantics and A/B harness, but its example command used the script path that fails from the repo root because package imports do not resolve there. Document the module invocation instead so verification can reproduce the harness without ad hoc path fixes.
Constraint: Keep documentation aligned with the current harness without changing runtime behavior or the default debate path
Rejected: Add PYTHONPATH=. to the examples | less ergonomic and easier to drift from normal repo-root usage
Confidence: high
Scope-risk: narrow
Directive: Keep profiling examples runnable from the repo root; update the docs if the harness entrypoint changes again
Tested: python -m orchestrator.profile_stage_chain --help
Tested: python -m pytest tradingagents/tests/test_research_guard.py orchestrator/tests/test_llm_runner.py orchestrator/tests/test_live_mode.py orchestrator/tests/test_contract_v1alpha1.py orchestrator/tests/test_trading_graph_config.py
Tested: lsp_diagnostics_directory (0 errors, 0 warnings)
Not-tested: end-to-end profile run against a live LLM backend
This change set introduces a versioned result contract, shared config schema/loading, provider/data adapter seams, and a no-strategy application-service skeleton so the current research graph, orchestrator layer, and dashboard backend stop drifting further apart. It also keeps the earlier MiniMax compatibility and compact-prompt work aligned with the new contract shape and extends regression coverage so degradation, fallback, and service migration remain testable during the next phases.
Constraint: Must preserve existing FastAPI entrypoints and fallback behavior while introducing an application-service seam
Constraint: Must not turn application service into a new strategy or learning layer
Rejected: Full backend rewrite to service-only execution now | too risky before contract and fallback paths stabilize
Rejected: Leave provider/data/config logic distributed across scripts and endpoints | continues boundary drift and weakens verification
Confidence: high
Scope-risk: broad
Directive: Keep future application-service changes orchestration-only; move any scoring, signal fusion, or learning logic to orchestrator or tradingagents instead
Tested: python -m compileall orchestrator tradingagents web_dashboard/backend
Tested: python -m pytest orchestrator/tests/test_signals.py orchestrator/tests/test_llm_runner.py orchestrator/tests/test_quant_runner.py orchestrator/tests/test_contract_v1alpha1.py orchestrator/tests/test_application_service.py orchestrator/tests/test_provider_adapter.py web_dashboard/backend/tests/test_main_api.py web_dashboard/backend/tests/test_portfolio_api.py web_dashboard/backend/tests/test_api_smoke.py web_dashboard/backend/tests/test_services_migration.py -q
Not-tested: live MiniMax/provider execution against external services
Not-tested: full dashboard/manual websocket flow against a running frontend
Not-tested: omx team runtime end-to-end in the primary workspace