claude-flow-novice 2.18.39 → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.claude/agents/SHARED_PROTOCOL.md +25 -1
  2. package/.claude/agents/cfn-dev-team/dev-ops/fly-io-specialist.md +418 -0
  3. package/.claude/agents/cfn-dev-team/developers/database/mem0-specialist.md +579 -0
  4. package/.claude/agents/cfn-dev-team/developers/database/memgraph-specialist.md +722 -0
  5. package/.claude/agents/cfn-dev-team/documentation/pseudocode.md +1 -1
  6. package/.claude/agents/cfn-dev-team/documentation/specification-agent.md +1 -1
  7. package/.claude/agents/cfn-dev-team/testers/tester.md +35 -0
  8. package/.claude/commands/{cfn-ruvector → cfn-codesearch}/cfn-codebase-reindex.md +4 -4
  9. package/.claude/commands/{cfn-ruvector → cfn-codesearch}/cfn-codebase-search.md +7 -7
  10. package/.claude/commands/{cfn-ruvector → cfn-codesearch}/cfn-detect-stale-docs.md +3 -3
  11. package/.claude/commands/{cfn-ruvector-search.md → cfn-codesearch-search.md} +7 -7
  12. package/.claude/commands/cfn-fix-errors.md +1 -1
  13. package/.claude/commands/cfn-loop-task.md +291 -291
  14. package/.claude/skills/{bulk-add-ruvector-instructions.sh → bulk-add-codesearch-instructions.sh} +12 -12
  15. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/AGENT_INTEGRATION_PATTERNS.md +20 -20
  16. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/AGENT_LIFECYCLE_INTEGRATION.md +11 -11
  17. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/Cargo.toml +9 -4
  18. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/EXTRACTION_EXAMPLES.md +6 -6
  19. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/IMMEDIATE_ACTION_REQUIRED.md +9 -9
  20. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/README.md +7 -7
  21. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/SCHEMA_V2_IMPLEMENTATION.md +1 -1
  22. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/SECURITY_IMPLEMENTATION.md +3 -3
  23. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/SECURITY_TESTING_COMPLETION.md +4 -4
  24. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/SKILL.md +31 -31
  25. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/analyze-agent-failures.sh +11 -11
  26. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/cfn-integration.sh +27 -27
  27. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/index-code.sh +11 -11
  28. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/index_all.sh +2 -2
  29. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/ingest-agent-transcript.sh +10 -10
  30. package/.claude/skills/{cfn-local-ruvector-accelerator/init-local-ruvector.sh → cfn-codesearch/init-local-codesearch.sh} +16 -16
  31. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/project-structure.md +10 -10
  32. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/query-local.sh +6 -6
  33. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/index.rs +233 -4
  34. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/init.rs +18 -18
  35. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/query.rs +64 -3
  36. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/embeddings.rs +19 -5
  37. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/lib.rs +6 -4
  38. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/main.rs +35 -25
  39. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/paths.rs +19 -13
  40. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/query_v2.rs +3 -4
  41. package/.claude/skills/cfn-codesearch/src/store_pgvector.rs +301 -0
  42. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/store_v2.rs +12 -1
  43. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/test-agent-lifecycle-integration.sh +6 -6
  44. package/.claude/skills/{cfn-local-ruvector-accelerator/test-local-ruvector.sh → cfn-codesearch/test-local-codesearch.sh} +7 -7
  45. package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/test_query_api.sh +2 -2
  46. package/.claude/skills/cfn-epic-creator/SKILL.md +110 -2
  47. package/.claude/skills/cfn-epic-creator/invoke.sh +120 -1
  48. package/.claude/skills/cfn-mdap-context-injection/SKILL.md +2 -2
  49. package/.claude/skills/cfn-mdap-context-injection/inject.sh +21 -21
  50. package/package.json +11 -11
  51. package/readme/feature-status.md +405 -0
  52. package/.claude/agents/docker-ts-fixer.md +0 -65
  53. /package/.claude/agents/cfn-dev-team/{testing → testers}/test-validation-agent.md +0 -0
  54. /package/.claude/{agents/cfn-dev-team/utility → cfn-extras/agents}/context-curator.md +0 -0
  55. /package/.claude/{agents/custom → cfn-extras/agents/custom-agents}/cfn-docker-expert.md +0 -0
  56. /package/.claude/{agents/custom → cfn-extras/agents/custom-agents}/cfn-loops-cli-expert.md +0 -0
  57. /package/.claude/{agents/custom → cfn-extras/agents/custom-agents}/cfn-redis-operations.md +0 -0
  58. /package/.claude/{agents/custom → cfn-extras/agents/custom-agents}/cfn-system-expert.md +0 -0
  59. /package/.claude/{agents/csuite → cfn-extras/agents/custom-agents}/cto-agent.md +0 -0
  60. /package/.claude/{agents/custom → cfn-extras/agents/custom-agents}/trigger-dev-expert.md +0 -0
  61. /package/.claude/{agents/cfn-dev-team/coordinators → cfn-extras/agents/deprecated-coordinators}/consensus-builder.md +0 -0
  62. /package/.claude/{agents/cfn-dev-team/coordinators → cfn-extras/agents/deprecated-coordinators}/multi-sprint-coordinator.md +0 -0
  63. /package/.claude/{agents → cfn-extras/agents/docker-team}/docker-coordinators/cfn-docker-v3-coordinator.md +0 -0
  64. /package/.claude/{agents/cfn-dev-team/dev-ops → cfn-extras/agents}/kubernetes-specialist.md +0 -0
  65. /package/.claude/{agents/cfn-dev-team/architecture → cfn-extras/agents}/planner.md +0 -0
  66. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/.claude/hooks/SessionStart-cfn-build-ruvector.sh +0 -0
  67. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/Cargo.toml.backup +0 -0
  68. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/SECURITY_FINDINGS_SUMMARY.txt +0 -0
  69. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/docs/EXECUTIVE_SUMMARY.txt +0 -0
  70. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/docs/PHASE_4_QUERY_API.md +0 -0
  71. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/docs/RUST_AST_EXTRACTOR_IMPLEMENTATION.md +0 -0
  72. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/docs/TRANSACTION_MANAGEMENT.md +0 -0
  73. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/docs/VALIDATION_FINDINGS.txt +0 -0
  74. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/embeddings_manager.py.backup +0 -0
  75. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/epic-ast-indexer.json +0 -0
  76. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/index/index.bin +0 -0
  77. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/index/metadata.json +0 -0
  78. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/index-code.sh.backup +0 -0
  79. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/query-agent-patterns.sh +0 -0
  80. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/requirements.txt +0 -0
  81. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/search_engine_v2.py.backup +0 -0
  82. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/sqlite_store.py.backup +0 -0
  83. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/cleanup.rs +0 -0
  84. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/export.rs +0 -0
  85. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/find.rs +0 -0
  86. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/index_ast.rs +0 -0
  87. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/index_modified.rs +0 -0
  88. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/migration.rs +0 -0
  89. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/mod.rs +0 -0
  90. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/refs.rs +0 -0
  91. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/reset.rs +0 -0
  92. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/cli/stats.rs +0 -0
  93. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/mod.rs +0 -0
  94. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/rust.rs +0 -0
  95. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/rust_placeholder.rs +0 -0
  96. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/text_fallback.rs +0 -0
  97. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/typescript.rs +0 -0
  98. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/extractors/typescript_full.rs +0 -0
  99. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/main.rs.backup +0 -0
  100. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/migration.rs +0 -0
  101. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/migration_backup.rs +0 -0
  102. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/migration_tx.rs +0 -0
  103. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/migration_v2.rs +0 -0
  104. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/path_validator.rs +0 -0
  105. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/query_api.rs +0 -0
  106. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/schema_v2.rs +0 -0
  107. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/search_engine.rs +0 -0
  108. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/security_tests.rs +0 -0
  109. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/sqlite_store.rs +0 -0
  110. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/store_v2_backup.rs +0 -0
  111. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/store_v2_fixed.rs +0 -0
  112. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/store_v2_tx.rs +0 -0
  113. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/test_schema.rs +0 -0
  114. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/src/transaction_tests.rs +0 -0
  115. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/test_ast_indexing.rs +0 -0
  116. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/test_schema.sql +0 -0
  117. /package/.claude/skills/{cfn-local-ruvector-accelerator → cfn-codesearch}/test_schema_v2.sql +0 -0
@@ -24,10 +24,14 @@ mod query_v2;
24
24
  mod transaction_tests;
25
25
 
26
26
  use cli::*;
27
+
28
+ /// Default PostgreSQL connection for pgvector
29
+ const DEFAULT_PG_URL: &str = "postgresql://postgres:postgres@localhost:5433/daily_platform";
30
+
27
31
  #[derive(Parser)]
28
- #[command(name = "local-ruvector")]
29
- #[command(about = "Local RuVector Accelerator - Fast pattern storage and search", long_about = None)]
30
- #[command(version = "1.0.0")]
32
+ #[command(name = "codesearch")]
33
+ #[command(about = "CodeSearch - Fast semantic code search with pgvector", long_about = None)]
34
+ #[command(version = "0.2.0")]
31
35
  struct Cli {
32
36
  #[command(subcommand)]
33
37
  command: Commands,
@@ -36,6 +40,10 @@ struct Cli {
36
40
  #[arg(short, long, default_value = ".")]
37
41
  project_dir: String,
38
42
 
43
+ /// PostgreSQL connection string
44
+ #[arg(long, env = "CODESEARCH_PG_URL", default_value = DEFAULT_PG_URL)]
45
+ pg_url: String,
46
+
39
47
  /// Enable verbose logging
40
48
  #[arg(short, long)]
41
49
  verbose: bool,
@@ -43,7 +51,7 @@ struct Cli {
43
51
 
44
52
  #[derive(Subcommand)]
45
53
  enum Commands {
46
- /// Initialize local RuVector in project
54
+ /// Initialize local CodeSearch in project
47
55
  Init {
48
56
  /// Force reinitialization
49
57
  #[arg(long)]
@@ -234,11 +242,11 @@ fn main() -> Result<()> {
234
242
  .canonicalize()
235
243
  .map_err(|e| anyhow!("Invalid project directory: {}", e))?;
236
244
 
237
- info!("Local RuVector Accelerator v1.0.0");
245
+ info!("Local CodeSearch Accelerator v1.0.0");
238
246
  info!("Project: {}", project_path.display());
239
247
 
240
- // Check if RuVector is initialized for most commands
241
- let ruvector_dir = project_path.join(".ruvector");
248
+ // Check if CodeSearch is initialized for most commands
249
+ let ruvector_dir = project_path.join(".codesearch");
242
250
 
243
251
  match cli.command {
244
252
  Commands::Init { force } => {
@@ -247,14 +255,14 @@ fn main() -> Result<()> {
247
255
  cmd.execute()?;
248
256
  }
249
257
  Commands::Index { path, types, patterns, force } => {
250
- // Auto-initialize RuVector if not already initialized
251
- let db_path = local_ruvector::paths::get_database_path()?;
258
+ // Auto-initialize CodeSearch if not already initialized
259
+ let db_path = codesearch::paths::get_database_path()?;
252
260
  if !db_path.exists() {
253
- info!("RuVector not initialized, auto-initializing...");
261
+ info!("CodeSearch not initialized, auto-initializing...");
254
262
  let init_cmd = InitCommand::new(&project_path, false);
255
263
  init_cmd.check_environment()?;
256
264
  init_cmd.execute()?;
257
- info!("✅ RuVector auto-initialized");
265
+ info!("✅ CodeSearch auto-initialized");
258
266
  }
259
267
 
260
268
  let file_types: Vec<String> = types.split(',').map(|s| s.trim().to_string()).collect();
@@ -267,6 +275,7 @@ fn main() -> Result<()> {
267
275
  file_types,
268
276
  pattern_list,
269
277
  force,
278
+ Some(&cli.pg_url),
270
279
  )?;
271
280
  let stats = cmd.execute()?;
272
281
  println!("✅ Indexed {} files with {} patterns", stats.files_processed, stats.embeddings_generated);
@@ -281,10 +290,10 @@ fn main() -> Result<()> {
281
290
  batch,
282
291
  output,
283
292
  } => {
284
- // Check centralized database exists (not local .ruvector dir)
293
+ // Check centralized database exists (not local .codesearch dir)
285
294
  let db_path = paths::get_database_path()?;
286
295
  if !db_path.exists() {
287
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
296
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
288
297
  }
289
298
 
290
299
  if let Some(batch_file) = batch {
@@ -310,6 +319,7 @@ fn main() -> Result<()> {
310
319
  output_format,
311
320
  context,
312
321
  file,
322
+ Some(&cli.pg_url),
313
323
  )?;
314
324
  cmd.execute()?;
315
325
  }
@@ -320,10 +330,10 @@ fn main() -> Result<()> {
320
330
  analyze,
321
331
  report,
322
332
  } => {
323
- // Check centralized database exists (not local .ruvector dir)
333
+ // Check centralized database exists (not local .codesearch dir)
324
334
  let db_path = paths::get_database_path()?;
325
335
  if !db_path.exists() {
326
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
336
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
327
337
  }
328
338
 
329
339
  let output_format = match format {
@@ -347,10 +357,10 @@ fn main() -> Result<()> {
347
357
  dry_run,
348
358
  force,
349
359
  } => {
350
- // Check centralized database exists (not local .ruvector dir)
360
+ // Check centralized database exists (not local .codesearch dir)
351
361
  let db_path = paths::get_database_path()?;
352
362
  if !db_path.exists() {
353
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
363
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
354
364
  }
355
365
 
356
366
  let cmd = CleanupCommand::new(
@@ -373,36 +383,36 @@ fn main() -> Result<()> {
373
383
 
374
384
  if ruvector_dir.exists() {
375
385
  std::fs::remove_dir_all(&ruvector_dir)?;
376
- println!("✅ Reset complete: removed .ruvector directory");
386
+ println!("✅ Reset complete: removed .codesearch directory");
377
387
  } else {
378
- println!("ℹ️ No RuVector data found to reset");
388
+ println!("ℹ️ No CodeSearch data found to reset");
379
389
  }
380
390
  }
381
391
  Commands::Migrate { source: _, path: _, dry_run: _ } => {
382
392
  println!("⚠️ Migration feature not yet implemented");
383
393
  }
384
394
  Commands::Export { path, format: _, include_embeddings: _ } => {
385
- // Check centralized database exists (not local .ruvector dir)
395
+ // Check centralized database exists (not local .codesearch dir)
386
396
  let db_path = paths::get_database_path()?;
387
397
  if !db_path.exists() {
388
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
398
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
389
399
  }
390
400
  println!("⚠️ Export feature not yet implemented");
391
401
  println!("Would export to: {}", path);
392
402
  }
393
403
  Commands::Find { args } => {
394
- // Check centralized database exists (not local .ruvector dir)
404
+ // Check centralized database exists (not local .codesearch dir)
395
405
  let db_path = paths::get_database_path()?;
396
406
  if !db_path.exists() {
397
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
407
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
398
408
  }
399
409
  args.execute(&project_path)?;
400
410
  }
401
411
  Commands::Refs { args } => {
402
- // Check centralized database exists (not local .ruvector dir)
412
+ // Check centralized database exists (not local .codesearch dir)
403
413
  let db_path = paths::get_database_path()?;
404
414
  if !db_path.exists() {
405
- return Err(anyhow!("RuVector database not found. Run 'init' and 'index' first."));
415
+ return Err(anyhow!("CodeSearch database not found. Run 'init' and 'index' first."));
406
416
  }
407
417
  args.execute(&project_path)?;
408
418
  }
@@ -1,25 +1,25 @@
1
- // Centralized path management for RuVector index
1
+ // Centralized path management for CodeSearch index
2
2
  use std::path::PathBuf;
3
3
  use anyhow::{Result, Context};
4
4
 
5
- /// Get the centralized RuVector directory
6
- /// Location: ~/.local/share/ruvector/
7
- pub fn get_ruvector_dir() -> Result<PathBuf> {
5
+ /// Get the centralized CodeSearch directory
6
+ /// Location: ~/.local/share/codesearch/
7
+ pub fn get_codesearch_dir() -> Result<PathBuf> {
8
8
  let home = std::env::var("HOME")
9
9
  .context("HOME environment variable not set")?;
10
-
11
- let ruvector_dir = PathBuf::from(home)
10
+
11
+ let codesearch_dir = PathBuf::from(home)
12
12
  .join(".local")
13
13
  .join("share")
14
- .join("ruvector");
15
-
16
- Ok(ruvector_dir)
14
+ .join("codesearch");
15
+
16
+ Ok(codesearch_dir)
17
17
  }
18
18
 
19
19
  /// Get the centralized database path
20
- /// Location: ~/.local/share/ruvector/index_v2.db
20
+ /// Location: ~/.local/share/codesearch/index_v2.db
21
21
  pub fn get_database_path() -> Result<PathBuf> {
22
- Ok(get_ruvector_dir()?.join("index_v2.db"))
22
+ Ok(get_codesearch_dir()?.join("index_v2.db"))
23
23
  }
24
24
 
25
25
  /// DEPRECATED: V1 index is no longer used
@@ -27,5 +27,11 @@ pub fn get_database_path() -> Result<PathBuf> {
27
27
  /// This function remains only for migration cleanup
28
28
  #[deprecated(since = "2.0.0", note = "V1 index removed. Use get_database_path() for V2.")]
29
29
  pub fn get_v1_index_dir() -> Result<PathBuf> {
30
- Ok(get_ruvector_dir()?.join("index"))
31
- }
30
+ Ok(get_codesearch_dir()?.join("index"))
31
+ }
32
+
33
+ // Legacy alias for backwards compatibility during transition
34
+ #[deprecated(since = "0.2.0", note = "Use get_codesearch_dir instead")]
35
+ pub fn get_ruvector_dir() -> Result<PathBuf> {
36
+ get_codesearch_dir()
37
+ }
@@ -51,7 +51,6 @@ impl QueryV2 {
51
51
  let project_root_str = project_root
52
52
  .to_string_lossy()
53
53
  .to_string();
54
- let project_root_pattern = format!("{}%", project_root_str);
55
54
 
56
55
  // 2. Get all embeddings with entity details, filtered by project root
57
56
  let mut stmt = self.store.conn.prepare(
@@ -61,10 +60,10 @@ impl QueryV2 {
61
60
  ee.embedding
62
61
  FROM entities e
63
62
  JOIN entity_embeddings ee ON e.id = ee.entity_id
64
- WHERE e.file_path LIKE ?"
63
+ WHERE e.project_root = ?"
65
64
  )?;
66
-
67
- let embedding_rows = stmt.query_map(params![project_root_pattern], |row| {
65
+
66
+ let embedding_rows = stmt.query_map(params![project_root_str], |row| {
68
67
  let entity_id: i64 = row.get(0)?;
69
68
  let entity_kind: String = row.get(1)?;
70
69
  let entity_name: String = row.get(2)?;
@@ -0,0 +1,301 @@
1
+ //! PostgreSQL/pgvector storage backend for CodeSearch
2
+ //!
3
+ //! This module provides vector similarity search using pgvector extension.
4
+ //! Embeddings are stored in pgvector for fast HNSW-indexed similarity search.
5
+
6
+ use anyhow::{Result, Context, anyhow};
7
+ use tokio_postgres::NoTls;
8
+ use deadpool_postgres::{Config, Pool, Runtime};
9
+ use serde::{Serialize, Deserialize};
10
+ use tracing::{info, debug, warn};
11
+ use pgvector::Vector;
12
+
13
+ use crate::store_v2::Entity;
14
+
15
+ /// Expected embedding dimension for text-embedding-3-small model
16
+ pub const EMBEDDING_DIMENSION: usize = 1536;
17
+
18
+ /// PostgreSQL connection pool for pgvector operations
19
+ pub struct PgvectorStore {
20
+ pool: Pool,
21
+ }
22
+
23
+ impl PgvectorStore {
24
+ /// Create a new pgvector store from connection URL
25
+ pub async fn new(database_url: &str) -> Result<Self> {
26
+ let config = database_url.parse::<tokio_postgres::Config>()
27
+ .context("Invalid PostgreSQL connection string")?;
28
+
29
+ let mut pool_config = Config::new();
30
+ pool_config.host = config.get_hosts().first()
31
+ .and_then(|h| match h {
32
+ tokio_postgres::config::Host::Tcp(s) => Some(s.clone()),
33
+ _ => None,
34
+ });
35
+ pool_config.port = config.get_ports().first().copied();
36
+ pool_config.user = config.get_user().map(|s| s.to_string());
37
+ pool_config.password = config.get_password().map(|p| String::from_utf8_lossy(p).to_string());
38
+ pool_config.dbname = config.get_dbname().map(|s| s.to_string());
39
+
40
+ // Configure connection pool for better resource management
41
+ // Limit max connections to avoid pool exhaustion
42
+ pool_config.manager = Some(deadpool_postgres::ManagerConfig {
43
+ recycling_method: deadpool_postgres::RecyclingMethod::Fast,
44
+ });
45
+ // Set max_size through pool_config fields directly
46
+ pool_config.pool = Some(deadpool_postgres::PoolConfig::new(10));
47
+
48
+ let pool = pool_config.create_pool(Some(Runtime::Tokio1), NoTls)
49
+ .context("Failed to create connection pool")?;
50
+
51
+ // Verify connection and pgvector extension
52
+ let client = pool.get().await.context("Failed to get connection from pool")?;
53
+ client.execute("SELECT 1", &[]).await.context("Failed to ping database")?;
54
+
55
+ // Check pgvector extension
56
+ let row = client.query_opt(
57
+ "SELECT extversion FROM pg_extension WHERE extname = 'vector'",
58
+ &[]
59
+ ).await.context("Failed to check pgvector extension")?;
60
+
61
+ if row.is_none() {
62
+ return Err(anyhow!("pgvector extension not installed. Run: CREATE EXTENSION vector;"));
63
+ }
64
+
65
+ let version: String = row.unwrap().get(0);
66
+ info!("Connected to PostgreSQL with pgvector v{}", version);
67
+ Ok(Self { pool })
68
+ }
69
+
70
+ /// Store an entity with its embedding
71
+ pub async fn store_entity_with_embedding(
72
+ &self,
73
+ entity: &Entity,
74
+ embedding: &[f32],
75
+ project_root: &str,
76
+ ) -> Result<i64> {
77
+ // Validate embedding dimension
78
+ if embedding.len() != EMBEDDING_DIMENSION {
79
+ return Err(anyhow!(
80
+ "Invalid embedding dimension: expected {}, got {} for entity '{}'",
81
+ EMBEDDING_DIMENSION, embedding.len(), entity.name
82
+ ));
83
+ }
84
+
85
+ let client = self.pool.get().await
86
+ .context(format!("Failed to get connection from pool for entity: {}", entity.name))?;
87
+
88
+ // Convert embedding to pgvector Vector type
89
+ let embedding_vec = Vector::from(embedding.to_vec());
90
+
91
+ let row = client.query_one(
92
+ r#"
93
+ INSERT INTO codesearch.embeddings (
94
+ entity_kind, entity_name, file_path, line_number,
95
+ signature, doc_comment, project_root, embedding
96
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
97
+ ON CONFLICT (project_root, file_path, entity_name, entity_kind, line_number)
98
+ DO UPDATE SET
99
+ signature = EXCLUDED.signature,
100
+ doc_comment = EXCLUDED.doc_comment,
101
+ embedding = EXCLUDED.embedding,
102
+ updated_at = NOW()
103
+ RETURNING id
104
+ "#,
105
+ &[
106
+ &format!("{:?}", entity.kind),
107
+ &entity.name,
108
+ &entity.file_path,
109
+ &(entity.line_number as i32),
110
+ &entity.signature,
111
+ &entity.doc_comment,
112
+ &project_root,
113
+ &embedding_vec,
114
+ ]
115
+ ).await.context(format!(
116
+ "Failed to store entity '{}' at {}:{}",
117
+ entity.name, entity.file_path, entity.line_number
118
+ ))?;
119
+
120
+ Ok(row.get::<_, i64>(0))
121
+ }
122
+
123
+ /// Search for similar entities by embedding
124
+ pub async fn search_similar(
125
+ &self,
126
+ query_embedding: &[f32],
127
+ max_results: usize,
128
+ threshold: f32,
129
+ project_root: Option<&str>,
130
+ ) -> Result<Vec<SearchResult>> {
131
+ // Validate query embedding dimension
132
+ if query_embedding.len() != EMBEDDING_DIMENSION {
133
+ return Err(anyhow!(
134
+ "Invalid query embedding dimension: expected {}, got {}",
135
+ EMBEDDING_DIMENSION, query_embedding.len()
136
+ ));
137
+ }
138
+
139
+ let client = self.pool.get().await.context("Failed to get connection")?;
140
+
141
+ // Convert query embedding to pgvector Vector type
142
+ let embedding_vec = Vector::from(query_embedding.to_vec());
143
+
144
+ debug!("Searching pgvector with threshold {} for {} results", threshold, max_results);
145
+
146
+ // Convert threshold to f64 for PostgreSQL float8 compatibility
147
+ let threshold_f64 = threshold as f64;
148
+
149
+ let rows = if let Some(project) = project_root {
150
+ client.query(
151
+ r#"
152
+ SELECT id, entity_kind, entity_name, file_path, line_number,
153
+ signature, doc_comment, project_root,
154
+ 1 - (embedding <=> $1) as similarity
155
+ FROM codesearch.embeddings
156
+ WHERE project_root = $2
157
+ AND 1 - (embedding <=> $1) >= $3
158
+ ORDER BY embedding <=> $1
159
+ LIMIT $4
160
+ "#,
161
+ &[
162
+ &embedding_vec,
163
+ &project,
164
+ &threshold_f64,
165
+ &(max_results as i64),
166
+ ]
167
+ ).await
168
+ } else {
169
+ client.query(
170
+ r#"
171
+ SELECT id, entity_kind, entity_name, file_path, line_number,
172
+ signature, doc_comment, project_root,
173
+ 1 - (embedding <=> $1) as similarity
174
+ FROM codesearch.embeddings
175
+ WHERE 1 - (embedding <=> $1) >= $2
176
+ ORDER BY embedding <=> $1
177
+ LIMIT $3
178
+ "#,
179
+ &[
180
+ &embedding_vec,
181
+ &threshold_f64,
182
+ &(max_results as i64),
183
+ ]
184
+ ).await
185
+ }.context("Failed to search embeddings")?;
186
+
187
+ let results = rows.iter().map(|row| {
188
+ SearchResult {
189
+ id: row.get::<_, i64>("id"),
190
+ entity_kind: row.get::<_, String>("entity_kind"),
191
+ entity_name: row.get::<_, String>("entity_name"),
192
+ file_path: row.get::<_, String>("file_path"),
193
+ line_number: row.get::<_, i32>("line_number") as i64,
194
+ signature: row.get::<_, Option<String>>("signature"),
195
+ doc_comment: row.get::<_, Option<String>>("doc_comment"),
196
+ project_root: row.get::<_, String>("project_root"),
197
+ similarity: row.get::<_, f64>("similarity") as f32,
198
+ }
199
+ }).collect();
200
+
201
+ Ok(results)
202
+ }
203
+
204
+ /// Get entity count by project
205
+ pub async fn get_entity_count(&self, project_root: Option<&str>) -> Result<i64> {
206
+ let client = self.pool.get().await.context("Failed to get connection")?;
207
+
208
+ let count: i64 = if let Some(project) = project_root {
209
+ let row = client.query_one(
210
+ "SELECT COUNT(*) FROM codesearch.embeddings WHERE project_root = $1",
211
+ &[&project]
212
+ ).await?;
213
+ row.get(0)
214
+ } else {
215
+ let row = client.query_one(
216
+ "SELECT COUNT(*) FROM codesearch.embeddings",
217
+ &[]
218
+ ).await?;
219
+ row.get(0)
220
+ };
221
+
222
+ Ok(count)
223
+ }
224
+
225
+ /// Delete entities for a file (for re-indexing)
226
+ pub async fn delete_file_entities(&self, file_path: &str, project_root: &str) -> Result<u64> {
227
+ let client = self.pool.get().await.context("Failed to get connection")?;
228
+
229
+ let result = client.execute(
230
+ "DELETE FROM codesearch.embeddings WHERE file_path = $1 AND project_root = $2",
231
+ &[&file_path, &project_root]
232
+ ).await.context("Failed to delete file entities")?;
233
+
234
+ Ok(result)
235
+ }
236
+ }
237
+
238
+ /// Search result from pgvector similarity search
239
+ #[derive(Debug, Clone, Serialize, Deserialize)]
240
+ pub struct SearchResult {
241
+ pub id: i64,
242
+ pub entity_kind: String,
243
+ pub entity_name: String,
244
+ pub file_path: String,
245
+ pub line_number: i64,
246
+ pub signature: Option<String>,
247
+ pub doc_comment: Option<String>,
248
+ pub project_root: String,
249
+ pub similarity: f32,
250
+ }
251
+
252
+ #[cfg(test)]
253
+ mod tests {
254
+ use super::*;
255
+
256
+ #[test]
257
+ fn test_embedding_dimension_constant() {
258
+ // Verify the constant matches the expected dimension for text-embedding-3-small
259
+ assert_eq!(EMBEDDING_DIMENSION, 1536);
260
+ }
261
+
262
+ #[test]
263
+ fn test_valid_embedding_dimension() {
264
+ let valid_embedding = vec![0.1f32; 1536];
265
+ assert_eq!(valid_embedding.len(), EMBEDDING_DIMENSION);
266
+ }
267
+
268
+ #[test]
269
+ fn test_invalid_embedding_dimension_too_small() {
270
+ let invalid_embedding = vec![0.1f32; 512];
271
+ assert_ne!(invalid_embedding.len(), EMBEDDING_DIMENSION);
272
+ assert!(invalid_embedding.len() < EMBEDDING_DIMENSION);
273
+ }
274
+
275
+ #[test]
276
+ fn test_invalid_embedding_dimension_too_large() {
277
+ let invalid_embedding = vec![0.1f32; 3072];
278
+ assert_ne!(invalid_embedding.len(), EMBEDDING_DIMENSION);
279
+ assert!(invalid_embedding.len() > EMBEDDING_DIMENSION);
280
+ }
281
+
282
+ #[tokio::test]
283
+ #[ignore = "Requires PostgreSQL with pgvector"]
284
+ async fn test_pgvector_connection() {
285
+ // This test requires CODESEARCH_PG_URL to be set
286
+ if let Ok(pg_url) = std::env::var("CODESEARCH_PG_URL") {
287
+ let store = PgvectorStore::new(&pg_url).await;
288
+ assert!(store.is_ok(), "Should connect to pgvector: {:?}", store.err());
289
+ }
290
+ }
291
+
292
+ #[tokio::test]
293
+ #[ignore = "Requires PostgreSQL with pgvector"]
294
+ async fn test_entity_count() {
295
+ if let Ok(pg_url) = std::env::var("CODESEARCH_PG_URL") {
296
+ let store = PgvectorStore::new(&pg_url).await.unwrap();
297
+ let count = store.get_entity_count(None).await;
298
+ assert!(count.is_ok(), "Should get entity count: {:?}", count.err());
299
+ }
300
+ }
301
+ }
@@ -9,6 +9,9 @@ use crate::schema_v2::{EntityKind, RefKind, Visibility};
9
9
  use crate::search_engine::SearchResult;
10
10
  use crate::path_validator;
11
11
 
12
+ /// Expected embedding dimension for text-embedding-3-small model
13
+ const EMBEDDING_DIMENSION: usize = 1536;
14
+
12
15
  #[derive(Debug, Clone, Serialize, Deserialize)]
13
16
  pub struct Entity {
14
17
  pub id: i64,
@@ -385,7 +388,15 @@ impl StoreV2 {
385
388
  // Embedding operations
386
389
  pub fn store_embedding(&self, entity_id: i64, embedding: &[f32], model: &str) -> Result<()> {
387
390
  debug!("Storing embedding for entity: {}", entity_id);
388
-
391
+
392
+ // Validate embedding dimension
393
+ if embedding.len() != EMBEDDING_DIMENSION {
394
+ return Err(anyhow!(
395
+ "Invalid embedding dimension: expected {}, got {} for entity_id {}",
396
+ EMBEDDING_DIMENSION, embedding.len(), entity_id
397
+ ));
398
+ }
399
+
389
400
  // Serialize embedding to bytes
390
401
  let embedding_bytes: Vec<u8> = embedding
391
402
  .iter()
@@ -1,5 +1,5 @@
1
1
  #!/bin/bash
2
- # test-agent-lifecycle-integration.sh - Test RuVector agent lifecycle integration
2
+ # test-agent-lifecycle-integration.sh - Test CodeSearch agent lifecycle integration
3
3
  #
4
4
  # Purpose: Verify that transcript ingestion and failure analysis work correctly
5
5
 
@@ -17,7 +17,7 @@ GREEN='\033[0;32m'
17
17
  YELLOW='\033[1;33m'
18
18
  NC='\033[0m' # No Color
19
19
 
20
- echo "=== RuVector Agent Lifecycle Integration Test ==="
20
+ echo "=== CodeSearch Agent Lifecycle Integration Test ==="
21
21
  echo ""
22
22
 
23
23
  # ============================================================================
@@ -195,17 +195,17 @@ echo ""
195
195
 
196
196
  echo "Test 5: Verifying metadata updates..."
197
197
 
198
- # Check if agent metadata was updated with RuVector processing flag
198
+ # Check if agent metadata was updated with CodeSearch processing flag
199
199
  METADATA=$(sqlite3 "$DB_PATH" "SELECT metadata FROM agents WHERE id = '$TEST_AGENT_ID';")
200
200
 
201
- if echo "$METADATA" | grep -q "ruvector_processed"; then
201
+ if echo "$METADATA" | grep -q "codesearch_processed"; then
202
202
  echo -e "${GREEN}✓${NC} Agent metadata updated with processing flag"
203
203
  else
204
204
  echo -e "${YELLOW}⚠${NC} Agent metadata not updated"
205
205
  fi
206
206
 
207
- if echo "$METADATA" | grep -q "ruvector_snippets"; then
208
- SNIPPET_COUNT_META=$(echo "$METADATA" | grep -o '"ruvector_snippets":[0-9]*' | cut -d':' -f2)
207
+ if echo "$METADATA" | grep -q "codesearch_snippets"; then
208
+ SNIPPET_COUNT_META=$(echo "$METADATA" | grep -o '"codesearch_snippets":[0-9]*' | cut -d':' -f2)
209
209
  echo -e "${GREEN}✓${NC} Snippet count recorded in metadata: $SNIPPET_COUNT_META"
210
210
  else
211
211
  echo -e "${YELLOW}⚠${NC} Snippet count not recorded"
@@ -1,13 +1,13 @@
1
1
  #!/bin/bash
2
- # test-local-ruvector.sh - Test Local RuVector implementation
2
+ # test-local-codesearch.sh - Test Local CodeSearch implementation
3
3
 
4
4
  set -e
5
5
 
6
6
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- STORAGE_PATH="${HOME}/.local-ruvector-test"
8
- TEST_DIR="/tmp/ruvector-test-project"
7
+ STORAGE_PATH="${HOME}/.local-codesearch-test"
8
+ TEST_DIR="/tmp/codesearch-test-project"
9
9
 
10
- echo "🧪 Testing Local RuVector Accelerator..."
10
+ echo "🧪 Testing Local CodeSearch Accelerator..."
11
11
 
12
12
  # Clean up previous test
13
13
  rm -rf "$STORAGE_PATH" "$TEST_DIR"
@@ -168,10 +168,10 @@ EOF
168
168
 
169
169
  echo "✅ Test files created"
170
170
 
171
- # Initialize Local RuVector
171
+ # Initialize Local CodeSearch
172
172
  echo ""
173
- echo "🚀 Initializing Local RuVector..."
174
- STORAGE_PATH="$STORAGE_PATH" "$SCRIPT_DIR/init-local-ruvector.sh"
173
+ echo "🚀 Initializing Local CodeSearch..."
174
+ STORAGE_PATH="$STORAGE_PATH" "$SCRIPT_DIR/init-local-codesearch.sh"
175
175
 
176
176
  # Index test files
177
177
  echo ""
@@ -9,7 +9,7 @@ echo "=== Testing Phase 4 Query API Implementation ==="
9
9
  echo
10
10
 
11
11
  # Check if the binary was built
12
- BINARY_PATH="./target/debug/local-ruvector"
12
+ BINARY_PATH="./target/debug/local-codesearch"
13
13
  if [ ! -f "$BINARY_PATH" ]; then
14
14
  echo "❌ Binary not found at $BINARY_PATH"
15
15
  echo "Please build the project first with: cargo build"
@@ -57,7 +57,7 @@ echo "✅ Created test_code/sample.rs"
57
57
  echo
58
58
 
59
59
  # Test 3: Initialize and index
60
- echo "4. Initializing ruvector..."
60
+ echo "4. Initializing codesearch..."
61
61
  $BINARY_PATH init --force
62
62
  echo
63
63