Skip to content

id(web): saving a blockquote that starts with a code block, table or rule inserts two stray blank lines at the top of the quote #1002

Open

Description

@dezren39

Bug

In the id web editor's markdown ↔ ProseMirror codec (pkgs/id/src/web/markdown.rs), saving a document whose blockquote starts with a non-paragraph block (a fenced code block, a table, or a thematic break) inserts two stray blank lines — > lines — at the top of the quote, before that first block:

Input:

> ```rust
> let x = 1;
> ```

After one load/save round trip:

> 
> 
> ```rust
> let x = 1;
> ```

The ProseMirror document is correct throughout (the blockquote contains exactly one code_block, no empty paragraphs) and the output is a stable fixpoint — the two lines appear on the first save and stay. But every affected file gets polluted on save, the quote renders with a gap at the top in other renderers, and the diff noise obscures real edits.

Verified repro (this run, main 3b9d159)

Standalone verbatim-codec probe crate (evidence log: goal hidden_files/probe-2026-10-26-1415/out3.log, probe source is current markdown.rs verbatim):

  • markdown_to_prosemirror("> ```rust\n> let x = 1;\n> ```\n") → {"type":"blockquote","content":[{"type":"code_block","attrs":{"params":"rust"}, …}]} — correct, no empty paragraphs.
  • prosemirror_to_markdown of that document → "> \n> \n> ```rust\n> let x = 1;\n> ```\n" — two leading blank quote lines.
  • Same pattern for a table as first block (> | a |… → two leading > lines) and a thematic break first (> ---\n> text → two leading > lines, plus the normal separator before text).
  • Controls that save cleanly: blockquote starting with a paragraph, a heading, or a list; a blockquote where the same code block is not first (> intro + fence) saves with exactly the one normal separator line.
  • Control isolating the layer: comrak's own parse → format_commonmark render of the original input produces the same two blank lines, so the quirk is in the comrak CommonMark renderer behaviour the codec's save direction relies on (prosemirror_to_markdown, markdown.rs:868-874, serializes a hand-built AST with format_commonmark) — the codec inherits it on every save even though its own AST is correct.

Not #954: that issue is no-info code blocks being rewritten as indented blocks (document-level). This one is about leading blank lines inside a blockquote, affects info-string fences, tables and thematic breaks, and also appears when the block is not first in the file but first in the quote.

Why it matters

Silent file pollution on save, in the same codec family as #982/#954/#981 but a distinct mechanism: quoted code snippets, quoted tables and quoted rules are common in notes/docs, and the first save of any such file rewrites its top-of-quote for no reason.

Suggested fix

In the save direction, stop the two spurious separator lines from reaching the file — e.g. investigate whether the hand-built AST is missing something the renderer keys on for a blockquote's first child (in which case fix json_to_ast's blockquote/code_block construction), or post-process the serialized output to collapse a blockquote's leading blank > lines (only at quote start — blank separators between blocks in a quote are required and must be kept, cf. the > intro + fence control). If the behaviour turns out to be unfixable without forking the renderer, record that and close with the rationale rather than leaving it untracked.

Acceptance criteria

  • Round-trip tests: blockquote starting with (a) a fenced code block with an info string, (b) a table, (c) a thematic break followed by text — each saves byte-identical to its input (no leading > lines).
  • Regression controls unchanged: blockquote starting with paragraph/heading/list, and paragraph-then-fence inside a quote (exactly one separator blank line), still round-trip as today.
  • Existing web::markdown tests pass.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Oct 26, 2026
  2. developing-today commented on Oct 26, 2026

    @developing-today
    Contributor
  3. added
    source/creatorFiled by the new-issue-creator job
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Oct 26, 2026
  4. dezren39 commented on Oct 26, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job
    • Session / ID: new-issue-creator cron run 2026-10-26 14:10 CDT
    • Found via: filed this run
    • Task: Verified with a standalone verbatim-codec probe on main 3b9d159 (log hidden_files/probe-2026-10-26-1415/out3.log): a blockquote whose first block is a fenced code block, table or thematic break saves with two stray leading > blank lines; the ProseMirror doc is correct and comrak's own parse→render shows the same quirk, so it is the save direction's renderer behaviour. Enqueued as a triage packet to repo-health-code-pilot.
    • Expectation: triage decides the fix layer (AST construction vs serializer post-processing); done when quote-first-block round trips are byte-identical and the between-block separator controls still pass.
    • Links: probe evidence in goal hidden_files (see issue body)
  5. added
    effort/sSmall: expected under 2 hours of work
    mode/onlineFully doable remotely: design, config, code, cloud
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  6. 65 remaining items

  7. added
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  8. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  9. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    task: 6565
    state: handed_off
    lane: code-b (queue) / opencode (execution)
    Issue #1002 and canonical PR #4816 re-verified OPEN at claim (2026-11-05), no held/user-owned/do-not labels on either. Execution lane assigned opencode; handing off to the laptop opencode claimant — PR #4816 remains the canonical PR, do not create a competing PR. Parking task 6565 for 20 minutes for the claimant. Note: attempts 32/32 (at max_attempts cap) — if the claimant misses this lease, the task will need a cap raise to be claimable again. Unresolved review items on PR #4816 per prior checkpoint: CodeRabbit major fence-state finding + nitpick on blank quoted line inside fenced block.

  10. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 5, 2026
  11. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: fleet monitor
    • Session / ID: task 6565 (repo-fleet-monitor run 2026-11-05T15:32:18Z)
    • Found via: monitor reconciliation (Duty 1 claim/label divergence repair)
    • Task: Claim evaporated: task 6565 is queued and unclaimed in repo-health-code-pilot, but this issue still carried claimed labels. Labels reset to the truth (queue/queued + status/needs-triage). Checkpoint stage at evaporation: handed_off.
    • Expectation: The next lane claim picks task 6565 up from the queued state and posts a fresh pickup note.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)mode/onlineFully doable remotely: design, config, code, cloudpriority/lowNice to have; do when convenientqueue/parkedQueue task is parked (waiting on CI, time, or an event)queue/queuedHas a queued task in the Supabase agent queuesource/creatorFiled by the new-issue-creator jobstatus/needs-triageNot yet triaged; needs a first lookstatus/parkedDeliberately paused with a recorded resume conditiontask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions