Repository navigation
bug(analytics): the frontend call scanner reads JSDoc examples as live calls — 3 of 4 'Potential Bugs' are documentation #17668
Description
Child of #12745. That issue's primary cause — the backend scan returning 0 routes and flooding the panel with 2400 findings — is evidently addressed: the panel now reports 4. This is a second, independent cause that survives it, and it is now the dominant one by proportion.
The finding
On the live panel, "Missing Endpoints (4) — Potential Bugs":
| # | reported | reality | verdict |
|---|---|---|---|
| 1 | GET /api/export @ useFileDownload.ts:11 |
inside the /** … */ opening at line 6, closing at 17 — a Usage: example |
false |
| 2 | GET /api/export @ useFileDownload.ts:16 |
same block, Or inline: example |
false |
| 3 | GET /api/users @ apiErrorHandler.ts:222 |
inside the JSDoc ```typescript fence opening at 212 |
false |
| 4 | POST /api/themes @ ThemeManagerView.vue:35 |
real call, await apiClient.post('/api/themes', form), and no backend route matches |
true |
3 of 4 false, on a panel labelled "Potential Bugs".
Mechanism
api_endpoint_scanner.py:1030-1032, per line:
# Skip comments
stripped = line.strip()
if stripped.startswith("//") or stripped.startswith("/*"):
continueThe filter knows two spellings of "this line is a comment" and the class has at least three:
- Block-comment continuation —
* const response = await ApiClient.get('/api/export')strips to* const …, which starts with neither//nor/*. This is where JSDoc examples live, and it is all three false positives above. - Block interior without a leading
*— any line inside/* … */that does not begin with a star. - Trailing comment —
doThing() // await apiClient.get('/api/legacy')does not start with//, so the commented-out call is scanned as live.
A per-line prefix test cannot answer "is this position inside a comment"; that needs block state carried across lines.
Why this is worse than an empty panel
An empty panel gets investigated. A panel that is 75% false on its own label gets acted on — the three false findings cost investigation time, and the one real finding is discounted along with them. POST /api/themes is a theme upload that can only 404, and it is currently indistinguishable from noise.
Proposed fix
Blank comments out of the content before scanning, preserving line and column structure so reported positions stay correct — comment characters become spaces rather than being deleted. It needs string-literal awareness, or 'https://…' would be read as a line comment and truncate the rest of a genuine call.
Acceptance criteria
- A call appearing only inside a
/* … */block, including a*continuation line, is not reported - A call after a
//on a line whose code precedes it is not reported - A URL containing
//inside a string literal does not truncate scanning of that line -
POST /api/themesatThemeManagerView.vue:35is still reported — the fix must not silence the true positive - Tests cover all four forms, mutation-proved: reverting the comment handling fails a named test
- The three known-false findings above are gone from the panel, verified against the live instance
Related
- codebase-analytics: 'Missing Endpoints' ~97% false positives — backend scan finds 0 routes, findings lack file/method #12745 — parent; the backend-scan cause, and its AC3 ("exclude test/docstring/example sources") which this makes concrete
- bug(analytics): 13+ codebase-analytics panels render empty, and two of them cannot report a failure at all #17651 — the mirror failure on a sibling panel: every row filtered out by a missing
source_id, so that surface shows nothing real while this one shows mostly noise. Unrelated causes, same net effect on trust.
Activity
test(analytics): settle the fourth finding with the scanner, not a pr…
test(reach): re-pin the one-claim-registry floor to its live populati…
fix(analytics): verify through the production scanner, and treat ${} …
fix(analytics): count interpolation braces in code only (#17668)
fix(analytics): the call scanner read JSDoc examples as live calls — …
mrveiss commentedon Sep 28, 2026
Closure evidence, verified against merged
mainThis issue auto-closed on #17670's merge with no evidence posted. A merge is not a closure, so each criterion is checked against merged code.
origin/main/* … */, including a*continuation line, is not reportedcomment_blanking.pycarries_consume_until/_consume_line_comment/_HTML_OPEN/_matching_brace(11 references); block state is carried across lines rather than tested per-line//following code is not reported//inside a string does not truncate scanning_consume_stringcopies literals verbatim; asserted bytest_a_url_containing_a_double_slash_does_not_start_a_commentPOST /api/themesatThemeManagerView.vue:35is still reportedfrontend_call_scanner_comments_test.py::test_the_one_real_finding_is_named_and_keptassertsafter.get(35) == "/api/themes"through_scan_filecomment_blanking_test.py+ 3 infrontend_call_scanner_comments_test.py; mutations recorded in the PR body (identity → 6 fail, delete-not-blank → 5, no string awareness → 1, no block state → 4, code-blanked-too → 2)api_endpoint_scanner.pypinned at 1444, down from 1445 — the helper went to its own module rather than growing the scannerOne criterion I cannot tick, and it should not be ticked by someone else without doing it:
I verified the scanner no longer reports them — before/after finding sets through
_scan_file, which is the mechanism behind the panel. I did not re-open the panel on the live deployment and confirm the rendered output. Those are different claims: the second also depends on cache state and on the panel's own query path, neither of which this PR touched.What the work found beyond the stated scope
The panel was wrong in both directions. Running the real scanner to settle the fourth finding surfaced
DELETE /api/themes/${id}atThemeManagerView.vue:49— a second genuine call, on the same missing route, that the panel never reported. So the surface was over-reporting documentation and under-reporting real calls simultaneously. "Make the findings precise" is therefore not the whole remedy; the same panel is also missing things, and that half is not addressed here.Three defects were found inside the fix itself, each one level further in, and all by review rather than by a tool: a verification using a private regex instead of the scanner's own patterns; a test that reimplemented the scan loop and so would have passed with production blanking removed; and
_matching_bracecounting raw braces, so a}inside a comment or string ended an interpolation early and leaked its contents. Recorded because a change whose subject is detectors that see less than they claim cannot quietly contain three of them.