bcquality/tools/routing-index.md
dayland 6ed56b95b7 R6 Tier-1: content-owned routing index generator + CI guard
Retire the orchestrator's hardcoded ~28-token signal catalog by compiling a
routing index from article front-matter. New tools/Build-RoutingIndex.ps1 scans
all knowledge layers and emits routing-index.json (signal-token -> domain +
backing articles), seeded from the migrated legacy catalog (routing-seed.json)
so recall is never below today. Optional per-article 'signals:' front-matter
(validator rule R24) is the authored precision path; domain-normalization
reconciles front-matter/orchestrator/feedback domain vocabularies.

Artifact is a runtime build (gitignored), orchestrator-facing only (not the
lean agent-replayed knowledge index). CI guard Test-RoutingIndex.ps1 asserts
determinism, seed recall floor, no orphaned signals, and normalization
completeness; wired into the index workflow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-13 11:20:30 +01:00

6 KiB

Routing index

The routing index (routing-index.json) is the orchestrator-facing companion to the knowledge index. Where the knowledge index lets the agent enumerate candidate articles inside the CLI run, the routing index lets the orchestrator decide — deterministically, before any tokens are spent — which review domains a PR touches and which articles back each detection signal.

It exists to retire a shadow catalog. The PR-review orchestrator historically carried a hand-written ~28-token regex catalog ($BcqSignalCatalog) hardcoded in Invoke-CopilotPRReview.ps1. That catalog never read the domain / keywords front-matter every article already declares, so its blind spots were exactly where findings were missed. The routing index moves that knowledge into content: signals and their domains are compiled from articles, so a new article — even a community one — becomes routable the moment it lands, with no orchestrator edit.

What it is (and is not)

  • It is an orchestrator-side artifact. It is consumed by Build-ReviewManifest (behind the BCQ_INDEX_V2 flag) to score per-domain suspicion and shortlist candidate articles. It is never fed into the CLI prompt, so it can be richer than the lean knowledge index without inflating the token-paid path.
  • It is not committed. Like knowledge-index.json, it is a runtime artifact rebuilt over each consumer's already-pruned clone (tools/Build-RoutingIndex.ps1) and is .gitignored.
  • It is not the knowledge index. The two are siblings built from the same front-matter; the knowledge index is agent-replayed, the routing index is not.

How signals are compiled

Build-RoutingIndex.ps1 composes signals from three sources, highest precision first:

  1. Seed (tools/routing-seed.json) — the migrated legacy catalog. Ingested first so routing recall is never below what the old hardcoded catalog caught. Each seed signal is then enriched with every article whose (normalized) domain matches, so recall is complete-by-construction rather than limited by a hand-maintained token→article map.
  2. Article-declared (signals: front-matter, optional) — the authored, highest-precision path. Use it when an article catches a specific AL construct the seed does not name.
  3. Keyword-derived (-IncludeKeywordSignals, off by default) — soft signals from article keywords at reduced weight. Off by default because keywords are lowercase-kebab and match noisily, and the online-evals feedback shows the agent already over-fires. Prefer authored signals: for precision.

The optional signals: front-matter block

Knowledge articles may declare an optional signals: block. When omitted, the article is still routed via the seed + its domain (fully back-compatible — no existing article must change). Each entry is either a bare token string or a mapping:

domain: performance
keywords: [lock, readonly, isolation]
signals:
  - LockTable                     # bare token -> pattern \bLockTable\b, domain = article domain
  - token: ReadIsolation
    pattern: '\bReadIsolation\b'  # explicit regex (optional)
    domain: performance           # override domain (optional; normalized)
  • token (required) — stable signal id; need not be an AL identifier verbatim.
  • pattern (optional) — regex matched against added diff lines. Defaults to \b<token>\b.
  • domain (optional) — defaults to the article's domain, then normalized.

The front-matter validator (.github/scripts/validate_frontmatter.py, rule R24) enforces this shape; signals is the only optional key in the otherwise-closed knowledge key set.

Domain normalization

Three vocabularies describe the same domains and must be reconciled:

Front-matter (article) Orchestrator ($DomainMap) Feedback (byDomain)
ui Accessibility accessibility
error-handling Error Handling
web-services Web Services
breaking-changes Breaking Changes
events / interfaces Events / Interfaces
telemetry Privacy (folded)

routing-seed.json → domain-normalization maps front-matter domains to the orchestrator's canonical TitleCase taxonomy so seed signals (authored in that taxonomy) attach to the right articles. appsource is a documented pass-through domain (indexed, but has no review leaf skill, so it routes only via the al-code-review super-skill). The CI guard fails if a new front-matter domain appears that is neither normalized nor a pass-through, keeping the map complete as content grows.

Layer-replication story

The whole process is open and per-layer. A partner running the pipeline against their own community/ or custom/ layers gets routing for free: their articles' front-matter (and any signals: they add) compile into the same index by the same generator. No Microsoft-only data is required to build Tier 1. The later Tier 2 feedback overlay (precision weights distilled from online evals) is a separate, aggregate-only artifact that multiplies onto these Tier-1 weights — each layer carries its own overlay produced from its own feedback.

Files

File Role
tools/Build-RoutingIndex.ps1 Generator (scan layers → routing-index.json)
tools/routing-seed.json Content-owned seed: migrated catalog + domain-normalization + object-kind hints
tools/routing-index.schema.json JSON Schema for the compiled artifact
.github/scripts/Test-RoutingIndex.ps1 CI guard (determinism, recall floor, no orphans, normalization complete)
.github/workflows/knowledge-index.yml Runs both index guards on PR/push to main