17 - the gate holds every built function to 52 lines #111

Merged
lilleman merged 4 commits from size-ratchet into main 2026-09-20 18:30:42 +02:00
7 changed files with 463 additions and 14 deletions
+8
View File
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": { "correctness": "off" },
"ignorePatterns": ["src/**/*.test.ts", "src/property-harness.ts"],
"rules": {
"eslint/max-lines-per-function": ["error", { "IIFEs": true, "max": 52, "skipBlankLines": false, "skipComments": false }]
}
}
+13 -1
View File
@@ -78,7 +78,9 @@ vendored the same way, at `spec/adf-schema/`, rather than as the `@atlaskit/adf-
dependency — CommonJS-only, some fifty packages with React among them, and a release most days for dependency — CommonJS-only, some fifty packages with React among them, and a release most days for
Renovate to automerge — re-pinned by hand when a payload or a report shows the need. Renovate to automerge — re-pinned by hand when a payload or a report shows the need.
`devDependencies`: few, each earning its keep; they never reach a consumer. `fast-check` earns its `devDependencies`: few, each earning its keep; they never reach a consumer. `fast-check` earns its
place shrinking a failing generated document to the nodes that break it. place shrinking a failing generated document to the nodes that break it, `oxlint` measuring §10's
size ratchet — TypeScript 7 is a native compiler publishing no in-process parser, only the
`unstable/` AST surface an out-of-process handshake reaches.
## 6. The package contract ## 6. The package contract
@@ -254,6 +256,16 @@ functions, and a branch floor that only ever moves upward. It sits below 100 bec
`noUncheckedIndexedAccess` and ADF's optional keys force — `?? []`, `?? {}`, `?.`, an index `noUncheckedIndexedAccess` and ADF's optional keys force — `?? []`, `?? {}`, `?.`, an index
compared against `undefined` — have a half no valid document reaches. compared against `undefined` — have a half no valid document reaches.
The size ratchet is the other such number, `.oxlintrc.json`'s single rule over the files
`tsconfig.build.json` builds: a per-function line ceiling, set at that set's worst and moving only
downward. It covers the built files alone, since one ceiling over the tests too would have to be
their worst, loosening the guard over the shipped code. It guards against drift and never drives a
refactor, so no cyclomatic rule and no second lint rule join it: neither measure picked out what
nine readers found hard (the comprehension panel, 2026-09-20). Three switches guard a silent green:
`IIFEs: true`, since oxlint exempts an IIFE otherwise; an explicit `-c`, so a config gone missing
fails the leg instead of falling back to oxlint's own defaults; and `--deny-warnings`, since a rule
from a category this config never names arrives as a warning it exits 0 on.
The corpus, all checked in: hand-built fixtures per node and combination; real ADF Atlassian's The corpus, all checked in: hand-built fixtures per node and combination; real ADF Atlassian's
editor wrote; the CommonMark spec suite against `markdownToAdf` and `markdownToHtml`. editor wrote; the CommonMark spec suite against `markdownToAdf` and `markdownToHtml`.
+1
View File
@@ -5,6 +5,7 @@ source ./docker-runner.sh
leg "install ($node_image)" in_image "$node_image" npm ci leg "install ($node_image)" in_image "$node_image" npm ci
leg "typecheck ($node_image)" in_image "$node_image" npm run typecheck leg "typecheck ($node_image)" in_image "$node_image" npm run typecheck
leg "size ratchet ($node_image)" in_image "$node_image" npm run size-ratchet
test_log=$(mktemp) test_log=$(mktemp)
node_tests() { node_tests() {
+397
View File
@@ -11,12 +11,360 @@
"devDependencies": { "devDependencies": {
"@types/node": "24.13.3", "@types/node": "24.13.3",
"fast-check": "4.10.0", "fast-check": "4.10.0",
"oxlint": "1.83.0",
"typescript": "7.0.2" "typescript": "7.0.2"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@oxlint/binding-android-arm-eabi": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.83.0.tgz",
"integrity": "sha512-0yGY24EwsLk5YDe6F+VkmZyRHSwJDALa3nIrPpq7FXmp2lV2d0TzvBCGeZk+wgiULRGr5blhyr4QMp5KCXJUqA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-android-arm64": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.83.0.tgz",
"integrity": "sha512-hHfJ0vc17A4iUjH5p9BsTUPYbYRNxGpvD2lbu1aBRk54bzNIx9o5TtYF39QPZcV95DagZd+4DEAw2RH3G2ZsMg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-darwin-arm64": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.83.0.tgz",
"integrity": "sha512-hsOjYjszLb/3zym/TkzUMPAoQlTJcuzSyEPOAyA+skXJIX9M0o+4JfOtqopX/Vf4hSLrJ98j0nvFo23gzk8auQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-darwin-x64": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.83.0.tgz",
"integrity": "sha512-mjh5oH2EA+wl5yRJYT9K9G61O2zFlpuv+yf2JwZOi0+dq2FnTUtm1h8i+5Ik0fXPWIu/k84I1psZR9aQsLAnyA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-freebsd-x64": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.83.0.tgz",
"integrity": "sha512-fNHr64/YaO8YssuoDVC8+F4Uk5enR86q5uxfHkQrjAPs1dbAILOrD2uaud+J7MO8Fx774g44ERLD0IGIvZE48w==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm-gnueabihf": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.83.0.tgz",
"integrity": "sha512-Qpwy3zzAwMj+8/lyYItHmkSMwbkprFNWTK7jPYDOxSyxEhaSLOWYUTCMkjF334J8/WD0nznCCsoBbIH6hpsuIw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm-musleabihf": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.83.0.tgz",
"integrity": "sha512-s+BirYLFq7JL2k9sP0XI3ZXJ9dYvJ8sX3jLCLoag7tt+zrSHpZxP0jqznfL+Gdgwu7ay0dYgGYJXrQvq3iWloA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm64-gnu": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.83.0.tgz",
"integrity": "sha512-7lihXt3vKr+GIyapNbHrnFHm/biiW30le6Zv/DExbAFPF6YwCQXVFlONPFehxs0CpGO4CBfYPM9rdDT+XMoIlg==",
"cpu": [
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-arm64-musl": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.83.0.tgz",
"integrity": "sha512-q63JalLYVkZiZvls1z3PPUnpmQluOMXp0khqQMznCeAPLGydfNY8JhvuA4WlK57JfrvikU8wB5lPVveqpIXvew==",
"cpu": [
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-ppc64-gnu": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.83.0.tgz",
"integrity": "sha512-krQmDF+dRbxvdqVPV88ZuOoPPu8X5BuqDA8Hd+qcS4YMRQCb+nexA57DazgGsc/rGdKBe3QmV0mnv0bdpW/p5g==",
"cpu": [
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-riscv64-gnu": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.83.0.tgz",
"integrity": "sha512-MmOl8Y6txEAXZU1RG8Rr264jQ6D7VPmqFsU/45x/FeWsGe32hklTqGrLE6UxHzp5Rjt0wP+20tY8YXKgSFB3mw==",
"cpu": [
"riscv64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-riscv64-musl": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.83.0.tgz",
"integrity": "sha512-u1rMymh0W3JZkq370kzQsYPULGWqhE09pZRqnZvUSoYaI9pVO5yVX+iYIslmWuEgwuzH9YAaOsScJiobWCHoOw==",
"cpu": [
"riscv64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-s390x-gnu": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.83.0.tgz",
"integrity": "sha512-y0zK3HNwGysu7rqtE+BQG/d0bx5gh/KwlOtghN8oWeK1KcWzeaLqtZrbm8owqdma1lFyrce/hTO5ismuNu+INQ==",
"cpu": [
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-x64-gnu": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.83.0.tgz",
"integrity": "sha512-rS5gM0NgD7ngmuJmbIehsidtrOwKkLFwCQbKEeb9KuyQrrWNq5Zkn0uV6AYdXOMJ0grrWEiLwBuvMxt8w5vsNw==",
"cpu": [
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-linux-x64-musl": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.83.0.tgz",
"integrity": "sha512-W2IH4EtpcPaWcvNGCA95YoDg4vxqE/ZiPCi3arrxEEpsK7+JQN9WYwrlYFx9pcdP6KPXqRqkv3zdQPHcx7b6YQ==",
"cpu": [
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-openharmony-arm64": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.83.0.tgz",
"integrity": "sha512-6LyKkUyoajssTPLlZmDbZIbu4IZ5B4bGuRUnBgCGpEvHP3FQMaYITncHA/unPUo7q+Z+pIu2HhdkQ+8d1SG7iA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-arm64-msvc": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.83.0.tgz",
"integrity": "sha512-Uz/fObEtF0jmNJQJ8CGRBKfefYstS0/wjD3s6IGzP8nUwsJykHQJBiN3npHwKiGRGn/vvBEgNr4B3cCzmmatvg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-ia32-msvc": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.83.0.tgz",
"integrity": "sha512-u7XcvPW6Bk58tY5iWs2ESb0vJjoE/kuSpHxopbwp/p3ZtWVQXZ6wor5w3ssVTHOqd/v8b+QdhSFWQ4grEUNWpA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@oxlint/binding-win32-x64-msvc": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.83.0.tgz",
"integrity": "sha512-LZRubd7ph13QmAg4fFecTYVZkiYbROR2Htaxh/ufWRkDhPOm2wrwaEYR89e0YpPFD3dqBrPoxS7myBw5hmYA7Q==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.13.3", "version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
@@ -390,6 +738,55 @@
"node": ">=12.17.0" "node": ">=12.17.0"
} }
}, },
"node_modules/oxlint": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.83.0.tgz",
"integrity": "sha512-cyDzSzaw3uzP0TeCeq3lLRPPoaUxkbB4ZOXj+kn+5r+BX9V+4bNVGk9lxer+WrgcpebH4JxLlJ3KQjveVztOLQ==",
"dev": true,
"license": "MIT",
"bin": {
"oxlint": "bin/oxlint"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/sponsors/oxc-project"
},
"optionalDependencies": {
"@oxlint/binding-android-arm-eabi": "1.83.0",
"@oxlint/binding-android-arm64": "1.83.0",
"@oxlint/binding-darwin-arm64": "1.83.0",
"@oxlint/binding-darwin-x64": "1.83.0",
"@oxlint/binding-freebsd-x64": "1.83.0",
"@oxlint/binding-linux-arm-gnueabihf": "1.83.0",
"@oxlint/binding-linux-arm-musleabihf": "1.83.0",
"@oxlint/binding-linux-arm64-gnu": "1.83.0",
"@oxlint/binding-linux-arm64-musl": "1.83.0",
"@oxlint/binding-linux-ppc64-gnu": "1.83.0",
"@oxlint/binding-linux-riscv64-gnu": "1.83.0",
"@oxlint/binding-linux-riscv64-musl": "1.83.0",
"@oxlint/binding-linux-s390x-gnu": "1.83.0",
"@oxlint/binding-linux-x64-gnu": "1.83.0",
"@oxlint/binding-linux-x64-musl": "1.83.0",
"@oxlint/binding-openharmony-arm64": "1.83.0",
"@oxlint/binding-win32-arm64-msvc": "1.83.0",
"@oxlint/binding-win32-ia32-msvc": "1.83.0",
"@oxlint/binding-win32-x64-msvc": "1.83.0"
},
"peerDependencies": {
"oxlint-tsgolint": ">=7.0.2001",
"vite-plus": "*"
},
"peerDependenciesMeta": {
"oxlint-tsgolint": {
"optional": true
},
"vite-plus": {
"optional": true
}
}
},
"node_modules/pure-rand": { "node_modules/pure-rand": {
"version": "8.4.2", "version": "8.4.2",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.2.tgz", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.2.tgz",
+2
View File
@@ -23,12 +23,14 @@
}, },
"scripts": { "scripts": {
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"size-ratchet": "oxlint --deny-warnings -c .oxlintrc.json src",
"test": "node --test --experimental-test-coverage --test-coverage-exclude=\"src/**/*.test.ts\" --test-coverage-exclude=src/property-harness.ts --test-coverage-branches=98 --test-coverage-functions=100 --test-coverage-lines=100 \"src/**/*.test.ts\"", "test": "node --test --experimental-test-coverage --test-coverage-exclude=\"src/**/*.test.ts\" --test-coverage-exclude=src/property-harness.ts --test-coverage-branches=98 --test-coverage-functions=100 --test-coverage-lines=100 \"src/**/*.test.ts\"",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.build.json" "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.build.json"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "24.13.3", "@types/node": "24.13.3",
"fast-check": "4.10.0", "fast-check": "4.10.0",
"oxlint": "1.83.0",
"typescript": "7.0.2" "typescript": "7.0.2"
} }
} }
+21
View File
@@ -856,6 +856,27 @@ The done `todo.md` items in full, as they were written. `todo.md` keeps a one-li
dropping the outer link silently as `closeLink`'s `applyMark` does today, with a dropping the outer link silently as `closeLink`'s `applyMark` does today, with a
normalization fixture per shape (the stability-reviewer, 2026-09-16; the maintainer, normalization fixture per shape (the stability-reviewer, 2026-09-16; the maintainer,
2026-09-17). 2026-09-17).
- [x] **17 — A machine-enforced size ratchet (`0.2.0`).** Add a per-function line ceiling to the
gate, set at today's worst and only ever moving down, so the largest body of new code cannot
exceed what is already here (the systems-architect, 2026-09-16; narrowed by the comprehension
panel, 2026-09-20). oxlint's `eslint/max-lines-per-function` measures it — one devDependency,
carrying the musl binding the gate's image needs, since TypeScript 7 is the native compiler
and exposes no parser to write the check against. No cyclomatic rule: `eslint/complexity`
charges `?.` and `??` a point each, the guards §10 already exempts from the branch floor, and
its two worst functions, `readBlockLine` and `parseInline`, went unnamed by all nine readers
while `isNodeArray` and `blockNode` were volunteered as among the clearest code here. Length
ranks no better: `emitList` and `blockNode` are both 26 lines, one the panel's unanimous top
four and the other the clearest map of the format in the repo. So the ceiling guards against
drift and never drives a refactor — 19 to 27 are where the hard work actually is.
**Done** (2026-09-20): `.oxlintrc.json` carries the one rule, `correctness` off so nothing
else runs, over the 40 files `tsconfig.build.json` builds — the tests and
`property-harness.ts` out, five functions over the ceiling with them, the worst 64. The
ceiling is 52, `parseInline`'s length and the built set's worst; at 51 the gate reddens on
it. `skipBlankLines` and `skipComments` are spelled at oxlint 1.83.0's defaults, so a changed
default cannot move what 52 counts. The leg runs `npm run size-ratchet` beside the typecheck
at 0.8s, and the lockfile carries every platform binding, so `npm ci` resolves the musl one
inside the image. §10 holds the rule and what each switch guards (the stability-reviewer,
2026-09-20).
- [x] **18 — The subtree the directive spelling asks about (`0.2.0`).** The parser asks - [x] **18 — The subtree the directive spelling asks about (`0.2.0`).** The parser asks
`commonMarkSpelling` at every directive-spelled block and the answer emits the whole subtree `commonMarkSpelling` at every directive-spelled block and the answer emits the whole subtree
below, so a node at depth d is spelled d times: three nested rule-first directive lists cost below, so a node at depth d is spelled d times: three nested rule-first directive lists cost
+21 -13
View File
@@ -18,7 +18,8 @@ Start a session with: `Read AGENTS.md and todo.md, then do what todo.md's "Next
## Milestones ## Milestones
Shipping order: 3h, 3i, 3j, 5a, 5b, 5c, 5d, 5 → `0.1.0` (shipped 2026-09-05); 3k, 11, 4, 12, 13, 4b, 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, 19, 20, 21, 22, 23, 24, 25, 26, 27, 10, 6, 7, 5f, 5g → `0.2.0`; 4c, 14, 15, 16, 18, 4d, 28, 17, 29, 19, 20, 21, 22, 23, 24, 25, 30, 26, 27, 10, 6, 7, 5f, 5g →
`0.2.0`;
8, 9 → TBD; 5e last. 8, 9 → TBD; 5e last.
The numbering is the order the work was planned in, not the order it ships. Everything known and The numbering is the order the work was planned in, not the order it ships. Everything known and
shaped ships in one release rather than a string of them: nothing waits on a version, and no shaped ships in one release rather than a string of them: nothing waits on a version, and no
@@ -36,7 +37,25 @@ head (2026-09-20). They read ahead of 6, 7 and 10 because every one of them is c
HTML format lands than after: 19 and 20 because HTML has no answer without them, 21 to 24 because HTML format lands than after: 19 and 20 because HTML has no answer without them, 21 to 24 because
HTML doubles the importers and the file count they touch, and 25 to 27 because they are what the HTML doubles the importers and the file count they touch, and 25 to 27 because they are what the
panel says the next reader pays for. 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.
- [ ] **29 — Goal 3 names the whole of the exception (`0.2.0`).** README §Goals 3 says "the three
carve-outs and the one gap below are the whole of the exception", and §The guarantees says
"apart from the raw HTML below, with three carve-outs … and one gap". Raw HTML is a fourth
exception, the commonest one in markdown written elsewhere, and `unmappable-html` refuses it
today. Name it in the goal, or stop enumerating there. Settle at the same time whether the
goal is written for `0.2.0`, where the element mapping the error text promises could make
raw HTML convert — the answer decides which repair is the true one, so it is the
maintainer's.
- [ ] **30 — AGENTS.md says each thing once (`0.2.0`).** §15's ask protocol — name the class, cite
the earlier asks of it, never "A or B?" — is the rule reviewers cite most and has no heading,
two thirds down a 50-line section in a file with no index. Give it one. §15 also offers "the
gate's seconds" as a stated number that is kept, and no such number is stated anywhere, §14
forbidding the category outright; drop the example. Then the restatements: §15 repeats the
one-chunk rule three times and `version`/`NPM_TOKEN` twice, §12 says the default is delete
twice, and §5's "few, each earning its keep; they never reach a consumer" is npm's own
definition of the field. Cut to one copy each, the one carrying the why.
- [ ] **19 — A home for what both formats read (`0.2.0`).** Settle where a construct both formats - [ ] **19 — A home for what both formats read (`0.2.0`).** Settle where a construct both formats
need lives, and say so in AGENTS.md §11. Today `adf/` may hold no format knowledge and each need lives, and say so in AGENTS.md §11. Today `adf/` may hold no format knowledge and each
format directory holds its own shared layer, so there is no third place; the first ADF-shaped format directory holds its own shared layer, so there is no third place; the first ADF-shaped
@@ -253,18 +272,7 @@ panel says the next reader pays for.
- [x] **14 — The CommonMark subset's directory (`0.2.0`).** - [x] **14 — The CommonMark subset's directory (`0.2.0`).**
- [x] **15 — The href-less directive link (`0.2.0`).** - [x] **15 — The href-less directive link (`0.2.0`).**
- [x] **16 — The link wrapping a link (`0.2.0`).** - [x] **16 — The link wrapping a link (`0.2.0`).**
- [ ] **17 — A machine-enforced size ratchet (`0.2.0`).** Add a per-function line ceiling to the - [x] **17 — A machine-enforced size ratchet (`0.2.0`).**
gate, set at today's worst and only ever moving down, so the largest body of new code cannot
exceed what is already here (the systems-architect, 2026-09-16; narrowed by the comprehension
panel, 2026-09-20). oxlint's `eslint/max-lines-per-function` measures it — one devDependency,
carrying the musl binding the gate's image needs, since TypeScript 7 is the native compiler
and exposes no parser to write the check against. No cyclomatic rule: `eslint/complexity`
charges `?.` and `??` a point each, the guards §10 already exempts from the branch floor, and
its two worst functions, `readBlockLine` and `parseInline`, went unnamed by all nine readers
while `isNodeArray` and `blockNode` were volunteered as among the clearest code here. Length
ranks no better: `emitList` and `blockNode` are both 26 lines, one the panel's unanimous top
four and the other the clearest map of the format in the repo. So the ceiling guards against
drift and never drives a refactor — 19 to 27 are where the hard work actually is.
- [x] **18 — The subtree the directive spelling asks about (`0.2.0`).** - [x] **18 — The subtree the directive spelling asks about (`0.2.0`).**
- [x] **28 — `emitLine`'s retry loop cannot spin (`0.2.0`).** - [x] **28 — `emitLine`'s retry loop cannot spin (`0.2.0`).**