DOC-6968 Fix two node-redis step names, and add the missing incr step for nine clients - #3809
Conversation
Renames `hIncrBy_hGet_hMget` to `incrby_get_mget` in the hashes example and
`sinster` to `sinter` in the sets example, and corrects one output comment
the rename exposed.
Both files always contained correct, working code for these steps. What was
wrong was only the name, so the shortcode could not find the step and fell
back to rendering the entire file: 120 lines of unrelated hash examples on
the hashes page, 114 on the sets page, imports and all, where the reader
expects a short snippet. Nothing failed, no test broke, and the tab was
present and populated the whole time, which is why this survived.
build/components/example.py lowercases step names, so the other camelCase
markers in these files (hmGet, hExpire, hpExpire) normalise onto the
canonical names by accident. Only these two did not survive that: one has
the wrong name structure rather than the wrong case, and the other is a
plain typo. "sinster" is not a command, a method or a word.
The sets rename then exposed a second defect in the six lines it made
visible. The expected-output comment read {'bike:1'}, a Python set literal,
in a JavaScript example whose own assertion two lines below says
deepEqual(res7, ['bike:1']). Observed output is [ 'bike:1' ]. The comment
had presumably been copied from the redis-py tab; the whole-file fallback
had buried it in 114 lines where nobody would read it against the assertion.
That is the second time in this branch's work that an expected value
inherited from a sibling client's tab turned out to be wrong for the client
it was published under.
Verified by running both examples against Redis 8.8.0, and by rebuilding the
site and diffing legacy-fallback panes across the whole output: 111 before,
109 after, the two removed being exactly these, none added.
Learned: a whole-file fallback hides per-step defects rather than merely looking untidy, because nobody reads a 114-line dump closely enough to catch a wrong comment in it
Directive: a STEP name must match the set's canonical step after lowercasing — camelCase is safe, a different name structure is not, and nothing in the build will tell you
Constraint: the fix is the name only; both steps' code and assertions were already correct and must not be rewritten to look like the other clients
Ticket: DOC-6968
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds an `incr` step to the redis-py, node-redis, ioredis, predis, rust-sync, rust-async, lettuce-async, lettuce-reactive and hiredis files in the cmds_string set. Nine of the twelve clients on content/commands/incr.md had no such step, so each of those tabs was rendering its client's whole file instead of a three-command snippet. Done ahead of the shortcode fix in this ticket rather than after it, and that order matters. The fix omits a tab when the client lacks the requested step, which on this page would have cut incr.md from twelve client tabs to three, losing Python and Node.js — the two clients most readers arrive with — from a core string command page. Wrong-but-present beats absent for a reader, so the coverage had to land first. incr.md now renders all twelve clients sliced correctly, so the fix will take nothing from it. set() does not return "OK" everywhere. redis-py returns a bool, so its comment reads True where the Go and Jedis references read OK. Copying the reference's value into the Python tab would have been wrong in exactly the way two earlier defects on this branch were wrong, both times from an expected value inherited off a sibling client's tab. Every implementation was executed against Redis 8.8.0 except the C one, which the portable harness cannot run (clients.tsv gives hiredis no portable runner) and which could not be compiled here either, as no hiredis headers are installed. Its reply-type choices were checked against the live server instead: INCR returns an integer, so reply->integer with %lld is right, and GET returns a bulk string, so reply->str is right. That is weaker than running it, and the gap is stated rather than papered over. Two false alarms worth not re-investigating. cargo prints a second "running 0 tests" block for the doc-test pass, so reading the tail of a Rust log suggests the test never ran when the real result is one test passed higher up. And Rust tests capture stdout, so the printed values are confirmed by the assert_eq! calls inside each step rather than by anything in the log. Verified by rebuilding the whole site and diffing legacy-fallback panes: 109 before, 100 after, the nine removed being exactly these, none added. Learned: set() returns a bool in redis-py and a status string in most other clients, so an expected-output comment cannot be shared across tabs even for a trivial command Constraint: the incr step must stay self-contained — it does its own SET of mykey, so it needs no recreate scaffolding, and mykey belongs in each file's REMOVE cleanup at both ends Gaps: the hiredis implementation is not execution-verified; run it under --fidelity, or install hiredis and compile it, before trusting its printed output Directive: do not "normalise" the redis-py comment to OK to match the other tabs — True is what the client actually returns Ticket: DOC-6968 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Correction to commit 282798c's That trailer says the C implementation is not execution-verified and should be run under Not amended into the commit because it was already pushed. hiredis cannot be verified through That absence-not-SKIP behaviour is the durable lesson here, and it is worth considering against the skill's own gate ("every client PASS, or SKIP with a stated reason — a silent SKIP is a failure"), which hiredis silently evades. |
Sets the hiredis row's `portable` column to `hiredis` and adds `run_hiredis`, so `run.sh` can test the C examples in portable mode. Previously hiredis was fidelity-only, which in practice meant untested: fidelity needs client repo clones via bootstrap.sh, so nobody ran it. The hazard this removes is not that C was untested, it is that the harness did not say so. `clients_for_mode()` filters the run list on the `portable` column, so a client with `-` there gets no row in the results table at all — not a SKIP. The "no portable runner; try --fidelity" FAIL branch only fires when that client is named explicitly on the command line. So a full-set run looked green while saying nothing whatsoever about the C tab, and there was no line of output to notice. RedisVL is now the only client in that state. hiredis is the one client portable mode cannot self-bootstrap. Every other runner installs its dependency into work/ with pip, npm or gem; hiredis is a system C library, so the runner compiles against an existing install. It searches /usr/local, /opt/homebrew and /usr for include/hiredis/hiredis.h rather than hard-coding one box's layout, and links with -rpath so the built binary runs without the caller setting DYLD_LIBRARY_PATH or LD_LIBRARY_PATH. Where hiredis is absent, a toolchain_skip_reason guard reports a stated SKIP naming the paths searched, following the existing precedent for the Go toolchain and Ruby version guards. That skip path was exercised by pointing the prefix list at nonexistent directories, not just written and assumed. Verified: hiredis PASSES on cmds_string, cmds_hash and cmds_generic, and the full cmds_string sweep still passes for every other client with hiredis added to the table. The two pre-existing C examples turn out to have been correct all along; they had simply never been executed. The skill's reference table claimed "13 (no C)" portable clients and "13 (no RedisVL)" for fidelity. Both were already stale before this change — counting clients.tsv gives 17 of 18 in each mode, the sole exclusion being RedisVL. I had first written 14 by adding one to the old figure instead of counting, which is the same mistake in miniature. Learned: a client filtered out of the harness run list is indistinguishable from a passing one when scanning output, because it produces no row at all — count rows against clients.tsv when coverage matters Constraint: run_hiredis must resolve its prefix by search rather than hard-coding /usr/local, and must keep the -rpath link flag, or the built binary needs a library-path env var to run Directive: do not remove the toolchain_skip_reason guard to "simplify" — without it, a box with no hiredis reports a compile-error FAIL that reads like a broken example Ticket: DOC-6968 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6a12a9a. Configure here.
Two corrections to the harness runner added earlier on this branch. `run_hiredis` passed `-lhiredis` before the source file. GNU ld resolves left to right and Debian/Ubuntu default to --as-needed, so a library listed before anything references it is dropped and the link fails with undefined symbols — on a box that has hiredis installed, which would have turned a clean SKIP into a confusing FAIL. macOS/ld64 tolerates either order, which is exactly why local testing passed and hid it. Found by Cursor Bugbot; bootstrap.sh's fidelity C build already had the order right, so this was a divergence from the repo's own working precedent rather than an unknown. The second is the other half of a hazard this branch documented but only half-fixed. Adding a portable runner made the C examples visible, but `clients_for_mode()` still silently drops any client whose column is `-`, so such a client produced no row at all — indistinguishable from a pass when scanning the summary, and with no line of output to prompt a second look. RedisVL was the last client in that state. A full sweep now emits an explicit SKIP for every client the mode cannot test, so the summary accounts for all eighteen rows in clients.tsv. Naming clients explicitly is unchanged: the existing "no portable runner" FAIL already covers that path. Verified: hiredis still PASSES on cmds_string after the flag reorder, the full sweep now prints eighteen rows against eighteen clients.tsv entries, and an explicit single-client run still prints one row rather than dragging the excluded ones in. Learned: a linker-order bug in a C build is invisible on macOS and fatal on Linux, so matching an existing working invocation beats composing a fresh one Constraint: keep the source file before -lhiredis in run_hiredis, and keep -rpath, or the build breaks on Linux or the binary needs a library-path env var Ticket: DOC-6968 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks @dwdougherty ! |

DOC-6968 — two node-redis step names that never matched their sets
Three lines changed across two files. The effect is larger than the diff: two docs pages stop dumping an entire example file where a short snippet belongs.
local_examples/tmp/datatypes/hashes/dt-hash.jsSTEP_START hIncrBy_hGet_hMgetSTEP_START incrby_get_mgetlocal_examples/tmp/datatypes/sets/dt-set.jsSTEP_START sinsterSTEP_START sinterlocal_examples/tmp/datatypes/sets/dt-set.js// >>> {'bike:1'}// >>> ['bike:1']What was actually broken
Both files always contained correct, working code for these steps. Only the name was wrong, so
clients-examplecould not find the step and fell back to embedding the whole file:develop/data-types/hashes— the Node.js tab forincrby_get_mgetrendered 120 lines instead of 14.develop/data-types/sets— the Node.js tab forsinterrendered 114 lines instead of 6.Imports, connection setup and every unrelated example in the file, in a tab a reader opened to see one counter pattern. Nothing failed and no test broke — the tab was present and populated the entire time, which is exactly why this survived.
build/components/example.py:146lowercases step names, so the other camelCase markers in these files (hmGet,hExpire,hpExpire) land on the canonical names by accident. These two didn't: one has the wrong name structure rather than the wrong case, and the other is a plain typo —sinsteris not a command, a method, or a word.The comment the rename exposed
Making the
sinterpane visible surfaced a second defect in the six lines it revealed. The expected-output comment read{'bike:1'}— a Python set literal — in a JavaScript example whose own assertion two lines below readsassert.deepEqual(res7, [ 'bike:1' ]). Observed output is[ 'bike:1' ]. It had evidently been copied from the redis-py tab, and the whole-file fallback had buried it in 114 lines where nobody would read it against the assertion.Worth noting as a pattern: this is the second time in this run of work that an expected value inherited from a sibling client's tab proved wrong for the client it was published under (the first was
hpttlin #3808, inherited as59994where Ruby returns59999).Verification
named_stepsidentical to Python's for both setsrun.sh hash_tutorial node-redisandrun.sh sets_tutorial node-redisboth PASS against Redis 8.8.01, 2, 3, 1, 1, 3, ['1','1']confirmed against the run;sintercorrected to the observed['bike:1']Only comments and a marker name changed, so no runtime behaviour is affected — but both examples were run anyway rather than assumed.
Context
This is the "cause A" item from DOC-6968, which catalogues 74 panes site-wide rendering whole files this way. These two were the only ones fixable by a rename — the other ~64 are files that genuinely lack the example code and need examples written. The shortcode fix that makes the whole class impossible is tracked in the same ticket and has no prerequisites.
Doing these two before that fix is deliberate: afterwards the symptom becomes a quietly-omitted tab rather than an obvious whole-file dump, so a typo like
sinsterwould get harder to spot, not easier.🤖 Generated with Claude Code
Note
Low Risk
Changes are limited to local example sources, doc step markers, and the example test harness; no production services, auth, or data paths are affected.
Overview
Fixes DOC-6968 doc slicing and expands example coverage for
incrand C (hiredis).Node.js datatype tutorials: Renames mismatched
STEP_STARTmarkers indt-hash.js(incrby_get_mget) anddt-set.js(sinter), and corrects thesinterexpected-output comment from a Python-style set to['bike:1'], so those tabs render short snippets instead of whole files.cmds_string/ INCR: Adds a sharedincrstep (SET→INCR→GET) to nine clients (Python, Node, ioredis, Predis, Rust sync/async, Lettuce async/reactive, hiredis), with client-accurate>>>comments (e.g. redis-pyTruevsOK) and cleanup keys updated formykey.Example test harness: Registers hiredis as a portable runner (
run_hiredis, system-library discovery, Linux-safe link order), setsportabletohiredisinclients.tsv, and on full sweeps emits explicit SKIP rows for clients excluded from the current mode so missing coverage is visible.testing.mddocuments hiredis limits and the new behavior.Reviewed by Cursor Bugbot for commit cc44a07. Bugbot is set up for automated code reviews on this repo. Configure here.
Second commit — the missing
incrstep for nine clientsAdds an
incrstep (SET mykey 10→INCR→GET) to the redis-py, node-redis, ioredis, predis, rust-sync, rust-async, lettuce-async, lettuce-reactive and hiredis files incmds_string. Nine of the twelve clients oncontent/commands/incr.mdhad no such step, so each of those tabs rendered its client's whole file — 12 to 51 lines — instead of three commands.commands/incr.mdnow renders all 12 client tabs correctly sliced (verified in built HTML: 13 panes including redis-cli, none on the legacy path).Why this is in the same PR, and why it comes first
The shortcode fix tracked in DOC-6968 omits a tab when the client lacks the requested step. On this page that would have cut 12 client tabs to 3, losing Python and Node.js — the two clients most readers arrive with — from a core string command page. Wrong-but-present beats absent for a reader, so the coverage lands before the fix rather than after it. With this in, the fix takes nothing from
incr.md.set()does not returnOKeverywhereredis-py's
set()returns a bool, so the Python tab's comment reads# >>> Truewhere the Go and Jedis reference implementations readOK. Copying the reference value into the Python tab would have been wrong — the same failure mode as the two other defects on this branch, both from an expected value inherited off a sibling client's tab.Verification
True,11,11OK,11,11OK,11,11OK,11,11assert_eq!calls (cargo captures stdout)assertThatcallsOK,11,11(compiled and executed after hiredis was installed locally; see the update below)build/example-test-harness/run.sh cmds_stringreports PASS for all nine, with the pre-existing jedis, go-redis and nredisstack implementations untouched and still passing. The remainingSKIP (no source)entries are clients with no file in this set at all.The C gap is now closed. It was initially unverifiable here —
clients.tsvgives hiredis no portable runner, and no hiredis headers were installed. With the headers now in place it compiles clean (gcc -Wall -Wextra; the only two warnings are pre-existing complaints aboutmain's unusedargc/argv) and runs against Redis 8.8.0, printingOK,11,11— matching all three comments exactly, exiting 0, with no assertion-failure output and no keys left behind.Note for anyone re-running this: hiredis remains untestable through
run.sh, so this was a manualgcc+ execute. TheGaps:trailer on commit 282798c still says the C implementation is unverified; that was true when written and is now stale — see the reflect-note comment on this PR.Whole-site effect of both commits
Legacy-fallback panes across the entire built site: 111 → 100. The eleven removed are exactly the two renames plus these nine
incrpanes; none added.Rendered panes were also checked by eye for Python, C and Java-Async: assertions and cleanup stripped, no
REMOVE/HIDE/STEP_scaffolding reaching the page, and the Lettuce chain still valid Java once its innerREMOVEblocks are removed.