@nielspeter/eess-md 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/conditions/resolve.d.ts +20 -1
- package/dist/conditions/resolve.d.ts.map +1 -1
- package/dist/conditions/resolve.js +63 -2
- package/dist/conditions/resolve.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/ledger.d.ts +110 -0
- package/dist/rules/ledger.d.ts.map +1 -1
- package/dist/rules/ledger.js +264 -39
- package/dist/rules/ledger.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @nielspeter/eess-md
|
|
2
2
|
|
|
3
|
-
Architecture testing for a **Markdown corpus** — the Markdown dialect of the [eess](
|
|
3
|
+
Architecture testing for a **Markdown corpus** — the Markdown dialect of the [eess](https://github.com/nielspeter/eess/blob/main/README.md) family. _Specifications you can run._
|
|
4
4
|
|
|
5
|
-
A repo's markdown (docs, ADRs, plans) should stay honest: cross-links resolve, code pointers point at real lines, and — if you use them — ADRs declare how they're enforced. `eess-md` validates all of that on the shared [`@nielspeter/eess`](
|
|
5
|
+
A repo's markdown (docs, ADRs, plans) should stay honest: cross-links resolve, code pointers point at real lines, and — if you use them — ADRs declare how they're enforced. `eess-md` validates all of that on the shared [`@nielspeter/eess`](https://www.npmjs.com/package/@nielspeter/eess) kernel, so you write a declarative rules file, not a custom validator script.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -47,8 +47,7 @@ selection into one side of a `correspondence()`. Bind a table to what it
|
|
|
47
47
|
describes and drift in either direction fails the build:
|
|
48
48
|
|
|
49
49
|
```typescript
|
|
50
|
-
import { corpus, rows } from '@nielspeter/eess-md'
|
|
51
|
-
import { correspondence } from '@nielspeter/eess'
|
|
50
|
+
import { corpus, rows, correspondence } from '@nielspeter/eess-md'
|
|
52
51
|
|
|
53
52
|
const c = corpus({ roots: ['README.md'] })
|
|
54
53
|
|
|
@@ -61,8 +60,15 @@ const packageRows = rows(c, {
|
|
|
61
60
|
identify: (r) => ({ name: r.get('pkg'), file: r.doc.relPath, line: r.line }),
|
|
62
61
|
})
|
|
63
62
|
|
|
64
|
-
// `workspacePackages` is a plain Selection you build from the filesystem
|
|
65
|
-
|
|
63
|
+
// `workspacePackages` is a plain Selection you build from the filesystem —
|
|
64
|
+
// keyBy omitted: it defaults to each side's own identify().name
|
|
65
|
+
const workspacePackages = {
|
|
66
|
+
elements: [] as { name: string }[],
|
|
67
|
+
label: 'workspace package',
|
|
68
|
+
identify: (p: { name: string }) => ({ name: p.name }),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
correspondence({ left: packageRows, right: workspacePackages })
|
|
66
72
|
.should()
|
|
67
73
|
.beComplete({ direction: 'both' }) // every row has a package AND vice versa
|
|
68
74
|
.because('the README package table must not drift from the workspace')
|
|
@@ -25,12 +25,31 @@ export interface LinkResolveOptions {
|
|
|
25
25
|
* resolution is still tried first, so plain repo-absolute links keep working.
|
|
26
26
|
*/
|
|
27
27
|
readonly rootDir?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a link naming a real directory (`./fixed/` or `./fixed`, with or
|
|
30
|
+
* without the trailing slash — both forms occur in this repo's own corpus)
|
|
31
|
+
* even when it has no index file. Correct for a repo-hosted corpus (GitHub,
|
|
32
|
+
* GitLab render a directory link as its listing); wrong for a static-site
|
|
33
|
+
* corpus where a bare directory is not itself a page — there, reach for
|
|
34
|
+
* {@link tryIndex} instead. Off by default: this widens what "resolves"
|
|
35
|
+
* means, and a link resolving that shouldn't is a false green, not a
|
|
36
|
+
* convenience. Default `false`.
|
|
37
|
+
*
|
|
38
|
+
* A link naming a real directory always wins over an unrelated typo — if
|
|
39
|
+
* `./foo` was meant as a deleted `foo.md` but a directory `foo/` happens to
|
|
40
|
+
* exist at that path, it resolves as the directory. Not a new failure mode:
|
|
41
|
+
* GitHub renders that link as the directory listing too, so this only
|
|
42
|
+
* closes the gap between the gate and what the link actually does when
|
|
43
|
+
* followed, it doesn't introduce a new way to be surprised by it.
|
|
44
|
+
*/
|
|
45
|
+
readonly resolveDirectories?: boolean;
|
|
28
46
|
}
|
|
29
47
|
/**
|
|
30
48
|
* Condition: every (internal) link resolves to a file in the corpus's repo tree.
|
|
31
49
|
* Closes over the `Corpus` for the file index. External links and pure anchors
|
|
32
50
|
* are skipped. `options` adds extensionless-link resolution (`tryExtensions`,
|
|
33
|
-
* `tryIndex`) for static-site corpora
|
|
51
|
+
* `tryIndex`) for static-site corpora, and directory resolution
|
|
52
|
+
* (`resolveDirectories`) for repo-hosted ones.
|
|
34
53
|
*/
|
|
35
54
|
export declare function linkResolves(corpus: Corpus, options?: LinkResolveOptions): Condition<MdLink>;
|
|
36
55
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAG/C;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAG/C;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CACtC;AA8DD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,SAAS,CAAC,MAAM,CAAC,CAyEhG"}
|
|
@@ -32,11 +32,38 @@ function candidates(target, options) {
|
|
|
32
32
|
}
|
|
33
33
|
return out;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Every known directory reachable from `fileIndex`'s files, derived from it
|
|
37
|
+
* rather than new I/O: each indexed file's ancestors are known directories.
|
|
38
|
+
* `fileIndex` itself spans the whole physical repo walk from `cwd`, not just
|
|
39
|
+
* the corpus's configured `roots` (`roots` only filters which files become
|
|
40
|
+
* *documents* — see `corpus()`), so a directory link can resolve against
|
|
41
|
+
* something outside any configured root. Built only when `resolveDirectories`
|
|
42
|
+
* is on — the cost of a directory-shaped link resolving is opt-in, so is the
|
|
43
|
+
* cost of computing it.
|
|
44
|
+
*
|
|
45
|
+
* The repo root itself (`.`) is deliberately excluded — `[root](/)` still
|
|
46
|
+
* won't resolve even with the option on. Nobody links "the whole repo," and
|
|
47
|
+
* `resolveTargets` never had a resolvable shape for it before this option
|
|
48
|
+
* existed either.
|
|
49
|
+
*/
|
|
50
|
+
function directoryIndex(corpus) {
|
|
51
|
+
const dirs = new Set();
|
|
52
|
+
for (const rel of corpus.fileIndex) {
|
|
53
|
+
let dir = posix.dirname(rel);
|
|
54
|
+
while (dir !== '.' && dir !== '/' && !dirs.has(dir)) {
|
|
55
|
+
dirs.add(dir);
|
|
56
|
+
dir = posix.dirname(dir);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return dirs;
|
|
60
|
+
}
|
|
35
61
|
/**
|
|
36
62
|
* Condition: every (internal) link resolves to a file in the corpus's repo tree.
|
|
37
63
|
* Closes over the `Corpus` for the file index. External links and pure anchors
|
|
38
64
|
* are skipped. `options` adds extensionless-link resolution (`tryExtensions`,
|
|
39
|
-
* `tryIndex`) for static-site corpora
|
|
65
|
+
* `tryIndex`) for static-site corpora, and directory resolution
|
|
66
|
+
* (`resolveDirectories`) for repo-hosted ones.
|
|
40
67
|
*/
|
|
41
68
|
export function linkResolves(corpus, options = {}) {
|
|
42
69
|
// Basename → repo files, for finding a uniquely-moved target of a broken link.
|
|
@@ -49,6 +76,33 @@ export function linkResolves(corpus, options = {}) {
|
|
|
49
76
|
else
|
|
50
77
|
byBasename.set(base, [rel]);
|
|
51
78
|
}
|
|
79
|
+
const dirIndex = options.resolveDirectories === true ? directoryIndex(corpus) : undefined;
|
|
80
|
+
// Bug 0137: a link that names a real directory and one that names nothing
|
|
81
|
+
// at all both reported the identical "does not resolve" message — no hint
|
|
82
|
+
// that `resolveDirectories` exists, or that this specific target would
|
|
83
|
+
// resolve with it on. Built lazily (at most once, memoized) rather than
|
|
84
|
+
// unconditionally alongside `dirIndex`, so the happy path (no violations)
|
|
85
|
+
// never pays for it, and only when `resolveDirectories` is already off —
|
|
86
|
+
// when it's on, a real directory already resolved above and can't reach
|
|
87
|
+
// this branch at all.
|
|
88
|
+
//
|
|
89
|
+
// A site-absolute link with `rootDir` set yields two candidates
|
|
90
|
+
// (repo-root, then content-root — see `resolveTargets`), and either can
|
|
91
|
+
// independently be a real directory. Reporting whichever comes first
|
|
92
|
+
// unlabelled can name the *wrong* one: a repo-root directory that happens
|
|
93
|
+
// to share a name with the intended content-root page sends the author to
|
|
94
|
+
// toggle `resolveDirectories`, which would resolve the unrelated
|
|
95
|
+
// repo-root directory, not fix their actual (still-missing) page. Labelled
|
|
96
|
+
// only when there are two candidates to disambiguate between — the common,
|
|
97
|
+
// single-target case (no `rootDir`) is unaffected.
|
|
98
|
+
let diagnosticDirIndex;
|
|
99
|
+
const directoryHint = (target, label) => {
|
|
100
|
+
diagnosticDirIndex ??= directoryIndex(corpus);
|
|
101
|
+
const bare = target.replace(/\/+$/, '');
|
|
102
|
+
return diagnosticDirIndex.has(bare)
|
|
103
|
+
? ` — "${bare}"${label} is a real directory; this check runs with resolveDirectories off`
|
|
104
|
+
: '';
|
|
105
|
+
};
|
|
52
106
|
return {
|
|
53
107
|
description: 'resolve to an existing file',
|
|
54
108
|
evaluate: (links, ctx) => links.flatMap((link) => {
|
|
@@ -59,12 +113,19 @@ export function linkResolves(corpus, options = {}) {
|
|
|
59
113
|
return [];
|
|
60
114
|
if (targets.some((t) => candidates(t, options).some((c) => corpus.fileIndex.has(c))))
|
|
61
115
|
return [];
|
|
116
|
+
if (dirIndex !== undefined && targets.some((t) => dirIndex.has(t.replace(/\/+$/, ''))))
|
|
117
|
+
return [];
|
|
118
|
+
const hint = options.resolveDirectories === true
|
|
119
|
+
? ''
|
|
120
|
+
: (targets
|
|
121
|
+
.map((t, i) => directoryHint(t, targets.length > 1 ? (i === 0 ? ' (repo-root)' : ' (content-root)') : ''))
|
|
122
|
+
.find((h) => h) ?? '');
|
|
62
123
|
return [
|
|
63
124
|
mdViolation({
|
|
64
125
|
element: `${link.doc.relPath} → ${link.url}`,
|
|
65
126
|
file: link.doc.file,
|
|
66
127
|
line: link.line,
|
|
67
|
-
message: `broken link: "${link.url}" does not resolve to a file in the repo`,
|
|
128
|
+
message: `broken link: "${link.url}" does not resolve to a file in the repo${hint}`,
|
|
68
129
|
sourceText: link.doc.text,
|
|
69
130
|
fix: movedLinkFix(link, byBasename),
|
|
70
131
|
context: ctx,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAIjC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAIjC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AA8CnD;;;;;GAKG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,OAA2B;IAC/D,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACpD,IAAI,eAAe,KAAK,EAAE;QAAE,OAAO,EAAE,CAAA,CAAC,uBAAuB;IAC7D,MAAM,OAAO,GAAG,kBAAkB,CAAC,eAAe,CAAC,CAAA;IACnD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;QAC/D,OAAO,OAAO,CAAC,OAAO,KAAK,SAAS;YAClC,CAAC,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;YACxE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC5C,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;AACrD,CAAC;AAED,yEAAyE;AACzE,SAAS,UAAU,CAAC,MAAc,EAAE,OAA2B;IAC7D,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;IACpB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACvC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;QAC9C,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAA;IACtB,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC5B,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACb,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,UAA8B,EAAE;IAC3E,+EAA+E;IAC/E,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;QAChD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;;YACnB,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IAClC,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAkB,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEzF,0EAA0E;IAC1E,0EAA0E;IAC1E,uEAAuE;IACvE,wEAAwE;IACxE,0EAA0E;IAC1E,yEAAyE;IACzE,wEAAwE;IACxE,sBAAsB;IACtB,EAAE;IACF,gEAAgE;IAChE,wEAAwE;IACxE,qEAAqE;IACrE,0EAA0E;IAC1E,0EAA0E;IAC1E,iEAAiE;IACjE,2EAA2E;IAC3E,2EAA2E;IAC3E,mDAAmD;IACnD,IAAI,kBAAmD,CAAA;IACvD,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,KAAa,EAAU,EAAE;QAC9D,kBAAkB,KAAK,cAAc,CAAC,MAAM,CAAC,CAAA;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACvC,OAAO,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,OAAO,IAAI,IAAI,KAAK,mEAAmE;YACzF,CAAC,CAAC,EAAE,CAAA;IACR,CAAC,CAAA;IAED,OAAO;QACL,WAAW,EAAE,6BAA6B;QAC1C,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CACvB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,IAAI,IAAI,CAAC,QAAQ;gBAAE,OAAO,EAAE,CAAA;YAC5B,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAA;YACnC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClF,OAAO,EAAE,CAAA;YACX,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;gBACpF,OAAO,EAAE,CAAA;YACX,MAAM,IAAI,GACR,OAAO,CAAC,kBAAkB,KAAK,IAAI;gBACjC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,CAAC,OAAO;qBACL,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACZ,aAAa,CACX,CAAC,EACD,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CACzE,CACF;qBACA,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9B,OAAO;gBACL,WAAW,CAAC;oBACV,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE;oBAC5C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;oBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,iBAAiB,IAAI,CAAC,GAAG,2CAA2C,IAAI,EAAE;oBACnF,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;oBACzB,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC;oBACnC,OAAO,EAAE,GAAG;iBACb,CAAC;aACH,CAAA;QACH,CAAC,CAAC;KACL,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,UAAiC;IACnE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA,CAAC,kBAAkB;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACtE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA,CAAC,2CAA2C;IACtF,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACzB,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC1C,IAAI,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAA;IACjE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;IAC1C,MAAM,WAAW,GAAG,GAAG,GAAG,QAAQ,CAAA;IAClC,IAAI,WAAW,KAAK,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAA;IAC9C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;QACnB,KAAK,EAAE,IAAI,CAAC,QAAQ;QACpB,GAAG,EAAE,IAAI,CAAC,MAAM;QAChB,WAAW;QACX,QAAQ,EAAE,iBAAiB,IAAI,CAAC,GAAG,QAAQ,WAAW,GAAG;KAC1D,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { corpus } from './corpus.js';
|
|
2
2
|
export type { CorpusOptions, Corpus } from './corpus.js';
|
|
3
|
+
export type { Predicate, Condition, ConditionContext, ArchFix, PresetReportOptions, PresetBaseOptions, } from '@nielspeter/eess';
|
|
4
|
+
export { RuleBuilder, finishPreset, generateCodeFrame, not, dispatchRule, validateOverrides, } from '@nielspeter/eess';
|
|
5
|
+
export { correspondence, CorrespondenceBuilder } from '@nielspeter/eess';
|
|
3
6
|
export type { MdDocument, MdSection, MdTable, MdCodeBlock } from './model/document.js';
|
|
4
7
|
export type { MdRow, ColumnSpec, RowMatchOptions, RowMatchMode } from './model/rows.js';
|
|
5
8
|
export { matchTableRows } from './model/rows.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOxD,YAAY,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,OAAO,EACP,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,GAAG,EACH,YAAY,EACZ,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AASzB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAGxE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtF,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC5D,YAAY,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACrE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACzE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC7E,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAGnG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAClE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA;AACpE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
// from `@nielspeter/eess-md/rules/adr`.
|
|
7
7
|
// Corpus loader
|
|
8
8
|
export { corpus } from './corpus.js';
|
|
9
|
+
export { RuleBuilder, finishPreset, generateCodeFrame, not, dispatchRule, validateOverrides, } from '@nielspeter/eess';
|
|
10
|
+
// `correspondence`/`CorrespondenceBuilder`: not touched by this package's
|
|
11
|
+
// OWN source (so the family.rules.ts code-import scan can't see this gap —
|
|
12
|
+
// review found it manually), but this README's own "Binding a spec table to
|
|
13
|
+
// code" example, and docs/markdown.md's equivalent, both teach
|
|
14
|
+
// `rows()` + `correspondence()` as the flagship way to bind a markdown table
|
|
15
|
+
// to code — without this re-export, that documented example does not
|
|
16
|
+
// compile against @nielspeter/eess-md alone, the exact second-install this
|
|
17
|
+
// plan exists to close.
|
|
18
|
+
export { correspondence, CorrespondenceBuilder } from '@nielspeter/eess';
|
|
9
19
|
export { matchTableRows } from './model/rows.js';
|
|
10
20
|
// Entry points
|
|
11
21
|
export { docs, DocsRuleBuilder } from './builders/docs.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,wCAAwC;AAExC,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,wCAAwC;AAExC,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAgBpC,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,GAAG,EACH,YAAY,EACZ,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AAC/D,6EAA6E;AAC7E,qEAAqE;AACrE,2EAA2E;AAC3E,wBAAwB;AACxB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAKxE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGhD,eAAe;AACf,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG5D,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAEtE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAG7E,oDAAoD;AACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA"}
|
package/dist/rules/ledger.d.ts
CHANGED
|
@@ -19,6 +19,17 @@ import type { ArchViolation } from '../model/violation.js';
|
|
|
19
19
|
* `collectTaskItems`), so a `- [ ]` in fenced code or a blockquote is excluded
|
|
20
20
|
* for free — no hand-rolled stripping. `deferred: none` summaries and the
|
|
21
21
|
* `State:` header token are unambiguous prose lines, scanned from the source.
|
|
22
|
+
*
|
|
23
|
+
* **Expressed through the builder DSL** (bug 0131, closed by plan 0101 Phase 1):
|
|
24
|
+
* previously this preset hand-iterated `corpus.documents()` directly, calling
|
|
25
|
+
* no `RuleBuilder`/`TerminalBuilder` at all — invisible to every kernel-level
|
|
26
|
+
* guarantee, including the ADR-010 evidence gate the fold (plan 0088) landed.
|
|
27
|
+
* `docs(corpus)` and `taskItems(corpus)` already existed and already
|
|
28
|
+
* `extends RuleBuilder<T, Corpus>` — the detection logic below is unchanged
|
|
29
|
+
* from the pre-fold version (same regexes, same `findState`/`isDoneItem`
|
|
30
|
+
* helpers, same messages), only its *iteration* now goes through the DSL, so
|
|
31
|
+
* this preset inherits the fold's fail-closed floor like every sibling
|
|
32
|
+
* builder-based rule already does.
|
|
22
33
|
*/
|
|
23
34
|
export interface HonestyAtCloseOptions extends PresetReportOptions {
|
|
24
35
|
/**
|
|
@@ -47,11 +58,108 @@ export interface HonestyAtCloseOptions extends PresetReportOptions {
|
|
|
47
58
|
* whether or not they also appear in {@link states}.
|
|
48
59
|
*/
|
|
49
60
|
readonly terminalStates?: readonly string[];
|
|
61
|
+
/**
|
|
62
|
+
* Declare that this corpus may legitimately hold zero non-board documents
|
|
63
|
+
* right now — a freshly-bootstrapped lane before its first real item is
|
|
64
|
+
* authored (e.g. a `kit/`-seeded `work/plans/` containing only
|
|
65
|
+
* `ROADMAP.md`). Default `false`: an empty non-board selection is treated
|
|
66
|
+
* as a dead selector (wrong glob, broken `boardFiles`) and reported.
|
|
67
|
+
*
|
|
68
|
+
* This is a genuine, caller-declared claim, not something `honestyAtClose`
|
|
69
|
+
* can infer — nothing else in the corpus distinguishes "nothing authored
|
|
70
|
+
* yet" from "the selector broke." Per ADR-010 it **expires**: the day a
|
|
71
|
+
* real document appears, `examined > 0` while this is still declared `true`
|
|
72
|
+
* is itself reported ("the declaration has expired"), so remove it once
|
|
73
|
+
* the lane has real content.
|
|
74
|
+
*/
|
|
75
|
+
readonly expectEmptyHeaders?: boolean;
|
|
50
76
|
}
|
|
51
77
|
/**
|
|
52
78
|
* Run the honesty-at-close gate over a corpus. Throws `ArchRuleError` on any
|
|
53
79
|
* finding. Placement is checked on every item; ledger reconciliation only on
|
|
54
80
|
* done-items (the inverse of the frozen-folder exemption).
|
|
81
|
+
*
|
|
82
|
+
* Three builder-based rules, merged: header state↔folder (`docs()`), silent
|
|
83
|
+
* open boxes (`taskItems()`, filtered to done-items), and the deferred-none
|
|
84
|
+
* lie (`docs()`, filtered to done-items carrying a deferred-disposed box).
|
|
85
|
+
*
|
|
86
|
+
* **Emptiness declarations, and why each is shaped the way it is** (bug 0131
|
|
87
|
+
* follow-up, six-persona review before this landed): `.expectEmpty()` is only
|
|
88
|
+
* a sound fail-closed gate when the thing that decides *whether* to declare
|
|
89
|
+
* it is independent of the predicate the declaration would otherwise let
|
|
90
|
+
* pass silently. Two designs were tried and rejected for this reason:
|
|
91
|
+
*
|
|
92
|
+
* 1. Peeking the exact same selection each rule gates (`.select()` on
|
|
93
|
+
* `openBoxesOnDoneItems`/`doneItemsWithDeferredBox` themselves) before
|
|
94
|
+
* conditionally declaring `.expectEmpty()`. This *reads* as a live check
|
|
95
|
+
* but is circular: the peek and the real run filter the identical
|
|
96
|
+
* elements through the identical predicates with nothing in between, so
|
|
97
|
+
* the declaration is always self-consistent and can never expire — it
|
|
98
|
+
* provides zero protection against exactly the corruption class ADR-010
|
|
99
|
+
* exists to catch, for either rule.
|
|
100
|
+
* 2. Gating on `terminalStates.length === 0` alone. Correct for the
|
|
101
|
+
* always-structurally-empty `proposals` lane, but too narrow: it doesn't
|
|
102
|
+
* cover a plan/bug lane's own test fixtures that legitimately have zero
|
|
103
|
+
* done-items in a given run (e.g. a single-document fixture testing an
|
|
104
|
+
* unrelated placement rule).
|
|
105
|
+
* 3. Gating both rules on one coarse "any done item exists in this corpus"
|
|
106
|
+
* signal. Independent of the right predicate, but the wrong *scope*: most
|
|
107
|
+
* done items carry zero open boxes and zero deferred boxes — that's the
|
|
108
|
+
* normal, healthy, permanent state for a reconciled item, not a corner
|
|
109
|
+
* case — so "a done item exists" routinely holds while the real selection
|
|
110
|
+
* (open boxes on it, or a deferred box on it) is legitimately empty. That
|
|
111
|
+
* false-positived on the project's own `fixed/green-bug-closed.md` fixture
|
|
112
|
+
* (a done item with one already-checked box, no open boxes at all).
|
|
113
|
+
*
|
|
114
|
+
* The fix: peek `openTaskItems` once (`taskItems(corpus).that().areOpen()`,
|
|
115
|
+
* a purely structural filter, no done-item check), then derive each rule's
|
|
116
|
+
* own emptiness signal from *that*, narrowed to what the rule actually
|
|
117
|
+
* selects, while staying independent of the specific predicate/function
|
|
118
|
+
* being protected:
|
|
119
|
+
*
|
|
120
|
+
* - `silentOpenBoxViolations` is gated by `belongsToADoneItem`. Its peek
|
|
121
|
+
* (`anyOpenBoxOnADoneItem`) calls `isDoneItem` on `openTaskItems` directly
|
|
122
|
+
* — not through `belongsToADoneItem` — so a corruption of that predicate
|
|
123
|
+
* specifically doesn't also blind the peek.
|
|
124
|
+
* - `deferredLieViolations`'s selection adds `hasDeferredDisposedBox` (which
|
|
125
|
+
* walks each done document's own mdast via a separate
|
|
126
|
+
* `collectTaskItems(doc.root)` call) on top of `isDoneItemPredicate`. Its
|
|
127
|
+
* peek (`anyDeferredDisposedBoxOnADoneItem`) instead re-tests
|
|
128
|
+
* `openTaskItems` (a different traversal) against the same
|
|
129
|
+
* `DEFERRED_DISPOSITION_RE` constant `hasDeferredDisposedBox` uses — so a
|
|
130
|
+
* corruption of `hasDeferredDisposedBox`'s own body doesn't blind this
|
|
131
|
+
* peek either.
|
|
132
|
+
*
|
|
133
|
+
* Both peeks share `isDoneItem` and the underlying `collectTaskItems` box
|
|
134
|
+
* collection with the very selections they protect — a corruption isolated to
|
|
135
|
+
* either would defeat both peek and real selection identically, uniformly,
|
|
136
|
+
* for every lane. This is a real residual gap, not a narrow one: verified by
|
|
137
|
+
* sabotaging `isDoneItem` against this repo's own real corpus during bug
|
|
138
|
+
* 0131's round-2 review, which produced **zero violations, exit 0** — not a
|
|
139
|
+
* partial miss. `headerStateCondition` does **not** independently backstop
|
|
140
|
+
* this (an earlier draft of this comment claimed it "would likely also
|
|
141
|
+
* surface through `headerViolations`" — false: `headerStateCondition` never
|
|
142
|
+
* calls `isDoneItem`, it recomputes the folder half of the same determination
|
|
143
|
+
* inline, so it only catches a corruption if a live state/folder mismatch
|
|
144
|
+
* already exists in the scanned corpus, which it usually doesn't).
|
|
145
|
+
*
|
|
146
|
+
* `honestyAtClose` itself can't close this gap generically — a corpus with
|
|
147
|
+
* zero done-items is legitimate on a freshly-bootstrapped lane's first day,
|
|
148
|
+
* so a library-level "zero done-items across the whole call is always wrong"
|
|
149
|
+
* assertion would be exactly the false-positive class `expectEmptyHeaders`
|
|
150
|
+
* exists to avoid. What closes it is caller knowledge: **a corpus with an
|
|
151
|
+
* established history should assert its own "zero done-items is never
|
|
152
|
+
* legitimate here" claim on top.** `scripts/check-ledger.mjs` (this repo's
|
|
153
|
+
* own wiring) does exactly that — 0 done-items summed across every lane fails
|
|
154
|
+
* the build, because this repo has carried done-items in every
|
|
155
|
+
* terminal-states lane for its entire history. A `kit/`-seeded caller with no
|
|
156
|
+
* history yet should not copy that assertion verbatim; it becomes true, and
|
|
157
|
+
* worth adding, once the corpus has one.
|
|
158
|
+
*
|
|
159
|
+
* `headerViolations` gets no computed declaration — nothing in the corpus
|
|
160
|
+
* can tell "no non-board documents authored yet" apart from "the selector
|
|
161
|
+
* broke." Callers who know the former is legitimate (a freshly-bootstrapped
|
|
162
|
+
* lane) opt in explicitly via {@link HonestyAtCloseOptions.expectEmptyHeaders}.
|
|
55
163
|
*/
|
|
56
164
|
export declare function honestyAtClose(corpus: Corpus, options?: HonestyAtCloseOptions): ArchViolation[];
|
|
57
165
|
/** What a {@link honestyAtClose} run actually examined. */
|
|
@@ -77,6 +185,8 @@ export interface LedgerStats {
|
|
|
77
185
|
* Callers must not re-derive it. `check-ledger.mjs` did, with a copy of the very
|
|
78
186
|
* expression 0119 removed, and its copy disagreed with the preset on 56 of 56
|
|
79
187
|
* records while heading a section captioned "so a green is provably non-vacuous".
|
|
188
|
+
*
|
|
189
|
+
* Pure read-only counting, not a rule — no evidence gate applies here.
|
|
80
190
|
*/
|
|
81
191
|
export declare function ledgerStats(corpus: Corpus, options?: HonestyAtCloseOptions): LedgerStats;
|
|
82
192
|
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/rules/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/rules/ledger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAK1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CACtC;AAmVD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,aAAa,EAAE,CAyEjB;AAED,2DAA2D;AAC3D,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,qFAAqF;IACrF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,WAAW,CAqB5F"}
|
package/dist/rules/ledger.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { finishPreset } from '@nielspeter/eess';
|
|
2
2
|
import { collectTaskItems } from '../model/task-items.js';
|
|
3
|
+
import { docs } from '../builders/docs.js';
|
|
4
|
+
import { taskItems } from '../builders/task-items.js';
|
|
3
5
|
const DEFAULT_DONE_FOLDERS = ['/completed/', '/fixed/', '/wont-do/', '/delivered/', '/archived/'];
|
|
4
6
|
const DEFAULT_BOARD_FILES = ['ROADMAP.md', 'BUGS.md', 'REFINEMENT.md', 'SUPPORT.md', 'README.md'];
|
|
5
7
|
const DEFAULT_STATES = ['Draft', 'Ready', 'Open', 'Done', "Won't-do"];
|
|
@@ -28,8 +30,21 @@ const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
|
28
30
|
* apostrophe accepts either glyph (an editor smart-quoting `Won't-do` should not
|
|
29
31
|
* break a build over two near-identical characters), and matching is
|
|
30
32
|
* case-insensitive with the declared spelling returned as canonical.
|
|
33
|
+
*
|
|
34
|
+
* An empty `states` must never match — a lane with no known/terminal
|
|
35
|
+
* vocabulary (`terminalStates: []`, a legitimate config: bug 0121's
|
|
36
|
+
* `proposals` lane, where nothing is ledger-closed by design) is a real,
|
|
37
|
+
* supported input, not a caller error. Naively joining zero alternatives
|
|
38
|
+
* makes the capture group `()`, a zero-width match that fires at almost any
|
|
39
|
+
* position — `findState` would then read every `State:`-shaped line as
|
|
40
|
+
* "readable, value ''" instead of falling through to the `UNREADABLE_RE`
|
|
41
|
+
* fallback, silently miscounting `withReadableState`/`unreadableState` and
|
|
42
|
+
* (for `isDoneItem`, which calls this with `terminalStates` directly) relying
|
|
43
|
+
* on `[].includes('')` being `false` by accident rather than by design.
|
|
31
44
|
*/
|
|
32
45
|
function stateMatcher(states) {
|
|
46
|
+
if (states.length === 0)
|
|
47
|
+
return /(?!)/; // never matches: forces the UNREADABLE_RE fallback
|
|
33
48
|
const alts = [...states]
|
|
34
49
|
.sort((a, b) => b.length - a.length)
|
|
35
50
|
.map((s) => escapeRe(s).replace(/['’]/g, "['’]"))
|
|
@@ -129,40 +144,203 @@ function headerStateViolation(doc, inDoneFolder, closeInPlace, states, terminalS
|
|
|
129
144
|
}
|
|
130
145
|
return null;
|
|
131
146
|
}
|
|
132
|
-
/**
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
/** A box's disposition is disclosed, or it is a silent open box. */
|
|
148
|
+
function isDisposed(boxText) {
|
|
149
|
+
return DISPOSITION_RE.test(boxText);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Does this document carry at least one open box disposed as `deferred→<home>`?
|
|
153
|
+
*
|
|
154
|
+
* A corruption here (always `false`) is caught by
|
|
155
|
+
* `scripts/nonvacuity/bad-ledger.mjs`'s `completed/0005-deferred-none-lie.md`
|
|
156
|
+
* fixture (bug 0131 round-2 review) — before it existed, no fixture in that
|
|
157
|
+
* corpus carried a `deferred→<home>` box at all, so this function's only
|
|
158
|
+
* "protection" was this repo's own live corpus incidentally carrying one,
|
|
159
|
+
* which would have silently vanished the day that box got resolved.
|
|
160
|
+
*/
|
|
161
|
+
function hasDeferredDisposedBox(doc) {
|
|
162
|
+
return collectTaskItems(doc.root).some((box) => !box.checked && DEFERRED_DISPOSITION_RE.test(box.text));
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* A `none` deferral-summary while the document carries a box disposed as
|
|
166
|
+
* `deferred→<home>` — the summary contradicts the boxes. Absence of a summary
|
|
167
|
+
* is deliberately NOT gated; only a *contradicting* one is.
|
|
168
|
+
*/
|
|
169
|
+
function deferredNoneLieViolation(doc) {
|
|
170
|
+
const lines = stripFencedCode(doc.text).split('\n');
|
|
171
|
+
for (let i = 0; i < lines.length; i++) {
|
|
172
|
+
const raw = lines[i] ?? '';
|
|
173
|
+
if (/^\s*>/.test(raw))
|
|
174
|
+
continue;
|
|
175
|
+
const sm = raw.match(DEFERRED_SUMMARY_RE);
|
|
176
|
+
if (sm && /^none\b/i.test((sm[1] ?? '').trim())) {
|
|
177
|
+
return v('ledger/deferred-none-lie', doc, i + 1, "'deferred: none' contradicts a box disposed as deferred→<home>", 'the out-loud summary must reconcile with the box states, not override them');
|
|
143
178
|
}
|
|
144
179
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
/** Predicate: not a board/index file (never scanned as an item). */
|
|
183
|
+
function notBoardFile(boardFiles) {
|
|
184
|
+
return {
|
|
185
|
+
description: 'is not a board file',
|
|
186
|
+
test: (doc) => !boardFiles.has(doc.relPath.split('/').pop() ?? doc.relPath),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/** Predicate: this document is a done-item under the caller's own vocabulary. */
|
|
190
|
+
function isDoneItemPredicate(doneFolders, terminalStates) {
|
|
191
|
+
return {
|
|
192
|
+
description: 'is a done item',
|
|
193
|
+
test: (doc) => isDoneItem(doc, doneFolders, terminalStates),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Predicate: this task item's own document is a done-item.
|
|
198
|
+
*
|
|
199
|
+
* A corruption here (always `false`) is caught not by a purpose-built
|
|
200
|
+
* fixture but as a side effect of `ledger.test.ts`'s pre-existing
|
|
201
|
+
* `flags a silent open box in a done-item (red)` /
|
|
202
|
+
* `passes a done-item whose every open box is disposed (green)` pair, and of
|
|
203
|
+
* `scripts/nonvacuity/bad-ledger.mjs`'s `completed/0001-silent-open-box.md`
|
|
204
|
+
* fixture — both keep a real open box on a real done-item in the corpus, the
|
|
205
|
+
* exact shape `honestyAtClose`'s independent `anyOpenBoxOnADoneItem` peek
|
|
206
|
+
* (see its docstring) needs to diverge from a corrupted `belongsToADoneItem`.
|
|
207
|
+
* Simplifying either fixture to drop that box, even for reasons unrelated to
|
|
208
|
+
* this concern, would silently regress the coverage.
|
|
209
|
+
*/
|
|
210
|
+
function belongsToADoneItem(doneFolders, terminalStates) {
|
|
211
|
+
return {
|
|
212
|
+
description: 'belongs to a done item',
|
|
213
|
+
test: (t) => isDoneItem(t.doc, doneFolders, terminalStates),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/** Condition: the header `State:` line is readable and matches its folder. */
|
|
217
|
+
function headerStateCondition(doneFolders, closeInPlace, states, terminalStates) {
|
|
218
|
+
return {
|
|
219
|
+
description: 'have a readable State: line that matches its folder',
|
|
220
|
+
evaluate(elements, _ctx) {
|
|
221
|
+
const out = [];
|
|
222
|
+
for (const doc of elements) {
|
|
223
|
+
const inDoneFolder = doneFolders.some((seg) => `/${doc.relPath}`.includes(seg));
|
|
224
|
+
const found = headerStateViolation(doc, inDoneFolder, closeInPlace, states, terminalStates);
|
|
225
|
+
if (found)
|
|
226
|
+
out.push(found);
|
|
157
227
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
228
|
+
return out;
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/** Condition: an open box on a done-item carries a disposition token. */
|
|
233
|
+
function dispositionCondition() {
|
|
234
|
+
return {
|
|
235
|
+
description: 'carry a disposition token (done-otherwise / deferred→<home> / dropped-on-purpose / validation-owed)',
|
|
236
|
+
evaluate(elements, _ctx) {
|
|
237
|
+
return elements
|
|
238
|
+
.filter((t) => !isDisposed(t.text))
|
|
239
|
+
.map((t) => v('ledger/silent-open-box', t.doc, t.line, 'unchecked box with no disposition (done-otherwise / deferred→<home> / dropped-on-purpose / validation-owed)', "silence is not 'nothing deferred' — a done-item with a silently-open box has lost scope"));
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/** Condition: a document with a deferred-disposed box does not lie in its summary. */
|
|
244
|
+
function deferredNoneLieCondition() {
|
|
245
|
+
return {
|
|
246
|
+
description: "not summarize deferrals as 'none' while a box is deferred→<home>",
|
|
247
|
+
evaluate(elements, _ctx) {
|
|
248
|
+
const out = [];
|
|
249
|
+
for (const doc of elements) {
|
|
250
|
+
const found = deferredNoneLieViolation(doc);
|
|
251
|
+
if (found)
|
|
252
|
+
out.push(found);
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
},
|
|
256
|
+
};
|
|
161
257
|
}
|
|
162
258
|
/**
|
|
163
259
|
* Run the honesty-at-close gate over a corpus. Throws `ArchRuleError` on any
|
|
164
260
|
* finding. Placement is checked on every item; ledger reconciliation only on
|
|
165
261
|
* done-items (the inverse of the frozen-folder exemption).
|
|
262
|
+
*
|
|
263
|
+
* Three builder-based rules, merged: header state↔folder (`docs()`), silent
|
|
264
|
+
* open boxes (`taskItems()`, filtered to done-items), and the deferred-none
|
|
265
|
+
* lie (`docs()`, filtered to done-items carrying a deferred-disposed box).
|
|
266
|
+
*
|
|
267
|
+
* **Emptiness declarations, and why each is shaped the way it is** (bug 0131
|
|
268
|
+
* follow-up, six-persona review before this landed): `.expectEmpty()` is only
|
|
269
|
+
* a sound fail-closed gate when the thing that decides *whether* to declare
|
|
270
|
+
* it is independent of the predicate the declaration would otherwise let
|
|
271
|
+
* pass silently. Two designs were tried and rejected for this reason:
|
|
272
|
+
*
|
|
273
|
+
* 1. Peeking the exact same selection each rule gates (`.select()` on
|
|
274
|
+
* `openBoxesOnDoneItems`/`doneItemsWithDeferredBox` themselves) before
|
|
275
|
+
* conditionally declaring `.expectEmpty()`. This *reads* as a live check
|
|
276
|
+
* but is circular: the peek and the real run filter the identical
|
|
277
|
+
* elements through the identical predicates with nothing in between, so
|
|
278
|
+
* the declaration is always self-consistent and can never expire — it
|
|
279
|
+
* provides zero protection against exactly the corruption class ADR-010
|
|
280
|
+
* exists to catch, for either rule.
|
|
281
|
+
* 2. Gating on `terminalStates.length === 0` alone. Correct for the
|
|
282
|
+
* always-structurally-empty `proposals` lane, but too narrow: it doesn't
|
|
283
|
+
* cover a plan/bug lane's own test fixtures that legitimately have zero
|
|
284
|
+
* done-items in a given run (e.g. a single-document fixture testing an
|
|
285
|
+
* unrelated placement rule).
|
|
286
|
+
* 3. Gating both rules on one coarse "any done item exists in this corpus"
|
|
287
|
+
* signal. Independent of the right predicate, but the wrong *scope*: most
|
|
288
|
+
* done items carry zero open boxes and zero deferred boxes — that's the
|
|
289
|
+
* normal, healthy, permanent state for a reconciled item, not a corner
|
|
290
|
+
* case — so "a done item exists" routinely holds while the real selection
|
|
291
|
+
* (open boxes on it, or a deferred box on it) is legitimately empty. That
|
|
292
|
+
* false-positived on the project's own `fixed/green-bug-closed.md` fixture
|
|
293
|
+
* (a done item with one already-checked box, no open boxes at all).
|
|
294
|
+
*
|
|
295
|
+
* The fix: peek `openTaskItems` once (`taskItems(corpus).that().areOpen()`,
|
|
296
|
+
* a purely structural filter, no done-item check), then derive each rule's
|
|
297
|
+
* own emptiness signal from *that*, narrowed to what the rule actually
|
|
298
|
+
* selects, while staying independent of the specific predicate/function
|
|
299
|
+
* being protected:
|
|
300
|
+
*
|
|
301
|
+
* - `silentOpenBoxViolations` is gated by `belongsToADoneItem`. Its peek
|
|
302
|
+
* (`anyOpenBoxOnADoneItem`) calls `isDoneItem` on `openTaskItems` directly
|
|
303
|
+
* — not through `belongsToADoneItem` — so a corruption of that predicate
|
|
304
|
+
* specifically doesn't also blind the peek.
|
|
305
|
+
* - `deferredLieViolations`'s selection adds `hasDeferredDisposedBox` (which
|
|
306
|
+
* walks each done document's own mdast via a separate
|
|
307
|
+
* `collectTaskItems(doc.root)` call) on top of `isDoneItemPredicate`. Its
|
|
308
|
+
* peek (`anyDeferredDisposedBoxOnADoneItem`) instead re-tests
|
|
309
|
+
* `openTaskItems` (a different traversal) against the same
|
|
310
|
+
* `DEFERRED_DISPOSITION_RE` constant `hasDeferredDisposedBox` uses — so a
|
|
311
|
+
* corruption of `hasDeferredDisposedBox`'s own body doesn't blind this
|
|
312
|
+
* peek either.
|
|
313
|
+
*
|
|
314
|
+
* Both peeks share `isDoneItem` and the underlying `collectTaskItems` box
|
|
315
|
+
* collection with the very selections they protect — a corruption isolated to
|
|
316
|
+
* either would defeat both peek and real selection identically, uniformly,
|
|
317
|
+
* for every lane. This is a real residual gap, not a narrow one: verified by
|
|
318
|
+
* sabotaging `isDoneItem` against this repo's own real corpus during bug
|
|
319
|
+
* 0131's round-2 review, which produced **zero violations, exit 0** — not a
|
|
320
|
+
* partial miss. `headerStateCondition` does **not** independently backstop
|
|
321
|
+
* this (an earlier draft of this comment claimed it "would likely also
|
|
322
|
+
* surface through `headerViolations`" — false: `headerStateCondition` never
|
|
323
|
+
* calls `isDoneItem`, it recomputes the folder half of the same determination
|
|
324
|
+
* inline, so it only catches a corruption if a live state/folder mismatch
|
|
325
|
+
* already exists in the scanned corpus, which it usually doesn't).
|
|
326
|
+
*
|
|
327
|
+
* `honestyAtClose` itself can't close this gap generically — a corpus with
|
|
328
|
+
* zero done-items is legitimate on a freshly-bootstrapped lane's first day,
|
|
329
|
+
* so a library-level "zero done-items across the whole call is always wrong"
|
|
330
|
+
* assertion would be exactly the false-positive class `expectEmptyHeaders`
|
|
331
|
+
* exists to avoid. What closes it is caller knowledge: **a corpus with an
|
|
332
|
+
* established history should assert its own "zero done-items is never
|
|
333
|
+
* legitimate here" claim on top.** `scripts/check-ledger.mjs` (this repo's
|
|
334
|
+
* own wiring) does exactly that — 0 done-items summed across every lane fails
|
|
335
|
+
* the build, because this repo has carried done-items in every
|
|
336
|
+
* terminal-states lane for its entire history. A `kit/`-seeded caller with no
|
|
337
|
+
* history yet should not copy that assertion verbatim; it becomes true, and
|
|
338
|
+
* worth adding, once the corpus has one.
|
|
339
|
+
*
|
|
340
|
+
* `headerViolations` gets no computed declaration — nothing in the corpus
|
|
341
|
+
* can tell "no non-board documents authored yet" apart from "the selector
|
|
342
|
+
* broke." Callers who know the former is legitimate (a freshly-bootstrapped
|
|
343
|
+
* lane) opt in explicitly via {@link HonestyAtCloseOptions.expectEmptyHeaders}.
|
|
166
344
|
*/
|
|
167
345
|
export function honestyAtClose(corpus, options = {}) {
|
|
168
346
|
const doneFolders = options.doneFolders ?? DEFAULT_DONE_FOLDERS;
|
|
@@ -170,19 +348,64 @@ export function honestyAtClose(corpus, options = {}) {
|
|
|
170
348
|
const closeInPlace = options.closeInPlace ?? false;
|
|
171
349
|
const states = options.states ?? DEFAULT_STATES;
|
|
172
350
|
const terminalStates = options.terminalStates ?? DEFAULT_TERMINAL_STATES;
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
351
|
+
const expectEmptyHeaders = options.expectEmptyHeaders ?? false;
|
|
352
|
+
let headerRule = docs(corpus)
|
|
353
|
+
.that()
|
|
354
|
+
.satisfy(notBoardFile(boardFiles))
|
|
355
|
+
.should()
|
|
356
|
+
.satisfy(headerStateCondition(doneFolders, closeInPlace, states, terminalStates));
|
|
357
|
+
if (expectEmptyHeaders)
|
|
358
|
+
headerRule = headerRule.expectEmpty();
|
|
359
|
+
const headerViolations = headerRule.violations();
|
|
360
|
+
// Open task items, collected once and reused for both peeks below. "Any
|
|
361
|
+
// done item exists" is too coarse a signal on its own — most done items
|
|
362
|
+
// legitimately carry zero open boxes and zero deferred boxes, so gating on
|
|
363
|
+
// it alone false-positives on the common, healthy case (a done item with
|
|
364
|
+
// nothing outstanding). Each peek below narrows to what its own rule
|
|
365
|
+
// actually selects, while staying independent of the predicate/function
|
|
366
|
+
// that rule uses to select it.
|
|
367
|
+
const openTaskItems = taskItems(corpus)
|
|
368
|
+
.that()
|
|
369
|
+
.areOpen()
|
|
370
|
+
.select({
|
|
371
|
+
label: 'open task items',
|
|
372
|
+
identify: (t) => ({ name: t.doc.relPath, file: t.doc.file, line: t.line }),
|
|
373
|
+
}).elements;
|
|
374
|
+
// Independent of `belongsToADoneItem`: calls `isDoneItem` directly rather
|
|
375
|
+
// than through that predicate object, so a corruption of
|
|
376
|
+
// `belongsToADoneItem` itself doesn't also blind this peek.
|
|
377
|
+
const anyOpenBoxOnADoneItem = openTaskItems.some((t) => isDoneItem(t.doc, doneFolders, terminalStates));
|
|
378
|
+
let silentBoxRule = taskItems(corpus)
|
|
379
|
+
.that()
|
|
380
|
+
.areOpen()
|
|
381
|
+
.satisfy(belongsToADoneItem(doneFolders, terminalStates))
|
|
382
|
+
.should()
|
|
383
|
+
.satisfy(dispositionCondition());
|
|
384
|
+
if (!anyOpenBoxOnADoneItem)
|
|
385
|
+
silentBoxRule = silentBoxRule.expectEmpty();
|
|
386
|
+
const silentOpenBoxViolations = silentBoxRule.violations();
|
|
387
|
+
// Independent of `hasDeferredDisposedBox`: that function walks each done
|
|
388
|
+
// document's own mdast via a separate `collectTaskItems(doc.root)` call:
|
|
389
|
+
// this peek instead reuses the flat, already-collected `openTaskItems` list
|
|
390
|
+
// (from the `taskItems()` builder's own traversal) and the same
|
|
391
|
+
// `DEFERRED_DISPOSITION_RE` constant `hasDeferredDisposedBox` tests against
|
|
392
|
+
// — two different collection paths converging on the one shared pattern,
|
|
393
|
+
// so a corruption of `hasDeferredDisposedBox`'s own body doesn't blind this
|
|
394
|
+
// peek too.
|
|
395
|
+
const anyDeferredDisposedBoxOnADoneItem = openTaskItems.some((t) => isDoneItem(t.doc, doneFolders, terminalStates) && DEFERRED_DISPOSITION_RE.test(t.text));
|
|
396
|
+
let deferredLieRule = docs(corpus)
|
|
397
|
+
.that()
|
|
398
|
+
.satisfy(isDoneItemPredicate(doneFolders, terminalStates))
|
|
399
|
+
.satisfy({
|
|
400
|
+
description: 'carries a box disposed as deferred→<home>',
|
|
401
|
+
test: (doc) => hasDeferredDisposedBox(doc),
|
|
402
|
+
})
|
|
403
|
+
.should()
|
|
404
|
+
.satisfy(deferredNoneLieCondition());
|
|
405
|
+
if (!anyDeferredDisposedBoxOnADoneItem)
|
|
406
|
+
deferredLieRule = deferredLieRule.expectEmpty();
|
|
407
|
+
const deferredLieViolations = deferredLieRule.violations();
|
|
408
|
+
return finishPreset([...headerViolations, ...silentOpenBoxViolations, ...deferredLieViolations], options);
|
|
186
409
|
}
|
|
187
410
|
/**
|
|
188
411
|
* The denominator, computed by the preset itself.
|
|
@@ -196,6 +419,8 @@ export function honestyAtClose(corpus, options = {}) {
|
|
|
196
419
|
* Callers must not re-derive it. `check-ledger.mjs` did, with a copy of the very
|
|
197
420
|
* expression 0119 removed, and its copy disagreed with the preset on 56 of 56
|
|
198
421
|
* records while heading a section captioned "so a green is provably non-vacuous".
|
|
422
|
+
*
|
|
423
|
+
* Pure read-only counting, not a rule — no evidence gate applies here.
|
|
199
424
|
*/
|
|
200
425
|
export function ledgerStats(corpus, options = {}) {
|
|
201
426
|
const doneFolders = options.doneFolders ?? DEFAULT_DONE_FOLDERS;
|
package/dist/rules/ledger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/rules/ledger.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/rules/ledger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nielspeter/eess-md",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Architecture testing for a Markdown corpus — the Markdown dialect of the eess family. Links resolve, code pointers ground, ADRs declare enforcement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"eess"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@nielspeter/eess": "^0.
|
|
51
|
+
"@nielspeter/eess": "^0.4.0",
|
|
52
52
|
"mdast-util-from-markdown": "^2.0.3",
|
|
53
53
|
"mdast-util-gfm": "^3.1.0",
|
|
54
54
|
"micromark-extension-gfm": "^3.0.0",
|