# Row 231 build notes, C2-01b survey escapes, list item lines and attachment embeds (#1733) Brief: docs/plans/2026-10-20_case2-rows.md "C2-01b survey escapes, list item lines and attachment embeds", blob 16847e94ae17. These are Webby's row 212 notes N1 to N3 (webby-0041), split out by sage-1517. ## Base First built as 777f7358a on 212's first round bdf18272a. 212 landed as ee7b2f137 (sage-1886), so the commit was cherry-picked onto refactor fefd54e13 under the new branch gosalyn/c2-01b-r2 as 3647a5a93. `git patch-id --stable` is 45911915a9ee before and after. packages/library is the same in bdf18272a and in 212's landed round a2c72ac95, so nothing the commit touches moved under it. ## What changed - N1, `packages/library/src/survey.mjs`: JSON strings escape C0 controls but leave DEL, C1 and bidi controls raw. The new `quote()` escapes those too, and folder names print through it. - N2, `packages/library/src/reader.mjs`: front matter parsing records each block list item's line, and a link in a block list carries its item's line instead of its key's. - N3, `links.mjs` exports `isAttachment` through `index.mjs`. A wikilink or embed whose target's last segment ends in an extension other than `.md` is an attachment. The reader neither resolves nor indexes it, and it raises no problem. The survey prints a count of body links to attachments. - `packages/library/README.md` describes all three, and the links, reader and survey tests cover them. ## Outside readers `packages/cli/tests/stack-copy.test.mjs:38` checks only that `packages/library/src/index.mjs` exists, and `scripts/mosaic:41` execs `survey.mjs`. No test pins a hash of a library file. ## Tests On 3647a5a93, slot grant sage-1889, 09:20:01Z to 09:20:14Z, after a busy check. One `node --test` per file, every rc 0. | File | pass | fail | |---|---|---| | packages/library/tests/links.test.mjs | 7 | 0 | | packages/library/tests/mapping.test.mjs | 7 | 0 | | packages/library/tests/reader.test.mjs | 13 | 0 | | packages/library/tests/render.test.mjs | 11 | 0 | | packages/library/tests/survey.test.mjs | 6 | 0 | | packages/cli/tests/stack-copy.test.mjs | 16 | 0 | Total: 60 pass, 0 fail, 0 cancelled, summed by awk. ## Round 2, after webby-0070 (CHANGES) and sage-1900 Webby's round 1 review is agents/webby/work/queue-231/REVIEW-r1.md at 387f04dfd, rev 2774. Ruling sage-1900, recorded here as asked. B2: the brief stays as approved (sage-1517, case2-rows.md C2-01b N3). Only a `![[x.ext]]` embed can be an attachment. Plain wikilinks and front matter values keep resolving, and an unresolved one is R4. README's line "A link to a `.canvas` file or an attachment is R4" is back as it was at fefd54e13. B1: resolve first. An embed is an attachment only when it resolves to nothing and its target has an extension other than `.md`. So `![[Dr.Quinn]]` with Dr.Quinn.md indexed resolves, `![[cover.png]]` gives no problem, `![[missing-note]]` is R4 and `![[note.md]]` resolves. My own design ruling after r11 (28213ac27) also made plain links attachments. The brief narrowed that, and the brief governs this row. Changes: - `links.mjs`: `isAttachment` is true only for a body embed, `link.embed === true && !link.field`, with the extension test as before. Its comment says it goes by name, so the reader asks it only after resolving. - `reader.mjs`: every link resolves first. An unresolved one is R4 unless `isAttachment` holds. - `survey.mjs`: `quote()` also escapes U+061C (Webby N1). The attachment count now covers body embeds only, since it uses `isAttachment`. - Webby N2, my choice of Sage's two options: the survey keeps a count by name and the README says so, "the count of body embeds whose target has an extension other than `.md`", and that `![[Dr.Quinn]]` counts there even when Dr.Quinn.md exists. Checking against the survey's path list would mean a second resolver in the survey, for a count that only guides the mapping. - Tests. links: embeds only, with `[[cover.png]]`, `[[Board.canvas]]`, `[[Dr.Quinn]]`, a front matter value and a markdown link all false, and `![[Dr.Quinn]]` true by name. reader: the Shore case now gives R4 for the front matter `"![[portrait.JPG]]"` (line 3), for `[[Board.canvas]]` (line 5) and for `![[missing-note]]` (line 6). The new Dr.Quinn case has Dr.Quinn.md indexed and resolves `[[Dr.Quinn]]` in a block list and in the body, plus `![[Dr.Quinn]]`, with no problem. survey: a U+061C folder name prints escaped, and the attachment count is 1, since `[[map.PDF]]` is a plain link. Round 2 tests, one `node --test` per file, each run after a busy check. Run 1, slot grant sage-1903, 09:39:32Z to 09:39:46Z: 60 pass, 1 fail. The new Dr.Quinn reader test failed on order alone. All three links resolved to Dr.Quinn.md with the right field, line and embed values, and there was no problem. The reader lists body links before front matter links, and my expected array put the `relationships` link first. I stopped and reported it (gosalyn-0098). Run 2, after the test-only fix sage-1907 approved, which moves that entry to the end of the expected array, 09:43:42Z to 09:43:56Z. Every rc 0. | File | pass | fail | |---|---|---| | packages/library/tests/links.test.mjs | 7 | 0 | | packages/library/tests/mapping.test.mjs | 7 | 0 | | packages/library/tests/reader.test.mjs | 14 | 0 | | packages/library/tests/render.test.mjs | 11 | 0 | | packages/library/tests/survey.test.mjs | 6 | 0 | | packages/cli/tests/stack-copy.test.mjs | 16 | 0 | Total: 61 pass, 0 fail, 0 cancelled, summed by awk.