Skip to content

feat(scope): intent-based default scoping for multi-repo workspaces#202

Open
pacaya wants to merge 2 commits into
zzet:mainfrom
pacaya:main
Open

feat(scope): intent-based default scoping for multi-repo workspaces#202
pacaya wants to merge 2 commits into
zzet:mainfrom
pacaya:main

Conversation

@pacaya

@pacaya pacaya commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Implementation of the issue #172

In a multi-repo workspace, graph queries had no principled default scope:
every tool read the full index, so results leaked across project and workspace boundaries unless the caller manually scoped each call. This PR
makes scope a first-class, intent-derived default while keeping explicit overrides uniform and workspace a hard isolation boundary.

Behavior change (default ON)

Ships enabled by default (scope.intent_defaults: true, override with GORTEX_SCOPE_INTENT_DEFAULTS=0). In a multi-repo workspace, results that
previously spanned every indexed repo now default to the session's repo (lookups) or workspace (reachability / analysis). Set the flag to false to
restore the prior whole-index behavior. Single-repo setups are unaffected.

Two-layer model

  • Layer A — uniform overrides: an explicit repo: / project: / scope:
    (workspace) argument overrides the default identically across query, MCP,
    and analyze tools. repo:"*" is a sentinel escape hatch meaning "all repos", not a post-filter.
  • Layer B — intent-based defaults: with no explicit scope, the default is
    chosen by the tool's intent —
    • Locate (symbol search / lookup) — repo (narrowest)
    • Reach (callers / usages / dependents / walk) — workspace
    • Analyze — workspace Defaults only ever narrow; they never widen past the session workspace.

Analyze made scope-aware

The analyze dispatcher now scopes its kinds in tiers: kinds built on the scoped-node accessors inherit scoping automatically; dead_code, hotspots,
cycles, and releases are per-row filtered via analyzeNodeVisible; the edge / algorithm / framework and file / AST-scan kinds were taught to honor
the resolved scope. Kinds that read the full graph directly (community / git-mining / per-id / synthesizer) are not narrowed in v1 and now stamp a
scope_note saying their results may span the whole index.

Tests & docs

  • New tests: scope_resolve_test.go, analyze_scope_test.go, workspace_isolation_test.go, scope_allows_test.go, plus search_text and
    field_query cases. go build ./... and go test -race ./internal/mcp/...
    pass.
  • docs/multi-repo.md documents the defaults and the narrow-only invariant;
    docs/proposals/scope-intent-defaults.md records the design and the default-ON decision.

Summary

Brief description of what this PR does.

Changes

Testing

  • All tests pass (go test -race ./...)
  • New tests added for new functionality
  • Benchmarks run if performance-relevant

Checklist

  • Code follows existing patterns in the codebase
  • No unnecessary abstractions added
  • Language extractor includes Meta["methods"] for interfaces (if applicable)
  • Methods have EdgeMemberOf edges to their containing type (if applicable)

In a multi-repo workspace, graph queries had no principled default
scope:
every tool read the full index, so results leaked across project and
workspace boundaries unless the caller manually scoped each call. This
PR
makes scope a first-class, intent-derived default while keeping explicit
overrides uniform and workspace a hard isolation boundary.

## Behavior change (default ON)

Ships enabled by default (`scope.intent_defaults: true`, override with
`GORTEX_SCOPE_INTENT_DEFAULTS=0`). In a multi-repo workspace, results
that
previously spanned every indexed repo now default to the session's repo
(lookups) or workspace (reachability / analysis). Set the flag to false
to
restore the prior whole-index behavior. Single-repo setups are
unaffected.

## Two-layer model

- Layer A — uniform overrides: an explicit `repo:` / `project:` /
`scope:`
  (workspace) argument overrides the default identically across query,
MCP,
  and analyze tools. `repo:"*"` is a sentinel escape hatch meaning "all
  repos", not a post-filter.
- Layer B — intent-based defaults: with no explicit scope, the default
is
  chosen by the tool's intent —
    - Locate (symbol search / lookup) ............... repo (narrowest)
    - Reach  (callers / usages / dependents / walk) . workspace
    - Analyze ....................................... workspace
  Defaults only ever narrow; they never widen past the session
workspace.

## Analyze made scope-aware

The analyze dispatcher now scopes its kinds in tiers: kinds built on the
scoped-node accessors inherit scoping automatically; dead_code,
hotspots,
cycles, and releases are per-row filtered via analyzeNodeVisible; the
edge / algorithm / framework and file / AST-scan kinds were taught to
honor
the resolved scope. Kinds that read the full graph directly (community /
git-mining / per-id / synthesizer) are not narrowed in v1 and now stamp
a
`scope_note` saying their results may span the whole index.

## Tests & docs

- New tests: scope_resolve_test.go, analyze_scope_test.go,
  workspace_isolation_test.go, scope_allows_test.go, plus search_text
and
  field_query cases. `go build ./...` and `go test -race
./internal/mcp/...`
  pass.
- docs/multi-repo.md documents the defaults and the narrow-only
invariant;
  docs/proposals/scope-intent-defaults.md records the design and the
  default-ON decision.
@pacaya pacaya force-pushed the main branch 2 times, most recently from e6ece38 to 468f494 Compare June 30, 2026 05:26
Comment thread docs/proposals/scope-intent-defaults.md Outdated
…repo.md

The proposal in docs/proposals/ had become a half-spec/half-status
hybrid that would only
drift. All user-facing behavior (the scope.intent_defaults flag, intent
table, opt-out, upgrade note) is already documented in
docs/multi-repo.md,
which stays the single source of truth. Design rationale lives in the
merged commit and PR thread. Also drops the now-dangling cross-reference
link to the deleted file.
@zzet

zzet commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Hey @pacaya! Thank you for your contribution and your time.
The scope of changes seems bigger than I imagined, and it will require additional time to review the change.

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.

2 participants