Constrain provider vocabulary candidate promotion

This commit is contained in:
2026-05-15 17:29:07 +02:00
parent d44d50f623
commit 324fbb3745
3 changed files with 61 additions and 3 deletions

View File

@@ -579,7 +579,8 @@ class CandidateGraphGenerator:
for fact in facts for fact in facts
if not ( if not (
fact.kind == "llm_provider" 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 [ return [
fact fact
for fact in facts 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: def _utility_relationship(self, fact: ObservedFact) -> str:

View File

@@ -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(): def test_candidate_generator_excludes_mention_only_providers_from_promoted_capability():
repository = Repository( repository = Repository(
id=1, id=1,

View File

@@ -32,7 +32,7 @@ This workplan is deliberately about generation quality, not acceptance policy.
```task ```task
id: RREG-WP-0016-T01 id: RREG-WP-0016-T01
status: todo status: done
priority: high priority: high
state_hub_task_id: "0e65e301-aba6-4720-a4bd-481eebf1b63f" 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 - Existing llm-connect-like fixtures that truly model provider adapters remain
explainable through source-role metadata. 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 ## T02: Generate Native Repo-Scoping Candidate Families
```task ```task