From 324fbb37452876a5324a5457fd1c9582029c969e Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 15 May 2026 17:29:07 +0200 Subject: [PATCH] Constrain provider vocabulary candidate promotion --- .../candidate_graph/generator.py | 5 +- tests/test_candidate_graph.py | 47 +++++++++++++++++++ ...16-native-candidate-generation-recovery.md | 12 ++++- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/repo_registry/candidate_graph/generator.py b/src/repo_registry/candidate_graph/generator.py index 99ad26e..453411f 100644 --- a/src/repo_registry/candidate_graph/generator.py +++ b/src/repo_registry/candidate_graph/generator.py @@ -579,7 +579,8 @@ class CandidateGraphGenerator: for fact in facts if not ( fact.kind == "llm_provider" - and self._utility_relationship(fact) not in {"owned", "facade", "adapter"} + and self._utility_relationship(fact) + not in {"facade", "adapter"} ) ), ] @@ -1054,7 +1055,7 @@ class CandidateGraphGenerator: return [ fact for fact in facts - if self._utility_relationship(fact) in {"owned", "facade", "adapter"} + if self._utility_relationship(fact) in {"facade", "adapter"} ] def _utility_relationship(self, fact: ObservedFact) -> str: diff --git a/tests/test_candidate_graph.py b/tests/test_candidate_graph.py index fcfc009..de41846 100644 --- a/tests/test_candidate_graph.py +++ b/tests/test_candidate_graph.py @@ -517,6 +517,53 @@ def test_candidate_generator_does_not_promote_llm_provider_mentions_to_capabilit ] == [] +def test_candidate_generator_does_not_promote_owned_provider_vocabulary_to_capability(): + repository = Repository( + id=1, + name="RepoScoping", + url="/tmp/repo-scoping", + description="Maps repositories into reviewable capability graphs.", + branch="main", + status="analyzed", + ) + facts = [ + fact(1, "documentation", "README", "README.md"), + fact(2, "interface", "python route decorator", "src/api.py", '@app.get("/repos")'), + fact( + 3, + "llm_provider", + "OpenRouter", + "src/repo_registry/repo_scanning/scanner.py", + "openrouter", + {"source_role": "implementation_source", "utility_relationship": "owned"}, + ), + fact( + 4, + "provider_registry", + "LLM provider registry", + "src/repo_registry/repo_scanning/scanner.py", + metadata={ + "source_role": "implementation_source", + "utility_relationship": "owned", + }, + ), + fact( + 5, + "credential_config", + "OpenRouter API key", + "src/repo_registry/repo_scanning/scanner.py", + "OPENROUTER_API_KEY", + {"source_role": "implementation_source", "utility_relationship": "configure"}, + ), + ] + + graph = CandidateGraphGenerator().generate(repository, facts) + + capability_names = {capability.name for capability in graph[0].capabilities} + assert "Route LLM Requests Across Providers" not in capability_names + assert "Expose Repository Interface" in capability_names + + def test_candidate_generator_excludes_mention_only_providers_from_promoted_capability(): repository = Repository( id=1, diff --git a/workplans/RREG-WP-0016-native-candidate-generation-recovery.md b/workplans/RREG-WP-0016-native-candidate-generation-recovery.md index a0e747d..42eb9ac 100644 --- a/workplans/RREG-WP-0016-native-candidate-generation-recovery.md +++ b/workplans/RREG-WP-0016-native-candidate-generation-recovery.md @@ -32,7 +32,7 @@ This workplan is deliberately about generation quality, not acceptance policy. ```task id: RREG-WP-0016-T01 -status: todo +status: done priority: high state_hub_task_id: "0e65e301-aba6-4720-a4bd-481eebf1b63f" ``` @@ -48,6 +48,16 @@ Acceptance criteria: - Existing llm-connect-like fixtures that truly model provider adapters remain explainable through source-role metadata. +Implementation note 2026-05-15: narrowed deterministic LLM-provider capability +promotion to facts classified as `utility-facade` or `utility-adapter`; generic +owned implementation vocabulary such as scanner constants, normalization +tables, and API schemas now remains observed fact material. Added regression +coverage proving owned provider vocabulary does not create +`Route LLM Requests Across Providers` while adapter-like provider fixtures still +can. A throwaway self-assessment preview moved repo-scoping from `regression` +to `needs_review`: the forbidden provider-routing candidate disappeared and the +remaining generated candidate is `Expose Repository Interface`. + ## T02: Generate Native Repo-Scoping Candidate Families ```task