Skip to content

id(web): multi-paragraph footnote definitions fuse into one run of text on save — paragraphs concatenated with no separator #1031

Closed

Description

@dezren39

Summary

In the id web markdown codec (pkgs/id/src/web/markdown.rs), a footnote definition with more than one paragraph loses the paragraph boundary on save: the paragraphs are fused into a single run of text with no separator at all — first + second para saves as firstsecond para. Words are glued together and the definition's block structure is destroyed.

Evidence (verified this run, main 76672b9)

Standalone probe crate carrying a verbatim copy of src/web/markdown.rs (comrak 0.56.0, the locked version), round-tripping markdown_to_prosemirror → prosemirror_to_markdown twice. Probe logs: goal hidden_files/probe-2026-10-26-1815/ (batch2.log, inspect.log).

Input:

text[^a]

[^a]: first

    second para

ProseMirror after parse (inspect.log): the footnote_definition node's content is two bare text nodes — [{"text":"first"},{"text":"second para"}] — the paragraph wrappers are already gone.

First save:

text[^a]

[^a]:
    firstsecond para

The output is a stable spelling from then on, but the document's words are fused and the second paragraph no longer exists as a paragraph.

Root cause (code evidence)

  • Parse direction, markdown.rs:505-520 (NodeValue::FootnoteDefinition arm): iterates the definition's block children and extends one flat inline-content vec with collect_inline_children(child, &[]) for each — block boundaries between children are discarded by construction.
  • Save direction, markdown.rs:1203-1220: re-wraps all of that inline content in a single Paragraph before handing the AST to comrak, so nothing can reintroduce the boundary; adjacent text nodes render concatenated with no separator.

This is the footnote counterpart of #1003 (multi-paragraph table cells fusing), at a different code site with a different representation problem: the PM schema for footnote_definition currently cannot represent more than one block at all. A definition containing a list or code block flattens the same way.

Why it matters

Multi-paragraph footnotes are ordinary markdown (the standard way to write a long footnote). Opening such a document in the id web editor and saving — even without touching the footnote — permanently fuses its paragraphs and glues words together. Silent data corruption on save, in the same family as #981/#1003/#1017.

Acceptance criteria

  • A footnote definition with two paragraphs round-trips with the paragraph boundary preserved (two paragraphs, or a representation that renders identically and is a fixpoint from the first save).
  • No word fusion: saved text never concatenates two block children's text without a separator.
  • A definition containing another block type (list, code block) either round-trips or degrades with an explicit separator, never silent fusion.
  • Regression tests in web::markdown cover the two-paragraph definition (fixpoint asserted over two saves); existing markdown tests pass.

Suggested direction (triage decides): either carry block children on the PM footnote_definition node (schema change, editor side must tolerate it), or — if the flat inline representation stays — join block children with an explicit paragraph break on parse and split on save.

Dedup: searched open + closed issues for footnote — #945 (closed) covers basic footnote round-tripping and single-paragraph definitions; no issue covers multi-block definitions. #1003 is the table-cell site, distinct code path.

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
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 26, 2026
  2. developing-today commented on Oct 26, 2026

    @developing-today
    Contributor
  3. added
    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 18:15 CDT
    • Found via: filed this run
    • Task: Verified with a standalone probe crate carrying a verbatim copy of src/web/markdown.rs (comrak 0.56.0 = locked version) on main 76672b9 (logs hidden_files/probe-2026-10-26-1815/): a two-paragraph footnote definition parses to two bare text nodes (markdown.rs:505-520 flattens block children via collect_inline_children) and saves as firstsecond para — paragraph boundary and separator lost; save side re-wraps all inline content in one Paragraph (:1203-1220). Enqueued as a triage packet to repo-health-code-pilot — the fix may need a PM schema decision for multi-block footnote definitions.
    • Expectation: triage picks the representation (block children on the PM node vs explicit break join/split); done when a two-paragraph footnote definition round-trips without word fusion, fixpoint over two saves.
    • Links: probe evidence in goal hidden_files (see issue body)
  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 26, 2026
  6. 35 remaining items

  7. added
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Oct 27, 2026
  8. added a commit that references this issue on Oct 27, 2026
  9. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    Done — PR #1040 merged (merge commit 596096a); issue auto-closed. CI rerun fully green (the first run's failures were Magic Nix Cache 418 infra, as diagnosed). Codec probe verification from the implementation shift: web::markdown suite 68/68.

    {"v":1,"kind":"note","state":"done","task_id":1210,"summary":"PR 1040 merged on the CI rerun: multi-paragraph footnote definitions carry block children in the PM codec, so they no longer fuse on save. All checks SUCCESS on the rerun.","artifacts":["https://github.com/developing-today/code/pull/1040"],"next":"none — task 1210 complete (fixed_merged)"}
    
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)kind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:donetask/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