Skip to content

Route Direct knowledge by per-repo data and a per-request knowledge view - #203

Merged
tzhouam merged 2 commits into
mainfrom
kb/direct-routing-multirepo
Sep 28, 2026
Merged

tzhouam merged 2 commits into
mainfrom
kb/direct-routing-multirepo

Conversation

@tzhouam

@tzhouam tzhouam commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

First PR of the knowledge-base redesign (Copilot owns the knowledge base; quality-gated auto-merge; release sweep). This one makes Direct routing repo-neutral and makes knowledge reads follow the active snapshot.

What changes

  • Routing is data, not code. The vllm-omni owner table moves to knowledge/repos/vllm-omni/_routes.yaml. Repo aliases come from each adapter's repo.full_name/repo.aliases. direct_routing.py no longer names any repository.
  • One routing path for every repo. A repo with a non-empty _routes.yaml gets owner and model routing. Otherwise, a repo with an adapter gets changed-file routing. Anything else is unsupported. repo is now required.
  • KnowledgeView resolves per request. Unset KNOWLEDGE_ROOT means the packaged tree, as today. When set, the path is resolved once per request. A snapshot with MANIFEST.json is verified when loaded and on every read, and a tampered, missing or unlisted file fails closed.
  • SDK DirectClient pins the snapshot each plan was issued from.
    • Completion is validated against that pinned tree, recomputed without the digest cache, so edits made after planning are caught.
    • read_document(..., review_context_id=...) reads from the pinned tree.
    • diagnostics.knowledge_snapshot reports which snapshot was used.
  • MCP document reads and searches are checked against the manifest.

Test Plan

  • test/test_knowledge_view_routing.py:
    • golden routing output from the old router for 150 merged vllm-omni PRs, plus adapter-only and unsupported repos;
    • a second repo routed through its own _routes.yaml;
    • an atomic snapshot switch taking effect on the next request;
    • tampering and unlisted-file rejection;
    • the SDK pinning plans, reads and completion;
    • completion catching changes after planning;
    • a routes file deleted from a loaded snapshot failing closed.
  • Updated the ratchets in test_repo_vocabulary.py / test_v2_p0.py: direct_routing.py leak ceilings go from 24 + 2 + 52 to 0.
  • Full offline suite, both knowledge validators, check_spec_freshness, check_doc_links.

Test Result

  • Full suite: all passed (PYTHONPATH=src python -m pytest -q).
  • check_knowledge_tree.py: 0 errors. check_wiki_lint.py: 0 errors, 0 reminders.
  • check_spec_freshness: 83/83 verified, 0 uncovered. check_doc_links: OK.
  • Local review gate (gpt-6-astra-high): approved after fixes for pinned reads, MCP verification, uncached revalidation and a missing routes file in a snapshot.

🤖 Generated with Claude Code

Direct routing named vllm-omni in code: the owner table, repo aliases, the
default repo, the model directory, and a `!= "vllm-omni"` branch that sent
every other repository down a different path. The knowledge root was also
captured at import, so an activated knowledge snapshot would keep serving the
old tree until the process restarted.

- Move the owner table to knowledge/repos/vllm-omni/_routes.yaml (owners and
  models); aliases now come from each adapter's repo.full_name/aliases.
- Pick the routing path by data: a repo with a non-empty _routes.yaml uses
  owner/model routing, else adapter changed-file routing, else unsupported.
  `repo` is required; path-like names are unsupported, not an escape.
- Add KnowledgeView: KNOWLEDGE_ROOT resolves once per request; a snapshot with
  MANIFEST.json is verified on load and per read (fail closed on tampering).
- DirectClient pins one view per plan and validates completion against the
  pinned tree (recomputed without the digest cache, so a file changed or
  deleted after planning still fails completion), so activating a snapshot
  mid-review does not reject it; plans
  report diagnostics.knowledge_snapshot. read_document() takes an optional
  review_context_id and then reads (every page) from that plan's snapshot.
- The MCP document reader verifies every read and search against the snapshot
  manifest (KnowledgeDocs gains an optional per-file verify callback).

A golden file records the old router's output for 150 merged vllm-omni PRs plus
adapter-only and unsupported repos; the new router reproduces it exactly. The
repo-neutrality ratchets drop direct_routing.py from 24 + 2 + 52 to zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T10:14:05.573903Z 7c877a2 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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

https://github.com/JiusiServe/InferMatrixCopilot/blob/7c877a2cb3009a5835d85ae5b90e2814690ac783/src/infermatrix_copilot/thin_mcp_server.py#L170-L171
P1 Badge Restore alias lookup in the Strict URL path

In the Strict MCP PR-URL path, whenever resolve_repo_alias returns None—including a default installation without repo_full_names or repo_paths, and any unsupported URL—this fallback evaluates _REPO_ALIASES, which this commit removed from the imports and from direct_routing.py. The request therefore raises an uncaught NameError instead of resolving a built-in adapter alias or returning the intended configuration error.

ℹ️ 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 on lines +84 to +85
@lru_cache(maxsize=64)
def _load_routes(view: KnowledgeView, repo: str) -> dict | None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid caching routes for mutable knowledge views

When KNOWLEDGE_ROOT points to the supported plain development tree, its KnowledgeView remains equal across requests, so this cache permanently retains the first parsed _routes.yaml; editing or deleting that file does not affect subsequent requests until a process restart or manual cache clear. The same cache also prevents a previously loaded manifest-backed route file from being rechecked after corruption, undermining the per-read fail-closed behavior.

Useful? React with 👍 / 👎.

Comment on lines 294 to +296
alias, changed_files = self._request_values(request)
expected_head = request.expected_head_sha.strip().casefold()
view = self._view()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve the knowledge view before request validation

During DirectClient.plan, _request_values calls self.capabilities(), which resolves and hashes the currently active knowledge view, and only afterward does this code resolve another view for routing. If the activation symlink is swapped between those operations, repository support is validated against one snapshot while the plan is built from another, causing a newly supported repo to be rejected or a removed repo to receive an unsupported plan rather than preserving the advertised one-view-per-request invariant.

Useful? React with 👍 / 👎.

raise ValueError(f"{relative}: owners[{index}] needs a unique owner")
if not isinstance(signals, list) or not isinstance(prefixes, list):
raise ValueError(f"{relative}: owners[{index}] signals/scope_prefixes must be lists")
view.path(path) # fail closed on a route to a missing page

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict owner routes to their repository slice

A repository's _routes.yaml can currently name any existing file in the knowledge tree, so, for example, repos/demo-repo/_routes.yaml can point an owner at repos/vllm-omni/... and Direct will serve another repository's rules. Validate that each owner path remains under repos/<repo>/ so a configuration mistake cannot cross owner/repository boundaries.

AGENTS.md reference: AGENTS.md:L12-L17

Useful? React with 👍 / 👎.

Model routes were sorted by name length only, so models with equal-length
names (lingbot-world, minicpm-o-4-5, lingbot-video) kept filesystem order. When
the three-route cap cut between them, two machines routed the same PR
differently: the golden test passed locally and failed in CI for PRs 8175 and
7892. Break ties by name; the golden entry for 7892 records the new
deterministic order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant