Knowledge Base¶
Purpose¶
This is the canonical record of project knowledge that has been verified or is explicitly tracked as unresolved. It is not a transcript and it is not a place to paste raw external research.
Raw Perplexity responses belong in Research/. Local investigation reports belong in Findings/. Promote information here only when its evidence and confidence are clear.
Project status¶
| Area | Status |
|---|---|
| Internet research | Complete |
| Local investigation | Complete (Phase 1B findings recorded 2026-08-02) |
| Architecture | Approved (Phase 2 complete 2026-08-02; data sources and failure behavior identified) |
| Design | Approved (Phase 3 complete 2026-08-02; ADR-0009) |
| Implementation | Complete (Phase 4 complete 2026-08-03; committed 5c0973b, deployed to ~/.claude/statusline/) |
| Validation | Complete (Phase 5 complete 2026-08-03; report in Findings/2026-08-03 - Phase 5 - Validation Report.md) |
| V1.0 release | Complete (ADR-0010 recorded 2026-08-03; merged to main, tagged v1.0.0) |
| Post-V1.0 styling | Implemented (2026-08-04; feature/statusline-polish, commit c0792f9) |
| Context window data source | Investigated (2026-08-04; findings in Findings/2026-08-04 - Context Window Data Source and Statusline Styling.md); Model Database sync verified — models.dev sync populated model_capabilities 0 → 7,278 rows with limit_context; V2 implemented & deployed (2026-08-04; feature/statusline-polish, commits e3c03c5/ca4a9ec) — mapping carries contextWindows, statusline shows the resolved model's real window with payload fallback |
Confirmed facts¶
Fact: The statusline payload carries the requested model, not the resolved route¶
- Status: Confirmed
- Evidence:
Findings/2026-08-01 - Phase 1B - Statusline Input Contract.md;model.display_namein the payload equals the configuredANTHROPIC_MODEL(auto/cheap) in.claude/settings.local.json. - Observed on: 2026-08-02
- Confidence: High
- Notes: This is the documented Claude Code contract, not a defect.
Fact: OmniRoute records the resolved provider/model per request in SQLite¶
- Status: Confirmed
- Evidence:
Findings/2026-08-01 - Phase 1B - OmniRoute Topology and Logs.md;call_logstable columnsmodelandproviderhold the post-routing values, separate fromrequested_model. Sample:requested_model=auto/cheap→model=big-pickle,provider=opencode. - Observed on: 2026-08-02
- Confidence: High
- Notes: Data is in the Docker volume
omniroute-data(/app/data/storage.sqlite), accessible read-only viadocker execor a throwaway volume-mounted container.
Fact: The session transcript records the resolved model per assistant message¶
- Status: Confirmed
- Evidence:
Findings/2026-08-01 - Phase 1B - Statusline Input Contract.md; 101 assistant messages in the current session transcript carry amodelfield with resolved values (deepseek-v4-flash,mimo-v2.5-free,gemini-3-flash-preview,sonnet). - Observed on: 2026-08-02
- Confidence: High
- Notes: The transcript
modelis the API response'smodelfield echoed by OmniRoute; it carries the model string but not a separate provider field.
Fact: The statusline contract has no resolved-provider field¶
- Status: Confirmed
- Evidence: Full statusline schema (code.claude.com/docs/en/statusline) and local payload inspection; only
model.idandmodel.display_nameexist. - Observed on: 2026-08-02
- Confidence: High
- Notes: Any resolved-provider display requires a side channel (SQLite or transcript), not the statusline payload.
Fact: Session-level correlation is not functional in this installation¶
- Status: Confirmed
- Evidence:
Findings/2026-08-01 - Phase 1B - OmniRoute Topology and Logs.md;session_tagis NULL on all 3680call_logsrows;session_model_historyhas 0 rows. - Observed on: 2026-08-02
- Confidence: High
- Notes: A statusline can report the most recent route but cannot reconstruct per-session history from OmniRoute logs alone.
Fact: OmniRoute management APIs require a separate token¶
- Status: Confirmed
- Evidence:
Findings/2026-08-01 - Phase 1B - OmniRoute Topology and Logs.md; all/api/usage/*,/api/sessions,/api/analytics/*, and/api/cloud/model/resolvereturn 403AUTH_001with the gateway token. - Observed on: 2026-08-02
- Confidence: High
- Notes: A management token (scope
["manage","grammars"]) exists inapi_keysbut is not in the local configuration.
Fact: The resolved route for an auto combo is not stable across requests¶
- Status: Confirmed
- Evidence:
Findings/2026-08-02 - Phase 2 - Read-only Verification.md;combo_name='auto/cheap'(482 rows) resolves to 20+(provider, model)pairs with mixed success (status 200/400/402/413/429/499/502). - Observed on: 2026-08-02
- Confidence: High
- Notes: A statusline that displays "the resolved route" displays the most recent route, not a stable value. Each statusline event must re-read.
Fact: The transcript carries the resolved model on every assistant message¶
- Status: Confirmed
- Evidence: Phase 2 transcript inspection; 78/78 assistant messages carry
message.model, values matchingcall_logs.model(big-pickle,mimo-v2.5-free). - Observed on: 2026-08-02
- Confidence: High
- Notes: In the current Claude Code version the field is nested at
message.model(Phase 1B read it at the top level) — evidence of transcript version drift. No separate provider field exists in the transcript.
Fact: The transcript read is sub-millisecond; SQLite read latency is dominated by Docker startup¶
- Status: Confirmed
- Evidence: Phase 2 measurements: transcript tail 0.00 s; SQLite query <10 ms;
docker runstartup 0.21–0.29 s;docker run+apk add sqlite0.73–1.13 s.sqlite3is not present in theomnirouteor plainalpineimages. - Observed on: 2026-08-02
- Confidence: High
- Notes: The 300 ms statusline debounce is exceeded by the
docker run+ install path; a pre-baked sqlite3 image is required for any SQLite-based read.
Fact: combo_name is the reliable filter for auto-routed traffic in call_logs¶
- Status: Confirmed
- Evidence: Phase 2 query;
requested_model='auto/cheap'matches only 14 rows (all status 499, providerauto— the blocked/classifier-gated requests), whilecombo_name='auto/cheap'matches 482 rows including all concrete resolutions. - Observed on: 2026-08-02
- Confidence: High
- Notes: Any SQLite query for auto routes must filter on
combo_name, notrequested_model.
Fact: The empirical model→provider mapping is currently unambiguous¶
- Status: Confirmed (observation about current data)
- Evidence: Phase 2 query over successful auto-routed rows; no model appears under more than one provider (e.g.,
big-pickle→opencode864,mimo-v2.5-free→opencode145). - Observed on: 2026-08-02
- Confidence: Medium — reflects the current catalog; providers can add or remove models, so this is a heuristic, not a contract.
Fact: The statusline never calls OmniRoute at read time¶
- Status: Confirmed (verified from code and contract test)
- Evidence:
Statusline/lib/*read only the local transcript (JSONL) and the local mapping file; contract test case 16 asserts the route-path modules load nochild_process;Statusline/Design/04-caching-timeout-policy.md. - Observed on: 2026-08-03
- Confidence: High
- Notes: "OmniRoute unavailable" exercises no statusline code path beyond a frozen transcript; this is why the Phase 5 scenario is opportunistic, not a required induced failure.
Fact: Assistant messages stream into the transcript progressively with write-time timestamps¶
- Status: Confirmed
- Evidence: Transcript lines for one message (
id 313c518e): thinking07:24:04.911Z, text07:24:05.368Z, tool_use07:24:07.688Z— separate flushed lines, distinct timestamps, model present on the first (thinking) entry. - Observed on: 2026-08-03
- Confidence: High
- Notes: A new turn produces a fresh, parseable assistant entry with a fresh timestamp at generation start. This is why the
[stale]marker clears before the response completes — correct per the ADR-0009 design.
Fact: Auto-routing is request-weight dependent (observed once)¶
- Status: Confirmed (single observation pair)
- Evidence:
call_logs2026-08-03 07:45–07:46 — a fresh light session (tokens_in≈ 31K) resolvedmimo-v2.5-free/opencode; a heavy session (tokens_in≈ 152K) stayedbig-pickle/opencode; both status 200. - Observed on: 2026-08-03
- Confidence: Medium — a single observed pair; routing heuristics may consider other request characteristics.
- Notes: The statusline faithfully shows whatever the last assistant message resolved to; it does not explain why a route was chosen.
Fact: The statusline failure invariant holds¶
- Status: Confirmed
- Evidence: 29 contract tests (all 16 acceptance cases + invariants) pass; live failure paths verified — missing transcript →
auto/cheap, unparseable stdin →"", empty mapping → model-only. Every failure path degrades to the requested label or empty; neverundefined/null/error in output. - Observed on: 2026-08-03
- Confidence: High
Fact: Context window comes from Claude Code's payload, not from an observed source (superseded by V2)¶
- Status: Confirmed (V1 behavior); superseded by V2 for the context-window segment
- Evidence: Under V1,
formatContextreadctx.context_window_sizefrom the stdin payload (Claude Code provides this) — no hardcoded context-window value exists in the statusline source. V2 (2026-08-04,feature/statusline-polish) prefers the resolved model's real window from the mapping'scontextWindowsblock and falls back to the payload when no entry exists. The payload still reflects what Claude Code believes the requested model's window is. - Observed on: 2026-08-04
- Confidence: High
- Notes: This is the same "requested vs resolved" divergence documented for model names. V2 closes it for models covered by
model_capabilities.limit_context.
Fact: OmniRoute's model_context_overrides table has real context windows, but coverage is uneven¶
- Status: Confirmed
- Evidence:
model_context_overrideshas 424 rows (allsource = 'auto:discovery'), keyed by (provider, model_id) with areal_contextcolumn. Providers with entries:openrouter(362),gemini(47),groq(15). Providers with no entries:opencode,nvidia,local,anthropic. Only 62 resolved calls incall_logshave a direct model_id match to this table. Provider keys differ betweencall_logsandmodel_context_overrides(e.g.,call_logsrecordsprovider = "nvidia"for nemotron models;model_context_overridesstores them underprovider = "openrouter"). - Observed on: 2026-08-04
- Confidence: High
- Notes: This is the most promising source for the resolved model's real context window, but it does not cover the internal proxy models (
big-pickle,mimo-v2.5-free,deepseek-v4-flash-free) that are the most common resolved models in this setup. Extending the mapping script to pullreal_contextwould improve accuracy for external models; the internal proxy models have no observed context-window data in any OmniRoute table.
Fact: The models.dev Model Database sync populates model_capabilities with real context windows¶
- Status: Confirmed
- Evidence: OmniRoute admin UI "Model Database" section ("Auto-sync pricing, capabilities & specs from models.dev"); after a manual sync,
model_capabilitieswent from 0 to 7,278 rows, all withlimit_contextpopulated. The internal proxy models each appear under provideropencode(matchingcall_logs):big-pickle200,000,mimo-v2.5-free200,000,deepseek-v4-flash-free200,000,deepseek-v4-flash1,000,000. Provider+model join returns 1,709 matched call rows; 384 distinct resolved models map to a row. - Observed on: 2026-08-04
- Confidence: High
- Notes: This supersedes the gap recorded in the
model_context_overridesfact — internal proxy models now have observed context-window data. For the commonauto/cheapcase the value (200,000) matches Claude Code's payload guess; the divergence shows for models likedeepseek-v4-flash(1,000,000).model_context_overridesis unchanged (424 rows): the sync writes tomodel_capabilities, not overrides.
Fact: V2 mapping carries contextWindows; the statusline prefers the resolved model's real window¶
- Status: Confirmed
- Evidence:
Scripts/update-model-provider-mapping.jsLEFT JOINsmodel_capabilitiesonmodel_idand writesMAX(limit_context)under a siblingcontextWindowsblock;Statusline/lib/mapping.jsresolveContextWindowreads it;formatContext(ctx, overrideWindow)prefers a positive override over the payload. Regenerated mapping: 8 → 12 models, all 12 withcontextWindows(e.g.mistral-large-latest262,144;deepseek-v4-flash1,000,000), no existing provider mapping changed. Suite 50/50. - Observed on: 2026-08-04
- Confidence: High
- Notes: The block is optional — old mappings without it degrade to the payload fallback (provider resolution is untouched). The V2 generation path was fixed in commit
ca4a9ecafter deployment verification caught thataggregate()dropped the ctx column (see the findings doc Part 4).
External research claims awaiting verification¶
The Perplexity responses may contain useful claims about Claude Code, OmniRoute, statuslines, source files, routing, or endpoints. Those claims must remain in Research/ until they are independently assessed.
Do not convert a claim into a confirmed fact merely because it appears in an external response.
Open questions¶
- Does a management token exist in
server.envor the OmniRoute admin UI that could unlock the HTTP API path? (Explicitly out of scope for the approved architecture; the design treats the management API as unavailable.) - Is the
opencodevsopencode-zenduplication inmodel_capabilitiesa stable convention (same model mirrored under multiple aggregator keys), and which key should the mapping script prefer? - Does the OmniRoute Model Database sync run on a schedule or only manually? (Relevant to mapping-file freshness.)
- Does
model_capabilities.limit_contextreflect the model's native window or a provider-capped window? - Is the provider key mismatch (
nvidiaincall_logsvsopenrouterinmodel_context_overrides) a permanent naming convention, or will OmniRoute reconcile them?
Resolved questions (answered by Phase 1B findings)¶
- Which exact fields does Claude Code provide to the statusline? → Documented schema confirmed;
model.idandmodel.display_nameare the only model fields; no resolved-provider field exists. - Is the resolved provider/model available in the statusline input? → Not in the payload; available via the transcript (model string) and SQLite call_logs (model + provider).
- Why does the statusline show
auto? → It is the configured requested model (ANTHROPIC_MODEL), not a bug. - Which local boundary exposes the resolved route? → SQLite
call_logsvia Docker volume; transcript JSONL per-assistant-messagemodelfield. - Is a local integration read-only feasible? → Yes: both SQLite (docker exec / docker run read-only) and transcript (JSONL read) are read-only paths.
- Can the integration be read-only? → Yes; no live inference or config changes required for either path.
Resolved questions (answered by Phase 2 findings, 2026-08-02)¶
- How stable is the resolved model label across requests? → Not stable;
auto/cheapresolves to 20+ provider/model combos with a large failure tail. The statusline displays the most recent route, re-read on each event. - Can the transcript model field be relied upon to always reflect the resolved model? → Yes for the observed providers: present on 78/78 assistant messages, values match
call_logs.model. The field reflects the model the API response used; no separate provider field exists. - What is the latency difference between transcript and SQLite reads? → Transcript sub-millisecond; SQLite query <10 ms but Docker startup 0.21–1.13 s, over the 300 ms budget unless a pre-baked sqlite3 image is used.
- What is the safest fallback when SQLite or the transcript is unavailable or stale? → Defined fallback chain (ADR-0005/0006): requested-model from the payload until the first assistant message; model-only display when provider enrichment fails;
stalemarker past the threshold. - Which data may be displayed locally without exposing secrets? → Metadata only (model, provider, combo, status, timestamp); never request bodies,
server.env, or key tables.
Resolved questions (answered by the approved Phase 3 design, 2026-08-02)¶
- What staleness threshold is acceptable for an interactive statusline? → 5 minutes by default (configurable constant); a
[stale]marker is appended past the threshold. - How is the empirical model→provider mapping stored and refreshed? → Versioned JSON at
~/.claude/statusline-model-provider.json, refreshed out-of-band by aScripts/maintenance script, never at statusline read time. - Which provider source does the design use? → The empirical mapping is the default; SQLite enrichment is a documented optional path (off by default). A missing provider degrades to model-only.
- Is the transcript tail window a fixed architectural size? → No; the architecture requires only a bounded tail read, and the concrete window size is an implementation constant (currently 256 KB) — approved change request in ADR-0009.
Resolved questions (answered by Phase 4/5 validation, 2026-08-03)¶
- Does the
[stale]marker clear at the right time? → Yes. Staleness keys to the last assistant message's timestamp; transcript entries stream in at generation start, so the marker clears as soon as a new turn begins processing — before response completion. This matches the approved design (ADR-0009); not a bug. - Does the statusline track per-session route changes? → Yes. Live model-switch validated: a fresh light session showed
opencode/mimo-v2.5-freewhile a heavy session keptopencode/big-pickle; each session's statusline showed its own resolved route. - Does the statusline stay bounded across terminal widths? → Yes. Manual resize test: single line, no wrap, no prompt overlap, readable.
- Is the OmniRoute-unavailable scenario a required induced failure? → No; opportunistic only. The statusline has no runtime coupling to OmniRoute, and the statusline-visible effect (no new assistant messages →
[stale]) is identical to idle and already validated. - Is the statusline resilient to the safety-classifier gating seen in Phase 1B? → Yes. The 2026-08-02 classifier outage did not affect the statusline; its route path uses only plain
fsreads (contract case 16). - Does the deployed statusline still resolve a real route after the Phase 4 install? → Yes. Live smoke returned
opencode/big-picklefrom the deployed binary with real transcript + mapping, matchingcall_logs.
Resolved questions (answered by context window investigation, 2026-08-04)¶
- Is the "200K ctx" hardcoded in the statusline? → No.
formatContextreadsctx.context_window_sizefrom the Claude Code stdin payload. No200000literal exists in the statusline source; the window value is whatever Claude Code sends. - Is the context window data from OmniRoute, like the provider? → No. The provider is resolved from the transcript + mapping (OmniRoute-observed data). The context window comes from Claude Code's own payload — it reflects the requested model's window, not the resolved model's window. This is the same "requested vs resolved" divergence documented for model names.
- Does OmniRoute record the real context window anywhere? → Yes:
model_context_overrides.real_context(424 rows, allauto:discovery), but coverage is uneven — openrouter (362), gemini (47), groq (15); no entries foropencode,nvidia,local, oranthropicas used in the mapping file. Only 62 resolved calls have a direct model_id match. - Is a provider-hue statusline styling feasible without changing the provider-aware logic? → Yes. A presentation layer (
lib/style.js) applies ANSI decoration at render time only; all segment-content functions and their tests are unchanged. This architecture was implemented onfeature/statusline-polish(commitc0792f9) and passes all35 tests. - Could
model_capabilitiesbe populated, and by what process? → Yes. The OmniRoute admin "Model Database" section ("Auto-sync pricing, capabilities & specs from models.dev") populates it. After a manual sync: 7,278 rows, all withlimit_context. (Recorded 2026-08-04.) - Are there OmniRoute tables that record context-window data for the internal proxy models (
big-pickle,mimo-v2.5-free,deepseek-v4-flash-free)? → Yes —model_capabilities, populated by the models.dev sync. All three havelimit_context = 200000under provideropencode(matchingcall_logs);deepseek-v4-flashis 1,000,000. (Recorded 2026-08-04.)
Research sources¶
Add source entries only when they are tied to a research record or finding:
### <source title>
- URL: <url>
- Used by: `Research/<filename>.md`
- Accessed: <date>
- Relevance: <one or two sentences>
- Verification status: Unassessed | Partially assessed | Verified locally | Not applicable
The bibliography itself belongs in References/; this section is an index of sources that materially support the knowledge base.
Promotion rules¶
- Preserve the original external claim in
Research/. - Record local observations and supporting evidence in
Findings/. - State the conclusion, scope, confidence, and remaining limitations.
- Add the conclusion here only after review.
- Update
Architecture.mdorDecisions.mdwhen the conclusion changes design or project direction.