Skip to content

id(web): mixed task/plain lists cannot be saved at all — parse builds mixed lists its own placement validation rejects #1370

Closed

Description

@dezren39

Problem

A markdown list that mixes checkbox items with plain items — a very common checklist shape — cannot be saved at all in the id web editor. The codec's parse direction produces a ProseMirror doc its own save direction rejects, so every save of the document fails; the doc is also invalid under the editor's own schema.

Evidence (verified this run on main 0cbb91b1)

Probe: verbatim copy of pkgs/id/src/web/markdown.rs in a standalone crate (comrak 0.56.0), markdown_to_prosemirror → prosemirror_to_markdown. Logs: fleet bookkeeping probe-2026-10-27-creator-a/out2.log + out3.log.

All four mixed shapes fail the same way:

Input Parsed PM shape Save result
- [ ] todo / - plain note / - [x] done task_list containing a list_item Err: Misplaced node: list_item cannot appear inside task_list
- plain note / - [ ] todo / - [x] done bullet_list containing task_list_items Err: Misplaced node: task_list_item cannot appear inside bullet_list
1. [ ] todo / 2. plain step / 3. [x] done task_list (order 1) containing a list_item Err: Misplaced node: list_item cannot appear inside task_list
1. plain step / 2. [ ] todo ordered_list containing a task_list_item Err: Misplaced node: task_list_item cannot appear inside ordered_list

Root cause, both directions:

  • Parse: the List arm decides task-vs-plain from the first child only (pkgs/id/src/web/markdown.rs:223-226 — is_task_list = first child is a TaskItem), then converts every child by its own kind, producing a mixed-children list node.
  • Save: prosemirror_to_markdown first runs the id(web): prosemirror_to_markdown panics on misplaced nodes — json_to_ast never validates block/inline placement #1043 placement validation (markdown.rs:1057-1058), and placement_allowed (markdown.rs:980-981) allows only ListItem under bullet/ordered lists and only TaskListItem under task_list — so the parse direction's own output is rejected.
  • The save route propagates the error (pkgs/id/src/web/routes.rs:1984-1989, ContentMode::Markdown), so the user's save fails outright — not a silent rewrite, a hard failure on any edit to the file.
  • The editor schema agrees the doc is invalid: task_list declares content: "task_list_item+" (pkgs/id/web/src/editor.ts:98-100), so the mixed doc cannot be represented faithfully in the editor either.

Controls from the same probe: pure task lists (bullet, ordered, nested, in blockquotes) and pure plain lists round-trip cleanly; nested task sublists under plain items also work — only same-level mixing breaks.

Why it matters

Checklists with interleaved plain notes/steps are everywhere (shopping lists with headers, procedures with checkbox steps, meeting notes). Today, opening such a file in id and making any edit makes the file unsavable — the user discovers it only when the save errors, with their edit stranded. The #1043 validation did its job (no panic, clean error); the gap is that the parse direction manufactures docs the rest of the system forbids.

Acceptance criteria

Activity

  1. developing-today commented on Oct 27, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/highImportant and time-sensitive
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/mMedium: expected under 1 day of work
    on Oct 27, 2026
  3. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    Intake review

    Codec parse/save asymmetry in pkgs/id/src/web/markdown.rs: parse builds mixed task_list/list_item shapes its own placement validation rejects, so mixed checklists are unsavable and schema-invalid. Reproduced on main 0cbb91b with a standalone-crate probe (all four mixed shapes fail identically). Risk: any fix must keep pure task lists and pure plain lists round-tripping as fixpoints. Suggested approach: decide the canonical PM shape for mixed lists (split into sibling lists, or normalize items) at parse time, then add round-trip regression tests for the four probed shapes.

    Related: Related: #1369 (same codec round-trip family); queue triage task already live for this issue.

    Still live: checked this run — no merged PR in the recent merged list of this repo implements or resolves this issue, and no closing reference was found; the issue stays open.

    🤖 Agent note · filed

  5. added
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    work/assignedQueue worker lifecycle state
    and removed on Oct 27, 2026
  6. 157 remaining items

  7. added
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 28, 2026
  8. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    Parked — CI rollup pending — queue task 1676, lane A shift 2026-10-28.

    PR #1590 @6131d87b: all 31 substantive checks pass (guard, full nix flake check matrix, benchmark, treefmt). The only non-green entry is the aggregate nix flake check rollup job, queued with no runner assigned since 12:41Z. Task parked 20 min; resume = merge PR #1590 as soon as the rollup completes green.

  9. added
    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 Oct 28, 2026
  10. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. added a commit that references this issue on Oct 28, 2026
  12. dezren39 commented on Oct 28, 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)effort/mMedium: expected under 1 day of workkind/bugSomething isn't working (prefixed form of the classic bug label)meta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/highImportant and time-sensitivesource/creatorFiled by the new-issue-creator jobtask/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