Skip to content

feat(serve): add multi-graph support to MCP server (#581) - #2099

Open
YanisGuerault wants to merge 2 commits into
Graphify-Labs:v8from
YanisGuerault:feat/add-multi-graph-support
Open

feat(serve): add multi-graph support to MCP server (#581)#2099
YanisGuerault wants to merge 2 commits into
Graphify-Labs:v8from
YanisGuerault:feat/add-multi-graph-support

Conversation

@YanisGuerault

@YanisGuerault YanisGuerault commented Jul 22, 2026

Copy link
Copy Markdown

Summary

  • Enable serving multiple knowledge graphs from a single MCP endpoint via --graphs-dir flag or GRAPHS_DIR env var
  • Always registry-based architecture: single graph = 1-entry registry, multi-graph = directory scan — no separate code path
  • Resolve issue MCP server must work with multiple repos #581

Changes

  • Add GraphContext dataclass + GraphRegistry (from_path, from_directory, hot-reload via rescan)
  • Refactor _build_server to accept GraphRegistry with per-call context resolution (_get_ctx)
  • Tool visibility keyed on registry size: list_graphs/use_graph when >1, PR tools when ==1
  • New graph param on all tool schemas (replaces project_path)
  • --graphs-dir CLI flag forces HTTP transport with daemon rescan thread

🤖 Generated with Claude Code

@YanisGuerault
YanisGuerault force-pushed the feat/add-multi-graph-support branch from 12f436c to 6d020bd Compare July 22, 2026 10:24
@YanisGuerault YanisGuerault changed the title feat(serve): add multi-graph support to MCP server feat(serve): add multi-graph support to MCP server (#581) Jul 22, 2026
Enable serving multiple knowledge graphs from a single MCP endpoint.
Always registry-based: single graph = 1-entry registry, multi-graph =
directory scan via --graphs-dir flag or GRAPHS_DIR env var.

- Add GraphContext dataclass + GraphRegistry (from_path, from_directory)
- Refactor _build_server to accept GraphRegistry with per-call resolution
- Tool visibility keyed on registry size: list_graphs/use_graph when >1,
  PR tools when ==1. New graph param on all tool schemas.
- Add --graphs-dir CLI flag forcing HTTP transport with auto-rescan
- Remove multi_serve.py and graphify-multi-mcp entry point (consolidated)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@YanisGuerault
YanisGuerault force-pushed the feat/add-multi-graph-support branch from 6d020bd to 2e39ab0 Compare August 25, 2026 13:56

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a multi-graph MCP server mode alongside the existing single-graph one: a new GraphRegistry loads either a single graph.json or every <name>/graph.json under a directory, rescans on an interval to pick up file changes (dropping graphs whose files vanish or fail to load), and _resolve_graph selects a target by explicit graph param, session default, or the sole loaded graph. Reworks _build_server to route all tool handlers through the registry and expose list_graphs/use_graph, and returns its handler dict for testing. Ships a multi Docker target driven by GRAPHS_DIR/SCAN_INTERVAL/PORT env vars plus a docker-compose.multi.yml and README docs, leaving the default single-graph image and entrypoint unchanged.

Worth a look

  • Default Docker build now produces multi-graph image instead of existing single-graph imageDockerfile:28 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Multi-graph compose publishes unauthenticated MCP service by defaultdocker-compose.multi.yml:11 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • except (OSError, SystemExit, Exception) swallows SystemExit and all errors, deleting graphgraphify/serve.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • GraphRegistry.get/names read shared _graphs without lockgraphify/serve.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Non-atomic single-graph resolution can return None during concurrent rescangraphify/serve.py:146 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1850 functions depend on the 1647 functions this change touches.

Health — this change adds coupling hotspots:

  • new: dispatch_command() — 2 callers, 122 callees
  • new: _build_server() — 12 callers, 17 callees
  • new: _query_graph_text() — 20 callers, 10 callees
  • new: _score_query() — 15 callers, 6 callees
  • new: _build_http_app() — 19 callers, 4 callees
  • new: _query_terms() — 20 callers, 3 callees
  • new: _subgraph_to_text() — 20 callers, 3 callees
  • new: _main() — 8 callers, 7 callees
  • …and 14 more — each is listed as a finding

Verification — 1850 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 1689 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Could not verify: Could not verify \_build\_http\_app.

The verifier did not have enough to check \_build\_http\_app, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 24 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly SystemExit — names the real obstacle, not a sampling gap)

Could not verify: Could not verify \_build\_server.

The verifier did not have enough to check \_build\_server, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 54 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly AttributeError — names the real obstacle, not a sampling gap)

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Verification did not run: Verification did not run for \_main.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=1): error: Graph path must be a .json file, got: '/workspace/job-a1e2a6c2baa84ce596d72365c42bb445/head/a' error: Graph path

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Verification did not run: Verification did not run for serve.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=1): error: Graph path must be a .json file, got: '/workspace/job-a1e2a6c2baa84ce596d72365c42bb445/head/a longer string' erro

Verification did not run: Verification did not run for serve\_http.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=124): timeout after 30s

· 9 grounded finding(s) anchored inline below; 13 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/serve.py Outdated
)


def _load_graph(graph_path: str) -> nx.Graph:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_load_graph()

12 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py


def _build_server(graph_path: str):
def _build_server(registry: GraphRegistry, *, session_state: dict | None = None):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_build_server()

fans out to 17 callees (efferent coupling); 12 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
path = _resolve_graph_path(project_path)
G, communities = _load_ctx(path)
active_graph_path = str(Path(path).resolve())
def _get_ctx(arguments: dict) -> GraphContext:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_get_ctx()

9 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -1781,6 +1919,8 @@ def _tool_get_node(arguments: dict) -> str:
])

def _tool_get_neighbors(arguments: dict) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_tool_get_neighbors()

fans out to 8 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -1884,6 +2035,8 @@ def _tool_list_prs(arguments: dict) -> str:
return format_prs_text(prs, base)

def _tool_get_pr_impact(arguments: dict) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_tool_get_pr_impact()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -1990,17 +2174,33 @@ async def list_resources() -> list[types.Resource]:
]

async def read_resource(uri: AnyUrl) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionread_resource()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py Outdated
return server, _handlers


def serve(graph_path: str | None = None) -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionserve()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -2175,8 +2374,9 @@ async def __call__(self, scope, receive, send) -> None:


def _build_http_app(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_build_http_app()

19 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread tests/test_serve_http.py
assert "Nodes: 2" in _call_tool(client, headers, "graph_stats", {}, rid=3)


def test_corrupt_project_graph_is_a_tool_error_without_killing_server(tmp_path):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressiontest_corrupt_project_graph_is_a_tool_error_without_killing_server()

fans out to 7 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Replace directory discovery with explicit repository paths and remove the legacy multi-MCP deployment workflow.
@YanisGuerault
YanisGuerault force-pushed the feat/add-multi-graph-support branch from 3e02e0a to 70194e1 Compare August 25, 2026 15:02

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. 2 change(s) tested, no difference found (not proven).


Graphify review — findings

Adds a public graphify <repo>... --mcp CLI path that serves one or more existing repository graphs over MCP, parsed by _run_mcp_cli and dispatched to stdio via serve or HTTP via serve_http, rejecting duplicate repo basenames, missing graphify-out/graph.json, and malformed transport/host/port/api-key options. Introduces GraphRegistry and GraphContext to hold multiple named graphs, with from_paths skipping the learning overlay and project-path access, and exposes list_graphs/use_graph tools plus an optional per-tool graph parameter so callers can target a specific graph or set a session default. Retools the Dockerfile and adds docker-compose.multi.yml to run the public CLI against a mounted repo tree instead of baking a graph into the image.

Worth a look

  • HTTP transport binds to 0.0.0.0 without requiring API keygraphify/__main__.py:519 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • CLI allows unauthenticated non-loopback HTTP MCP bindinggraphify/__main__.py:584 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • GraphRegistry.get/names read shared dict without holding the lock while rescan mutates itgraphify/serve.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Per-call project_path graph selection removed from tool dispatchgraphify/serve.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • MCP tool calls no longer honor project_path routinggraphify/serve.py:2080 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 839 functions depend on the 570 functions this change touches.

Health — this change adds coupling hotspots:

  • new: dispatch_command() — 2 callers, 122 callees
  • new: _build_server() — 14 callers, 17 callees
  • new: _query_graph_text() — 20 callers, 10 callees
  • new: _score_query() — 15 callers, 6 callees
  • new: _build_http_app() — 20 callers, 4 callees
  • new: render() — 13 callers, 5 callees
  • new: _get_ctx() — 9 callers, 7 callees
  • new: _query_terms() — 20 callers, 3 callees
  • …and 21 more — each is listed as a finding

Verification — 839 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 827 function(s) in the blast radius were not formally verified this run

Formal verification

No difference found (not proven): No behavior difference found in \_run\_cli (not a proof).

The verifier ran both versions of \_run\_cli on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Could not verify: Could not verify \_build\_http\_app.

The verifier did not have enough to check \_build\_http\_app, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 24 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly SystemExit — names the real obstacle, not a sampling gap)

Could not verify: Could not verify \_build\_server.

The verifier did not have enough to check \_build\_server, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 54 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly AttributeError — names the real obstacle, not a sampling gap)

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Could not verify: Could not verify \_load\_graph.

The verifier did not have enough to check \_load\_graph, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 23 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly SystemExit — names the real obstacle, not a sampling gap)

Verification did not run: Verification did not run for \_main.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=1): error: Graph path must be a .json file, got: '/workspace/job-7af6d2a6766b4d54bd60987fc9155ca7/head/a' error: Graph path

Could not verify: Could not verify \_\_init\_\_.

The verifier did not have enough to check \_\_init\_\_, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: signature changed: no shared positional arity

Verification did not run: Verification did not run for serve.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=1): error: Graph path must be a .json file, got: '/workspace/job-7af6d2a6766b4d54bd60987fc9155ca7/head/a longer string' erro

Verification did not run: Verification did not run for serve\_http.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=124): timeout after 30s

No difference found (not proven): No behavior difference found in monolith\_roundtrip (not a proof).

The verifier ran both versions of monolith\_roundtrip on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

· 11 grounded finding(s) anchored inline below; 18 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/__main__.py
serve(registry=registry)


def _serve_mcp_repositories(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_serve_mcp_repositories()

6 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/__main__.py
return True


def _run_cli() -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_run_cli()

high coupling complexity (Ca·Ce = 15).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
)


def _load_graph(graph_path: str, *, load_learning_overlay: bool = True) -> nx.Graph:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_load_graph()

12 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py


def _build_server(graph_path: str):
def _build_server(registry: GraphRegistry, *, session_state: dict | None = None):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_build_server()

fans out to 17 callees (efferent coupling); 14 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
return fallback_session_state
return session_states.setdefault(session, {})

def _get_ctx(arguments: dict) -> GraphContext:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_get_ctx()

fans out to 7 callees (efferent coupling); 9 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -1884,6 +2023,8 @@ def _tool_list_prs(arguments: dict) -> str:
return format_prs_text(prs, base)

def _tool_get_pr_impact(arguments: dict) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_tool_get_pr_impact()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -1990,17 +2164,34 @@ async def list_resources() -> list[types.Resource]:
]

async def read_resource(uri: AnyUrl) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionread_resource()

fans out to 8 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py


def serve(graph_path: str | None = None) -> None:
def serve(graph_path: str | None = None, *, registry: GraphRegistry | None = None) -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionserve()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread graphify/serve.py
@@ -2175,8 +2366,9 @@ async def __call__(self, scope, receive, send) -> None:


def _build_http_app(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression_build_http_app()

20 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Comment thread tests/test_serve_http.py
assert "Nodes: 2" in _call_tool(client, headers, "graph_stats", {}, rid=3)


def test_corrupt_project_graph_is_a_tool_error_without_killing_server(tmp_path):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressiontest_corrupt_project_graph_is_a_tool_error_without_killing_server()

fans out to 7 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

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