Cut 0.1.0 to the corpus round-trip, and date the proof work after it
CI / gate (push) Successful in 5s
CI / gate (push) Successful in 5s
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
# Todo
|
||||
|
||||
The plan, in order. Nothing is built. Design questions are settled in `AGENTS.md`; remaining spec
|
||||
detail is settled at its own milestone.
|
||||
The plan. Design questions are settled in `AGENTS.md`; remaining spec detail is settled at its own
|
||||
milestone.
|
||||
|
||||
## Milestones
|
||||
|
||||
Shipping order: 3h, 3i, 3j, 5 → `0.1.0`; 4b → `0.1.1`; 4, 3k → `0.2.0`; 6, 7 → `0.3.0`. The
|
||||
numbering is the order the work was planned in, not the order it ships.
|
||||
|
||||
- [x] **0 — Scaffold.** `package.json` per §6, `tsconfig.json`, `.npmrc` (`save-exact=true`), the
|
||||
Docker tooling, `renovate.json` (§9), and `.gitea/workflows/ci.yml` gating branches:
|
||||
`runs-on: docker-host`, actions pinned to semver tags.
|
||||
@@ -155,8 +158,8 @@ detail is settled at its own milestone.
|
||||
2f raises what 1d's unspelled block separation costs: a single `localId` on a paragraph
|
||||
beside a plain one now refuses every container body that is a directive's — a panel, an
|
||||
expand, a table cell — where before 2f the attribute refused the document anyway.
|
||||
- [ ] **3 — `markdownToAdf`.** Each sub-item lands the fixtures its own code reads, and the runner
|
||||
grows a parse half as they do: `parsingDirectories` beside `emittingDirectories`, a
|
||||
- [ ] **3 — `markdownToAdf` (`0.1.0`).** Each sub-item lands the fixtures its own code reads, and
|
||||
the runner grows a parse half as they do: `parsingDirectories` beside `emittingDirectories`, a
|
||||
round-trip directory joining it only once every fixture in it reads back to its document,
|
||||
and readers for `corpus/normalization/` (setext, indented code, loose lists, `*`/`+`
|
||||
bullets, entity references, soft wraps — one-way, the markdown not canonical) and
|
||||
@@ -359,9 +362,12 @@ detail is settled at its own milestone.
|
||||
named error, a carry inside a mark spelling another, and the three carve-outs' escapes
|
||||
reading as the literal text they hold. 3g refuses the `adf` fence rather than reading a
|
||||
`codeBlock` from it; the refusal goes when the carry reads it.
|
||||
- [ ] **3k — The CommonMark spec suite.** Checked in at `corpus/commonmark-spec/`, pinned to
|
||||
the version it ships — the one `html-blocks.ts` names for its start conditions —
|
||||
`corpus/README.md` gaining the kind.
|
||||
`index.ts` gains `markdownToAdf` here, and the README's status line with it: this is the
|
||||
last parser chunk, so `parsingDirectories` becomes `emittingDirectories` and the whole
|
||||
corpus round-trips both ways — `0.1.0`'s proof, which 4 widens rather than replaces.
|
||||
- [ ] **3k — The CommonMark spec suite (`0.2.0`).** Checked in at `corpus/commonmark-spec/`,
|
||||
pinned to the version it ships — the one `html-blocks.ts` names for its start
|
||||
conditions — `corpus/README.md` gaining the kind.
|
||||
**Settled** (the maintainer, 2026-08-27): three checks an example must pass, the reference
|
||||
HTML each ships read as corpus data — which adds no format and no direction (§1). §2's
|
||||
canonical fixpoint: a named error, or markdown that parses and emits to itself byte for
|
||||
@@ -374,16 +380,12 @@ detail is settled at its own milestone.
|
||||
counts close both. The exception list stays the maintainer's. One outcome is no
|
||||
exception and must not be filed as one: valid CommonMark parsing to a document
|
||||
`adfToMarkdown` refuses is a §2 hole, which is what three of `corpus/unspellable/`'s four
|
||||
hold until 3c, 3e and 3h land their answers. The parser's `ConvertErrorCode` additions
|
||||
are read here as one list before §8's freeze — nine sessions mint them independently, and
|
||||
one cause wearing two codes is breaking to undo after `0.1.0`. `index.ts` gains
|
||||
`markdownToAdf` here with the README's status line, neither waiting on the exception list:
|
||||
a parser still missing syntax is a claim the entrypoint cannot keep, and the corpus reads
|
||||
it from its module meanwhile.
|
||||
- [ ] **4 — Round-trip property tests** over the corpus, both ways — the thing that proves 2 and
|
||||
3. Editor-normal (§2) is finished here, on 3i's merging — `toEditorNormal(doc)` and the
|
||||
equality the round-trip asserts, which over normalized input is the canonical serializer's
|
||||
compact spelling — rather than staying spelled inline as `?? []` at every reader. The
|
||||
hold until 3c, 3e and 3h land their answers.
|
||||
- [ ] **4 — Round-trip property tests (`0.2.0`)**, widening 3j's corpus round-trip past the
|
||||
documents a human wrote — the thing that proves 2 and 3 beyond them. Editor-normal (§2) is
|
||||
finished here, on 3i's merging — `toEditorNormal(doc)` and the equality the round-trip
|
||||
asserts, which over normalized input is the canonical serializer's compact spelling —
|
||||
rather than staying spelled inline as `?? []` at every reader. The
|
||||
reading half is `nodeContent`/`nodeAttrs`/`nodeMarks` over the ~28 sites spelling it
|
||||
inline today, which also lifts the branch floor §10 keeps below 100 for exactly those
|
||||
halves.
|
||||
@@ -393,7 +395,7 @@ detail is settled at its own milestone.
|
||||
a document that round-trips proves no other document shares its spelling — so decide here
|
||||
whether that gate stays as the parser-free, faster-failing signal or goes; the half holding
|
||||
no fixture duplicates is hygiene rather than a round-trip claim, and stays either way.
|
||||
- [ ] **4b — The block walk's retry, before 5.** `emitBlock` walks a subtree twice wherever
|
||||
- [ ] **4b — The block walk's retry (`0.1.1`).** `emitBlock` walks a subtree twice wherever
|
||||
`readableBlock` reads it whole and then gives up — a list item whose first line reads back
|
||||
as a thematic break — and the walk below does the same, so the cost doubles per level:
|
||||
3.4kB of nested lists takes half a second, depth 20 about eight, depth 24 minutes. It
|
||||
@@ -403,19 +405,30 @@ detail is settled at its own milestone.
|
||||
is what to remove — one walk answering both the readable question and the directive
|
||||
fallback. Memoizing `emitBlock` is the shortcut, and the node reference is the wrong key: a
|
||||
caller may hold one node object at two positions, where the cached depth and path are
|
||||
another node's.
|
||||
another node's. `0.1.0` ships with the retry in it, so a deep document is slow rather than
|
||||
wrong until the patch.
|
||||
- [ ] **5 — Release pipeline, ship `0.1.0`.** Publish-on-version-change (§9), `NPM_TOKEN` secret,
|
||||
the repo made public first (§6). The `ConvertErrorCode` freeze (§8) is checkable here: every
|
||||
`corpus/unspellable/` document is a decision or a deferred trigger this file names, so the
|
||||
directory empties as they land and whatever survives is permanent. `0.1.0` is the markdown round-trip: both markdown
|
||||
directions, the types, `isAdfDocument`. The build lands here: a build tsconfig emitting JS
|
||||
and `.d.ts` to `dist/` (the dev config's `allowImportingTsExtensions` forces `noEmit`, so
|
||||
the build config needs `rewriteRelativeImportExtensions`), plus `exports`/`files` in
|
||||
`package.json`. The maintainer's bump PR also removes `private: true`, the guard against any
|
||||
earlier publish.
|
||||
- [ ] **6 — The HTML dialect spec.** Element-by-element mapping, the `data-*` fidelity scheme, the
|
||||
opaque-carry form, and the documented foreign-element set `htmlToAdf` accepts.
|
||||
- [ ] **7 — HTML, ship `0.2.0`.** `adfToHtml`, `htmlToAdf`, the composed `markdownToHtml` /
|
||||
directory empties as they land and whatever survives is permanent. The parser's own code
|
||||
additions are read here as one list before that freeze — nine sessions mint them
|
||||
independently, and one cause wearing two codes is breaking to undo after `0.1.0`. `0.1.0`
|
||||
is the markdown round-trip: both markdown directions, the types, `isAdfDocument`. The build
|
||||
lands here: a build tsconfig emitting JS and `.d.ts` to `dist/` (the dev config's
|
||||
`allowImportingTsExtensions` forces `noEmit`, so the build config needs
|
||||
`rewriteRelativeImportExtensions`), plus `exports`/`files` in `package.json`. The
|
||||
maintainer's bump PR also removes `private: true`, the guard against any earlier publish.
|
||||
**Settled** (the maintainer, 2026-09-01): the round-trip proved over the checked-in corpus
|
||||
is what `0.1.0` ships on, and the open-ended proof work follows it rather than gating it —
|
||||
3k's spec suite and 4's generators and maintainer-supplied payloads are `0.2.0`, 4b's retry
|
||||
`0.1.1`. A consumer using the library is worth more than a wider proof nobody has needed
|
||||
yet, and §8's pre-1.0 rules cover what the wider proof then finds. 3k's exception list
|
||||
landing after the release leaves the README's canonical-fixpoint sentence claiming more than
|
||||
`0.1.0` keeps — 3e names three shapes that parse and then refuse — so the release narrows
|
||||
that sentence or lists them.
|
||||
- [ ] **6 — The HTML dialect spec (`0.3.0`).** Element-by-element mapping, the `data-*` fidelity
|
||||
scheme, the opaque-carry form, and the documented foreign-element set `htmlToAdf` accepts.
|
||||
- [ ] **7 — HTML, ship `0.3.0`.** `adfToHtml`, `htmlToAdf`, the composed `markdownToHtml` /
|
||||
`htmlToMarkdown`. CommonMark spec suite runs against `markdownToHtml` from here (§10).
|
||||
- [ ] **8 — CLI.** A later goal, shaped around the personas once the library exists.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user