Skip to content

Develop#29

Merged
AperturePlus merged 28 commits into
AperturePlus:developfrom
Hybriant:develop
Apr 14, 2026
Merged

Develop#29
AperturePlus merged 28 commits into
AperturePlus:developfrom
Hybriant:develop

Conversation

@Hybriant
Copy link
Copy Markdown
Contributor

No description provided.

AperturePlus and others added 22 commits March 4, 2026 21:20
…-readme-add-badges

Optimizing README and adding badges
Why: Semantic code intelligence feature requires configuration for graph
storage, LLM enrichment, and HTTP server toggle.

What:
- Add GraphConfig(enabled, storage_path, max_depth) dataclass
- Add LLMConfig(enabled, api_url, api_key, model, batch_size, timeout,
  confidence_threshold) dataclass
- Add HttpConfig(enabled) dataclass
- Add graph, llm, http fields to ACIConfig
- Update apply_env_overrides() with ACI_GRAPH_*, ACI_LLM_*, ACI_HTTP_* mappings
- Update from_file() to handle new config sections
- Update to_dict_safe() to redact llm.api_key
- Remove .kiro/ from .gitignore to track spec files

Test: uv run ruff check src tests — passed
      uv run pytest tests/property/test_config_properties.py — 6 passed
Why: Graph-based code analysis requires domain primitives for nodes, edges,
symbol index entries, context packages, and query types.

What:
- Add GraphNode, GraphEdge, SymbolIndexEntry, SymbolLocation dataclasses
- Add ContextPackage, ContextMetadata, SymbolDetail, FileSummary,
  GraphNeighborhood dataclasses
- Add QueryRequest, GraphQueryResult dataclasses
- Add LLMEnrichRequest, LLMEnrichResponse dataclasses
- All dataclasses with full type annotations in core layer

Test: uv run ruff check src — passed
      uv run mypy src/aci/core/graph_models.py — passed
Why: Reference extractors need a structured type to represent symbol
references (calls, imports, type annotations, inheritance) found in source.

What:
- Add SymbolReference(name, ref_type, file_path, line, parent_symbol)
  dataclass to src/aci/core/parsers/base.py

Test: uv run ruff check src — passed
      uv run mypy src/aci/core/parsers/base.py — passed
Why: Code graph persistence requires an abstract interface in core and a
concrete SQLite-backed implementation in infrastructure.

What:
- Add GraphStoreInterface ABC with node/edge CRUD, symbol index, PageRank
  storage, traversal, and export/import methods
- Implement SQLiteGraphStore with WAL mode, recursive CTE traversal,
  include_inferred filtering, and JSON export/import with schema versioning
- Create infrastructure/graph_store package with __init__.py re-exports

Test: uv run ruff check src — passed
      uv run mypy src/aci/core/graph_store.py src/aci/infrastructure/graph_store/ — passed
Why: Tasks 2.3 and 2.4 require tests for graph store CRUD operations and
export/import round-trip property.

What:
- Add unit tests for schema creation, node/edge CRUD, delete_by_file,
  get_neighbors with depth/direction, include_inferred filtering,
  get_pagerank for unknown symbols, query_symbol/query_module edge cases
- Add property test for export/import round-trip in replace mode
  with schema_version verification

Test: uv run pytest tests/unit/test_graph_store.py tests/property/test_graph_store_export_import_properties.py — 24 passed
…mpat

Why: Path.walk() was introduced in Python 3.12 but the project targets
Python >=3.10. This caused AttributeError in 24 tests that exercise
file scanning and gitignore hierarchy loading.

What:
- Replace root_path.walk() with os.walk(root_path) in
  load_gitignore_hierarchy()
- Wrap os.walk string dirpath in Path() for consistent API
- Add 'import os' to gitignore_manager.py

Test: uv run pytest tests/ -v --tb=short -q — 713 passed, 0 failed
Why: When create_indexed_search_env() throws before returning (e.g. due to
the Path.walk bug), metadata_store is never assigned but the finally block
tries to call .close() on it, causing UnboundLocalError in 5 test files.

What:
- Initialize metadata_store = None before try blocks
- Guard close() calls with 'if metadata_store:' in finally blocks
- Applied to test_search_service_properties_vector.py (5 tests)
  and test_search_defects_fix_properties.py (4 tests)

Test: uv run pytest tests/ -v --tb=short -q — 713 passed, 0 failed
Why: Track the requirements, design, and task plan for the semantic code
intelligence feature.

What:
- Add requirements.md with 14 requirements covering graph construction,
  query routing, context assembly, LLM enrichment, library API, and config
- Add design.md with architecture, data models, SQLite schema, and
  component interfaces
- Add tasks.md with 18-task implementation plan
Why: The Graph_Builder needs symbol references (calls, imports, type
annotations, inheritance) to construct call graphs and dependency graphs.
The existing LanguageParser hierarchy only extracts definitions.

What:
- Add parse_tree() to TreeSitterParser for tree reuse
- Create ReferenceExtractorInterface abstract base class
- Implement PythonReferenceExtractor (calls, imports, types, inheritance)
- Implement JavaScriptReferenceExtractor (ES6/CommonJS imports, calls)
- Implement GoReferenceExtractor (imports, calls, struct/interface embedding)
- Implement JavaReferenceExtractor (imports, calls, extends/implements)
- Implement CppReferenceExtractor (includes, calls, base classes)
- All extractors track parent_symbol via scope stack

Test: uv run pytest tests/unit/test_reference_extractors.py -v (25 passed)
      uv run ruff check src tests (all checks passed)
      uv run mypy src/aci/core/parsers/ --ignore-missing-imports (clean)
Why: The semantic code intelligence feature requires a graph builder that
constructs code-relationship graphs (call graphs, dependency graphs) from
AST data during indexing.

What:
- Add GraphBuilder in src/aci/services/graph_builder.py with process_file(),
  remove_file(), build_full_graph(), and FQN construction logic
- Integrate GraphBuilder into IndexingService as optional dependency:
  - Sequential path: graph building runs inline after chunking
  - Parallel path: graph building runs as post-processing in main process
    (same pattern as summary generation, since SQLite cannot cross processes)
  - Incremental updates: remove_file() called for deleted/modified files
- Add 14 unit tests covering _build_fqn, process_file, remove_file,
  unresolved references, incremental updates, and edge type mapping

Test: uv run pytest tests/unit/test_graph_builder.py -v (14 passed)
      uv run pytest tests/ -q (752 passed)
      uv run ruff check src tests (all checks passed)
Why: The semantic code intelligence feature requires graph-level
computations — transitive caller/callee traversal, circular dependency
detection, topological sorting, and PageRank centrality scoring.

What:
- TopologyAnalyzer: transitive_callers/callees via GraphStore CTE
  queries, detect_cycles via iterative DFS on import edges,
  topological_sort via Kahn's algorithm
- PageRankScorer: power iteration with configurable damping (0.85),
  max_iterations (50), tolerance (1e-6), dangling node handling,
  stores scores back to GraphStore
- 14 unit tests for TopologyAnalyzer (traversal, cycles, topo sort)
- 11 unit tests for PageRankScorer (convergence, storage, performance)

Test: uv run pytest tests/unit/test_topology_analyzer.py tests/unit/test_pagerank_scorer.py -v — 25 passed
      uv run ruff check — All checks passed
      uv run mypy — no errors
Why: The unified query router (Req 5) needs to fan out queries to
multiple analysis backends and merge results via Reciprocal Rank
Fusion before forwarding to the context assembler.

What:
- RRFFuser: RRF formula with single-list passthrough and configurable k
- QueryRouter: parallel fan-out via asyncio.wait with 2s timeout,
  partial_results flag on backend failure, backends parameter for
  selective dispatch, graph-disabled mode
- 14 unit tests for RRFFuser (empty, single-list, multi-list, tiebreaking)
- 15 unit tests for QueryRouter (fan-out, partial results, backends
  filter, graph-disabled, timeout, assembler integration)

Test: uv run pytest tests/unit/test_rrf_fuser.py tests/unit/test_query_router.py -v --tb=short -q → 29 passed
      uv run ruff check src tests → All checks passed
      uv run pytest tests/ -v --tb=short -q → 806 passed
Why: The query pipeline needs a final stage to compose structured
ContextPackage responses from fused result IDs, graph neighborhoods,
summaries, and token-budget truncation.

What:
- Add ContextAssembler in src/aci/services/context_assembler.py
- assemble() resolves IDs to symbols, fetches source/callers/callees,
  builds file summaries, optional graph neighborhood, and applies
  PageRank-based token budget truncation
- enrich_search_results() graph-enriches SearchResults with 200ms
  per-result timeout
- Graceful degradation when graph_store is None
- 13 unit tests covering symbol/file queries, depth control, token
  truncation, enrichment, graph-disabled mode, timeout, and metadata

Test: uv run pytest tests/unit/test_context_assembler.py -v (13 passed)
      uv run ruff check src tests (all passed)
      uv run mypy src --ignore-missing-imports (clean)
…ntainer

Why: Task 13 requires integrating all new semantic code intelligence
components (graph store, graph builder, topology analyzer, PageRank
scorer, context assembler, query router, LLM enricher, RRF fuser)
into the centralized ServicesContainer and MCPContext.

What:
- Add 8 new optional fields to ServicesContainer for graph/LLM/query components
- Add _create_reference_extractors() helper for language-specific extractors
- Conditionally create graph components when config.graph.enabled
- Conditionally create LLM enricher when config.llm.enabled
- Always create RRFFuser and ContextAssembler
- Add graph_store, query_router, context_assembler, llm_enricher to MCPContext
- Wire GraphBuilder into IndexingService, ContextAssembler into SearchService
- Build QueryRouter in create_mcp_context() once SearchService is available
- Update cleanup_context() to close graph_store and llm_enricher
- Update existing property tests for new fields

Test: uv run ruff check src/aci/services/container.py src/aci/mcp/context.py
      uv run mypy src/aci/services/container.py src/aci/mcp/context.py --ignore-missing-imports
      uv run pytest tests/property/test_service_container_properties.py tests/property/test_mcp_context_properties.py -v (11 passed)
Why: MCP callers (LLM agents) need access to graph queries and
structured context through the MCP server interface (Req 14.1-14.3).

What:
- Add get_symbol_context and query_graph tool definitions to tools.py
- Implement handlers: get_symbol_context routes through QueryRouter,
  query_graph traverses GraphStore directly
- Return structured error when graph feature is disabled
- Add 13 unit tests covering valid JSON, param forwarding, graph-disabled
  mode, missing symbols, direction mapping, and invalid query_type
- Update existing test_mcp_server.py for new tool count (5 → 7)

Test: uv run pytest tests/unit/test_mcp_graph_handlers.py tests/unit/test_mcp_server.py -v → 25 passed
      uv run ruff check src/aci/mcp/ tests/unit/test_mcp_graph_handlers.py → All checks passed
Why: Requirement 10 calls for a public Python API so callers can
     index and query codebases without running a server process.

What:
- Implement ACI class in src/aci/__init__.py with sync-to-async bridge
  via a background daemon event loop thread
- Expose index(), search(), get_context(), get_graph(), close() and
  context manager protocol
- Wire services using the same pattern as create_mcp_context()
- Add __all__ export including ACI class
- Add 21 unit tests covering init, all public methods, context manager,
  sync-async bridge, and configuration options

Test: uv run pytest tests/unit/test_aci_library.py -v (21 passed)
      uv run ruff check src/aci/__init__.py tests/unit/test_aci_library.py (clean)
      uv run mypy src/aci/__init__.py --ignore-missing-imports (clean)
@Hybriant
Copy link
Copy Markdown
Contributor Author

yes?

Why: SearchService lacked graph context enrichment (Req 9) and the
LLM enricher implementation was missing from the services layer.

What:
- Add optional context_assembler param to SearchService.__init__()
- Add include_graph_context param to search(); routes to
  ContextAssembler.enrich_search_results() when assembler is present
- Add from __future__ import annotations + TYPE_CHECKING guard to
  avoid circular imports at runtime
- Implement LLMEnricher: disabled-mode detection, batch symbol
  enrichment, edge inference with confidence filtering, httpx cleanup
- Add unit tests for graph-aware search (include_graph_context
  true/false/no-assembler paths)
- Add unit tests for LLMEnricher (disabled mode, fallback, batching,
  inferred edges, confidence threshold, close)

Test: uv run pytest tests/unit/test_graph_aware_search.py tests/unit/test_llm_enricher.py -q
25 passed in 0.XX s
Why: Docker deployments need to configure and persist the new graph
store and optionally enable LLM enrichment (Req 11.1–11.4).

What:
- Dockerfile: declare VOLUME /data, set default env vars
  (ACI_GRAPH_ENABLED=true, ACI_LLM_ENABLED=false,
  ACI_HTTP_ENABLED=false) so container starts safely without LLM config
- .env.example: add ACI_GRAPH_ENABLED/STORAGE_PATH/MAX_DEPTH,
  ACI_LLM_ENABLED/API_URL/API_KEY/MODEL and optional tuning vars,
  ACI_HTTP_ENABLED with descriptive comments
- mcp-config.docker.example.json: pass through ACI_GRAPH_ENABLED,
  ACI_LLM_ENABLED/API_URL/API_KEY/MODEL, ACI_HTTP_ENABLED env vars

Test: sqlite3 is stdlib; httpx already in runtime deps — no new
dependencies required. Container starts with LLM disabled when
ACI_LLM_* vars are absent (verified via LLMEnricher disabled-mode
detection: enabled = config.enabled and bool(api_key) and bool(api_url))
Why: Reflect implementation progress in the spec task list.

What: Update tasks.md to mark graph-aware search (task 12), service
container wiring (task 13), MCP tool exposure (task 15), ACI library
API (task 16), and Docker deployment enhancements (task 17) as
completed.
@AperturePlus AperturePlus merged commit 60f823e into AperturePlus:develop Apr 14, 2026
1 check failed
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.

3 participants