Answer the prose and product-owner reviews' first round
CI / gate (push) Successful in 43s
CI / publish (push) Has been skipped

This commit is contained in:
2026-10-02 22:36:37 +02:00
parent d9bacc4072
commit dff4983d4a
4 changed files with 26 additions and 27 deletions
+2 -2
View File
@@ -130,8 +130,8 @@ One-line commit messages and PR titles; short PR summaries. No AI-attribution ma
## 7. The working loop ## 7. The working loop
A session works one chunk, starting from the first item under the earliest release in `todo.md`, A session works one chunk, starting from the first item in `todo.md` whose prerequisites have
and stops when that chunk merges, whatever it was asked to finish: a release is a chain of landed, and stops when that chunk merges, whatever it was asked to finish: a release is a chain of
sessions, so an instruction to work until a release is done names the chain, not the session. An sessions, so an instruction to work until a release is done names the chain, not the session. An
open PR is a chunk already in flight, and finishing it is the session. open PR is a chunk already in flight, and finishing it is the session.
Per chunk: Per chunk:
+2 -1
View File
@@ -5,7 +5,8 @@ an HTML dialect.
**Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at **Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at
`0.2.0`.** `0.2.0`.**
Plan: `todo.md`. Decisions: Plan:
[`todo.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/todo.md). Decisions:
[`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md). Changes: [`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md). Changes:
[`CHANGELOG.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/CHANGELOG.md). The lossless flavour's grammar: [`CHANGELOG.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/CHANGELOG.md). The lossless flavour's grammar:
[`spec/flavour.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/spec/flavour.md). [`spec/flavour.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/spec/flavour.md).
+1 -1
View File
@@ -39,7 +39,7 @@ merges.
"Equals" is structural equality over editor-normal ADF — adjacent text nodes with identical marks "Equals" is structural equality over editor-normal ADF — adjacent text nodes with identical marks
and no attributes merged, JSON number semantics, an empty attrs object, marks array or content and no attributes merged, JSON number semantics, an empty attrs object, marks array or content
array the absent key — the only domain markdown can restore. array the absent key — the only domain markdown can restore.
Replaced by deep equality with `todo.md` item 40 (2026-09-28, the maintainer). `todo.md` item 40 replaces this with deep equality (2026-09-28, the maintainer).
## Unknown nodes ride the carry ## Unknown nodes ride the carry
+21 -23
View File
@@ -24,7 +24,7 @@
| ID | Release | Exempt | Item | R | S | A | G | Goals | Score | | ID | Release | Exempt | Item | R | S | A | G | Goals | Score |
|---|---|---|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|---|---|---|
| 40 | 0.2.0 | decision | **Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document it takes.** | 6 | 7 | 8 | 9 | 1 | 26.2 | | 40 | 0.2.0 | decision | **Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document `adfToMarkdown` takes.** | 6 | 7 | 8 | 9 | 1 | 26.2 |
| 7 | 0.2.0 | | **Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF.** | 6 | 9 | 9 | 9 | 2, 3 | 25.8 | | 7 | 0.2.0 | | **Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF.** | 6 | 9 | 9 | 9 | 2, 3 | 25.8 |
| 45 | 0.2.0 | | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`.** | 2 | 3 | 6 | 8 | 1 | 25.2 | | 45 | 0.2.0 | | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`.** | 2 | 3 | 6 | 8 | 1 | 25.2 |
| 6 | 0.2.0 | decision | **Specify the HTML dialect.** | 2 | 6 | 7 | 8 | 2, 3 | 24.7 | | 6 | 0.2.0 | decision | **Specify the HTML dialect.** | 2 | 6 | 7 | 8 | 2, 3 | 24.7 |
@@ -34,25 +34,25 @@
| 34 | 0.3.0 | | **Read emphasis flanking by the whole character beside an astral symbol.** | 2 | 3 | 3 | 6 | 3, 4 | 12.6 | | 34 | 0.3.0 | | **Read emphasis flanking by the whole character beside an astral symbol.** | 2 | 3 | 3 | 6 | 3, 4 | 12.6 |
| 42 | 0.3.0 | | **Trim a text leaf's trailing blanks in linear time.** | 1 | 2 | 5 | 9 | 8 | 12.5 | | 42 | 0.3.0 | | **Trim a text leaf's trailing blanks in linear time.** | 1 | 2 | 5 | 9 | 8 | 12.5 |
| 48 | 0.3.0 | question | **Keep the release path publishing past npm's bypass-2FA token retirement.** | 4 | 4 | 8 | 3 | 9 | 11.7 | | 48 | 0.3.0 | question | **Keep the release path publishing past npm's bypass-2FA token retirement.** | 4 | 4 | 8 | 3 | 9 | 11.7 |
| 31 | 0.3.0 | | **Make the branch figure the coverage floor is read against repeatable.** | 2 | 3 | 3 | 4 | 1 | 11.2 | | 31 | 0.3.0 | | **Make the branch-coverage figure repeat across runs of an unchanged tree.** | 2 | 3 | 3 | 4 | 1 | 11.2 |
| 33 | 0.3.0 | | **Make a carried mark run cost the line one re-emit.** | 4 | 5 | 6 | 9 | 8 | 10.7 | | 33 | 0.3.0 | | **Emit a line in time linear in its mark runs, in `adfToMarkdown` and the plain reduction.** | 4 | 5 | 6 | 9 | 8 | 10.7 |
| 46 | 0.3.0 | | **Publish the bundle size in the README, failing the release pipeline when it drifts.** | 2 | 4 | 5 | 5 | 7, 9 | 10.3 | | 46 | 0.3.0 | | **Publish the bundle size in the README, failing the release pipeline when it drifts.** | 2 | 4 | 5 | 5 | 7, 9 | 10.3 |
| 9 | 0.3.0 | | **Ship an online sandbox: a web page with two textboxes converting between ADF and markdown on the library's browser build.** | 2 | 6 | 6 | 8 | 9 | 10.3 | | 9 | 0.3.0 | | **Ship an online sandbox: a web page with two textboxes converting between ADF and markdown on the library's browser build.** | 2 | 6 | 6 | 8 | 9 | 10.3 |
| 8 | 0.4.0 | question | **Ship a CLI.** | 4 | 7 | 5 | 5 | 9 | 5.3 | | 8 | 0.4.0 | question | **Ship a CLI.** | 4 | 7 | 5 | 5 | 9 | 5.3 |
## Details ## Details
### 40. Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document it takes. ### 40. Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document `adfToMarkdown` takes.
Today it holds for editor-normal documents only: two adjacent text nodes with the same marks merge, Today it holds for editor-normal documents only: two adjacent text nodes with the same marks merge,
an empty `attrs`, `marks` or `content` drops, and `-0` reads back `0` — shapes pipelines and bots an empty `attrs`, `marks` or `content` drops, and `-0` reads back `0` — shapes pipelines and bots
build. Spell each so it reads back as written, CommonMark's spelling kept wherever none occurs; the build. Spell each so it reads back as written; CommonMark's spelling stays wherever the document
spellings are part of the chunk. `docs/decisions.md` §Equality is editor-normal, `spec/flavour.md` holds none of these shapes. The spellings are part of the chunk. `docs/decisions.md` §Equality is editor-normal, `spec/flavour.md`
and `corpus/README.md` follow, and the tests drop `toEditorNormal`. and `corpus/README.md` follow, and the tests drop `toEditorNormal`.
### 7. Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF. ### 7. Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF.
Builds on item 6. The CommonMark spec suite runs against `markdownToHtml` from here. The README Builds on item 6. Once it lands, the CommonMark spec suite runs against `markdownToHtml`. The README
documents HTML as it documents markdown, and its tagline and `package.json`'s `description` regain documents HTML as it documents markdown, and its tagline and `package.json`'s `description` regain
HTML. HTML.
@@ -83,14 +83,11 @@ already escape it.
### 47. Open the README with what the package is, what it does and for whom. ### 47. Open the README with what the package is, what it does and for whom.
It opens with the pre-launch rationale — Atlassian's REST APIs, `pf-editor-service/convert` being It opens with the pre-launch rationale — Atlassian's REST APIs, `pf-editor-service/convert` being
decommissioned, a link to JRACLOUD-77436 — where a shipped package should answer what it is, what it decommissioned, a link to JRACLOUD-77436. The background goes entirely, no endpoint, ticket or
does and for whom first, then the shortest runnable example. The background goes entirely, no "why" note left. The badges are npm's version and the Gitea Actions status. The README names the
endpoint, ticket or "why" note left. The top follows the package-README order: an npm version badge lossy pair, `adfToPlainMarkdown` and `plainMarkdownToAdf`, and the flavours it writes and reads —
and the Gitea Actions badge, a tagline that is also `package.json`'s `description`, a feature list GitHub Flavored Markdown's alerts and task lists, Obsidian Flavored Markdown's callouts — so a
and a one-line table of contents, then install and the shortest runnable example; a table of search for either finds the package.
everything exported sits near the bottom. The README names the lossy pair and the flavours it
writes and reads — GitHub Flavored Markdown's alerts and task lists, Obsidian Flavored Markdown's
callouts — so a search for either finds the package.
### 34. Read emphasis flanking by the whole character beside an astral symbol. ### 34. Read emphasis flanking by the whole character beside an astral symbol.
@@ -111,13 +108,13 @@ writes was not enough, and npm answered `EOTP` until the token itself bypassed.
bypass-2FA tokens for direct publishing around January 2027, leaving them `npm stage publish`, which bypass-2FA tokens for direct publishing around January 2027, leaving them `npm stage publish`, which
a maintainer approves with 2FA; its replacement — trusted publishing over OIDC — supports a maintainer approves with 2FA; its replacement — trusted publishing over OIDC — supports
GitHub-hosted Actions, GitLab.com's shared runners and CircleCI's cloud, self-hosted runners planned GitHub-hosted Actions, GitLab.com's shared runners and CircleCI's cloud, self-hosted runners planned
without a date. So the release path has an expiry date and no drop-in successor yet. Revisit: without a date. Revisit:
whether npm has added Gitea or self-hosted OIDC, and otherwise whether the release moves to the whether npm has added Gitea or self-hosted OIDC, and otherwise whether the release moves to the
staged publish — which fits badly with publish-on-merge, and is the maintainer's trade to weigh staged publish — which fits badly with publish-on-merge, and is the maintainer's trade to weigh.
rather than discover on a red release run. It stays out of `0.2.0` knowing the cutoff may land The Goals and G cells are provisional: no README goal covers the release path. It stays out of `0.2.0` knowing the cutoff may land
first. first.
### 31. Make the branch figure the coverage floor is read against repeatable. ### 31. Make the branch-coverage figure repeat across runs of an unchanged tree.
Three Node test legs over one unchanged tree reported `emit/inline-line.ts` at 95.83%, 96.23% and Three Node test legs over one unchanged tree reported `emit/inline-line.ts` at 95.83%, 96.23% and
96.23%, and the total at 98.80%, 98.84% and 98.84% (2026-09-21). `--experimental-test-coverage` 96.23%, and the total at 98.80%, 98.84% and 98.84% (2026-09-21). `--experimental-test-coverage`
@@ -128,7 +125,7 @@ moves upward, so the first raise to the measured figure reddens a run that chang
measurement repeatable, or state the number the floor may be raised to and why it is not the measurement repeatable, or state the number the floor may be raised to and why it is not the
measured one. measured one.
### 33. Make a carried mark run cost the line one re-emit. ### 33. Emit a line in time linear in its mark runs, in `adfToMarkdown` and the plain reduction.
`adfToMarkdown` spends 23 s on one paragraph of 2000 × `un` plus `**-r**`: each run its flanking `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, and the plain cannot spell re-emits the whole line before riding the carry, quadratic in the runs, and the plain
@@ -138,7 +135,7 @@ reduction's `spellableLine` drops one mark per re-emit the same way. Make both l
Lands after item 7, which changes it. The quantity is what a consumer downloads and loads: the Lands after item 7, which changes it. The quantity is what a consumer downloads and loads: the
tarball `npm pack` produces, its unpacked `dist`, and the built JavaScript minified + gzipped — the tarball `npm pack` produces, its unpacked `dist`, and the built JavaScript minified + gzipped — the
figure the competitors advertise (marklassian's "12kb") and the only apple-to-apple one, since ours figure the competitors advertise (marklassian's "12kb") and the only apples-to-apples one, since ours
ships tsc's unminified output and no minifier yet (decide here whether to minify for the build or ships tsc's unminified output and no minifier yet (decide here whether to minify for the build or
report the unminified gzip). The figure lands in README §The package beside the "no runtime report the unminified gzip). The figure lands in README §The package beside the "no runtime
dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5 kB, JS gzipped dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5 kB, JS gzipped
@@ -146,5 +143,6 @@ dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5
### 8. Ship a CLI. ### 8. Ship a CLI.
No goal or persona in the README covers it yet; the maintainer names both before it is built, and The Goals and G cells are provisional: no goal or persona in the README covers a CLI yet. The
they land in the README's `## Goals` and `## Audience` with it. maintainer names both before it is built, and they land in the README's `## Goals` and `## Audience`
with it.