You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MCP analyze results are not scoped to the session's bound workspace: with the default one-workspace-per-repo layout, unscoped calls return symbols from all tracked repos. Passing target {repo: "<name>"} fixes it for some kinds (clones, dead_code) but the health kind ignores the repo selector entirely — in both name and path form — while accepting it without error.
The CLI is not affected: gortex analyze --kind health_score run from a repo cwd scopes correctly. So the graph and analyzers can scope; the MCP facade is what loses the binding.
Environment
daemon v0.61.1+89263194, linux/amd64, go1.26.5, systemd user unit
14 tracked repos, default workspaces (one per repo, no shared workspace: declarations)
Every worst symbol is from a different tracked repo. analyze kind=clones likewise returns clusters from gortex-web, tradebot, whatdowewatch, rivalbot — none from the bound repo.
health ignores an explicit repo target. Both forms return the identical 4393-symbol global result:
No error — the selector is accepted and silently ignored. (An invalid selector key is rejected with unknown target selector, so the target is being parsed.)
The selector works for other kinds, which is what isolates the bug to health:
analyze kind=clones target={"repo": "vault-stack"} → 0 clusters (correct for this repo)
MCP analyze with no target should default to the session's bound workspace, matching CLI behavior (or at minimum the docs should say it's global).
Every kind should honor target.repo; accepting the selector and ignoring it is the worst combination, since results look plausible until a foreign path shows up.
Possibly related
The MCP and CLI kind lists have diverged: MCP exposes health and clones; the CLI exposes health_score and has no clones. If MCP health is a distinct global aggregator rather than a facade over health_score, that would explain repro 2 — but it silently accepting target.repo still seems wrong.
Summary
MCP
analyzeresults are not scoped to the session's bound workspace: with the default one-workspace-per-repo layout, unscoped calls return symbols from all tracked repos. Passingtarget {repo: "<name>"}fixes it for some kinds (clones,dead_code) but thehealthkind ignores the repo selector entirely — in both name and path form — while accepting it without error.The CLI is not affected:
gortex analyze --kind health_scorerun from a repo cwd scopes correctly. So the graph and analyzers can scope; the MCP facade is what loses the binding.Environment
v0.61.1+89263194, linux/amd64, go1.26.5, systemd user unitworkspace:declarations)vault-stack—workspace(operation:"active_project")returnsbound: true, project: vault-stack, workspace: vault-stackReproduction
Unscoped
analyzeis global, not workspace-bound. From the session bound tovault-stack(a ~50-symbol bash repo):Every worst symbol is from a different tracked repo.
analyze kind=cloneslikewise returns clusters fromgortex-web,tradebot,whatdowewatch,rivalbot— none from the bound repo.healthignores an explicit repo target. Both forms return the identical 4393-symbol global result:No error — the selector is accepted and silently ignored. (An invalid selector key is rejected with
unknown target selector, so the target is being parsed.)The selector works for other kinds, which is what isolates the bug to
health:CLI control. From the repo's directory:
Expected
analyzewith no target should default to the session's bound workspace, matching CLI behavior (or at minimum the docs should say it's global).target.repo; accepting the selector and ignoring it is the worst combination, since results look plausible until a foreign path shows up.Possibly related
healthandclones; the CLI exposeshealth_scoreand has noclones. If MCPhealthis a distinct global aggregator rather than a facade overhealth_score, that would explain repro 2 — but it silently acceptingtarget.repostill seems wrong.analyze kind=routesmixes fields —lineis the mux registration line butfileis the handler's file (Go net/http 1.22 method patterns) #322 (analyze kind=routesmixes fields) may share plumbing but describes field attribution, not scope.