From eae1eda375a68883911c3e55c036ec0a432dba05 Mon Sep 17 00:00:00 2001 From: Andy Stark Date: Fri, 6 Nov 2026 10:49:25 +0000 Subject: [PATCH] DOC-7267 Record the node_redis, redis_py and NRedisStack lessons in client-quirks The DOC-7267 cleanup PRs (#4482, #4484, #4486) left their durable findings only in commit bodies, where a future sweep would not see them before authoring. They now sit in the per-client sections of the skill's quirks reference: node-redis lists every command under an uppercase and a camelCase key and modules are client..; reply types come from source, not the .d.ts; ten redis-py methods raise NotImplementedError; an NRedisStack async entry is never a copy of the sync one, and the scan overloads return IAsyncEnumerable. Directive: when a sweep finds a client convention that is not in this file, add it here in the same PR Ticket: DOC-7267 Co-Authored-By: Claude Sonnet 5.5 --- .../reference/client-quirks.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.claude/skills/command-api-mapping/reference/client-quirks.md b/.claude/skills/command-api-mapping/reference/client-quirks.md index b18c06f210..3c7cc19e5b 100644 --- a/.claude/skills/command-api-mapping/reference/client-quirks.md +++ b/.claude/skills/command-api-mapping/reference/client-quirks.md @@ -43,6 +43,17 @@ Translation rules: `ARGREP_WITHVALUES`). Put both `arGrep` and `arGrepWithValues` as two signature objects in the single `ARGREP.json`. Cross-check the canonical command list in `data/commands*.json` before creating a file — if the name isn't there, it's a variant to fold, not a new file. +- **Both spellings exist; entries use camelCase (DOC-7267).** `index.ts` lists each command + under an UPPER key and a camelCase key (`APPEND`, `append`). Use the camelCase one. Module + commands are `client..`: `bf cf cms tDigest topK` (bloom), `json`, `ft` + (search), `ts` (time-series), so `client.bf.add`, never the dotted `BF.ADD`. +- **Read the reply type from the source `transformReply`, not the published `.d.ts`**, which + expands aliases (`ArrayReply>`). Where a command declares both `2:` + and `3:`, use the RESP2 type, the client default. Use the `.d.ts` only to check names and + arity: `tsc --strict` on `typeof client.` proves a name exists on the real client. +- Tooling: sources come from `gh api repos/redis/node-redis/tarball/redis@`, and + `npm install redis typescript --cache ./.npm-cache` gives the declarations and `tsc`. Both + need the sandbox off. ## redis_py (Python) - Method names are the command lowercased with **no word separators** (`arset`, `arget`, @@ -63,6 +74,17 @@ Translation rules: - redis-py exposes **one method per command**, folding options into params (`argrep` has `withvalues`/`nocase` flags; `arop` takes `operation` + optional `value`) — unlike Lettuce, which splits these into separate named methods. +- **Some methods exist but raise `NotImplementedError` (DOC-7267).** In 8.1.0: `command_docs`, + `command_info`, `failover`, `explain_cli`, `hello`, `latency_doctor`, `latency_graph`, + `latency_histogram`, `memory_doctor`, `script_debug`. Don't author a signature. Leave the + list empty and record `unsupported` in the status file. Confirm by calling the method on a + `Redis()`: the error fires before any connection. +- Module methods live on their own classes (`Search`, `JSON`, `TimeSeries`, `BFBloom` and its + siblings, `VectorSet`), and names like `add` and `exists` repeat across them, so resolve a + method against the class for the command's prefix. The dictionary methods are `dict_add`, + `dict_del` and `dict_dump`. +- Pin the version to check against: `pip install --no-deps --target redis==`, + then run with `PYTHONPATH=`. ## go-redis (Go) - New command families get a dedicated `_commands.go` at the repo root (e.g. arrays are in @@ -117,6 +139,13 @@ Translation rules: `IDatabaseAsync.cs`). Module commands (JSON/Search/TimeSeries) are in NRedisStack. - XML doc comments (``, ``, ``) → descriptions; strip ``. - Drop trailing `CommandFlags flags = CommandFlags.None` optional param or note it. +- **An async entry is never a copy of the sync one (DOC-7267).** The name gains `Async` and + `returns.type` is `Task` (or `Task`). The scan overloads (`HashScanAsync`, `SetScanAsync`, + `SortedSetScanAsync`, `KeysAsync`) return `IAsyncEnumerable` directly and take `cursor` and + `pageOffset` (`KeysAsync` also `database`). Verify by reflection over `IDatabaseAsync`, + `IServer` and `ISubscriber` on the pinned StackExchange.Redis version: the method must exist + with the same parameter names and types. +- Core entries leave the return type out of `signature` and put `Task` in `returns.type`. ## php (predis) - **`@method` docblocks in `src/ClientInterface.php` are the authoritative, complete source** —