3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-12 11:48:29 +01:00

Answer prose round 1: 0 🔴, 5 🟡; state the directive boundary, split the spelling-questions sentence and tighten the plan items

This commit is contained in:
2026-10-22 00:06:35 +02:00
committed by Lillem4n
parent d36c99cd55
commit 48e5f045d1
3 changed files with 26 additions and 25 deletions
+6 -6
View File
@@ -924,15 +924,15 @@ them. A primitive knowing neither ADF nor a format stays at `src/` root. A const
what both read where there are two.
A flavour's own code, both directions included, sits in its own directory: `markdown/portable/`;
`todo.md` item 62 moves what still sits in `parse/` and `emit/`. The directive grammar likewise
sits in `markdown/directive/`. Otherwise each format directory parts into `emit/` (ADF→format) and
`todo.md` item 62 moves what still sits in `parse/` and `emit/`. The directive grammar, both
directions included, sits in `markdown/directive/`, which imports neither `emit/` nor `parse/`.
Otherwise each format directory parts into `emit/` (ADF→format) and
`parse/` (format→ADF), the rest of it holding what both directions read. A construct's reader lives
there beside the regex the emitter escapes against, so the two cannot drift; a reader with no emit
counterpart goes in `parse/`, unless it is part of a construct that side already holds — a grammar
stays in one file rather than splitting across the seam. A rule both directions must answer alike —
whether a list marker interrupts a paragraph — is one function there too, never a copy per
direction, however conservative the copy would be. Where the rule is the emitter's own choice, input
consults it rather than restating it, and that is the only import `parse/` takes from `emit/`,
through `emit/spelling-questions.ts`, which names `commonMarkSpelling`, `openingLinkTakesDirective`
and the `SpellingMemo` type — so no fixture the emitter writes can be refused, and a spelling the
emitter refuses gives its own error rather than a second name for it.
consults it rather than restating it, so no fixture the emitter writes can be refused, and a
spelling the emitter refuses gives its own error rather than a second name for it. That consulting
is the only import `parse/` takes from `emit/`, through `emit/spelling-questions.ts`.
+1 -1
View File
@@ -25,7 +25,7 @@ export type ParseError = ConvertError & { position: SourcePosition }
export type Result<T, E extends ConvertError = ConvertError> = { error: E; ok: false } | { ok: true; value: T }
// A reader with no path to name; the walk attaches the path where it knows it.
// A fault without a path, for a reader that cannot know it; its caller adds the path.
export type Read<T> = { fault: ConvertFault; value?: undefined } | { fault?: undefined; value: T }
export function failure<T>(code: ConvertErrorCode, message: string, path: ConvertErrorPath): Result<T> {
+19 -18
View File
@@ -28,7 +28,7 @@
| 75 | 0.4.0 | | | **Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.** | 1 | 1 | 1 | 1 | 2 | code health by 2 | 17.4 |
| 45 | 0.4.0 | | defect | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`.** | 2 | 1 | 3 | 4 | 3 | 1 by 2 | 13.1 |
| 68 | 0.4.0 | | defect | **Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.** | 2 | 1 | 2 | 3 | 3 | 1 by 2 | 13.1 |
| 127 | 0.4.0 | | principle | **Hold what `result.test.ts`, `json-text.test.ts` and `entity-references.test.ts` check by asserting outcomes, so none reads source text.** | 2 | 2 | 1 | 3 | 3 | code health by 2 | 13.1 |
| 127 | 0.4.0 | | principle | **Hold what `entity-references.test.ts`, `json-text.test.ts` and `result.test.ts` check by asserting outcomes, so none reads source text.** | 2 | 2 | 1 | 3 | 3 | code health by 2 | 13.1 |
| 112 | 0.4.0 | | | **Pad a GFM pipe table's short rows with empty cells, read its body rows holding no pipe, and read a one-column table without leading pipes in `portableMarkdownToAdf`.** | 2 | 1 | 2 | 3 | 3 | 4 by 4 | 6.2 |
| 80 | 0.4.0 | | | **Name the node's path and the attribute key when `not-an-adf-document` refuses a node inside the document.** | 2 | 1 | 2 | 3 | 3 | 6 by 4 | 6.0 |
| 81 | 0.4.0 | | | **Fail the gate unless the README's error tables list exactly the codes `ConvertErrorCode` holds.** | 1 | 1 | 1 | 1 | 2 | 3 by 2 | 4.2 |
@@ -63,13 +63,14 @@
Two boundaries in `docs/decisions.md` §The source parts by ADF and format hold by convention only:
`src/markdown/parse/` imports from `src/markdown/emit/` only `emit/spelling-questions.ts`, and
`src/markdown/directive/` imports neither `emit/` nor `parse/`. A test scanning the source is
refused, since `~/.claude/principles/technical-principles.md` says a test never scans source.
oxlint 1.89.0 can hold both with `overrides` carrying `no-restricted-imports`. Verified: a
`from '…'`, a bare `import '…'`, a double-quoted and a dynamic `import()` each fail the
`size-ratchet` leg, and the exception `!../emit/spelling-questions.ts` passes.
`src/markdown/directive/` imports neither `emit/` nor `parse/`. The technical principles refuse a
test that scans the source: principle "Assert the outcome" bans it. oxlint 1.89.0 can hold both
boundaries with `overrides` carrying `no-restricted-imports`. Verified: a forbidden import fails
the `size-ratchet` leg in each form, as `from '…'`, as a bare `import '…'`, with a double-quoted
specifier and as a dynamic `import()`. An import of `../emit/spelling-questions.ts`, listed as the
exception, passes.
But §The size ratchet, the maintainer's, gives `.oxlintrc.json` a single rule and says no second
But the maintainer's §The size ratchet gives `.oxlintrc.json` a single rule and says no second
lint rule joins it. The question for the maintainer: may the config hold a second kind of rule, the
import boundaries? If so, amend that entry's "single rule" and "no second lint rule", and rename the
`size-ratchet` script and `ci.sh` leg, whose name would no longer say what they hold.
@@ -205,23 +206,23 @@ round-trips them; `docs/decisions.md` §The code list gives a cause the carry an
them from the README's `unsupported-node-shape` cause "Writing, in `adfToLosslessMarkdown`". Found by the README-goals
audit, 2026-10-04.
### 127. Hold what `result.test.ts`, `json-text.test.ts` and `entity-references.test.ts` check by asserting outcomes, so none reads source text.
### 127. Hold what `entity-references.test.ts`, `json-text.test.ts` and `result.test.ts` check by asserting outcomes, so none reads source text.
Technical principle "Assert the outcome", which bans scanning the source with `ast` or a regex.
Three tests read source text:
- `src/markdown/commonmark/entity-references.test.ts` regex-extracts the `packedReferences` literal
from `entity-references.ts`, to guard that each of the 2125 packed references parts into one name
and one value the table decodes. Reformatting the literal fails it with the table unchanged.
- `src/json-text.test.ts` greps every shipped file for `JSON.parse(`, to guard that only
`parseJsonText` reads JSON text. `JSON.parse (` or `JSON['parse'](` escapes it.
- `src/result.test.ts` regex-parses the `ConvertErrorCode` union out of `result.ts`, and each
`failure('…'` and `code: '…'` out of every shipped file, to guard that every declared code has a
production cause and every call site names a declared code. A code held in a variable or passed
through another helper escapes it.
- `src/json-text.test.ts` greps every shipped file for `JSON.parse(`, to guard that only
`parseJsonText` reads JSON text. `JSON.parse (` or `JSON['parse'](` escapes it.
- `src/markdown/commonmark/entity-references.test.ts` regex-extracts the `packedReferences` literal
from `entity-references.ts`, to guard that each of the 2125 packed references parts into one name
and one value the table decodes. Reformatting the literal fails it with the table unchanged.
Item 81 also touches `result.test.ts`; a lint rule for the `JSON.parse` ban meets item 126's
question about what `.oxlintrc.json` may hold. Found by the technical-principles audit of item 60,
Item 81 changes `result.test.ts` too. Whether `.oxlintrc.json` may hold a lint rule for the
`JSON.parse` ban is item 126's question. Found by the technical-principles audit of item 60,
2026-10-22.
### 112. Pad a GFM pipe table's short rows with empty cells, read its body rows holding no pipe, and read a one-column table without leading pipes in `portableMarkdownToAdf`.
@@ -261,9 +262,9 @@ documents markdown, its comparison table names HTML, and its tagline and `packag
description and keywords name HTML again. `htmlToAdf` refuses a value that is not a string as
`not-a-string` (`docs/decisions.md` §Which code a cause takes).
`html/` may not import `markdown/`. Whatever it shares with the carry (`opaque-carry.ts`) or the
mark spellings (`mark-spellings.ts`) moves out of `markdown/` as `docs/decisions.md` §The source
parts by ADF and format says. A composed call naming a markdown `Flavour` sits above both peers.
Whatever `html/` shares with the carry (`opaque-carry.ts`) or the mark spellings
(`mark-spellings.ts`) splits: the ADF question moves to `adf/`, and each format keeps its own
spelling. Where a composed call naming a markdown `Flavour` sits is this item's to settle.
### 46. Publish the bundle size in the README, failing the release pipeline when it drifts.