Skip to content

DOC-6968 Fix two node-redis step names, and add the missing incr step for nine clients - #3809

Merged
andy-stark-redis merged 4 commits into
mainfrom
DOC-6968-tce-step-name-fixes
Aug 13, 2026
Merged

DOC-6968 Fix two node-redis step names, and add the missing incr step for nine clients#3809
andy-stark-redis merged 4 commits into
mainfrom
DOC-6968-tce-step-name-fixes

Conversation

@andy-stark-redis

@andy-stark-redis andy-stark-redis commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

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.

File Was Now
local_examples/tmp/datatypes/hashes/dt-hash.js STEP_START hIncrBy_hGet_hMget STEP_START incrby_get_mget
local_examples/tmp/datatypes/sets/dt-set.js STEP_START sinster STEP_START sinter
local_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-example could not find the step and fell back to embedding the whole file:

  • develop/data-types/hashes — the Node.js tab for incrby_get_mget rendered 120 lines instead of 14.
  • develop/data-types/sets — the Node.js tab for sinter rendered 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:146 lowercases 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 — sinster is not a command, a method, or a word.

The comment the rename exposed

Making the sinter pane 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 reads assert.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 hpttl in #3808, inherited as 59994 where Ruby returns 59999).

Verification

Check Result
Step names now match the reference client ✅ node-redis named_steps identical to Python's for both sets
Examples still run run.sh hash_tutorial node-redis and run.sh sets_tutorial node-redis both PASS against Redis 8.8.0
Output comments match reality ✅ hash step's 1, 2, 3, 1, 1, 3, ['1','1'] confirmed against the run; sinter corrected to the observed ['bike:1']
Panes now slice ✅ 14 lines and 6 lines respectively, checked in built HTML
Nothing else changed ✅ site-wide legacy-fallback panes 111 → 109, the two removed being exactly these, none added

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 sinster would 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 incr and C (hiredis).

Node.js datatype tutorials: Renames mismatched STEP_START markers in dt-hash.js (incrby_get_mget) and dt-set.js (sinter), and corrects the sinter expected-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 shared incr step (SETINCRGET) to nine clients (Python, Node, ioredis, Predis, Rust sync/async, Lettuce async/reactive, hiredis), with client-accurate >>> comments (e.g. redis-py True vs OK) and cleanup keys updated for mykey.

Example test harness: Registers hiredis as a portable runner (run_hiredis, system-library discovery, Linux-safe link order), sets portable to hiredis in clients.tsv, and on full sweeps emits explicit SKIP rows for clients excluded from the current mode so missing coverage is visible. testing.md documents 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 incr step for nine clients

Adds an incr step (SET mykey 10INCRGET) to the redis-py, node-redis, ioredis, predis, rust-sync, rust-async, lettuce-async, lettuce-reactive and hiredis files in cmds_string. Nine of the twelve clients on content/commands/incr.md had no such step, so each of those tabs rendered its client's whole file — 12 to 51 lines — instead of three commands.

commands/incr.md now 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 return OK everywhere

redis-py's set() returns a bool, so the Python tab's comment reads # >>> True where the Go and Jedis reference implementations read OK. 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

Client Result
redis-py ✅ ran — True, 11, 11
node-redis ✅ ran — OK, 11, 11
ioredis ✅ ran — OK, 11, 11
predis ✅ ran — OK, 11, 11
rust-sync / rust-async ✅ ran, 1 test passed each; values confirmed by the in-step assert_eq! calls (cargo captures stdout)
lettuce-async / lettuce-reactive ✅ ran; values confirmed by the in-chain assertThat calls
hiredis (C) ✅ ran — OK, 11, 11 (compiled and executed after hiredis was installed locally; see the update below)

build/example-test-harness/run.sh cmds_string reports PASS for all nine, with the pre-existing jedis, go-redis and nredisstack implementations untouched and still passing. The remaining SKIP (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.tsv gives 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 about main's unused argc/argv) and runs against Redis 8.8.0, printing OK, 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 manual gcc + execute. The Gaps: 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 incr panes; 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 inner REMOVE blocks are removed.

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>
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

DOC-6968

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@andy-stark-redis
andy-stark-redis requested a review from a team August 13, 2026 12:37
@andy-stark-redis andy-stark-redis self-assigned this Aug 13, 2026
@andy-stark-redis andy-stark-redis added bug Something isn't working clients Client library docs labels Aug 13, 2026
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>
@andy-stark-redis andy-stark-redis changed the title DOC-6968 Fix two node-redis TCE step names that never matched their sets DOC-6968 Fix two node-redis step names, and add the missing incr step for nine clients Aug 13, 2026
@andy-stark-redis

Copy link
Copy Markdown
Contributor Author

Correction to commit 282798c's Gaps: trailer — the hiredis gap is closed.

That trailer says the C implementation is not execution-verified and should be run under --fidelity or compiled before its output is trusted. True when written; no longer true. hiredis headers were installed locally afterwards, and the example now compiles clean and runs against Redis 8.8.0, printing OK, 11, 11 — matching all three of its comments, exit 0, no assertion-failure output, no keys left behind.

Not amended into the commit because it was already pushed. /finalize should drop that Gaps: line from the durable squash message rather than carrying it forward, and replace it with the fact that matters:

hiredis cannot be verified through run.sh at allclients.tsv gives it no portable runner, and the harness does not report it as a SKIP either, so it is simply absent from the results table. Anyone editing a C example needs to know that a green harness run says nothing about it, and that the verification route is a manual gcc -I/usr/local/include -L/usr/local/lib -lhiredis plus DYLD_LIBRARY_PATH=/usr/local/lib to execute.

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.

@dwdougherty dwdougherty left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

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>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread build/example-test-harness/run.sh
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>
@andy-stark-redis
andy-stark-redis merged commit 0f2cfea into main Aug 13, 2026
89 checks passed
@andy-stark-redis
andy-stark-redis deleted the DOC-6968-tce-step-name-fixes branch August 13, 2026 14:17
@andy-stark-redis

Copy link
Copy Markdown
Contributor Author

Thanks @dwdougherty !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working clients Client library docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants