one time bootstrap path

This commit is contained in:
2026-05-02 00:36:00 +02:00
parent 911ca45618
commit 76f5ecb1b4
12 changed files with 328 additions and 27 deletions

View File

@@ -108,6 +108,51 @@ def test_candidate_generator_enriches_descriptions_from_content_chunks():
assert '@app.post("/classify")' in graph[0].capabilities[0].description
def test_candidate_generator_prefers_intent_over_derived_scope_chunks():
repository = Repository(
id=1,
name="KeyCape",
url="/tmp/key-cape",
description=None,
branch="main",
status="analyzed",
)
facts = [
fact(1, "intent", "INTENT", "INTENT.md"),
fact(2, "scope", "SCOPE", "SCOPE.md"),
fact(3, "documentation", "README", "README.md"),
]
chunks = [
chunk(
1,
"scope",
"SCOPE.md",
"# SCOPE\nAlready provides deployed IAM runtime behavior.",
end_line=2,
),
chunk(
2,
"intent",
"INTENT.md",
"# INTENT\nDesign a lightweight IAM profile implementation.",
end_line=2,
),
chunk(
3,
"documentation",
"README.md",
"# KeyCape\nREADME fallback should not beat intent.",
end_line=2,
),
]
graph = CandidateGraphGenerator().generate(repository, facts, chunks)
assert graph[0].name == "Design A Lightweight IAM Profile Implementation"
assert "INTENT. Design a lightweight IAM profile implementation" in graph[0].description
assert graph[0].source_refs[0].path == "INTENT.md"
def test_candidate_confidence_scoring_stays_conservative_for_weak_facts():
repository = Repository(
id=1,

View File

@@ -86,18 +86,18 @@ def test_content_extractor_chunks_provider_related_config(tmp_path):
assert "OPENROUTER_API_KEY" in chunks[0].text
def test_content_extractor_preserves_source_role_metadata(tmp_path):
def test_content_extractor_preserves_intent_source_role_metadata(tmp_path):
repo = tmp_path / "repo"
repo.mkdir()
(repo / "SCOPE.md").write_text("# SCOPE\n\nProvides OIDC.\n", encoding="utf-8")
(repo / "INTENT.md").write_text("# INTENT\n\nProvide OIDC.\n", encoding="utf-8")
chunks = ContentExtractor().extract(
repo,
[
fact(1, "scope", "SCOPE", "SCOPE.md", source_role="scope_summary"),
fact(1, "intent", "INTENT", "INTENT.md", source_role="intent_summary"),
],
)
assert len(chunks) == 1
assert chunks[0].kind == "scope"
assert chunks[0].metadata["source_role"] == "scope_summary"
assert chunks[0].kind == "intent"
assert chunks[0].metadata["source_role"] == "intent_summary"

View File

@@ -0,0 +1,51 @@
from datetime import date
from repo_registry.intent.bootstrap import bootstrap_intent_from_scope, scope_to_intent_text
def test_scope_to_intent_text_replaces_scope_heading_and_marks_bootstrap():
text = scope_to_intent_text(
"# SCOPE.md - Demo\n\n## One-liner\n\nCurrent utility.\n",
today=date(2026, 5, 2),
)
assert text.startswith("# INTENT\n\n")
assert "Bootstrapped from `SCOPE.md`" in text
assert "Bootstrap date: 2026-05-02" in text
assert "## One-liner\n\nCurrent utility." in text
def test_bootstrap_intent_from_scope_creates_intent_when_missing(tmp_path):
repo = tmp_path / "repo"
repo.mkdir()
(repo / "SCOPE.md").write_text("# SCOPE\n\nProvides search.\n", encoding="utf-8")
result = bootstrap_intent_from_scope(repo, today=date(2026, 5, 2))
assert result.status == "created"
intent_text = (repo / "INTENT.md").read_text(encoding="utf-8")
assert intent_text.startswith("# INTENT")
assert "Provides search." in intent_text
def test_bootstrap_intent_from_scope_does_not_overwrite_existing_intent(tmp_path):
repo = tmp_path / "repo"
repo.mkdir()
(repo / "SCOPE.md").write_text("# SCOPE\n", encoding="utf-8")
(repo / "INTENT.md").write_text("# INTENT\n\nKeep me.\n", encoding="utf-8")
result = bootstrap_intent_from_scope(repo)
assert result.status == "exists"
assert (repo / "INTENT.md").read_text(encoding="utf-8") == "# INTENT\n\nKeep me.\n"
def test_bootstrap_intent_from_scope_dry_run_reports_without_writing(tmp_path):
repo = tmp_path / "repo"
repo.mkdir()
(repo / "SCOPE.md").write_text("# SCOPE\n", encoding="utf-8")
result = bootstrap_intent_from_scope(repo, dry_run=True)
assert result.status == "would_create"
assert not (repo / "INTENT.md").exists()

View File

@@ -42,20 +42,29 @@ def test_deterministic_scanner_extracts_structural_facts(tmp_path):
assert languages == {"Python": 2}
def test_scanner_records_scope_with_source_role(tmp_path):
def test_scanner_records_intent_and_scope_with_distinct_source_roles(tmp_path):
repo = tmp_path / "sample"
repo.mkdir()
(repo / "INTENT.md").write_text(
"# INTENT\n\nProvides planned OIDC profile enforcement.\n",
encoding="utf-8",
)
(repo / "SCOPE.md").write_text(
"# SCOPE\n\n## One-liner\n\nProvides OIDC profile enforcement.\n",
"# SCOPE\n\n## One-liner\n\nCurrently provides OIDC profile enforcement.\n",
encoding="utf-8",
)
result = DeterministicScanner().scan(repo)
intent_fact = next(fact for fact in result.facts if fact.kind == "intent")
assert intent_fact.name == "INTENT"
assert intent_fact.path == "INTENT.md"
assert intent_fact.metadata["source_role"] == "intent_summary"
scope_fact = next(fact for fact in result.facts if fact.kind == "scope")
assert scope_fact.name == "SCOPE"
assert scope_fact.path == "SCOPE.md"
assert scope_fact.metadata["source_role"] == "scope_summary"
assert scope_fact.metadata["source_role"] == "derived_scope"
def test_scanner_readme_only_fixture_records_docs_without_interfaces(tmp_path):