Repository navigation
DOC-7047: Formalize DOC-6909 shortcode migration tooling - #3937
Merged
Merged
Conversation
Checks in the three ad hoc converters used to migrate develop/clients/redis-py (relref->plain, callouts->blockquote, absolute->/content/*.md) as build/migrate_shortcode_links.py, plus build/diff_rendered_hrefs.py to verify a migration changed no rendered link. The originals lived only in a scratch session dir and were lost, so later sections would have reinvented them. Also extends check_shortcode_paths.py to validate the new /content/*.md link form at edit time, mirroring the existing relref check (same diff-scoping, same mount-aware resolution) -- previously only relref got this coverage, so a migrated page's broken link had no edit-time catch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
4 tasks done
Contributor
This was referenced Sep 8, 2026
This was referenced Sep 8, 2026
- migrate_shortcode_links.py: _find_content_file no longer follows the module-mount remapping (_mount_variants) when deciding what to rewrite a link to. The one real mount (Active-Active rs/rc) has an open product question attached (DOC-6909 mount probe: relref itself resolves an in-mount-target link to the rs permalink, leaving the rc mount) -- that's a pre-existing site behavior, not this tool's call to make, and silently rewriting to the mount source would bake it into a literal path forever. The validator (check_shortcode_paths.resolve_relref) still follows mounts, since "does this resolve at all" is a different question than "what literal path should a rewrite commit to." No effect on any content actually converted so far -- none of the DOC-7047 client-docs units touch Active-Active pages. - diff_rendered_hrefs.py: comparing two empty page sets (wrong public/ path, or a prefix that matches nothing) now errors instead of silently exiting 0 -- "0 pages compared" was indistinguishable from "0 differences found." Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 8, 2026
Converts content/develop/clients/nodejs/ (12 files, flat directory) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 7 {{< note >}} callouts -> `> [!NOTE]` blockquotes. No nesting, no custom titles, no percent-delimited {{% alert %}} shortcodes in this directory. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Gaps: Human review (dwdougherty) spot-checked a handful of links rather than testing every one; the href-diff build comparison is the completeness evidence, not the manual review. Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 8, 2026
Converts content/develop/clients/dotnet/ (12 files: 8 top-level plus the nested nredisstack/ subdirectory) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 9 note/warning callouts -> `> [!NOTE]`-style blockquotes across 119 converted links. No percent-delimited `{{% alert %}}` forms in this section. Also fixes a pre-existing malformed relref in nredisstack/vecsearch.md (a stray backtick before the closing paren broke the link syntax, so the converter's regex couldn't match it) -- folded into this PR as a bonus rather than a separate ticket. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Gaps: Human review (dwdougherty) was a skim/spot-check, not exhaustive; the href-diff build comparison is the completeness evidence, not the manual review. Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
RELREF_RX required the markdown ')' immediately after '>}}', so
]({{< relref "X" >}}#anchor) and ]({{< relref "X" >}}?query) -- an anchor
or query written OUTSIDE the shortcode rather than inside the quoted path
-- never matched. Those relrefs silently stayed unconverted with no
warning (105 files site-wide use this form, e.g. develop/data-types/_index.md's
`?group=` command-reference links). Fixed by capturing the optional
suffix and re-appending it when unwrapping.
That alone would have introduced a real regression: linkify only
preserved a '#anchor' suffix when resolving the rewritten link, not a
'?query' one, so a freshly-unwrapped ?query link would have had its query
string silently dropped. Fixed linkify to split on the first '#' or '?'
and preserve whichever suffix is present.
Verified: idempotency proof still holds on redis-py (0 changes) and on
the already-merged nodejs/dotnet content (0 changes, checked in a
separate worktree against current main). Live-tested all three shapes
(in-quote anchor, outside-shortcode anchor, outside-shortcode query) --
the query case correctly stays unconverted when its target has no
_index.md, with the query string preserved rather than dropped.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 8, 2026
Converts content/develop/clients/jedis/ (11 files, flat directory) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 6 {{< note >}} callouts -> `> [!NOTE]` blockquotes. No nesting, no custom titles, no percent-delimited {{% alert %}} shortcodes in this directory. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <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 3f8cb7c. Configure here.
dwdougherty
approved these changes
Sep 8, 2026
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/go/ (13 files, flat directory) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form (121 links), and 10 {{< note >}} callouts -> `> [!NOTE]` blockquotes, including one with an embedded fenced code block. No custom titles, no nesting, no percent-delimited {{% alert %}} shortcodes. Also fixes a cosmetic regression a reviewer caught: a note directly after a {{< clients-example >}} widget rendered too close to it, because unwrapping the shortcode to a native blockquote drops the <p>-wrap margin the old shortcode form got for free (the same "benign <p>-wrapping" delta DOC-6909 already flagged as usually harmless). Fixed with a bare ` ` spacer line, the same pattern already used the other way round in go/scan-buffer.md. Confirmed this is the only such adjacency in this unit and doesn't recur in any other DOC-7047 unit. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Learned: unwrapping a callout shortcode to a native blockquote can visibly tighten spacing when it sits directly against another block element (e.g. clients-example) -- watch for this wherever the rollout touches such an adjacency, fix with a bare ` ` spacer line. Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/lettuce/ (10 files) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 5 {{< note >}} callouts -> `> [!NOTE]` blockquotes. produsage.md keeps one {{% alert title="Tip" color="warning" %}} shortcode untouched -- the percent-delimited custom-title form the converter doesn't handle (an accepted gap; the redis-py reference conversion has the same two instances left as-is). Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Gaps: produsage.md's {{% alert %}} (percent-delimited, custom title) is still an unconverted shortcode -- not a miss, the tool doesn't handle this form yet. Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/php/ (8 files) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 3 {{< note >}} callouts -> `> [!NOTE]` blockquotes. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/patterns/ (5 files, including the nested indexes/ subdirectory) from relref shortcodes to the DOC-6909 render hooks: relref -> plain link -> canonical /content/<path>.md[#anchor] form (75 links total). No callouts in this section. Also fixes a dead command-reference anchor a reviewer caught: [text](/commands/#sorted_set) resolved without warning but did nothing -- the #sorted_set anchor doesn't exist on the current filterable /commands/ grid. Replaced with the query-string form the site's own command-group.html shortcode generates internally (?group=sorted-set), which the page's own JS reads on load to pre-select the group filter. Confirmed the render-link hook preserves this query-string form intact (it has explicit, pre-existing handling for exactly this case). Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Directive: always `find <dir> -name '*.md'` recursively when scoping a DOC-7047 unit's files -- a one-level-deep glob misses nested subdirectories (this unit's indexes/ was the first instance). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/rust/ (5 files) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 2 {{< note >}} callouts -> `> [!NOTE]` blockquotes. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/hiredis/ (8 files, including the nested int-examples/ subdirectory) from relref shortcodes to the DOC-6909 render hooks: relref -> plain link -> canonical /content/<path>.md[#anchor] form. No callouts in this section. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts content/develop/clients/ruby/ (5 files) from relref/callout shortcodes to the DOC-6909 render hooks, continuing the DOC-7047 rollout: relref -> plain link -> canonical /content/<path>.md[#anchor] form, and 4 {{< note >}} callouts -> `> [!NOTE]` blockquotes. Also fixes a spacing regression a reviewer caught in queryjson.md and vecsearch.md: two `> [!NOTE]` blocks separated by only a blank line rendered directly touching, since a bare blockquote doesn't get the free <p>-wrap margin the old shortcode form got individually (same root cause as the go/queryjson.md fix in #3948, a different sub-case: adjacent alerts rather than an alert after another widget). Fixed with a bare ` ` spacer line between them. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Directive: a ` ` spacer between two blockquotes needs a blank line on BOTH sides, not just after -- with none before, it lazily continues the preceding blockquote (CommonMark lazy-continuation) and produces zero visual change. Verify by grepping the rendered HTML for a real `<p> </p>` between the two alert divs, not by trusting the source diff. Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
andy-stark-redis
added a commit
that referenced
this pull request
Sep 9, 2026
Converts the 9 shared top-level content/develop/clients/*.md files (pools-and-muxing, error-handling, client-side-caching, etc. -- the files every per-client subdirectory links into) from relref/callout shortcodes to the DOC-6909 render hooks: relref -> plain link -> canonical /content/<path>.md[#anchor] form (109 links), and 4 {{< note >}} callouts -> `> [!NOTE]` blockquotes across _index.md, client-side-caching.md, and sch.md. Verified with a full-site Hugo build merged onto main alongside the rest of its batch: 0 rendered href differences, 0 new build warnings (build/diff_rendered_hrefs.py, from #3937). Ticket: DOC-7047 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bugbot: PLAIN_LINK_RX only allowed an optional #fragment after .md, so it never matched /content/*.md?query -- the form linkify emits when it preserves a `?` suffix (fixed in a prior commit on this branch, house style's ?group= command-reference links). Such links got zero edit-time validation even though resolve_plain_link/_norm_relref already strip both `?` and `#` before resolving; the regex just never captured that href shape to feed them in the first place. Verified: full-repo baseline scan unchanged (39 relref, 0 link issues), and two live tests -- a broken /content/*.md?query link is now caught, a valid one passes silently, and the combined ?query#anchor form works too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3 tasks done
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
develop/clients/redis-py(the DOC-6909 proof section) asbuild/migrate_shortcode_links.py: relref→plain link, callouts→> [!NOTE]blockquote, absolute/plain→canonical/content/*.md. The originals lived only in a scratch session dir and were lost, so later sections would otherwise reinvent them.build/diff_rendered_hrefs.py, an href-fingerprint diff tool to verify a migration changed no rendered link (formalizes the ad hoc recipe used during DOC-6909, excludes the two known-nondeterministic page families by default)..claude/hooks/check_shortcode_paths.pyto validate the new/content/*.mdlink form at edit time, mirroring the existingrelrefcheck (same diff-scoping, same mount-aware resolution). Previously onlyrelrefgot this coverage, so a migrated page's broken link had no edit-time catch.This is Phase 0 of DOC-7047 (rolling the DOC-6909 render-hook migration out to the rest of
content/develop/clients/) — no content changes, prerequisite tooling only.Test plan
build/migrate_shortcode_links.py allrun against the already-converteddevelop/clients/redis-pyproduces 0 changes — proves the formalized tool reproduces the hand-done reference conversion exactly.develop/clients/ioredis(DOC-7047: Migrate develop/clients/ioredis to render hooks #3938) — before/after Hugo build, 0 rendered href differences site-wide, no new warnings.check_shortcode_paths.py --scan --allon currentmain: baseline 39relrefissues (known, pre-existing), 0 newlinkissues./content/*.mdlink is caught; a valid one is not.Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Note
Low Risk
Adds and extends offline build/validation scripts and a Claude edit hook; no production runtime or content changes in this PR.
Overview
Phase 0 tooling only — no content edits. This checks in the workflow needed to roll the DOC-6909 render-hook migration (plain
/content/*.mdlinks + GitHub-style callout blockquotes) beyond the redis-py pilot.Adds
build/migrate_shortcode_links.py, a three-stage, idempotent converter: unwraprelrefshortcodes in links, turnnote/warning/etc. shortcodes into> [!NOTE]blockquotes (before link rewriting so links resolve in page context), then rewrite resolvable internal links to canonical/content/<path>.mdtargets. It reuses mount-aware resolution from the hook module but deliberately does not remap module mounts when rewriting paths.Adds
build/diff_rendered_hrefs.pyto compare two Hugopublic/trees by per-page href fingerprints (optional URL prefix filter, known nondeterministic sections excluded by default) so migrations can prove reader-visible links did not change.Extends
check_shortcode_paths.pyso edit-time validation covers the new markdown link form the same way it already covered absoluterelref(diff-scoped against HEAD, mount-aware resolution, optionalSHORTCODE_SKIP_PLAIN_LINK). Refactors HEAD diffing from relref-only lists to full prior text plus a shared_new_occurrenceshelper.Reviewed by Cursor Bugbot for commit 9194bbc. Bugbot is set up for automated code reviews on this repo. Configure here.