@nielspeter/eess 0.4.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.
Files changed (125) hide show
  1. package/README.md +94 -1
  2. package/dist/baseline-generator.d.ts +9 -0
  3. package/dist/baseline-generator.d.ts.map +1 -1
  4. package/dist/baseline-generator.js +9 -0
  5. package/dist/baseline-generator.js.map +1 -1
  6. package/dist/baseline.d.ts +1 -1
  7. package/dist/cardinality.d.ts.map +1 -1
  8. package/dist/cardinality.js +20 -5
  9. package/dist/cardinality.js.map +1 -1
  10. package/dist/cli-config.d.ts +59 -0
  11. package/dist/cli-config.d.ts.map +1 -0
  12. package/dist/cli-config.js +84 -0
  13. package/dist/cli-config.js.map +1 -0
  14. package/dist/collect-result.d.ts +94 -0
  15. package/dist/collect-result.d.ts.map +1 -0
  16. package/dist/collect-result.js +142 -0
  17. package/dist/collect-result.js.map +1 -0
  18. package/dist/combinators.d.ts +14 -0
  19. package/dist/combinators.d.ts.map +1 -1
  20. package/dist/combinators.js +53 -16
  21. package/dist/combinators.js.map +1 -1
  22. package/dist/condition.d.ts +37 -0
  23. package/dist/condition.d.ts.map +1 -1
  24. package/dist/condition.js +48 -1
  25. package/dist/condition.js.map +1 -1
  26. package/dist/correspondence.d.ts +30 -0
  27. package/dist/correspondence.d.ts.map +1 -1
  28. package/dist/correspondence.js +36 -1
  29. package/dist/correspondence.js.map +1 -1
  30. package/dist/dedupe-config-findings.d.ts.map +1 -1
  31. package/dist/dedupe-config-findings.js +27 -0
  32. package/dist/dedupe-config-findings.js.map +1 -1
  33. package/dist/diff-aware.d.ts +8 -9
  34. package/dist/diff-aware.d.ts.map +1 -1
  35. package/dist/diff-aware.js +38 -17
  36. package/dist/diff-aware.js.map +1 -1
  37. package/dist/emitter-findings.d.ts +167 -0
  38. package/dist/emitter-findings.d.ts.map +1 -0
  39. package/dist/emitter-findings.js +237 -0
  40. package/dist/emitter-findings.js.map +1 -0
  41. package/dist/errors.d.ts +48 -0
  42. package/dist/errors.d.ts.map +1 -1
  43. package/dist/errors.js +61 -0
  44. package/dist/errors.js.map +1 -1
  45. package/dist/exclusion-comments.d.ts +36 -1
  46. package/dist/exclusion-comments.d.ts.map +1 -1
  47. package/dist/exclusion-comments.js +185 -37
  48. package/dist/exclusion-comments.js.map +1 -1
  49. package/dist/execute-rule.d.ts +12 -3
  50. package/dist/execute-rule.d.ts.map +1 -1
  51. package/dist/execute-rule.js +184 -7
  52. package/dist/execute-rule.js.map +1 -1
  53. package/dist/file-walk.d.ts +22 -0
  54. package/dist/file-walk.d.ts.map +1 -0
  55. package/dist/file-walk.js +51 -0
  56. package/dist/file-walk.js.map +1 -0
  57. package/dist/format-json.d.ts +13 -0
  58. package/dist/format-json.d.ts.map +1 -1
  59. package/dist/format-json.js +24 -0
  60. package/dist/format-json.js.map +1 -1
  61. package/dist/index.d.ts +14 -46
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +13 -41
  64. package/dist/index.js.map +1 -1
  65. package/dist/internal.d.ts +55 -0
  66. package/dist/internal.d.ts.map +1 -0
  67. package/dist/internal.js +92 -0
  68. package/dist/internal.js.map +1 -0
  69. package/dist/mask-non-comment.d.ts +49 -0
  70. package/dist/mask-non-comment.d.ts.map +1 -0
  71. package/dist/mask-non-comment.js +261 -0
  72. package/dist/mask-non-comment.js.map +1 -0
  73. package/dist/owns-empty-discovery.d.ts.map +1 -1
  74. package/dist/owns-empty-discovery.js +12 -4
  75. package/dist/owns-empty-discovery.js.map +1 -1
  76. package/dist/path-suffix.d.ts +57 -0
  77. package/dist/path-suffix.d.ts.map +1 -0
  78. package/dist/path-suffix.js +73 -0
  79. package/dist/path-suffix.js.map +1 -0
  80. package/dist/predicate.d.ts +12 -0
  81. package/dist/predicate.d.ts.map +1 -1
  82. package/dist/predicate.js +20 -1
  83. package/dist/predicate.js.map +1 -1
  84. package/dist/preset-dispatch.d.ts +6 -34
  85. package/dist/preset-dispatch.d.ts.map +1 -1
  86. package/dist/preset-dispatch.js +30 -52
  87. package/dist/preset-dispatch.js.map +1 -1
  88. package/dist/report.d.ts +31 -7
  89. package/dist/report.d.ts.map +1 -1
  90. package/dist/report.js +174 -15
  91. package/dist/report.js.map +1 -1
  92. package/dist/rule-builder-like.d.ts +8 -2
  93. package/dist/rule-builder-like.d.ts.map +1 -1
  94. package/dist/rule-builder.d.ts +15 -0
  95. package/dist/rule-builder.d.ts.map +1 -1
  96. package/dist/rule-builder.js +41 -36
  97. package/dist/rule-builder.js.map +1 -1
  98. package/dist/rule-description.d.ts +50 -0
  99. package/dist/rule-description.d.ts.map +1 -1
  100. package/dist/rule-description.js +58 -0
  101. package/dist/rule-description.js.map +1 -1
  102. package/dist/selection-memo.d.ts +1 -3
  103. package/dist/selection-memo.d.ts.map +1 -1
  104. package/dist/selection-memo.js +1 -3
  105. package/dist/selection-memo.js.map +1 -1
  106. package/dist/silent-exclusion.d.ts +12 -0
  107. package/dist/silent-exclusion.d.ts.map +1 -1
  108. package/dist/silent-exclusion.js +22 -0
  109. package/dist/silent-exclusion.js.map +1 -1
  110. package/dist/terminal-builder.d.ts +29 -15
  111. package/dist/terminal-builder.d.ts.map +1 -1
  112. package/dist/terminal-builder.js +97 -51
  113. package/dist/terminal-builder.js.map +1 -1
  114. package/dist/vacuity-findings.d.ts +0 -6
  115. package/dist/vacuity-findings.d.ts.map +1 -1
  116. package/dist/vacuity-findings.js +27 -57
  117. package/dist/vacuity-findings.js.map +1 -1
  118. package/dist/violation.d.ts +22 -1
  119. package/dist/violation.d.ts.map +1 -1
  120. package/dist/violation.js.map +1 -1
  121. package/dist/watch.d.ts +71 -0
  122. package/dist/watch.d.ts.map +1 -0
  123. package/dist/watch.js +129 -0
  124. package/dist/watch.js.map +1 -0
  125. package/package.json +6 -1
@@ -1,8 +1,7 @@
1
+ import { collectResult } from './collect-result.js';
1
2
  import { severityFor } from './violation.js';
2
3
  import { formatViolations } from './format.js';
3
- import { finishPreset } from './report.js';
4
4
  import { writeStderr } from './stderr.js';
5
- import { UNSUPPRESSABLE } from './unsuppressable.js';
6
5
  /**
7
6
  * Dispatch a single rule within a preset.
8
7
  *
@@ -17,19 +16,34 @@ export function dispatchRule(builder, rule, defaultSeverity, overrides) {
17
16
  // agent`, not just the id.
18
17
  const meta = typeof rule === 'string' ? { id: rule } : rule;
19
18
  const effective = overrides?.[meta.id] ?? defaultSeverity;
20
- if (effective === 'off')
21
- return [];
19
+ if (effective === 'off') {
20
+ // A real, measured zero — and deliberately NOT `declaredEmpty`.
21
+ //
22
+ // ADR-014 §3, amended 2026-09-05: a declaration is one a caller MADE over a
23
+ // live instrument, never one eess infers from a configuration.
24
+ // `overrides: { id: 'off' }` is an instruction, and it is byte-identical
25
+ // whether the author meant "I have scoped this out" or "I turned this off to
26
+ // stop a finding" — eess is not positioned to tell those apart, so by
27
+ // ADR-013's rule it must not decide. Marking it declared here would mint,
28
+ // on the author's behalf, exactly the declaration `declaredEmptyFindings`
29
+ // refuses to let them write ("'off' deleted the rule, so the declaration
30
+ // about it is dead").
31
+ //
32
+ // The consequence is deliberate: a preset with every rule off sums to zero
33
+ // examined with no declaration, and the emitter reports it (bug 0261).
34
+ return collectResult([], { examined: 0, notRun: true });
35
+ }
22
36
  const violations = builder.rule(meta).violations();
23
37
  if (effective === 'warn') {
24
38
  if (violations.length > 0) {
25
39
  writeStderr(formatViolations(violations));
26
40
  }
27
41
  // `bypassFilters` outranks a per-rule `overrides: { id: 'warn' }` — see
28
- // `severityFor`. A config finding like `presetConstructsNothingViolation`
29
- // is `UNSUPPRESSABLE` by its own text; silently dropping it here just
30
- // because its OWN rule was downgraded is exactly the suppression path
31
- // that text promises does not exist.
32
- return violations.filter((v) => severityFor(v, 'warn') === 'error');
42
+ // `severityFor`. A config finding — a zero-examined rule, or a preset that
43
+ // constructed nothing — is `UNSUPPRESSABLE` by its own text; silently
44
+ // dropping it here just because its OWN rule was downgraded is exactly the
45
+ // suppression path that text promises does not exist.
46
+ return collectResult(violations.filter((v) => severityFor(v, 'warn') === 'error'), { examined: violations.examined });
33
47
  }
34
48
  return violations;
35
49
  }
@@ -37,7 +51,13 @@ export function dispatchRule(builder, rule, defaultSeverity, overrides) {
37
51
  * Validate override keys against known rule IDs. Warns for unrecognized keys
38
52
  * (likely typos).
39
53
  */
40
- export function validateOverrides(overrides, knownIds) {
54
+ export function validateOverrides(
55
+ // `Partial<Record<...>>` and `readonly`, widened from the narrower shapes this
56
+ // signature had, so `eess-ts`'s byte-identical copy could be deleted rather
57
+ // than kept for its types. Both are strictly more permissive: `Partial` admits
58
+ // an explicit `undefined` value, `readonly` admits a frozen list. No caller
59
+ // loses anything.
60
+ overrides, knownIds) {
41
61
  if (!overrides)
42
62
  return;
43
63
  const knownSet = new Set(knownIds);
@@ -48,46 +68,4 @@ export function validateOverrides(overrides, knownIds) {
48
68
  }
49
69
  }
50
70
  }
51
- /**
52
- * A configuration finding for a preset call that constructed **zero** rules —
53
- * every optional capability was left off, or a required discovery pattern
54
- * (a folder glob, a repositories glob) matched nothing, so the call checked
55
- * nothing and would otherwise pass silently. The vacuity matrix
56
- * (`scripts/vacuity-matrix.mjs`) is what proves a preset needs this: it
57
- * probes every published preset at its minimal type-correct call, and a
58
- * preset reaching `fail-open` there is exactly this shape.
59
- *
60
- * Unsuppressable (ADR-010) for the same reason a zero-examined rule is: the
61
- * caller's mistake is in how the preset was configured, not in the code the
62
- * preset would have checked, and `.excluding()`/a baseline/`--changed` all
63
- * aim at the latter.
64
- *
65
- * @param presetName - The preset's own name, e.g. `'agentGuardrails'`.
66
- * @param optionsHint - The option names that would enable a rule, for the
67
- * remedy — e.g. `'noGenericErrors, noStubs, noEmptyBodies'`.
68
- */
69
- export function presetConstructsNothingViolation(presetName, optionsHint) {
70
- const message = `${presetName}(...) constructed zero rules at this call — no capability of this ` +
71
- `preset was enabled, or a discovery pattern matched nothing, so it checks nothing ` +
72
- `and passes silently. Enable at least one option (${optionsHint}), or remove the call.`;
73
- return {
74
- rule: presetName,
75
- element: presetName,
76
- file: '',
77
- line: 0,
78
- message,
79
- suggestion: `${message} ${UNSUPPRESSABLE}`,
80
- bypassFilters: true,
81
- };
82
- }
83
- /**
84
- * Emit (stderr text) and throw a single `ArchRuleError` with all aggregated
85
- * violations, if any. Kept for backward compatibility; it is now `finishPreset`
86
- * in the default `throw` mode. New presets take `PresetReportOptions` and call
87
- * `finishPreset` so a caller can opt into `report: 'return'` / `--format json`
88
- * (plan 0070).
89
- */
90
- export function throwIfViolations(violations) {
91
- finishPreset(violations, { report: 'throw' });
92
- }
93
71
  //# sourceMappingURL=preset-dispatch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preset-dispatch.js","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,YAAY,EAA4B,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAuBpD;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAqB,EACrB,IAA8C,EAC9C,eAA6B,EAC7B,SAAmD;IAEnD,8EAA8E;IAC9E,gFAAgF;IAChF,6EAA6E;IAC7E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC3D,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,eAAe,CAAA;IACzD,IAAI,SAAS,KAAK,KAAK;QAAE,OAAO,EAAE,CAAA;IAElC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAA;IAElD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,wEAAwE;QACxE,0EAA0E;QAC1E,sEAAsE;QACtE,sEAAsE;QACtE,qCAAqC;QACrC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,CAAA;IACrE,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAmD,EACnD,QAAkB;IAElB,IAAI,CAAC,SAAS;QAAE,OAAM;IACtB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,WAAW,CACT,wBAAwB,GAAG,4CAA4C;gBACrE,oBAAoB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5C,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gCAAgC,CAC9C,UAAkB,EAClB,WAAmB;IAEnB,MAAM,OAAO,GACX,GAAG,UAAU,oEAAoE;QACjF,mFAAmF;QACnF,oDAAoD,WAAW,wBAAwB,CAAA;IACzF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,UAAU;QACnB,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,CAAC;QACP,OAAO;QACP,UAAU,EAAE,GAAG,OAAO,IAAI,cAAc,EAAE;QAC1C,aAAa,EAAE,IAAI;KACpB,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA2B;IAC3D,YAAY,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;AAC/C,CAAC"}
1
+ {"version":3,"file":"preset-dispatch.js","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAuBzC;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAqB,EACrB,IAA8C,EAC9C,eAA6B,EAC7B,SAAmD;IAEnD,8EAA8E;IAC9E,gFAAgF;IAChF,6EAA6E;IAC7E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC3D,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,eAAe,CAAA;IACzD,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,gEAAgE;QAChE,EAAE;QACF,4EAA4E;QAC5E,+DAA+D;QAC/D,yEAAyE;QACzE,6EAA6E;QAC7E,sEAAsE;QACtE,0EAA0E;QAC1E,0EAA0E;QAC1E,yEAAyE;QACzE,sBAAsB;QACtB,EAAE;QACF,2EAA2E;QAC3E,uEAAuE;QACvE,OAAO,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAA;IAElD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,wEAAwE;QACxE,2EAA2E;QAC3E,sEAAsE;QACtE,2EAA2E;QAC3E,sDAAsD;QACtD,OAAO,aAAa,CAClB,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,EAC5D,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAClC,CAAA;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;AAC/B,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,kBAAkB;AAClB,SAA4D,EAC5D,QAA2B;IAE3B,IAAI,CAAC,SAAS;QAAE,OAAM;IACtB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,WAAW,CACT,wBAAwB,GAAG,4CAA4C;gBACrE,oBAAoB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5C,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
package/dist/report.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ArchViolation } from './violation.js';
1
+ import { type CollectResult } from './collect-result.js';
2
2
  import type { OutputFormat } from './check-options.js';
3
3
  /**
4
4
  * How a preset delivers its violations (plan 0070, ADR-008):
@@ -18,6 +18,30 @@ export interface ReportOptions {
18
18
  export interface PresetReportOptions extends ReportOptions {
19
19
  /** Delivery mode. Default `throw`. */
20
20
  readonly report?: ReportMode;
21
+ /**
22
+ * Declare that this preset's subject legitimately does not exist here —
23
+ * [ADR-010](../../../adr/010-a-pass-is-constructed-from-evidence.md) §3.
24
+ *
25
+ * **On the shared options type, not on six preset interfaces**, because
26
+ * ADR-010 §3's second clause is about presets as a class: "A preset user does
27
+ * not hold the builder; if a preset option cannot carry the user's
28
+ * empty-declaration to the mint, their only reachable remedy is disabling the
29
+ * option — deleting coverage permanently (ADR-009 rule 1's trained-suppression
30
+ * dynamic, reproduced by this ADR's own gate if unaddressed)." A preset that
31
+ * examines nothing and cannot be told so leaves its user exactly one exit, and
32
+ * it is the wrong one.
33
+ *
34
+ * **It expires**, which is the only reason it is admissible at all: declare
35
+ * this and then examine something, and the emitter reports
36
+ * `emitter/expired-declaration`. A claim nothing can contradict is not an
37
+ * assertion — the property ADR-014 §3's 2026-09-05 amendment turns on when it
38
+ * refuses to infer a declaration from `overrides: 'off'`.
39
+ *
40
+ * Use it for a corpus with no ER diagrams, a suite with no exemptions, a
41
+ * project that genuinely has none of this preset's subject. Do not use it to
42
+ * quiet a preset whose glob is wrong: the day the glob is fixed, this reddens.
43
+ */
44
+ readonly expectEmpty?: boolean;
21
45
  }
22
46
  /**
23
47
  * How many violations this module has actually WRITTEN, ever.
@@ -32,13 +56,13 @@ export interface PresetReportOptions extends ReportOptions {
32
56
  * exactly that case. Count emissions, not silences.
33
57
  */
34
58
  export declare function violationsEmittedCount(): number;
35
- export declare function reportViolations(violations: ArchViolation[], options?: ReportOptions): void;
59
+ export declare function reportViolations(violations: CollectResult, options?: ReportOptions): CollectResult;
36
60
  /**
37
61
  * Finish a preset: deliver its aggregated violations per the requested mode
38
- * (plan 0070). `throw` (default) emits then throws — backward-compatible with
39
- * `throwIfViolations`; `return` hands the violations back untouched (the caller
40
- * owns emission and control flow); `warn` emits without throwing. Always
41
- * returns the violations, so a caller can inspect them regardless of mode.
62
+ * (plan 0070). `throw` (default) emits then throws; `return` hands the
63
+ * violations back untouched (the caller owns emission and control flow);
64
+ * `warn` emits without throwing. Always returns the violations, so a caller can
65
+ * inspect them regardless of mode.
42
66
  */
43
- export declare function finishPreset(violations: ArchViolation[], options?: PresetReportOptions): ArchViolation[];
67
+ export declare function finishPreset(violations: CollectResult, options?: PresetReportOptions): CollectResult;
44
68
  //# sourceMappingURL=report.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAMtD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEpD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAA;CAC7B;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,IAAI,CAa/F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,EAAE,EAC3B,OAAO,GAAE,mBAAwB,GAChC,aAAa,EAAE,CAQjB"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAA8B,MAAM,qBAAqB,CAAA;AAUpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAMtD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEpD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAA;IAE5B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAC/B;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA6HD,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CAqBf;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,mBAAwB,GAChC,aAAa,CAoCf"}
package/dist/report.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { collectResult, hasEvidence } from './collect-result.js';
2
+ import { isEmitterFinding, noReceiptViolation, sourceEmptyViolation, passWithoutEvidenceViolation, expiredDeclarationViolation, contradictoryEvidenceViolation, } from './emitter-findings.js';
1
3
  import { ArchRuleError } from './errors.js';
2
4
  import { formatViolations } from './format.js';
3
5
  import { formatViolationsJson } from './format-json.js';
@@ -25,38 +27,195 @@ let violationsEmitted = 0;
25
27
  export function violationsEmittedCount() {
26
28
  return violationsEmitted;
27
29
  }
30
+ /**
31
+ * The evidence gate both emitters share — ADR-014 §1, §4.
32
+ *
33
+ * Produced BEFORE the delivery mode is chosen, so the finding is in the value
34
+ * returned under `return`, rides the throw under `throw`, and is in the text
35
+ * written under `warn`. A contract that binds only one door does not bind.
36
+ *
37
+ * A value that already carries a finding passes through untouched (§4): a
38
+ * terminal that examined nothing has already named its own cause, and "you
39
+ * constructed nothing" beside "your glob is dead" is a false second remedy.
40
+ */
41
+ function withEvidenceGate(violations) {
42
+ // Deliberately looser than the exported signatures. The TYPE refuses a bare
43
+ // array (D1/D2); this guard is for the untyped JavaScript caller the type
44
+ // cannot reach — ADR-014's stated residual, and the field failure in
45
+ // proposal 009 was exactly that consumer.
46
+ if (!hasEvidence(violations)) {
47
+ return collectResult([...violations, noReceiptViolation()], { examined: 0 });
48
+ }
49
+ // Expiry FIRST, and before the `examined > 0` exit — ADR-014 §3. A declaration
50
+ // that cannot be contradicted is not an assertion, which is the whole reason
51
+ // §3's amendment refuses to infer one from a config. Checked even when real
52
+ // violations are present: the declaration is wrong independently of them.
53
+ if (violations.declaredEmpty === true && violations.examined > 0) {
54
+ return collectResult([...violations, expiredDeclarationViolation(violations.examined)], {
55
+ examined: violations.examined,
56
+ sourceEmpty: violations.sourceEmpty,
57
+ });
58
+ }
59
+ // The same check for the third state — ADR-014 §3, added after review found
60
+ // `notRun` shipped as a suppressor with no falsifier while `declaredEmpty` had
61
+ // one. A rule that never ran examined nothing and found nothing; either half
62
+ // present contradicts the flag, and BOTH are read because either alone would
63
+ // leave the other as an unchecked claim.
64
+ //
65
+ // Before the two exits below, deliberately: `examined > 0` is precisely the
66
+ // state that contradicts `notRun`, so checking after them would make the
67
+ // finding unreachable — the mistake this ADR's §2 warns about in its own
68
+ // implementation notes.
69
+ if (violations.notRun === true && (violations.examined > 0 || violations.length > 0)) {
70
+ return collectResult([...violations, contradictoryEvidenceViolation(violations.examined, violations.length)], { examined: violations.examined, sourceEmpty: violations.sourceEmpty });
71
+ }
72
+ // **`sourceEmpty` beside real evidence is a contradiction, like its siblings.**
73
+ // A source that loaded nothing cannot have yielded units to examine — the flag
74
+ // is set precisely when `examined === 0`. Checked before the two exits below,
75
+ // for the same reason the `notRun` check above is: after them it would be
76
+ // unreachable.
77
+ //
78
+ // Without this, `sourceEmpty` was the one flag in the vocabulary that could
79
+ // quiet a zero and never be contradicted — `notRun` beside evidence is
80
+ // `emitter/contradictory-evidence`, `declaredEmpty` beside evidence is
81
+ // `emitter/expired-declaration`, and `{ examined: 900, sourceEmpty: true }` was
82
+ // silent. That asymmetry is what ADR-014's "every flag that can quiet a zero
83
+ // can be contradicted" row exists to refuse, and promoting `sourceEmpty` to a
84
+ // verdict-changing flag with its own id is what put it in scope.
85
+ if (violations.sourceEmpty === true && violations.examined > 0) {
86
+ return collectResult([
87
+ ...violations,
88
+ contradictoryEvidenceViolation(violations.examined, violations.length, 'sourceEmpty'),
89
+ ], { examined: violations.examined });
90
+ }
91
+ if (violations.length > 0)
92
+ return violations;
93
+ if (violations.examined > 0)
94
+ return violations;
95
+ // **An empty source outranks any declaration, and names the source** — ADR-014
96
+ // §4, and ADR-010 §3's own `gated` row ("Zero loaded source files outranks any
97
+ // `.expectEmpty()` declaration") which the terminal has always honoured.
98
+ //
99
+ // This branch is checked BEFORE `declaredEmpty` and `notRun`, and that ordering
100
+ // is the whole point. The comment that used to sit here said `sourceEmpty` does
101
+ // not legitimise a zero — and the next line returned green on `declaredEmpty`
102
+ // without ever reading it. Measured:
103
+ // `finishPreset(collectResult([], { examined: 0, sourceEmpty: true, declaredEmpty: true }))`
104
+ // was GREEN. A hand-assembled receipt claiming an empty source and declaring it
105
+ // away is precisely the escape hatch that comment claimed this ADR had closed.
106
+ //
107
+ // A terminal that loaded nothing already carries `zeroLoadedSourceViolation` and
108
+ // exits at the `length > 0` line above, so this fires for the hand-assembled
109
+ // receipt — the population ADR-014's gate exists for.
110
+ if (violations.sourceEmpty === true) {
111
+ return collectResult([...violations, sourceEmptyViolation()], {
112
+ examined: violations.examined,
113
+ sourceEmpty: true,
114
+ // The input's own declarations are carried through, not dropped. They do
115
+ // not rescue the verdict — that is the precedence this branch enforces —
116
+ // but a downstream reader still needs to know they were made, and the
117
+ // sibling branches above preserve what they were handed for the same
118
+ // reason.
119
+ declaredEmpty: violations.declaredEmpty,
120
+ notRun: violations.notRun,
121
+ deadGlob: violations.deadGlob,
122
+ });
123
+ }
124
+ if (violations.declaredEmpty === true)
125
+ return violations;
126
+ // `notRun` legitimises a zero here for the same reason `declaredEmpty` does,
127
+ // and for the reason the MERGE already exempts it: a rule turned off examined
128
+ // nothing and found nothing, and reporting that as a vacuous pass is the
129
+ // "one disabled rule reddens a whole preset" failure `notRun` was added to
130
+ // prevent (measured on `adrEnforcement` with `adr/valid-tiers` off).
131
+ //
132
+ // **The two doors disagreed until this line.** `mergeCollectResults` exempts a
133
+ // `notRun` member from its dead filter; this gate had no such branch, so the
134
+ // per-builder doors judged an off rule alone and reddened it. Measured:
135
+ // `checkAll([healthy, off])` was GREEN while `eess-ts check` over the same two
136
+ // builders reported `1 of 2 rules failing`. Same receipts, opposite verdicts,
137
+ // decided by which door you walked through — and `check.ts` claimed per-builder
138
+ // gating was "strictly stronger, not weaker", which is how a false positive is
139
+ // manufactured.
140
+ //
141
+ // It is not a mute button: a `notRun` beside a non-zero `examined` or any
142
+ // violation is `emitter/contradictory-evidence`, checked above and reached
143
+ // before this line. And the all-off case still reports, because the merged
144
+ // receipt carries no `notRun` — so a preset whose every member is off sums to
145
+ // zero examined, undeclared, and reds exactly as ADR-014 §3 requires.
146
+ if (violations.notRun === true)
147
+ return violations;
148
+ return collectResult([passWithoutEvidenceViolation()], { examined: violations.examined });
149
+ }
28
150
  export function reportViolations(violations, options = {}) {
29
- if (violations.length === 0)
30
- return;
31
- violationsEmitted += violations.length;
151
+ const gated = withEvidenceGate(violations);
152
+ if (gated.length === 0)
153
+ return gated;
154
+ violationsEmitted += gated.length;
32
155
  const format = options.format ?? 'terminal';
33
156
  if (format === 'json') {
34
- process.stdout.write(formatViolationsJson(violations, options.reason) + '\n');
157
+ process.stdout.write(formatViolationsJson(gated, options.reason) + '\n');
35
158
  }
36
159
  else if (format === 'github') {
37
- process.stdout.write(formatViolationsGitHub(violations, 'error') + '\n');
160
+ process.stdout.write(formatViolationsGitHub(gated, 'error') + '\n');
38
161
  }
39
162
  else {
40
163
  // Rich text to stderr — test runners show the plain-text Error message,
41
164
  // while stderr carries the colorized Why/Fix/Docs output.
42
- process.stderr.write(formatViolations(violations, options.reason) + '\n');
165
+ process.stderr.write(formatViolations(gated, options.reason) + '\n');
166
+ }
167
+ // ADR-014 §5: a bare `reportViolations` hands nothing back that a caller must
168
+ // act on, so a printed unsuppressable finding above a zero exit is the lie by
169
+ // another name. The gate's own finding escalates to a throw here.
170
+ if (gated.some((v) => v.bypassFilters === true && isEmitterFinding(v))) {
171
+ throw new ArchRuleError(gated, options.reason);
43
172
  }
173
+ return gated;
44
174
  }
45
175
  /**
46
176
  * Finish a preset: deliver its aggregated violations per the requested mode
47
- * (plan 0070). `throw` (default) emits then throws — backward-compatible with
48
- * `throwIfViolations`; `return` hands the violations back untouched (the caller
49
- * owns emission and control flow); `warn` emits without throwing. Always
50
- * returns the violations, so a caller can inspect them regardless of mode.
177
+ * (plan 0070). `throw` (default) emits then throws; `return` hands the
178
+ * violations back untouched (the caller owns emission and control flow);
179
+ * `warn` emits without throwing. Always returns the violations, so a caller can
180
+ * inspect them regardless of mode.
51
181
  */
52
182
  export function finishPreset(violations, options = {}) {
53
183
  const mode = options.report ?? 'throw';
184
+ // A caller's declaration reaches the gate ON the receipt (ADR-014 §3), never
185
+ // as a delivery option the gate reads separately — one boolean beside a sum
186
+ // cannot be weighed against that sum's parts.
187
+ const declared = options.expectEmpty === true && !violations.declaredEmpty
188
+ ? collectResult(violations, {
189
+ examined: violations.examined,
190
+ sourceEmpty: violations.sourceEmpty,
191
+ deadGlob: violations.deadGlob,
192
+ declaredEmpty: true,
193
+ })
194
+ : violations;
195
+ // The gate runs before the mode is read, so every door carries the finding.
196
+ const gated = withEvidenceGate(declared);
54
197
  if (mode === 'return')
55
- return violations;
56
- reportViolations(violations, options);
57
- if (mode === 'throw' && violations.length > 0) {
58
- throw new ArchRuleError(violations, options.reason);
198
+ return gated;
199
+ const emitterFinding = gated.some((v) => isEmitterFinding(v));
200
+ if (gated.length > 0) {
201
+ violationsEmitted += gated.length;
202
+ const format = options.format ?? 'terminal';
203
+ if (format === 'json') {
204
+ process.stdout.write(formatViolationsJson(gated, options.reason) + '\n');
205
+ }
206
+ else if (format === 'github') {
207
+ process.stdout.write(formatViolationsGitHub(gated, 'error') + '\n');
208
+ }
209
+ else {
210
+ process.stderr.write(formatViolations(gated, options.reason) + '\n');
211
+ }
212
+ }
213
+ // §5 again: `warn` prints without failing for ordinary violations, but an
214
+ // unsuppressable configuration finding printed above a zero exit is exactly
215
+ // the silent green this ADR closes.
216
+ if ((mode === 'throw' && gated.length > 0) || emitterFinding) {
217
+ throw new ArchRuleError(gated, options.reason);
59
218
  }
60
- return violations;
219
+ return gated;
61
220
  }
62
221
  //# sourceMappingURL=report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAwB3D;;;;;;GAMG;AACH,IAAI,iBAAiB,GAAG,CAAC,CAAA;AAEzB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,iBAAiB,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAA2B,EAAE,UAAyB,EAAE;IACvF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IACnC,iBAAiB,IAAI,UAAU,CAAC,MAAM,CAAA;IACtC,MAAM,MAAM,GAAiB,OAAO,CAAC,MAAM,IAAI,UAAU,CAAA;IACzD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAA;IAC/E,CAAC;SAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAC1E,CAAC;SAAM,CAAC;QACN,wEAAwE;QACxE,0DAA0D;QAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAA;IAC3E,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,UAA2B,EAC3B,UAA+B,EAAE;IAEjC,MAAM,IAAI,GAAe,OAAO,CAAC,MAAM,IAAI,OAAO,CAAA;IAClD,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAA;IACxC,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACrC,IAAI,IAAI,KAAK,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACrD,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,17 @@
1
- import type { ArchViolation } from './violation.js';
1
+ import type { CollectResult } from './collect-result.js';
2
2
  /**
3
3
  * Minimal shape the CLI runner and presets collect violations from: anything
4
4
  * exposing a non-throwing, severity-stamped `.violations()`. Lives in core (not
5
5
  * `cli/`) so presets can return `RuleBuilderLike[]` without depending on CLI
6
6
  * infrastructure.
7
+ *
8
+ * **The single member carries the evidence** — plan 0235's D1. An accessor
9
+ * beside it could be walked around: a caller keeps calling `violations()`,
10
+ * never asks for the count, and the evidence is optional again by another
11
+ * route. One member, and it hands back the receipt, so a rule file that cannot
12
+ * say what it examined does not compile.
7
13
  */
8
14
  export interface RuleBuilderLike {
9
- violations: () => ArchViolation[];
15
+ violations: () => CollectResult;
10
16
  }
11
17
  //# sourceMappingURL=rule-builder-like.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-builder-like.d.ts","sourceRoot":"","sources":["../src/rule-builder-like.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,aAAa,EAAE,CAAA;CAClC"}
1
+ {"version":3,"file":"rule-builder-like.d.ts","sourceRoot":"","sources":["../src/rule-builder-like.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,aAAa,CAAA;CAChC"}
@@ -4,6 +4,21 @@ import type { RuleDescription } from './rule-description.js';
4
4
  import type { Selection, ElementInfo } from './correspondence.js';
5
5
  import type { GlobNode } from './glob-site.js';
6
6
  import { TerminalBuilder, type CollectResult } from './terminal-builder.js';
7
+ /**
8
+ * The actual walk `RuleBuilder.globs()` delegates to — a free function
9
+ * rather than a method body, to keep the class itself under this repo's own
10
+ * 300-line class-length gate (`arch.internal.rules.ts`).
11
+ */
12
+ /**
13
+ * The globs a rule declares, stamped with where each came from.
14
+ *
15
+ * Exported (as family plumbing) so `eess-ts` can call it instead of keeping its
16
+ * own copy — they were 94% similar, and the difference was not cosmetic: only
17
+ * the eess-ts copy honoured `originLabel`. The kernel's `Predicate` has carried
18
+ * that field all along and this function ignored it, so a preset's label was
19
+ * dropped for `eess-md`, `eess-mermaid` and `eess-gherkin`. Found by unifying.
20
+ */
21
+ export declare function declaredGlobsOf<T>(predicates: readonly Predicate<T>[], conditions: readonly Condition<T>[]): GlobNode[];
7
22
  /**
8
23
  * Abstract base class for all rule builders.
9
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"rule-builder.d.ts","sourceRoot":"","sources":["../src/rule-builder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,KAAK,EAAgB,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE5D,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAA0B,MAAM,uBAAuB,CAAA;AA6CnG;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8BAAsB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAE,SAAQ,eAAe;IAc3D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAbzC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAK;IAC1C,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAK;IAC1C,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAAc;IACzD,4EAA4E;IAC5E,SAAS,CAAC,cAAc,UAAQ;IAChC;;;;;OAKG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,CAAK;gBAEJ,OAAO,EAAE,CAAC;IAMzC;;;;;OAKG;IACH,IAAI,IAAI,IAAI;IAMZ;;;OAGG;IACH,GAAG,IAAI,IAAI;IAIX;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAOd;;;OAGG;IACH,SAAS,IAAI,IAAI;IAIjB;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAelD;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,WAAW,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC,CAAC;IAOpF;;;OAGG;IACH,YAAY,IAAI,eAAe;IAW/B;;;;;;;;;;;;;;;;;;OAkBG;IACH;;;;;;;OAOG;IACH,SAAS,CAAC,gBAAgB,IAAI,OAAO;IAIrC,SAAS,CAAC,eAAe,IAAI,MAAM;cAQhB,kBAAkB,IAAI,OAAO;IAKhD;;;;;;;;;;OAUG;IACH,SAAS,CAAC,WAAW,IAAI,OAAO;IAIhC,4EAA4E;IAC5E,KAAK,IAAI,SAAS,QAAQ,EAAE;IAI5B,6EAA6E;IAC7E,UAAU,IAAI,CAAC;IAIf,6FAA6F;IAC7F,SAAS,CAAC,iBAAiB,IAAI,MAAM,GAAG,SAAS;IAMjD;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAWrD;;;OAGG;IACH,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;IAMrD;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,EAAE;IAErC;;;;;;;;;OASG;cACgB,IAAI,IAAI,IAAI;IAQ/B;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,IAAI,IAAI,IAAI;IAQtB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,iBAAiB,IAAI,aAAa;IAuC5C;;;;;;OAMG;IACH,SAAS,CAAC,qBAAqB,IAAI,gBAAgB;CASpD"}
1
+ {"version":3,"file":"rule-builder.d.ts","sourceRoot":"","sources":["../src/rule-builder.ts"],"names":[],"mappings":"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"}