fix(ai): stop /format from rewriting lines inside code fences - #312
Merged
petertzy merged 2 commits intoOct 2, 2026
Merged
Conversation
_apply_markdown_formatting_rules() normalised every line independently with no notion of fences, so a leading '#', '-' or '1.' inside a code block was read as heading/list syntax and rewritten. A shell shebang became '# !/usr/bin/env bash' -- the script no longer runs -- and the float 1.5 became '1. 5'. Both are applied with no confirmation, so running 'format' over a snippet silently produces broken code. Track fence state in the loop and pass fenced lines through. The opener is ``` or ~~~ indented up to 3 spaces (CommonMark); the closer must use the same char and be at least as long; an unclosed fence protects the rest, as the renderer does. Fenced lines still get rstrip() so blank-line collapsing is unchanged. Prose behaviour is byte-identical -- verified original vs patched on '#heading', '####deep', '-item', '*star', '1.item', ' ###x'. Adds 7 cases; verified 6 fail against the unmodified ai_logic.py (the 7th is the prose-baseline guard, which must pass either way).
Owner
|
Approve. This change correctly prevents /format from rewriting content inside fenced code blocks while preserving existing prose formatting behavior. I also fixed an edge case where a fence line with an info string, such as ```python, could be incorrectly treated as a closing fence. All backend tests pass (265 passed), and Ruff checks are clean. |
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
/formatrewrote lines inside fenced code blocks, corrupting executablecode. A script's shebang was made invalid, and numeric literals were split.
Before
_apply_markdown_formatting_rules()normalised every line independently, withno notion of code fences:
Inside a fence those prefixes mean something else entirely:
/format#!/usr/bin/env bash# !/usr/bin/env bash1.51. 5#comment# comment#cfg: true# cfg: trueThe shebang is the serious one: this is applied with no confirmation, so running
"format" on a shell-script snippet produces something that no longer executes.
Changes
backend/ai_logic.py— track fence state in the loop and pass fenced linesthrough untouched.
Details that matter:
_CODE_FENCE_REallows up to three leading spaces, per CommonMark, andboth
```and~~~the opener, so a
~~~inside a```block is treated as coderenderer treats it
Fenced lines still get
.rstrip(), so the blank-line collapsing below isunchanged and output is stable.
Prose behaviour is byte-identical to before. I verified the original and
patched functions agree exactly on
#heading,####deep,-item,*star,1.itemand###x.Testing
tests/test_ai_automation_logic.py::TestFormattingRulesSkipFencedCode, 7 cases:~~~inside a```block is codeVerified 6 of the 7 fail against the unmodified
ai_logic.py; the seventhis the prose-baseline guard, which must pass both before and after.
Verification
pytest— 202 passed (was 195 onmain; this PR adds 7)ruff check/ruff format --checkon changed files — cleannpm test— 23 passed, unchangednpm run lint/npm run build— clean