Skip to content

id(web): adjacent bullet lists with different markers accumulate '<!-- end list -->' comments and html fences on every save — non-fixpoint, grows per save #1032

Closed

Description

@dezren39

Summary

In the id web markdown codec (pkgs/id/src/web/markdown.rs), saving a document with adjacent bullet lists that use different markers (-, +, * with no blank line between them — three separate one-item lists) writes literal <!-- end list --> HTML comments into the user's file. Worse, the result is not a fixpoint and grows on every save: on the next save each comment block additionally becomes a ```html code fence, and the save after that duplicates them again. A document with two list boundaries gains two more code blocks per save, forever.

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). Probe logs: goal hidden_files/probe-2026-10-26-1815/ (batch2.log case mixed_markers, inspect.log).

Input:

- a
+ b
* c

Parse (inspect.log): three separate bullet_list PM nodes — correct; the PM model has no marker attribute, so the three lists are indistinguishable from one list except for being separate nodes.

Save 1:

- a

<!-- end list -->

- b

<!-- end list -->

- c

Save 2 (the comments from save 1 now reparse through the HTML-block path, cf. #982, and come back as code fences, while fresh comments are emitted again):

- a

<!-- end list -->

```html
<!-- end list -->
  • b
<!-- end list -->
  • c

Save 3 doubles the accumulated ```` ```html ```` blocks again (two per list boundary; full sequence in `inspect.log`). Every open→save cycle permanently adds blocks to the file.

## Root cause (code evidence)

- Save direction `json_to_ast` (list arms, `markdown.rs:997-1045`) builds a separate comrak `List` node per PM `bullet_list`; comrak's CommonMark renderer separates two adjacent lists of the same type by emitting an `<!-- end list -->` HTML comment — the codec passes that through verbatim into the saved file.
- On reparse, a standalone comment is an HTML block; the codec's HTML-block handling (the behaviour tracked in #982) turns it into a ```` ```html ```` fenced block, while the renderer emits fresh `<!-- end list -->` comments for the still-adjacent lists — hence unbounded growth instead of a fixpoint.

## Why it matters

Mixed-marker adjacent lists appear in real notes (and in files produced by other editors). A user who opens such a file in the id web editor and saves repeatedly watches their document accumulate comment lines and then duplicated code fences — visible corruption that compounds, in the same non-fixpoint family as #944/#981 but with growth per save.

## Acceptance criteria

- `- a` / `+ b` / `* c` (and the two-list case) saves to a form that is a fixpoint from the first save: repeated open→save cycles are byte-stable.
- No `<!-- end list -->` comments or ```` ```html ```` artefacts are introduced into the saved file.
- The saved form still renders as the same list items with the same text (merging the adjacent bullet lists into one list on save is acceptable — the PM model cannot represent the marker distinction anyway; separating them by a construct that round-trips is equally acceptable).
- Regression tests in `web::markdown` assert byte-stability over at least three consecutive saves; existing markdown tests pass.

Suggested direction (triage decides): coalesce adjacent `bullet_list` nodes (same for ordered lists with a continuous `start`, if reproducible) in `json_to_ast` or in the parse direction, rather than letting comrak's renderer invent separators the codec cannot reparse. Interaction with #982 (HTML blocks → ```` ```html ````) should be noted: fixing #982 alone does not stop the comment emission, and fixing the emission alone leaves the comment-reparse path armed for user-authored comments between lists.

Dedup: searched open + closed issues for `end list`, `mixed marker`, `adjacent list` — no matches. #982 covers user-authored HTML blocks becoming code fences, a different trigger; this issue is about the codec's own renderer emitting comments it cannot round-trip.

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/normalOrdinary priority (the default)
    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 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 / + b / * c parses to three bullet_list PM nodes; save 1 emits literal <!-- end list --> comments (comrak renderer separating adjacent same-type lists built by json_to_ast list arms markdown.rs:997-1045); save 2 turns prior comments into ```html fences (the id(web): HTML blocks (comments, <details>, <div>) are rewritten as ```html code blocks on save #982 HTML-block path) plus fresh comments; save 3 doubles the fences — unbounded growth per save, no fixpoint. Enqueued as a triage packet to repo-health-code-pilot (coalesce-on-save vs parse-side coalescing is the triage choice; interacts with id(web): HTML blocks (comments, <details>, <div>) are rewritten as ```html code blocks on save #982).
    • Expectation: triage picks the fix layer; done when mixed-marker adjacent lists are byte-stable over 3+ saves with no comment/fence artefacts.
    • 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 27, 2026
  6. 16 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

    🤖 Agent note · done

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