Analyzed codebase for improvement areas.
UnderstandFlagged critical security issue with API key.
EditCompiled detailed top-10 improvement list.
VerifyAnalyze the Spark Intelligence codebase in this directory. Find top 10 areas for improvement in code quality, architecture, features, performance, security, docs, and UX. Be specific with file names.
Here's my analysis of the websocket-rate-limiter codebase โ top 10 areas for improvement:
1. ๐ Security: No message size limit โ src/websocket-handler.ts
handleMessage() accepts rawMessage: string with no size check. A client can send a 500MB JSON payload and you'll happily JSON.parse() it. Add a maxMessageSize config and reject oversized messages before parsing.
2. ๐๏ธ Architecture: check() has a side effect โ src/rate-limiter.ts
check() both evaluates and consumes a request slot (pushes to requests[]). The consume() method's docstring even warns about this. This is confusing API design โ split into check() (read-only) and consume() (mutating), or rename check to tryConsume to make the side effect obvious.
3. ๐งช Test coverage: No tests for websocket-handler.ts error handling in handlers โ tests/rate-limiter.test.ts
There's no test for when a registered handler throws an error (the catch block in handleMessage). Also missing: tests for destroy(), getRateLimiter(), and the startCleanup/stopCleanup lifecycle. The handler error path silently logs to console.error โ untested.
4. โก Performance: Unbounded requests[] array with linear filter โ src/rate-limiter.ts
Every check() call does state.requests.filter(ts => ts > windowStart), which is O(n). For high-throughput presets (burst: 50/sec), this array grows fast. Use a circular buffer or simple counter with timestamp buckets instead.
5. ๐ Docs: Zero documentation โ No README.md
No README, no API docs, no usage examples. For a library package ("main": "dist/index.js"), this is critical. Users won't know how to use createRateLimitedHandler vs RateLimitedWebSocketServer or when to pick which.
6. ๐๏ธ Architecture: No actual WebSocket dependency โ src/websocket-handler.ts
The WebSocketClient interface is custom but there's no integration with any real WS library (ws, uWebSockets.js, etc.). The package exports a handler but provides no way to actually create a WebSocket server. Add an adapter or at least document how to wire it to ws.
7. ๐ Bug: Memory leak with startCleanup โ src/rate-limiter.ts
RateLimitedWebSocketServer calls this.rateLimiter.startCleanup() in the constructor, creating a setInterval that holds a reference. If destroy() isn't called (common in real apps), the interval keeps the limiter in memory forever. The interval should use unref() so it doesn't prevent Node process exit.
8. ๐ง Code quality: tsconfig.json has loose settings โ tsconfig.json
noUnusedLocals: false, noUnusedParameters: false, noFallthroughCasesInSwitch: false โ these should all be true for a library. Also missing: forceConsistentCasingInFileNames, resolveJsonModule. The experimentalDecorators flag is enabled but no decorators are used.
9. ๐ฏ Feature gap: No per-message-type rate limiting โ src/websocket-handler.ts
All message types share one global rate limit. In practice, you'd want different limits for subscribe vs chat vs ping. The on() method should accept optional per-type rate limit configs.
10. ๐ฆ Package hygiene: No .npmignore or files field โ package.json
Publishing this package would include tests/, src/, tmp_screen.png (660KB!), memory files, and all workspace cruft. Add "files": ["dist"] to package.json to ship only the compiled output.
Analyze THIS codebase (Spark Intelligence, the current directory). Find the top 10 areas for improvement in: - Code quality - Architecture - Missing features - Performance - Security - Documentation - User experience Be specific with file names and line numbers.
Let me find the actual Spark Intelligence codebase.
This is a substantial codebase. Let me read the key files to give a precise analysis.
retry
๐จ Critical finding first: Your .env file contains a live ElevenLabs API key (sk_8fe8c3cc...). Even though .env is in .gitignore, I want to flag it immediately. If this repo was ever force-pushed or the gitignore was bypassed, that key is leaked. Consider rotating it.
Here's the full top-10 analysis of vibeship-spark-intelligence:
.env fileFile: .env (line 24)
The ElevenLabs key sk_8fe8c3ccc4efb57b... is sitting in the repo root. While .gitignore covers .env, the file also gets read by a hand-rolled parser in spark_voice_addon.py (lines 18-25) that split('=', 1) and jams values into os.environ โ no validation, no masking. If any logging or diagnostics dump os.environ, the key leaks. Fix: Use python-dotenv, move secrets to a keychain/1Password, and add a pre-commit hook to scan for key patterns.
advisory_engine.py is a 2,815-line god module with 67 except Exception blocksFile: lib/advisory_engine.py
This single file has ~60 env-var-driven feature flags (lines 19-95), dozens of JSONL file paths, and 67 blanket exception handlers. Every failure is silently swallowed. The module handles advisory orchestration, deduplication, rate limiting, JSONL ledger management, prefetching, and synthesis routing โ all in one file. Fix: Split into advisory/engine.py, advisory/dedupe.py, advisory/ledger.py, advisory/prefetch.py. Replace except Exception with specific exception types and structured logging.
lib/Files: 55+ files in lib/ with 3+ except Exception each (see counts above)
advisor.py alone has 80 bare except Exception catches. advisory_packet_store.py has 62. bridge_cycle.py has 37. These silently eat real bugs โ corrupted state, broken JSON, missing files โ and make debugging nearly impossible. Fix: Audit every catch; log at minimum; use narrow exception types (json.JSONDecodeError, FileNotFoundError, sqlite3.OperationalError).
Files: lib/advisory_engine.py (lines 22-26), lib/advisory_packet_store.py, lib/queue.py
The codebase uses ~15+ JSONL files (advisory_engine.jsonl, advisory_decision_ledger.jsonl, advisory_global_dedupe.jsonl, etc.) as primary storage. _tail_jsonl() (advisory_engine.py ~135) reads chunks from the end of the file every call. _append_jsonl_capped() (~165) rewrites the entire file when it exceeds max lines. With GLOBAL_DEDUPE_LOG_MAX = 5000 and frequent advisory cycles, this is O(n) on every advisory. Fix: Use SQLite (you already have memory_store.py with it) or at least add mmap-based tail reads.
File: lib/advisory_engine.py (lines 19-95), scattered across lib/*.py
Configuration is spread across raw os.getenv() calls with string-to-bool/float conversions wrapped in try/except. Typos in env var names fail silently. There's a tuneables_schema.py (600 lines) but it's not enforced at startup. Fix: Consolidate all config into a single Pydantic Settings model validated at import time. Fail fast on invalid config.
Files: README.md (referenced in pyproject.toml but not verified), no docs/ directory
A 140k+ line codebase with 170+ Python files, 80+ tests, a daemon (sparkd.py), a dashboard, a CLI, a FastAPI server (mind_server.py), and multiple adapters โ but no architecture overview, no getting-started guide, no module dependency diagram. The 20+ markdown files (SPARK_EMOTIONS.md, META_RALPH.md, STUCK_STATE_PLAYBOOK.md, etc.) are design docs, not user docs. Fix: Write a README with quickstart, architecture diagram, and module map.
.env parser in spark_voice_addon.pyFile: spark_voice_addon.py (lines 18-25)
The .env parser splits on = once, then strips comments with split('#')[0] โ which breaks values containing # (e.g., color codes, URL fragments). It also loads .env on every import of the module, polluting os.environ globally. Fix: Use python-dotenv (already a common dependency pattern). Load once at module init with override=False.
/healthFile: sparkd.py (lines 1-15)
The daemon has /health and /status endpoints but no readiness/liveness differentiation, no dependency health checks (SQLite writable? Embeddings model loaded? Claude CLI reachable?), and no circuit breaker for the advisory pipeline. If memory_store.sqlite is locked or corrupted, the system silently degrades with swallowed exceptions. Fix: Add /ready that checks critical dependencies. Add circuit breakers around the advisory and LLM paths.
spark_voice_addon.py loads .env on every call, no cachingFile: spark_voice_addon.py (line 18 โ module-level), speak_advisory() function
As noted in your own SPARK_ADVISORY.md: "speak_advisory() loads .env on every call." The env parsing happens at module import (line 18-25, runs once per import), but the ElevenLabs client is re-initialized on every speak_advisory() call (line 70). No connection pooling, no client reuse. Fix: Cache the ElevenLabs client at module level after first successful init.
lib/llm.py shells out to claude CLI via subprocessFile: lib/llm.py (lines 1-80)
The entire AI layer depends on finding the claude CLI binary, launching a subprocess, and parsing stdout. Rate limiting is done via a JSON file (~/.spark/llm_calls.json) that's read-modify-written on every call with no file locking โ a race condition when multiple processes call ask_claude() concurrently (e.g., sparkd.py + bridge_worker.py + cron scripts). The 30-call/hour limit is also very conservative. Fix: Use the Anthropic Python SDK directly, add proper file locking (fcntl.flock) on the rate limit file, or use SQLite for atomic rate tracking.
Bonus pattern: The codebase has 393 Python files (excluding .venv), 140k+ lines in lib/ alone, and 80+ test files โ but pyproject.toml only lists 3 runtime dependencies (requests, httpx, pyyaml). Everything else (FastAPI, ElevenLabs, fastembed, SQLite FTS5) is optional and discovered at runtime via try: import ... except. This makes dependency management fragile and the failure modes unpredictable.