Repository navigation
Description
Problem
In the id web editor's markdown codec (pkgs/id/src/web/markdown.rs), a fenced code block without an info string is rewritten as an indented (4-space) code block on save. The user's chosen fence form is destroyed on every open→save, even when nothing else changed. An empty fenced block additionally gains a spurious blank line.
Evidence (verified this run)
Round-trip probe on main a2eef6f7 (standalone crate compiling the verbatim pkgs/id/src/web/markdown.rs against comrak 0.56.0 + serde_json; full logs in the goal's hidden_files/probe-2026-10-26-0312/out.log and out3.log):
| Input | Saved output |
|---|---|
``` block with blank lines, no info (```\nline1\n\n\nline2\n```) |
indented block: line1\n \n \n line2 |
```` block containing a ``` line (no info) |
indented block: ```\n inner |
| fenced block (no info) inside a list item | rewritten to a 6-space indented block inside the item |
| fenced block (no info) inside a blockquote | rewritten to indented form (> code line) |
empty fenced block (```\n```) |
```\n\n``` — a blank content line appears |
```rust block with blanks (control, has info) |
stays fenced, unchanged ✓ |
The rewritten forms are currently stable fixpoints (a second round-trip does not degrade them further), so this is a fidelity/diff-noise bug rather than progressive corruption — but the rewrite is unconditional: merely opening and saving a note reformats every info-less fenced block in it.
Root cause (to confirm in triage)
json_to_ast builds every code_block as fenced: true, fence_length: 3 (pkgs/id/src/web/markdown.rs:885-890), yet comrak's format_commonmark renderer still emits the indented form for these blocks — the cases above suggest it does so whenever there is no info string (the rust-info control stays fenced). Separately, the literal is always built as format!("{content}\n") (:890), so an empty block's literal is a single "\n", which renders as the spurious blank line. The existing round-trip test (test_roundtrip_code_block) only covers an info-carrying block, so neither behavior is pinned.
Why it matters
- Silent reformatting on save pollutes diffs in synced/vault notes and erodes trust in the editor's other (correct) round-trips.
- Indented code is context-fragile once the user edits the saved file by hand or in another tool: it cannot interrupt a paragraph, is invisible as a block, and is the form most likely to be mangled by other markdown tooling.
- Info-less fences are the common case for plain shell/output snippets.
Acceptance criteria
- A fenced code block without an info string round-trips open→save still fenced (byte-identical modulo the file's trailing newline), including blocks with blank lines, blocks containing ``` lines, and blocks nested in list items and blockquotes.
- An empty fenced block round-trips with no spurious blank line added.
- Info-carrying blocks and all existing codec tests are unchanged; new unit tests in
pkgs/id/src/web/markdown.rscover the info-less and empty cases. - Saved output is a stable fixpoint on a second round-trip.
Activity
dezren39 commentedon Oct 26, 2026
🤖 Agent note · state: filed
dezren39 commentedon Oct 27, 2026
🤖 Agent note · filed
- item+ twoblocks ("code", "more") → save 1 renders both as one indented region (` code\n\n more`) → re-parse yields a SINGLE code_block with literal `code\n\nmore` (PM2 inspected) → save 2 is that merged block. Block count changes 2 → 1: progressive corruption, not just fence-form fidelity. Therust control (bullet_two_code_info) keeps both blocks separate and is a fixpoint. Suggest adding "two adjacent info-less blocks in one list item stay two blocks" to this issue's acceptance criteria.dezren39 commentedon Nov 2, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 2, 2026
🤖 Agent note · handed off
40 remaining items
dezren39 commentedon Nov 5, 2026
agent-note:v1
task 1103 (queue repo-health-code-pilot, lane code-h) — handed off
state: parked for opencode claimant
Verified fresh 2026-11-05: issue #954 OPEN, no hard-stop labels (held/user/owned/do-not-merge/do-not-auto-edit absent). Execution lane assigned opencode via fleet queue lane; checkpoint stage handed_off recorded. Claimant launches the bound opencode session; this lane did not work the task directly.
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off