Skip to content

Latest commit

 

History

History
991 lines (778 loc) · 68.5 KB

File metadata and controls

991 lines (778 loc) · 68.5 KB

Tests Implementation Plan

Tests live primarily in codeagent-engine/crates/codeagent-core/src/, with additional tests in codeagent-mcp (MCP server tools) and codeagent-cli (init + hooks). This document lists every test that has been (or should be) written, organised by the phase whose feature it exercises. Tests that cover infrastructure shared across multiple phases are filed under the earliest phase that requires them.


Status legend

Symbol Meaning
Implemented and passing
Planned — not yet written
🔁 Deferred — requires infrastructure not yet built

Phase-coverage summary

Phase Implemented Planned / Deferred
1 — Foundation 148 0
2a — Semantic enrichment 37 0
2b — Rename detection 23 0
3 — Embedding 17 0
Multi-file fixture (integration) 41 0
4a — Retrieval channels 20 0
4b — Merge, rerank, eval 28 0
5 — MCP server 24 0
6 — Hardening 28 0
OSS Integration Tests 30 0
Hooks, Dead Code & Init 17 0
ASP.NET Core API Boundary 33 0
Pipeline integration 7 0

Phase 1 — Foundation

Features: tree-sitter parsing, schema + migrations, graph CRUD, FTS5, path normalisation, type system, embedding text construction, query layer, basic incremental invalidation.


adapters/csharp

ID Test Description Status
T-001 test_csharp_extracts_namespace namespace Foo {} → Module node with symbol_key = "Foo:module"
T-002 test_csharp_extracts_class_with_method Class + method both extracted; method symbol_key includes param count and types
T-003 test_csharp_overload_distinct_symbol_keys Two methods with same name but different param lists → distinct symbol_key values
T-004 test_csharp_extracts_interface interface IFoo {} → Interface node
T-005 test_csharp_extracts_property public int Prop { get; set; } → Property node
T-006 test_csharp_generated_flag_propagated Node from a file matching a generated-glob pattern has generated = 1
T-007 test_csharp_parse_status_on_invalid_syntax Malformed C# does not panic; file node still emitted with parse_status = 'syntactic_only'
T-008 test_csharp_extracts_enum enum Status { … }NodeType::Type with symbol_key = "Status:type"
T-009 test_csharp_extracts_struct struct Point { … } routed through handle_class → Class node
T-010 test_csharp_nested_class_qualified_name Nested class receives fully-qualified name Outer.Inner:class; type-stack propagates correctly
T-011 test_csharp_extracts_constructor Constructor symbol_key includes param count, e.g. Widget.Widget:constructor:1(string)
T-013 test_csharp_deeply_nested_generics_signature_truncated Parameter signature with deeply-nested generics truncated at configured max_signature_length; stored value ends with "..."
T-420 test_csharp_reference_count_defaults_to_zero_in_phase1 Phase 1 tree-sitter indexing sets reference_count = 0 for all method nodes (not computed until semantic enrichment)

adapters/typescript

ID Test Description Status
T-014 test_ts_extracts_exported_function export function foo() → node with export_scope = "module", stored as node_type = 'method'
T-015 test_ts_extracts_interface export interface IService {} → Interface node
T-016 test_ts_non_exported_function_has_file_scope Non-exported function extracted with export_scope = "file"
T-017 test_ts_symbol_key_contains_file_id_segment Phase 1 TS symbol_key contains the file_id segment for module-scoped symbols
T-018 test_tsx_file_parses_without_error .tsx file with JSX parses without error
T-019 test_ts_file_node_emitted Indexing a .ts file produces a file node
T-020 test_ts_arrow_function_extracted_as_method const double = (n: number) => …node_type = 'method'
T-021 test_ts_class_method_extracted Class extracted + body method extracted as node_type = 'method'
T-022 test_ts_type_alias_extracted type UserId = stringNodeType::Type
T-023 test_ts_enum_extracted enum Direction { … }NodeType::Type
T-421 test_ts_reference_count_defaults_to_zero_in_phase1 Phase 1 tree-sitter indexing sets reference_count = 0 for all method nodes (not computed until semantic enrichment)
T-422 test_ts_same_named_exports_in_different_files_distinct_keys Two identically-named exported functions in different files produce distinct identity keys (file_id segment differs)
T-431 test_ts_interface_body_walked Interface method and property signatures extracted as child nodes

db/migrations

ID Test Description Status
T-025 test_migration_from_empty Empty DB → migrate to CURRENT_SCHEMA_VERSION
T-026 test_migration_idempotent Running run_migrations() twice is a no-op
T-027 test_downgrade_rejected DB at higher schema version → CoreError::SchemaTooNew
T-028 test_quick_check_passes_on_valid_db PRAGMA quick_check succeeds on a freshly migrated DB
T-029 test_schema_tables_exist All expected tables are present after migration 001
T-030 test_primary_span_partial_unique_index_exists idx_node_spans_one_primary partial unique index exists
T-031 test_node_identity_map_table_exists node_identity_map table present after migration 002
T-032 test_node_identity_map_index_exists idx_node_identity_map_old index exists after migration 002
T-033 test_node_identity_map_insert_and_query Row with BLOB(16) UUID columns can be inserted and queried back
T-034 test_schema_version_is_4 CURRENT_SCHEMA_VERSION == 4; DB reaches version 4 after all migrations (api_endpoints added by migration 004)

graph/nodes

ID Test Description Status
T-036 test_root_project_creation_and_idempotency ensure_root_project() creates self-referential project node; second call is a no-op
T-037 test_upsert_node_insert New node round-trips all fields via upsert_node()
T-039 test_c_sharp_overload_identity Two C# overloads coexist without a UNIQUE constraint violation
T-040 test_multi_span_chunk_hash_ordering Multi-span chunk_hash is order-independent (sorted by bytes ASC)
T-041 test_fts_insert_and_search After sync_fts_insert(), FTS MATCH query on name returns that node
T-042 test_fts_delete_on_node_removal After sync_fts_delete(), FTS query returns no results
T-043 test_fts_prefix_search 3-character prefix query (Pro*) returns the matching node
T-044 test_fts_update_replaces_old_name Re-inserting with a new display_name removes old name from FTS index
T-045 test_fts_dotted_name_is_single_token . is a tokenchar: AuthSvc.Login is one FTS token; plain AuthSvc does NOT match it
T-046 test_fts_at_verbatim_identifier_preserved @ is a tokenchar: @event is indexed and matchable as a single token
T-047 test_fts_underscore_identifier_preserved _ is a tokenchar: MY_CONST is indexed as one token
T-048 test_fts_dollar_identifier_preserved $ is a tokenchar: $scope is indexed as one token including the $ prefix
T-423 test_upsert_nodes_in_tx_panics_above_500 debug_assert fires when caller passes >500 nodes to upsert_nodes_in_tx (bounded write transactions invariant)
T-424 test_multi_project_same_symbol_name_coexists Identical symbol_key in two distinct projects coexists without UNIQUE violation (project_id differentiates)
T-425 test_parse_status_stays_syntactic_only_when_enrichment_skipped Node inserted with parse_status=syntactic_only retains that value until explicit upgrade to full

graph/edges

ID Test Description Status
T-049 test_edge_insert_and_query Edge inserted and retrieved by get_outgoing_edges() / get_incoming_edges()
T-050 test_on_delete_cascade_for_edges Deleting the source node cascade-deletes its edges
T-051 test_replace_semantic_edges_removes_stale replace_semantic_edges_in_tx() removes old exact edges and inserts the new set
T-052 test_replace_semantic_edges_preserves_out_of_scope_edges Approximate edges from nodes outside the scope survive the replacement
T-053 test_replace_semantic_edges_upgrades_approximate_to_exact Approximate edge for (A→B) upgraded to exact when semantic pass confirms the same edge
T-054 test_replace_semantic_edges_empty_new_set_removes_exact Empty new-edge slice removes all exact and approximate edges from the scope
T-055 test_delete_outgoing_edges_by_type_selects_only_matching_type delete_outgoing_edges_by_type(Calls) leaves References edges untouched
T-056 test_upsert_edge_insert_or_ignore_no_duplicate Calling upsert_edge twice produces exactly one row

graph/spans

ID Test Description Status
T-057 test_insert_span_roundtrip Span inserted via insert_span() is retrievable with all fields correct
T-058 test_replace_spans_replaces_old replace_spans() removes prior spans for a node and inserts the new set
T-059 test_primary_span_flag After replace_spans(), exactly one span has is_primary = 1
T-060 test_reassign_primary_span reassign_primary_span() flips the primary flag correctly without touching other nodes
T-061 test_replace_spans_on_empty_slice replace_spans() with an empty slice leaves no spans for the node
T-426 test_node_spans_file_id_cascade_deletes_orphaned_spans Directly deleting a file node CASCADE-deletes its node_spans rows (safety net independent of explicit deletion algorithm)

graph/deletion

ID Test Description Status
T-062 test_delete_file_removes_single_span_nodes Deleting a file removes all single-span nodes and their spans; journals each deleted node; edges cascade-delete
T-063 test_delete_file_preserves_multi_span_node Multi-span node not hard-deleted when only one of its files is removed; primary span reassigned
T-064 test_deletion_is_in_single_transaction Entire deletion sequence (spans → nodes → file node) executes atomically
T-065 test_journal_sweep sweep_deletion_journal() removes entries older than the configured TTL
T-066 test_journal_node_direct_roundtrip journal_node() writes all fields (including chunk_fingerprint bytes) to deletion_log
T-067 test_delete_symbol_journals_and_removes_node delete_symbol() writes a journal entry first, then hard-deletes the node
T-068 test_delete_file_no_orphaned_fts_rows After file deletion, fts_nodes has no rows for any deleted symbol's node_id

ingest/batch

ID Test Description Status
T-069 test_creates_before_deletes_ordering ChangeBatch always yields creates/modifications before deletes regardless of event order
T-070 test_deduplication_keeps_latest Multiple events for the same path are collapsed to the most recent

ingest/invalidation

ID Test Description Status
T-072 test_decision_matrix_calls_source_changed Calls + SourceNodeChangedRecomputeViaSemantic
T-073 test_decision_matrix_calls_target_body_only Calls + TargetBodyOnlyNoAction
T-074 test_decision_matrix_calls_node_id_preserved Calls + TargetNodeIdPreservedNodeIdPreserved
T-075 test_decision_matrix_calls_node_id_replaced Calls + TargetNodeIdReplacedCascadeRemoved
T-076 test_decision_matrix_contains_child_changed Contains + ContainerChildChangedRecomputeFromAst
T-077 test_decision_matrix_contains_method_body_only Contains + MethodBodyOnlyNoAction
T-078 test_decision_matrix_imports_source_changed Imports + SourceNodeChangedRecomputeFromAst
T-079 test_decision_matrix_semantic_context_recompute Any edge + SemanticContextChangedRecomputeSemanticEdges
T-080 test_needs_reindex_hash_changed needs_reindex() returns true when chunk_hash differs
T-081 test_decision_matrix_references_source_changed References + SourceNodeChangedRecomputeViaSemantic
T-082 test_decision_matrix_references_target_body_only References + TargetBodyOnlyNoAction
T-083 test_decision_matrix_references_target_node_id_replaced References + TargetNodeIdReplacedCascadeRemoved
T-084 test_decision_matrix_inherits_declaration_header_changed Inherits + DeclarationHeaderChangedRecomputeViaSemantic
T-085 test_decision_matrix_inherits_base_type_changed Inherits + BaseTypeChangedNoAction
T-086 test_decision_matrix_implements_declaration_header_changed Implements + DeclarationHeaderChangedRecomputeViaSemantic
T-087 test_decision_matrix_implements_base_type_changed Implements + BaseTypeChangedNoAction
T-088 test_decision_matrix_overrides_declaration_header_changed Overrides + DeclarationHeaderChangedRecomputeViaSemantic
T-089 test_decision_matrix_overrides_base_type_changed Overrides + BaseTypeChangedNoAction
T-090 test_decision_matrix_accepts_source_changed Accepts + SourceNodeChangedRecomputeViaSemantic (+ ProbableIfStructural)
T-091 test_decision_matrix_accepts_target_body_only Accepts + TargetBodyOnlyNoAction
T-092 test_decision_matrix_extends_source_changed Extends + SourceNodeChangedRecomputeViaSemantic
T-093 test_decision_matrix_extends_target_body_only Extends + TargetBodyOnlyNoAction
T-094 test_decision_matrix_default_fallback_is_no_action Any unspecified (edge_type, change_type) pair → NoAction

ingest/project_detection

ID Test Description Status
T-095 test_resolve_project_id_exact_dir File inside a project directory resolves to that project
T-096 test_resolve_project_id_falls_back_to_root File with no matching project resolves to the root
T-097 test_resolve_project_id_most_specific_wins File under nested projects resolves to the most deeply nested one
T-098 test_detect_csproj_project Directory with a .csproj file detected as a CSharp project
T-099 test_detect_package_json_project package.json → TypeScript project with correct display_name
T-100 test_detect_tsconfig_only_project tsconfig.json with no package.json → detected as TS project
T-101 test_detect_skips_node_modules node_modules/ subtrees not walked during detection
T-102 test_detect_nested_csproj_projects Two .csproj at different depths → two distinct detected projects
T-103 test_ensure_projects_in_db_idempotent Calling ensure_projects_in_db twice returns the same ProjectId both times

path

ID Test Description Status
T-104 test_to_posix_forward_slashes Windows backslashes converted to forward slashes
T-105 test_normalize_relative_path Leading separators stripped; backslashes converted
T-106 test_detect_language .csCSharp; .ts/.tsxTypeScript; others → None
T-107 test_is_generated Files matching configured glob patterns flagged as generated
T-108 test_is_semantic_context_file .csproj, tsconfig.json, package.json identified as semantic context files
T-109 test_glob_match Glob pattern matching works for common patterns
T-110 test_symlink_outside_repo_root_rejected Symlink pointing outside repo root → path rejected by verify_within_repo_root()
T-111 test_symlink_inside_repo_root_accepted_when_follow_enabled Symlink within repo root indexed when follow_symlinks = true; skipped when false

types

ID Test Description Status
T-112 test_language_roundtrip Language::as_str() / from_str() / Display consistent; unknown string → None
T-113 test_node_type_roundtrip All 10 NodeType variants round-trip through as_str()from_str()
T-114 test_edge_type_roundtrip All 9 EdgeType variants round-trip
T-115 test_edge_type_is_source_driven Calls, References, Overrides, Extendstrue; other 5 → false
T-116 test_edge_confidence_roundtrip All 3 EdgeConfidence variants round-trip
T-117 test_parse_status_roundtrip All 3 ParseStatus variants round-trip
T-118 test_access_modifier_roundtrip All 7 AccessModifier variants (incl. ProtectedInternal, Exported, Unexported) round-trip
T-119 test_export_scope_roundtrip All 3 ExportScope variants round-trip
T-121 test_content_hash_to_hex_all_zeroes All-zero hash → 64-char hex of "00"×32
T-122 test_content_hash_to_hex_known_value Known byte values produce expected hex characters
T-123 test_content_hash_from_bytes_roundtrip as_bytes()from_bytes() returns original ContentHash
T-124 test_content_hash_from_bytes_wrong_length 31, 33, and 0-byte slices all return None
T-125 test_content_hash_serde_roundtrip serde_json serialize → deserialize produces identical ContentHash; form is 64-char hex
T-126 test_node_id_from_bytes_roundtrip NodeId::as_bytes()from_bytes() round-trips
T-127 test_node_id_from_bytes_wrong_length 15 and 17-byte slices return None
T-128 test_file_id_and_project_id_roundtrip FileId and ProjectId both round-trip; wrong-length slices return None
T-129 test_node_id_to_string_repr_is_uuid_format to_string_repr() produces canonical 8-4-4-4-12 UUID format

embedding/onnx (text builders only — model load requires external files)

ID Test Description Status
T-130 test_build_embedding_text_no_boilerplate Symbol embedding text omits constant boilerplate
T-131 test_build_file_embedding_text File embedding text includes path, filename, and language
T-132 test_build_embedding_text_all_none_optionals All-None → output is just "qualified_name node_type"
T-133 test_build_embedding_text_empty_string_optionals_skipped Empty "" optional strings produce no extra tokens
T-134 test_build_embedding_text_doc_comment_truncated_at_200 Doc comments > 200 chars are truncated
T-135 test_build_file_embedding_text_no_slash_in_path Path with no / still extracts the filename correctly
T-136 test_build_file_embedding_text_empty_summary_omitted Empty import/export summary not included
T-137 test_build_file_embedding_text_doc_comment_truncated File doc comment truncated to 200 chars

query

ID Test Description Status
T-138 test_get_node_roundtrip Node written to DB → retrieved with all fields intact
T-139 test_get_node_not_found get_node() returns None for an unknown NodeId
T-140 test_get_neighbors_outgoing get_neighbors() returns correct outgoing edges and their target nodes
T-141 test_get_neighbors_incoming get_neighbors() returns correct incoming edges and their source nodes
T-142 test_get_source get_source() returns the primary span content for a node
T-143 test_get_outline get_outline() returns all child nodes of a file, ordered by line number
T-144 test_filter_nodes_sql filter_nodes() applies language, type, and text search filters correctly
T-145 test_get_node_by_qualified_name Node looked up by qualified_name
T-146 test_filter_nodes_fts_returns_bm25_rank FTS query in filter_nodes() populates rank field; results ordered best-first

Phase 2a — Semantic Enrichment

Features: Roslyn / TS Language Service IPC, identity reconciliation, semantic edge replacement, semantic-context invalidation.


ipc/manager

ID Test Description Status
T-149 test_csharp_unavailable_when_safe_mode_true safe_mode = true blocks C# even when the extractor path is set
T-150 test_csharp_available_when_safe_mode_false_and_path_set safe_mode = false + path set → C# available
T-151 test_csharp_unavailable_when_no_extractor_path csharp_extractor_path = None → C# unavailable regardless of safe_mode
T-152 test_typescript_available_regardless_of_safe_mode TypeScript availability not gated by safe_mode
T-153 test_typescript_unavailable_when_no_extractor_path typescript_extractor_path = None → TypeScript unavailable
T-154 test_default_config_both_languages_unavailable Default config (safe_mode=true, no paths) → both languages unavailable
T-432 test_parse_tfm_major_valid TFM major version parsing succeeds for net8.0 and net10.0
T-433 test_parse_tfm_major_rejects_invalid TFM parsing rejects netstandard and invalid formats
T-434 test_resolve_dll_picks_highest_available_runtime DLL resolution selects highest TFM with installed runtime
T-435 test_resolve_dll_falls_back_when_no_runtime_matches DLL resolution returns original path if no matching runtime
T-436 test_resolve_dll_not_under_tfm_dir_returns_as_is Non-TFM DLL paths returned unchanged
T-437 test_resolve_non_dll_returns_as_is Non-DLL files returned as-is by resolver
T-155 test_ipc_handshake_version_mismatch_triggers_fallback Protocol version mismatch during handshake → graceful fallback to syntactic-only mode
T-156 test_ipc_request_deadline_enforced IPC request that exceeds deadline → Timeout error code returned promptly
T-157 test_ipc_child_process_crash_clears_slot Child process exiting clears the slot so next request re-spawns
T-158 test_nuget_restore_blocked_when_allow_nuget_restore_false allow_nuget_restore = false → NuGet restore command not sent even when safe_mode = false
T-251 test_ipc_backpressure_error_when_child_queue_full Bounded semaphore at capacity → next request returns structured backpressure error rather than blocking indefinitely
T-252 test_ipc_cancel_inflight_request_does_not_write_edges Cancelling a request mid-flight prevents any edges from that enrichment request being committed
T-253 test_ipc_deadline_timeout_respects_max_retries IPC request exceeding deadline is retried up to the configured max-retries then returns a structured timeout error

ipc/protocol

ID Test Description Status
T-159 test_rpc_request_new_has_jsonrpc_2_0_field RpcRequest::new() sets jsonrpc = "2.0"
T-160 test_rpc_notification_has_empty_id RpcRequest::notification() produces empty id string
T-161 test_rpc_request_serializes_to_valid_json_rpc_2_0 Serialized JSON has correct jsonrpc, method, id fields
T-162 test_rpc_request_no_params_omitted_in_json params: None omitted via skip_serializing_if
T-163 test_ipc_error_code_from_code_all_variants All 5 IpcErrorCode variants decode from their integer codes
T-164 test_ipc_error_code_unknown_returns_none Unrecognised codes return None
T-165 test_parse_result_extracts_analyze_file_result parse_result<AnalyzeFileResult>() deserializes valid response
T-166 test_parse_result_returns_error_on_rpc_error_field parse_result returns Err when response has error field
T-167 test_parse_result_returns_error_when_no_result_and_no_error parse_result returns Err when both fields absent
T-168 test_handshake_params_serde_roundtrip HandshakeParams serializes and deserializes losslessly
T-169 test_analyze_file_params_project_file_omitted_when_none project_file: None omitted from AnalyzeFileParams JSON
T-170 test_analyze_file_params_project_file_present_when_some project_file: Some(_) present in AnalyzeFileParams JSON
T-171 test_rpc_error_data_omitted_when_none data: None omitted from RpcError JSON

graph/identity

ID Test Description Status
T-172 test_csharp_reconciliation_in_place Roslyn-provided symbol_key replaces tree-sitter key in-place
T-173 test_csharp_reconciliation_noop_if_same_key Reconciling with identical key makes no DB change
T-174 test_csharp_reconciliation_conflict_falls_back_to_identity_map UNIQUE conflict → old node deleted; surviving node gets new key; node_identity_map entry written
T-175 test_ts_export_scope_upgrade upgrade_ts_export_scope() updates export_scope and symbol_key in-place

ingest/semantic

ID Test Description Status
T-254 test_semantic_enrichment_failure_preserves_existing_edges When enrichment returns an error for a scope, existing edges (exact or approximate) survive unchanged; no partial replacement occurs

Phase 2b — Rename Detection

Features: git-based, fingerprint-based, and symbol-level rename detection; deletion_log chunk_fingerprint; node_identity_map fallback.


ingest/rename

ID Test Description Status
T-177 test_rename_detector_no_deletes_returns_empty Batch with no deletes → empty rename result set
T-178 test_rename_detector_no_creates_returns_empty Batch with deletes but no creates → empty rename result set
T-179 test_parse_git_rename_basic "R95\told.cs\tnew.cs" parses to one rename pair
T-180 test_parse_git_rename_not_in_batch_filtered_out Rename line referencing paths not in the batch excluded
T-181 test_parse_git_rename_ignores_non_rename_lines M, A, D status lines ignored
T-182 test_parse_git_rename_multiple_renames Multiple rename lines all parsed correctly
T-183 test_parse_git_rename_malformed_line_skipped Malformed R lines skipped silently
T-184 test_fingerprint_rename_detected_via_deletion_log Deletion log entry with matching fingerprint → rename detected
T-185 test_fingerprint_rename_not_detected_when_no_journal_entry No journal entry → no fingerprint match
T-438 test_rename_class_and_file_detected_via_fingerprint Fingerprint detects simultaneous class and file rename
T-186 test_symbol_level_rename_preserves_node_id Method rename (same body, new name) → node_identity_map entry written; node_id preserved or remapped
T-187 test_rename_and_body_change_is_not_detected Rename + substantial body rewrite → similarity < threshold → treated as delete+create
T-188 test_file_rename_preserves_embeddings File-level rename → node_id preserved; vec_nodes embedding row retained
T-255 test_rename_detector_ambiguous_candidates_resolved_deterministically Two deleted nodes with similar fingerprints and one created node → either no match (preferred) or highest-score with deterministic tie-breaker; result stable across runs
T-257 test_git_diff_failure_falls_back_to_fingerprint Git unavailable or errors → rename detector continues with fingerprint-only mode without failing the batch

ingest/fingerprint

ID Test Description Status
T-189 test_jaccard_identical Identical fingerprints → similarity 1.0
T-190 test_jaccard_empty Empty fingerprint sets → similarity 0.0
T-191 test_jaccard_disjoint Completely different sets → similarity 0.0
T-192 test_jaccard_half_overlap Half-overlapping sets → Jaccard ≈ 0.33 (intersection=2, union=6)
T-193 test_renamed_method_high_similarity Method with only its name changed → Jaccard ≥ 0.80
T-194 test_fingerprint_roundtrip fingerprint_to_bytes() / fingerprint_from_bytes() round-trip losslessly
T-195 test_fingerprint_unchanged_file_similarity_is_1 Same file content both times → Jaccard = 1.0
T-196 test_fingerprint_completely_rewritten_is_below_threshold Completely different content → similarity < 0.20

Phase 3 — Embedding

Features: EmbeddingProvider trait; HashEmbeddingProvider test stub (SHA-256 deterministic, L2-normalised, 384-dim); vec_nodes embedding store (regular SQLite table for Phase 3; Phase 4 upgrades to ANN); embedding invalidation on model change.


embedding/provider

ID Test Description Status
T-200 test_hash_embedding_provider_dimensionality HashEmbeddingProvider reports dimensionality() == 384
T-201 test_hash_embedding_provider_unit_norm SHA-256-based embedding is L2-normalised (‖v‖ ≈ 1.0)
T-202 test_hash_embedding_provider_deterministic Same text always produces identical embedding vector
T-203 test_hash_embedding_provider_different_texts_differ Two distinct texts produce different embeddings
T-204 test_hash_embedding_provider_batch_matches_single embed_batch results match embed_single results element-by-element
T-205 test_hash_embedding_provider_model_id model_id() returns "test-hash-model" for default constructor
T-207 test_hash_embedding_provider_custom_model_id with_model_id() constructor overrides the model ID

graph/vectors

ID Test Description Status
T-206 test_embedding_stored_in_vec_nodes After indexing a node, vec_nodes contains a row with the node's 384-dim embedding (stored as 1 536 LE bytes)
T-208 test_embedding_model_change_triggers_re_embedding handle_model_change() with a new model ID clears all vec_nodes rows and updates _metadata.embedding_model
T-258 test_embedding_model_unchanged_returns_false handle_model_change() with the same model ID returns false and leaves vec_nodes untouched
T-259 test_insert_or_replace_overwrites_existing_embedding Calling insert_or_replace_embedding twice for the same node results in exactly one row
T-262 test_delete_embedding_removes_row delete_embedding() removes the row for the given node_id
T-263 test_delete_embedding_is_noop_when_absent delete_embedding() with an absent node_id does not error
T-264 test_vec_nodes_table_created_by_ensure ensure_vec_nodes_table() creates the vec_nodes table (verified via sqlite_master)
T-265 test_ensure_vec_nodes_table_is_idempotent Calling ensure_vec_nodes_table() twice does not error
T-439 test_vector_search_brute_force_empty_table Empty vec_nodes table returns no results
T-440 test_vector_search_brute_force_limit Vector search respects limit parameter

Phase 4a — Retrieval Channels

Features: sqlite-vec vector index; BM25 channel; qualified-name channel; hybrid retrieval with token-budget enforcement.


retrieval/channels + retrieval/context + retrieval/mod

ID Test Description Status
T-209 test_vector_channel_returns_ranked_results Vector similarity search returns ranked results with correct ordering
T-210 test_bm25_channel_returns_ranked_results BM25 channel returns the expected node for a known-good keyword query
T-211 test_qualified_name_channel_exact_match Qualified-name channel returns exact match with rank=1, score=1.0
T-212 test_token_budget_truncation Result set serialised to context never exceeds token budget; truncated flag set
T-213 test_retrieve_end_to_end Full retrieve() pipeline returns results from independent channels
T-271 test_build_fts_query_escapes_special_chars FTS5 operators escaped and wildcard appended; no panic or query error
T-272 test_qualified_name_channel_no_match Qualified-name channel returns empty for non-existent name
T-273 test_looks_like_qualified_name Query analysis routes dot-separated identifiers to qname lookup
T-274 test_vector_search_brute_force_roundtrip Brute-force cosine search returns results ordered by distance
T-276 test_context_preserves_score_order Results with scores are ordered deterministically in context assembly
T-277 test_token_budget_no_truncation Token budget with enough room fits all results; truncated=false
T-441 test_bm25_channel_empty_query BM25 search with empty FTS query returns empty results
T-442 test_build_fts_query_empty Empty query string produces empty FTS query
T-443 test_build_fts_query_qualified_name_quoted Qualified names wrapped in quotes for FTS phrase matching
T-444 test_build_fts_query_simple_words Simple words converted to OR-joined tokens with wildcards
T-445 test_context_entry_has_metadata Context entry contains node type, public api, and signatures
T-446 test_estimate_tokens_non_zero Token estimation produces non-zero positive result
T-447 test_retrieve_cross_cutting_doubles_channel_k Cross-cutting queries double the per-channel result limit
T-448 test_retrieve_no_results Non-existent queries return empty results
T-449 test_retrieve_qualified_name_triggers_qname_channel Qualified name queries rank qname channel matches first

Phase 4b — Merge, Rerank & Eval

Features: Reciprocal Rank Fusion (RRF); quality/confidence penalty multipliers; intent classifier; NDCG@10 eval harness.


retrieval/reranker + retrieval/intent

ID Test Description Status
T-216 test_rrf_merge_multi_channel RRF score for a node in two channels is higher than a node in one channel
T-217 test_generated_node_penalty Nodes with generated = true receive the configured generated_penalty multiplier
T-218 test_failed_parse_excluded Nodes with parse_status = Failed are excluded from results entirely
T-220 test_cross_cutting_diversity_penalty Cross-cutting mode diversity penalty reduces score for 2nd+ node from same file
T-221 test_targeted_intent_qualified_symbol Dot-qualified symbol and file path queries classified as targeted intent
T-222 test_cross_cutting_intent "All usages of …" style query classified as cross_cutting intent
T-223 test_exploratory_intent Broad "how does X work" query classified as exploratory intent
T-224 test_eval_produces_valid_metrics Eval harness produces valid NDCG and MRR metrics in [0,1] range
T-225 test_eval_negative_queries Queries referencing non-existent symbols produce 0 metrics
T-278 test_qname_match_ranks_first Qualified-name exact match always ranked first regardless of RRF base score
T-279 test_public_api_boost Public API boost applied additively after base RRF score computation
T-280 test_fallback_is_targeted Ambiguous queries without clear signals default to targeted intent
T-281 test_syntactic_only_penalty Syntactic-only nodes penalized below full-parse nodes
T-450 test_targeted_intent_file_path File paths classified as targeted intent
T-451 test_targeted_takes_priority_over_cross_cutting_when_symbol_present Dot-qualified symbols take priority over quantifiers

eval

ID Test Description Status
T-282 test_ndcg_at_k NDCG@k computed on hardcoded relevance list matches expected values; perfect ranking yields 1.0
T-283 test_mrr MRR computed on hardcoded ranked result list matches expected value (1/rank)
T-284 test_precision_at_k Precision@k matches expected values for known result sets
T-452 test_recall_at_k Recall@k matches expected values for known result sets
T-285 test_load_eval_dataset_roundtrip Eval dataset loads from JSON and round-trips correctly; archetype serde verified
T-453 test_ndcg_no_relevant_nodes NDCG@k returns 0.0 with empty relevance set
T-454 test_mrr_first_is_relevant MRR equals 1.0 when first result is relevant
T-455 test_mrr_no_relevant MRR equals 0.0 when no relevant nodes found
T-456 test_precision_k_zero Precision@k returns 0.0 when k is zero
T-457 test_recall_no_relevant Recall@k returns 0.0 when no relevant nodes exist
T-458 test_load_eval_dataset_missing_file Missing eval dataset file returns error
T-459 test_query_archetype_serde_roundtrip All QueryArchetype enums serialize and deserialize correctly
T-460 test_eval_empty_dataset Empty eval dataset produces zero metrics

Phase 5 — MCP Server

Features: MCP tool registration; file system tools (sandboxed); index query tools; engine management tools; transport (stdio + SSE).


mcp/sandbox

ID Test Description Status
T-461 test_resolve_sandboxed_allows_valid_path Valid paths inside repo root are resolved successfully
T-462 test_resolve_sandboxed_empty_path_returns_root Empty path resolves to repository root
T-463 test_resolve_sandboxed_nonexistent_path Nonexistent paths return error
T-464 test_resolve_sandboxed_rejects_dotdot Paths containing .. are rejected as escaping sandbox

mcp/tools/filesystem (planned module)

ID Test Description Status
T-226 test_list_directory_returns_files_and_dirs list_directory at repo root returns known files and subdirectories with correct types
T-227 test_list_directory_rejects_path_escape list_directory with ../ path returns path_escape error
T-228 test_read_file_returns_content read_file for a known file returns its full content with correct line count
T-229 test_read_file_line_range read_file with line_start and line_end returns only the specified lines
T-230 test_read_file_rejects_binary read_file on a binary file returns binary_file error with detected MIME type
T-231 test_read_file_truncates_large_content read_file on a file exceeding max lines returns truncated: true
T-232 test_get_directory_tree_respects_depth get_directory_tree with depth=1 returns only immediate children
T-233 test_get_directory_tree_respects_gitignore get_directory_tree excludes paths matched by .gitignore

mcp/tools/search (planned module)

ID Test Description Status
T-286 test_search_symbols_returns_ranked_results search_symbols with FTS query returns BM25-ranked results with expected fields
T-287 test_lookup_symbol_by_qualified_name lookup_symbol returns exact match(es) for a known qualified name
T-260 test_search_symbols_filters_by_type_and_language search_symbols with node_type and language filters restricts results correctly

mcp/tools/navigation (planned module)

ID Test Description Status
T-261 test_get_symbol_returns_full_metadata get_symbol returns all node fields including access modifier and return type
T-288 test_get_callers_returns_incoming_call_edges get_callers returns nodes with Calls edges pointing to the target
T-289 test_get_file_outline_returns_symbols_in_order get_file_outline returns symbols ordered by line number
T-290 test_get_implementations_returns_implements_and_extends get_implementations returns both Implements and Extends incoming edges
T-465 test_get_symbol_invalid_uuid Invalid UUID node_id returns INVALID_PARAMETER error

mcp/tools/management (planned module)

ID Test Description Status
T-291 test_index_files_triggers_pipeline index_files with valid paths runs the ingest pipeline and updates the graph
T-292 test_get_status_returns_accurate_counts get_status returns correct indexed_files, indexed_symbols, and watcher_active
T-466 test_index_files_rejects_empty_paths Empty paths array is rejected with INVALID_PARAMETER
T-467 test_index_files_rejects_too_many_paths More than 100 paths rejected with INVALID_PARAMETER

Phase 6 — Hardening

Features: WAL performance; large-repo stress; adversarial encodings; generated-code dampening; concurrent read/write safety.


Logging & privacy

ID Test Description Status
T-293 test_default_logs_exclude_prompt_and_source With default log config, debug_content_logging defaults to false — prevents leaking content
T-294 test_debug_content_logging_gated_by_opt_in Content logging only enabled when explicitly set via config flag; defaults to off

IPC retry & error classification

ID Test Description Status
T-469 test_ipc_child_exited_is_retryable IpcChildExited classified as retryable (respawn will fix it)
T-470 test_ipc_timeout_is_retryable IpcTimeout classified as retryable (temporary overload)
T-471 test_ipc_oom_restart_is_retryable IPC error with code -32104 (OomRestart) classified as retryable
T-472 test_ipc_version_mismatch_is_not_retryable IpcVersionMismatch classified as non-retryable (fundamental incompatibility)
T-473 test_cancelled_is_not_retryable Cancelled classified as non-retryable (explicit cancellation)
T-474 test_ipc_semantic_unavailable_is_not_retryable IPC error -32100 classified as non-retryable (deterministic)
T-475 test_ipc_project_load_failed_is_not_retryable IPC error -32101 classified as non-retryable (deterministic)
T-476 test_ipc_plugin_blocked_is_not_retryable IPC error -32102 classified as non-retryable (safe mode)
T-477 test_non_ipc_errors_are_not_retryable Non-IPC errors (NotInitialized, WriteQueueFull, etc.) all classified as non-retryable
T-478 test_ipc_retry_defaults Default ipc_max_retries=2 and ipc_retry_base_delay_ms=500
T-479 test_ipc_retry_config_from_json JSON config overrides for retry fields parse correctly
T-480 test_ipc_retry_config_defaults_when_omitted Missing retry fields in JSON default to expected values
T-481 test_ipc_retry_zero_disables_retry Setting ipc_max_retries=0 disables retry

Stress & adversarial

ID Test Description Status
T-234 test_large_file_creates_file_node_and_metadata 1 000-method file → file node emitted; method spans have file_path and line numbers
T-235 test_cyclic_call_graph_traversal_terminates A→B→C→A call graph → WITH RECURSIVE query terminates via UNION dedup; returns bounded results
T-236 test_2000_near_identical_methods_indexed 2 000 methods with near-identical bodies indexed; FTS search returns bounded results
T-237 test_wal_concurrent_read_write_no_data_loss Concurrent writer + 4 read connections under load; all reads observe consistent snapshots (#[ignore])
T-238 test_mixed_encoding_bom_stripped_before_hashing UTF-8 BOM stripped before parsing/hashing; chunk_hash matches BOM-free equivalent
T-239 test_generated_code_glob_applies_penalty Generated node gets generated = 1; retrieval score receives multiplicative ×0.3 penalty
T-240 test_rename_class_and_file_uuid_reused Class + file renamed → journal entry + node_identity_map links old→new (unit + integration)
T-241 test_10k_file_write_throughput Index 10 000 files via writer; completes within 60s (#[ignore])
T-295 test_reader_pool_connections_set_required_pragmas Every reader pool connection has foreign_keys = ON, busy_timeout = 5000, and correct mmap_size
T-296 test_disk_full_returns_structured_error Write failure on read-only file → structured CoreError with meaningful message
T-297 test_mcp_tool_error_returns_structured_json MCP tool error → ErrorData with NOT_FOUND code and descriptive message
T-427 test_cancellation_rolls_back_uncommitted_writes Writer thread rolls back uncommitted transaction when CancellationToken fires before COMMIT; no partial results persisted
T-428 test_writer_connection_has_foreign_keys_on Writer connection has PRAGMA foreign_keys = ON (complements T-295 which tests reader pool)

Multi-file fixture project tests (integration)

Tests that index small multi-file C# and TypeScript projects and verify the full graph output. Located in tests/fixture_tests.rs with fixtures under tests/fixtures/{csharp_project,typescript_project}/.


C# fixture — node census

ID Test Description Status
T-300 test_cs_fixture_file_nodes 6 .cs files → 6 file nodes
T-301 test_cs_fixture_module_nodes 2 namespaces deduplicated across 6 files → 2 module nodes
T-302 test_cs_fixture_class_nodes User, Address (struct), UserService → 3 class nodes
T-303 test_cs_fixture_interface_nodes IEntity, IUserService → 2 interface nodes
T-304 test_cs_fixture_type_nodes Status enum → 1 type node
T-305 test_cs_fixture_constructor_nodes User(string), User(string,string) → 2 constructor nodes
T-306 test_cs_fixture_method_nodes 12 method nodes across all files
T-307 test_cs_fixture_property_nodes 7 property nodes across all files

TypeScript fixture — node census

ID Test Description Status
T-308 test_ts_fixture_file_nodes 6 .ts files → 6 file nodes
T-309 test_ts_fixture_type_nodes UserId, UserRole, Status → 3 type nodes
T-310 test_ts_fixture_interface_nodes IEntity, IUserService → 2 interface nodes (body not walked)
T-311 test_ts_fixture_class_nodes User, UserServiceImpl → 2 class nodes
T-312 test_ts_fixture_method_nodes 12 method nodes (class methods + top-level functions)
T-313 test_ts_fixture_property_nodes 6 property nodes (class fields + constants)

Symbol keys and qualified names

ID Test Description Status
T-314 test_cs_fixture_qualified_names User and UserService have fully-qualified symbol keys with namespace prefix
T-315 test_cs_fixture_overloaded_methods_distinct_keys GetDisplayName(0) and GetDisplayName(1) have distinct symbol keys
T-316 test_cs_fixture_overloaded_constructors_distinct_keys User(string) and User(string,string) have distinct symbol keys
T-317 test_cs_fixture_struct_is_class_node Address struct stored as class node
T-318 test_cs_fixture_enum_is_type_node Status enum stored as type node

Contains edges

ID Test Description Status
T-319 test_cs_fixture_namespace_contains_class Module(SampleApp.Models) → Contains → User, Address, IEntity, Status
T-320 test_cs_fixture_class_contains_methods Class(User) → Contains → GetDisplayName, Validate
T-321 test_ts_fixture_file_contains_symbols File(utils.ts) → Contains → formatName, capitalize, internalHelper, MAX_USERS
T-322 test_ts_fixture_class_contains_methods Class(User) → Contains → constructor, getDisplayName, toJSON

FTS

ID Test Description Status
T-323 test_cs_fixture_fts_search_finds_user FTS query "User" returns User class
T-324 test_ts_fixture_fts_search_finds_function FTS query "formatName" returns the function
T-325 test_cs_fixture_fts_by_qualified_name FTS query "SampleApp.Models"* returns namespace members

File deletion cascade

ID Test Description Status
T-326 test_cs_fixture_delete_file_removes_symbols Delete Address.cs → class + 3 properties + file gone; others remain
T-327 test_cs_fixture_delete_preserves_shared_namespace Delete Status.cs → SampleApp.Models module survives (span from Address.cs)
T-328 test_ts_fixture_delete_file_removes_symbols Delete utils.ts → 4 symbols + file gone; other files unaffected

Project detection

ID Test Description Status
T-329 test_cs_fixture_detects_csproj detect_projects() finds SampleApp.csproj with language=CSharp
T-330 test_ts_fixture_detects_package_json detect_projects() finds package.json with display_name=sample-ts-app

Outline

ID Test Description Status
T-331 test_cs_fixture_outline_user_file get_outline() for User.cs returns class, properties, constructors, methods
T-332 test_ts_fixture_outline_utils_file get_outline() for utils.ts returns formatName, capitalize, internalHelper, MAX_USERS

Flags and access modifiers

ID Test Description Status
T-333 test_cs_fixture_private_method_not_public_api User.Validate has is_public_api=false
T-334 test_cs_fixture_static_method UserService.Create has is_static=true
T-335 test_cs_fixture_async_method UserService.RefreshAsync has is_async=true
T-336 test_ts_fixture_export_scope_module formatName has export_scope=module
T-337 test_ts_fixture_export_scope_file internalHelper has export_scope=file

Idempotent re-indexing

ID Test Description Status
T-338 test_ts_fixture_reindex_idempotent TS fixture indexed twice → same node count (deterministic FileId)
T-468 test_cs_fixture_reindex_idempotent Re-indexing same C# fixture produces identical node count

Project detection sequencing

ID Test Description Status
T-429 test_project_detection_before_indexing_assigns_correct_project_id Running detect_projects + ensure_projects_in_db before indexing assigns detected project_id (not root) to symbols

OSS Integration Tests

Real-world open-source repository indexing and query tests. Tests against tRPC (TypeScript, v11.10.0) and Hot Chocolate graphql-platform (C#, 15.1.12) at pinned commits. Gated behind cargo test --features oss-tests. Cached DBs reused across tests for fast iteration.

Tier 0 — Baseline Indexing

ID Test Description Status
T-339 test_oss_trpc_typescript_indexing tRPC repo indexes with low error rate; node census meets thresholds; FTS finds key symbols; no duplicate symbol keys
T-340 test_oss_hotchocolate_csharp_indexing Hot Chocolate repo indexes with low error rate; node census meets thresholds; FTS finds key symbols; no duplicate symbol keys
T-341 test_oss_trpc_idempotent_reindex Re-indexing tRPC produces identical node count as first pass
T-342 test_oss_hotchocolate_idempotent_reindex Re-indexing Hot Chocolate produces identical node count as first pass

Tier 1 — Basic Navigation

ID Test Description Status
T-343 test_oss_trpc_lookup_symbol_by_qualified_name Lookup discovered method by qualified name returns correct node with matching language
T-344 test_oss_trpc_file_outline_ordered_by_line File outline is non-empty, ordered by line_start, excludes file and project nodes
T-345 test_oss_trpc_fts_search_known_name FTS search for discovered method display name returns results with rank
T-346 test_oss_trpc_neighbors_contains Container node has non-empty outgoing contains edges, all typed Contains
T-347 test_oss_trpc_neighbors_implements Interface has incoming implements edges (skips gracefully if none in Phase 1 TS)
T-348 test_oss_hc_lookup_symbol_by_qualified_name Lookup discovered C# method by qualified name returns correct node
T-349 test_oss_hc_file_outline_ordered_by_line C# file outline is non-empty, ordered by line_start, excludes file and project nodes
T-350 test_oss_hc_fts_search_known_name FTS search for discovered C# method display name returns results with rank
T-351 test_oss_hc_neighbors_contains C# container has non-empty outgoing contains edges
T-352 test_oss_hc_neighbors_implements C# interface has incoming implements edges (skips if none)

Tier 2 — Complex Queries and Stress

ID Test Description Status
T-353 test_oss_trpc_multihop_interface_methods 2-hop: interface → implementors → their methods (skips if no implements)
T-354 test_oss_trpc_multihop_callers_file 3-hop: method → callers → caller file_path (skips if no calls edges)
T-355 test_oss_trpc_transitive_contains Transitive closure from module: result >= direct children, no duplicate node IDs
T-356 test_oss_trpc_fts_common_terms_bounded FTS search for 5 common terms each returns <=50 results in <5s
T-357 test_oss_trpc_outline_all_files_no_panics Outline up to 200 files with no panics, <5000 symbols per file
T-358 test_oss_trpc_filter_combined_criteria Combined filter: language + node_type + FTS query returns matching results
T-359 test_oss_hc_multihop_interface_methods 2-hop: C# interface → implementors → methods; asserts non-empty
T-360 test_oss_hc_multihop_callers_file 3-hop: C# method → callers → file_path
T-361 test_oss_hc_transitive_contains Transitive closure from C# namespace: result >= direct children, no dupes
T-362 test_oss_hc_fts_common_terms_bounded FTS search for 5 common C# terms each returns <=50 results in <5s
T-363 test_oss_hc_outline_all_files_no_panics Outline up to 500 C# files with no panics, <5000 symbols per file
T-364 test_oss_hc_filter_combined_criteria Combined filter: C# language + Class + FTS query returns matching results

Tier 3 — Benchmarks

ID Test Description Status
T-365 test_oss_trpc_benchmarks 5 benchmarks (symbol lookup, FTS, neighbors, outline, transitive) on tRPC DB
T-366 test_oss_hc_benchmarks 5 benchmarks (symbol lookup, FTS, neighbors, outline, transitive) on HC DB

Tier 4 — Pipeline Benchmarks

End-to-end pipeline tests that run initial indexing, incremental reindex, and (for HC) a touched-file reindex across multiple projects. Gated behind --features oss-tests. Semantic enrichment paths (IPC, solution load, minimal solution reload) only exercise when the corresponding extractor is found on the system: CodeAgentExtractor.dll for C# (Roslyn), dist/index.js for TypeScript, and codeagent-rust-extractor for Rust. Without extractors, tests still pass but skip semantic assertions. Run 10–30 minutes; use run_in_background and poll.

ID Test Description Status
T-482 test_oss_trpc_pipeline_benchmark Full tRPC pipeline: initial index + idempotent reindex with content-hash skip; integrity checks (dup edges, FTS, orphans)
T-483 test_oss_hc_pipeline_benchmark Full HC pipeline: initial index + idempotent reindex + touched-file reindex (60 files across 10 projects exercises minimal solution reload); integrity checks and node stability across 3 passes
T-484 test_oss_rust_analyzer_pipeline_benchmark Full rust-analyzer pipeline (Rust, ~1435 .rs files, ~50 crates): initial index + idempotent reindex with content-hash skip; node census (methods, structs, traits, modules), integrity checks, semantic enrichment when extractor available

Hooks, Dead Code Detection & Init

PageRank computation, dead code detection, Claude Code hook handlers, and CLI init command. Tests span codeagent-core (graph/ranking, query/dead_code) and codeagent-cli (init).


PageRank (graph/ranking.rs)

ID Test Description Status
T-367 test_pagerank_star_topology Star graph: hub node called by 5 callers ranks highest
T-368 test_pagerank_linear_chain Chain A→B→C: B (both in-degree and out-degree) outranks A
T-369 test_pagerank_isolated_node Isolated node (no edges) does not appear in edge-based PageRank results
T-370 test_pagerank_empty_graph Empty graph (no edges) returns empty results
T-371 test_pagerank_summary_returns_nodes get_pagerank_summary returns full Node objects with display names and positive scores

Dead code detection (query/dead_code.rs)

ID Test Description Status
T-372 test_dead_code_uncalled_method Method with zero incoming Calls/References is detected as dead code
T-373 test_dead_code_constructor_excluded Constructor excluded from dead code by default (entry point)
T-374 test_dead_code_public_api_filtering Public API method excluded by default, included when include_public_api=true
T-375 test_dead_code_override_excluded Override method excluded from dead code (interface implementations are not dead)
T-376 test_dead_code_called_method_not_dead Method called by another method is NOT flagged as dead code
T-377 test_dead_code_cross_file Method in file A with no callers from any file is detected as dead
T-378 test_count_dead_code_matches count_dead_code returns same count as find_dead_code().len()

Init command (codeagent-cli/init.rs)

ID Test Description Status
T-379 test_init_creates_directory_and_config Creates .codeagent/ dir, config.json, index.db, and .claude/settings.json
T-380 test_init_idempotent Running init twice does not duplicate hooks or corrupt config
T-381 test_init_preserves_existing_settings Preserves existing .claude/settings.json content while adding hooks
T-382 test_init_gitignore_entry Adds .codeagent/index.db to .gitignore without duplicating on re-run

CLI output (codeagent-cli)

ID Test Description Status
T-430 test_cli_commands_produce_valid_json All CLI subcommands that output JSON produce valid JSON (requires subprocess invocation or refactoring command logic into testable functions)

ASP.NET Core API Boundary Support

Features: API endpoint detection, route/auth/request/response metadata extraction from tree-sitter and Roslyn, api_endpoints table (Migration 004), MCP search_api_endpoints tool, endpoint enrichment on get_symbol and get_file_outline.


graph/api_endpoints (schema + CRUD)

ID Test Description Status
T-383 test_migration_004_creates_api_endpoints_table Migration 004 creates api_endpoints table in SQLite
T-384 test_upsert_and_get_roundtrip Upsert an endpoint then read it back with all fields matching
T-385 test_upsert_replaces_existing_row Upsert same node_id twice replaces old row; only one row exists
T-386 test_search_by_http_method search_api_endpoints with http_method=GET returns only GET endpoints
T-387 test_search_by_route_pattern search_api_endpoints with route_pattern substring matches correct routes
T-388 test_search_by_controller_id search_api_endpoints with controller_id filter returns only that controller's endpoints
T-389 test_delete_api_endpoints_for_file Deleting endpoints for a file path removes correct rows, preserves others
T-390 test_on_delete_cascade_removes_endpoint Deleting a node hard-removes its api_endpoints row via ON DELETE CASCADE
T-391 test_get_api_endpoints_for_file Batch load returns all endpoints for nodes in a given file
T-392 test_search_limit_capped_at_50 Requesting limit=100 is capped to 50 rows returned
T-393 test_get_nonexistent_endpoint_returns_none Looking up a random node_id returns None
T-394 test_api_style_roundtrip All ApiStyle variants round-trip through as_str/from_str

adapters/csharp (ASP.NET tree-sitter extraction)

ID Test Description Status
T-395 test_aspnet_basic_api_controller_httpget Basic [ApiController] + [HttpGet] produces api_endpoints row with GET method
T-396 test_aspnet_all_http_methods [HttpGet/Post/Put/Delete/Patch] each produce correct http_method values
T-397 test_aspnet_route_resolution_with_controller_token [Route("api/[controller]")] + [HttpGet("{id}")] resolves to api/users/{id}
T-398 test_aspnet_auth_extraction [Authorize(Policy="Admin")] and [AllowAnonymous] produce correct auth_policy
T-399 test_aspnet_from_body_parameter [FromBody] parameter type extracted as request_body_type
T-400 test_aspnet_response_type_from_action_result ActionResult and Task<ActionResult> unwrapped to response_type
T-401 test_aspnet_non_controller_class_no_endpoints Class without [ApiController] or ControllerBase produces no api_endpoints
T-402 test_aspnet_class_without_api_controller_attribute_no_endpoints Class without [ApiController] attribute and not inheriting ControllerBase produces no endpoints
T-403 test_aspnet_controller_base_inheritance_without_attribute Class inheriting ControllerBase (no [ApiController]) still detected as controller
T-404 test_resolve_route_template_combinations Unit test for route template resolution helper with various inputs
T-405 test_extract_response_type_from_return_type Unit test for response type extraction from Task<ActionResult> strings
T-406 test_unwrap_generic Unit test for generic type unwrapping helper

ipc/protocol (API endpoint IPC backward compat)

ID Test Description Status
T-407 test_semantic_node_with_api_endpoint_deserializes SemanticNode JSON with api_endpoint field deserializes correctly
T-408 test_semantic_node_without_api_endpoint_backward_compat SemanticNode JSON missing api_endpoint deserializes as None
T-409 test_semantic_node_api_endpoint_omitted_in_serialization_when_none Serializing SemanticNode with api_endpoint=None omits the field

mcp/tools/search (search_api_endpoints tool)

ID Test Description Status
T-410 test_search_api_endpoints_returns_results search_api_endpoints returns endpoint+method JSON with all fields
T-411 test_search_api_endpoints_filters_by_route search_api_endpoints with route_pattern returns matching endpoints only
T-412 test_search_api_endpoints_empty_filters_returns_all search_api_endpoints with no filters returns all endpoints up to limit

mcp/tools/navigation (endpoint enrichment on get_symbol/get_file_outline)

ID Test Description Status
T-413 test_get_symbol_includes_api_endpoint get_symbol for an action method includes api_endpoint field with metadata
T-414 test_get_symbol_omits_api_endpoint_when_absent get_symbol for a non-endpoint method omits api_endpoint field
T-415 test_get_file_outline_includes_api_endpoint get_file_outline includes api_endpoint on action methods, omits on helpers

Test harness prerequisites (Phase 3+)

The following traits and test utilities are introduced for Phases 3–5 to enable TDD without real network calls, ONNX models, or child processes:

  • EmbeddingProvider trait (embedding/provider.rs) — real: ONNX EmbeddingModel; test: HashEmbeddingProvider (SHA-256 deterministic, L2-normalised, 384-dim, no model file)
  • Clock trait — real: system time; test: frozen clock for TTL and correlation-window tests
  • ChildProcessTransport trait — real: stdio JSON-RPC; test: in-memory scripted responder
  • TestRepoBuilder utility — creates temp repo with files, optional git init, and common project structures (.csproj, tsconfig.json, package.json)
  • TestDb helper — file-backed SQLite with extensions enabled (needed for sqlite-vec ANN integration tests in Phase 4a)

Pipeline integration (deferred)

These tests require a file-based SQLite database, start_writer_thread, DbReaderPool, a live IpcManager, and #[tokio::test]. The cost of the test harness is high; they are deferred to a dedicated integration-test phase.

ID Test Description Status
T-242 test_pipeline_full_index_csharp Full ingest of a small C# project → correct nodes, edges, and FTS entries in DB
T-243 test_pipeline_incremental_update Modify one file → only changed nodes updated; chunk_hash comparison skips unchanged
T-244 test_pipeline_semantic_enrichment_csharp C# semantic pass via Roslyn extractor → parse_status = 'full', exact edges present
T-245 test_pipeline_semantic_enrichment_typescript TS semantic pass via TS LS extractor → parse_status = 'full', exact edges present
T-246 test_pipeline_semantic_context_invalidation .csproj change → semantic edges for affected project recomputed atomically
T-247 test_pipeline_rename_detection_end_to_end Delete + create within debounce window → rename detected; node_id preserved
T-248 test_pipeline_delete_file_journals_and_cleans_up Delete file → nodes hard-deleted; deletion journal written; FTS + edges removed