feat: CommandVault v0.2.0 — SQLite adapter, security hardening, FTS5, search operators, registry#53
Merged
Merged
Conversation
Uses createRequire to import package.json at runtime so the CLI version stays in sync with package.json automatically — no manual updates needed when bumping versions.
Unifies all package versions at 0.1.7 for the first coordinated release. Updates release-please manifest to match.
Introduces a DatabaseAdapter interface with two implementations: - BetterSqliteAdapter: native SQLite with WAL mode, busy_timeout, and file-level locking for safe concurrent access - SqlJsAdapter: fallback with 2s debounced persist for environments without native modules Key improvements: - Eliminates 15.4MB full-DB serialize on every mutation (WAL handles durability) - Fixes N+1 query in EntryStore.index() (batch SELECT before loop) - Adds tag map caching with invalidation (no more full scan per search) - Removes all manual persist() calls from stores - Factory auto-detects better-sqlite3 availability, falls back to sql.js Projected: memory 335MB→80MB, cold start 859ms→300ms, bundle 1.49MB→200KB
- Hook parser: validate script paths with safePath() before reading, restricting to claudeConfigPath and CWD (prevents arbitrary file read via malicious .claude/settings.json) - Watcher: add followSymlinks: false to chokidar options (prevents symlink-based file exposure in ~/.claude/) - Webview: validate openFile paths against allowedRoots before opening (prevents arbitrary file access from webview messages) - Sync: add redirect: 'error' to importFromUrl fetch (SSRF hardening) - Deps: add pnpm overrides to patch ws, fast-uri, brace-expansion Also adds safePath() and isSecretFile() utilities to parsers/utils.ts
…dering - Fuse.js: truncate content to 500 chars on index (memory 10.8MB→~2MB) - Extract shared applyFilters() into filter-utils.ts (DRY across engines) - Skip per-entry events on initial scan (1,214 events→0) - Sort entries by stable ID after scan (deterministic cross-run ordering) - CLI: lazy-import interactive command (defer Ink/React until needed) - Typed event listener map with handler isolation (try-catch in emit)
New test files: - sync.test.ts: 32 tests (export/import roundtrip, SSRF blocking, URL fetch) - multi-agent-parser.test.ts: 14 tests (Cursor, Copilot, Windsurf, Aider) - watcher.test.ts: 14 tests (events, debounce, symlink config, lifecycle) - search-engine.test.ts: 18 tests (tier routing, LRU cache, TTL, suggest) - error-paths.test.ts: 16 tests (corrupt DB, malformed YAML, ENOENT) - query-parser.test.ts: 19 tests (all operators, edge cases) - CLI commands: 37 tests (list, search, stats, doctor, tag, favorite) Also adds coverage thresholds (80% lines, 75% functions, 70% branches) to vitest.config.ts as a CI gate. Total: 259→409 tests (58% increase)
QueryParser adds fzf-style search operators across all tiers: 'exact ^prefix !exclude tag:name type:skill source:gstack CLI enhancements: - First-run onboarding with guided next steps after vault init - --tag filter on search command (parity with VS Code) - Grouped help output (Discovery, Management, Data, Setup) - Bulk favorite/tag operations with --type filter - Config: handle JSON arrays and tilde expansion - Explicit --tui / --no-tui flags (removes magic TTY switching) VS Code extension: - Filter-by-type button in tree view toolbar - Search syntax help displayed in QuickPick results
…gistry FTS5 full-text search (migration v3): - Standalone FTS5 virtual table rebuilt after each index() - MATCH queries with prefix matching and bm25 ranking - Graceful fallback to LIKE if FTS5 unavailable - Column indexes on type, source, favorite for filter queries Staleness detection: - detectStaleness() checks source file mtime vs entry lastModified - Flags entries >30 days stale or with missing source files - Batched parallel stat() with concurrency limit of 50 Quality scoring: - scoreEntries() rates 0-100 across recency, usage, completeness, engagement - Surfaces low-quality entries (no description, no tags, never used) Remote registry: - RegistryManager aggregates multiple RegistryAdapter instances - JsonRegistryAdapter fetches static JSON registries with 5min TTL cache - vault registry add/remove/list/search commands CLI: - vault audit: staleness + quality report with --json, --threshold, --min-score - vault registry: manage and search remote skill registries
These files are superseded by the DatabaseAdapter pattern: - sqlite-connection.ts → replaced by better-sqlite-adapter.ts + sqljs-adapter.ts - migrations.ts → inlined into sqlite-engine.ts runAdapterMigrations() No active imports reference either file. Also updates AGENTS.md with commitlint scopes, PR template reference, and path-router documentation.
📦 Bundle Sizes
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Major upgrade across all 3 packages delivering 5 phases of improvements identified by a comprehensive 7-agent audit (architecture, performance, security, code quality, test coverage, competitive landscape, DX/UX).
Root cause addressed:
sql.js(in-memory, full-file serialize) was responsible for 70% of all issues — replaced withbetter-sqlite3behind a clean adapter interface.Changes
Phase 1 — SQLite Adapter Pattern
DatabaseAdapterinterface withBetterSqliteAdapter(WAL mode, concurrent access) andSqlJsAdapter(debounced persist fallback)EntryStore.index()(4,856 statements → 1 batch query)persist()calls removed (WAL handles durability)Phase 2 — Security Hardening + Performance
safePath()containment validation before reading scriptsfollowSymlinks: false+realpath()resolutionopenFilepath validation against allowedRootsredirect: 'error'on importFromUrl fetchfilter-utils.tsextracted (DRY across engines)Phase 3 — Test Coverage (+150 tests)
sync.test.ts— 32 tests (export/import, SSRF blocking, URL fetch)multi-agent-parser.test.ts— 14 tests (Cursor, Copilot, Windsurf, Aider)watcher.test.ts— 14 tests (events, debounce, symlink config)search-engine.test.ts— 18 tests (tier routing, LRU cache, TTL)error-paths.test.ts— 16 tests (corrupt DB, malformed YAML, ENOENT)query-parser.test.ts— 19 tests (all operators, edge cases)Phase 4 — DX/UX Improvements
'exact ^prefix !exclude tag:x type:skill source:y)--tagfilter on CLI search (parity with VS Code)--typefilter--tui/--no-tuiflags (explicit mode control)Phase 5 — Competitive Features
vault auditcommand: combined staleness + quality reportRegistryManager+JsonRegistryAdapterwith 5min TTL cachevault registry add/remove/list/searchcommandsCleanup
sqlite-connection.tsandmigrations.ts(superseded by adapter pattern)Metrics
New Files (25)
Core infrastructure:
database-adapter.ts,better-sqlite-adapter.ts,sqljs-adapter.ts,database-factory.ts,filter-utils.ts,query-parser.ts,staleness-detector.ts,quality-scorer.ts,registry/types.ts,registry/json-adapter.ts,registry/index.tsTests (14):
sync.test.ts,multi-agent-parser.test.ts,watcher.test.ts,search-engine.test.ts,error-paths.test.ts,query-parser.test.ts,cli/commands/{list,search,stats,doctor,tag,favorite}.test.tsCLI commands (2):
audit.ts,registry.tsValidation Sign-Off
Test Plan
pnpm typecheck— 0 errors across all packagespnpm test— 409/409 passingpnpm build— all packages build successfullypnpm format:check— all files formattedpnpm audit— 0 vulnerabilitiesvault searchreturns results with new FTS5 tiervault auditproduces staleness/quality report