Closes #116. `config/models.yaml` declared a default chain and six per-skill chains. The issue filed against it said the deployed service does not read the file. That was true and understated: **nothing reads it at all**, and the loader written to read it is dead too. The whole chain goes: - `config/models.yaml` — data with no consumer - `internal/config/models.go` — `LoadModels` and `ModelFor`, whose only callers are in `models_test.go` - `internal/config/config.go` — the `ModelsFile` field, assigned from `SUPERVISOR_MODELS_FILE` and never read - `.env.example` — the variable that configures the path to the file nobody opens Deleting the YAML alone would have left a loader pointing at a missing file: one decoy replaced by another. This subsystem had THREE PASSING TESTS. That is what kept it invisible. Green assertions proving a function nobody calls works correctly are worse than no tests, because coverage is exactly the signal someone would use to decide the code is alive. The repo's own `docs/superpowers/specs/2026-04-20-model-orchestration-design.md` said so in April — "the model routing config exists but is dead weight" — and it survived five more months anyway. Two of the six models it named no longer exist (`iguana/qwen3-coder-next`, retired in infra#416, and `koala/qwen3-coder-30b`, gone earlier). Nobody noticed because the file being unread is the only reason it never failed. Live routing is env, on the deployed `ingestion` service: `INGEST_LLM_MODEL`, `BRAIN_LLM_PRIMARY_MODEL`, and four more. Not one name from the deleted file appears there. Env is the real configuration surface; this file read as though it were, which is why editing it to change routing would have changed nothing, silently. `go build ./...` clean, `task check` EXIT=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
40 lines
1.5 KiB
Go
40 lines
1.5 KiB
Go
package config
|
|
|
|
import "os"
|
|
|
|
type Config struct {
|
|
Port string // SUPERVISOR_PORT, default 3200
|
|
LiteLLMBaseURL string // LITELLM_BASE_URL, default http://iguana:4000
|
|
LiteLLMAPIKey string // LITELLM_API_KEY
|
|
ConfigDir string // SUPERVISOR_CONFIG_DIR, default ./config/supervisor
|
|
IngestBaseURL string // INGEST_BASE_URL, default http://localhost:3300
|
|
IngestSvcURL string // INGEST_SVC_URL — base URL for brain_ingest (/ingest, /ingest-path)
|
|
KBRetrievalURL string // KB_RETRIEVAL_URL — base URL for brain_search
|
|
SessionsDir string // SUPERVISOR_SESSIONS_DIR, default ./brain/sessions
|
|
BrainDir string // SUPERVISOR_BRAIN_DIR, default ./brain
|
|
MCPAuthToken string // SUPERVISOR_MCP_TOKEN — optional bearer token for MCP HTTP; empty disables auth
|
|
}
|
|
|
|
func Load() (Config, error) {
|
|
cfg := Config{
|
|
Port: envOr("SUPERVISOR_PORT", "3200"),
|
|
LiteLLMBaseURL: envOr("LITELLM_BASE_URL", "http://iguana:4000"),
|
|
LiteLLMAPIKey: os.Getenv("LITELLM_API_KEY"),
|
|
ConfigDir: envOr("SUPERVISOR_CONFIG_DIR", "./config/supervisor"),
|
|
}
|
|
cfg.IngestBaseURL = envOr("INGEST_BASE_URL", "http://localhost:3300")
|
|
cfg.IngestSvcURL = envOr("INGEST_SVC_URL", "")
|
|
cfg.KBRetrievalURL = envOr("KB_RETRIEVAL_URL", "")
|
|
cfg.SessionsDir = envOr("SUPERVISOR_SESSIONS_DIR", "./brain/sessions")
|
|
cfg.BrainDir = envOr("SUPERVISOR_BRAIN_DIR", "./brain")
|
|
cfg.MCPAuthToken = os.Getenv("SUPERVISOR_MCP_TOKEN")
|
|
return cfg, nil
|
|
}
|
|
|
|
func envOr(key, def string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|