@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 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](../../README.md) family. _Specifications you can run._
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`](../core) kernel, so you write a declarative rules file, not a custom validator script.
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
- correspondence({ left: packageRows, right: workspacePackages, keyBy: (e) => e.name })
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;CAC1B;AAmCD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,SAAS,CAAC,MAAM,CAAC,CAgChG"}
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":"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"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"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"}
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';
@@ -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;AAGxD,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"}
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;AAMpC,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"}
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"}
@@ -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;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAG1D;;;;;;;;;;;;;;;;;;GAkBG;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;CAC5C;AAoOD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,aAAa,EAAE,CAoBjB;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;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,WAAW,CAqB5F"}
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"}
@@ -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
- /** Ledger reconciliation of one done-item: unchecked boxes + the `none`-summary lie. */
133
- function ledgerViolations(doc) {
134
- const out = [];
135
- let anyDeferredDisposedBox = false;
136
- for (const box of collectTaskItems(doc.root)) {
137
- if (box.checked)
138
- continue; // only open boxes are live ledger entries
139
- if (DEFERRED_DISPOSITION_RE.test(box.text))
140
- anyDeferredDisposedBox = true;
141
- if (!DISPOSITION_RE.test(box.text)) {
142
- out.push(v('ledger/silent-open-box', doc, box.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"));
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
- // A `none` deferral-summary while a box carries a defer disposition — the
146
- // summary contradicts the boxes. (Absence of a summary is deliberately NOT gated.)
147
- if (anyDeferredDisposedBox) {
148
- const lines = stripFencedCode(doc.text).split('\n');
149
- for (let i = 0; i < lines.length; i++) {
150
- const raw = lines[i] ?? '';
151
- if (/^\s*>/.test(raw))
152
- continue;
153
- const sm = raw.match(DEFERRED_SUMMARY_RE);
154
- if (sm && /^none\b/i.test((sm[1] ?? '').trim())) {
155
- out.push(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'));
156
- break;
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
- return out;
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 violations = [];
174
- for (const doc of corpus.documents()) {
175
- const base = doc.relPath.split('/').pop() ?? doc.relPath;
176
- if (boardFiles.has(base))
177
- continue;
178
- const inDoneFolder = doneFolders.some((seg) => `/${doc.relPath}`.includes(seg));
179
- const header = headerStateViolation(doc, inDoneFolder, closeInPlace, states, terminalStates);
180
- if (header)
181
- violations.push(header);
182
- if (isDoneItem(doc, doneFolders, terminalStates))
183
- violations.push(...ledgerViolations(doc));
184
- }
185
- return finishPreset(violations, options);
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;
@@ -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.2.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.2.2",
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",