Skip to content

cross-repo HTTP edges missing when caller URL is a constant #706

Description

@medeirosjoaquim

Version

codebase-memory-mcp 0.8.1

Platform

Linux (x64)

Install channel

GitHub release archive / install.sh / install.ps1

Binary variant

standard

What happened, and what did you expect?

I wanted to cross index 3 different related microservices and it failed to create the edges

Reproduction

Summary

index_repository(mode="cross-repo-intelligence") produces 0 CROSS_HTTP_CALLS edges for a real HTTP integration between two indexed repos. Root cause is on the caller side: the URL extractor only resolves URLs that appear as string literals at the call site. When the caller passes a module-level constant (or any Name / string-concatenation / env-derived value), no url_path is attached to the call, so no HTTP_CALLS edge is created — and the cross-repo matcher then has nothing to link against the callee's Route nodes.

This is a false negative: cross_http_calls: 0 reads as "no integration" when the integration exists.

Observed behavior (anonymized)

  • Callee repo: FastAPI service that defines routes via @app.post("/<path>").
  • Caller repo: Python service that calls those routes via requests.post(...).

The callee's routes are indexed correctly as Route nodes with literal paths. The caller's calls are not captured as HTTP edges, so cross-repo matching yields nothing.

Callee side is fine — Route nodes exist with literal paths

MATCH (r:Route) RETURN r.qualified_name, r.method

Returns the expected __route__POST__/<path> nodes (literal paths preserved).

Caller side — HTTP_CALLS edges only appear for literal-path arguments

MATCH (a)-[e:HTTP_CALLS]->(b) RETURN e.url_path, e.via, e.callee

Every surviving edge has via = "arg_url" and a concrete url_path — i.e. it survived only because the path was passed as a literal string argument at the call site.

Calls with a variable URL are downgraded to plain CALLS with empty url_path

MATCH (a)-[e:CALLS]->(b)
WHERE e.callee = 'requests.post'
RETURN e.callee, e.via, e.url_path, e.strategy

For call sites that pass a constant/variable URL:

callee = requests.post   via = ""   url_path = ""   strategy = "unique_name"

The extractor resolved the callee symbol but extracted no URL.

cross-repo-intelligence result

index_repository(mode="cross-repo-intelligence", target_projects=[...])
=> { cross_http_calls: 0, total_cross_edges: 0 }

Root cause

The caller passes a variable, not a literal — the common pattern of centralizing endpoint URLs:

API_URL = API_BASE_URL + "some/path"     # base often env-derived
...
requests.post(API_URL, json=payload, ...)

The first argument is a Name bound to base_var + "literal". The URL extractor does literal reading only (via=arg_url); it does not do constant folding or interprocedural value resolution for Name → (base_var + "literal"). With no literal in hand it emits a generic CALLS edge and discards the path.

Impact

  • Any service-to-service integration where the caller centralizes endpoint URLs in constants/config (a near-universal pattern) is invisible to cross-repo-intelligence.
  • Users cannot trust cross_http_calls: 0 as "not integrated."
  • trace_path(mode="cross_service") likewise misses these hops.

Proposed fixes (in rough priority)

  1. Intra-file constant folding for URL args. When a call argument is a Name, resolve it to a same-module assignment and fold simple str + str / f-string / .format concatenations where at least one operand is a literal. Recover the literal suffix even when the base is an env var, and store it as a partial url_path.
  2. Suffix/contains matching in the cross-repo matcher. Even a partial path (no host) should match a Route by path-suffix + method, with reduced confidence on the edge.
  3. Emit a low-confidence HTTP_CALLS edge for unresolved client calls. When the callee is a known HTTP client (requests.post, httpx, fetch, axios) but the URL is unresolved, still create an HTTP_CALLS edge with url_path=null and confidence="unresolved", so callers can see "this function makes an outbound HTTP call we couldn't pin to a route."
  4. Report unresolved client calls in the index result. Add unresolved_http_calls: N to the cross-repo-intelligence response so 0 cross edges isn't silently misleading.

Minimal repro

  1. Repo A: @app.post("/foo") (FastAPI/Express).
  2. Repo B: URL = BASE + "foo"; requests.post(URL).
  3. Index both, run cross-repo-intelligence from B targeting A → 0 edges.
  4. Change B to requests.post(BASE + "foo") or a literal → edge appears (literal/arg_url path).

Logs


Diagnostics trajectory (memory / performance / leak issues)


Project scale (if relevant)

No response

Confirmations

  • I searched existing issues and this is not a duplicate.
  • My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/normalStandard review queue; useful PR with ordinary maintainer urgency.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions