From 0644d1bc5df5bc5ae67507c468085f5853b3180e Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Fri, 25 Sep 2026 08:14:57 +0200 Subject: [PATCH 1/3] 10 - lossy conversion keeps the content, and a reader panel settles what the audience expects --- AGENTS.md | 7 +++++++ README.md | 12 ++++++++---- todo.md | 23 +++++++++++++++-------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e762ced..c505a91 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -429,6 +429,13 @@ and the instance it yields, and ask for the rule. The maintainer answers the rul here, and the instance follows from it in the chunk. A rule that keeps collecting instances is wrong: rewrite it rather than append to it. +Which output the audience expects — README goal 5 — is settled by a reader panel rather than +asked: three fresh-context readers, one per README persona the conversion serves, each given only +`## Audience` and the input, writing what they expect before picking among outputs the goals +allow, rendered, shuffled, with no rationale and nothing saying what is implemented. Three agreeing +settle it; otherwise four more read, five of seven settle it, and less is a missing goal, asked. +The verdict lands in the item it settles (the maintainer, 2026-09-25). + ### Rules the loop has settled (the maintainer, 2026-09-18) - A finding inside the chunk's item is fixed in the chunk. Outside it, a new `todo.md` item, always diff --git a/README.md b/README.md index 17737ee..d654dc7 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ represent. In priority order. -1. **Lossless first.** The round-trip holds for every document, node types this version does not - know included; one that has no spelling is refused and says where, never silently reduced. +1. **Lossless first.** The round-trip holds for every document the lossless pair converts, node + types this version does not know included; one that has no spelling is refused and says where, never silently reduced. Every goal below gives way to this one. 2. **Three formats, ADF the hub.** ADF, one markdown flavour, one HTML dialect, markdown↔HTML composing through ADF — four conversions to keep correct, never a fifth, and never a fourth @@ -34,9 +34,13 @@ In priority order. escapable, so the flavour is opt-in. 4. **Output a person can edit.** A node CommonMark can spell gets that spelling; the directive form carries only what CommonMark cannot hold. -5. **Failures are values.** Nothing throws, and `code` is a closed list — as much a contract as +5. **Lossy conversion keeps the content.** `adfToPlainMarkdown` and `plainMarkdownToAdf` drop what + plain markdown cannot hold — format, design, structure — never content: what a reader of the + rendered document sees or follows, its text, images and link targets. What is dropped goes the + way the audience expects. +6. **Failures are values.** Nothing throws, and `code` is a closed list — as much a contract as the emitted formats are. -6. **Nothing in the way.** No runtime dependencies, no I/O, no configuration, no host API: ESM on +7. **Nothing in the way.** No runtime dependencies, no I/O, no configuration, no host API: ESM on any ES2022 engine, in a browser as readily as on a server. ## Audience diff --git a/todo.md b/todo.md index 388410d..244987c 100644 --- a/todo.md +++ b/todo.md @@ -213,16 +213,23 @@ chunk clearing a §11 seam. spelling, attributes dropped. - `mention` and `status` become their text, the mention's `@` kept; `emoji` its text or else its `shortName`; `date` its ISO date in UTC (`2026-09-13`); `inlineCard`, `blockCard` and - `embedCard` a link to their `url`, dropped when they carry only `data`; a `mediaSingle` - holding an external image stays `![alt](url)`; `media`, `mediaGroup` and `mediaInline` their - `alt` text or nothing; `caption` its text as a paragraph; `extension`, `inlineExtension` and - `syncBlock` their `text` attribute or nothing; `placeholder` nothing; a node no row names, or - one standing where no spelling holds it, its blocks or its text. + `embedCard` a link to their `url`, or to their `data`'s `url` named by its `name` — the name + alone without a `url`; an external image, wherever it stands, `![alt](url)`; `media`, + `mediaGroup` and `mediaInline` holding a stored file their `alt` text; `caption` its text as + a paragraph; `extension` and `inlineExtension` their `text` attribute; `placeholder` nothing, + its text being the editor's prompt rather than the document's; a node no row names, or one + standing where no spelling holds it, its blocks or its text. + - Content the document only references — a stored file with no `alt`, an extension with no + `text`, a `syncBlock`, a card with neither `url` nor `data` naming one — leaves MARKER. - A table stays a pipe table: the first row becomes the header, a cell's blocks join on one line - with spaces, and spans and the cells they cover drop. + with spaces, and a span keeps its cell under its header by empty cells in the columns and + rows it covered, padding at most to the table's cell count. + - A list stays a list: where CommonMark cannot hold a block inside an item, what gives way is + what a reader does not see — the spaces of a whitespace-only code line, a rule's spelling. - `code`, `em`, `link`, `strike` and `strong` stay and every other mark drops, keeping its text — - `subsup` too, since `~2~` is a strike on GitHub; a link no CommonMark escape writes becomes its - text, and a mark run CommonMark's flanking or matching cannot spell drops its mark. + `subsup` too, since `~2~` is a strike on GitHub; a link no CommonMark escape writes has its + `href` percent-encoded until one does, and a mark run CommonMark's flanking or matching cannot + spell drops its mark. - A newline in text becomes a hard break and edge whitespace is trimmed; carriage returns and null characters are removed; a paragraph line opening with a code span whose backticks would read as a fence loses the code mark; an empty paragraph drops, and adjacent lists of one type -- 2.52.0 From 3fce43e884bc018620fef9ce2cbc962672c2b5d4 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Fri, 25 Sep 2026 18:49:19 +0200 Subject: [PATCH 2/3] 10 - referenced content leaves a note naming it --- README.md | 5 +++-- todo.md | 13 ++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d654dc7..4e79824 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,9 @@ In priority order. form carries only what CommonMark cannot hold. 5. **Lossy conversion keeps the content.** `adfToPlainMarkdown` and `plainMarkdownToAdf` drop what plain markdown cannot hold — format, design, structure — never content: what a reader of the - rendered document sees or follows, its text, images and link targets. What is dropped goes the - way the audience expects. + rendered document sees or follows, its text, images and link targets. Content the document only + references is marked where it stood, by a note that reads as the converter's and names what was + left out. What is dropped goes the way the audience expects. 6. **Failures are values.** Nothing throws, and `code` is a closed list — as much a contract as the emitted formats are. 7. **Nothing in the way.** No runtime dependencies, no I/O, no configuration, no host API: ESM on diff --git a/todo.md b/todo.md index 244987c..184481d 100644 --- a/todo.md +++ b/todo.md @@ -15,14 +15,15 @@ Start a session with: `Read AGENTS.md and todo.md, then do what todo.md's "Next states, which wins over where an item's bullet sits: a newly filed item is written beside the one it came in with, not at its own place in the order. Where that item has no release, the planning chunk §15 describes. -3. In flight: nothing. +3. In flight: 10a on the local branch `10a` (worktree `../adf-codec-10a`, `8a3a83f`), built before + item 10's rows were rewritten on 2026-09-25; rework it against them. 4. Before stopping, rewrite this section: the in-flight line, and the prompt itself wherever the session found it wrong or short. ## Milestones Shipping order: 3h, 3i, 3j, 5a, 5b, 5c, 5d, 5 → `0.1.0` (shipped 2026-09-05); 3k, 11, 4, 12, 13, 4b, -4c, 14, 15, 16, 18, 4d, 28, 17, 29, 19, 20, 21, 22, 32, 23, 24, 25, 30, 26, 27, 10, 6, 7, 31, 5f, 5g → +4c, 14, 15, 16, 18, 4d, 28, 17, 29, 19, 20, 21, 22, 32, 23, 24, 25, 30, 26, 27, 10, 6, 7, 31, 33, 5f, 5g → `0.2.0`; 8, 9 → TBD; 5e last. The numbering is the order the work was planned in, not the order it ships. Everything known and @@ -43,6 +44,8 @@ HTML doubles the importers and the file count they touch, and 25 to 27 because t panel says the next reader pays for. 29 and 30 come from 17's prose pass (2026-09-20). 29 reads first because every goal is what a later ask is settled against, 19's included; 30 sits beside 25, the other chunk rereading AGENTS.md. +33 comes from 10a (2026-09-25) and reads beside 31, the other chunk about what the pipeline +measures. 31 comes from 20's gate runs (2026-09-21) and reads beside 5f, the other chunk putting a measured number under the pipeline. 32 comes from 21's review (2026-09-21) and reads beside 22, the other chunk clearing a §11 seam. @@ -56,6 +59,9 @@ chunk clearing a §11 seam. upward, so the first raise to the measured figure reddens a run that changed nothing. Make the measurement repeatable, or state the number the floor may be raised to and why it is not the measured one. +- [ ] **33 — A carried mark run costs the line one re-emit (`0.2.0`).** `adfToMarkdown` spends 23 s + on one paragraph of 2000 × `un` plus `**-r**`: each run its flanking cannot spell re-emits the + whole line before riding the carry, quadratic in the runs (§11 Bounds). Make it linear. - [x] **24 — The conformance gates have a directory (`0.2.0`).** - [x] **25 — AGENTS.md §8 and §11 are findable (`0.2.0`).** - [x] **26 — The two mutable structures say what they guarantee (`0.2.0`).** @@ -220,7 +226,8 @@ chunk clearing a §11 seam. its text being the editor's prompt rather than the document's; a node no row names, or one standing where no spelling holds it, its blocks or its text. - Content the document only references — a stored file with no `alt`, an extension with no - `text`, a `syncBlock`, a card with neither `url` nor `data` naming one — leaves MARKER. + `text`, a `syncBlock`, a card with neither `url` nor `data` naming one — leaves an italic note + naming it: `*(image not included)*`, `*(jira-issues-table not included)*`. - A table stays a pipe table: the first row becomes the header, a cell's blocks join on one line with spaces, and a span keeps its cell under its header by empty cells in the columns and rows it covered, padding at most to the table's cell count. -- 2.52.0 From cb30512a90315f0af6ad036879e906ff966d506c Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Fri, 25 Sep 2026 18:49:38 +0200 Subject: [PATCH 3/3] 10 - goal 1 wraps --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e79824..5249f2c 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ represent. In priority order. -1. **Lossless first.** The round-trip holds for every document the lossless pair converts, node - types this version does not know included; one that has no spelling is refused and says where, never silently reduced. +1. **Lossless first.** The round-trip holds for every document the lossless conversions take, node + types this version does not know included; one that has no spelling is refused and says where, + never silently reduced. Every goal below gives way to this one. 2. **Three formats, ADF the hub.** ADF, one markdown flavour, one HTML dialect, markdown↔HTML composing through ADF — four conversions to keep correct, never a fifth, and never a fourth -- 2.52.0