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
Add a sibling repository-context provider plane for evidence-backed workspace,
project, package, source-root, target, task, entrypoint and project-dependency
topology. Join it to code files under the same input-generation transaction and
expose it through a typed branch of the existing single MCP tool.
Do not overload language providers, parse every build DSL in core, or mix
generated summaries/embeddings with declared or tool-resolved build facts.
Verified current boundary
The language graph is good at symbol-scale semantics. Repository orientation
still repeatedly falls back to rg, directory walks and raw manifests for:
workspace/package membership;
applications versus libraries;
source/test/generated roots;
build targets/tasks/entrypoints; and
project-to-project dependencies.
Current IGraphProvider is intentionally a language-slice owner:
languages is non-empty;
provider selection rejects overlapping language ownership;
facts is the GraphEdgeKind code-semantic union; and
a bulk session replaces language slices atomically.
Generalizing it to ?anything that emits graph-shaped data? would weaken those
invariants. The current dump provenance/generation machinery is reusable, but
repository topology needs a sibling contract and fact vocabulary.
Decision: separate fact plane and provider registry
Reuse provider lifecycle concepts?resolve, prepare, build inputs,
configuration, refusal, open/refresh/close, universe/manifest/content digests,
source digests, shard transaction and coverage?but do not require a language
slice.
The first ontology is deliberately small.
Node kinds
workspace
project
package
source-set
source-root
generated-root
build-target
task
entrypoint
Relation kinds
contains
depends-on
source-of
test-of
produces
invokes
entrypoint-of
joins-file
Repository nodes/edges stay in a separate dump plane. Do not encode a Gradle
project as a GraphNodeKind.class or reuse code-semantic calls.
Evidence and authority
Every topology fact has:
provider/tool/version;
authority: tool-resolved, declared, or later inferred;
source manifest/export artifact and source evidence where available;
build configuration/target universe;
input and content digests; and
complete, partial, or unsupported coverage per topology family.
Version one accepts only tool-resolved and versioned declared facts.
Directory naming conventions, guessed entrypoints and generated prose are out.
If inference is added later it must remain a lower authority and visibly
separate.
Authoritative adapter routes
Prefer the owning tool's machine-readable model:
Ecosystem
First authoritative route
npm/pnpm/Yarn
package-manager workspace/member output plus versioned package manifests/lockfile
configured target graph from cquery --output=proto; action/output facts from aquery only when needed
Clang generic
compilation database TUs plus include/source joins; not a full build-project ontology
Swift
SourceKit-LSP build system/BSP or SwiftPM/Xcode build description
Dart/Flutter
pub workspace/package configuration and analysis contexts
Composer
Composer package/lock/installed/autoload model
Ruby
Bundler resolved specs/groups plus explicit gem/package manifests
Python
versioned pyproject.toml workspace/build-backend metadata plus the selected environment's installed distribution/import model
Parsing a manifest is acceptable when that manifest itself is the versioned
declarative contract. Do not write a general Groovy/Kotlin/Starlark/YAML parser
to emulate a build tool. Adapter failures or unavailable tool models produce
partial/unsupported coverage and a fallback to smaller declared facts.
Metadata commands must have a documented side-effect/security policy. Avoid
executing arbitrary tasks/scripts solely for orientation; if a build tool must
evaluate project code, report it before invocation and use the project wrapper/
configured environment.
Identity, joins and generation compatibility
Repository identities include provider/ecosystem, workspace root, project/
package/target coordinate and configuration. Same project under two Gradle
configurations, Cargo feature sets or Bazel configured targets is not one node.
entrypoint joins its source file and, when the language provider proves it,
a code symbol; and
project dependencies remain repository edges even when no symbol-level edge
is present.
File-level joins are sufficient for version one. Add symbol joins only for
explicit entrypoint/generated-symbol evidence, not name guessing.
Topology and language shards commit independently, but an MCP generation may
combine them only when their input manifests/configuration coordinates are
compatible. On mismatch:
retain the last compatible topology generation if its inputs still match;
otherwise publish the code graph with topology coverage marked unavailable;
never silently join new code to stale topology.
A topology-only edit invalidates joins/affected targets, not unrelated semantic
code shards.
MCP surface decision
Keep one MCP tool, inspect_code_graph, but add a versioned topology request
branch and typed result rather than forcing project nodes into code operations.
The branch supports:
workspace/project/package orientation;
dependencies/dependents;
source sets/roots and generated roots;
build targets/tasks;
declared/tool-resolved entrypoints; and
file joins into existing graph handles.
tour, overview and entrypoints may consume topology internally and include
an optional topology section, but their code-semantic nodes/edges retain their
meaning.
This is an intentional coordinated application-schema revision. Update the
application parity fixture/reference contract in the same change or gate the
branch behind an explicit protocol capability. Do not smuggle structured
topology into the English audit string.
Every result returns topology provenance, coverage, generation and join status
beside #63's language coverage.
Incremental and performance behavior
Topology is shardable by provider/workspace/project/target:
no-op: validate tool/manifests and load prior shards;
manifest/lock edit: rerun only the owning metadata adapter and affected joins;
build configuration/feature/target change: select a new universe;
provider failure/cancel/malformed output: retain the prior compatible context;
and
language graph update: recompute only file joins whose identities moved.
Use resident owning tools where they exist?Gradle Tooling API daemon, BSP
server, SourceKit-LSP, Roslyn workspace. Simple declared manifests should parse
in-process. Target no-op below 250 ms after validated inputs; record tool startup,
model query, normalization/join and MCP readiness separately.
First implementation slice
Dogfood a mixed fixture with:
this repository's pnpm workspace;
a Cargo workspace using cargo metadata;
a Gradle multi-project build using Tooling API; and
a CMake project using File API codemodel.
This exercises declared and tool-resolved authority, multiple ecosystems,
configuration, generated/source roots and cross-plane file joins without
attempting every adapter at once.
add deterministic fake-provider transaction and stale-join tests;
implement pnpm/package manifest adapter and dogfood this repository;
implement Cargo, Gradle and CMake adapters;
add the versioned MCP topology branch and use topology in
overview/tour/entrypoints;
add remaining adapters behind the same conformance suite; and
publish support documentation only for adapters with real fixtures.
Correctness and impact experiment
Use a pinned repository-orientation question, for example:
Explain the workspaces, applications and packages, their source/test/generated
roots and entrypoints, and the project dependency flow relevant to X.
Record:
topology MCP calls and returned evidence;
rg/directory walk/raw manifest reads;
correctness of projects, dependencies, roots and entrypoints;
unsupported/inferred claims;
input tokens/tool latency; and
whether file/code joins led to the correct semantic follow-up.
The goal is not zero shell reads. It is that stable, authoritative topology is
read from one indexed model and shell/source reads become explicit gaps.
Do not run a paid agent A/B benchmark without separate authorization.
Acceptance
Repository context has a sibling registry/fact plane; language ownership
and GraphEdgeKind remain unchanged.
Ontology, identity, provenance, coverage and joins are versioned and
validated.
pnpm, Cargo, Gradle and CMake mixed fixtures assert exact projects,
targets, roots, dependencies, entrypoints and file joins.
Declared/tool-resolved/inferred authority cannot be conflated.
Incompatible code/topology generations never join.
No-op, manifest/lock/config edit, create/delete/rename, provider failure,
cancel, stale result and retry are atomic.
The single MCP tool has a typed/versioned topology request/result and
operation-scoped coverage.
Orientation experiments show correctness and tool/read changes without
claiming shell search is eliminated.
Adapters use authoritative tool models where available and do not emulate
build DSLs in core.
Focused tests, pnpm build, pnpm test, and pnpm coverage pass.
Non-goals
universal deployment/ownership/release ontology;
embeddings or generated Wiki prose as build truth;
PR #164 delivered the sibling plane and first four adapters, but the next solo
campaign reproduced correctness gaps beyond the previously recorded missing
orientation experiment.
Initial static resident generations cannot join
createResidentGraphSource computes the initial static state's input generation
but publishes the raw buildStaticGraphResult dump without attaching it. A
fresh mode: "static" MCP server therefore withholds every joins-file edge on
its first topology call and reports the no-generation explanation intended for
unrevalidated graph files and legacy dumps. LSP/hybrid initial builds already
attach their committed generation; the defect is the explicit-static branch.
Repository path classification is inconsistent
Cargo, Gradle, and CMake each carry a private isInside implementation:
On Windows, path.relative("D:\\a", "C:\\b") is the absolute C:\\b, so all
three report cross-drive targets/roots/artifacts as internal. The shared isSubPath utility already handles that case and preserves Windows
case-insensitive comparison.
The pnpm adapter has a separate instance of the same class of error. Manifest
roots and entrypoints are always emitted with external: false. A reproduced
absolute main outside the workspace became file: ../outside-entry.js while
remaining non-external. A files: ["../outside-root"] entry escaped its package,
used a non-canonical pkg/../outside-root identity, and normalized its public
root to a different value.
pnpm publication files are labeled as source directories
The pnpm adapter maps every simple package files entry to source-root unless
its spelling resembles a generated directory. Dogfooding this repository
therefore labels README.md, LICENSE, lint.config.ts, and tsconfig.json as
source roots. npm's files field is a publication allow-list and may name
individual files; it does not establish that each path is a source directory.
The same boundary trusts the manifest cast without checking consumed fields. A
string-valued files field is iterated character by character as roots, and a
string-valued scripts field becomes numeric task names. Valid open-ended exports condition keys should remain supported, but wrong field types must
fail closed with the manifest identity.
Nested workspace creation is not observed
The pnpm and Cargo sessions watch current member manifests and only one nearby
ancestor. In real temporary workspaces using groups/*/*, the initial groups/a/one member watches groups/a but not groups. Creating groups/b/two changes no watched identity, so the second refresh returns changed: false and permanently omits the package until another input moves.
The directory ancestor chain from each member to the workspace root is the
owning discovery surface; hashing immediate entries at each level detects new
siblings without emulating either workspace DSL.
Cargo cannot execute on a standard Windows rustup install
The Cargo adapter hardcodes cargo.cmd on Windows. rustup installs cargo.exe; on the campaign checkout the real provider failed with cargo.cmd is not recognized while cargo.exe was present on PATH. Use the
platform-aware command resolver around the native cargo name and add a
hermetic executable-resolution test.
Residual consequence surface
These defects affect topology dump identity, resident no-op and package
create/rename/delete behavior, the external trust flag, file-join admission,
TypeScript API/MCP results, Windows Cargo/CMake/Gradle users, and the orientation
experiment. A fix must keep inferred facts out of protocol v1 and preserve
atomic last-good recovery.
Residual acceptance and verification
A fresh static resident topology call admits joins when code/topology
generations are current; graph-file and legacy no-generation cases remain
unavailable for their existing reasons.
Cargo, Gradle, CMake, and pnpm use one canonical workspace-containment rule,
including Windows cross-drive and case behavior.
pnpm source/generated roots are canonical, package-confined directories;
individual publication files are not relabeled as roots.
Consumed pnpm manifest/model fields are validated at the boundary and
malformed shapes fail closed without partial facts.
pnpm and Cargo detect member creation at every nested workspace depth,
plus deletion, rename, no-op, failed refresh, and recovery.
A hermetic Windows-path case proves the Cargo adapter resolves a native cargo.exe rather than inventing cargo.cmd.
The repository-orientation experiment reports authoritative projects,
packages, roots, entrypoints, dependencies, joins, unsupported claims,
tool/read changes, and latency without claiming shell reads are eliminated.
Outcome
Add a sibling repository-context provider plane for evidence-backed workspace,
project, package, source-root, target, task, entrypoint and project-dependency
topology. Join it to code files under the same input-generation transaction and
expose it through a typed branch of the existing single MCP tool.
Do not overload language providers, parse every build DSL in core, or mix
generated summaries/embeddings with declared or tool-resolved build facts.
Verified current boundary
The language graph is good at symbol-scale semantics. Repository orientation
still repeatedly falls back to
rg, directory walks and raw manifests for:Current
IGraphProvideris intentionally a language-slice owner:languagesis non-empty;factsis theGraphEdgeKindcode-semantic union; andGeneralizing it to ?anything that emits graph-shaped data? would weaken those
invariants. The current dump provenance/generation machinery is reusable, but
repository topology needs a sibling contract and fact vocabulary.
Decision: separate fact plane and provider registry
Add:
Reuse provider lifecycle concepts?resolve, prepare, build inputs,
configuration, refusal, open/refresh/close, universe/manifest/content digests,
source digests, shard transaction and coverage?but do not require a language
slice.
The first ontology is deliberately small.
Node kinds
workspaceprojectpackagesource-setsource-rootgenerated-rootbuild-targettaskentrypointRelation kinds
containsdepends-onsource-oftest-ofproducesinvokesentrypoint-ofjoins-fileRepository nodes/edges stay in a separate dump plane. Do not encode a Gradle
project as a
GraphNodeKind.classor reuse code-semanticcalls.Evidence and authority
Every topology fact has:
tool-resolved,declared, or laterinferred;complete,partial, orunsupportedcoverage per topology family.Version one accepts only
tool-resolvedand versioneddeclaredfacts.Directory naming conventions, guessed entrypoints and generated prose are out.
If inference is added later it must remain a lower authority and visibly
separate.
Authoritative adapter routes
Prefer the owning tool's machine-readable model:
cargo metadata --format-version 1, including workspace members, targets, features and resolved dependenciesgo env GOWORKandgo list -json/module/workspace metadatacquery --output=proto; action/output facts fromaqueryonly when neededpyproject.tomlworkspace/build-backend metadata plus the selected environment's installed distribution/import modelParsing a manifest is acceptable when that manifest itself is the versioned
declarative contract. Do not write a general Groovy/Kotlin/Starlark/YAML parser
to emulate a build tool. Adapter failures or unavailable tool models produce
partial/unsupported coverage and a fallback to smaller declared facts.
Metadata commands must have a documented side-effect/security policy. Avoid
executing arbitrary tasks/scripts solely for orientation; if a build tool must
evaluate project code, report it before invocation and use the project wrapper/
configured environment.
Identity, joins and generation compatibility
Repository identities include provider/ecosystem, workspace root, project/
package/target coordinate and configuration. Same project under two Gradle
configurations, Cargo feature sets or Bazel configured targets is not one node.
Join topology to code at file level first:
a code symbol; and
is present.
File-level joins are sufficient for version one. Add symbol joins only for
explicit entrypoint/generated-symbol evidence, not name guessing.
Topology and language shards commit independently, but an MCP generation may
combine them only when their input manifests/configuration coordinates are
compatible. On mismatch:
A topology-only edit invalidates joins/affected targets, not unrelated semantic
code shards.
MCP surface decision
Keep one MCP tool,
inspect_code_graph, but add a versionedtopologyrequestbranch and typed result rather than forcing project nodes into code operations.
The branch supports:
tour,overviewandentrypointsmay consume topology internally and includean optional topology section, but their code-semantic nodes/edges retain their
meaning.
This is an intentional coordinated application-schema revision. Update the
application parity fixture/reference contract in the same change or gate the
branch behind an explicit protocol capability. Do not smuggle structured
topology into the English
auditstring.Every result returns topology provenance, coverage, generation and join status
beside #63's language coverage.
Incremental and performance behavior
Topology is shardable by provider/workspace/project/target:
and
Use resident owning tools where they exist?Gradle Tooling API daemon, BSP
server, SourceKit-LSP, Roslyn workspace. Simple declared manifests should parse
in-process. Target no-op below 250 ms after validated inputs; record tool startup,
model query, normalization/join and MCP readiness separately.
First implementation slice
Dogfood a mixed fixture with:
cargo metadata;This exercises declared and tool-resolved authority, multiple ecosystems,
configuration, generated/source roots and cross-plane file joins without
attempting every adapter at once.
Implementation order:
topologybranch and use topology inoverview/tour/entrypoints;
Correctness and impact experiment
Use a pinned repository-orientation question, for example:
Record:
rg/directory walk/raw manifest reads;The goal is not zero shell reads. It is that stable, authoritative topology is
read from one indexed model and shell/source reads become explicit gaps.
Do not run a paid agent A/B benchmark without separate authorization.
Acceptance
and
GraphEdgeKindremain unchanged.validated.
targets, roots, dependencies, entrypoints and file joins.
cancel, stale result and retry are atomic.
operation-scoped coverage.
claiming shell search is eliminated.
build DSLs in core.
pnpm build,pnpm test, andpnpm coveragepass.Non-goals
Primary references
Verified residual on
1bf9486PR #164 delivered the sibling plane and first four adapters, but the next solo
campaign reproduced correctness gaps beyond the previously recorded missing
orientation experiment.
Initial static resident generations cannot join
createResidentGraphSourcecomputes the initial static state's input generationbut publishes the raw
buildStaticGraphResultdump without attaching it. Afresh
mode: "static"MCP server therefore withholds everyjoins-fileedge onits first topology call and reports the no-generation explanation intended for
unrevalidated graph files and legacy dumps. LSP/hybrid initial builds already
attach their committed generation; the defect is the explicit-static branch.
Repository path classification is inconsistent
Cargo, Gradle, and CMake each carry a private
isInsideimplementation:On Windows,
path.relative("D:\\a", "C:\\b")is the absoluteC:\\b, so allthree report cross-drive targets/roots/artifacts as internal. The shared
isSubPathutility already handles that case and preserves Windowscase-insensitive comparison.
The pnpm adapter has a separate instance of the same class of error. Manifest
roots and entrypoints are always emitted with
external: false. A reproducedabsolute
mainoutside the workspace becamefile: ../outside-entry.jswhileremaining non-external. A
files: ["../outside-root"]entry escaped its package,used a non-canonical
pkg/../outside-rootidentity, and normalized its publicroot to a different value.
pnpm publication files are labeled as source directories
The pnpm adapter maps every simple package
filesentry tosource-rootunlessits spelling resembles a generated directory. Dogfooding this repository
therefore labels
README.md,LICENSE,lint.config.ts, andtsconfig.jsonassource roots. npm's
filesfield is a publication allow-list and may nameindividual files; it does not establish that each path is a source directory.
The same boundary trusts the manifest cast without checking consumed fields. A
string-valued
filesfield is iterated character by character as roots, and astring-valued
scriptsfield becomes numeric task names. Valid open-endedexportscondition keys should remain supported, but wrong field types mustfail closed with the manifest identity.
Nested workspace creation is not observed
The pnpm and Cargo sessions watch current member manifests and only one nearby
ancestor. In real temporary workspaces using
groups/*/*, the initialgroups/a/onemember watchesgroups/abut notgroups. Creatinggroups/b/twochanges no watched identity, so the second refresh returnschanged: falseand permanently omits the package until another input moves.The directory ancestor chain from each member to the workspace root is the
owning discovery surface; hashing immediate entries at each level detects new
siblings without emulating either workspace DSL.
Cargo cannot execute on a standard Windows rustup install
The Cargo adapter hardcodes
cargo.cmdon Windows. rustup installscargo.exe; on the campaign checkout the real provider failed withcargo.cmd is not recognizedwhilecargo.exewas present onPATH. Use theplatform-aware command resolver around the native
cargoname and add ahermetic executable-resolution test.
Residual consequence surface
These defects affect topology dump identity, resident no-op and package
create/rename/delete behavior, the
externaltrust flag, file-join admission,TypeScript API/MCP results, Windows Cargo/CMake/Gradle users, and the orientation
experiment. A fix must keep inferred facts out of protocol v1 and preserve
atomic last-good recovery.
Residual acceptance and verification
generations are current; graph-file and legacy no-generation cases remain
unavailable for their existing reasons.
including Windows cross-drive and case behavior.
individual publication files are not relabeled as roots.
malformed shapes fail closed without partial facts.
plus deletion, rename, no-op, failed refresh, and recovery.
cargo.exerather than inventingcargo.cmd.packages, roots, entrypoints, dependencies, joins, unsupported claims,
tool/read changes, and latency without claiming shell reads are eliminated.
pnpm build,pnpm test, andpnpm coveragepass.No paid agent A/B run or global toolchain installation is authorized by this
issue.