claude-flow-novice 2.18.16 → 2.18.17

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 (70) hide show
  1. package/.claude/agents/cfn-dev-team/analysts/analyst.md +9 -0
  2. package/.claude/agents/cfn-dev-team/analysts/root-cause-analyst.md +9 -0
  3. package/.claude/agents/cfn-dev-team/architecture/api-designer-persona.md +10 -1
  4. package/.claude/agents/cfn-dev-team/architecture/base-template-generator.md +9 -0
  5. package/.claude/agents/cfn-dev-team/architecture/goal-planner.md +10 -1
  6. package/.claude/agents/cfn-dev-team/architecture/planner.md +9 -0
  7. package/.claude/agents/cfn-dev-team/architecture/system-architect.md +9 -0
  8. package/.claude/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +9 -0
  9. package/.claude/agents/cfn-dev-team/coordinators/consensus-builder.md +10 -1
  10. package/.claude/agents/cfn-dev-team/coordinators/handoff-coordinator.md +9 -0
  11. package/.claude/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +9 -0
  12. package/.claude/agents/cfn-dev-team/dev-ops/devops-engineer.md +9 -0
  13. package/.claude/agents/cfn-dev-team/dev-ops/docker-specialist.md +9 -0
  14. package/.claude/agents/cfn-dev-team/dev-ops/github-commit-agent.md +9 -0
  15. package/.claude/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +9 -0
  16. package/.claude/agents/cfn-dev-team/developers/api-gateway-specialist.md +9 -0
  17. package/.claude/agents/cfn-dev-team/developers/data/data-engineer.md +9 -0
  18. package/.claude/agents/cfn-dev-team/developers/database/database-architect.md +9 -0
  19. package/.claude/agents/cfn-dev-team/developers/database/supabase-specialist.md +9 -0
  20. package/.claude/agents/cfn-dev-team/developers/frontend/mobile-dev.md +10 -1
  21. package/.claude/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +10 -1
  22. package/.claude/agents/cfn-dev-team/developers/frontend/ui-designer.md +10 -1
  23. package/.claude/agents/cfn-dev-team/developers/graphql-specialist.md +9 -0
  24. package/.claude/agents/cfn-dev-team/developers/rust-developer.md +10 -1
  25. package/.claude/agents/cfn-dev-team/documentation/agent-type-guidelines.md +9 -0
  26. package/.claude/agents/cfn-dev-team/documentation/api-documentation.md +10 -1
  27. package/.claude/agents/cfn-dev-team/documentation/pseudocode.md +10 -1
  28. package/.claude/agents/cfn-dev-team/documentation/specification-agent.md +10 -1
  29. package/.claude/agents/cfn-dev-team/product-owners/accessibility-advocate-persona.md +10 -1
  30. package/.claude/agents/cfn-dev-team/product-owners/cto-agent.md +9 -0
  31. package/.claude/agents/cfn-dev-team/product-owners/power-user-persona.md +10 -1
  32. package/.claude/agents/cfn-dev-team/product-owners/product-owner.md +9 -0
  33. package/.claude/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +9 -0
  34. package/.claude/agents/cfn-dev-team/reviewers/quality/cyclomatic-complexity-reducer.md +9 -0
  35. package/.claude/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +9 -0
  36. package/.claude/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +10 -1
  37. package/.claude/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +9 -0
  38. package/.claude/agents/cfn-dev-team/testers/api-testing-specialist.md +9 -0
  39. package/.claude/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +9 -0
  40. package/.claude/agents/cfn-dev-team/testers/contract-tester.md +9 -0
  41. package/.claude/agents/cfn-dev-team/testers/e2e/playwright-tester.md +9 -0
  42. package/.claude/agents/cfn-dev-team/testers/integration-tester.md +9 -0
  43. package/.claude/agents/cfn-dev-team/testers/interaction-tester.md +9 -0
  44. package/.claude/agents/cfn-dev-team/testers/load-testing-specialist.md +9 -0
  45. package/.claude/agents/cfn-dev-team/testers/mutation-testing-specialist.md +9 -0
  46. package/.claude/agents/cfn-dev-team/testers/playwright-tester.md +10 -1
  47. package/.claude/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +10 -1
  48. package/.claude/agents/cfn-dev-team/testers/validation/validation-production-validator.md +10 -1
  49. package/.claude/agents/cfn-dev-team/testing/test-validation-agent.md +9 -0
  50. package/.claude/agents/cfn-dev-team/utility/agent-builder.md +10 -1
  51. package/.claude/agents/cfn-dev-team/utility/context-curator.md +9 -0
  52. package/.claude/agents/cfn-dev-team/utility/memory-leak-specialist.md +9 -0
  53. package/.claude/agents/cfn-dev-team/utility/researcher.md +9 -0
  54. package/.claude/agents/cfn-dev-team/utility/z-ai-specialist.md +9 -0
  55. package/.claude/hooks/SessionStart-cfn-build-ruvector.sh +12 -0
  56. package/.claude/hooks/SessionStart:cfn-build-ruvector.sh +28 -0
  57. package/.claude/skills/bulk-add-ruvector-instructions.sh +34 -46
  58. package/.claude/skills/cfn-local-ruvector-accelerator/.claude/hooks/SessionStart-cfn-build-ruvector.sh +12 -0
  59. package/.claude/skills/cfn-local-ruvector-accelerator/SKILL.md +89 -6
  60. package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/index.rs +36 -10
  61. package/.claude/skills/cfn-local-ruvector-accelerator/src/cli/index_ast.rs +4 -1
  62. package/.claude/skills/cfn-local-ruvector-accelerator/src/extractors/mod.rs +1 -1
  63. package/.claude/skills/cfn-local-ruvector-accelerator/src/migration_v2.rs +7 -7
  64. package/.claude/skills/cfn-local-ruvector-accelerator/src/query_api.rs +6 -3
  65. package/.claude/skills/cfn-local-ruvector-accelerator/src/schema_v2.rs +16 -1
  66. package/.claude/skills/cfn-local-ruvector-accelerator/src/store_v2.rs +7 -3
  67. package/.claude/skills/cfn-local-ruvector-accelerator/src/store_v2_tx.rs +5 -3
  68. package/.claude/skills/cfn-local-ruvector-accelerator/src/transaction_tests.rs +8 -2
  69. package/CLAUDE.md +2 -1
  70. package/package.json +1 -1
@@ -1,8 +1,91 @@
1
- # 1. Initialize local RuVector
2
- ./target/release/local-ruvector init
1
+ # RuVector Local Semantic Code Search
3
2
 
4
- # 2. Index your codebase
5
- ./target/release/local-ruvector index --path /path/to/project --types rs
3
+ ## WHEN TO USE THIS SKILL
6
4
 
7
- # 3. Query patterns instantly
8
- ./target/release/local-ruvector query --pattern "authentication rust" --limit 5
5
+ **USE RuVector V2 SQL for ALL indexed projects (400x FASTER than grep):**
6
+ ```bash
7
+ # Exact name lookup - 0.002s vs grep's 0.8s
8
+ sqlite3 ~/.local/share/ruvector/index_v2.db "SELECT file_path, line_number FROM entities WHERE name = 'MyFunction';"
9
+
10
+ # Fuzzy search - 0.004s
11
+ sqlite3 ~/.local/share/ruvector/index_v2.db "SELECT file_path, line_number FROM entities WHERE name LIKE '%Store%' LIMIT 10;"
12
+ ```
13
+
14
+ **USE grep/rg ONLY when:**
15
+ - Project is NOT indexed yet
16
+ - Searching for strings that aren't code entities (error messages, comments, config values)
17
+ - Quick one-off search in small directory
18
+
19
+ **USE RuVector semantic search when:**
20
+ - "Where is authentication implemented?" (conceptual search)
21
+ - Finding similar patterns you can't name exactly
22
+ - Discovering how a feature is built
23
+
24
+ ## Quick Commands
25
+
26
+ ### Semantic Search (V1 - Embeddings)
27
+ ```bash
28
+ # Natural language search
29
+ /codebase-search "authentication middleware pattern"
30
+ /cfn-ruvector-search "error handling in API routes"
31
+
32
+ # CLI direct
33
+ ./.claude/skills/cfn-local-ruvector-accelerator/target/release/local-ruvector query --pattern "user login flow"
34
+ ```
35
+
36
+ ### Structural Search (V2 - SQL on AST)
37
+ ```bash
38
+ # Find all callers of a function
39
+ sqlite3 ~/.local/share/ruvector/index_v2.db \
40
+ "SELECT * FROM refs WHERE target_name = 'MyFunction';"
41
+
42
+ # Find all functions in a file
43
+ sqlite3 ~/.local/share/ruvector/index_v2.db \
44
+ "SELECT name, line_number FROM entities WHERE file_path LIKE '%myfile.rs' AND kind = 'function';"
45
+
46
+ # Find entities by project (multi-project isolation)
47
+ sqlite3 ~/.local/share/ruvector/index_v2.db \
48
+ "SELECT COUNT(*) FROM entities WHERE project_root = '/path/to/project';"
49
+ ```
50
+
51
+ ## Index Management
52
+
53
+ ```bash
54
+ # Index a project (first time or full rebuild)
55
+ ./target/release/local-ruvector index --path /path/to/project --types rs,ts,py
56
+
57
+ # Incremental update (after code changes)
58
+ /codebase-reindex
59
+
60
+ # Check index stats
61
+ sqlite3 ~/.local/share/ruvector/index_v2.db "SELECT project_root, COUNT(*) FROM entities GROUP BY project_root;"
62
+ ```
63
+
64
+ ## Key Features
65
+
66
+ - **Multi-project isolation**: Index multiple projects in single database without data collision
67
+ - **Non-destructive**: Indexing one project never deletes data from other projects
68
+ - **Centralized storage**: `~/.local/share/ruvector/index_v2.db`
69
+ - **Dual search**: V1 semantic (embeddings) + V2 structural (SQL on AST)
70
+ - **Fast**: Rust binary with SQLite backend
71
+
72
+ ## Database Location
73
+ ```
74
+ ~/.local/share/ruvector/index_v2.db
75
+ ```
76
+
77
+ ## For Agents
78
+
79
+ Before implementing changes, ALWAYS query RuVector first:
80
+ ```bash
81
+ # Find similar patterns
82
+ /codebase-search "relevant search terms" --top 5
83
+
84
+ # Query past errors
85
+ ./.claude/skills/cfn-ruvector-codebase-index/query-error-patterns.sh --task-description "description"
86
+
87
+ # Query learnings
88
+ ./.claude/skills/cfn-ruvector-codebase-index/query-learnings.sh --task-description "description" --category PATTERN
89
+ ```
90
+
91
+ This prevents duplicated work and leverages existing solutions.
@@ -432,14 +432,21 @@ impl IndexCommand {
432
432
  ) -> Result<()> {
433
433
  let file_hash = self.calculate_file_hash(file_path)?;
434
434
 
435
+ // Check if file is already indexed with same hash (incremental indexing)
435
436
  if !self.force && self.is_file_indexed(file_path, &file_hash)? {
436
- debug!("Skipping already indexed file: {}", file_path.display());
437
+ debug!("Skipping already indexed file (unchanged): {}", file_path.display());
437
438
  return Ok(());
438
439
  }
439
440
 
440
- // Clean up old entries before reindexing to prevent duplicate entities
441
+ // Non-destructive update: Only delete entities for THIS specific file
442
+ // The delete_file_entities already scopes to project_root for multi-project safety
441
443
  let file_path_str = file_path.to_string_lossy();
442
- self.store_v2.delete_file_entities(&file_path_str, &self.project_dir)?;
444
+
445
+ // Only clean up if the file was previously indexed (avoid unnecessary DB operations)
446
+ if self.is_file_in_index(file_path)? {
447
+ debug!("Updating existing file entries: {}", file_path.display());
448
+ self.store_v2.delete_file_entities(&file_path_str, &self.project_dir)?;
449
+ }
443
450
 
444
451
  let content = fs::read_to_string(file_path)
445
452
  .with_context(|| format!("Failed to read file: {}", file_path.display()))?;
@@ -470,7 +477,7 @@ impl IndexCommand {
470
477
  s.embeddings_generated += embeddings.len();
471
478
  }
472
479
 
473
- self.mark_file_indexed(file_path, &file_hash)?;
480
+ self.mark_file_indexed(file_path, &file_hash, extraction_result.entities.len())?;
474
481
 
475
482
  Ok(())
476
483
  }
@@ -539,6 +546,7 @@ impl IndexCommand {
539
546
  doc_comment: None,
540
547
  attributes: None,
541
548
  metadata: Some(serde_json::to_string(&entity.metadata)?),
549
+ project_root: project_root_str.to_string(),
542
550
  created_at: chrono::Utc::now(),
543
551
  updated_at: chrono::Utc::now(),
544
552
  };
@@ -654,15 +662,33 @@ impl IndexCommand {
654
662
  Ok(count > 0)
655
663
  }
656
664
 
657
- fn mark_file_indexed(&self, file_path: &Path, file_hash: &str) -> Result<()> {
665
+ /// Check if file exists in the index (regardless of hash)
666
+ fn is_file_in_index(&self, file_path: &Path) -> Result<bool> {
667
+ let query = "SELECT COUNT(*) FROM file_hashes WHERE file_path = ?";
668
+ let mut stmt = self.store_v2.conn.prepare(query)?;
669
+ let count: i64 = stmt.query_row(
670
+ params![file_path.to_string_lossy()],
671
+ |row| row.get(0)
672
+ )?;
673
+ Ok(count > 0)
674
+ }
675
+
676
+ fn mark_file_indexed(&self, file_path: &Path, file_hash: &str, patterns_count: usize) -> Result<()> {
677
+ let timestamp = chrono::Utc::now().timestamp();
678
+ let file_path_str = file_path.to_string_lossy().to_string();
679
+
680
+ // Update file_hashes table (for incremental indexing)
658
681
  self.store_v2.conn.execute(
659
682
  "INSERT OR REPLACE INTO file_hashes (file_path, file_hash, indexed_at) VALUES (?1, ?2, ?3)",
660
- params![
661
- file_path.to_string_lossy(),
662
- file_hash,
663
- chrono::Utc::now().timestamp()
664
- ]
683
+ params![&file_path_str, file_hash, timestamp]
665
684
  )?;
685
+
686
+ // Also update the files table (for legacy compatibility and stats)
687
+ self.store_v2.conn.execute(
688
+ "INSERT OR REPLACE INTO files (path, hash, last_indexed, patterns_count) VALUES (?1, ?2, ?3, ?4)",
689
+ params![&file_path_str, file_hash, timestamp, patterns_count as i64]
690
+ )?;
691
+
666
692
  Ok(())
667
693
  }
668
694
 
@@ -299,6 +299,7 @@ impl AstIndexCommand {
299
299
  let mut entity_map = HashMap::new();
300
300
  let mut type_usages = Vec::new();
301
301
 
302
+ let project_root_str = self.project_dir.to_string_lossy().to_string();
302
303
  for (idx, entity) in extraction_result.entities.iter().enumerate() {
303
304
  let store_entity = StoreEntity {
304
305
  id: 0,
@@ -313,6 +314,7 @@ impl AstIndexCommand {
313
314
  doc_comment: None, // TODO: Extract doc comments
314
315
  attributes: None, // TODO: Extract attributes
315
316
  metadata: Some(serde_json::to_string(&entity.metadata)?),
317
+ project_root: project_root_str.clone(),
316
318
  created_at: chrono::Utc::now(),
317
319
  updated_at: chrono::Utc::now(),
318
320
  };
@@ -613,6 +615,7 @@ impl AstIndexCommand {
613
615
  Ok(entity.id)
614
616
  } else {
615
617
  // Create a placeholder entity for unknown references
618
+ let project_root_str = self.project_dir.to_string_lossy().to_string();
616
619
  let placeholder = StoreEntity {
617
620
  id: 0,
618
621
  kind: EntityKind::Function,
@@ -626,11 +629,11 @@ impl AstIndexCommand {
626
629
  doc_comment: None,
627
630
  attributes: None,
628
631
  metadata: None,
632
+ project_root: project_root_str.clone(),
629
633
  created_at: chrono::Utc::now(),
630
634
  updated_at: chrono::Utc::now(),
631
635
  };
632
636
 
633
- let project_root_str = self.project_dir.to_string_lossy();
634
637
  Ok(self.store_v2.insert_entity(&placeholder, &project_root_str)?)
635
638
  }
636
639
  }
@@ -28,7 +28,7 @@ pub fn create_text_fallback_extractor() -> Result<text_fallback::TextFallbackExt
28
28
  }
29
29
 
30
30
  /// Common entity kinds across languages
31
- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
31
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
32
32
  pub enum EntityKind {
33
33
  // Functions
34
34
  Function,
@@ -359,21 +359,21 @@ mod tests {
359
359
 
360
360
  SchemaV2::initialize(&conn)?;
361
361
 
362
- // Insert test entities with different path patterns
362
+ // Insert test entities with project_root set (schema now requires it)
363
363
  conn.execute(
364
- "INSERT INTO entities (kind, name, file_path, line_number) VALUES (?, ?, ?, ?)",
365
- params!["struct", "Test1", "/home/user/project/src/main.rs", 10]
364
+ "INSERT INTO entities (kind, name, file_path, line_number, project_root) VALUES (?, ?, ?, ?, ?)",
365
+ params!["struct", "Test1", "/home/user/project/src/main.rs", 10, "/home/user/project"]
366
366
  )?;
367
367
 
368
368
  conn.execute(
369
- "INSERT INTO entities (kind, name, file_path, line_number) VALUES (?, ?, ?, ?)",
370
- params!["function", "Test2", "/var/app/lib/utils.rs", 20]
369
+ "INSERT INTO entities (kind, name, file_path, line_number, project_root) VALUES (?, ?, ?, ?, ?)",
370
+ params!["function", "Test2", "/var/app/lib/utils.rs", 20, "/var/app"]
371
371
  )?;
372
372
 
373
- // Run migration
373
+ // Run migration (will be skipped since schema already has project_root)
374
374
  MigrationV2::run_v2_migration(&mut conn)?;
375
375
 
376
- // Verify project_root extraction
376
+ // Verify project_root values
377
377
  let project1: String = conn.query_row(
378
378
  "SELECT project_root FROM entities WHERE name = ?",
379
379
  params!["Test1"],
@@ -310,14 +310,15 @@ impl QueryApi {
310
310
  row.get::<_, Option<String>>(9)?, // doc_comment
311
311
  row.get::<_, Option<String>>(10)?, // attributes
312
312
  row.get::<_, Option<String>>(11)?, // metadata
313
- row.get::<_, i64>(12)?, // created_at
314
- row.get::<_, i64>(13)?, // updated_at
313
+ row.get::<_, String>(12)?, // project_root
314
+ row.get::<_, i64>(13)?, // created_at
315
+ row.get::<_, i64>(14)?, // updated_at
315
316
  ))
316
317
  })?;
317
318
 
318
319
  for row in rows {
319
320
  let row = row?;
320
- let (id, kind_str, name, signature, visibility_str, parent_id, file_path, line_number, column_number, doc_comment, attributes, metadata, created_at, updated_at) = row;
321
+ let (id, kind_str, name, signature, visibility_str, parent_id, file_path, line_number, column_number, doc_comment, attributes, metadata, project_root, created_at, updated_at) = row;
321
322
  // For now, just create a simple entity - the full parsing can be done later
322
323
  // This is just to get the IDs for reference finding
323
324
  matching_entities.push(crate::store_v2::Entity {
@@ -333,6 +334,7 @@ impl QueryApi {
333
334
  doc_comment,
334
335
  attributes,
335
336
  metadata,
337
+ project_root,
336
338
  created_at: chrono::DateTime::from_timestamp(created_at, 0).unwrap_or_default(),
337
339
  updated_at: chrono::DateTime::from_timestamp(updated_at, 0).unwrap_or_default(),
338
340
  });
@@ -366,6 +368,7 @@ impl QueryApi {
366
368
  doc_comment: None,
367
369
  attributes: None,
368
370
  metadata: None,
371
+ project_root: "".to_string(),
369
372
  created_at: chrono::DateTime::from_timestamp(0, 0).unwrap_or_default(),
370
373
  updated_at: chrono::DateTime::from_timestamp(0, 0).unwrap_or_default(),
371
374
  };
@@ -226,9 +226,10 @@ impl SchemaV2 {
226
226
  doc_comment TEXT,
227
227
  attributes TEXT,
228
228
  metadata TEXT,
229
+ project_root TEXT NOT NULL DEFAULT '',
229
230
  created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
230
231
  updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
231
-
232
+
232
233
  FOREIGN KEY (parent_id) REFERENCES entities(id) ON DELETE RESTRICT
233
234
  );
234
235
 
@@ -282,6 +283,14 @@ impl SchemaV2 {
282
283
 
283
284
  FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE RESTRICT
284
285
  );
286
+
287
+ -- Create files table for tracking indexed files (stats and legacy compatibility)
288
+ CREATE TABLE IF NOT EXISTS files (
289
+ path TEXT PRIMARY KEY,
290
+ hash TEXT NOT NULL,
291
+ last_indexed INTEGER NOT NULL,
292
+ patterns_count INTEGER NOT NULL DEFAULT 0
293
+ );
285
294
  "#
286
295
  )?;
287
296
 
@@ -311,6 +320,8 @@ impl SchemaV2 {
311
320
  CREATE INDEX IF NOT EXISTS idx_entities_kind_name ON entities(kind, name);
312
321
  CREATE INDEX IF NOT EXISTS idx_entities_file_kind ON entities(file_path, kind);
313
322
  CREATE INDEX IF NOT EXISTS idx_entities_parent_kind ON entities(parent_id, kind);
323
+ CREATE INDEX IF NOT EXISTS idx_entities_project_root ON entities(project_root);
324
+ CREATE INDEX IF NOT EXISTS idx_entities_project_file ON entities(project_root, file_path);
314
325
 
315
326
  -- Reference indexes
316
327
  CREATE INDEX IF NOT EXISTS idx_refs_source ON refs(source_entity_id);
@@ -338,6 +349,10 @@ impl SchemaV2 {
338
349
 
339
350
  -- Entity-module relationship index (via file path)
340
351
  CREATE INDEX IF NOT EXISTS idx_entities_module_lookup ON entities(file_path);
352
+
353
+ -- Files table indexes
354
+ CREATE INDEX IF NOT EXISTS idx_files_hash ON files(hash);
355
+ CREATE INDEX IF NOT EXISTS idx_files_last_indexed ON files(last_indexed);
341
356
  "#
342
357
  )?;
343
358
 
@@ -23,6 +23,7 @@ pub struct Entity {
23
23
  pub doc_comment: Option<String>,
24
24
  pub attributes: Option<String>,
25
25
  pub metadata: Option<String>,
26
+ pub project_root: String,
26
27
  pub created_at: DateTime<Utc>,
27
28
  pub updated_at: DateTime<Utc>,
28
29
  }
@@ -558,8 +559,9 @@ impl StoreV2 {
558
559
 
559
560
  // Helper methods to convert rows to structs
560
561
  pub(crate) fn row_to_entity(&self, row: &Row) -> rusqlite::Result<Entity> {
561
- let created_timestamp: i64 = row.get(12)?;
562
- let updated_timestamp: i64 = row.get(13)?;
562
+ let project_root: String = row.get(12)?;
563
+ let created_timestamp: i64 = row.get(13)?;
564
+ let updated_timestamp: i64 = row.get(14)?;
563
565
 
564
566
  let kind_str = row.get::<_, String>(1)?;
565
567
  let kind = EntityKind::from_str(&kind_str)
@@ -582,6 +584,7 @@ impl StoreV2 {
582
584
  doc_comment: row.get(9)?,
583
585
  attributes: row.get(10)?,
584
586
  metadata: row.get(11)?,
587
+ project_root,
585
588
  created_at: DateTime::from_timestamp(created_timestamp, 0).unwrap_or_default(),
586
589
  updated_at: DateTime::from_timestamp(updated_timestamp, 0).unwrap_or_default(),
587
590
  })
@@ -664,11 +667,12 @@ mod tests {
664
667
  doc_comment: Some("Test function".to_string()),
665
668
  attributes: None,
666
669
  metadata: None,
670
+ project_root: "/test/project".to_string(),
667
671
  created_at: Utc::now(),
668
672
  updated_at: Utc::now(),
669
673
  };
670
674
 
671
- let entity_id = store.insert_entity(&entity)?;
675
+ let entity_id = store.insert_entity(&entity, "/test/project")?;
672
676
  assert!(entity_id > 0);
673
677
 
674
678
  // Retrieve entity
@@ -225,10 +225,11 @@ impl StoreV2WithTx {
225
225
  // Execute the callback
226
226
  f(&tx)?;
227
227
 
228
- // Record file hash
228
+ // Record file hash with current timestamp
229
+ let current_time = chrono::Utc::now().timestamp();
229
230
  tx.execute(
230
- "INSERT INTO file_hashes (file_path, file_hash) VALUES (?, ?)",
231
- params![file_path, file_hash],
231
+ "INSERT INTO file_hashes (file_path, file_hash, indexed_at) VALUES (?, ?, ?)",
232
+ params![file_path, file_hash, current_time],
232
233
  )?;
233
234
 
234
235
  tx.commit()
@@ -308,6 +309,7 @@ mod tests {
308
309
  doc_comment: None,
309
310
  attributes: None,
310
311
  metadata: None,
312
+ project_root: "/test/project".to_string(),
311
313
  created_at: Utc::now(),
312
314
  updated_at: Utc::now(),
313
315
  }).collect();
@@ -44,6 +44,7 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
44
44
  doc_comment: None,
45
45
  attributes: None,
46
46
  metadata: None,
47
+ project_root: "/test/project".to_string(),
47
48
  created_at: chrono::Utc::now(),
48
49
  updated_at: chrono::Utc::now(),
49
50
  };
@@ -67,6 +68,7 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
67
68
  doc_comment: None,
68
69
  attributes: None,
69
70
  metadata: None,
71
+ project_root: "/test/project".to_string(),
70
72
  created_at: chrono::Utc::now(),
71
73
  updated_at: chrono::Utc::now(),
72
74
  };
@@ -84,6 +86,7 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
84
86
  doc_comment: None,
85
87
  attributes: None,
86
88
  metadata: None,
89
+ project_root: "/test/project".to_string(),
87
90
  created_at: chrono::Utc::now(),
88
91
  updated_at: chrono::Utc::now(),
89
92
  };
@@ -92,8 +95,8 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
92
95
  r#"
93
96
  INSERT INTO entities (
94
97
  kind, name, signature, visibility, parent_id, file_path,
95
- line_number, column_number, doc_comment, attributes, metadata
96
- ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
98
+ line_number, column_number, doc_comment, attributes, metadata, project_root
99
+ ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)
97
100
  "#
98
101
  )?;
99
102
 
@@ -109,6 +112,7 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
109
112
  entity1.doc_comment,
110
113
  entity1.attributes,
111
114
  entity1.metadata,
115
+ entity1.project_root,
112
116
  ])?;
113
117
 
114
118
  stmt.execute(params![
@@ -123,6 +127,7 @@ fn test_atomic_file_indexing_with_rollback() -> Result<()> {
123
127
  entity2.doc_comment,
124
128
  entity2.attributes,
125
129
  entity2.metadata,
130
+ entity2.project_root,
126
131
  ])?;
127
132
 
128
133
  Ok(())
@@ -220,6 +225,7 @@ fn test_batch_insert_rollback() -> Result<()> {
220
225
  doc_comment: None,
221
226
  attributes: None,
222
227
  metadata: None,
228
+ project_root: "/test/project".to_string(),
223
229
  created_at: chrono::Utc::now(),
224
230
  updated_at: chrono::Utc::now(),
225
231
  });
package/CLAUDE.md CHANGED
@@ -24,7 +24,8 @@ Purpose: concise reference for CFN agents. Focus on persona, mandatory rules, ed
24
24
  - Do not run tests inside agents; run once via coordinator/main chat, agents read results.
25
25
  - Never save to project root; use appropriate subdirectories.
26
26
  - Never hardcode secrets; always redact as `[REDACTED]`.
27
- - Prefer `rg`/`grep` over `find`; when monitoring, sleep-check-sleep loops.
27
+ - Use RuVector SQL for indexed projects (400x faster than grep); use grep only for non-indexed projects or non-code strings.
28
+ - When monitoring, sleep-check-sleep loops.
28
29
  - All agent communication must use coordination protocols; no ad-hoc file coordination.
29
30
 
30
31
  ## 3) Cerebras MCP & Context Discovery Protocols
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow-novice",
3
- "version": "2.18.16",
3
+ "version": "2.18.17",
4
4
  "description": "Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture\n\nIncludes Local RuVector Accelerator and all CFN skills for complete functionality.",
5
5
  "main": "index.js",
6
6
  "type": "module",