36b - §8, §9 and §14's decisions move to docs/decisions.md #136
@@ -28,96 +28,24 @@ In `docs/decisions.md`:
|
||||
- ESM only
|
||||
- One built entrypoint
|
||||
- Public on npm
|
||||
- The formats are API
|
||||
- The code list
|
||||
- Which code a cause takes
|
||||
- `message` and `path`
|
||||
- Publish on a version bump
|
||||
- Docs describe the release being built
|
||||
- No schema validation
|
||||
- No streaming APIs
|
||||
- No performance budget
|
||||
|
||||
## 7. Nothing about any consumer
|
||||
|
||||
No Jira client, no HTTP, no REST shapes, no issue keys, no actual consumer named anywhere. Design
|
||||
against the README's personas.
|
||||
|
||||
## 8. Semver: the formats are API
|
||||
|
||||
The emitted markdown and HTML are contracts. After 1.0: previously-emitted output parsing
|
||||
differently, or not at all, is MAJOR; new syntax while old output still round-trips is MINOR.
|
||||
Pre-1.0, normal 0.x rules. A spelled node's content model is part of that contract — leaf or
|
||||
container is the model, not the syntax — so giving a spelled node's model content it had not, or
|
||||
taking it away, is MAJOR whatever ADF's own schema does.
|
||||
|
||||
The error surface is a contract too; `README.md` §The errors states it to the consumer, and the
|
||||
types in `src/result.ts` hold its shape.
|
||||
|
||||
### The code list
|
||||
|
||||
- Adding, removing or renaming a code is breaking, so a new cause takes an existing code whose
|
||||
name reads true of it in both directions; where none does and a plain name exists, a new code —
|
||||
in any 0.x minor, and after 1.0 only in a MAJOR (the maintainer, 2026-09-18).
|
||||
- A refusal whose cause is this library's own invariant rather than the input takes the existing
|
||||
code nearest what the consumer sees — a document that does not convert is
|
||||
`unsupported-node-shape` — since a code no input reaches is one no consumer can switch on (the
|
||||
maintainer, 2026-09-20).
|
||||
- A refusal no spelling recovers from is a gap in the flavour rather than a code: give the flavour
|
||||
the spelling and the code goes, which the freeze is the last moment for (`unspellable-link`, the
|
||||
maintainer, 2026-09-13). A cause the carry answers gets no code: a mark no spelling writes rides
|
||||
the carry with its node.
|
||||
|
||||
### Which code a cause takes
|
||||
|
||||
- A code names the cause; where one cause recurs across node types, across one mark's attributes
|
||||
or across directions, one code covers them all and `path` and `message` say which —
|
||||
`unsupported-nesting-depth` is the 500-level guard whichever direction hits it,
|
||||
`unspellable-character` the text node and the code block alike. Where two codes stay apart, the
|
||||
line between them is what they name: `unspellable-character` is a character CommonMark rewrites
|
||||
wherever text holds it, `unspellable-whitespace` the newline no inline directive's content slot
|
||||
spans, in either direction.
|
||||
- A claim code names the spelling claimed, never the node that spelling would have built: a
|
||||
malformed `!adf:table` is a `malformed-directive`, and an alignment colon a
|
||||
`malformed-pipe-table` — the flavour's own delimiter row is `-` runs, so the grammar refuses the
|
||||
colon rather than ADF's missing column model doing it. What the grammar itself refuses stays a
|
||||
claim code, key order among it, and a leaf given a body is refused at its opener, as a container
|
||||
missing its closer is (the maintainer, 2026-09-16).
|
||||
- A directive whose name reads back to no node is `unknown-directive-name` rather than a claim
|
||||
code — the spelling is well formed, and telling that apart from a typo is what a consumer
|
||||
switches on when a later MINOR gives the name meaning. A reserved name is a known name, so never
|
||||
that code, and the two the flavour reserves part on form: a form the grammar does not have is a
|
||||
claim code — `!adf:carry`, whose carry is the fence — and a well-formed form in the wrong place
|
||||
is `unsupported-node-shape`, `!adf:listBreak` parting anything but two adjacent lists of one
|
||||
type.
|
||||
- A well-formed directive the node tables refuse — an attribute a node does not hold or spells
|
||||
elsewhere, a value outside its kind or its canonical spelling, an argument, or a body of a shape
|
||||
its content model does not take — is `unsupported-node-shape`, the emitter's code for the same
|
||||
mismatch read the other way: one code across both directions for good, since the call site
|
||||
knows which direction it called and parting them after `0.1.0` is MAJOR.
|
||||
- A non-finite number takes two codes: `unsupported-node-shape` parsing, `not-an-adf-document`
|
||||
emitting — no document holds one, so no round-trip crosses them.
|
||||
|
||||
### `message` and `path`
|
||||
|
||||
- A message names the violation, not the rule alone — a rule by itself states a truth the reader
|
||||
must invert before it reads as a failure — and where the flavour's claim refuses ordinary prose
|
||||
it names the escape that unclaims the form claimed: `\!adf:` for a directive, block line and
|
||||
inline alike, `\|` for every pipe row.
|
||||
- `not-an-adf-document` carries the document's own path throughout: seven of the guard's eight
|
||||
branches read the document's own shape, and threading a path to the eighth — a malformed node
|
||||
anywhere in the tree — wants the manual stack §11's no-recursion rule forces, whose empty half
|
||||
no input reaches. The message names the violation instead.
|
||||
|
||||
## 9. Release automation
|
||||
|
||||
- `package.json` version on `main` is the source of truth. CI on `main`: tests green and version
|
||||
differs from npm → publish and tag `vX.Y.Z`. No bump, no deploy; the bump is each shipping PR's
|
||||
deliberate semver judgment. `publish.sh` is that job, and `private: true` stops it before it
|
||||
reads the token, so the pipeline is live and silent until the maintainer's first bump drops the
|
||||
field.
|
||||
- The bump commit renames `CHANGELOG.md`'s `## Unreleased` to the version.
|
||||
- Docs on `main` describe the release being built rather than the version npm holds, so they match
|
||||
it the moment the bump publishes; add no interim note marking the gap (the maintainer,
|
||||
2026-09-16).
|
||||
- The publish and the tag each observe their own end state — the version on npm, the tag on the
|
||||
remote — and neither gates the other, so a run that dies between them converges on the next push
|
||||
to `main` rather than leaving npm ahead of the tags. An unanswered registry reads the same as an
|
||||
unpublished version, which npm's own duplicate rejection is what catches. The job rebuilds rather
|
||||
than taking the gate's `dist`: the lockfile is committed, the image is patch-pinned and `tsc` is
|
||||
deterministic, so the two builds agree, and promoting an artifact would make the release path
|
||||
depend on a store that the gate would then have to keep.
|
||||
- Exact versions: `save-exact=true` in `.npmrc`.
|
||||
- Renovate watches devDependencies, Docker pins and action tags; automerges everything on green CI.
|
||||
- Docker images pin the full patch version (`node:24.19.0-alpine3.24`, never `node:24`), as
|
||||
@@ -316,16 +244,6 @@ Applies everywhere: comments, every markdown file in this repo (this one include
|
||||
|
||||
One-line commit messages and PR titles; short PR summaries. No AI-attribution markers, ever.
|
||||
|
||||
## 14. Non-goals
|
||||
|
||||
No network or filesystem I/O, no name→id resolution (`docs/decisions.md` §Names stay text), no ADF
|
||||
schema validation or exported validator — a refusal that keeps the round-trip is not schema
|
||||
validation, so the one a spelled node carrying the same mark type twice earns stays, and input
|
||||
nesting a spelling inside its own kind (`*(*a*)*`) names that mark once, no shipped CSS
|
||||
(`docs/decisions.md` §The HTML dialect), no streaming APIs, no performance budget past §11's
|
||||
scanning rule — nothing here is tuned, and no figure is promised. A CLI is a later goal (`todo.md`),
|
||||
not a non-goal.
|
||||
|
||||
## 15. The working loop
|
||||
|
||||
`todo.md` lists what is left under the release that ships it, in shipping order. One item per
|
||||
@@ -347,7 +265,8 @@ Per chunk:
|
||||
reworded for them into `CHANGELOG.md`'s `## Unreleased` — report, stop.
|
||||
|
||||
Reserved for the maintainer whatever any rule here says: changing `version` in `package.json` (a
|
||||
bump on `main` publishes, §9 — every release is the maintainer's) and the `NPM_TOKEN` secret.
|
||||
bump on `main` publishes, `docs/decisions.md` §Publish on a version bump — every release is the
|
||||
maintainer's) and the `NPM_TOKEN` secret.
|
||||
|
||||
### Ask, don't guess
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@ emit refuses:
|
||||
- Past that and `~~`, no GFM: an autolink literal and a `- [ ]` marker stay text, and a checklist
|
||||
is the `taskList` directive — `plainMarkdownToAdf` turns the marker into a `taskList`.
|
||||
- A document nested deeper than 500 levels is an error result, not a stack overflow.
|
||||
- The emitted formats are semver surface (AGENTS.md §8).
|
||||
- The emitted formats are semver surface
|
||||
([`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md#the-formats-are-api)).
|
||||
- **`0.2.0`** — `htmlToAdf(adfToHtml(doc))` equals `doc`; fidelity HTML cannot express rides
|
||||
`data-*` attributes. Foreign HTML maps a documented element set, which markdown's raw HTML reads
|
||||
through as well, and a construct outside it is an error; well-formed HTML only — no tag-soup
|
||||
|
||||
@@ -182,3 +182,127 @@ an npm consumer.
|
||||
|
||||
Published to public npm as `@larvit/adf-codec`. Public source: the Gitea repo goes public,
|
||||
LICENSE in place, before the first publish.
|
||||
|
||||
## The formats are API
|
||||
|
||||
2026-08-23, content models 2026-09-16, the maintainer. Goals 1 and 6. Valid while consumers store
|
||||
what the library emits.
|
||||
|
||||
The emitted markdown and HTML are contracts. After 1.0: previously-emitted output parsing
|
||||
differently, or not at all, is MAJOR; new syntax while old output still round-trips is MINOR.
|
||||
Pre-1.0, normal 0.x rules. A spelled node's content model is part of that contract — leaf or
|
||||
container is the model, not the syntax — so giving a spelled node's model content it had not, or
|
||||
taking it away, is MAJOR whatever ADF's own schema does.
|
||||
|
||||
The error surface is a contract too; `README.md` §The errors states it to the consumer, and the
|
||||
types in `src/result.ts` hold its shape.
|
||||
|
||||
## The code list
|
||||
|
||||
2026-08-25, the maintainer; dated below where a rule came later. Goal 6. Valid while a consumer
|
||||
switches on `code` with no `default`.
|
||||
|
||||
- Adding, removing or renaming a code is breaking, so a new cause takes an existing code whose
|
||||
name reads true of it in both directions; where none does and a plain name exists, a new code —
|
||||
in any 0.x minor, and after 1.0 only in a MAJOR (2026-09-18).
|
||||
- A refusal whose cause is this library's own invariant rather than the input takes the existing
|
||||
code nearest what the consumer sees — a document that does not convert is
|
||||
`unsupported-node-shape` — since a code no input reaches is one no consumer can switch on
|
||||
(2026-09-20).
|
||||
- A refusal no spelling recovers from is a gap in the flavour rather than a code: give the flavour
|
||||
the spelling and the code goes, which the freeze is the last moment for (`unspellable-link`,
|
||||
2026-09-13). A cause the carry answers gets no code: a mark no spelling writes rides the carry
|
||||
with its node.
|
||||
|
||||
## Which code a cause takes
|
||||
|
||||
2026-08-28, the maintainer; dated below where a rule came later. Goal 6. Valid while a consumer
|
||||
handles one cause alike whichever node, attribute or direction raised it.
|
||||
|
||||
- A code names the cause; where one cause recurs across node types, across one mark's attributes
|
||||
or across directions, one code covers them all and `path` and `message` say which —
|
||||
`unsupported-nesting-depth` is the 500-level guard whichever direction hits it,
|
||||
`unspellable-character` the text node and the code block alike. Where two codes stay apart, the
|
||||
line between them is what they name: `unspellable-character` is a character CommonMark rewrites
|
||||
wherever text holds it, `unspellable-whitespace` the newline no inline directive's content slot
|
||||
spans, in either direction.
|
||||
- A claim code names the spelling claimed, never the node that spelling would have built: a
|
||||
malformed `!adf:table` is a `malformed-directive`, and an alignment colon a
|
||||
`malformed-pipe-table` — the flavour's own delimiter row is `-` runs, so the grammar refuses the
|
||||
colon rather than ADF's missing column model doing it. What the grammar itself refuses stays a
|
||||
claim code, key order among it, and a leaf given a body is refused at its opener, as a container
|
||||
missing its closer is (2026-09-16).
|
||||
- A directive whose name reads back to no node is `unknown-directive-name` rather than a claim
|
||||
code — the spelling is well formed, and telling that apart from a typo is what a consumer
|
||||
switches on when a later MINOR gives the name meaning. A reserved name is a known name, so never
|
||||
that code, and the two the flavour reserves part on form: a form the grammar does not have is a
|
||||
claim code — `!adf:carry`, whose carry is the fence — and a well-formed form in the wrong place
|
||||
is `unsupported-node-shape`, `!adf:listBreak` parting anything but two adjacent lists of one
|
||||
type (2026-09-01).
|
||||
- A well-formed directive the node tables refuse — an attribute a node does not hold or spells
|
||||
elsewhere, a value outside its kind or its canonical spelling, an argument, or a body of a shape
|
||||
its content model does not take — is `unsupported-node-shape`, the emitter's code for the same
|
||||
mismatch read the other way: one code across both directions for good, since the call site
|
||||
knows which direction it called and parting them after `0.1.0` is MAJOR (2026-09-23).
|
||||
- A non-finite number takes two codes: `unsupported-node-shape` parsing, `not-an-adf-document`
|
||||
emitting — no document holds one, so no round-trip crosses them (2026-09-23).
|
||||
|
||||
## `message` and `path`
|
||||
|
||||
2026-09-03, the path 2026-09-23, the maintainer. Goals 3 and 6. Valid while a person fixing the
|
||||
input reads `message`.
|
||||
|
||||
- A message names the violation, not the rule alone — a rule by itself states a truth the reader
|
||||
must invert before it reads as a failure — and where the flavour's claim refuses ordinary prose
|
||||
it names the escape that unclaims the form claimed: `\!adf:` for a directive, block line and
|
||||
inline alike, `\|` for every pipe row.
|
||||
- `not-an-adf-document` carries the document's own path throughout: seven of the guard's eight
|
||||
branches read the document's own shape, and threading a path to the eighth — a malformed node
|
||||
anywhere in the tree — wants the manual stack the no-recursion rule (`AGENTS.md` §11) forces,
|
||||
whose empty half no input reaches. The message names the violation instead.
|
||||
|
||||
## Publish on a version bump
|
||||
|
||||
2026-08-23, converging 2026-09-03, the maintainer. Goal 7. Valid while CI on `main` holds the npm
|
||||
token.
|
||||
|
||||
`package.json` version on `main` is the source of truth. CI on `main`: tests green and version
|
||||
differs from npm → publish and tag `vX.Y.Z`. No bump, no deploy; the bump is each shipping PR's
|
||||
deliberate semver judgment. `publish.sh` is that job, and `private: true` stops it before it reads
|
||||
the token, so the pipeline is live and silent until the maintainer's first bump drops the field.
|
||||
|
||||
The publish and the tag each observe their own end state — the version on npm, the tag on the
|
||||
remote — and neither gates the other, so a run that dies between them converges on the next push
|
||||
to `main` rather than leaving npm ahead of the tags. An unanswered registry reads the same as an
|
||||
unpublished version, which npm's own duplicate rejection is what catches. The job rebuilds rather
|
||||
than taking the gate's `dist`: the lockfile is committed, the image is patch-pinned and `tsc` is
|
||||
deterministic, so the two builds agree, and promoting an artifact would make the release path
|
||||
depend on a store that the gate would then have to keep.
|
||||
|
||||
## Docs describe the release being built
|
||||
|
||||
2026-09-16, the maintainer. Goal 7. Valid while a bump on `main` publishes.
|
||||
|
||||
Docs on `main` describe the release being built rather than the version npm holds, so they match it
|
||||
the moment the bump publishes; add no interim note marking the gap.
|
||||
|
||||
## No schema validation
|
||||
|
||||
2026-08-23, the mark refusal 2026-08-25, the maintainer. Goal 1. Valid while the site a document
|
||||
is saved to validates it.
|
||||
|
||||
No ADF schema validation or exported validator. A refusal that keeps the round-trip is not schema
|
||||
validation, so the one a spelled node carrying the same mark type twice earns stays, and input
|
||||
nesting a spelling inside its own kind (`*(*a*)*`) names that mark once.
|
||||
|
||||
## No streaming APIs
|
||||
|
||||
2026-08-23, the maintainer. Goal 8. Valid while a document fits in memory.
|
||||
|
||||
A call takes a whole document and returns a whole result.
|
||||
|
||||
## No performance budget
|
||||
|
||||
2026-08-23, the maintainer. Goal 8. Valid while no persona needs a speed figure.
|
||||
|
||||
Nothing is tuned past the scanning rule (`AGENTS.md` §11), and no figure is promised.
|
||||
|
||||
+20
-19
@@ -1,12 +1,12 @@
|
||||
# The markdown flavour
|
||||
|
||||
The grammar of the extended markdown `adfToMarkdown` emits and `markdownToAdf` parses. Plain
|
||||
CommonMark is a subset apart from raw HTML (below), with three carve-outs: literal text that
|
||||
matches directive syntax below or reads as a pipe table is claimed by the flavour, and a matched
|
||||
`~~` pair spells `strike` (escape the `!adf:`, `|` or `~` to keep it literal) — and one gap: a
|
||||
CommonMark image fits only as its own
|
||||
title-less paragraph — mid-text and titled images are named errors. The emitted form is contract
|
||||
(AGENTS.md §8). Per-node syntaxes build on this grammar in the sections below.
|
||||
CommonMark is a subset apart from raw HTML (below), with three carve-outs: literal text that matches
|
||||
directive syntax below or reads as a pipe table is claimed by the flavour, and a matched `~~` pair
|
||||
spells `strike` (escape the `!adf:`, `|` or `~` to keep it literal) — and one gap: a CommonMark
|
||||
image fits only as its own title-less paragraph — mid-text and titled images are named errors. The
|
||||
emitted form is contract (`docs/decisions.md` §The formats are API). Per-node syntaxes build on this
|
||||
grammar in the sections below.
|
||||
|
||||
## Canonical form
|
||||
|
||||
@@ -76,13 +76,14 @@ normalizes to it through the round-trip.
|
||||
One grammar for everything CommonMark lacks, namespaced: every directive opens with the literal
|
||||
`!adf:`. A directive name is `[a-z][A-Za-z0-9]*` — the ADF node and mark names the sections below
|
||||
spell as directives. Recognition is syntactic and name-set-independent: anything matching the forms
|
||||
below parses as a directive regardless of whether the name is known, and an unknown name is an
|
||||
error result naming it at the opener, whatever follows it — so output an old emitter escaped stays
|
||||
escaped, and erroring input gaining meaning later is MINOR, never a reparse (§8). Each name belongs
|
||||
to one position, and a name the other one spells — a mark or an inline node written as a block
|
||||
directive, a block node written inline — is a different error, naming the spelling it takes. Two
|
||||
reserved names read back to no node: `carry` for the opaque carry, as both directive name and fence
|
||||
info string, and `listBreak` for the leaf that parts two adjacent lists (Canonical form).
|
||||
below parses as a directive regardless of whether the name is known, and an unknown name is an error
|
||||
result naming it at the opener, whatever follows it — so output an old emitter escaped stays
|
||||
escaped, and erroring input gaining meaning later is MINOR, never a reparse (`docs/decisions.md`
|
||||
§The formats are API). Each name belongs to one position, and a name the other one spells — a mark
|
||||
or an inline node written as a block directive, a block node written inline — is a different error,
|
||||
naming the spelling it takes. Two reserved names read back to no node: `carry` for the opaque carry,
|
||||
as both directive name and fence info string, and `listBreak` for the leaf that parts two adjacent
|
||||
lists (Canonical form).
|
||||
|
||||
**Claiming**: an unescaped `!adf:` claims wherever it stands. What follows picks the form: `/name`
|
||||
closes a container, and a name picks by what follows it in turn — a space or the line's end a block
|
||||
@@ -123,7 +124,7 @@ Which of the two a node takes is its content model, never the spelling: a model
|
||||
written as an opener–closer pair and one taking none as a leaf, so a leaf given a body and a
|
||||
container missing its closer are each a named error. A node holding no content whose model takes
|
||||
some is an empty pair. A spelled node's content model is contract in consequence — changing one is
|
||||
MAJOR (AGENTS.md §8).
|
||||
MAJOR (`docs/decisions.md` §The formats are API).
|
||||
|
||||
Canonical spacing is the only spacing input reads: one space parts the name, `arg` and `{attrs}`,
|
||||
and one parts each attribute pair, with no padding inside the braces. Trailing whitespace on a
|
||||
@@ -184,11 +185,11 @@ HTML.
|
||||
|
||||
## Block nodes
|
||||
|
||||
The directive name is always the ADF node type. A container's body is the node's `content`; a
|
||||
leaf has none. Every directive parses in any position — `markdownToAdf` builds exactly what is
|
||||
written; validity against ADF's content models stays the author's business (AGENTS.md §14). It
|
||||
parses only in the form the emitter picks, though: a directive spelling a node the emitter would
|
||||
have written as CommonMark is a named error.
|
||||
The directive name is always the ADF node type. A container's body is the node's `content`; a leaf
|
||||
has none. Every directive parses in any position — `markdownToAdf` builds exactly what is written;
|
||||
validity against ADF's content models stays the author's business (`docs/decisions.md` §No schema
|
||||
validation). It parses only in the form the emitter picks, though: a directive spelling a node the
|
||||
emitter would have written as CommonMark is a named error.
|
||||
|
||||
Each section lists attributes as `name (type)`. A parenthesized value set documents what real
|
||||
payloads hold; the type stays string and any value round-trips verbatim. Values map to attrs by
|
||||
|
||||
@@ -91,7 +91,7 @@ test('the refusal list is unique per example and names real examples', () => {
|
||||
for (const example of exampleToRefusal.keys()) assert.ok(spec.some((entry) => entry.example === example), `refusal ${example} names no example in the suite`)
|
||||
})
|
||||
|
||||
// A mark is counted once per text node it touches (AGENTS.md §14).
|
||||
// A mark is counted once per text node it touches (docs/decisions.md §No schema validation).
|
||||
const countKeys = ['a', 'blockquote', 'br', 'code', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'img', 'li', 'ol', 'pre', 'strong', 'ul']
|
||||
const nodeElement: Record<string, string> = {
|
||||
blockquote: 'blockquote',
|
||||
|
||||
@@ -69,7 +69,7 @@ export function readInlineDirectiveNode(
|
||||
return success(namedNode(name, attrs.value, undefined))
|
||||
}
|
||||
|
||||
// A name the other position spells names that spelling, never the code a later MINOR may fill (AGENTS.md §8).
|
||||
// A name the other position spells names that spelling, never the code a later MINOR may fill (docs/decisions.md §Which code a cause takes).
|
||||
function inlineSpellingFault(name: string): ConvertFault | undefined {
|
||||
const mark = inlineMarkSpellingFault(name)
|
||||
if (mark !== undefined) return mark
|
||||
|
||||
@@ -477,7 +477,7 @@ function markType(character: string, used: number): string {
|
||||
return used === 2 ? 'strong' : 'em'
|
||||
}
|
||||
|
||||
// A node cannot carry one mark type twice (AGENTS.md §14).
|
||||
// A node cannot carry one mark type twice (docs/decisions.md §No schema validation).
|
||||
function applyMark(nodes: readonly AdfNode[], mark: AdfMark): AdfNode[] {
|
||||
return nodes.map((node) => {
|
||||
const marks = nodeMarks(node)
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ function calledCodes(): string[] {
|
||||
return [...called].sort()
|
||||
}
|
||||
|
||||
// The list is frozen at 0.1.0 (AGENTS.md §8), so a code outliving its cause is a removal that costs a MAJOR.
|
||||
// The list is frozen at 0.1.0 (docs/decisions.md §The code list), so a code outliving its cause is a removal that costs a MAJOR.
|
||||
test('every ConvertErrorCode is the code of a production call site, and every call site names a declared one', () => {
|
||||
assert.deepEqual(calledCodes(), declaredCodes())
|
||||
})
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
one no goal serves is proposed as a goal and asked. Sources: `AGENTS.md`'s body, the settled text
|
||||
in this file's items, and `todo-history.md`, deleted with the bare `(28)` citations into it once
|
||||
nothing cites it. Split by `AGENTS.md` section where one chunk is too big.
|
||||
- **36b — Move §8, §9 and §14's decisions.** The code list's rules, release automation and the
|
||||
non-goals.
|
||||
- **36c — Move §10 and §11's decisions.** The engine legs, floors, size ratchet, bounds, spellings
|
||||
and layout; the style rules stay working rules.
|
||||
- **36d — Move the settled text in `todo.md`'s items and §15's dated rules, and point §15's
|
||||
|
||||
Reference in New Issue
Block a user