# Part A measured — file-routed enumeration by LOCATION (#40 / #36b)

audience: AI coding agents first. Optimize for activation, not prose.

**BLUF: Part A landed and is MEASURED on multideal. STOP gate PASSED.** File-routed kinds
(`http-file-route`, `edge-function`) now enumerate from `FILE_ROUTE_RULES` (filesystem LOCATION),
not from the `KIND_SIGNALS` content regex. Every dropped entry was confirmed a genuine non-route.
No real route lost → no false-coverage → Part B (Tasks 3–6) is unblocked.

## What changed (the ONE thesis: a filesystem fact beats a content-regex guess)

- `mapper.actual_surface` / `mapper.enumerate_surface`: branch by kind. File-routed kinds emit by
  LOCATION (`_file_routed_kind` → `FILE_ROUTE_RULES`); call-registered kinds (`http-defn-call`,
  `webhook-receiver`, `queue-consumer`, `cron-scheduled`, …) still emit by CONTENT (`KIND_SIGNALS`).
- `KIND_SIGNALS` rows for the file-routed kinds are KEPT INTACT — they have TWO jobs and only the
  *enumerator* job moved. The remaining job is the cross-kind DENOMINATOR. The `onRequest` regex is
  retired *as an enumerator* (its false-positives vanish); its ROW stays for the denominator.
- `conventions.py` `FILE_ROUTE_RULES["http-file-route"]` anchor: `("pages","api")` → `("src","pages")`.
  Astro/Next route ALL `.ts`/`.js` under `src/pages/`, not just `src/pages/api/`. Anchored on the
  CONSECUTIVE `src`+`pages` pair so `components/pages/` and `src/foo/pages/` do NOT inflate the
  denominator. Root-layout `pages/` with no `src/` is a deferred best-effort case (spec NOT-covered).

## What `kind_coverage_by_volume` means AFTER this change (verbatim — record per spec)

`kind_coverage_by_volume = enumerated / actual`: the share of detected entry points whose KIND the
mapper enumerates. File-routed kinds (`http-file-route`, `edge-function`) are counted by LOCATION
(`FILE_ROUTE_RULES`) on BOTH sides of the ratio; call-registered kinds by CONTENT signal. Per-rowed-kind
recall is 1.0 BY CONSTRUCTION — the number only exposes KINDS with no row as misses, NOT within-kind
signal lossiness. `within_kind_recall` (file-routed only) is now LOCATION-based and 1.0 by construction;
`retired_signal_recall` is the DIAGNOSTIC showing how lossy the retired content signal was
(content_signal_hits / fs_routes). `canonical_confirmation` stays SECONDARY and gated on the source
repo being checked out — never read a gated value as recall.

## Measurement (multideal, git-driven walk, 2026-06-18)

### http-file-route — location ⊆ content, so it can only stay or DECREASE; every drop inspected

```
BEFORE (content KIND_SIGNALS regex):  383
AFTER  (location FILE_ROUTE_RULES):   382
dropped: 1   added: 0
  - apps/web/src/pages/api/_health.ts
```

**The 1 drop is correct (not false-coverage), verified two ways — not accepted on convention:**
1. Framework = Astro `^6.3.2` (`apps/web/package.json`). Astro EXCLUDES `_`-prefixed files under
   `src/pages/` from routing (documented framework rule) → `_health.ts` is not a live route.
2. `grep -rn _health` across `apps/web` (ts/tsx/js/mjs/json/toml): ZERO import / re-export / rewrite /
   redirect re-exposes `src/pages/api/_health.ts`. Remaining hits are unrelated substring matches
   (`admin_system_health` i18n namespace, `HealthFindingRow`/`HealthBanner` components). Nothing in code
   re-exposes the file → `EXCLUDE_NONROUTE` dropping it is correct, not a coverage hole.

**The pilot STOP gate fired and was honored.** The first anchor `("pages","api")` dropped 7 entries:
6 were REAL Astro routes living directly under `src/pages/` (`pages/r2/[...path].ts`,
`robots.txt.ts`, `sitemap-deals.xml.ts`, `sitemap-entities.xml.ts`, `sitemap-index.xml.ts`,
`sitemap-static.xml.ts`) — forbidden false-coverage. Broadening the anchor to `("src","pages")`
recovered all 6 (dropped 7→1, added 0). Only `_health.ts` remains, correctly excluded.

### edge-function — enumerated by location, content `onRequest` regex retired

```
edge-function enumerated: 2
  * functions/api/subscribe.js
  * functions/api/subscribe.ts
```

Acceptance met: enumerated == 2 (both real CF Pages functions under `functions/`), 0 `onRequest`
false-positives. The retired content regex had MISSED the `export default` idiom (these two files)
and FALSE-POSITIVED on off-location `onRequest` (e.g. `DealCTA.tsx`, `middleware.ts`) — both classes
fixed by switching the enumerator to location. `retired_signal_recall` records that lossiness.

## Tests

`rtk proxy python3 -m pytest tests/` → 15 passed. Includes the 2 Part-A tests:
- `test_edge_function_enumerated_by_location_not_content` — `functions/api/x.ts` (export-default) IN;
  `src/mw.ts` (`onRequest` off-location) NOT.
- `test_file_routed_recall_surfaces_signal_miss_and_prunes_nested_git` — location enumerates the
  export-default route the retired regex missed; `retired_signal_recall==0.5` records the loss.
Fixtures use `src/pages/api/…` → still match `("src","pages")` at segment 0 → no regression.

## Honest scope (NOT-covered, carried to Part B / deferred)

- Root-layout `pages/` with no `src/` (older Next) — best-effort defer, not anchored here (avoiding
  bare `("pages",)`, which would match `components/pages/` anywhere = denominator inflation).
- This is COVERAGE (an enumerator-correctness fact), NOT a recall result. Value chain stays explicit:
  coverage ↑ → oracle/LLM reaches more sinks → catches are the DOWNSTREAM #24 sweep. Never present a
  coverage delta as a recall number.
