From 67d2ff7a67d19d4d05a74790ffcb1514ff15b0bd Mon Sep 17 00:00:00 2001 From: Sebastiangmz Date: Tue, 30 Jun 2026 15:40:30 -0600 Subject: [PATCH 1/3] test: add Milestone 6 interface contract Spec-Slice: CRAG-20260630-M6-PRODUCTION-INTERFACES --- ...06-30-m6-production-interfaces-contract.md | 20 +++ tests/test_m6_interfaces_docs.py | 146 ++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-30-m6-production-interfaces-contract.md create mode 100644 tests/test_m6_interfaces_docs.py diff --git a/docs/superpowers/plans/2026-06-30-m6-production-interfaces-contract.md b/docs/superpowers/plans/2026-06-30-m6-production-interfaces-contract.md new file mode 100644 index 0000000..6e4ef2a --- /dev/null +++ b/docs/superpowers/plans/2026-06-30-m6-production-interfaces-contract.md @@ -0,0 +1,20 @@ +# Milestone 6 Contract: Production Interfaces and Docs + +## Scope + +Stabilize the user-facing CodeRAG contracts across REST, MCP, CLI, and README without claiming production readiness beyond verified evidence. + +## Acceptance Criteria + +- M6-AC1: REST/MCP/CLI expose the same documented capability set where implementation exists: index, update, list, query, search, hybrid search, context packs, symbol lookup, reference lookup, and blast radius. +- M6-AC2: Representative REST, MCP, and CLI output shapes are covered by deterministic snapshot/contract tests. +- M6-AC3: User-facing docs position CodeRAG as a verified codebase context engine, not an autonomous coding agent. +- M6-AC4: Docs state current privacy and readiness limits: loopback default, explicit deployment hardening required, cloud LLMs require user-configured keys, and unsupported graph languages degrade explicitly. +- M6-AC5: CI and EvalFly smoke gates include the M6 interface/doc contract checks. + +## Non-goals + +- No autonomous editing behavior. +- No blanket production-ready claim. +- No broad redesign of Gradio UI. +- No expansion of unsupported language graph confidence. diff --git a/tests/test_m6_interfaces_docs.py b/tests/test_m6_interfaces_docs.py new file mode 100644 index 0000000..d3cd175 --- /dev/null +++ b/tests/test_m6_interfaces_docs.py @@ -0,0 +1,146 @@ +"""Milestone 6 interface and documentation contract tests.""" +# mypy: disable-error-code="no-untyped-def,no-untyped-call,union-attr,arg-type" + +import json +from types import SimpleNamespace + +import pytest +from click.testing import CliRunner + +from coderag.models.repository import Repository, RepositoryStatus + + +def test_mcp_tool_surface_includes_production_context_tools(): + import coderag.mcp.tools as tools + + expected = { + "index_repository", + "update_repository", + "list_repositories", + "query_code", + "search_code", + "search_hybrid", + "get_context_pack", + "find_symbol", + "find_references", + "get_blast_radius", + } + + assert expected <= {name for name in expected if callable(getattr(tools, name, None))} + + +@pytest.mark.asyncio +async def test_rest_hybrid_search_contract(monkeypatch): + from coderag.api import routes + from coderag.api.schemas import HybridSearchRequest + from coderag.models.response import RetrievedChunk + + repo = Repository(id="repo-ready", url="https://github.com/acme/demo", status=RepositoryStatus.READY) + + class FakeRegistry: + def get_unique(self, repo_id: str): + return repo if repo.id == repo_id else None + + class FakeRetrievalService: + def search_hybrid(self, repo_id: str, query: str, top_k: int, max_tokens: int, max_chunks_per_file: int): + assert (repo_id, query, top_k, max_tokens, max_chunks_per_file) == ( + "repo-ready", + "auth flow", + 2, + 512, + 1, + ) + return [ + RetrievedChunk( + chunk_id="chunk-1", + content="def login(): pass", + file_path="src/auth.py", + start_line=10, + end_line=12, + relevance_score=0.91, + chunk_type="function", + name="login", + retrieval_sources=["semantic", "lexical"], + score_breakdown={"combined": 0.91, "lexical": 0.8}, + token_estimate=4, + ranking_reason="semantic and lexical match", + ) + ] + + monkeypatch.setattr(routes, "registry", FakeRegistry()) + monkeypatch.setattr(routes, "retrieval_service", FakeRetrievalService()) + + response = await routes.search_hybrid( + HybridSearchRequest(repo_id="repo-ready", query="auth flow", top_k=2, max_tokens=512, max_chunks_per_file=1) + ) + + assert response.count == 1 + assert response.results[0].citation == "[src/auth.py:10-12]" + assert response.results[0].retrieval_sources == ["semantic", "lexical"] + assert response.results[0].score_breakdown["combined"] == 0.91 + + +def test_cli_hybrid_search_outputs_structured_json(monkeypatch): + from coderag.cli import cli + + async def search_hybrid(**kwargs): + assert kwargs == { + "repo_id": "repo-ready", + "query": "auth flow", + "top_k": 2, + "max_tokens": 512, + "max_chunks_per_file": 1, + } + return { + "results": [ + { + "chunk_id": "chunk-1", + "file_path": "src/auth.py", + "start_line": 10, + "end_line": 12, + "citation": "[src/auth.py:10-12]", + "retrieval_sources": ["semantic", "lexical"], + "score_breakdown": {"combined": 0.91}, + "content": "def login(): pass", + } + ], + "count": 1, + } + + monkeypatch.setitem( + __import__("sys").modules, + "coderag.mcp.handlers", + SimpleNamespace(get_mcp_handlers=lambda: SimpleNamespace(search_hybrid=search_hybrid)), + ) + + result = CliRunner().invoke( + cli, + [ + "search-hybrid", + "repo-ready", + "auth flow", + "--top-k", + "2", + "--max-tokens", + "512", + "--max-chunks-per-file", + "1", + "--format", + "json", + ], + ) + + assert result.exit_code == 0 + payload = json.loads(result.output) + assert payload["count"] == 1 + assert payload["results"][0]["citation"] == "[src/auth.py:10-12]" + + +def test_readme_positions_verified_context_engine_without_production_overclaim(): + readme = __import__("pathlib").Path("README.md").read_text() + + assert "verified codebase context engine" in readme + assert "not an autonomous coding agent" in readme + assert "Production readiness" in readme + assert "Unsupported graph languages degrade explicitly" in readme + assert "production-ready" not in readme.lower().replace("not production-ready", "") From f10acb865fea7d3f0d92e01ffb688f02ddaf3f2c Mon Sep 17 00:00:00 2001 From: Sebastiangmz Date: Tue, 30 Jun 2026 15:40:35 -0600 Subject: [PATCH 2/3] feat: stabilize production interface surfaces Spec-Slice: CRAG-20260630-M6-PRODUCTION-INTERFACES --- README.md | 75 ++++++++++++++++++++++++++----------- src/coderag/api/routes.py | 40 ++++++++++++++++++++ src/coderag/api/schemas.py | 35 +++++++++++++++++ src/coderag/cli.py | 38 +++++++++++++++++++ src/coderag/mcp/handlers.py | 1 + 5 files changed, 168 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index afc4ebc..17e366e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# CodeRAG - Code Q&A with Verifiable Citations +# CodeRAG - Verified Codebase Context Engine [![PyPI version](https://badge.fury.io/py/code-rag-me.svg)](https://pypi.org/project/code-rag-me/) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -RAG-based Q&A system for code repositories that provides grounded answers with verifiable citations. +CodeRAG is a verified codebase context engine for agents and developers. It indexes repositories, retrieves grounded code context, verifies citations against retrieved chunks, and exposes the results through CLI, REST, MCP, and a local web UI. It is not an autonomous coding agent and does not edit repositories. ## 🚀 Quick Start @@ -34,26 +34,32 @@ Now you can use CodeRAG directly in Claude Desktop! ## ✨ Features -- **Grounded Responses**: Every answer includes citations to source code `[file:start-end]` -- **Cloud or Local LLM**: Use Groq (free), OpenAI, Anthropic, or run locally with GPU -- **GitHub Integration**: Index any public GitHub repository -- **MCP Support**: Integrate directly with Claude Desktop -- **Semantic Chunking**: Tree-sitter for Python, text fallback for other languages -- **Web Interface**: Gradio UI for easy interaction -- **REST API**: Programmatic access for integration -- **CLI**: Full command-line interface +- **Verified citations**: Answers include citations like `[file:start-end]` and expose verification status. +- **Hybrid retrieval and context packs**: Combine semantic and lexical retrieval without requiring generation. +- **Code graph intelligence**: Python and TypeScript/JavaScript symbols, references, and blast-radius evidence are indexed when supported. +- **Cloud or local LLM**: Use Groq, OpenAI, Anthropic, OpenRouter, Together, or explicitly configured local models. +- **GitHub indexing**: Index public GitHub repositories with durable SQLite registry/job state. +- **MCP support**: Expose indexing, retrieval, context, and graph tools to MCP clients. +- **REST API and CLI**: Programmatic and terminal access to the same core capabilities. +- **Local web interface**: Gradio UI for local exploration. ## 📋 CLI Commands ```bash -coderag setup # Configure LLM provider and API key -coderag serve # Start web server -coderag mcp-install # Configure Claude Desktop for MCP -coderag mcp-run # Run MCP server (used by Claude Desktop) -coderag index # Index a GitHub repository -coderag query "?" # Ask a question about code -coderag repos # List indexed repositories -coderag doctor # Diagnose setup issues +coderag setup # Configure LLM provider and API key +coderag serve # Start local web/API/MCP server +coderag mcp-install # Configure Claude Desktop for MCP +coderag mcp-run # Run MCP server over stdio +coderag index # Index a GitHub repository +coderag update # Incrementally update an indexed repository +coderag query "?" # Ask a question with citations +coderag search-hybrid "query" # Retrieve hybrid code context without generation +coderag context-pack "query" # Build an agent-ready context pack +coderag find-symbol # Find indexed graph symbols +coderag find-references # Find indexed symbol references +coderag blast-radius # Show graph-backed impacted files/tests +coderag repos # List indexed repositories +coderag doctor # Diagnose setup issues ``` ## 🔧 Installation @@ -229,8 +235,17 @@ This will prompt you to: # Index a repository coderag index https://github.com/owner/repo -# Ask questions -coderag query abc12345 "How does authentication work?" +# Ask questions with citation verification metadata +coderag query abc12345 "How does authentication work?" --format json + +# Retrieve context without calling an LLM +coderag search-hybrid abc12345 "authentication flow" --format json +coderag context-pack abc12345 "authentication flow" + +# Inspect graph evidence +coderag find-symbol abc12345 AuthService --format json +coderag find-references abc12345 validate_token --format json +coderag blast-radius abc12345 validate_token --format json # List repositories coderag repos @@ -244,10 +259,20 @@ curl -X POST http://localhost:8000/api/v1/repos/index \ -H "Content-Type: application/json" \ -d '{"url": "https://github.com/owner/repo"}' -# Query +# Query with citation verification curl -X POST http://localhost:8000/api/v1/query \ -H "Content-Type: application/json" \ -d '{"question": "How does X work?", "repo_id": "abc12345"}' + +# Hybrid retrieval without generation +curl -X POST http://localhost:8000/api/v1/search-hybrid \ + -H "Content-Type: application/json" \ + -d '{"query": "authentication flow", "repo_id": "abc12345", "top_k": 5}' + +# Graph-backed blast radius +curl -X POST http://localhost:8000/api/v1/graph/blast-radius \ + -H "Content-Type: application/json" \ + -d '{"symbol": "validate_token", "repo_id": "abc12345"}' ``` ### Claude Desktop (MCP) @@ -290,6 +315,14 @@ SERVER_PORT=8000 Configuration is stored in `~/.config/coderag/config.json` after running `coderag setup`. +## Production readiness + +Current release-candidate work is evidence-gated. The supported default is local loopback (`127.0.0.1`) with user-configured model credentials. Binding to public interfaces requires explicit host, trusted CORS origins, authentication, and network controls outside CodeRAG's defaults. + +- Cloud LLM providers send prompt context to the selected provider. Use local/private profiles only when configured and verified for your environment. +- Unsupported graph languages degrade explicitly to text/chunk retrieval; they do not report fake graph confidence. +- CodeRAG verifies citations against retrieved chunks, but it does not prove repository correctness, execute arbitrary project tests, or make autonomous code changes. + ## 🏗️ Architecture ``` diff --git a/src/coderag/api/routes.py b/src/coderag/api/routes.py index 8a9ed66..6d042b7 100644 --- a/src/coderag/api/routes.py +++ b/src/coderag/api/routes.py @@ -16,6 +16,9 @@ GraphQueryRequest, GraphReferenceResponse, GraphSymbolResponse, + HybridSearchRequest, + HybridSearchResponse, + HybridSearchResultResponse, IndexRepositoryRequest, IndexRepositoryResponse, ListRepositoriesResponse, @@ -218,6 +221,43 @@ async def context_pack(request: ContextPackRequest) -> ContextPackResponse: ) +@router.post("/search-hybrid", response_model=HybridSearchResponse) +async def search_hybrid(request: HybridSearchRequest) -> HybridSearchResponse: + """Run hybrid retrieval without LLM generation.""" + repo = get_repo_or_404(request.repo_id) + try: + results = retrieval_service.search_hybrid( + repo.id, + request.query, + top_k=request.top_k, + max_tokens=request.max_tokens, + max_chunks_per_file=request.max_chunks_per_file, + ) + except ValueError as exc: + raise HTTPException(status_code=400, detail=str(exc)) from exc + return HybridSearchResponse( + results=[ + HybridSearchResultResponse( + chunk_id=chunk.chunk_id, + file_path=chunk.file_path, + start_line=chunk.start_line, + end_line=chunk.end_line, + citation=chunk.citation, + chunk_type=chunk.chunk_type, + name=chunk.name, + content=chunk.content, + relevance_score=chunk.relevance_score, + score_breakdown=chunk.score_breakdown, + retrieval_sources=chunk.retrieval_sources, + token_estimate=chunk.token_estimate, + ranking_reason=chunk.ranking_reason, + ) + for chunk in results + ], + count=len(results), + ) + + @router.post("/graph/find-symbol", response_model=FindSymbolResponse) def find_symbol(request: GraphQueryRequest) -> FindSymbolResponse: """Find graph symbols by name.""" diff --git a/src/coderag/api/schemas.py b/src/coderag/api/schemas.py index 7f75694..d0d8080 100644 --- a/src/coderag/api/schemas.py +++ b/src/coderag/api/schemas.py @@ -123,6 +123,41 @@ class ContextPackResponse(BaseModel): capabilities: dict[str, object] + +class HybridSearchRequest(BaseModel): + """Request to run hybrid retrieval without generation.""" + + repo_id: str = Field(..., description="Repository ID to search") + query: str = Field(..., description="Search query") + top_k: int = Field(10, ge=1, le=20, description="Maximum results to include") + max_tokens: int = Field(4000, ge=1, description="Maximum token estimate") + max_chunks_per_file: int = Field(3, ge=1, description="Maximum results per file") + + +class HybridSearchResultResponse(BaseModel): + """A hybrid retrieval result.""" + + chunk_id: str + file_path: str + start_line: int + end_line: int + citation: str + chunk_type: str + name: str | None = None + content: str + relevance_score: float = 0.0 + score_breakdown: dict[str, float] = Field(default_factory=dict) + retrieval_sources: list[str] = Field(default_factory=list) + token_estimate: int = 0 + ranking_reason: str | None = None + + +class HybridSearchResponse(BaseModel): + """Hybrid retrieval response.""" + + results: list[HybridSearchResultResponse] + count: int + class GraphQueryRequest(BaseModel): """Request for graph symbol queries.""" diff --git a/src/coderag/cli.py b/src/coderag/cli.py index d07860f..142d8aa 100644 --- a/src/coderag/cli.py +++ b/src/coderag/cli.py @@ -390,6 +390,44 @@ async def run_query(): +@cli.command("search-hybrid") +@click.argument("repo_id") +@click.argument("query_text") +@click.option("--top-k", default=10, type=int, help="Maximum results to include") +@click.option("--max-tokens", default=4000, type=int, help="Maximum token estimate") +@click.option("--max-chunks-per-file", default=3, type=int, help="Maximum results per file") +@click.option("--format", "output_format", type=click.Choice(["text", "json"]), default="text", help="Output format") +def search_hybrid(repo_id: str, query_text: str, top_k: int, max_tokens: int, max_chunks_per_file: int, output_format: str): + """Run hybrid retrieval without LLM generation.""" + _apply_config_to_env() + + import asyncio + + from coderag.mcp.handlers import get_mcp_handlers + + async def run_search_hybrid(): + return await get_mcp_handlers().search_hybrid( + repo_id=repo_id, + query=query_text, + top_k=top_k, + max_tokens=max_tokens, + max_chunks_per_file=max_chunks_per_file, + ) + + result = asyncio.run(run_search_hybrid()) + if result.get("error"): + click.echo(f"❌ Error: {result['error']}") + sys.exit(1) + if output_format == "json": + click.echo(json.dumps(result, indent=2)) + return + click.echo(f"Hybrid results for {query_text}: {result.get('count', 0)}") + for chunk in result.get("results", []): + citation = chunk.get("citation") or f"[{chunk['file_path']}:{chunk['start_line']}-{chunk['end_line']}]" + sources = ", ".join(chunk.get("retrieval_sources", [])) or "none" + click.echo(f"- {citation} sources={sources}") + + @cli.command("context-pack") @click.argument("repo_id") @click.argument("query_text") diff --git a/src/coderag/mcp/handlers.py b/src/coderag/mcp/handlers.py index 6f5d4ed..91560e2 100644 --- a/src/coderag/mcp/handlers.py +++ b/src/coderag/mcp/handlers.py @@ -42,6 +42,7 @@ def _retrieved_chunk_dict(chunk: Any) -> dict[str, Any]: "file_path": _read_field(chunk, "file_path"), "start_line": _read_field(chunk, "start_line"), "end_line": _read_field(chunk, "end_line"), + "citation": f"[{_read_field(chunk, 'file_path')}:{_read_field(chunk, 'start_line')}-{_read_field(chunk, 'end_line')}]", "chunk_type": _read_field(chunk, "chunk_type"), "name": _read_field(chunk, "name"), "content": _read_field(chunk, "content"), From dae290d0ae5d266e57ff5e691fc61c827e7e5b86 Mon Sep 17 00:00:00 2001 From: Sebastiangmz Date: Tue, 30 Jun 2026 15:40:40 -0600 Subject: [PATCH 3/3] ci: extend Milestone 6 validation gates Spec-Slice: CRAG-20260630-M6-PRODUCTION-INTERFACES --- .github/workflows/ci.yml | 14 +++--- .pi/.specsafe-state.json | 20 +++++++++ evals/config.json | 96 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99ac0bb..715c531 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,17 +25,17 @@ jobs: python -m pip install -e . --no-deps python -m pip install pytest pytest-asyncio pydantic pydantic-settings click PyYAML fastapi structlog ruff mypy mcp httpx - - name: Run Milestone 0-5 tests - run: PYTHONPATH=src python -m pytest tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_mcp_tools.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py + - name: Run Milestone 0-6 tests + run: PYTHONPATH=src python -m pytest tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_mcp_tools.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py tests/test_m6_interfaces_docs.py - - name: Run Milestone 0-5 lint baseline - run: ruff check src/coderag/generation src/coderag/indexing/vectorstore.py src/coderag/models src/coderag/retrieval src/coderag/graph src/coderag/services src/coderag/config.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/mcp/tools.py src/coderag/cli.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_mcp_tools.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py scripts/evalfly_smoke.py + - name: Run Milestone 0-6 lint baseline + run: ruff check src/coderag/generation src/coderag/indexing/vectorstore.py src/coderag/models src/coderag/retrieval src/coderag/graph src/coderag/services src/coderag/config.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/mcp/tools.py src/coderag/cli.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_mcp_tools.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py tests/test_m6_interfaces_docs.py scripts/evalfly_smoke.py - - name: Run Milestone 0-5 type baseline - run: PYTHONPATH=src mypy src/coderag/generation src/coderag/indexing/vectorstore.py src/coderag/models src/coderag/retrieval src/coderag/graph src/coderag/services src/coderag/config.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py scripts/evalfly_smoke.py + - name: Run Milestone 0-6 type baseline + run: PYTHONPATH=src mypy src/coderag/generation src/coderag/indexing/vectorstore.py src/coderag/models src/coderag/retrieval src/coderag/graph src/coderag/services src/coderag/config.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_mcp_handlers.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py tests/test_m6_interfaces_docs.py scripts/evalfly_smoke.py - name: Compile changed runtime modules - run: python -m py_compile src/coderag/__init__.py src/coderag/config.py src/coderag/main.py src/coderag/cli.py src/coderag/indexing/embeddings.py src/coderag/indexing/vectorstore.py src/coderag/generation/*.py src/coderag/models/*.py src/coderag/retrieval/*.py src/coderag/graph/*.py src/coderag/services/*.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/mcp/tools.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py scripts/evalfly_smoke.py + run: python -m py_compile src/coderag/__init__.py src/coderag/config.py src/coderag/main.py src/coderag/cli.py src/coderag/indexing/embeddings.py src/coderag/indexing/vectorstore.py src/coderag/generation/*.py src/coderag/models/*.py src/coderag/retrieval/*.py src/coderag/graph/*.py src/coderag/services/*.py src/coderag/api/schemas.py src/coderag/api/routes.py src/coderag/mcp/handlers.py src/coderag/mcp/tools.py src/coderag/ui/grounding.py src/coderag/ui/repository_metadata.py src/coderag/ui/handlers.py tests/test_m0_baseline.py tests/test_m1_services.py tests/test_m2_registry.py tests/test_citations.py tests/test_m3_citations.py tests/test_api_routes.py tests/test_ui_handlers.py tests/test_m4_hybrid_retrieval.py tests/test_m5_code_graph.py tests/test_m6_interfaces_docs.py scripts/evalfly_smoke.py - name: Build package run: python -m build diff --git a/.pi/.specsafe-state.json b/.pi/.specsafe-state.json index 15acb51..d050397 100644 --- a/.pi/.specsafe-state.json +++ b/.pi/.specsafe-state.json @@ -159,6 +159,26 @@ "turns": 0 } } + }, + { + "sliceId": "CRAG-20260630-M6-PRODUCTION-INTERFACES", + "workspaceId": "CodeRAG", + "sessionId": "omp-session", + "beganAt": "2026-06-30T21:35:47.487Z", + "endedAt": "2026-06-30T21:40:17.045Z", + "outcome": "PASS", + "costSummary": { + "externalMemoryCalls": 0, + "externalMemoryCost": 0, + "subagentTokens": { + "input": 0, + "output": 0, + "cacheRead": 0, + "cacheWrite": 0, + "cost": 0, + "turns": 0 + } + } } ] } diff --git a/evals/config.json b/evals/config.json index 7b14e55..cbee5f1 100644 --- a/evals/config.json +++ b/evals/config.json @@ -770,6 +770,102 @@ } ] } + }, + { + "schema_version": "evalfly.case.v1", + "case_id": "m6-production-interfaces-contract-exists", + "title": "Milestone 6 production interfaces contract exists", + "suite": "smoke", + "risk_tier": "critical", + "task_type": "delivery_governance", + "source": { + "kind": "acceptance_criteria", + "criteria": "M6-AC1 M6-AC2 M6-AC3 M6-AC4" + }, + "privacy": { + "classification": "public", + "sanitized": true + }, + "expected": { + "success_criteria": [ + "The Milestone 6 interface and documentation contract is committed." + ] + }, + "judge": { + "type": "deterministic", + "assertions": [ + { + "type": "file_exists", + "path": "docs/superpowers/plans/2026-06-30-m6-production-interfaces-contract.md" + } + ] + } + }, + { + "schema_version": "evalfly.case.v1", + "case_id": "m6-hybrid-search-interface-exists", + "title": "Hybrid search interface exists across adapters", + "suite": "smoke", + "risk_tier": "critical", + "task_type": "adapter_contract", + "source": { + "kind": "acceptance_criteria", + "criteria": "M6-AC1 M6-AC2" + }, + "privacy": { + "classification": "public", + "sanitized": true + }, + "expected": { + "success_criteria": [ + "REST and CLI expose hybrid retrieval without generation." + ] + }, + "judge": { + "type": "deterministic", + "assertions": [ + { + "type": "file_contains", + "path": "src/coderag/api/routes.py", + "text": "@router.post(\"/search-hybrid\"" + }, + { + "type": "file_contains", + "path": "src/coderag/cli.py", + "text": "@cli.command(\"search-hybrid\")" + } + ] + } + }, + { + "schema_version": "evalfly.case.v1", + "case_id": "m6-targeted-tests-exist", + "title": "Milestone 6 targeted interface tests exist", + "suite": "smoke", + "risk_tier": "critical", + "task_type": "test_coverage", + "source": { + "kind": "acceptance_criteria", + "criteria": "M6-AC2 M6-AC3 M6-AC4" + }, + "privacy": { + "classification": "public", + "sanitized": true + }, + "expected": { + "success_criteria": [ + "Targeted interface and README contract tests are committed." + ] + }, + "judge": { + "type": "deterministic", + "assertions": [ + { + "type": "file_exists", + "path": "tests/test_m6_interfaces_docs.py" + } + ] + } } ] }