# What Validation Checks Does verify-routing-coherence.ps1 Perform?

> Discover the three validation checks performed by verify-routing-coherence.ps1: routing coherence, operational contract fields, and supply chain pins to ensure CI pipeline success.

- Repository: [ZhaoXu/reverse-skill](https://github.com/zhaoxuya520/reverse-skill)
- Tags: how-to-guide
- Published: 2026-08-13

---

**`verify-routing-coherence.ps1` performs three main validation categories: routing and benchmark coherence, operational contract field validation, and supply-chain pin enforcement, causing CI pipeline failures when any check does not pass.**

The `verify-routing-coherence.ps1` script in the **reverse-skill** repository (`zhaoxuya520/reverse-skill`) is a critical CI gate that ensures structural integrity, operational compliance, and supply-chain security. Located at `skills/scripts/verify-routing-coherence.ps1`, it validates the project's routing configuration, mandatory documentation fields, and dependency pinning before any code can merge.

## Routing and Benchmark Coherence Checks

The script first validates that the central routing configuration is complete, consistent, and properly linked to runtime and test components.

### File Existence and Route Count

```powershell
if (Test-Path $routingJson) { … }
if ($rjRoutes.Count -ge 30) { Ok … } else { Bad … }   # → Line 28

```

- **At least 30 routes** must be defined in [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json)
- A count below this threshold triggers a `[FAIL]` with the message "routing.json route count suspicious (<30)"

### Required Route Fields

```powershell
if ($badRoute.Count -eq 0) { Ok … } else { Bad … }   # → Line 30

```

Every route object must contain three mandatory fields:
- **label** — the display name
- **skill** — the script path
- **keywords** — matching terms for routing

Missing any of these fields marks the route as invalid.

### Skill Script Verification

Two checks ensure skill scripts are properly managed:

```powershell
if ($missingRouteSkills.Count -eq 0) { Ok … } else { Bad … }   # → Line 34

if ($untrackedRouteSkills.Count -eq 0) { Ok … } else { Bad … } # → Line 40

```

- **Existence check**: All referenced skill scripts must exist on disk
- **Git tracking check**: All skill scripts must be tracked by Git (no untracked files)

### Priority Map Completeness

```powershell
if ($missingPrio.Count -eq 0 -and $extraPrio.Count -eq 0) { Ok … } else { Bad … } # → Line 46

```

The `priority` mapping must cover **every route exactly once** — no missing routes and no extra routes.

### master-route.ps1 Integrity

```powershell
if ($masterRoute -match 'hardcoded routing') { Bad … } else { Ok … }   # → Line 73

```

The script verifies that `skills/scripts/master-route.ps1` does **not** contain a hard-coded routing table. This enforces dynamic generation from [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) instead of static definitions.

### Benchmark Alignment

```powershell
if ($ghostExpect.Count -eq 0) { Ok … } else { Bad … }   # → Line 62

```

The benchmark file at [`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json) must only reference routes that actually exist in [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json). Any "ghost" expectations (routes expected by tests but missing from config) cause failure.

## Operational Contract Field Validation

The script enforces documentation standards across operational markdown files using a reusable `Assert-Fields` function.

### The Assert-Fields Function

```powershell
function Assert-Fields([string]$path, [string[]]$needles) { … }

```

This helper verifies that specified files contain all required section headers or keywords.

### Validated Operational Files

| File | Required Fields |
|------|---------------|
| [`ops/scope-contract.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/ops/scope-contract.md) | `auth`, `in_scope`, `out_of_scope`, `network_profile`, `deliverables` |
| [`ops/evidence-finding-path.md`](https://github.com/zhaoxuya520/reverse-skill/blob/main/ops/evidence-finding-path.md) | `Evidence`, `Finding`, `Path`, `repro_command`, `evidence_ids` |

```powershell
Assert-Fields (Join-Path $skillsRoot 'ops/scope-contract.md') @('auth','in_scope','out_of_scope','network_profile','deliverables')   # → Line 175

Assert-Fields (Join-Path $skillsRoot 'ops/evidence-finding-path.md') @('Evidence','Finding','Path','repro_command','evidence_ids')   # → Line 176

```

Additional operational documents are validated at Lines 177–185, ensuring consistent documentation structure across the project.

## Supply-Chain Pin Gate

The most security-critical validation enforces that all auto-install capabilities specify explicit version or commit references.

### Pin Requirement Logic

```powershell

# --- supply-chain pin gate: auto-install download sources MUST be pinned ---   # → Line 389

$hasPin = ($cap.pinnedVersion -or $cap.pinnedCommit -or $cap.pinPolicy)

```

Every capability must specify **one** of:
- `pinnedVersion` — exact version string
- `pinnedCommit` — specific Git commit hash
- `pinPolicy` — pinning strategy (including special `winget-latest` policy)

### Special Handling for winget

```powershell
case 'winget-package' { $hasPin = $hasPin }   # → Line 405

```

The `winget-package` bootstrap kind accepts `pinPolicy: winget-latest` as valid pinning, acknowledging that Windows Package Manager provides its own version stability.

### Enforcement and Failure

```powershell
if (-not $hasPin) { Bad "unpinned auto-install capability: $($cap.name) in $mn ($($cap.bootstrapKind))" } else { Ok "pinned $($cap.name) in $mn" }   # → Lines 412–414

```

Unpinned capabilities produce `[FAIL]` output like:

```

[FAIL] unpinned auto-install capability: mytool in agents (pip-package)

```

This blocks CI and prevents supply-chain attacks through dependency confusion or unexpected version upgrades.

## Running the Validation

### Local Execution

```powershell

# From repository root

powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/verify-routing-coherence.ps1

```

### CI Integration

```yaml

# .github/workflows/ci.yml

- name: Verify routing coherence
  run: ./skills/scripts/verify-routing-coherence.ps1

```

On failure, the script:
1. Writes `[FAIL] …` lines to stdout
2. Adds messages to an internal `$fail` collection
3. Exits with **non-zero status**, aborting the workflow

## Key Source Files

| File | Purpose |
|------|---------|
| `skills/scripts/verify-routing-coherence.ps1` | Main validation script |
| [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) | Central routing configuration |
| `skills/scripts/master-route.ps1` | Runtime routing generator |
| [`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json) | Test expectations |
| `skills/ops/*.md` | Operational contract documents |

## Summary

- **Routing coherence**: Validates [`routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/routing.json) structure, field completeness, Git tracking, priority coverage, and benchmark alignment while blocking hard-coded tables in `master-route.ps1`
- **Ops contracts**: Enforces required fields in operational markdown via `Assert-Fields`
- **Supply-chain safety**: Mandates explicit pins (`pinnedVersion`, `pinnedCommit`, or `pinPolicy`) for all auto-install capabilities
- **CI gate**: Exits non-zero on any failure, preventing broken configurations from merging

## Frequently Asked Questions

### What happens if routing.json has fewer than 30 routes?

The script outputs `[FAIL] routing.json route count suspicious (<30)` and exits with code 1. This threshold ensures the routing system maintains sufficient coverage for the project's skill library.

### Why does the script check if skill scripts are Git-tracked?

Untracked files indicate potential deployment issues — the script would pass locally but fail in CI where those files don't exist. The Git tracking check at Line 40 catches this discrepancy early.

### Can I use unpinned dependencies in development?

No. The supply-chain pin gate (Lines 389–414) enforces pinning for all bootstrap kinds including `pip-package`, `npm-package`, `go-install`, and `git-clone`. Only `winget-package` accepts `winget-latest` as a valid policy, and even this is an explicit opt-in rather than an unpinned default.

### How do I fix a benchmark ghost expect error?

Add the missing route to [`skills/config/routing.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/config/routing.json) or remove the obsolete expectation from [`skills/tests/routing-benchmark.json`](https://github.com/zhaoxuya520/reverse-skill/blob/main/skills/tests/routing-benchmark.json). The check at Line 62 requires exact alignment between benchmark expectations and actual routing configuration.