claude-flow-novice
Version:
Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.
307 lines (235 loc) • 9.59 kB
Markdown
# RuVector Indexing Failure - Root Cause Analysis
## Executive Summary
The RuVector codebase indexer fails to index more than 1 file due to **multiple architectural issues** in the script coordination between Bash and Node.js. The failures manifest as either missing dependencies, incorrect module paths, or missing environment variables.
## Critical Findings
### Root Cause #1: Missing TypeScript Dependency (Primary Blocker)
**Location:** `.claude/skills/ruvector-codebase-index/parser.js:14`
**Issue:**
```javascript
import ts from 'typescript';
```
**Evidence:**
```
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'typescript' imported from
/tmp/cfn-index/.claude/skills/ruvector-codebase-index/parser.js
```
**Impact:** Script fails immediately when trying to parse any file because TypeScript is not installed in the skill's node_modules.
**Severity:** CRITICAL - Blocks all file indexing operations
---
### Root Cause #2: Incorrect RuVector Initialization Path
**Location:** `.claude/skills/ruvector-codebase-index/indexer.js:8`
**Issue:**
```javascript
import { initializeRuVector, getCollection, COLLECTIONS } from '../../../docker/trigger-dev/src/lib/ruvector-init.ts';
```
**Evidence:**
```
Error [ERR_MODULE_NOT_FOUND]: Cannot find module
'/mnt/c/Users/masha/Documents/claude-flow-novice/.claude/skills/ruvector-codebase-index/docker/trigger-dev/src/lib/ruvector-init.ts'
```
**Analysis:**
- Path is relative to `.claude/skills/ruvector-codebase-index/`
- `../../../docker/trigger-dev/src/lib/ruvector-init.ts` resolves to `.claude/skills/ruvector-codebase-index/docker/trigger-dev/src/lib/ruvector-init.ts` (WRONG)
- Should resolve to `/mnt/c/Users/masha/Documents/claude-flow-novice/docker/trigger-dev/src/lib/ruvector-init.ts` (CORRECT)
**Impact:** Database initialization fails when running from copied `/tmp` location
**Severity:** CRITICAL - Prevents RuVector database setup
---
### Root Cause #3: Environment Variable Not Propagated to Subprocesses
**Location:** `.claude/skills/ruvector-codebase-index/index.sh:175`
**Issue:**
```bash
embedding=$(node "$EMBEDDINGS_JS" "$embedding_text") || {
```
**Evidence:**
```
OpenAIError: The OPENAI_API_KEY environment variable is missing or empty
```
**Analysis:**
- `index.sh` loads `.env` with `set -a; source .env; set +a` (lines 21-25)
- Environment variables are set in the parent bash process
- Node.js subprocess spawned at line 175 doesn't inherit `OPENAI_API_KEY`
- The `node -e` calls at lines 86 and 164 also don't inherit environment
**Impact:** Embedding generation fails even when API key exists in .env
**Severity:** HIGH - Blocks embedding generation after parsing succeeds
---
### Root Cause #4: Inline Node.js Eval with Incorrect Module Resolution
**Location:** `.claude/skills/ruvector-codebase-index/index.sh:86-99, 164-168`
**Issue:**
```bash
node -e "
import { initializeRuVector, getCollection, COLLECTIONS } from '$PROJECT_ROOT/docker/trigger-dev/src/lib/ruvector-init.ts';
..."
```
**Analysis:**
- Using `node -e` with dynamic imports of TypeScript files (.ts)
- Node.js ESM loader cannot resolve `.ts` extensions without tsx/ts-node
- Variable substitution in heredocs can break ESM syntax
- No error handling or output capture from inline eval
**Impact:** Database initialization via inline script fails silently or with cryptic errors
**Severity:** HIGH - Unreliable initialization pattern
---
### Root Cause #5: Script Exits After Single File (Design Flaw)
**Location:** `.claude/skills/ruvector-codebase-index/indexer.js:52`
**Issue:**
```javascript
await indexFile(filePath, embedding, metadata);
process.exit(0);
```
**Analysis:**
- `indexer.js` is designed as a CLI tool that processes **one file per invocation**
- Each call to `node "$SCRIPT_DIR/indexer.js"` (index.sh:187) starts a new Node process
- Each process initializes RuVector database from scratch (line 13)
- Process exits immediately after indexing one file (line 52)
- Loop in index.sh:219-230 calls indexer.js 10,758 times sequentially
- Each call has initialization overhead + database connection overhead
**Impact:**
- Extremely slow (10,758 process spawns)
- Potential race conditions on database file
- Connection pool exhaustion
- Previous team likely cancelled after seeing "1 file indexed" and slow progress
**Severity:** MEDIUM - Performance/design issue, not a hard failure
---
## Secondary Issues
### Issue #6: Missing package.json in Skill Directory
**Evidence:** No `package.json` found at `.claude/skills/ruvector-codebase-index/`
**Impact:**
- No dependency declaration for `typescript`, `openai`, `ts-node`
- Cannot run `npm install` to fix dependencies
- Developers don't know what dependencies are required
---
### Issue #7: No Error Recovery or Partial Success Handling
**Location:** `.claude/skills/ruvector-codebase-index/index.sh:225-229`
**Issue:**
```bash
if index_file "$file"; then
((success++))
else
((failed++))
fi
```
**Analysis:**
- First failure prevents any further indexing
- No checkpoint/resume capability
- No logging of which files succeeded before failure
- Counter increments are meaningless if script exits early
---
## Why "Only 1 File Indexed"
The exact sequence of failures:
1. **Test Mode (a18d60):** Successfully indexed 1 file, then hit TypeScript missing error
2. **Production Runs:** Hit one of the critical errors immediately:
- Missing TypeScript (847694, a18d60)
- Missing OPENAI_API_KEY in subprocess (3ef465, 13b09c, c7c08c)
- Wrong ruvector-init.ts path (736cb4)
3. **Apparent Success, Then Failure:**
- Database initializes successfully
- Finds 10,758 files
- Starts indexing file 1
- Parsing fails (missing TypeScript) OR embedding fails (missing API key)
- Error handler logs error but continues loop
- Next file hits same error
- User cancels after seeing no progress
---
## Recommended Fixes (Priority Order)
### Fix #1: Add package.json and Install Dependencies
```bash
cd .claude/skills/ruvector-codebase-index
cat > package.json << 'EOF'
{
"name": "ruvector-codebase-index",
"type": "module",
"dependencies": {
"typescript": "^5.7.2",
"openai": "^4.77.3",
"tsx": "^4.19.2"
}
}
EOF
npm install
```
### Fix #2: Fix Import Paths Using Environment Variables
**indexer.js:8**
```javascript
// Use environment variable for project root
const PROJECT_ROOT = process.env.PROJECT_ROOT || process.cwd();
import(`${PROJECT_ROOT}/docker/trigger-dev/src/lib/ruvector-init.ts`)
.then(({ initializeRuVector, getCollection, COLLECTIONS }) => {
// ... rest of logic
});
```
OR create a shared module with absolute imports using project root detection.
### Fix #3: Propagate Environment to Node Subprocesses
**index.sh:175**
```bash
# Explicitly pass environment variables to Node.js
OPENAI_API_KEY="$OPENAI_API_KEY" ZAI_API_KEY="${ZAI_API_KEY:-}" node "$EMBEDDINGS_JS" "$embedding_text" || {
```
### Fix #4: Batch Processing Architecture (Recommended)
**Replace per-file process spawning with batch processing:**
Create `batch-indexer.js`:
```javascript
import { initializeRuVector } from '../../../docker/trigger-dev/src/lib/ruvector-init.ts';
// Initialize ONCE
await initializeRuVector();
// Read file list from stdin
for await (const filePath of readLines(process.stdin)) {
try {
await indexFile(filePath);
console.log(`SUCCESS: ${filePath}`);
} catch (err) {
console.error(`ERROR: ${filePath}: ${err.message}`);
}
}
```
**index.sh:219-230**
```bash
# Stream all files to batch indexer
printf '%s\n' "${files[@]}" | node "$SCRIPT_DIR/batch-indexer.js"
```
**Benefits:**
- 1 process instead of 10,758
- Database initialized once
- Connection pooling
- Progress tracking
- 100x+ faster
### Fix #5: Use tsx Instead of node for TypeScript
**All node commands should use tsx:**
```bash
npx tsx "$PARSER_JS" "$file_path"
npx tsx "$EMBEDDINGS_JS" "$embedding_text"
npx tsx "$SCRIPT_DIR/indexer.js" ...
```
---
## Testing Verification Steps
1. **Verify dependencies installed:**
```bash
cd .claude/skills/ruvector-codebase-index
npm ls typescript openai tsx
```
2. **Test single file parsing:**
```bash
cd .claude/skills/ruvector-codebase-index
npx tsx parser.js ../../../CLAUDE.md
```
3. **Test environment propagation:**
```bash
source .env
echo "API Key present: ${OPENAI_API_KEY:+YES}"
OPENAI_API_KEY="$OPENAI_API_KEY" node -e "console.log(process.env.OPENAI_API_KEY)"
```
4. **Test batch indexing (after implementing Fix #4):**
```bash
echo -e "./CLAUDE.md\n./README.md" | npx tsx batch-indexer.js
```
---
## Conclusion
The indexer's "1 file only" behavior is caused by:
1. **Hard blocker:** Missing TypeScript dependency
2. **Configuration error:** Environment variables not passed to Node subprocesses
3. **Architectural flaw:** Per-file process spawning instead of batch processing
4. **Import path bug:** Relative paths break when script is copied to /tmp
**All issues are fixable.** Priority should be:
1. Add package.json + npm install (5 minutes)
2. Fix environment variable propagation (2 minutes)
3. Refactor to batch processing architecture (30 minutes)
4. Fix import paths using absolute resolution (15 minutes)
**Estimated time to full resolution:** 1-2 hours