docs(tooling): surface SVG diagram alt text in generated llms-full files#4087
Conversation
Greptile SummaryThis PR adds SVG-diagram-to-text rewriting to the LLM reference-file generator so that diagram embeds (
Confidence Score: 5/5Safe to merge — changes are limited to text post-processing in the reference-file generator and its test suite, with no impact on the live docs or runtime code. The rewriting logic is correct: multiline No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["doc content (trimmed)"] --> B["describeSvgDiagrams()"]
B --> C{line starts with\nfence chars?}
C -- "no fence open\n(opening fence)" --> D["flushProse()\nset fence state\npush line → result"]
C -- "fence open &\nclosing condition met" --> E["clear fence state\npush line → result"]
C -- "fence open &\nnot a closer" --> F["push line → result\n(verbatim)"]
C -- "not a fence line,\nnot in fence" --> G["accumulate in prose[]"]
C -- "not a fence line,\nin fence" --> F
D --> C
E --> C
F --> C
G --> C
B --> H["flushProse() at EOF"]
H --> I["rewriteDiagramEmbeds(prose.join)"]
I --> J["replace p+img.svg → [Diagram: alt]"]
J --> K["replace standalone img.svg → [Diagram: alt]"]
K --> L["replace  → [Diagram: alt]"]
L --> M["result.join('\\n')"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["doc content (trimmed)"] --> B["describeSvgDiagrams()"]
B --> C{line starts with\nfence chars?}
C -- "no fence open\n(opening fence)" --> D["flushProse()\nset fence state\npush line → result"]
C -- "fence open &\nclosing condition met" --> E["clear fence state\npush line → result"]
C -- "fence open &\nnot a closer" --> F["push line → result\n(verbatim)"]
C -- "not a fence line,\nnot in fence" --> G["accumulate in prose[]"]
C -- "not a fence line,\nin fence" --> F
D --> C
E --> C
F --> C
G --> C
B --> H["flushProse() at EOF"]
H --> I["rewriteDiagramEmbeds(prose.join)"]
I --> J["replace p+img.svg → [Diagram: alt]"]
J --> K["replace standalone img.svg → [Diagram: alt]"]
K --> L["replace  → [Diagram: alt]"]
L --> M["result.join('\\n')"]
Reviews (1): Last reviewed commit: "docs(tooling): surface SVG diagram alt t..." | Re-trigger Greptile |
Code ReviewOverviewThis PR adds SVG diagram alt-text surfacing to the CorrectnessAttribute quoting assumption — Second Empty / missing alt — TestsThe new Minor Nits
SummaryThe implementation is correct for all real-world inputs in this repo. Most actionable follow-ups: harden the double-quote assumption in |
4b4b704 to
523b1e2
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Walkthrough
ChangesSVG diagram rewriting in llms-full generator
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code ReviewOverviewThis PR fixes a real gap: the LLM-reference files were silently copying dead Strengths
Issues and Suggestions1. Indented code blocks are not protected (minor correctness risk)
2. Missing test: standalone The test fixture only exercises the 3. Regex won't match multi-line
4. Only double-quoted attributes are matched
SummaryCorrect, well-scoped, and well-tested for the actual doc corpus. The indented-code-block gap (#1) and the missing phase-2 test (#2) are the only items I'd consider fixing before merge; the rest are hardening notes. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@script/generate-llms-full.mjs`:
- Line 289: The callback argument `whole` in the arrow function passed to the
replace method with the SVG regex pattern is unused, which violates the ESLint
no-unused-vars rule. Rename the `whole` parameter to `_whole` to follow the
convention for intentionally unused arguments, which will satisfy the linter and
prevent CI failures.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5201a4e7-e17a-4c7a-a1bb-10039b3a0957
📒 Files selected for processing (4)
llms-full-pro.txtllms-full.txtscript/generate-llms-full-test.bashscript/generate-llms-full.mjs
Code Review: docs(tooling): surface SVG diagram alt text in generated llms-full filesOverviewThis is a focused, well-motivated PR. The #3804 docs-to-SVG migration left dead What's Good
Minor Issues / Observations1. Inline code is NOT protected The fence exclusion skips fenced code blocks but not inline backtick spans. If a doc ever contained a backtick-wrapped inline code example showing a raw 2. Only double-quoted attributes are matched
3. The catch-all second
4. HTML entities in alt text pass through verbatim If any alt text contained VerdictApprove. The core implementation is correct, the design rationale is solid, and the tests cover all the main cases. The observations above are minor — none are correctness bugs for the current doc content. |
The #3804 docs-to-SVG conversion replaced Mermaid/ASCII diagram blocks with `<img src="images/*.svg">` embeds. In the LLM-facing llms-full*.txt files those embeds were dead weight — a relative path that resolves to nothing and no visual — so machine readers lost the structured diagram information they had when the Mermaid source was inline. generate-llms-full.mjs now rewrites each SVG diagram embed (both the `<p><img .../></p>` HTML form and the `` markdown form) to a `[Diagram: <alt text>]` marker when building the text reference. The alt text is the human-authored, accessibility-grade description of the diagram, so this keeps a single source of truth (no Mermaid duplication that would drift from the SVGs) while restoring the semantic content for LLM consumers. Embeds inside fenced code blocks are left verbatim so JSX `<img>` examples are never touched. Adds a generator test covering both embed forms and the code-fence exclusion, and regenerates llms-full.txt / llms-full-pro.txt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… filter Address advisory review feedback on the SVG diagram alt-text filter by adding two negative-path assertions to the generator test: - A PNG screenshot (non-SVG <img>) passes through verbatim; only .svg embeds are rewritten to diagram markers. - An SVG embed with empty alt collapses to a bare [Diagram] marker rather than emitting an empty description or leaving a dead relative path. These edge cases are the ones most likely to regress silently if the filter logic is adjusted later. The generator code already handled both correctly; this only closes the test-coverage gap. No change to generated llms-full*.txt output. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The `` replace callback in rewriteDiagramEmbeds binds the full-match argument as `whole` but only uses `alt`, tripping ESLint `no-unused-vars` (the shakacode config allows unused args only when `_`-prefixed). Rename to `_whole`. Pure no-op for generator output — llms-full*.txt are byte-identical after regeneration. Flagged by CodeRabbit review. The repo lint job is path-gated and was skipped for this docs/tooling PR, so the violation would otherwise surface on a full-CI or main run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
eb22595 to
4851e64
Compare
|
Code Review: PR 4087 - Surface SVG diagram alt text in llms-full files Summary: Clean, well-scoped fix. The approach (alt text as semantic fallback rather than re-embedding Mermaid source) is the right call -- single source of truth is preserved and the accessibility description carries the structural meaning an LLM needs. Low risk: build script and generated outputs only, no application runtime paths changed. CORRECTNESS Fence detection is spec-correct. The CommonMark-aligned close-fence check (char === fence.char && len >= fence.len && isBareFence) correctly prevents a fenced block from being closed by a line with an info string (e.g. triple-backtick-jsx) and handles tildes vs backticks independently. Multi-line img tags are not matched. [^>]* does not cross newlines, so an img tag whose attributes span multiple lines would fall through silently. Current docs always put the img on a single line, so this is safe today -- but a short code comment flagging the constraint would help future maintainers. Double-quote-only attribute matching. rewriteImgTag matches only src and alt with double-quoted values. Single-quoted attributes are silently skipped. Docs are consistent today, so not a real issue -- just worth noting for future authors. Two-pass img replacement. The first regex handles the p-wrapped img canonical pattern; the second catches bare img tags outside a p wrapper. A lone SVG img in prose is also rewritten -- appears intentional but is not covered by any test fixture. TEST COVERAGE GAP test_svg_diagram_embeds_become_text_descriptions covers five key scenarios well. The one missing case is a bare SVG img outside a p wrapper -- the second .replace in rewriteDiagramEmbeds (line 288) handles it but no fixture exercises it. MINOR STYLE NOTE isBareFence (line 314) is always computed in the opener block but only consumed in the fence-close branch. Moving it inside the else-if would make the data flow marginally clearer -- purely cosmetic, not a bug. VERDICT: Approve. Correct for the current doc conventions, tests are solid, and the design rationale (alt-text-as-semantic-fallback over re-introducing Mermaid source) is sound. Does not block merge. |
…4053) (#4063) ## Why Issue #4053: the recommended renderer readiness probe `curl --http2-prior-knowledge -fsS http://localhost:3800/ready` breaks container startup. The container never becomes ready; removing `-fsS` "fixes" it (but then the probe always passes, defeating its purpose). **Root cause (confirmed in `worker.ts`):** `-f`/`--fail` makes curl exit non-zero on any HTTP status `>= 400`, and `/ready` returns `503 {"status":"waiting_for_bundle"}` during the cold-start window until the answering worker compiles its first bundle. A `--fail` probe against `/ready` with no warm-up path therefore deadlocks startup. This is intended gating behavior — but the docs lacked an explicit per-endpoint status-code contract and any Control Plane guidance, so the reporter hit the deadlock without a clear answer. Endpoint contract (from [`worker.ts`](packages/react-on-rails-pro-node-renderer/src/worker.ts)): - `/health` → always `200` - `/info` → always `200` - `/ready` → `200` once a bundle is compiled, else `503` ## What changed Documentation only — `docs/oss/building-features/node-renderer/health-checks.md`: 1. **Status-Code Contract** section with a per-endpoint table and a callout explaining exactly why `curl -fsS .../ready` breaks startup, and what to probe instead (`/health` or `/info` for an always-passes probe; reserve `--fail` against `/ready` for setups with a warm-up path). 2. **Control Plane (CPLN)** section: CPLN exposes HTTP and Command (exec) probes; the HTTP probe is HTTP/1.1 and cannot speak the renderer's h2c listener, so use a Command probe with h2c-aware curl against `/health` by default, switching to `/ready` only with a warm-up path. This addresses all three of the issue's requests: a probe command that works, the `/ready`+`/info` status-code contract, and the CPLN-specific probe options. ## Validation - `npx prettier --check` passes on the changed file. - Docs-only; no CHANGELOG entry per `.claude/docs/changelog-guidelines.md` (docs fixes excluded). Fixes #4053 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Documentation-only changes with no runtime, security, or deployment code modifications. > > **Overview** > Documents why **`curl --fail` against `/ready`** can deadlock container readiness during cold start, and how to probe safely. > > Adds a **Status-Code Contract** table for `/health`, `/info`, and `/ready` (including when `503 waiting_for_bundle` is expected) plus guidance to use **`/health` or `/info`** for probes that must pass once the process is up, and **`/ready` with `--fail` only when a warm-up path** compiles the first bundle. > > Adds a **Control Plane (CPLN)** section explaining that HTTP probes cannot use the renderer’s **h2c** listener, with example **`exec` Command probes** using h2c-aware `curl` against `/health` for readiness and liveness. The same content is mirrored in **`llms-full.txt`**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 40ae833. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added a “Status-Code Contract” describing expected HTTP responses for health endpoints, including when `/ready` may return `503` during cold start * Expanded guidance on `curl --fail`/`-f`/`-fsS`, warning against using `/ready` as a failing readiness gate without a warm-up path * Added Control Plane-specific probe instructions and example probe shapes to match connectivity constraints <!-- end of auto-generated comment: release notes by coderabbit.ai --> ## Agent Merge Confidence (coordinator) **Merged by Claude Code coordinator under explicit maintainer (justin808) delegation** — "merge authorization if confident + documented." - **Confidence: HIGH.** Docs-only (`docs/oss/.../health-checks.md`) + regenerated `llms-full.txt`. - **Rebased** onto merged #4087 (Group B, generated `llms-full.txt` serialization); `llms-full.txt` regenerated via `node script/generate-llms-full.mjs` — regeneration produced zero diff and the `--check` guard passes (auto-merge was correct). - **Doc accuracy verified vs source:** `/health`→200, `/ready`→200/503 `waiting_for_bundle` confirmed against `packages/react-on-rails-pro-node-renderer/src/worker.ts`; CPLN probe schema confirmed against `react_on_rails_pro/.controlplane/rails.yml`. - **Current-head review threads triaged against the actual file (not merged blind):** the recurring CodeRabbit/claude/codex "missing `timeoutSeconds`" and greptile "missing liveness probe" flags are **stale/incorrect** — the CPLN snippet already contains `timeoutSeconds: 5` on both `readinessProbe` and `livenessProbe`. `startupProbe` omission is intentional and safe (probes `/health`, always 200; cold start cannot misfire). The `-sfS` and localhost-qualification notes are advisory/misreads. No actionable must-fix remained. - **CI:** `mergeStateStatus: CLEAN`, all checks pass/skip. **Merge ledger** sole hard violation `unknown_review_decision` — overridden by maintainer merge delegation. Changelog `not_user_visible`. - **Cross-batch:** Batch-1 #4037 also touches `llms-full.txt` and must rebase+regenerate after this merge. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* origin/main: (40 commits) feat(pro): use built-in Rails i18n compiler for React Intl demo (#4128) Fix pr-merge-ledger UTF-8 crash under non-UTF-8 locale (#4123) Add canonical AI-agent prompts source (prompts.yml) (#4124) Local benchmark runner: raise server-boot timeout for slower machines (#4073) (#4125) Docs(generator): note Pro production devtool for source-mapped SSR stacks (#3893) (#4113) docs: add "Consuming an Unreleased Build" guide and fix pnpm git-subdir syntax (#4117) Address deferred AI-review feedback on PR-helper scripts (#4069) (#4105) Wrap generated demo file paths in onboarding page (Part 1 of #4062) (#4107) fix(ci): build bundle-size base from PR merge commit's first parent (#4110) Add internal RSC architecture deep-dive docs (RoR Pro vs Next.js) (#4006) Disable noisy automatic benchmark regression issue filing (#4071) (#4116) Release-train branching + phase-tiered merge gating (beta/RC/final) (#4018) Fix Webpack dependency selection in install generator (#4109) Document health-probe status-code contract and Control Plane probes (#4053) (#4063) Local dedicated-hardware benchmark runner (#4073) (#4088) docs(tooling): surface SVG diagram alt text in generated llms-full files (#4087) docs(agents): codify review-loop convergence + local/CI parity in PR-batch workflow (#4101) Split RenderFunction: drop the legacy renderer arm (#4096) Add OSS hydrate_on scheduling (#4037) Docs: fix stale evaluate-issue gate cross-reference (#3910) (#4104) ...
Why
The #3804 docs-to-SVG initiative replaced inline Mermaid/ASCII diagram blocks with
<img src="images/*.svg">embeds. The generatedllms-full.txt/llms-full-pro.txtfiles (built byscript/generate-llms-full.mjsand consumed by LLMs as plain text) copy each doc body verbatim — so after the conversion, an LLM reading those files saw only a raw<img>tag: a relative path that resolves to nothing and no visual. The structured diagram information it had when the Mermaid source was inline was lost.This was flagged in #4084 review and deliberately deferred from that doc-only PR.
What
generate-llms-full.mjsnow rewrites each SVG diagram embed to a[Diagram: <alt text>]marker when building the text reference:<p><img src="…svg" alt="…" /></p>HTML form and themarkdown form..svgsources are rewritten — screenshots (.png) and JSXsrc={…}examples are left alone.<img>code samples are never corrupted.Why alt text rather than re-introducing Mermaid
The alt text is the human-authored, accessibility-grade description of each diagram. It captures the semantic content (branches, decisions, edge labels expressed as prose) that matters to an LLM, while keeping a single source of truth — re-introducing the Mermaid source would mean maintaining a second representation that drifts from the SVGs, defeating the point of #3804. Improving a diagram's machine description is now the same act as improving its accessibility text.
Result
44 diagram embeds across the OSS and Pro docs now render as readable
[Diagram: …]blocks in the generated text. Example:Tests
generate-llms-full-test.bashcase covering both embed forms and the code-fence exclusion.node script/generate-llms-full.mjs --checkpasses (regeneratedllms-full.txt/llms-full-pro.txtcommitted).🤖 Generated with Claude Code
Note
Low Risk
Docs and build-script output only; no application runtime or auth paths change.
Overview
script/generate-llms-full.mjsnow runs doc bodies throughdescribeSvgDiagramsso SVG diagram embeds become[Diagram: …]text instead of dead<img src="images/*.svg">paths inllms-full.txtandllms-full-pro.txt.Rewriting covers
<p><img … /></p>andforms, limits to.svgsources (PNG screenshots stay as-is), and skips fenced code blocks so JSX<img>examples are not altered. Empty alt collapses to[Diagram].script/generate-llms-full-test.bashadds coverage for both embed forms, non-SVG passthrough, code-fence preservation, and empty alt. The regenerated llms-full outputs reflect the new markers across OSS and Pro docs.Reviewed by Cursor Bugbot for commit 4851e64. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
Documentation
Build/Generation
<img>diagrams into text markers while leaving non-SVG images and fenced code snippets unchanged.Tests
<img>examples.Merge rationale (maintainer-authorized)
Merged by the coordinator agent under explicit maintainer merge authorization ("you have merge authorization if you are confident and you document why").
Confidence basis, verified at merge time:
pr-ci-readinessverdictREADY, no failing/pending checks;check-llms-fullpassing.script/generate-llms-full.mjs, its test harness, and the regeneratedllms-full*.txt. No library/runtime code. Changelog classification:not_user_visible.523b1e2d.reviewDecisionis empty (no required reviewers; author cannot self-approve). This is the documented maintainer waiver of that gate, not an unreviewed merge — the change was reviewed by CodeRabbit, Greptile, claude-review, Cursor Bugbot, and CodeQL with no blocking findings.Coordination: agent-coord merge lane claimed by
coord-elegant-hermann-4087-merge; prior implementerworker-batch-4087-llms-full-altreleased its claim and handed off "ready".