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>
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 theBCQ_INDEX_V2flag) 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:
- 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. - 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. - 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 authoredsignals: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'sdomain, 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 |