Skip to content

[luv-313] fix: strip stray trailing ``` fences from translated MDX (Mintlify deploy unblock)#313

Merged
NiveditJain merged 6 commits into
mainfrom
luv-313
May 8, 2026
Merged

[luv-313] fix: strip stray trailing ``` fences from translated MDX (Mintlify deploy unblock)#313
NiveditJain merged 6 commits into
mainfrom
luv-313

Conversation

@NiveditJain
Copy link
Copy Markdown
Member

@NiveditJain NiveditJain commented May 8, 2026

Summary

Same change set as the now-closed #311, rebased onto latest main (which moved past 939ad19 via the auto-translate workflow runs #309/#310/#312). Force-push was blocked by repo policy, hence the new branch.

  • New stripStrayTrailingFence(content: string) helper in scripts/translate-docs/mdx-translator.ts: detects an odd count of ``` fence-line markers and drops only the last unmatched one, preserving every balanced pair before it.
  • Wired into both translateMdxPage (after sanitizeJsxAttributes) and translateReadme (before the RTL <div> wrap).
  • Surgical fix to all three already-broken files in main:
    • docs/i18n/README.he.md — initial offender from run 25542951106
    • docs/i18n/README.tr.md — initial offender from run 25542951106
    • docs/i18n/README.ar.md — regenerated by main's auto-translate run [auto] update translations #312 with the same bug; caught during the rebase
  • Six-case unit test in __tests__/scripts/translate-docs/mdx-translator.test.ts.

Why

Streamed Sonnet runs of long pages (post-#307) sometimes append an unmatched ``` to the end of the translation. The Mintlify MDX parser interprets it as opening a code block that consumes everything to EOF — including the wrapping </div> for RTL pages — and surfaces as:

Failed to parse page content at path i18n/README.he.md:
Expected a closing tag for `<div>` (6:1-6:16)

Empirical signal scanning every translated file at HEAD before this PR:

File Fence-line count Status
docs/i18n/README.en.md (source) 30 canonical
docs/i18n/README.he.md 31 ❌ stray
docs/i18n/README.tr.md 31 ❌ stray
docs/i18n/README.ar.md 31 ❌ stray (regenerated #312)
All other 11 translated READMEs 30
All 18 × 13 translated MDX pages even

Sporadic LLM output noise, not deterministic. The sanitizer is the right shape because it only fires on odd counts (no false positives) and strips only the last fence-line.

Test plan

  • bunx tsc --noEmit clean
  • bun run test:run -- mdx-translator.test — 24 passed (6 new + 18 existing)
  • Repo-wide scan: 0 unbalanced files at HEAD
  • CI green (quality / test / build / test-e2e) on this PR
  • Once merged, Mintlify deploy on main succeeds (was failing on the <div> parse error)
  • Next gh workflow run translate-docs.yml -f force=true exercises the sanitizer on a fresh translation

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Streaming-based document translation to avoid timeout failures; increased per-job concurrency for faster translations.
  • Bug Fixes

    • Removal of stray trailing Markdown fence artifacts that caused parsing errors (including RTL READMEs).
  • Tests

    • Added unit tests covering stray-fence detection and removal scenarios.
  • Documentation

    • Added attribution/branding lines to several localized README files.
  • Chores

    • Tuned SDK retries and CI parallelism settings to improve translation reliability.

NiveditJain and others added 3 commits May 8, 2026 01:01
…X parser on RTL READMEs

Streaming Sonnet runs of long pages sometimes append an unmatched ```
line to the end of the translation. The Mintlify MDX parser interprets
that as opening a code block that consumes everything to EOF, including
the wrapping `</div>` on RTL pages, surfacing as
"Failed to parse page content at path i18n/README.he.md: Expected a
closing tag for <div> (6:1-6:16)".

New `stripStrayTrailingFence` helper in mdx-translator.ts detects the
odd-fence-count case and removes only the last unmatched fence,
preserving every balanced pair before it. Wired into both
`translateMdxPage` and `translateReadme`. Surgical fix to the two
already-broken files (`docs/i18n/README.he.md`, `docs/i18n/README.tr.md`)
so Mintlify can deploy today without a full re-translate.

Six-case unit test in __tests__/scripts/translate-docs/mdx-translator.test.ts.

Refs: post-streaming-switch run 25542951106

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…elated to this PR)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address CodeRabbit comment on PR #311.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7d2ea2c9-08ff-43de-b08f-27e38c683c19

📥 Commits

Reviewing files that changed from the base of the PR and between 2461a8f and 5a6813e.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • __tests__/scripts/translate-docs/mdx-translator.test.ts
  • scripts/translate-docs/mdx-translator.ts

📝 Walkthrough

Walkthrough

Adds stripStrayTrailingFence to remove unmatched trailing triple-backtick fences from translated content; integrates it into MDX and README translation flows, adds unit tests, and documents reliability and concurrency tuning in the changelog and i18n READMEs.

Changes

Translation Pipeline Fence Cleanup

Layer / File(s) Summary
Core Sanitization Utility
scripts/translate-docs/mdx-translator.ts
stripStrayTrailingFence function counts fence markers and removes the final unmatched fence line when total count is odd.
MDX Translation Pipeline
scripts/translate-docs/mdx-translator.ts
translateMdxPage sanitization flow now applies three sequential transformations: sanitizeJsxAttributesstripStrayTrailingFencerewriteInternalLinks.
README Translation Pipeline
scripts/translate-docs/readme-translator.ts
Imports and applies stripStrayTrailingFence to translated content before composing output file (translatedcleaned).
Test Coverage
__tests__/scripts/translate-docs/mdx-translator.test.ts
Adds six test cases covering balanced fences, unmatched trailing fences, single fence removal, no-fence preservation, start-of-line-only fence detection, and quad-tick handling; updates imports.
Changelog & Attribution
CHANGELOG.md, docs/i18n/README.he.md, docs/i18n/README.tr.md, docs/i18n/README.ar.md
Unreleased changelog entries document fence sanitizer, Bedrock streaming change, SDK retry increase (2→5), concurrency increase (2→4), and GitHub Actions matrix cap (max-parallel: 4); i18n READMEs receive ExosphereHost attribution footers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I nudge the fences, trim the stray,
A rabbit coder saves the day—🐇
Lines now balanced, builds run clean,
Translated pages neat and seen.
Hoppity hop, the docs convene.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is comprehensive and well-structured but does not follow the template structure with Type of Change and Checklist sections from the repository's template. Consider reformatting the description to include the required 'Type of Change' (Bug fix selected) and 'Checklist' sections from the repository template for consistency and to verify all checks pass.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a helper to strip stray trailing code fences from translated MDX to unblock Mintlify deployment.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands and usage tips.

NiveditJain and others added 2 commits May 8, 2026 01:04
…ng on main)

The auto-translate run on main (#312) regenerated docs/i18n/README.ar.md
with the same trailing-fence bug observed on he/tr. Drop the stray
fence so Mintlify can parse this file too. Sanitizer in the script
will prevent recurrence on future runs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@CHANGELOG.md`:
- Line 6: Update the PR number in the Unreleased changelog entry: locate the
bullet that references the new stripStrayTrailingFence helper (mentions
translateMdxPage and translateReadme) and replace the suffix "(`#311`)" with the
correct PR number "(`#313`)" so the Unreleased entry reflects the current PR.

In `@scripts/translate-docs/mdx-translator.ts`:
- Around line 81-90: stripStrayTrailingFence currently treats any line starting
with three backticks as a fence and can remove legitimate inner backtick lines
inside longer-fence blocks; update stripStrayTrailingFence to detect fenced code
blocks robustly by replacing the /^```/ test with a fence regex like /^(?:
{0,3})(`{3,})([^`]*)?$/ and track an "open" fence object (markerLength and
index) while iterating lines: on first fence set open, on a subsequent fence
close it only if its marker length is >= open.markerLength, and only remove the
unmatched opening fence (open.index) at the end if still open; keep references
to symbol names stripStrayTrailingFence, fenceRe, and open so you can locate and
implement the change.
🪄 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: 8b679018-4431-4f0f-9669-db69098e8468

📥 Commits

Reviewing files that changed from the base of the PR and between 8bebb7c and 06f9bc6.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • __tests__/scripts/translate-docs/mdx-translator.test.ts
  • docs/i18n/README.he.md
  • docs/i18n/README.tr.md
  • scripts/translate-docs/mdx-translator.ts
  • scripts/translate-docs/readme-translator.ts
💤 Files with no reviewable changes (2)
  • docs/i18n/README.he.md
  • docs/i18n/README.tr.md

Comment thread CHANGELOG.md Outdated
Comment thread scripts/translate-docs/mdx-translator.ts
… ref to #313

Address CodeRabbit findings on PR #313:
1. /^```/ matched 4-tick fence markers too, which would miscount inner
   ``` content inside a quad-tick block as a fence marker. Tightened to
   /^```(?!`)/ so only exactly-three-backtick lines are counted.
2. CHANGELOG entry referenced #311 (the predecessor of this PR); updated
   to #313.

Added regression test for the quad-tick edge case.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@NiveditJain NiveditJain merged commit c4506b9 into main May 8, 2026
8 checks passed
NiveditJain added a commit that referenced this pull request May 8, 2026
Promote the six entries accumulated under `## Unreleased` to a versioned
heading `## 0.0.10-beta.6 — 2026-05-08`. Add a fresh `## Unreleased`
heading at the top for the next development cycle.

package.json was already at 0.0.10-beta.6 (pre-bumped); no version edit
needed here. The CHANGELOG cut completes the release-prep handshake.

Entries promoted:
- Cursor Stop hook enforcement fix (this PR)
- 5 scripts/translate-docs fixes from #305, #306, #307, #312, #313

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
NiveditJain added a commit that referenced this pull request May 8, 2026
…a.6 (#318)

* [luv-319] fix: enforce Stop hook on Cursor Agent CLI (followup_message + SubagentStop parity)

Cursor's `stop` hook ignores the flat `{permission: "deny"}` shape — that's
honored on tool events only. The only force-retry channel for Stop is
`{followup_message}` on stdout (exit 0), per https://cursor.com/docs/hooks.
The instruct branch already used this shape correctly since #245; the deny
path needed the same treatment, mirroring Copilot's #299 fix.

Without this, the 5 require-*-before-stop builtins were observation-only on
Cursor — the deny was logged but the agent stopped cleanly. User repro:
session 1b510ad4-906c-4f30-9467-ff2e6c581cce at /home/nivedit/dev-purge.

Also subscribes to `subagentStop` (CURSOR_HOOK_EVENT_TYPES + CURSOR_EVENT_MAP)
and widens both deny and instruct branches to match it, for parity with the
Copilot SubagentStop widening from #299.

Cloud Agents caveat: Cursor Cloud Agent VMs do NOT run stop/subagentStop
hooks at all, so this fix only covers local Cursor sessions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: cut 0.0.10-beta.6 release in CHANGELOG

Promote the six entries accumulated under `## Unreleased` to a versioned
heading `## 0.0.10-beta.6 — 2026-05-08`. Add a fresh `## Unreleased`
heading at the top for the next development cycle.

package.json was already at 0.0.10-beta.6 (pre-bumped); no version edit
needed here. The CHANGELOG cut completes the release-prep handshake.

Entries promoted:
- Cursor Stop hook enforcement fix (this PR)
- 5 scripts/translate-docs fixes from #305, #306, #307, #312, #313

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant