claude-flow-novice 2.18.21 → 2.18.23

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.
@@ -0,0 +1,150 @@
1
+ #!/bin/bash
2
+ # Memory Leak Prevention Script (ANTI-024)
3
+ # Detects and kills orphaned test processes (jest, vitest, node test runners)
4
+ #
5
+ # Usage:
6
+ # ./scripts/check-memory.sh # Report only
7
+ # ./scripts/check-memory.sh --kill # Kill orphans
8
+ # ./scripts/check-memory.sh --kill 500 # Kill if total MB > 500
9
+
10
+ set -euo pipefail
11
+
12
+ KILL_MODE=false
13
+ THRESHOLD_MB=0
14
+
15
+ # Parse arguments
16
+ while [[ $# -gt 0 ]]; do
17
+ case "$1" in
18
+ --kill)
19
+ KILL_MODE=true
20
+ shift
21
+ if [[ "${1:-}" =~ ^[0-9]+$ ]]; then
22
+ THRESHOLD_MB="$1"
23
+ shift
24
+ fi
25
+ ;;
26
+ --help|-h)
27
+ echo "Usage: $0 [--kill [threshold_mb]]"
28
+ echo " --kill Kill orphaned test processes"
29
+ echo " --kill 500 Only kill if total memory > 500MB"
30
+ exit 0
31
+ ;;
32
+ *)
33
+ shift
34
+ ;;
35
+ esac
36
+ done
37
+
38
+ # Find test-related processes
39
+ find_test_processes() {
40
+ # Jest, Vitest, and generic node test runners
41
+ pgrep -af "(jest|vitest|node.*test)" 2>/dev/null || true
42
+ }
43
+
44
+ # Calculate memory usage of test processes (in MB)
45
+ get_test_memory_mb() {
46
+ ps aux 2>/dev/null | grep -E "(jest|vitest|node.*test)" | grep -v grep | \
47
+ awk '{sum+=$6} END {print int(sum/1024)}' || echo "0"
48
+ }
49
+
50
+ # Find orphaned processes (parent PID = 1 or parent dead)
51
+ find_orphans() {
52
+ local orphans=()
53
+
54
+ while IFS= read -r line; do
55
+ local pid=$(echo "$line" | awk '{print $1}')
56
+ if [[ -z "$pid" ]]; then continue; fi
57
+
58
+ local ppid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ' || echo "")
59
+ if [[ -z "$ppid" ]]; then continue; fi
60
+
61
+ # Check if parent is init (1) or parent process doesn't exist
62
+ if [[ "$ppid" == "1" ]] || ! ps -p "$ppid" > /dev/null 2>&1; then
63
+ orphans+=("$pid")
64
+ fi
65
+ done < <(find_test_processes)
66
+
67
+ echo "${orphans[@]:-}"
68
+ }
69
+
70
+ # Kill processes gracefully
71
+ kill_processes() {
72
+ local pids=("$@")
73
+
74
+ for pid in "${pids[@]}"; do
75
+ if [[ -z "$pid" ]]; then continue; fi
76
+
77
+ echo "Killing orphaned process: $pid"
78
+
79
+ # Try SIGTERM first
80
+ kill -TERM "$pid" 2>/dev/null || continue
81
+
82
+ # Wait up to 5 seconds for graceful shutdown
83
+ local count=0
84
+ while ps -p "$pid" > /dev/null 2>&1 && [[ $count -lt 5 ]]; do
85
+ sleep 1
86
+ ((count++))
87
+ done
88
+
89
+ # Force kill if still running
90
+ if ps -p "$pid" > /dev/null 2>&1; then
91
+ echo "Force killing: $pid"
92
+ kill -KILL "$pid" 2>/dev/null || true
93
+ fi
94
+ done
95
+ }
96
+
97
+ # Main
98
+ main() {
99
+ local total_mb=$(get_test_memory_mb)
100
+ local orphans=($(find_orphans))
101
+ local orphan_count=${#orphans[@]}
102
+
103
+ echo "=== Memory Check (ANTI-024) ==="
104
+ echo "Test process memory: ${total_mb}MB"
105
+ echo "Orphaned processes: ${orphan_count}"
106
+
107
+ if [[ $orphan_count -gt 0 ]]; then
108
+ echo ""
109
+ echo "Orphan PIDs: ${orphans[*]}"
110
+
111
+ if $KILL_MODE; then
112
+ if [[ $THRESHOLD_MB -gt 0 ]] && [[ $total_mb -lt $THRESHOLD_MB ]]; then
113
+ echo "Memory ($total_mb MB) below threshold ($THRESHOLD_MB MB), skipping kill"
114
+ exit 0
115
+ fi
116
+
117
+ echo ""
118
+ echo "Killing orphaned processes..."
119
+ kill_processes "${orphans[@]}"
120
+
121
+ # Verify cleanup
122
+ sleep 1
123
+ local remaining=$(find_orphans | wc -w)
124
+ echo "Remaining orphans: $remaining"
125
+
126
+ if [[ $remaining -gt 0 ]]; then
127
+ echo "WARNING: Some processes could not be killed"
128
+ exit 1
129
+ fi
130
+ else
131
+ echo ""
132
+ echo "Run with --kill to terminate orphaned processes"
133
+ fi
134
+ else
135
+ echo "No orphaned test processes found"
136
+ fi
137
+
138
+ # Report current test processes
139
+ local running=$(find_test_processes | wc -l)
140
+ if [[ $running -gt 0 ]]; then
141
+ echo ""
142
+ echo "Running test processes: $running"
143
+ find_test_processes | head -5
144
+ if [[ $running -gt 5 ]]; then
145
+ echo "... and $((running - 5)) more"
146
+ fi
147
+ fi
148
+ }
149
+
150
+ main "$@"
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+ # Run command with memory limit enforcement (ANTI-024)
3
+ # Uses systemd-run when available, falls back to ulimit
4
+ #
5
+ # Usage:
6
+ # ./scripts/run-with-memory-limit.sh <memory_limit> <command...>
7
+ # ./scripts/run-with-memory-limit.sh 6G npm test
8
+ # ./scripts/run-with-memory-limit.sh 2G npm run test:unit
9
+
10
+ set -euo pipefail
11
+
12
+ MEMORY_LIMIT="${1:-6G}"
13
+ shift
14
+
15
+ if [[ $# -eq 0 ]]; then
16
+ echo "Usage: $0 <memory_limit> <command...>"
17
+ echo "Example: $0 6G npm test"
18
+ exit 1
19
+ fi
20
+
21
+ # Parse memory limit to bytes for ulimit fallback
22
+ parse_memory_to_kb() {
23
+ local mem="$1"
24
+ local num="${mem%[GgMmKk]*}"
25
+ local unit="${mem: -1}"
26
+
27
+ case "$unit" in
28
+ G|g) echo $((num * 1024 * 1024)) ;;
29
+ M|m) echo $((num * 1024)) ;;
30
+ K|k) echo "$num" ;;
31
+ *) echo "$mem" ;; # Assume KB if no unit
32
+ esac
33
+ }
34
+
35
+ # Check systemd availability
36
+ use_systemd() {
37
+ # Check if systemd-run exists and user session is available
38
+ command -v systemd-run >/dev/null 2>&1 && \
39
+ systemctl --user is-system-running >/dev/null 2>&1
40
+ }
41
+
42
+ # Check if running in WSL (systemd support varies)
43
+ is_wsl() {
44
+ grep -qi microsoft /proc/version 2>/dev/null
45
+ }
46
+
47
+ echo "=== Memory-Limited Execution (ANTI-024) ==="
48
+ echo "Limit: $MEMORY_LIMIT"
49
+ echo "Command: $*"
50
+ echo ""
51
+
52
+ if use_systemd; then
53
+ echo "Using: systemd-run (cgroups v2)"
54
+ echo ""
55
+
56
+ # Run with systemd memory limit
57
+ # --user: run as current user
58
+ # --scope: transient scope (not a service)
59
+ # -p MemoryMax: hard memory limit
60
+ # -p MemorySwapMax=0: disable swap so OOM killer triggers at limit
61
+ exec systemd-run --user --scope \
62
+ -p MemoryMax="$MEMORY_LIMIT" \
63
+ -p MemorySwapMax=0 \
64
+ --description="CFN test run with memory limit" \
65
+ "$@"
66
+
67
+ elif is_wsl; then
68
+ # WSL may not have full systemd support
69
+ echo "Using: ulimit (WSL detected, systemd unavailable)"
70
+ echo ""
71
+
72
+ MEM_KB=$(parse_memory_to_kb "$MEMORY_LIMIT")
73
+
74
+ # Set virtual memory limit (soft enforcement)
75
+ ulimit -v "$MEM_KB" 2>/dev/null || true
76
+
77
+ # Also set resident set size limit
78
+ ulimit -m "$MEM_KB" 2>/dev/null || true
79
+
80
+ exec "$@"
81
+
82
+ else
83
+ echo "Using: ulimit (systemd unavailable)"
84
+ echo ""
85
+
86
+ MEM_KB=$(parse_memory_to_kb "$MEMORY_LIMIT")
87
+ ulimit -v "$MEM_KB" 2>/dev/null || true
88
+ ulimit -m "$MEM_KB" 2>/dev/null || true
89
+
90
+ exec "$@"
91
+ fi
@@ -1,148 +1,148 @@
1
- # Claude Code Hooks
2
-
3
- This directory contains hooks that integrate with Claude Code's lifecycle events.
4
-
5
- ## cfn-precompact-enhanced.sh
6
-
7
- Enhanced PreCompact hook that preserves context before conversation compaction (manual or auto).
8
-
9
- ### Features
10
-
11
- **Context Preservation:**
12
- - Captures current git state (branch, status, recent commits)
13
- - Saves uncommitted and staged changes
14
- - Records modified files
15
-
16
- **Session Metrics:**
17
- - Counts recently edited files
18
- - Estimates session duration from git history
19
- - Detects test execution and status
20
- - Tracks tool usage (if transcript available)
21
- - Approximates token usage
22
-
23
- **CFN-Specific Detection:**
24
- - Active CFN Loop tasks
25
- - Running CFN Docker containers
26
- - Redis coordination state
27
- - Recent pre-edit backups
28
-
29
- **Output:**
30
- - Prints structured summary to stdout (injected into Claude's context)
31
- - Saves detailed JSON log to `.artifacts/precompact/session-{timestamp}.json`
32
- - Includes CLAUDE.md reminders for best practices
33
-
34
- ### Configuration
35
-
36
- The hook is configured in `.claude/settings.json`:
37
-
38
- ```json
39
- {
40
- "hooks": {
41
- "PreCompact": [
42
- {
43
- "matcher": "manual",
44
- "hooks": [
45
- {
46
- "type": "command",
47
- "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
48
- }
49
- ]
50
- },
51
- {
52
- "matcher": "auto",
53
- "hooks": [
54
- {
55
- "type": "command",
56
- "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
57
- }
58
- ]
59
- }
60
- ]
61
- }
62
- }
63
- ```
64
-
65
- ### Performance
66
-
67
- - **Timeout Protection**: 9-second overall script timeout
68
- - **Non-Blocking**: Always exits with code 0
69
- - **Optimized for WSL2**: Limits `find` depth and targets specific directories
70
- - **Graceful Degradation**: Continues if git/jq unavailable
71
-
72
- ### Testing
73
-
74
- ```bash
75
- # Test without stdin
76
- ./.claude/hooks/cfn-precompact-enhanced.sh
77
-
78
- # Test with simulated input
79
- echo '{"type": "manual", "compact_type": "manual"}' | \
80
- CLAUDE_PROJECT_DIR=$(pwd) bash .claude/hooks/cfn-precompact-enhanced.sh
81
- ```
82
-
83
- ### Output Example
84
-
85
- ```
86
- === PRE-COMPACT CONTEXT PRESERVATION ===
87
-
88
- Compact Type: manual
89
- Timestamp: 2025-12-10 04:46:26
90
-
91
- Git State:
92
- Branch: feature/auth-system
93
- Uncommitted: 3 files
94
- Modified: 2 files
95
- Staged: 1 files
96
- Last commit: abc123 - "Add JWT validation" (2 hours ago)
97
-
98
- Session Summary:
99
- Recent file edits: 5
100
- Duration: 45 minutes
101
- Tests run: true
102
- Test status: passing
103
- Tools used: 12 (Bash: 8, Edit: 4)
104
- Approx tokens: ~800
105
-
106
- Key Context:
107
- - Working directory: /path/to/project
108
- - Uncommitted changes
109
- - 2 CFN container(s) running
110
-
111
- Full context saved to: .artifacts/precompact/session-1765370786.json
112
-
113
- === CLAUDE.md REMINDERS ===
114
- • Use CFN Loop for multi-step tasks
115
- • Batch operations in single messages
116
- • Pre-edit backup required before edits
117
- • Run tests before commits
118
- • Use service names in Docker networks
119
- ```
120
-
121
- ### Artifacts
122
-
123
- Session data is preserved in:
124
- - `.artifacts/precompact/session-{timestamp}.json` - Full JSON context
125
- - `.artifacts/precompact/{timestamp}-git.diff` - Git diff (if changes exist)
126
- - `.artifacts/precompact/{timestamp}-commits.txt` - Recent commit history
127
- - `.artifacts/precompact/backup-{todo-file}-{timestamp}` - Copied todo files
128
-
129
- ### Environment Variables
130
-
131
- - `CLAUDE_PROJECT_DIR` - Project root (defaults to `pwd`)
132
- - `TRANSCRIPT_PATH` - Path to conversation transcript (optional, for tool usage stats)
133
- - `INPUT` - JSON input from Claude Code (compact_type, custom_instructions)
134
-
135
- ### Troubleshooting
136
-
137
- **Hook times out:**
138
- - Check if running on Windows mount (should be Linux filesystem)
139
- - Verify timeout settings in script (default 9 seconds)
140
- - Reduce `find` depth or target fewer directories
141
-
142
- **No JSON output:**
143
- - Ensure `.artifacts/precompact/` directory exists
144
- - Check for `jq` availability (gracefully degrades if missing)
145
-
146
- **Line ending issues:**
147
- - Convert to Unix line endings: `dos2unix .claude/hooks/cfn-precompact-enhanced.sh`
148
- - Or use: `sed -i 's/\r$//' .claude/hooks/cfn-precompact-enhanced.sh`
1
+ # Claude Code Hooks
2
+
3
+ This directory contains hooks that integrate with Claude Code's lifecycle events.
4
+
5
+ ## cfn-precompact-enhanced.sh
6
+
7
+ Enhanced PreCompact hook that preserves context before conversation compaction (manual or auto).
8
+
9
+ ### Features
10
+
11
+ **Context Preservation:**
12
+ - Captures current git state (branch, status, recent commits)
13
+ - Saves uncommitted and staged changes
14
+ - Records modified files
15
+
16
+ **Session Metrics:**
17
+ - Counts recently edited files
18
+ - Estimates session duration from git history
19
+ - Detects test execution and status
20
+ - Tracks tool usage (if transcript available)
21
+ - Approximates token usage
22
+
23
+ **CFN-Specific Detection:**
24
+ - Active CFN Loop tasks
25
+ - Running CFN Docker containers
26
+ - Redis coordination state
27
+ - Recent pre-edit backups
28
+
29
+ **Output:**
30
+ - Prints structured summary to stdout (injected into Claude's context)
31
+ - Saves detailed JSON log to `.artifacts/precompact/session-{timestamp}.json`
32
+ - Includes CLAUDE.md reminders for best practices
33
+
34
+ ### Configuration
35
+
36
+ The hook is configured in `.claude/settings.json`:
37
+
38
+ ```json
39
+ {
40
+ "hooks": {
41
+ "PreCompact": [
42
+ {
43
+ "matcher": "manual",
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "matcher": "auto",
53
+ "hooks": [
54
+ {
55
+ "type": "command",
56
+ "command": "/bin/bash .claude/hooks/cfn-precompact-enhanced.sh"
57
+ }
58
+ ]
59
+ }
60
+ ]
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Performance
66
+
67
+ - **Timeout Protection**: 9-second overall script timeout
68
+ - **Non-Blocking**: Always exits with code 0
69
+ - **Optimized for WSL2**: Limits `find` depth and targets specific directories
70
+ - **Graceful Degradation**: Continues if git/jq unavailable
71
+
72
+ ### Testing
73
+
74
+ ```bash
75
+ # Test without stdin
76
+ ./.claude/hooks/cfn-precompact-enhanced.sh
77
+
78
+ # Test with simulated input
79
+ echo '{"type": "manual", "compact_type": "manual"}' | \
80
+ CLAUDE_PROJECT_DIR=$(pwd) bash .claude/hooks/cfn-precompact-enhanced.sh
81
+ ```
82
+
83
+ ### Output Example
84
+
85
+ ```
86
+ === PRE-COMPACT CONTEXT PRESERVATION ===
87
+
88
+ Compact Type: manual
89
+ Timestamp: 2025-12-10 04:46:26
90
+
91
+ Git State:
92
+ Branch: feature/auth-system
93
+ Uncommitted: 3 files
94
+ Modified: 2 files
95
+ Staged: 1 files
96
+ Last commit: abc123 - "Add JWT validation" (2 hours ago)
97
+
98
+ Session Summary:
99
+ Recent file edits: 5
100
+ Duration: 45 minutes
101
+ Tests run: true
102
+ Test status: passing
103
+ Tools used: 12 (Bash: 8, Edit: 4)
104
+ Approx tokens: ~800
105
+
106
+ Key Context:
107
+ - Working directory: /path/to/project
108
+ - Uncommitted changes
109
+ - 2 CFN container(s) running
110
+
111
+ Full context saved to: .artifacts/precompact/session-1765370786.json
112
+
113
+ === CLAUDE.md REMINDERS ===
114
+ • Use CFN Loop for multi-step tasks
115
+ • Batch operations in single messages
116
+ • Pre-edit backup required before edits
117
+ • Run tests before commits
118
+ • Use service names in Docker networks
119
+ ```
120
+
121
+ ### Artifacts
122
+
123
+ Session data is preserved in:
124
+ - `.artifacts/precompact/session-{timestamp}.json` - Full JSON context
125
+ - `.artifacts/precompact/{timestamp}-git.diff` - Git diff (if changes exist)
126
+ - `.artifacts/precompact/{timestamp}-commits.txt` - Recent commit history
127
+ - `.artifacts/precompact/backup-{todo-file}-{timestamp}` - Copied todo files
128
+
129
+ ### Environment Variables
130
+
131
+ - `CLAUDE_PROJECT_DIR` - Project root (defaults to `pwd`)
132
+ - `TRANSCRIPT_PATH` - Path to conversation transcript (optional, for tool usage stats)
133
+ - `INPUT` - JSON input from Claude Code (compact_type, custom_instructions)
134
+
135
+ ### Troubleshooting
136
+
137
+ **Hook times out:**
138
+ - Check if running on Windows mount (should be Linux filesystem)
139
+ - Verify timeout settings in script (default 9 seconds)
140
+ - Reduce `find` depth or target fewer directories
141
+
142
+ **No JSON output:**
143
+ - Ensure `.artifacts/precompact/` directory exists
144
+ - Check for `jq` availability (gracefully degrades if missing)
145
+
146
+ **Line ending issues:**
147
+ - Convert to Unix line endings: `dos2unix .claude/hooks/cfn-precompact-enhanced.sh`
148
+ - Or use: `sed -i 's/\r$//' .claude/hooks/cfn-precompact-enhanced.sh`
@@ -1,35 +1,35 @@
1
- #!/bin/bash
2
-
3
- # SessionStart hook: Load OpenAI API key from root .env file
4
- # This ensures OPENAI_API_KEY is available for embedding generation
5
-
6
- set -e
7
-
8
- # Path to root .env file
9
- ROOT_ENV="${PROJECT_ROOT:-.}/.env"
10
-
11
- # Check if .env exists
12
- if [[ ! -f "$ROOT_ENV" ]]; then
13
- echo "⚠️ Warning: $ROOT_ENV not found. OpenAI embeddings will not work." >&2
14
- exit 0
15
- fi
16
-
17
- # Extract OPENAI_API_KEY from .env
18
- if grep -q "^OPENAI_API_KEY=" "$ROOT_ENV"; then
19
- # Export the key for this session
20
- export OPENAI_API_KEY=$(grep "^OPENAI_API_KEY=" "$ROOT_ENV" | cut -d'=' -f2- | tr -d '"')
21
-
22
- # Verify key is set
23
- if [[ -n "$OPENAI_API_KEY" ]]; then
24
- echo "✅ Loaded OPENAI_API_KEY from root .env" >&2
25
- else
26
- echo "⚠️ Warning: OPENAI_API_KEY found but empty in $ROOT_ENV" >&2
27
- fi
28
- else
29
- echo "⚠️ Warning: OPENAI_API_KEY not found in $ROOT_ENV. OpenAI embeddings will not work." >&2
30
- fi
31
-
32
- # Make it available to subprocesses
33
- export OPENAI_API_KEY
34
-
35
- exit 0
1
+ #!/bin/bash
2
+
3
+ # SessionStart hook: Load OpenAI API key from root .env file
4
+ # This ensures OPENAI_API_KEY is available for embedding generation
5
+
6
+ set -e
7
+
8
+ # Path to root .env file
9
+ ROOT_ENV="${PROJECT_ROOT:-.}/.env"
10
+
11
+ # Check if .env exists
12
+ if [[ ! -f "$ROOT_ENV" ]]; then
13
+ echo "⚠️ Warning: $ROOT_ENV not found. OpenAI embeddings will not work." >&2
14
+ exit 0
15
+ fi
16
+
17
+ # Extract OPENAI_API_KEY from .env
18
+ if grep -q "^OPENAI_API_KEY=" "$ROOT_ENV"; then
19
+ # Export the key for this session
20
+ export OPENAI_API_KEY=$(grep "^OPENAI_API_KEY=" "$ROOT_ENV" | cut -d'=' -f2- | tr -d '"')
21
+
22
+ # Verify key is set
23
+ if [[ -n "$OPENAI_API_KEY" ]]; then
24
+ echo "✅ Loaded OPENAI_API_KEY from root .env" >&2
25
+ else
26
+ echo "⚠️ Warning: OPENAI_API_KEY found but empty in $ROOT_ENV" >&2
27
+ fi
28
+ else
29
+ echo "⚠️ Warning: OPENAI_API_KEY not found in $ROOT_ENV. OpenAI embeddings will not work." >&2
30
+ fi
31
+
32
+ # Make it available to subprocesses
33
+ export OPENAI_API_KEY
34
+
35
+ exit 0
@@ -1,28 +1,28 @@
1
- #!/bin/bash
2
- # SessionStart hook: Build RuVector Rust binary if missing
3
- # This ensures RuVector is compiled on cfn init
4
-
5
- RUVECTOR_DIR="$(dirname "$(dirname "$(dirname "$0")")")/skills/cfn-local-ruvector-accelerator"
6
- BINARY="$RUVECTOR_DIR/target/release/local-ruvector"
7
-
8
- # Only build if binary doesn't exist
9
- if [ ! -f "$BINARY" ]; then
10
- echo "[cfn-build-ruvector] Binary not found, building..."
11
-
12
- # Check if Cargo is available
13
- if ! command -v cargo &> /dev/null; then
14
- echo "[cfn-build-ruvector] WARNING: Cargo not installed, skipping RuVector build"
15
- exit 0
16
- fi
17
-
18
- # Build release binary
19
- cd "$RUVECTOR_DIR" && cargo build --release --quiet 2>/dev/null
20
-
21
- if [ -f "$BINARY" ]; then
22
- echo "[cfn-build-ruvector] ✅ RuVector binary built successfully"
23
- else
24
- echo "[cfn-build-ruvector] WARNING: Build failed, RuVector unavailable"
25
- fi
26
- else
27
- echo "[cfn-build-ruvector] ✅ RuVector binary already exists"
28
- fi
1
+ #!/bin/bash
2
+ # SessionStart hook: Build RuVector Rust binary if missing
3
+ # This ensures RuVector is compiled on cfn init
4
+
5
+ RUVECTOR_DIR="$(dirname "$(dirname "$(dirname "$0")")")/skills/cfn-local-ruvector-accelerator"
6
+ BINARY="$RUVECTOR_DIR/target/release/local-ruvector"
7
+
8
+ # Only build if binary doesn't exist
9
+ if [ ! -f "$BINARY" ]; then
10
+ echo "[cfn-build-ruvector] Binary not found, building..."
11
+
12
+ # Check if Cargo is available
13
+ if ! command -v cargo &> /dev/null; then
14
+ echo "[cfn-build-ruvector] WARNING: Cargo not installed, skipping RuVector build"
15
+ exit 0
16
+ fi
17
+
18
+ # Build release binary
19
+ cd "$RUVECTOR_DIR" && cargo build --release --quiet 2>/dev/null
20
+
21
+ if [ -f "$BINARY" ]; then
22
+ echo "[cfn-build-ruvector] ✅ RuVector binary built successfully"
23
+ else
24
+ echo "[cfn-build-ruvector] WARNING: Build failed, RuVector unavailable"
25
+ fi
26
+ else
27
+ echo "[cfn-build-ruvector] ✅ RuVector binary already exists"
28
+ fi