@nielspeter/eess 0.2.2 → 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.
Files changed (209) hide show
  1. package/README.md +97 -4
  2. package/dist/assertion-advice.d.ts +26 -0
  3. package/dist/assertion-advice.d.ts.map +1 -0
  4. package/dist/assertion-advice.js +29 -0
  5. package/dist/assertion-advice.js.map +1 -0
  6. package/dist/baseline-generator.d.ts +9 -0
  7. package/dist/baseline-generator.d.ts.map +1 -1
  8. package/dist/baseline-generator.js +9 -0
  9. package/dist/baseline-generator.js.map +1 -1
  10. package/dist/baseline.d.ts +69 -4
  11. package/dist/baseline.d.ts.map +1 -1
  12. package/dist/baseline.js +119 -13
  13. package/dist/baseline.js.map +1 -1
  14. package/dist/cache-registry.d.ts +14 -0
  15. package/dist/cache-registry.d.ts.map +1 -0
  16. package/dist/cache-registry.js +37 -0
  17. package/dist/cache-registry.js.map +1 -0
  18. package/dist/cardinality.d.ts +35 -0
  19. package/dist/cardinality.d.ts.map +1 -0
  20. package/dist/cardinality.js +80 -0
  21. package/dist/cardinality.js.map +1 -0
  22. package/dist/check-options.d.ts +14 -0
  23. package/dist/check-options.d.ts.map +1 -1
  24. package/dist/cli-config.d.ts +59 -0
  25. package/dist/cli-config.d.ts.map +1 -0
  26. package/dist/cli-config.js +84 -0
  27. package/dist/cli-config.js.map +1 -0
  28. package/dist/collect-result.d.ts +94 -0
  29. package/dist/collect-result.d.ts.map +1 -0
  30. package/dist/collect-result.js +142 -0
  31. package/dist/collect-result.js.map +1 -0
  32. package/dist/combinators.d.ts +14 -0
  33. package/dist/combinators.d.ts.map +1 -1
  34. package/dist/combinators.js +53 -16
  35. package/dist/combinators.js.map +1 -1
  36. package/dist/comment-suppression.d.ts +60 -0
  37. package/dist/comment-suppression.d.ts.map +1 -0
  38. package/dist/comment-suppression.js +89 -0
  39. package/dist/comment-suppression.js.map +1 -0
  40. package/dist/condition.d.ts +43 -0
  41. package/dist/condition.d.ts.map +1 -1
  42. package/dist/condition.js +48 -1
  43. package/dist/condition.js.map +1 -1
  44. package/dist/correspondence-core.d.ts +35 -0
  45. package/dist/correspondence-core.d.ts.map +1 -0
  46. package/dist/correspondence-core.js +38 -0
  47. package/dist/correspondence-core.js.map +1 -0
  48. package/dist/correspondence.d.ts +57 -5
  49. package/dist/correspondence.d.ts.map +1 -1
  50. package/dist/correspondence.js +74 -5
  51. package/dist/correspondence.js.map +1 -1
  52. package/dist/dedupe-config-findings.d.ts +56 -0
  53. package/dist/dedupe-config-findings.d.ts.map +1 -0
  54. package/dist/dedupe-config-findings.js +101 -0
  55. package/dist/dedupe-config-findings.js.map +1 -0
  56. package/dist/define.d.ts +44 -2
  57. package/dist/define.d.ts.map +1 -1
  58. package/dist/define.js +45 -4
  59. package/dist/define.js.map +1 -1
  60. package/dist/diff-aware.d.ts +8 -1
  61. package/dist/diff-aware.d.ts.map +1 -1
  62. package/dist/diff-aware.js +39 -9
  63. package/dist/diff-aware.js.map +1 -1
  64. package/dist/diff-disclosure.d.ts +72 -0
  65. package/dist/diff-disclosure.d.ts.map +1 -0
  66. package/dist/diff-disclosure.js +110 -0
  67. package/dist/diff-disclosure.js.map +1 -0
  68. package/dist/disk-set.d.ts +27 -0
  69. package/dist/disk-set.d.ts.map +1 -0
  70. package/dist/disk-set.js +12 -0
  71. package/dist/disk-set.js.map +1 -0
  72. package/dist/edge-coverage.d.ts +96 -0
  73. package/dist/edge-coverage.d.ts.map +1 -0
  74. package/dist/edge-coverage.js +108 -0
  75. package/dist/edge-coverage.js.map +1 -0
  76. package/dist/emitter-findings.d.ts +167 -0
  77. package/dist/emitter-findings.d.ts.map +1 -0
  78. package/dist/emitter-findings.js +237 -0
  79. package/dist/emitter-findings.js.map +1 -0
  80. package/dist/errors.d.ts +73 -0
  81. package/dist/errors.d.ts.map +1 -1
  82. package/dist/errors.js +93 -0
  83. package/dist/errors.js.map +1 -1
  84. package/dist/exclusion-comments.d.ts +36 -1
  85. package/dist/exclusion-comments.d.ts.map +1 -1
  86. package/dist/exclusion-comments.js +185 -37
  87. package/dist/exclusion-comments.js.map +1 -1
  88. package/dist/execute-rule.d.ts +11 -1
  89. package/dist/execute-rule.d.ts.map +1 -1
  90. package/dist/execute-rule.js +220 -11
  91. package/dist/execute-rule.js.map +1 -1
  92. package/dist/file-walk.d.ts +22 -0
  93. package/dist/file-walk.d.ts.map +1 -0
  94. package/dist/file-walk.js +51 -0
  95. package/dist/file-walk.js.map +1 -0
  96. package/dist/format-github.d.ts.map +1 -1
  97. package/dist/format-github.js +37 -5
  98. package/dist/format-github.js.map +1 -1
  99. package/dist/format-json.d.ts +96 -1
  100. package/dist/format-json.d.ts.map +1 -1
  101. package/dist/format-json.js +94 -9
  102. package/dist/format-json.js.map +1 -1
  103. package/dist/format.d.ts +4 -2
  104. package/dist/format.d.ts.map +1 -1
  105. package/dist/format.js +41 -19
  106. package/dist/format.js.map +1 -1
  107. package/dist/glob-site.d.ts +232 -0
  108. package/dist/glob-site.d.ts.map +1 -0
  109. package/dist/glob-site.js +156 -0
  110. package/dist/glob-site.js.map +1 -0
  111. package/dist/identity-root.d.ts +55 -0
  112. package/dist/identity-root.d.ts.map +1 -0
  113. package/dist/identity-root.js +170 -0
  114. package/dist/identity-root.js.map +1 -0
  115. package/dist/index.d.ts +18 -12
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +12 -10
  118. package/dist/index.js.map +1 -1
  119. package/dist/internal.d.ts +55 -0
  120. package/dist/internal.d.ts.map +1 -0
  121. package/dist/internal.js +92 -0
  122. package/dist/internal.js.map +1 -0
  123. package/dist/mask-non-comment.d.ts +49 -0
  124. package/dist/mask-non-comment.d.ts.map +1 -0
  125. package/dist/mask-non-comment.js +261 -0
  126. package/dist/mask-non-comment.js.map +1 -0
  127. package/dist/owns-empty-discovery.d.ts +5 -0
  128. package/dist/owns-empty-discovery.d.ts.map +1 -0
  129. package/dist/owns-empty-discovery.js +85 -0
  130. package/dist/owns-empty-discovery.js.map +1 -0
  131. package/dist/path-suffix.d.ts +57 -0
  132. package/dist/path-suffix.d.ts.map +1 -0
  133. package/dist/path-suffix.js +73 -0
  134. package/dist/path-suffix.js.map +1 -0
  135. package/dist/path-universe.d.ts +44 -0
  136. package/dist/path-universe.d.ts.map +1 -0
  137. package/dist/path-universe.js +21 -0
  138. package/dist/path-universe.js.map +1 -0
  139. package/dist/predicate.d.ts +45 -0
  140. package/dist/predicate.d.ts.map +1 -1
  141. package/dist/predicate.js +20 -1
  142. package/dist/predicate.js.map +1 -1
  143. package/dist/preset-dispatch.d.ts +6 -15
  144. package/dist/preset-dispatch.d.ts.map +1 -1
  145. package/dist/preset-dispatch.js +35 -17
  146. package/dist/preset-dispatch.js.map +1 -1
  147. package/dist/project-relative.d.ts +25 -0
  148. package/dist/project-relative.d.ts.map +1 -0
  149. package/dist/project-relative.js +54 -0
  150. package/dist/project-relative.js.map +1 -0
  151. package/dist/report.d.ts +42 -12
  152. package/dist/report.d.ts.map +1 -1
  153. package/dist/report.js +190 -14
  154. package/dist/report.js.map +1 -1
  155. package/dist/rule-builder-like.d.ts +17 -0
  156. package/dist/rule-builder-like.d.ts.map +1 -0
  157. package/dist/rule-builder-like.js +2 -0
  158. package/dist/rule-builder-like.js.map +1 -0
  159. package/dist/rule-builder.d.ts +124 -84
  160. package/dist/rule-builder.d.ts.map +1 -1
  161. package/dist/rule-builder.js +230 -181
  162. package/dist/rule-builder.js.map +1 -1
  163. package/dist/rule-description.d.ts +83 -1
  164. package/dist/rule-description.d.ts.map +1 -1
  165. package/dist/rule-description.js +75 -1
  166. package/dist/rule-description.js.map +1 -1
  167. package/dist/rule-metadata.d.ts +20 -3
  168. package/dist/rule-metadata.d.ts.map +1 -1
  169. package/dist/selection-memo.d.ts +45 -0
  170. package/dist/selection-memo.d.ts.map +1 -0
  171. package/dist/selection-memo.js +66 -0
  172. package/dist/selection-memo.js.map +1 -0
  173. package/dist/shallow-clone.d.ts +20 -0
  174. package/dist/shallow-clone.d.ts.map +1 -0
  175. package/dist/shallow-clone.js +27 -0
  176. package/dist/shallow-clone.js.map +1 -0
  177. package/dist/silent-exclusion.d.ts +12 -0
  178. package/dist/silent-exclusion.d.ts.map +1 -1
  179. package/dist/silent-exclusion.js +22 -0
  180. package/dist/silent-exclusion.js.map +1 -1
  181. package/dist/stderr.d.ts +16 -0
  182. package/dist/stderr.d.ts.map +1 -0
  183. package/dist/stderr.js +73 -0
  184. package/dist/stderr.js.map +1 -0
  185. package/dist/terminal-builder.d.ts +224 -10
  186. package/dist/terminal-builder.d.ts.map +1 -1
  187. package/dist/terminal-builder.js +336 -46
  188. package/dist/terminal-builder.js.map +1 -1
  189. package/dist/type-guards.d.ts +38 -0
  190. package/dist/type-guards.d.ts.map +1 -0
  191. package/dist/type-guards.js +42 -0
  192. package/dist/type-guards.js.map +1 -0
  193. package/dist/unsuppressable.d.ts +54 -0
  194. package/dist/unsuppressable.d.ts.map +1 -0
  195. package/dist/unsuppressable.js +76 -0
  196. package/dist/unsuppressable.js.map +1 -0
  197. package/dist/vacuity-findings.d.ts +49 -0
  198. package/dist/vacuity-findings.d.ts.map +1 -0
  199. package/dist/vacuity-findings.js +94 -0
  200. package/dist/vacuity-findings.js.map +1 -0
  201. package/dist/violation.d.ts +173 -4
  202. package/dist/violation.d.ts.map +1 -1
  203. package/dist/violation.js +262 -1
  204. package/dist/violation.js.map +1 -1
  205. package/dist/watch.d.ts +71 -0
  206. package/dist/watch.d.ts.map +1 -0
  207. package/dist/watch.js +129 -0
  208. package/dist/watch.js.map +1 -0
  209. package/package.json +6 -1
@@ -1,25 +1,68 @@
1
1
  import type { ArchViolation } from './violation.js';
2
+ import { type CollectResult } from './collect-result.js';
2
3
  import type { CheckOptions } from './check-options.js';
3
4
  import type { RuleMetadata } from './rule-metadata.js';
4
5
  import type { RuleDescription } from './rule-description.js';
5
6
  import type { SilentExclusion } from './silent-exclusion.js';
7
+ /**
8
+ * A rule's verdict, carrying evidence of examination alongside the findings —
9
+ * ADR-010. `examined` is the count of units the family's own examining seam
10
+ * actually iterated (never a count of matches, never upstream discovery like
11
+ * files loaded) — each concrete `collectViolations()` names its own unit.
12
+ *
13
+ * `sourceEmpty` — ADR-010 part 3's precedence rule: "an empty project
14
+ * outranks every token." Set `true` when `examined === 0` because the
15
+ * family's own upstream source (files loaded, a diagram parsed, an SDL
16
+ * string) produced nothing at all — BEFORE any predicate/selection
17
+ * narrowed it — as distinct from a predicate narrowing a non-empty source
18
+ * down to zero. This is a stronger claim than a bare zero-examined dead
19
+ * selector: `.expectEmpty()` cannot rescue it, because there is no
20
+ * selection to widen — the instrument itself never loaded anything to
21
+ * examine. Omit (or `false`) when the distinction doesn't apply (the
22
+ * family has no separate source/selection stages) or the zero came from
23
+ * narrowing, not upstream emptiness.
24
+ */
25
+ export type { CollectResult } from './collect-result.js';
6
26
  /**
7
27
  * Abstract base class for builders that share the terminal method pattern
8
28
  * (because, rule, excluding, check, warn, severity) but have different
9
29
  * element collection and evaluation models.
10
30
  *
11
31
  * Used by SliceRuleBuilder, SchemaRuleBuilder, ResolverRuleBuilder,
12
- * PairFinalBuilder, and SmellBuilder — all of which implement the same
13
- * terminal methods but differ in how they collect and evaluate elements.
14
- *
15
- * RuleBuilder<T> does NOT extend this because it predates it and has
16
- * additional concerns (predicate/condition pipeline, fork semantics).
32
+ * PairFinalBuilder, SmellBuilder, CorrespondenceBuilder, TsconfigBuilder, and
33
+ * (as of plan 0088 Phase 4) RuleBuilder — all of which implement the same
34
+ * terminal methods and now share evidence-of-examination (ADR-010) alongside
35
+ * evaluation-model differences.
17
36
  */
18
37
  export declare abstract class TerminalBuilder {
19
38
  protected _reason?: string;
20
39
  protected _metadata?: RuleMetadata;
21
- private readonly _exclusions;
22
- private readonly _silentIndices;
40
+ protected _exclusions: (string | RegExp)[];
41
+ protected _silentIndices: Set<number>;
42
+ /** ADR-010 part 3 — `.expectEmpty()`/`.expectNonEmpty()`. `undefined` = no declaration. */
43
+ protected _expectEmpty?: boolean;
44
+ /**
45
+ * Declare that this rule's examined set is expected to be empty. A pass is
46
+ * legitimate only while the declaration stays true — the day a unit is
47
+ * examined, this rule reddens (ADR-010 part 3's expiry property). The
48
+ * complement of `expectNonEmpty()`; declaring both is nonsensical and the
49
+ * later call wins (last-write, matching `.rule()`'s own semantics).
50
+ */
51
+ expectEmpty(): this;
52
+ /**
53
+ * Declare that this rule's examined set must be non-empty — the opposite
54
+ * assertion, for a corpus the author has positive knowledge should never
55
+ * legitimately be empty. Unlike a bare, undeclared rule, this **overrides
56
+ * `assertsCardinality()`'s exemption**: a `.notExist()`-shaped condition
57
+ * that finds zero subjects normally passes silently (emptiness satisfies
58
+ * what it asserts) — but if the author declared `.expectNonEmpty()`, that
59
+ * silence is exactly what they said should never happen, so it reddens
60
+ * instead, naming the declaration as the reason. This is the real
61
+ * difference from not declaring anything: without it, a `.notExist()` rule
62
+ * over an accidentally-emptied corpus (a glob typo, a temporarily-missing
63
+ * folder) passes and says nothing; with it, that same emptiness is caught.
64
+ */
65
+ expectNonEmpty(): this;
23
66
  /**
24
67
  * Attach a human-readable rationale to the rule.
25
68
  * Included in violation messages when `.check()` throws.
@@ -49,11 +92,27 @@ export declare abstract class TerminalBuilder {
49
92
  * Used by the `explain` CLI subcommand.
50
93
  */
51
94
  describeRule(): RuleDescription;
95
+ /** This rule's own account of itself, for `vacuity-findings.ts`. */
96
+ private facts;
97
+ /**
98
+ * What every terminal method hands the filter pipeline.
99
+ *
100
+ * The same four fields were written out at each of `violations`, `check` and
101
+ * `warn` — `no-copy-paste` reported the three at 100% with `applyFilters ->
102
+ * executeCheck` as the only varying axis. `eess-ts`'s `TerminalBuilder`
103
+ * already had exactly this method; the kernel never adopted it.
104
+ *
105
+ * Not just tidier: three terminal methods that build the filter context
106
+ * separately can drift, and a field present on `.check()` but missing on
107
+ * `.violations()` means a rule fails in CI and passes when a preset
108
+ * aggregates it — the same finding, two answers.
109
+ */
110
+ private filterContext;
52
111
  /**
53
112
  * Execute the rule and return violations after exclusion filtering.
54
113
  * Does not throw — use for programmatic access (presets, aggregation).
55
114
  */
56
- violations(): ArchViolation[];
115
+ violations(): CollectResult;
57
116
  /**
58
117
  * Execute the rule and throw `ArchRuleError` if any violations are found.
59
118
  * This is the primary terminal method — use in test assertions.
@@ -68,6 +127,59 @@ export declare abstract class TerminalBuilder {
68
127
  * @param options - Optional baseline, diff filtering, and output format
69
128
  */
70
129
  warn(options?: CheckOptions): void;
130
+ /**
131
+ * ADR-010 — the evidence gate. Calls `collectViolations()` once and turns
132
+ * its `{ violations, examined, sourceEmpty }` verdict into the
133
+ * `ArchViolation[]` every terminal method still emits, applying the
134
+ * declared-empty precedence:
135
+ *
136
+ * - `examined === 0`, `sourceEmpty === true`: ADR-010 part 3's precedence
137
+ * rule — "an empty project outranks every token." The family's own
138
+ * upstream source (files loaded, a diagram parsed) produced nothing at
139
+ * all, before any predicate ran. Neither `.expectEmpty()` nor
140
+ * `assertsCardinality()` can rescue this: there is no selection to
141
+ * widen, and a `.notExist()`-shaped condition "passing" against an
142
+ * instrument that never loaded anything is not evidence of anything.
143
+ * Always an unsuppressable configuration finding.
144
+ * - `examined === 0`, `.expectNonEmpty()` declared: the caller has positive
145
+ * knowledge this corpus should never be empty — this OVERRIDES
146
+ * `assertsCardinality()`'s exemption (a `.notExist()` rule that would
147
+ * otherwise pass silently on zero subjects reddens instead, since silent
148
+ * emptiness is exactly what the declaration rules out). Fails, naming the
149
+ * unmet declaration.
150
+ * - `examined === 0`, no `.expectEmpty()` declared: the rule's own
151
+ * instrument is broken (a dead selector, an unreachable seam) — this is
152
+ * a configuration finding, unsuppressable (`bypassFilters`), not a silent
153
+ * pass. This is the guarantee ADR-009/010 exist for.
154
+ * - `examined === 0`, `.expectEmpty()` declared: satisfied. Passes.
155
+ * - `examined === 0`, `assertsCardinality()` true (and no `.expectNonEmpty()`
156
+ * override above): the rule's own conditions are satisfied BY emptiness
157
+ * (e.g. `.notExist()`) — a different exemption from `.expectEmpty()`,
158
+ * because it is a property of what the condition asserts, not a caller's
159
+ * declaration about the corpus. Passes, with no finding at all (not even
160
+ * a silent one — the condition already reported truthfully that it found
161
+ * nothing wrong).
162
+ * - `examined > 0`, `.expectEmpty()` declared: the declaration has expired
163
+ * — a unit was examined despite the author's "this stays empty" claim.
164
+ * Fails, appending an expiry finding to whatever `collectViolations()`
165
+ * found (never replacing it — the underlying findings are still real).
166
+ * - `examined > 0`, no declaration or `.expectNonEmpty()` (the ordinary
167
+ * case — `.expectNonEmpty()` has nothing left to assert once subjects
168
+ * exist): the rule's own violations stand as computed.
169
+ */
170
+ private evidencedViolations;
171
+ /**
172
+ * Which finding a zero-examined rule earns, or `undefined` when it earned none
173
+ * because it declared the emptiness.
174
+ *
175
+ * Extracted from `evidencedViolations` under `check:arch`'s complexity rule.
176
+ * The precedence is the whole content and is unchanged: an empty source
177
+ * outranks every declaration (ADR-010 §3), an explicit declaration is
178
+ * satisfied, `.expectNonEmpty()` is unmet, a cardinality condition is
179
+ * satisfied by emptiness, and a nameable dead glob outranks the generic
180
+ * message because it is strictly more actionable.
181
+ */
182
+ private zeroExaminedFinding;
71
183
  /**
72
184
  * Execute the rule with the given severity.
73
185
  * `.severity('error')` is equivalent to `.check()`.
@@ -75,9 +187,111 @@ export declare abstract class TerminalBuilder {
75
187
  */
76
188
  severity(level: 'error' | 'warn'): void;
77
189
  /**
78
- * Subclasses implement this to collect and evaluate violations.
190
+ * An independent copy of this builder.
191
+ *
192
+ * **A held selection is immutable** (a bug class ported alongside the
193
+ * kernel — plan 0088 Phase 4, matching `ts-archunit`'s own documented
194
+ * "bug 0016"). Before this, every chain method mutated `this` in place:
195
+ *
196
+ * ```ts
197
+ * const repos = classes(p).that().extend('BaseRepository')
198
+ * repos.that().haveNameEndingWith('Legacy').should().notExist().check()
199
+ * repos.should().beExported().check() // silently narrowed to Legacy too
200
+ * ```
201
+ *
202
+ * A held selection reused for a second rule silently inherited the first
203
+ * rule's narrowing, exclusions, and rule id — found live in this repo's own
204
+ * test suite once the ADR-010 evidence gate stopped treating "examined
205
+ * zero units because a stale narrowing ate the selection" as an ordinary,
206
+ * silent pass. `because`/`rule`/`excluding`/`expectEmpty`/`expectNonEmpty`
207
+ * on `TerminalBuilder`, and `that`/`addPredicate`/`addCondition` on
208
+ * `RuleBuilder`, all return a copy rather than mutating `this`.
209
+ *
210
+ * Subclasses with additional fields beyond `TerminalBuilder`'s own MUST
211
+ * override this (see `RuleBuilder.copy()`) and call `super.copy()` first.
212
+ */
213
+ protected copy(): this;
214
+ /**
215
+ * Give this builder independent copies of another's filter state.
216
+ *
217
+ * `copy()` shallow-copies every field via `Object.assign`, so without this
218
+ * a copy would share its source's `_exclusions` array and `_silentIndices`
219
+ * set by reference — `.excluding()` on one would silently mutate the
220
+ * other, the exact hazard `copy()` exists to close, one field deeper.
221
+ */
222
+ protected adoptFilterState(source: TerminalBuilder): void;
223
+ /**
224
+ * Subclasses implement this to collect and evaluate violations, and to
225
+ * report how many units they examined (ADR-010) — counted at the family's
226
+ * own examining seam, in whatever unit that family names as its own
227
+ * (post-predicate subjects for `RuleBuilder`, bodies compared for
228
+ * `SmellBuilder`, the key sets of both sides for `correspondence()`).
79
229
  * Called lazily during `.check()` / `.warn()`.
80
230
  */
81
- protected abstract collectViolations(): ArchViolation[];
231
+ protected abstract collectViolations(): CollectResult;
232
+ /**
233
+ * Is this rule's own assertion satisfied by an empty examined set, as a
234
+ * matter of what it asserts (`.notExist()`-shaped), not a caller's
235
+ * `.expectEmpty()` declaration? Default `false` — most families have no
236
+ * such condition and stay covered by the ordinary zero-examined gate.
237
+ * `RuleBuilder` overrides this to check its own `_conditions` against the
238
+ * kernel's `assertsCardinality()` registry (ADR-010, `cardinality.ts`).
239
+ */
240
+ protected assertsCardinality(): boolean;
82
241
  }
242
+ /**
243
+ * The configuration finding for a rule that asserts nothing — bug 0155.
244
+ *
245
+ * An assertion-less rule — subjects found, nothing asserted about them —
246
+ * cannot fail, so it certifies nothing while reading as coverage.
247
+ *
248
+ * **The guard was unreachable, not merely quiet.** It used to read
249
+ * `_conditions.length === 0 && _phase === 'predicate'`, and `should()` sets
250
+ * the phase to `'condition'`, so for every rule shape the DSL documents it
251
+ * could never fire — the defect passed in total silence, never even reaching
252
+ * the stderr warning it was routed to. Hence no `_phase` term at the call
253
+ * site.
254
+ *
255
+ * **A finding, not a warning**, per ADR-009 rule 1's discriminator: the remedy
256
+ * is not optional. There is no state in which "keeps asserting nothing" is
257
+ * correct — add a condition, or delete the rule. The two rules ADR-009 names
258
+ * as deliberately `warn` (`no-silent-catch`, `no-empty-bodies`) warn *because*
259
+ * they carry suppressible false positives a reader must judge case by case.
260
+ * This carries none.
261
+ *
262
+ * **A declared emptiness expectation is an assertion**, so `_expectEmpty`
263
+ * exempts a rule from this gate. `.expectNonEmpty()` reddens when the corpus
264
+ * it says must never be empty becomes empty; `.expectEmpty()` reddens the day
265
+ * the set it says must stay empty gains a member. Neither lives in
266
+ * `_conditions`. Without that term the gate called a working corpus guard
267
+ * assertion-less and told its author to "add a condition or delete the rule" —
268
+ * both of which destroy the guard — and for `.expectEmpty()` reported two
269
+ * findings for one fault. Found in PR #71's review.
270
+ *
271
+ * **Placed AFTER the zero-examined branch**, so a dead selector still reports
272
+ * as a dead selector. Measured: `resideInFolder('srcc/**')` with no condition
273
+ * reports the dead glob, not this finding. An earlier draft of this docstring
274
+ * (and of the changeset and bug record) claimed the opposite — "reports the
275
+ * missing assertion only" — and justified it as gate-first. Both were wrong:
276
+ * `getElements()` and the predicate filter already ran, so the ordering saves
277
+ * no work, and the behaviour is the reverse. The real precedence is the better
278
+ * one, and is now stated as what it is: this finding fires only when subjects
279
+ * were actually selected.
280
+ *
281
+ * **Exported** rather than private to `RuleBuilder`. Its five siblings
282
+ * (`zeroExaminedViolation`, `deadGlobViolation`, `unmetExpectNonEmptyViolation`,
283
+ * `expiredExpectEmptyViolation`, `zeroLoadedSourceViolation`) have since moved to
284
+ * `vacuity-findings.ts`; this one stayed, because unlike them it is constructed
285
+ * from a builder's own condition list rather than from `RuleFacts` alone. The *detection* has to stay per-builder —
286
+ * `TerminalBuilder` has no `_conditions` — but a private constructor meant
287
+ * `eess-ts`'s slice/schema/resolver builders could not reuse it and were left
288
+ * warning while the kernel's rules failed: the same defect, one DSL, four
289
+ * different answers.
290
+ *
291
+ * `bypassFilters` makes it a **configuration** finding — `error` regardless of
292
+ * `.asSeverity('warn')`, refused by `.excluding()`, skipped by diff and
293
+ * baseline. It reports that the rule's own instrument is broken, not a fault
294
+ * in what was examined, so a filter aimed at the latter must not suppress it.
295
+ */
296
+ export declare function assertionLessViolation(ruleId: string, advice?: string): ArchViolation;
83
297
  //# sourceMappingURL=terminal-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-builder.d.ts","sourceRoot":"","sources":["../src/terminal-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAI5D;;;;;;;;;;;GAWG;AACH,8BAAsB,eAAe;IACnC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IAExD;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK7B;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAQlC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,GAAG,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC,EAAE,GAAG,IAAI;IAYnE;;;OAGG;IACH,YAAY,IAAI,eAAe;IAW/B;;;OAGG;IACH,UAAU,IAAI,aAAa,EAAE;IAU7B;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAcnC;;;;;OAKG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAclC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAQvC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,iBAAiB,IAAI,aAAa,EAAE;CACxD"}
1
+ {"version":3,"file":"terminal-builder.d.ts","sourceRoot":"","sources":["../src/terminal-builder.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,qBAAqB,CAAA;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAM5D;;;;;;;;;;;;;;;;;GAiBG;AACH,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD;;;;;;;;;;GAUG;AACH,8BAAsB,eAAe;IACnC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IAClC,SAAS,CAAC,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAK;IAC/C,SAAS,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAY;IACjD,2FAA2F;IAC3F,SAAS,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAEhC;;;;;;OAMG;IACH,WAAW,IAAI,IAAI;IAMnB;;;;;;;;;;;;OAYG;IACH,cAAc,IAAI,IAAI;IAMtB;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAM7B;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IASlC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,GAAG,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC,EAAE,GAAG,IAAI;IAMnE;;;OAGG;IACH,YAAY,IAAI,eAAe;IAQ/B,oEAAoE;IACpE,OAAO,CAAC,KAAK;IAQb;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,aAAa;IAcrB;;;OAGG;IACH,UAAU,IAAI,aAAa;IAa3B;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAInC;;;;;OAKG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAIlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,OAAO,CAAC,mBAAmB;IAwC3B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,mBAAmB;IAY3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAQvC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,SAAS,CAAC,IAAI,IAAI,IAAI;IAOtB;;;;;;;OAOG;IACH,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAKzD;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,CAAC,iBAAiB,IAAI,aAAa;IAErD;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,OAAO;CAGxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAiCrF"}