Skip to content

fix(analytics): locate the backend under the scan root instead of assuming its depth (#12853) - #12943

Merged
mrveiss merged 1 commit into
Dev_new_guifrom
issue-12853
Jul 29, 2026
Merged

mrveiss merged 1 commit into
Dev_new_guifrom
issue-12853

Conversation

@mrveiss

@mrveiss mrveiss commented Jul 29, 2026 •

Copy link
Copy Markdown
Owner

Closes #12944. Refs #12853 — which stays open for the remaining coverage gap and live per-source validation (see "What remains").

Thinking Path

#12853 attributes the 0-route scan to resolve_project_root() returning the deployed tree rather than the analyzed source, and proposes wiring the scan to the source's indexed tree. I checked that premise first, and the wiring already exists: resolve_source_root(source_id) returns source.clone_path, _build_analysis_tasks threads it as scan_root, and _get_api_endpoint_analysis(project_root=scan_root) passes it to the scanner (#12372). Handing the scanner a correct root would not have fixed anything.

The actual defect is what the scanner does with the root. It looks for routes at project_root / "api" and for the router registry at project_root / "backend" / "initialization" / "router_registry". Neither exists in this repo — the backend is autobot-backend/:

MISSING  api
MISSING  backend/initialization/router_registry
EXISTS   autobot-backend/api
EXISTS   autobot-backend/initialization/router_registry

Running the unmodified scanner at two roots isolates it — the root is fine, the assumed depth is not:

/…/AutoBot-AI                 backend_path=False  endpoints=0
/…/AutoBot-AI/autobot-backend backend_path=True   endpoints=1986

That is the whole "0 of ~2156 routes" symptom: with an empty endpoint map every frontend call matches nothing, which is what produced the ~2400 "missing endpoints" that were 97% false.

A second defect surfaced while confirming the first. The registry path is built from a different wrong assumption (project_root/"backend"/…), so it resolves nowhere in any layout — even when the route scan works:

registry path tried : /…/autobot-backend/backend/initialization/router_registry
exists              : False
router_prefixes     : 0

So endpoints were being recorded without their router prefixes, meaning even a populated map would mismatch against frontend calls. Fixing the route path alone would have left the report wrong in a subtler way. While fixing it I also found integration_routers.py absent from the hand-maintained config_tuple_files list, so its routers carried no prefix either.

What Changed

api/codebase_analytics/api_endpoint_scanner.py:

  • Added find_backend_dir(project_root), which resolves the backend among autobot-backend/, backend/, and the root itself. It prefers a candidate that also holds initialization/router_registry, so a directory that merely happens to contain api/ cannot win, and falls back to the root unchanged — callers already pointing at the backend are unaffected.
  • backend_path and the router-registry path both derive from that resolved directory.
  • The registry file list is now globbed (*_routers.py) instead of hand-maintained, which picks up integration_routers.py and anything added later.

api_endpoint_scanner_test.py: 7 tests — nested layout, backend-at-root, decoy api/ losing to the registry-bearing candidate, unrecognised-layout fallback, the scanner pointing at the nested backend, the registry resolving under the backend, and every *_routers.py being parsed.

Verification

$ python3 -m pytest api/codebase_analytics/api_endpoint_scanner_test.py -q
11 passed          (4 pre-existing + 7 new)

$ python3 -m pytest api/codebase_analytics/ -q
225 passed, 11 skipped in 4.84s

$ python3 -m flake8 …/api_endpoint_scanner.py …/api_endpoint_scanner_test.py
(clean)

Scanning from the repo root (the case that previously returned nothing), before → after:

before after
endpoints found 0 1986
module prefix map 16 871
paths under /api/ 0 1984

Cross-checked against the authoritative table from app.openapi() (2159 unique normalized paths):

scanned unique            : 1806
scanned IN openapi        : 1736   (80.4% of real routes)
scanned NOT in openapi    : 70
openapi MISSED by scanner : 423

What remains

The issue's acceptance criteria are not fully met, so this does not close it:

  1. 423 real routes still unmatched (~20%). A static AST scan will not reach dynamically-registered or data-driven mounts, but 423 is too many to assume that is the whole story; it needs its own pass with the numbers above as the baseline.
  2. 70 scanned paths that app.openapi() does not expose — prefix reconstruction is still imperfect for some routers.
  3. Live per-source validation (the source_id → indexed-tree case on a real instance, and confirming scan_error stays empty) is untouched here — I verified against this checkout, not a running instance.
  4. The file: "?" / method: UNKNOWN loss noted at the end of bug(analytics): backend endpoint scan resolves /opt/autobot, not the analyzed source — finds 0 of ~2156 routes #12853 is a separate path and not addressed.

This PR fixes the primary defect and makes those remaining numbers measurable rather than hidden behind a zero.

Model Used

claude-opus-5

…uming its depth (#12853)

BackendEndpointScanner read routes from project_root/'api' and the router
registry from project_root/'backend'/'initialization'/'router_registry'. Both
assume a layout that no longer exists: this repo keeps the backend in
autobot-backend/, so the route scan found 0 endpoints and the registry path
matched nothing, leaving every endpoint without its router prefix.

Zero endpoints is what made the report claim thousands of missing endpoints --
with an empty map, every frontend call matches nothing.

find_backend_dir() now locates the backend under the scan root, preferring a
candidate that also carries the router registry so a stray api/ directory
cannot win, and falling back to the root unchanged. The registry is read from
the resolved backend, and every *_routers.py there is parsed rather than a
hand-maintained list that had already missed integration_routers.py.

Measured against the repo root: 0 -> 1986 endpoints, prefix map 16 -> 871,
1736 of 2159 real app.openapi() paths matched (80.4%).
@github-actions

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No hardcoded values detected that have SSOT config equivalents!

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