scan_frontend_api_calls in roam/workspace/api_scanner.py queries the symbol graph for any edge whose target name is one of {get, post, put, delete, patch, fetch, $fetch, useFetch, useLazyFetch, request, axios} (the _FRONTEND_CALL_NAMES set, line 18). Any method call to a symbol with one of those names is treated as a frontend API call, regardless of whether the receiver is an HTTP client or an HTTP server router/app.
Result: in any repo tagged role: "frontend" that also contains backend route handler code (e.g. polyglot monorepos with both client UI and server route definitions), the route handler definitions get scanned as if they were API calls and produce false-positive cross-repo edges.
Minimal repro (zero external deps, two ~10-line TS files)
fake-frontend/src/server.ts (tagged role: "frontend"):
class Server {
get(path: string, handler: Function) {}
post(path: string, handler: Function) {}
}
const app = new Server();
app.get('/users', () => ({ users: [] }));
app.post('/users', () => ({ created: true }));
app.get('/health', () => ({ ok: true }));
fake-backend/src/server.ts (tagged role: "backend", identical content).
.roam-workspace.json:
{
"workspace": "repro",
"repos": [
{"path": "/abs/fake-frontend", "name": "fake-frontend", "role": "frontend"},
{"path": "/abs/fake-backend", "name": "fake-backend", "role": "backend"}
],
"connections": [
{"type": "rest-api", "frontend": "fake-frontend", "backend": "fake-backend"}
]
}
cd fake-frontend && roam index
cd ../fake-backend && roam index
cd .. && roam ws resolve
Output:
Scanning fake-frontend for API calls... 2 found
Scanning fake-backend for routes... 3 found
Matching endpoints... 2/2 matched
Cross-repo edges: 2 api_call edges stored
Expected: 0 cross-repo edges — the "frontend" file isn't making API calls, it's defining server-side route handlers. The pattern app.get('/path', handler) is the same syntax both client.get('/path') (a fetch call) and app.get('/path', handler) (a route handler) use; nothing downstream of ws resolve can tell them apart from the output. roam-code v11.2.0.
Related: #18 (separate UX bug where connections: [] is silently required — finding that first is what surfaced this one).
scan_frontend_api_callsinroam/workspace/api_scanner.pyqueries the symbol graph for any edge whose target name is one of{get, post, put, delete, patch, fetch, $fetch, useFetch, useLazyFetch, request, axios}(the_FRONTEND_CALL_NAMESset, line 18). Any method call to a symbol with one of those names is treated as a frontend API call, regardless of whether the receiver is an HTTP client or an HTTP server router/app.Result: in any repo tagged
role: "frontend"that also contains backend route handler code (e.g. polyglot monorepos with both client UI and server route definitions), the route handler definitions get scanned as if they were API calls and produce false-positive cross-repo edges.Minimal repro (zero external deps, two ~10-line TS files)
fake-frontend/src/server.ts(taggedrole: "frontend"):fake-backend/src/server.ts(taggedrole: "backend", identical content)..roam-workspace.json:{ "workspace": "repro", "repos": [ {"path": "/abs/fake-frontend", "name": "fake-frontend", "role": "frontend"}, {"path": "/abs/fake-backend", "name": "fake-backend", "role": "backend"} ], "connections": [ {"type": "rest-api", "frontend": "fake-frontend", "backend": "fake-backend"} ] }Output:
Expected: 0 cross-repo edges — the "frontend" file isn't making API calls, it's defining server-side route handlers. The pattern
app.get('/path', handler)is the same syntax bothclient.get('/path')(a fetch call) andapp.get('/path', handler)(a route handler) use; nothing downstream ofws resolvecan tell them apart from the output. roam-code v11.2.0.Related: #18 (separate UX bug where
connections: []is silently required — finding that first is what surfaced this one).