resplite 1.2.6 → 1.2.10

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 (36) hide show
  1. package/README.md +168 -275
  2. package/package.json +1 -6
  3. package/scripts/create-interface-smoke.js +32 -0
  4. package/skills/README.md +22 -0
  5. package/skills/resplite-command-vertical-slice/SKILL.md +134 -0
  6. package/skills/resplite-ft-search-workbench/SKILL.md +138 -0
  7. package/skills/resplite-migration-cutover-assistant/SKILL.md +138 -0
  8. package/spec/00-INDEX.md +37 -0
  9. package/spec/01-overview-and-goals.md +125 -0
  10. package/spec/02-protocol-and-commands.md +174 -0
  11. package/spec/03-data-model-ttl-transactions.md +157 -0
  12. package/spec/04-cache-architecture.md +171 -0
  13. package/spec/05-scan-admin-implementation.md +379 -0
  14. package/spec/06-migration-strategy-core.md +79 -0
  15. package/spec/07-type-lists.md +202 -0
  16. package/spec/08-type-sorted-sets.md +220 -0
  17. package/spec/{SPEC_D.md → 09-search-ft-commands.md} +3 -1
  18. package/spec/{SPEC_E.md → 10-blocking-commands.md} +3 -1
  19. package/spec/{SPEC_F.md → 11-migration-dirty-registry.md} +61 -147
  20. package/src/commands/object.js +17 -0
  21. package/src/commands/registry.js +4 -0
  22. package/src/commands/zrevrange.js +27 -0
  23. package/src/engine/engine.js +19 -0
  24. package/src/migration/apply-dirty.js +8 -1
  25. package/src/migration/index.js +5 -4
  26. package/src/migration/migrate-search.js +25 -6
  27. package/src/storage/sqlite/zsets.js +34 -0
  28. package/test/integration/object-idletime.test.js +51 -0
  29. package/test/integration/zsets.test.js +18 -0
  30. package/test/unit/migrate-search.test.js +50 -2
  31. package/spec/SPEC_A.md +0 -1171
  32. package/spec/SPEC_B.md +0 -426
  33. package/src/cli/import-from-redis.js +0 -194
  34. package/src/cli/resplite-dirty-tracker.js +0 -92
  35. package/src/cli/resplite-import.js +0 -296
  36. package/test/contract/import-from-redis.test.js +0 -83
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: resplite-command-vertical-slice
3
+ description: Implements or extends a Redis-like command in RESPLite from spec to docs and tests. Use when the user says "add a command", "support a Redis option", "fix command compatibility", "implement ZRANGE behavior", or "update the compatibility matrix". Do not use for migration-only or FT-only work unless the change also affects the general command surface.
4
+ license: MIT
5
+ metadata:
6
+ author: Cursor Agent
7
+ version: 1.0.0
8
+ category: workflow-automation
9
+ tags: [resplite, redis-compatibility, commands, tests]
10
+ ---
11
+
12
+ # RESPLite Command Vertical Slice
13
+
14
+ Use this skill when a task requires changing RESPLite's public command behavior end to end rather than only editing one isolated function.
15
+
16
+ ## Use cases
17
+
18
+ **Use Case: Add a missing command**
19
+ Trigger: "implement command X", "add Redis compatibility for X", "support command Y"
20
+ Steps: inspect spec and current support, wire the handler, update engine or storage if needed, add tests, update docs
21
+ Result: a verified command slice that works through RESP and is reflected in the public docs
22
+
23
+ **Use Case: Extend a partially supported command**
24
+ Trigger: "support another ZRANGE option", "fix TTL edge case", "match Redis error behavior"
25
+ Steps: compare current implementation with intended semantics, patch the smallest layer that owns the behavior, strengthen tests, update compatibility notes
26
+ Result: improved compatibility without widening scope unnecessarily
27
+
28
+ **Use Case: Audit a command regression**
29
+ Trigger: "this command broke", "redis-cli behaves differently", "wrongtype or ERR output is wrong"
30
+ Steps: reproduce through tests, isolate whether the issue is parser, handler, engine, or storage, fix the owning layer, verify client-facing behavior
31
+ Result: the bug is fixed with regression coverage
32
+
33
+ ## Instructions
34
+
35
+ ### Step 1: Lock the compatibility target
36
+
37
+ Start by defining the exact command surface you are changing:
38
+
39
+ - command name and sub-options
40
+ - expected success reply shape
41
+ - expected error strings
42
+ - whether the change is Redis-standard behavior or RESPLite-specific behavior
43
+
44
+ Favor the smallest compatibility increment that solves the user's request. RESPLite is intentionally a practical subset, not a full Redis clone.
45
+
46
+ ### Step 2: Review the canonical sources first
47
+
48
+ Read these files before editing:
49
+
50
+ - `README.md` for the public compatibility matrix and examples
51
+ - `src/commands/registry.js` for command dispatch and handler registration
52
+
53
+ Then inspect the command-specific implementation:
54
+
55
+ - `src/commands/*.js` for argument parsing and command-level behavior
56
+ - `src/engine/*.js` when semantics belong to the engine
57
+ - `src/storage/sqlite/*.js` when persistence or query behavior changes
58
+ - relevant tests in `test/unit`, `test/integration`, and `test/contract`
59
+
60
+ ### Step 3: Choose the owning layer
61
+
62
+ Use this decision rule:
63
+
64
+ - parser or command syntax issue: fix the command handler
65
+ - business semantics issue: fix the engine layer
66
+ - persistence or query issue: fix SQLite storage helpers
67
+ - public support surface changed: also update `README.md` and, if needed, the spec
68
+
69
+ Avoid scattering logic across layers when one layer can own it cleanly.
70
+
71
+ ### Step 4: Implement the smallest vertical slice
72
+
73
+ Typical command workflow:
74
+
75
+ 1. Add or update the handler in `src/commands`
76
+ 2. Register it in `src/commands/registry.js` if needed
77
+ 3. Patch engine or storage behavior only where required
78
+ 4. Preserve existing error style such as `ERR ...` and wrong-type behavior
79
+ 5. Keep binary-safety expectations in mind when keys or values pass through buffers and SQLite
80
+
81
+ If a new command expands publicly supported behavior, update the compatibility matrix in `README.md`.
82
+
83
+ ### Step 5: Prove it through the right test level
84
+
85
+ Pick the smallest test mix that proves the change:
86
+
87
+ - `test/unit/*.test.js` for pure logic, engine rules, parser behavior, or storage helpers
88
+ - `test/integration/*.test.js` for end-to-end RESP behavior through the server
89
+ - `test/contract/*.test.js` when compatibility with `redis` client or `redis-cli` is part of the user-facing promise
90
+
91
+ Prefer adding a regression test that would fail before the fix and pass after it.
92
+
93
+ ### Step 6: Report the outcome clearly
94
+
95
+ When you finish, summarize:
96
+
97
+ - what compatibility surface changed
98
+ - which layers were touched
99
+ - which tests were run
100
+ - any remaining intentional gaps versus Redis
101
+
102
+ ## RESPLite-specific checklist
103
+
104
+ - Keep scope aligned with "practical Redis compatibility", not total parity
105
+ - Preserve RESP2-facing behavior
106
+ - Use the public docs to reflect newly supported behavior
107
+ - Do not claim support in docs until tests back it up
108
+ - If the command is intentionally unsupported, return the project's clear unsupported-command behavior instead of faking partial support
109
+
110
+ ## Examples
111
+
112
+ **Example 1: Add a missing command**
113
+ User says: "Implement a minimal `ZRANK` command."
114
+ Actions: review `spec/SPEC_A.md`, inspect zset handlers and storage helpers, add `src/commands/zrank.js`, register it, add unit and integration coverage, update `README.md` only if support becomes public
115
+ Result: one new command works end to end with verified semantics
116
+
117
+ **Example 2: Fix a compatibility edge case**
118
+ User says: "Make `TTL` return the right value for missing keys."
119
+ Actions: inspect existing TTL tests, patch the owning logic, add a regression test, verify no unrelated TTL behavior changed
120
+ Result: client-visible compatibility improves with minimal code churn
121
+
122
+ ## Troubleshooting
123
+
124
+ **Problem: The handler exists but the command still returns unsupported**
125
+ Cause: `src/commands/registry.js` was not updated, or the command name casing does not match dispatch behavior.
126
+ Solution: register the handler in uppercase form and verify the RESP command path through an integration test.
127
+
128
+ **Problem: The command works in unit tests but not through clients**
129
+ Cause: only internal logic was tested; RESP parsing, argument shape, or connection handling may differ.
130
+ Solution: add an integration test, and add a contract test if `redis-cli` or the official `redis` client is part of the promise.
131
+
132
+ **Problem: The change feels larger than one command**
133
+ Cause: the request may actually be a search feature or migration flow change rather than a generic command extension.
134
+ Solution: switch to the more specific RESPLite skill for migration or `FT.*` work instead of forcing everything into one command slice.
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: resplite-ft-search-workbench
3
+ description: Builds or refines RESPLite `FT.*` behavior and RediSearch migration mapping on top of SQLite FTS5. Use when the user says "add FT command support", "fix FT.SEARCH", "adjust SQLite FTS5 behavior", "migrate RediSearch indices", or "work on FT.CREATE or FT.ADD semantics". Do not use for unrelated command work outside the search surface.
4
+ license: MIT
5
+ metadata:
6
+ author: Cursor Agent
7
+ version: 1.0.0
8
+ category: workflow-automation
9
+ tags: [resplite, search, redisearch, sqlite, fts5]
10
+ ---
11
+
12
+ # RESPLite FT Search Workbench
13
+
14
+ Use this skill for search-specific work where RediSearch-inspired behavior must stay grounded in what maps naturally to SQLite FTS5.
15
+
16
+ ## Use cases
17
+
18
+ **Use Case: Add or refine an `FT.*` command**
19
+ Trigger: "implement FT command", "fix FT.SEARCH output", "support another FT option"
20
+ Steps: inspect the FT spec, trace command handler to SQLite search helpers, patch the narrowest layer, add unit and integration coverage, update docs if public behavior changed
21
+ Result: search behavior improves without pretending to support the full RediSearch surface
22
+
23
+ **Use Case: Work on index storage or ranking**
24
+ Trigger: "change FTS5 schema", "fix BM25 ordering", "debug search index behavior"
25
+ Steps: inspect per-index tables and search helpers, patch FTS mapping or metadata behavior, verify with search-focused tests
26
+ Result: SQLite-backed search behavior remains internally consistent and externally predictable
27
+
28
+ **Use Case: Improve RediSearch migration**
29
+ Trigger: "migrate FT indices", "map FT.INFO attributes", "handle TAG or NUMERIC fields"
30
+ Steps: inspect search migration mapping, keep support boundaries explicit, warn on downgraded or skipped fields, verify with unit tests
31
+ Result: migration is useful and honest about current limits
32
+
33
+ ## Instructions
34
+
35
+ ### Step 1: Start with the explicit search scope
36
+
37
+ Read these first:
38
+
39
+ - `spec/SPEC_D.md`
40
+ - `src/storage/sqlite/search.js`
41
+ - `src/commands/ft-create.js`
42
+ - `src/commands/ft-add.js`
43
+ - `src/commands/ft-search.js`
44
+ - `src/migration/migrate-search.js` when migration is involved
45
+
46
+ Then inspect the relevant tests:
47
+
48
+ - `test/unit/search.test.js`
49
+ - `test/integration/search.test.js`
50
+ - `test/unit/ft-parser.test.js`
51
+ - `test/unit/migrate-search.test.js`
52
+
53
+ ### Step 2: Preserve RESPLite's search philosophy
54
+
55
+ Keep these design constraints visible while you work:
56
+
57
+ - search is RediSearch-inspired, not RediSearch-complete
58
+ - the implementation should feel natural for SQLite FTS5
59
+ - unsupported behavior should be explicit rather than approximated badly
60
+ - public docs should not overstate feature parity
61
+
62
+ If a requested feature requires excessive gymnastics or breaks the current storage model, prefer a scoped implementation or a clear unsupported response.
63
+
64
+ ### Step 3: Change the correct layer
65
+
66
+ Use this split:
67
+
68
+ - syntax and RESP command shape: `src/commands/ft-*.js`
69
+ - index metadata, tables, search queries, suggestions: `src/storage/sqlite/search.js`
70
+ - migration from a source RediSearch instance: `src/migration/migrate-search.js`
71
+
72
+ Try not to duplicate validation rules across layers unless that duplication protects a stable public contract.
73
+
74
+ ### Step 4: Keep storage and public behavior aligned
75
+
76
+ When you modify index or query behavior, verify these invariants:
77
+
78
+ - index names and field names stay validated
79
+ - supported field types are still explicit
80
+ - document insert or replace behavior remains atomic
81
+ - search result ordering still matches the chosen ranking rules
82
+ - docs and migration warnings reflect the real support level
83
+
84
+ If you widen support, also update `README.md` where the FT surface is described.
85
+
86
+ ### Step 5: Test the exact path you changed
87
+
88
+ Use the narrowest relevant set:
89
+
90
+ - parser tests for argument and syntax behavior
91
+ - search unit tests for index helpers, query validation, ranking, and suggestion storage
92
+ - integration tests for RESP-facing `FT.*` behavior
93
+ - `migrate-search` tests for RediSearch compatibility and downgrade warnings
94
+
95
+ Prefer regression tests that capture the exact failure mode instead of broad smoke coverage only.
96
+
97
+ ### Step 6: Close with support boundaries
98
+
99
+ Report:
100
+
101
+ - what `FT.*` behavior changed
102
+ - whether the change affects runtime search, migration, or both
103
+ - what remains intentionally unsupported
104
+ - which tests prove the new behavior
105
+
106
+ ## RESPLite-specific checklist
107
+
108
+ - Keep the search surface consistent with `spec/SPEC_D.md`
109
+ - Do not imply full RediSearch parity
110
+ - Preserve the SQLite-first data model
111
+ - Keep migration warnings informative when mapping unsupported field types
112
+ - Update docs when public support changes
113
+
114
+ ## Examples
115
+
116
+ **Example 1: Fix `FT.SEARCH` behavior**
117
+ User says: "Make `FT.SEARCH` reject invalid query characters consistently."
118
+ Actions: inspect query validation in `src/storage/sqlite/search.js`, add a regression test in `test/unit/search.test.js`, run search integration coverage if the RESP result changes
119
+ Result: search input validation is stricter and reproducible
120
+
121
+ **Example 2: Improve RediSearch migration mapping**
122
+ User says: "Map `NUMERIC` fields into the current schema as text and emit warnings."
123
+ Actions: inspect `src/migration/migrate-search.js` and `test/unit/migrate-search.test.js`, preserve current support boundaries, update tests to prove the downgrade behavior
124
+ Result: migration becomes more practical without claiming unsupported range-query semantics
125
+
126
+ ## Troubleshooting
127
+
128
+ **Problem: The feature request sounds like full RediSearch parity**
129
+ Cause: the requested behavior exceeds the current SQLite-first scope.
130
+ Solution: narrow the request to the subset that maps naturally to FTS5, document the unsupported parts, and avoid shipping misleading compatibility claims.
131
+
132
+ **Problem: Search tests pass but migration still breaks**
133
+ Cause: runtime `FT.*` behavior and migration mapping are separate code paths.
134
+ Solution: verify both `src/storage/sqlite/search.js` and `src/migration/migrate-search.js`, then run both search and migrate-search tests.
135
+
136
+ **Problem: Delete behavior or row mapping becomes inconsistent**
137
+ Cause: index storage invariants were changed without preserving the doc to row mapping assumptions.
138
+ Solution: review the per-index tables and their relationships in `src/storage/sqlite/search.js`, then add a focused regression test before expanding the change.
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: resplite-migration-cutover-assistant
3
+ description: Guides Redis to RESPLite migration work using the programmatic migration API, dirty-key tracking, cutover, and verification. Use when the user says "migrate Redis", "dirty tracker", "cutover", "resume bulk import", "verify migration", or "move RediSearch data during migration". Do not use for generic command work that does not touch the migration flow.
4
+ license: MIT
5
+ metadata:
6
+ author: Cursor Agent
7
+ version: 1.0.0
8
+ category: workflow-automation
9
+ tags: [resplite, migration, redis, cutover, verification]
10
+ ---
11
+
12
+ # RESPLite Migration Cutover Assistant
13
+
14
+ Use this skill for migration work where correctness, resumability, and cutover sequencing matter more than raw implementation speed.
15
+
16
+ ## Use cases
17
+
18
+ **Use Case: Drive a Redis to RESPLite migration**
19
+ Trigger: "help me migrate Redis", "create migration script", "plan cutover"
20
+ Steps: inspect the migration API, build or adjust a single-script flow, verify preflight, bulk, dirty tracking, cutover, and verification
21
+ Result: a reproducible migration workflow with minimal downtime
22
+
23
+ **Use Case: Fix dirty-key tracking or resumability**
24
+ Trigger: "dirty tracker missed keys", "resume is broken", "migration status is wrong"
25
+ Steps: inspect registry and tracker logic, reproduce through tests, fix the persistent state transitions, verify cutover semantics
26
+ Result: the migration state machine behaves predictably across interruptions
27
+
28
+ **Use Case: Add or change RediSearch migration behavior**
29
+ Trigger: "migrate FT indices", "search migration", "map RediSearch fields"
30
+ Steps: review `migrate-search`, map fields to current FT support, verify warnings and skipped cases, test the result with fake Redis or integration coverage
31
+ Result: search migration stays aligned with the current FT implementation
32
+
33
+ ## Instructions
34
+
35
+ ### Step 1: Prefer the programmatic API
36
+
37
+ Start from `resplite/migration`, not from deleted or legacy CLI paths. The current intended entry point is `createMigration()` in `src/migration/index.js`.
38
+
39
+ Read these sources first:
40
+
41
+ - `README.md` migration section
42
+ - `spec/SPEC_F.md`
43
+ - `src/migration/index.js`
44
+ - `src/migration/tracker.js`
45
+ - `src/migration/migrate-search.js` when `FT.*` is involved
46
+
47
+ If the requested change conflicts with the documented sequence, treat the documented cutover flow as the source of truth unless the task explicitly updates docs and behavior together.
48
+
49
+ ### Step 2: Keep the real cutover model intact
50
+
51
+ Model the migration as these phases:
52
+
53
+ 1. `preflight()`
54
+ 2. `enableKeyspaceNotifications()`
55
+ 3. `startDirtyTracker()`
56
+ 4. `bulk({ resume: true })`
57
+ 5. pause and freeze writes to Redis
58
+ 6. `applyDirty()`
59
+ 7. `stopDirtyTracker()`
60
+ 8. `migrateSearch()` if the source uses `FT.*`
61
+ 9. `verify()`
62
+ 10. `close()`
63
+
64
+ Do not collapse cutover into "bulk then switch" if dirty tracking or write freeze is part of the scenario.
65
+
66
+ ### Step 3: Preserve resumability and persistence semantics
67
+
68
+ When editing migration internals, make sure these properties stay true:
69
+
70
+ - bulk progress checkpoints can resume after interruption
71
+ - dirty keys are persisted in SQLite
72
+ - final cutover uses the last dirty set after writes are frozen
73
+ - status can be read from SQLite without Redis being connected
74
+
75
+ If the source Redis has a renamed `CONFIG` command, keep `configCommand` support working across both preflight and notification setup.
76
+
77
+ ### Step 4: Distinguish KV migration from search migration
78
+
79
+ Keep these boundaries clear:
80
+
81
+ - `bulk` and `applyDirty` handle strings, hashes, sets, lists, and zsets
82
+ - `migrateSearch()` handles RediSearch schema and document migration separately
83
+ - search migration is not a substitute for the dirty-key delta flow
84
+
85
+ This separation keeps the code and operator workflow predictable.
86
+
87
+ ### Step 5: Verify the exact failure mode
88
+
89
+ Use the narrowest useful test set:
90
+
91
+ - `test/integration/migration-dirty-tracker.test.js` for dirty tracking and cutover behavior
92
+ - `test/unit/migration-registry.test.js` for persistent registry semantics
93
+ - `test/unit/migrate-search.test.js` for RediSearch mapping and migration edge cases
94
+
95
+ If you change the public script examples or workflow guidance, update `README.md` so the docs and implementation stay in sync.
96
+
97
+ ### Step 6: Report operationally, not just structurally
98
+
99
+ When closing the task, summarize:
100
+
101
+ - what phase of the migration flow changed
102
+ - whether the change affects operator cutover steps
103
+ - what verification was run
104
+ - any remaining assumptions about Redis configuration, notifications, or FT availability
105
+
106
+ ## RESPLite-specific checklist
107
+
108
+ - Use the single-script programmatic flow as the happy path
109
+ - Treat the final dirty apply after write freeze as authoritative
110
+ - Keep `resume: true` behavior simple and restart-safe
111
+ - Preserve the distinction between key migration and search migration
112
+ - Update docs when operator-facing behavior changes
113
+
114
+ ## Examples
115
+
116
+ **Example 1: Fix cutover sequencing**
117
+ User says: "The migration docs and code should make the final dirty apply happen only after writes are frozen."
118
+ Actions: review `README.md` and `spec/SPEC_F.md`, patch the sequencing if needed, adjust tests, verify the user-facing migration script matches the intended cutover flow
119
+ Result: docs, code, and tests describe the same operational sequence
120
+
121
+ **Example 2: Improve search migration**
122
+ User says: "Map RediSearch TAG fields into the current FT implementation with warnings."
123
+ Actions: inspect `src/migration/migrate-search.js`, preserve the current FT scope, update unit tests around field mapping, report unsupported field types clearly
124
+ Result: migration becomes more helpful without pretending to support unsupported search behavior
125
+
126
+ ## Troubleshooting
127
+
128
+ **Problem: Dirty tracking appears to miss updates**
129
+ Cause: keyspace notifications are not enabled, the tracker was not running during bulk, or the scenario expects durable CDC semantics that Redis notifications do not provide.
130
+ Solution: verify `enableKeyspaceNotifications()`, keep the tracker active during bulk, and rely on the final write freeze plus `applyDirty()` for authoritative cutover.
131
+
132
+ **Problem: Bulk resume logic is confusing**
133
+ Cause: code or docs treat first run and resumed run as separate flows.
134
+ Solution: keep `resume: true` as the default simple path and make sure the same script works for both start and resume.
135
+
136
+ **Problem: Search migration is mixed into the key delta**
137
+ Cause: the implementation is blurring `migrateSearch()` with key replication semantics.
138
+ Solution: keep the keyspace migration and RediSearch migration as separate steps, then verify each with the appropriate tests.
@@ -0,0 +1,37 @@
1
+ # RESPLite Specifications — Index
2
+
3
+ Specifications are split by topic. Names are specific and ordered by dependency.
4
+
5
+ ## Core (RESP server v1)
6
+
7
+ | File | Content |
8
+ |------|--------|
9
+ | [01-overview-and-goals.md](01-overview-and-goals.md) | Overview, product goals, non-goals, positioning |
10
+ | [02-protocol-and-commands.md](02-protocol-and-commands.md) | Protocol (RESP2), command scope, semantics, SET scope |
11
+ | [03-data-model-ttl-transactions.md](03-data-model-ttl-transactions.md) | Data model (SQLite schema), TTL/expiration, transaction rules |
12
+ | [04-cache-architecture.md](04-cache-architecture.md) | Hot cache, architecture layers, internal API shape |
13
+ | [05-scan-admin-implementation.md](05-scan-admin-implementation.md) | SCAN, admin commands (SQLITE.INFO, CACHE.INFO), project structure, testing, acceptance, implementation order |
14
+ | [06-migration-strategy-core.md](06-migration-strategy-core.md) | Migration strategy from Redis (programmatic), compatibility matrix, final design rule |
15
+
16
+ ## Data types (beyond base v1)
17
+
18
+ | File | Content |
19
+ |------|--------|
20
+ | [07-type-lists.md](07-type-lists.md) | Lists (LPUSH, RPUSH, LPOP, RPOP, LLEN, LRANGE, LINDEX, …) — data model and behavior |
21
+ | [08-type-sorted-sets.md](08-type-sorted-sets.md) | Sorted sets (ZADD, ZREM, ZCARD, ZSCORE, ZRANGE, ZRANGEBYSCORE) — data model and behavior |
22
+ | [09-search-ft-commands.md](09-search-ft-commands.md) | Search (FT.CREATE, FT.ADD, FT.SEARCH, FT.SUG*, …) — FTS5/BM25, schema, parser grammar |
23
+ | [10-blocking-commands.md](10-blocking-commands.md) | Blocking list commands (BLPOP, BRPOP) — wait model, wakeup, tests |
24
+
25
+ ## Migration (dirty key registry)
26
+
27
+ | File | Content |
28
+ |------|--------|
29
+ | [11-migration-dirty-registry.md](11-migration-dirty-registry.md) | Bulk import, dirty key tracker, delta apply, search index migration, operational guidance |
30
+
31
+ ---
32
+
33
+ ## Implementation status (as of review)
34
+
35
+ - **Implemented:** All commands in §02 (connection, strings, TTL, hashes, sets, SCAN, admin), plus Lists (§07), Sorted Sets (§08), FT.* (§09), BLPOP/BRPOP (§10). Migration API with bulk, dirty tracker, apply-dirty, migrateSearch (§11).
36
+ - **Schema:** Matches §03 and extends to list/zset/search tables per §07, §08, §09.
37
+ - **Specs:** SPEC_A–F have been split into the files above; content is unchanged except in Appendix F: the duplicate “F.10 Search Index Migration” was renumbered to **F.12**, and “F.12 Operational Guidance” to **F.13**.
@@ -0,0 +1,125 @@
1
+ # RESPLite Specification v1 — Overview and Goals
2
+
3
+ ## 1. Overview
4
+
5
+ RESPLite is a Redis-compatible subset server implemented in Node.js and backed by SQLite.
6
+ It exposes a TCP port that speaks RESP2 so existing Redis clients can connect to it.
7
+ The system is designed for single-node deployments where persistence, low operational overhead, and practical Redis compatibility matter more than full Redis feature parity.
8
+
9
+ This project is not a full Redis clone.
10
+ It is a RESP server with Redis-like semantics for a carefully selected subset of commands that map naturally and efficiently to SQLite.
11
+
12
+ Core principles:
13
+
14
+ - RESP-first product design
15
+ - SQLite as the persistent source of truth
16
+ - Hot in-memory cache for frequently accessed data
17
+ - Strictly scoped compatibility
18
+ - Strong correctness and test coverage before feature expansion
19
+ - No features that require unnatural or fragile implementation on SQLite
20
+
21
+ ---
22
+
23
+ ## 2. Product Goals
24
+
25
+ Version 1 focuses on the following goals:
26
+
27
+ - Expose a TCP server that speaks RESP2
28
+ - Support a useful subset of Redis commands
29
+ - Persist all data in SQLite
30
+ - Maintain practical compatibility with existing Redis clients
31
+ - Support strings, hashes, sets, and TTLs
32
+ - Provide SCAN and TYPE for basic introspection
33
+ - Keep the architecture ready for future FT.* commands powered by SQLite FTS5 with BM25 ranking
34
+
35
+ This project is intended to be packaged and distributed as an npm module, but v1 starts with RESP server mode only.
36
+ There is no embedded direct JavaScript API in the initial scope.
37
+
38
+ ---
39
+
40
+ ## 3. Non-Goals
41
+
42
+ The following are explicitly out of scope for v1:
43
+
44
+ - Pub/Sub
45
+ - Streams
46
+ - Lua scripting
47
+ - Redis Cluster
48
+ - Replication
49
+ - MULTI / EXEC / WATCH
50
+ - Blocking commands such as BLPOP
51
+ - Multiple logical databases via SELECT
52
+ - Full edge-case parity with Redis for every command and protocol nuance
53
+ - Matching Redis performance for high-concurrency, memory-first workloads
54
+
55
+ The project should return a clear error for unsupported commands:
56
+
57
+ - `ERR command not supported yet`
58
+
59
+ ---
60
+
61
+ ## 4. Positioning
62
+
63
+ RESPLite should be described as:
64
+
65
+ > A RESP2 server with practical Redis compatibility, backed by SQLite for persistent single-node workloads.
66
+
67
+ It should not be described as:
68
+
69
+ - a full Redis replacement for all workloads
70
+ - a Redis Cluster alternative
71
+ - a low-latency in-memory data store competitor for large-scale write-heavy systems
72
+
73
+ The intended sweet spot is:
74
+
75
+ - bots
76
+ - internal tools
77
+ - small to medium web applications
78
+ - persistent caches
79
+ - local development environments
80
+ - low-ops VPS deployments
81
+ - metadata stores
82
+ - feature flags
83
+ - counters
84
+ - session-like state where persistence matters
85
+
86
+ ---
87
+
88
+ ## 5. Protocol
89
+
90
+ ### 5.1 Supported protocol version
91
+
92
+ v1 supports:
93
+
94
+ - RESP2 only
95
+
96
+ RESP3 is out of scope for v1.
97
+
98
+ ### 5.2 Wire compatibility target
99
+
100
+ The server should be compatible enough for practical use with:
101
+
102
+ - `redis-cli`
103
+ - the official `redis` npm client
104
+
105
+ The wire-level contract must correctly support:
106
+
107
+ - Simple Strings
108
+ - Bulk Strings
109
+ - Null Bulk Strings
110
+ - Integers
111
+ - Arrays
112
+ - Errors
113
+
114
+ ### 5.3 Binary safety
115
+
116
+ The implementation must treat the following as binary-safe values:
117
+
118
+ - keys
119
+ - string values
120
+ - hash fields
121
+ - hash values
122
+ - set members
123
+
124
+ Internal command processing should use `Buffer` objects, not UTF-8 strings, as the default representation.
125
+ SQLite storage should use `BLOB` columns where appropriate.