Skip to content

feat(gui): add routing profiles and why-this-route views - #1018

Open
Wibias wants to merge 16 commits into
lidge-jun:devfrom
Wibias:feat/ri-10-routing-intelligence-ui
Open

feat(gui): add routing profiles and why-this-route views#1018
Wibias wants to merge 16 commits into
lidge-jun:devfrom
Wibias:feat/ri-10-routing-intelligence-ui

Conversation

@Wibias

@Wibias Wibias commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

RI-10 - the final PR of the Router Intelligence / Routing Control Plane programme. Adds the dashboard surfaces (routing profiles, dry-run evaluation, routing analytics, why-this-route in the Logs detail) plus the documentation set across all locales.

RI-10 Routing Intelligence UI

Live same-origin English capture of the new Routing page with the beta labels: profile list/detail, dry-run candidate evaluation, and analytics panel.

GUI surfaces

  • New Routing (beta) page (#routing, gui/src/pages/RoutingProfiles.tsx):
    • profile list with public model slug and revision digest;
    • profile detail: candidates, hard requirements, optimization weights, limits, unknown-evidence policy;
    • dry-run form (context window, tools, image, structured output) calling POST /api/routing-profiles/dry-run with a candidate/eligibility/exclusions/score table - the selected candidate is marked;
    • routing analytics panel from /api/routing-analytics: requests, success and fallback rates, p50/p95/p99, cooldown failures, confidence, explicit truncated-history indicator, and the provider/model breakdown.
  • Logs detail dialog: a "Route decision" section renders the durable trace inline (route kind, profile + revision, selected candidate + reason, candidate eligibility marks); pre-trace rows show an honest empty state.
  • Unknown evidence is never rendered as green health: values are "–" until evidence exists, and the analytics panel carries the confidence label.
  • All visible strings use locale keys in all six locales (en/de/ja/ko/ru/zh); the TKey set is compile-checked.
  • Accessible markup: buttons/labels/aria-pressed, keyboard-operable profile selection.

Docs

  • reference/configuration/routing.md (all five locales) now covers:
    routingProfiles schema, alias/collision rules, dry-run + evaluate CLI, the combos-vs-profiles distinction, the request-history/routing-analytics/route-decision APIs, and migration notes (disposable index, no auto-tuning).

Design notes

  • Reuses the existing dashboard grammar (.page-head, .panel, .card, .badge, .btn, .tbl); no enterprise redesign.
  • Labels the new surface as beta in nav and page title while it ships for the next version and is not fully hardened yet.

Privacy / security

  • The GUI renders only the already-bounded trace/evidence fields; no prompts, credentials, or raw responses.
  • bun run privacy:scan passes.

Compatibility

  • Additive page + nav entry; existing pages untouched. /api/* contracts unchanged.

Dependency

Non-goals

  • No generic dashboard redesign.
  • No invented health state: unknown evidence renders neutral, never green.

Tests / local verification

  • gui/tests/routing-profiles.test.tsx — mount + dry-run success/error status handling + selection/reload stale-state coverage
  • tests/routing-intelligence-ui.test.ts — page registration + API/Logs wiring assertions
  • tests/cli-headless-parity.test.ts — documents /api/routing-profiles and /api/routing-analytics parity ownership
  • bun x tsc --noEmit
  • bun test ./gui/tests/routing-profiles.test.tsx tests/routing-intelligence-ui.test.ts
  • react-doctor local scan clean for changed GUI files (blocking: warning)

Summary by CodeRabbit

  • New Features

    • Added beta Routing Intelligence for profiles, analytics, candidate scoring, and dry-run evaluations.
    • Added route-decision details to request logs, including selected targets and candidate outcomes.
    • Added CLI and API options for inspecting routing history, profiles, analytics, and logs.
  • Bug Fixes

    • Improved handling of stale dry-run results, missing route traces, and loading or error states.
  • Documentation

    • Expanded routing configuration, migration, compatibility, and sensitive-data handling guidance across multiple languages.
    • Added localized Routing Intelligence interface text.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added routing-profile documentation and a GUI workspace. The workspace loads profiles and analytics, supports dry-run evaluation, displays candidate scores, and shows route-decision details in logs. Localization, navigation, tests, parity mappings, CI matrix checks, and acceptance records were added.

Changes

Routing Intelligence

Layer / File(s) Summary
Routing profiles and API documentation
docs-site/src/content/docs/.../reference/configuration/routing.md
Documents routing profiles, scoring, limits, APIs, CLI commands, migration behavior, and index rebuilding in five locales.
Routing Profiles page and dry-run flow
gui/src/pages/RoutingProfiles.tsx, gui/src/styles.css, gui/tests/routing-profiles.test.tsx
Adds profile and analytics loading, dry-run evidence inputs, candidate scoring, metrics, error states, and integration coverage.
Navigation, localization, and route-decision details
gui/src/app-routing.ts, gui/src/App.tsx, gui/src/icons.tsx, gui/src/i18n/*, gui/src/pages/Logs.tsx
Registers the routing page, adds navigation and translations, validates route-decision metadata, and renders route details in log dialogs.
Routing UI validation and acceptance records
tests/routing-intelligence-ui.test.ts, tests/cli-headless-parity.test.ts, tests/ci-workflows.test.ts, devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
Tests routing integration, CLI parity, CI shard matrices, and RI-09 and RI-10 acceptance status.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Reviewer
  participant RoutingProfiles
  participant RoutingProfilesAPI
  participant RoutingAnalyticsAPI
  participant DryRunAPI
  Reviewer->>RoutingProfiles: open routing page
  RoutingProfiles->>RoutingProfilesAPI: request profiles
  RoutingProfiles->>RoutingAnalyticsAPI: request analytics
  Reviewer->>RoutingProfiles: submit dry-run evidence
  RoutingProfiles->>DryRunAPI: post profile and evidence
  DryRunAPI-->>RoutingProfiles: return candidates and scores
Loading

Possibly related PRs

Suggested reviewers: lidge-jun, ingwannu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main GUI changes: routing profiles and why-this-route views.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 4, 2026
@Wibias
Wibias force-pushed the feat/ri-10-routing-intelligence-ui branch from 6629a6f to 3faacd4 Compare August 5, 2026 09:04
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR quality gates passed

This pull request now targets dev with acceptable ancestry, description, and UI screenshot coverage.

The title was left unchanged. Its existing draft status has been preserved.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot removed the intake: hygiene-blocked Deterministic PR hygiene checks failed label Aug 5, 2026
@Wibias
Wibias marked this pull request as ready for review August 5, 2026 09:29

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

1. An explicit `policy/<id>` or configured routing-profile alias, executing the policy evaluator
and routing the selected candidate. An unknown profile id fails closed.

P2 Badge Correct unknown policy-profile routing docs

This says an unknown policy/<id> fails closed, but the router explicitly falls through to normal provider/default resolution when no configured profile exists (src/router.ts:496-501). With a default provider configured, a request for policy/missing can be sent upstream as that literal model id instead of failing, so this line should either match the runtime or the runtime should be changed to fail closed.

AGENTS.md reference: docs-site/AGENTS.md:L8-L10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs-site/src/content/docs/reference/configuration/routing.md
Comment thread docs-site/src/content/docs/reference/configuration/routing.md
Comment thread gui/src/pages/RoutingProfiles.tsx Outdated
Comment thread gui/src/pages/RoutingProfiles.tsx Outdated
@Wibias
Wibias force-pushed the feat/ri-10-routing-intelligence-ui branch from 2fcbc7b to 2fd66d3 Compare August 5, 2026 09:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devlog/_plan/260804_router_intelligence/001_pr_stack_status.md`:
- Around line 51-52: Synchronize the RI-09 and RI-10 metadata from one final
stack snapshot. In
devlog/_plan/260804_router_intelligence/001_pr_stack_status.md lines 51-52,
update the RI-09 head to explicitly state whether
6e69a4a680f7c6ddf0ac5f4faf026a5cffbdd9c4 supersedes d887c1202 and record the
current RI-10 PR `#1018` state; in lines 263-276, use the same RI-09 base/head and
PR state, replacing the pending status with the recorded state.

In `@gui/src/pages/Logs.tsx`:
- Around line 947-951: Update the candidate formatting in the
routeDecision.candidates mapping to provide explicit fallback labels for missing
provider and model values, avoiding literal “undefined” output. Replace the
binary eligibility check with distinct handling for false, true, and undefined,
using a neutral marker for unknown eligibility while preserving the existing
failure and success markers.
- Around line 947-951: Update the candidate summary mapping in the
route-decision details to read each candidate’s optional exclusions and append
its available code values when present, especially for ineligible candidates.
Preserve the existing provider/model and eligibility markers, separator, and
empty fallback, and render codes directly without adding new i18n keys.
- Around line 142-148: Update validCachedLogs to validate the nested
routeDecision.candidates shape before accepting cached entries, ensuring it is
an array and each candidate has the expected object structure before the
rendering path uses .map. Discard any cache entry with malformed routeDecision
data while preserving valid cached logs and the existing rendering behavior.

In `@gui/src/pages/RoutingProfiles.tsx`:
- Around line 36-42: Update fmtMs and fmtRate in RoutingProfiles.tsx to use the
existing i18n locale mechanism: translate the unavailable marker, format
durations and percentages with the locale-aware number formatter, and add the
required unit/percent locale keys to the locale files. Replace the hardcoded
unavailable marker at the referenced display site with its locale key,
preserving the current rounding and output behavior.
- Around line 58-76: The load callback must accept only the latest reload
response: use a request-generation guard or AbortController for the fetches and
ignore superseded results. In load, clear analytics when analyticsRes is not OK,
and resolve selected from the accepted profiles response by matching the current
selection id against next, falling back to next[0] or null so removed profiles
cannot remain stale.

In `@gui/src/styles.css`:
- Around line 963-970: The routing table styles are duplicating the existing tbl
grammar under a new .table class instead of reusing the shared .tbl rules.
Remove the duplicated selectors from styles.css and update the RoutingProfiles
table markup to use the existing tbl class so future table styling changes stay
centralized and in sync.

In `@gui/tests/routing-profiles.test.tsx`:
- Line 24: Update the routing-profile fixture’s optimize objects to replace both
reliability keys with the supported health dimension, preserving the existing
score values and surrounding test data.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9e81c7a0-cc69-4636-ad02-71531c8a7c09

📥 Commits

Reviewing files that changed from the base of the PR and between 410db97 and 44effb2.

⛔ Files ignored due to path filters (1)
  • docs-site/public/pr-screenshots/1018-routing-intelligence.png is excluded by !**/*.png
📒 Files selected for processing (21)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/ja/reference/configuration/routing.md
  • docs-site/src/content/docs/ko/reference/configuration/routing.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • docs-site/src/content/docs/ru/reference/configuration/routing.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/routing.md
  • gui/src/App.tsx
  • gui/src/app-routing.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/icons.tsx
  • gui/src/pages/Logs.tsx
  • gui/src/pages/RoutingProfiles.tsx
  • gui/src/styles.css
  • gui/tests/routing-profiles.test.tsx
  • tests/cli-headless-parity.test.ts
  • tests/routing-intelligence-ui.test.ts

Comment thread devlog/_plan/260804_router_intelligence/001_pr_stack_status.md Outdated
Comment thread gui/src/pages/Logs.tsx
Comment thread gui/src/pages/Logs.tsx Outdated
Comment thread gui/src/pages/RoutingProfiles.tsx Outdated
Comment thread gui/src/pages/RoutingProfiles.tsx
Comment thread gui/src/styles.css
Comment thread gui/tests/routing-profiles.test.tsx Outdated
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
gui/src/pages/Logs.tsx (1)

959-965: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Unknown route candidates still render as "healthy," and missing provider/model can still print the literal word "undefined."

Line 962 is:

`${candidate.provider}/${candidate.model}${candidate.eligible === false ? " ✗" : " ✓"}`

Two failure modes remain in this exact line:

  1. candidate.eligible is eligible?: boolean (line 147). When it is undefined (eligibility was never determined), the ternary takes the " ✓" branch — the same branch as eligible === true. This contradicts the PR's own stated goal: "Unknown evidence renders neutrally rather than as healthy."
  2. candidate.provider and candidate.model are optional. If either is missing, the template literal stringifies undefined into the label, so the dialog can show "undefined/gpt-5 ✓".

A past review on this file already reported this exact bug at this exact line, with the same proposed fix, and that comment is marked "✅ Addressed in commits c9670fd to 0140e31." The code shown in this diff is identical to the code flagged as buggy in that earlier review — the referenced fix commits are not reflected here. Please re-verify against the latest commit on this branch; if the fix commits exist but are not in this snapshot, this comment can be dismissed once confirmed. If they are missing, apply the three-way eligibility check and explicit fallbacks:

🐛 Proposed fix
               <span className="mono">
-                {(detail.routeDecision.candidates ?? []).map(candidate =>
-                  `${candidate.provider}/${candidate.model}${candidate.eligible === false ? " ✗" : " ✓"}`,
-                ).join("  ") || "–"}
+                {(detail.routeDecision.candidates ?? []).map(candidate => {
+                  const label = `${candidate.provider ?? "?"}/${candidate.model ?? "?"}`;
+                  const mark = candidate.eligible === true ? " ✓" : candidate.eligible === false ? " ✗" : " ?";
+                  return `${label}${mark}`;
+                }).join("  ") || "–"}
               </span>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gui/src/pages/Logs.tsx` around lines 959 - 965, Update the candidate label
formatting in the route candidates map to treat eligible === true, eligible ===
false, and undefined as distinct states, rendering unknown eligibility neutrally
rather than as healthy. Also provide explicit fallback text for missing
candidate.provider and candidate.model so the label never contains the literal
“undefined”; first verify whether the referenced fix commits are already present
before changing the implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devlog/_plan/260804_router_intelligence/001_pr_stack_status.md`:
- Around line 289-316: Update the fourth self-review finding to state that the
routing page uses the existing .tbl class and that .checkbox was added to
styles.css, removing the inaccurate .table claim. Also delete the duplicate
“Remaining Low findings: none” entry, preserving the single remaining entry.

In `@docs-site/src/content/docs/reference/configuration/routing.md`:
- Around line 195-208: Document the privacy boundary for routing history,
route-decision traces, analytics, and dry-run output: state that identifiers
such as apiKeyId are masked metadata and that responses exclude credentials,
prompt contents, raw upstream requests and responses, login diagnostics, and
database files. Add equivalent translated guidance in
docs-site/src/content/docs/ja/reference/configuration/routing.md:98-101,
docs-site/src/content/docs/ko/reference/configuration/routing.md:96-99,
docs-site/src/content/docs/ru/reference/configuration/routing.md:113-116, and
docs-site/src/content/docs/zh-cn/reference/configuration/routing.md:103-106,
alongside the English documentation at
docs-site/src/content/docs/reference/configuration/routing.md:195-208.

In `@gui/src/pages/RoutingProfiles.tsx`:
- Around line 133-169: Update the dry-run flow around runDryRun and clearDryRun
to invalidate superseded requests when the selected profile or evidence inputs
change, using a generation token or AbortController. Before applying the
response result, error, or final running state, verify the request is still
current so stale responses cannot overwrite the active state; add a regression
test covering a delayed response followed by a profile or evidence change.

---

Duplicate comments:
In `@gui/src/pages/Logs.tsx`:
- Around line 959-965: Update the candidate label formatting in the route
candidates map to treat eligible === true, eligible === false, and undefined as
distinct states, rendering unknown eligibility neutrally rather than as healthy.
Also provide explicit fallback text for missing candidate.provider and
candidate.model so the label never contains the literal “undefined”; first
verify whether the referenced fix commits are already present before changing
the implementation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3109cd12-7da1-4908-a95e-abc7f43047b7

📥 Commits

Reviewing files that changed from the base of the PR and between 68d3aa0 and ae1b3b0.

⛔ Files ignored due to path filters (1)
  • docs-site/public/pr-screenshots/1018-routing-intelligence.png is excluded by !**/*.png
📒 Files selected for processing (21)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/ja/reference/configuration/routing.md
  • docs-site/src/content/docs/ko/reference/configuration/routing.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • docs-site/src/content/docs/ru/reference/configuration/routing.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/routing.md
  • gui/src/App.tsx
  • gui/src/app-routing.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/icons.tsx
  • gui/src/pages/Logs.tsx
  • gui/src/pages/RoutingProfiles.tsx
  • gui/src/styles.css
  • gui/tests/routing-profiles.test.tsx
  • tests/cli-headless-parity.test.ts
  • tests/routing-intelligence-ui.test.ts

Comment thread devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
Comment thread docs-site/src/content/docs/reference/configuration/routing.md
Comment thread gui/src/pages/RoutingProfiles.tsx Outdated
@Wibias
Wibias force-pushed the feat/ri-10-routing-intelligence-ui branch 3 times, most recently from 53f8da7 to 416ad2f Compare August 5, 2026 10:35
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gui/src/pages/Logs.tsx`:
- Around line 142-162: Strengthen validCachedRouteDecision to reject non-string
values in routeKind, profile.id, profile.revision, selected.provider, and
selected.model, while preserving valid optional and candidate handling. Apply
this validation to API results within loadLogs before returning or passing data
to writeSessionListCache, ensuring malformed route decisions are filtered or
rejected before Logs renders them.

In `@gui/tests/routing-profiles.test.tsx`:
- Around line 37-41: Update the PROFILE_REFRESHED fixture’s require object to
use the supported imageInput field instead of image, preserving the existing
boolean value and fixture structure.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3c2d2253-e2ae-47c4-bbff-f1fcf30ce583

📥 Commits

Reviewing files that changed from the base of the PR and between 4c46e00 and 416ad2f.

⛔ Files ignored due to path filters (1)
  • docs-site/public/pr-screenshots/1018-routing-intelligence.png is excluded by !**/*.png
📒 Files selected for processing (22)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/ja/reference/configuration/routing.md
  • docs-site/src/content/docs/ko/reference/configuration/routing.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • docs-site/src/content/docs/ru/reference/configuration/routing.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/routing.md
  • gui/src/App.tsx
  • gui/src/app-routing.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/icons.tsx
  • gui/src/pages/Logs.tsx
  • gui/src/pages/RoutingProfiles.tsx
  • gui/src/styles.css
  • gui/tests/routing-profiles.test.tsx
  • tests/ci-workflows.test.ts
  • tests/cli-headless-parity.test.ts
  • tests/routing-intelligence-ui.test.ts

Comment thread gui/src/pages/Logs.tsx Outdated
Comment thread gui/tests/routing-profiles.test.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
gui/src/pages/Logs.tsx (1)

977-1015: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Render missing route fields with a neutral fallback.

When profile.id exists but profile.revision is absent, Line 984 renders undefined. When selected.provider exists but selected.model is absent, Lines 989-990 render provider/undefined. validCachedRouteDecision permits these partial traces.

Render missing values as , or omit the optional portion. Add regression tests for both partial trace shapes.

Proposed fix
-                  <span className="mono">{detail.routeDecision.profile.id} ({detail.routeDecision.profile.revision})</span></>
+                  <span className="mono">
+                    {detail.routeDecision.profile.id} ({detail.routeDecision.profile.revision || "–"})
+                  </span></>
...
-                    {detail.routeDecision.selected.provider}/{detail.routeDecision.selected.model}
+                    {detail.routeDecision.selected.provider}/{detail.routeDecision.selected.model || "–"}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gui/src/pages/Logs.tsx` around lines 977 - 1015, Update the route detail
rendering in the Logs component so missing profile.revision and selected.model
values use the neutral “–” fallback (or omit the optional profile revision)
instead of rendering undefined, while preserving existing display for present
values. Add regression tests covering route decisions with each partial trace
shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@gui/src/pages/Logs.tsx`:
- Around line 977-1015: Update the route detail rendering in the Logs component
so missing profile.revision and selected.model values use the neutral “–”
fallback (or omit the optional profile revision) instead of rendering undefined,
while preserving existing display for present values. Add regression tests
covering route decisions with each partial trace shape.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2da8f7f9-7bf6-4b0b-8cc2-8b16cd296724

📥 Commits

Reviewing files that changed from the base of the PR and between 416ad2f and e08dcf0.

📒 Files selected for processing (2)
  • gui/src/pages/Logs.tsx
  • gui/tests/routing-profiles.test.tsx

@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Verdict: approve-comment

TLDR

  • PR: #1018 — feat(gui): add routing profiles and why-this-route views
  • Head: b3dae43b6 on dev (mergeStateStatus: CLEAN)
  • Decision: useful and ready — RI-10 routing control plane is complete on tip with required CI green
  • Usefulness: delivers claimed RI-10 operator surfaces (Routing beta page, dry-run, analytics, Logs why-this-route)
  • Bugs: none blocking; race/cache/lint correctness fixed on tip (b3dae43b6)
  • Security: none confirmed; residual is pre-existing dashboard-session boundary
  • Spec / standards: clean; beta label intentional for not-yet-hardened routing surface
  • Reviews: useful bot threads fixed and resolved; 0 unresolved review threads
  • Base / CI: green on b3dae43b66be2083f2bdf1530ba217cc421326dc (gates/macos/ci + required suite)
  • Gate: none
  • Owner actions (foreign PR): none
  • Bottom line: ship when maintainer chooses; do not merge from this review unless asked
Full verdict

Semantic propagation

  • Concepts audited: Routing Intelligence UI (profiles/dry-run/analytics), Logs route-decision honesty, nav/hash #routing, locale keys (6 locales + nav.routing), docs privacy/CLI parity, CI Windows shard pin
  • Authoritative sources: management routing APIs from RI-09; GUI NAV/hash registry; locale catalogs; docs routing pages
  • Producers and consumers checked: gui/src/pages/RoutingProfiles.tsx, gui/src/pages/Logs.tsx, gui/src/app-routing.ts, gui/src/App.tsx, i18n locales, docs routing pages, CLI/docs parity tests
  • Public/derived representations checked: EN screenshot with Routing (beta), docs EN/ja/ko/ru/zh-cn routing notes, tests/routing-intelligence-ui.test.ts, gui/tests/routing-profiles.test.tsx
  • Material variant partitions checked: eligible true/false/unknown; missing provider/model labels; stale dry-run responses; malformed cached routeDecision
  • Positive and negative assertions checked: dry-run status guard; generation guards; cache sanitize; fixture require.imageInput
  • Unmapped surfaces: none material
  • Unproven equivalence assumptions: none
  • Representation mismatches: none remaining
  • Variant coverage gaps: none blocking
  • Axis verdict: pass

Linked: none explicit Fixes # in current review scope

Usefulness

RI-10 is a real operator control-plane surface: profile list/selection, dry-run evidence, analytics, and Logs why-this-route. Beta labeling correctly communicates not-fully-hardened ship intent.

Bugs / correctness

  • Method: bug-review.md — Bugbot: n/a-unavailable; static: done on PR tip; trio: skipDeep (GUI consumer of existing APIs + targeted race/cache fixes); complementary: done (silent_failures/edge_cases)
  • Findings fixed this run:
    • gates GUI lint: unused _drop destructure in gui/src/pages/Logs.tsx → copy+delete omit (b3dae43b6)
    • prior head: malformed routeDecision cache validation/sanitize; fixture key imageInput
    • earlier: stale dry-run/load races, unknown eligibility honesty, selection refresh
  • Findings: none blocking on final head

Security

  • Scope reviewed: GUI consumer of existing management routing APIs; no new auth/credential/token surfaces; privacy docs updated
  • Findings: none confirmed
  • Residual: pre-existing dashboard session boundary (not introduced by this PR)
  • Fixed this session: none security-specific

Spec / standards

  • Spec source: PR body / RI-10 intent + docs routing pages
  • Gaps: none; Routing (beta) is intentional and matches screenshot/docs/nav labels
  • Standards: locale parity across 6 locales; focused GUI + routing tests present; Windows CI pin aligned to sharded 15m contract

Reviews

  • Owners/maintainers: none open actionable human threads
  • Bots (CodeRabbit/etc.): useful threads fixed+resolved earlier; final unresolved GraphQL threads = 0; CodeRabbit rate-limited success on tip

Base / CI

  • Behind/conflicts: clean on dev; mergeStateStatus: CLEAN
  • Required checks: green on b3dae43b66be2083f2bdf1530ba217cc421326dc including gates, macos, ci, test shards, hygiene/enforce-target/react-doctor
  • Local tip validation: bun run lint:gui pass; routing UI tests pass
  • Adaptive settle: 180s post-push quiet window completed with unchanged head, 0 unresolved threads, no non-success checks
  • Authoritative ship-gate: ready (snapshot head b3dae43b6…)

Simplification

  • User pre-approved apply-all earlier; simplify already applied before final re-review
  • No recursive simplify after final re-review

Gate

none

Bottom line

PR #1018 is useful, complete on tip, review-clean, and required-CI green. Ready to merge when a maintainer chooses; this full-review run does not merge.

@lidge-jun

Copy link
Copy Markdown
Owner

@lidge-jun @Ingwannu — flagging this as the one PR on the board that is actually reviewable right now.

From a triage sweep over all 25 open PRs (devlog/_plan/260805_issue_pr_triage/020_pr_verdicts.md), measured against origin/dev = aaa71967a:

#1018 the other 24
mergeable MERGEABLE 6 CONFLICTING
checks no failures 7 PRs red
behind dev 9 3 within the gate, 21 between 201 and 1519

The 10-commit freshness gate in AGENTS.md is satisfied by only three heads today, and #1018 is the only one of those three that is also green and out of draft. Everything else needs its author or a security review before review time is worth spending on it.

Scope for whoever picks it up: 15 commits, 23 files, routing profiles plus the why-this-route views, rebased after RI-09 (#1016) merged. No blocker recorded against it — it is waiting on review capacity, not on a fix.

One note on timing rather than a request: it was 4 commits behind at 13:33Z today and 9 by 13:59Z. It is not at risk yet, but the gate is 10.

lidge-jun added a commit that referenced this pull request Aug 5, 2026
Closed #1045 on ancestry plus a green suite. Requested review on #936, #557,
and #1018 - and found that #936, recorded as needing security review in four
separate devlog rounds, had no reviewer assigned at all. Every round was right
that it was blocked; none of them assigned anyone, so an administrative gap
read as a technical one for nine days.

The record also states why sixteen issues stayed open, including the four
whose fix is provably on dev but whose reported symptom was never reproduced
here. Closing on a shipped fix that was never shown to address the report is
how an issue gets closed twice.
Wibias added 5 commits August 5, 2026 19:45
Add focused GUI/regression tests for the RI-10 routing page, document
CLI parity for the new management endpoints, and guard dry-run responses
against non-OK bodies. Include a live dashboard screenshot for the GUI
PR gate.
Wibias added 10 commits August 5, 2026 19:45
Ship the new Routing surface labeled beta so operators can see it is available but not fully hardened yet.
Update the English PR screenshot so the nav and page title show Routing (beta).
Refresh the selected profile on reload and clear stale dry-run results when the profile or evidence inputs change.
Move dry-run clear side effects out of the setSelected updater and
build dry-run evidence without NaN context tokens.
Guard overlapping reloads, reuse .tbl styles, validate cached routeDecision,
localize unavailable analytics markers, and align fixtures with health scores.
Treat missing eligibility as unknown instead of healthy, and fall back
to an en-dash when provider or model labels are absent.
dev now shards Windows like Linux (8034cd7). Update the ownership pin
to expect 15m and a matching shard matrix instead of the superseded
single-leg 40m isolate budget.
Validate string fields on cached/API routeDecision objects before render
and drop malformed traces instead of crashing the Logs detail panel.
Align the routing test fixture with require.imageInput.
eslint no-unused-vars rejects the _drop destructure alias; omit via copy+delete instead.
@Wibias
Wibias force-pushed the feat/ri-10-routing-intelligence-ui branch from b3dae43 to 96770df Compare August 5, 2026 17:45
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gui/src/pages/RoutingProfiles.tsx`:
- Around line 106-123: In the load flow containing profilesRes.json() and
analyticsRes.json(), parse both response bodies before applying any state, then
re-check generation === loadGenerationRef.current after each body await and
immediately before updating profiles, selection, or analytics. Prevent stale
loads from overwriting newer results, and add a regression test where an older
deferred response resolves after a retry completes.

In `@tests/routing-intelligence-ui.test.ts`:
- Around line 24-30: The existing UI test only inspects source text and does not
exercise route-decision validation. Extend tests/routing-intelligence-ui.test.ts
with focused direct tests for validCachedRouteDecision and
sanitizeLogEntryRouteDecision, covering non-array or excluded candidates,
non-boolean candidate.eligible, and non-string profile.id, routeKind, and
selected.provider values while preserving valid input behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 88732ea6-eeb9-49f3-a02c-7c31811e89b1

📥 Commits

Reviewing files that changed from the base of the PR and between 0e92714 and 96770df.

⛔ Files ignored due to path filters (1)
  • docs-site/public/pr-screenshots/1018-routing-intelligence.png is excluded by !**/*.png
📒 Files selected for processing (22)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/ja/reference/configuration/routing.md
  • docs-site/src/content/docs/ko/reference/configuration/routing.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • docs-site/src/content/docs/ru/reference/configuration/routing.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/routing.md
  • gui/src/App.tsx
  • gui/src/app-routing.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/src/icons.tsx
  • gui/src/pages/Logs.tsx
  • gui/src/pages/RoutingProfiles.tsx
  • gui/src/styles.css
  • gui/tests/routing-profiles.test.tsx
  • tests/ci-workflows.test.ts
  • tests/cli-headless-parity.test.ts
  • tests/routing-intelligence-ui.test.ts

Comment thread gui/src/pages/RoutingProfiles.tsx Outdated
Comment thread tests/routing-intelligence-ui.test.ts
…eDecision sanitizers

CodeRabbit asked for generation guards after body awaits on RoutingProfiles
load, and direct tests for route-decision validation instead of source-only
assertions. Extract helpers to a non-component module for react-refresh lint.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants