Repository navigation
Description
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
Listarm decides task-vs-plain from the first child only (pkgs/id/src/web/markdown.rs:223-226—is_task_list= first child is aTaskItem), then converts every child by its own kind, producing a mixed-children list node. - Save:
prosemirror_to_markdownfirst 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), andplacement_allowed(markdown.rs:980-981) allows onlyListItemunder bullet/ordered lists and onlyTaskListItemundertask_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_listdeclarescontent: "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
- All four mixed shapes above open and save without error; checkbox states and plain items are all preserved, and the saved form is a fixpoint on a second save.
- The chosen representation is coherent across all three layers — codec parse, codec save (placement validation), and the editor schema (
editor.ts) — with a note in the PR on which shape was picked (e.g. split into adjacent sibling lists at parse time, mirroring the id(web): adjacent bullet lists with different markers accumulate '<!-- end list -->' comments and html fences on every save — non-fixpoint, grows per save #1032 coalescing precedent in reverse; or mixed children allowed end-to-end) and what it does to list numbering/tightness for ordered lists. - Pure task lists and pure plain lists round-trip byte-identically to today (existing tests keep passing).
- Regression tests in
pkgs/id/src/web/markdown.rscover mixed bullet and mixed ordered lists in both first-child orders. - No relaxation of the id(web): prosemirror_to_markdown panics on misplaced nodes — json_to_ast never validates block/inline placement #1043 placement validation for genuinely misplaced nodes (its five panic-shape tests keep passing).
Activity
developing-today commentedon Oct 27, 2026
CODE-466
dezren39 commentedon Oct 27, 2026
🤖 Agent note · filed
dezren39 commentedon Oct 27, 2026
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
157 remaining items
dezren39 commentedon Oct 28, 2026
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 checkrollup job, queued with no runner assigned since 12:41Z. Task parked 20 min; resume = merge PR #1590 as soon as the rollup completes green.dezren39 commentedon Oct 28, 2026
🤖 Agent note · picked up
Merge pull request #1590 from developing-today/queue/1676-1370-mixed-…
dezren39 commentedon Oct 28, 2026
🤖 Agent note · done