Skip to content

feat(routing): add validated routing policy profiles - #1011

Merged
Wibias merged 8 commits into
lidge-jun:devfrom
Wibias:feat/ri-04-policy-profile-core
Aug 5, 2026
Merged

feat(routing): add validated routing policy profiles#1011
Wibias merged 8 commits into
lidge-jun:devfrom
Wibias:feat/ri-04-policy-profile-core

Conversation

@Wibias

@Wibias Wibias commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

RI-04 of the Router Intelligence / Routing Control Plane programme. Adds the
routing policy profile core: a validated top-level routingProfiles
config schema, deterministic normalization + revision digest, collision
validation, a dry-run evaluator, management API, CLI, and documentation.

Policy routing is inert in this PR: no production request uses a profile
yet (that is RI-05). Everything here is configuration, evaluation-on-demand,
and dry-run.

Scope

  • src/types.ts - OcxRoutingProfileConfig (candidates allowlist, alias,
    require, optimize, limits, unknownEvidence) + routingProfiles on
    OcxConfig.
  • src/routing/profile.ts - validation (routingProfileIssues), alias
    collision rules (providers, combos, codex account namespaces, sibling
    profiles, reserved native families, policy/ + combo/ namespaces),
    normalization (normalizeRoutingProfile), SHA-256 revision digest
    (16-hex), resolvePolicyProfileId / parsePolicyModelId /
    policyPublicModelId.
  • src/routing/evaluator.ts - deterministic dry-run evaluator: hard
    capability requirements (min context window, tools, image input, structured
    output, reasoning effort, service tier, local/remote, encrypted Codex
    tasks) are evaluated against supplied evidence; unknown-capability handling
    follows the profile's unknownEvidence; scoring is deterministic
    configured priority only (capability/health/quota/cost components arrive
    with RI-05..08). Produces a full RI-01 decision trace with
    profile.id/profile.revision.
  • src/config.ts - routingProfiles validated inside
    validateConfigCandidate (broken profiles fail closed like broken combos).
  • Management API: GET /api/routing-profiles,
    POST /api/routing-profiles/dry-run.
  • CLI: ocx route policy list | show <id> | dry-run <id> --model-context <tokens> --tools [--image] [--structured-output].
  • Docs: routing configuration reference gains the routingProfiles schema
    and the combos-vs-profiles distinction (locale sync completes in RI-10).
  • tests/routing-profile.test.ts - 12 tests.

Unknown is not zero

unknownEvidence per profile controls unknown capability evidence:
exclude (default), penalize, or allow. Unknown prices/health/quota stay
unknown; nothing converts unknown to zero or free.

No implicit routing

Existing model ids, combos, account namespaces, and default-provider
resolution are byte-for-byte unchanged. Profiles only activate for an
explicitly requested policy/<id> or alias (RI-05 wires execution).

Compatibility

  • Existing config files without routingProfiles load unchanged.
  • Additive APIs; /api/logs, /api/request-history, /api/routing-analytics
    unchanged.

Privacy / security

  • Dry-run never dispatches upstream requests and never touches credentials.
  • Traces follow RI-01 bounds; no prompts, keys, or raw responses.
  • bun run privacy:scan passes.

Dependency

Non-goals

  • No production policy execution (RI-05).
  • No health/quota/cost scoring (RI-06/07/08).
  • No explainability API or GUI (RI-09/10).
  • No implicit candidate expansion - explicit allowlist only.

Local verification (exact)

  • bun x tsc --noEmit -> PASSED (0 errors)
  • bun run test tests/routing-profile.test.ts -> 13/13 pass (12 + request-evidence regression)
  • Focused regression suites -> pass across route-decision-trace, routing-analytics,
    request-history-index, combos, codex-routing, internal-cli-dispatch
  • bun run privacy:scan -> passed
  • tests/config.test.ts: 109/115 pass; the 6 symlink failures reproduce
    identically on the pristine base (Windows symlink EPERM, environmental)

Review round (2026-08-05)

  • Dry-run evaluator now evaluates request evidence (context window, tools, image,
    structured output, reasoning effort, service tier, encrypted Codex tasks)
    against candidate capabilities together with the profile require block; the
    CLI dry-run flags are live.
  • Alias validation rejects aliases in the <provider>/<model> routing namespace
    of a configured provider.
  • Removed the dead routingProfileIssuesForConfig export; simplified CLI output
    calls and candidate scoring.

Notes for reviewers

  • Weight normalization keeps defaults for omitted dimensions (documented in
    tests): optimize: { latency: 1, cost: 3 } merges health 0.25 and quota
    0.1 before normalizing (sum 4.35).
  • The revision digest covers the normalized profile (sorted-key canonical
    JSON), so configs that differ only in formatting share a revision.

Summary by CodeRabbit

  • New Features
    • Added configurable routing policy profiles for selecting provider/model candidates based on capabilities, priorities, cost limits, and evidence handling.
    • Added route policy commands to list, inspect, and dry-run routing profiles.
    • Added management API endpoints for viewing profiles and testing routing decisions without sending requests.
    • Added validation, deterministic scoring, decision traces, and clear handling for invalid or incomplete evidence.
  • Documentation
    • Documented routing profiles, configuration options, examples, CLI commands, and their differences from combos.
  • Tests
    • Added comprehensive coverage for profile validation, evaluation, aliases, revisions, and management API behavior.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Wibias, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1c0fe84a-6aab-497d-93b4-00717324abeb

📥 Commits

Reviewing files that changed from the base of the PR and between 6392449 and d313d2b.

📒 Files selected for processing (8)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • src/cli/route-policy.ts
  • src/routing/evaluator.ts
  • src/routing/profile.ts
  • src/routing/trace.ts
  • src/server/management/routing-profile-routes.ts
  • tests/routing-profile.test.ts
📝 Walkthrough

Walkthrough

Changes

Routing policy profiles

Layer / File(s) Summary
Profile contracts and normalization
src/types.ts, src/routing/profile.ts, src/config.ts
Adds routing-profile configuration types, validation, alias resolution, normalization, defaults, and deterministic revisions.
Evidence evaluation and decision traces
src/routing/evaluator.ts, src/routing/trace.ts, tests/routing-profile.test.ts
Evaluates requirements and unknown evidence, scores eligible candidates, selects a candidate, and records decision traces.
Management API and CLI integration
src/server/management/..., src/server/management-api.ts, src/cli/..., tests/routing-profile.test.ts
Adds profile listing and dry-run endpoints and adds ocx route policy commands with validation and output handling.
Documentation and acceptance records
docs-site/src/content/docs/reference/configuration/routing.md, devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
Documents routing profiles, policy commands, and combo differences. Records RI-03 and RI-04 programme status and acceptance results.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RoutePolicyCLI
  participant ManagementAPI
  participant RoutingProfileRoutes
  participant PolicyEvaluator
  RoutePolicyCLI->>ManagementAPI: Submit policy dry-run
  ManagementAPI->>RoutingProfileRoutes: Validate profile and evidence
  RoutingProfileRoutes->>PolicyEvaluator: Evaluate candidates
  PolicyEvaluator-->>RoutingProfileRoutes: Return selection and decision trace
  RoutingProfileRoutes-->>RoutePolicyCLI: Return dry-run result
Loading

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding validated routing policy profiles.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@Wibias
Wibias force-pushed the feat/ri-04-policy-profile-core branch from 00e1c4a to 6392449 Compare August 5, 2026 00:04
@Wibias
Wibias marked this pull request as ready for review August 5, 2026 00:11

@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

Here are some automated review suggestions for this pull request.

Reviewed commit: 63924495e7

ℹ️ 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 src/routing/evaluator.ts
Comment thread src/routing/evaluator.ts Outdated
Comment thread src/routing/profile.ts
Comment thread src/routing/profile.ts

@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: 25

🤖 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 13-14: Synchronize the RI-03 and RI-04 entries across the stack
table and acceptance log: update every related SHA, PR number, and status field
so merged/open/pending states and RI-04’s base SHA agree with the recorded stack
history, including the sections around the acceptance entries and lines 148–160.
If historical values must remain, label them explicitly as historical rather
than presenting them as current.

In `@docs-site/src/content/docs/reference/configuration/routing.md`:
- Around line 88-100: Update the routing policy profiles documentation to state
that policy IDs and aliases are virtual model identifiers and do not rewrite
explicit provider-qualified model IDs, combo resolution, account namespaces,
default-provider resolution, credential routing, account pools, cooldowns, or
session affinity. Clarify that every candidate is an explicitly configured {
provider, model } pair.
- Around line 100-105: Expand the routing configuration documentation around the
candidates definition to state that provider and model are separate fields, with
model preserving the complete configured native ID including any “/” characters.
Document that candidate evaluation uses the selected provider’s adapter,
authentication mode, model metadata, and reasoning-capability constraints, and
clarify that dry-run only evaluates and exposes the decision without bypassing
adapter validation or transforming upstream requests.
- Line 14: Update the model-resolution order in the routing documentation to
include the policy-profile resolver at its actual precedence position. Document
canonical-ID-first resolution and note that both policy/fast and its ocx/fast
alias are valid identifiers, covering the corresponding resolution-order section
and repeated configuration example.
- Around line 88-91: Update the routing policy documentation around the profile
activation and route-decision trace descriptions to distinguish current RI-04
behavior from future RI-05–RI-08 work. State that production requests do not
currently route through profiles, profile decisions are exposed through dry-run
APIs only, and requested policy IDs do not yet activate production routing.
- Line 86: Update the ja, ko, ru, and zh-cn routing documentation pages to match
the English routing.md coverage, adding equivalent translated sections for
config.routingProfiles, policy/<id>, candidate allowlists, and ocx route policy
dry-run while preserving each locale’s existing formatting and terminology.

In `@src/cli/route-policy.ts`:
- Around line 81-89: Update the destructuring in handleRoutePolicyCommand to
default sub to "list" when argv is empty, matching handleComboCommand behavior.
Preserve the existing list, show, dry-run, and unknown-subcommand dispatch
logic.
- Around line 51-79: Update dryRun to accept a candidate-evidence input option,
parse it, and forward the resulting candidates array in the runtimeRequest
payload so requirements can be evaluated against capabilities. Add the option to
USAGE and validate malformed input consistently with other CLI arguments.
Replace the non-JSON raw result dump with a concise human-readable
eligibility/selection summary while preserving the complete result for --json.
Ensure the candidate evidence can represent false-valued capabilities needed by
negative requirements.

In `@src/routing/evaluator.ts`:
- Line 223: Move requirements from the trace-level construction around
candidates.flatMap into per-candidate RouteCandidateTrace and
TraceCandidateInput data, preserving candidate ownership. Apply the existing
per-candidate cap pattern used by MAX_EXCLUSIONS_PER_CANDIDATE, including a
budget.truncation flag when requirements are truncated, and remove the
cross-candidate slice(0, 16) behavior.
- Around line 67-82: Document the boolean requirement semantics in
booleanRequirement and OcxRoutingProfileRequirements: required false is a
negative assertion that rejects candidates reporting true, while omitting the
key means “don’t care.” Update the routing configuration page in docs-site to
state the same behavior consistently.
- Around line 219-221: Update the requestedModel field in
buildRouteDecisionTrace to use the shared policyModelId helper with profile.id
instead of the inline template and caller-supplied profileId. Preserve
consistency with profile.revision and the returned profileId; if requestedModel
represents the client-facing request, use policyPublicModelId so aliases are
retained.
- Around line 159-217: Update evaluatePolicyProfile to incorporate
requestEvidence when deriving each candidate’s effective requirements: raise
minContextWindow to at least requestEvidence.contextWindow and enforce the
request’s toolsRequired, imageRequired, and structuredOutputRequired flags
alongside profile requirements. Use these effective requirements for
unsatisfied/unknown checks and add a focused regression test varying only
requestEvidence to verify eligibility changes, without including request-derived
values in profileRevision.

In `@src/routing/profile.ts`:
- Around line 401-403: Update listRoutingProfileIds to replace localeCompare
with an explicit deterministic code-unit comparison, ordering IDs by their
character code values without locale-dependent collation. Preserve the existing
key extraction and sorted string-array behavior.
- Around line 363-381: Update normalizeRoutingProfile to fall back to
DEFAULT_PROFILE_WEIGHTS whenever the merged optimize weight sum is not positive,
then normalize those fallback weights so the result always sums to 1. Also
update routingProfileIssues to reject an optimize block whose weights are all
zero, while preserving acceptance of valid non-negative weight configurations.

In `@src/routing/trace.ts`:
- Around line 458-462: Update the serviceTier handling in the trace
normalization logic so it sets caps.strings = true whenever a non-unknown
serviceTier exceeds MAX_TRACE_STRING and is truncated. Preserve the existing
"unknown" behavior and normal assignment for values within the limit.
- Line 219: Update buildCandidate so input.score is normalized through the same
bounding and validation logic used by parseCandidate via parseScore. Extract the
shared score-normalization logic into a reusable helper if needed, then use that
helper in both paths to preserve bounded components and reject or safely handle
non-finite totals.
- Line 49: Update the serviceTier type and related routing logic to represent
missing evidence by omitting serviceTier rather than using the string "unknown".
In parseCapability, preserve any non-empty raw tier string—including
"unknown"—and leave serviceTier unset when evidence is missing; update
requirementFor and profile validation as needed so legitimate tiers or
requirements named "unknown" remain satisfiable.

In `@src/server/management/routing-profile-routes.ts`:
- Around line 31-44: Update parseEvidence to treat an absent or undefined raw
value as valid empty evidence, returning an empty PolicyRequestEvidence with ok:
true. Preserve ok: false for non-object malformed evidence so the route
continues rejecting values such as strings, while keeping the existing field
validation unchanged.
- Around line 58-63: Correct the comment above the capability, health, quota,
and cost mappings to state that these caller-supplied plain objects are echoed
without trace-normalizer validation; do not claim they are re-bounded. Keep the
existing isPlainRecord checks and structural casts unchanged.
- Around line 72-77: Update both success responses in the routing-profile
handlers: in src/server/management/routing-profile-routes.ts lines 72-77, pass
req and config to jsonResponse for the profiles response; in lines 106-107, pass
req and config to jsonResponse for result. Preserve the existing status code and
response payloads.

In `@tests/routing-profile.test.ts`:
- Around line 120-124: Update the collision test around routingProfileIssues so
it uses the bare alias "free" with the existing baseConfig combo, and assert the
resulting issue message contains "combo selector" to cover the resolveComboId
collision branch. Keep a separate test for the "combo/free" alias if the
reserved-prefix branch also needs coverage, asserting "reserved" there.
- Around line 246-248: Extend the list response type and assertion in the
routing-profile list test around listBody and the profiles[0] expectation to
include the model field. Assert that model equals the configured public alias,
ocx/fast, so the API contract verifies alias exposure rather than only id and
revision.
- Around line 93-110: Add a regression case to the existing “weights default and
normalize deterministically” test covering a routing profile whose optimize
block sets latency, health, cost, and quota to zero. Assert that the normalized
optimize weights satisfy the same sum-to-one invariant, alongside the existing
weight assertions, using getRoutingProfile and baseConfig.
- Around line 225-238: Rename the existing test to describe that it verifies the
highest-scoring candidate wins, since configuredPriority produces different
scores. Do not label it as a tie-break test; adding a genuine equal-score case
is optional and should only use an existing repeatable score component or
directly exercise the selection comparison in evaluatePolicyProfile.
- Around line 201-207: Preserve the literal value types of unknownEvidence in
the dry-run evaluator test by applying a const assertion or the appropriate
OcxRoutingProfileUnknownEvidence annotation. Update the TypeScript configuration
or typecheck setup so tests/routing-profile.test.ts is included in typechecking,
while retaining the existing test 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: 41f68c1e-efc1-4cc1-a7c5-808a6e52260c

📥 Commits

Reviewing files that changed from the base of the PR and between a594938 and 6392449.

📒 Files selected for processing (12)
  • devlog/_plan/260804_router_intelligence/001_pr_stack_status.md
  • docs-site/src/content/docs/reference/configuration/routing.md
  • src/cli/index.ts
  • src/cli/route-policy.ts
  • src/config.ts
  • src/routing/evaluator.ts
  • src/routing/profile.ts
  • src/routing/trace.ts
  • src/server/management-api.ts
  • src/server/management/routing-profile-routes.ts
  • src/types.ts
  • tests/routing-profile.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 docs-site/src/content/docs/reference/configuration/routing.md
Comment thread docs-site/src/content/docs/reference/configuration/routing.md Outdated
Comment thread docs-site/src/content/docs/reference/configuration/routing.md
Comment thread tests/routing-profile.test.ts
Comment thread tests/routing-profile.test.ts
Comment thread tests/routing-profile.test.ts
Comment thread tests/routing-profile.test.ts Outdated
Comment thread tests/routing-profile.test.ts Outdated
@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Addressed feedback

feedbacks:

  • review_comment:3717073495
  • review_comment:3717073496
  • review_comment:3717073497
  • review_comment:3717073499
  • review_comment:3717084130
  • review_comment:3717084133
  • review_comment:3717084139
  • review_comment:3717084141
  • review_comment:3717084150
  • review_comment:3717084154
  • review_comment:3717084173
  • review_comment:3717084193
  • review_comment:3717084197
  • review_comment:3717084200
  • review_comment:3717084206
  • review_comment:3717084221
  • review_comment:3717084234
  • review_comment:3717084244
  • review_comment:3717084247
  • review_comment:3717084250
  • review_comment:3717084260
  • review_comment:3717084267
  • review_comment:3717084270

commit: dd10c9a

@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Addressed feedback

feedbacks:

  • review_comment:3717119108

commit: d313d2b

@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Verdict: approve-comment

TLDR

  • PR: feat(routing): add validated routing policy profiles #1011 — feat(routing): add validated routing policy profiles
  • Head: d313d2b4 on dev (mergeStateStatus: CLEAN)
  • Decision: useful and ready — approve-comment
  • Usefulness: delivers the RI-04 policy-profile core (validated routingProfiles schema, normalization + revision digest, collision validation, deterministic dry-run evaluator, management API, CLI, docs); inert by design until RI-05 wires execution.
  • Bugs: none blocking — 2 medium findings fixed in this run (request-evidence now evaluated; <provider>/<model>-namespace aliases rejected) plus review-round hardening: cost-limit enforcement, all-zero weights rejected, reserved "unknown" service tier rejected, deterministic id ordering, trace truncation flag, absent-evidence handling, CLI subcommand error.
  • Security: none confirmed — routes sit behind the management auth boundary; dry-run never dispatches upstream requests; traces stay bounded; privacy:scan green.
  • Spec / standards: clean — PR claims verified (16 profile tests); combos-module discipline followed; docs now state the dry-run-only scope; stack ledger synced.
  • Reviews: CodeRabbit (2 rounds) + Codex connector fully triaged: 23 fixed/documented, 4 declined with rationale, 2 withdrawn by CodeRabbit; 8 bot threads resolved.
  • Base / CI: green on d313d2b4 (full matrix incl. macOS/Windows; test 4/4 timing flake rerun green); branch rebased onto dev@a594938c5.
  • Owner actions (foreign PR): none — own PR
  • Gate: ready (no draft/WIP, threads clear, CODEOWNERS advisory).
  • Bottom line: ship — merging.
Full verdict

Semantic propagation

  • Concepts audited: routing-profile config schema; policy/<id> namespace + alias resolution; alias collision family (providers, combos, account namespaces, native families, sibling aliases, reserved namespaces); revision digest; unknownEvidence semantics; trace contract (score, serviceTier); management API + CLI surfaces.
  • Authoritative sources: src/types.ts (OcxRoutingProfileConfig), src/routing/profile.ts, src/routing/trace.ts (RouteDecisionTraceV1).
  • Producers and consumers checked: config refine wiring (src/config.ts), evaluator, routes, CLI, trace normalizer, analytics (no trace-score consumer yet).
  • Public/derived representations checked: API DTO, CLI output, docs table, revision digest (canonical-JSON + SHA-256).
  • Material variant partitions checked: capability requirements (all 9 fields), unknown modes allow/penalize/exclude, request evidence fields, provider/disabled/duplicate candidates, alias collision partitions (bare provider, provider namespace, combo id + alias, account namespace, native family, sibling, reserved).
  • Positive and negative assertions checked: 16 tests incl. negative cases (unknown profile 404, invalid evidence 400, reserved tier, all-zero weights, provider-namespace alias, cost-limit).
  • Unmapped surfaces: none — CLI commands are exercised via API tests (thin wrapper, combo-pattern parity).
  • Unproven equivalence assumptions: none.
  • Representation mismatches: none.
  • Variant coverage gaps: none blocking (CLI command-level tests remain a residual gap).
  • Axis verdict: pass
    Linked: none

Usefulness

RI-04 is the configuration/evaluation foundation for the Router Intelligence programme: a validated, fail-closed routingProfiles schema; deterministic normalization with a formatting-insensitive revision digest; alias collision validation across providers/combos/account namespaces/native families; a pure dry-run evaluator that combines profile require with request evidence and enforces maxEstimatedCostUsd; management API (GET /api/routing-profiles, POST .../dry-run); CLI (ocx route policy list|show|dry-run); and reference docs. No production request is routed through profiles yet (RI-05), which keeps the blast radius zero.

Bugs / correctness

  • Method: bug-review.md — Bugbot: n/a (Codex host, no Cursor Bugbot); static: typecheck + focused suites; complementary lenses: done (silent_failures/resource_leaks/edge_cases/error_propagation/parsing_serialization/api_compatibility/concurrency).
  • Findings: B1 (MEDIUM, request evidence inert) — fixed in d478b393/27511bf7; B2 (MEDIUM, provider-namespace alias shadowing) — fixed in 8e1f1c3d; review-round hardening in ea19ab17 (cost limit, all-zero weights, trace truncation flag, absent-evidence, deterministic ordering, CLI error) and d313d2b4 (reserved "unknown" service tier).
  • Fixed this session: d478b393, 8e1f1c3d, aa9212fa, 27511bf7, ea19ab17, dd10c9aa, d313d2b4 (plus the rebase 63924495e).
  • Residual LOW: no-eligible trace names candidate 0 as selected (reason field disambiguates; RI-09 explainability); API evidence fields are permissively dropped.

Security

  • Scope reviewed: authn/authz (management-auth boundary at server level), injection (pattern-constrained ids, JSON-only), SSRF (no outbound), secrets (no credential touch; privacy scan), crypto (SHA-256 digest only), logging/privacy (bounded traces, no PII), business logic (deterministic pure evaluation, fail-closed config), supply chain (no dep changes), removed controls (none).
  • Findings: none confirmed.
  • Fixed this session: n/a.
  • Residual: alias validation gap closed before execution wiring; CLI cannot yet supply candidate capability evidence (documented).

Spec / standards

  • Spec source: PR body + devlog master plan (devlog/_plan/260804_router_intelligence/000_master_plan.md).
  • Gaps: none — all claimed scope present (schema, validation, digest, collisions, evaluator, API, CLI, docs, 16 tests); PR body updated post-resync (Dependency/verification/review round).
  • Standards: repo conventions followed (combos-module discipline, config refine wiring, management-route pattern, CLI runtime-api pattern); typecheck/tests/privacy green; docs sync additive (locale parity tracked in RI-10).

Reviews

  • Owners/maintainers: none open.
  • Bots: CodeRabbit rounds 1+2 + chatgpt-codex-connector — 23 items fixed/documented, 4 declined with rationale (locale deferral to RI-10, score-bound byte-budget backstop, TS autocomplete style, tests-in-typecheck n/a), 2 withdrawn by CodeRabbit; 8 threads resolved; [GD] Addressed feedback records posted for dd10c9aa and d313d2b4.

Base / CI

  • Behind/conflicts: clean — rebased onto dev@a594938c5, single PR delta, MERGEABLE.
  • Required checks: green on d313d2b4 (test 4/4 flake rerun verified green; all jobs incl. macOS/Windows pass).
  • Local tip compile/tests: bun x tsc --noEmit PASSED; tests/routing-profile.test.ts 16/16; regression batch 288+ pass (config symlink EPERM failures reproduce on base); privacy:scan passed.

Simplification

  • Approved and applied: S1 (remove dead routingProfileIssuesForConfig export), S2 (drop redundant printData args in CLI), S3 (compute configured-priority score once). Rollback: none needed. Validation: typecheck + full focused suites + privacy scan green on the post-simplification head d313d2b4; complete full review re-run on that head with simplification disabled.

Gate

none — draft cleared during review; ship-gate ready on d313d2b4; 180s settle completed on unchanged heads (5/5 polls).

Bottom line

Useful, well-scoped RI-04 core with all review findings fixed or explicitly documented. Merging.

@Wibias

Wibias commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

[GD] Merge ready

PR: #1011 — feat(routing): add validated routing policy profiles
Head: d313d2b4dev (mergeStateStatus: CLEAN)
Linked issues: none

Reviews

  • Humans (owners first): none open
  • Bots: 29 threads fully triaged — 23 fixed/documented, 4 declined with rationale, 2 withdrawn by CodeRabbit; 8 remaining threads resolved; [GD] Addressed feedback records posted
  • Own bug + security + spec/standards: bug-review (Bugbot n/a on Codex; complementary lenses done) + security-review (pass, no confirmed findings) + spec/standards (clean) on tip

Tip freshness

  • Updated from dev: yes (rebased onto dev@a594938c5)
  • Compiles/tests against tip: bun x tsc --noEmit PASSED; profile suite 16/16; regression batch green; privacy:scan passed
  • Conflicts: none

Checks

  • Required CI: green on d313d2b4 (full matrix incl. macOS/Windows; test 4/4 timing flake rerun verified green)
  • Policy: CODEOWNERS advisory only; reviewDecision clear; no merge queue

Why it helps: this is the RI-04 foundation of the routing control plane — a validated, fail-closed routingProfiles config schema with deterministic normalization and revision digests, alias collision validation, a pure dry-run evaluator (profile requirements + request evidence + cost limits), management API, CLI, and reference docs. Existing routing is byte-for-byte unchanged; profiles stay inert until RI-05 wires execution.

Ready to merge.

@Wibias
Wibias merged commit 68d0b53 into lidge-jun:dev Aug 5, 2026
37 of 39 checks passed
@Wibias
Wibias deleted the feat/ri-04-policy-profile-core branch August 5, 2026 01:23
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.

1 participant