@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.
- package/README.md +94 -1
- package/dist/baseline-generator.d.ts +9 -0
- package/dist/baseline-generator.d.ts.map +1 -1
- package/dist/baseline-generator.js +9 -0
- package/dist/baseline-generator.js.map +1 -1
- package/dist/baseline.d.ts +1 -1
- package/dist/cardinality.d.ts.map +1 -1
- package/dist/cardinality.js +20 -5
- package/dist/cardinality.js.map +1 -1
- package/dist/cli-config.d.ts +59 -0
- package/dist/cli-config.d.ts.map +1 -0
- package/dist/cli-config.js +84 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/collect-result.d.ts +94 -0
- package/dist/collect-result.d.ts.map +1 -0
- package/dist/collect-result.js +142 -0
- package/dist/collect-result.js.map +1 -0
- package/dist/combinators.d.ts +14 -0
- package/dist/combinators.d.ts.map +1 -1
- package/dist/combinators.js +53 -16
- package/dist/combinators.js.map +1 -1
- package/dist/condition.d.ts +37 -0
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +48 -1
- package/dist/condition.js.map +1 -1
- package/dist/correspondence.d.ts +30 -0
- package/dist/correspondence.d.ts.map +1 -1
- package/dist/correspondence.js +36 -1
- package/dist/correspondence.js.map +1 -1
- package/dist/dedupe-config-findings.d.ts.map +1 -1
- package/dist/dedupe-config-findings.js +27 -0
- package/dist/dedupe-config-findings.js.map +1 -1
- package/dist/diff-aware.d.ts +8 -9
- package/dist/diff-aware.d.ts.map +1 -1
- package/dist/diff-aware.js +38 -17
- package/dist/diff-aware.js.map +1 -1
- package/dist/emitter-findings.d.ts +167 -0
- package/dist/emitter-findings.d.ts.map +1 -0
- package/dist/emitter-findings.js +237 -0
- package/dist/emitter-findings.js.map +1 -0
- package/dist/errors.d.ts +48 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +61 -0
- package/dist/errors.js.map +1 -1
- package/dist/exclusion-comments.d.ts +36 -1
- package/dist/exclusion-comments.d.ts.map +1 -1
- package/dist/exclusion-comments.js +185 -37
- package/dist/exclusion-comments.js.map +1 -1
- package/dist/execute-rule.d.ts +12 -3
- package/dist/execute-rule.d.ts.map +1 -1
- package/dist/execute-rule.js +184 -7
- package/dist/execute-rule.js.map +1 -1
- package/dist/file-walk.d.ts +22 -0
- package/dist/file-walk.d.ts.map +1 -0
- package/dist/file-walk.js +51 -0
- package/dist/file-walk.js.map +1 -0
- package/dist/format-json.d.ts +13 -0
- package/dist/format-json.d.ts.map +1 -1
- package/dist/format-json.js +24 -0
- package/dist/format-json.js.map +1 -1
- package/dist/index.d.ts +14 -46
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -41
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +55 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +92 -0
- package/dist/internal.js.map +1 -0
- package/dist/mask-non-comment.d.ts +49 -0
- package/dist/mask-non-comment.d.ts.map +1 -0
- package/dist/mask-non-comment.js +261 -0
- package/dist/mask-non-comment.js.map +1 -0
- package/dist/owns-empty-discovery.d.ts.map +1 -1
- package/dist/owns-empty-discovery.js +12 -4
- package/dist/owns-empty-discovery.js.map +1 -1
- package/dist/path-suffix.d.ts +57 -0
- package/dist/path-suffix.d.ts.map +1 -0
- package/dist/path-suffix.js +73 -0
- package/dist/path-suffix.js.map +1 -0
- package/dist/predicate.d.ts +12 -0
- package/dist/predicate.d.ts.map +1 -1
- package/dist/predicate.js +20 -1
- package/dist/predicate.js.map +1 -1
- package/dist/preset-dispatch.d.ts +6 -34
- package/dist/preset-dispatch.d.ts.map +1 -1
- package/dist/preset-dispatch.js +30 -52
- package/dist/preset-dispatch.js.map +1 -1
- package/dist/report.d.ts +31 -7
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +174 -15
- package/dist/report.js.map +1 -1
- package/dist/rule-builder-like.d.ts +8 -2
- package/dist/rule-builder-like.d.ts.map +1 -1
- package/dist/rule-builder.d.ts +15 -0
- package/dist/rule-builder.d.ts.map +1 -1
- package/dist/rule-builder.js +41 -36
- package/dist/rule-builder.js.map +1 -1
- package/dist/rule-description.d.ts +50 -0
- package/dist/rule-description.d.ts.map +1 -1
- package/dist/rule-description.js +58 -0
- package/dist/rule-description.js.map +1 -1
- package/dist/selection-memo.d.ts +1 -3
- package/dist/selection-memo.d.ts.map +1 -1
- package/dist/selection-memo.js +1 -3
- package/dist/selection-memo.js.map +1 -1
- package/dist/silent-exclusion.d.ts +12 -0
- package/dist/silent-exclusion.d.ts.map +1 -1
- package/dist/silent-exclusion.js +22 -0
- package/dist/silent-exclusion.js.map +1 -1
- package/dist/terminal-builder.d.ts +29 -15
- package/dist/terminal-builder.d.ts.map +1 -1
- package/dist/terminal-builder.js +97 -51
- package/dist/terminal-builder.js.map +1 -1
- package/dist/vacuity-findings.d.ts +0 -6
- package/dist/vacuity-findings.d.ts.map +1 -1
- package/dist/vacuity-findings.js +27 -57
- package/dist/vacuity-findings.js.map +1 -1
- package/dist/violation.d.ts +22 -1
- package/dist/violation.d.ts.map +1 -1
- package/dist/violation.js.map +1 -1
- package/dist/watch.d.ts +71 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +129 -0
- package/dist/watch.js.map +1 -0
- package/package.json +6 -1
package/dist/preset-dispatch.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
29
|
-
// is `UNSUPPRESSABLE` by its own text; silently
|
|
30
|
-
// because its OWN rule was downgraded is exactly the
|
|
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(
|
|
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":"
|
|
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
|
|
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:
|
|
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
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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:
|
|
67
|
+
export declare function finishPreset(violations: CollectResult, options?: PresetReportOptions): CollectResult;
|
|
44
68
|
//# sourceMappingURL=report.d.ts.map
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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(
|
|
157
|
+
process.stdout.write(formatViolationsJson(gated, options.reason) + '\n');
|
|
35
158
|
}
|
|
36
159
|
else if (format === 'github') {
|
|
37
|
-
process.stdout.write(formatViolationsGitHub(
|
|
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(
|
|
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
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
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
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
|
|
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
|
|
219
|
+
return gated;
|
|
61
220
|
}
|
|
62
221
|
//# sourceMappingURL=report.js.map
|
package/dist/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import type {
|
|
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: () =>
|
|
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,
|
|
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"}
|
package/dist/rule-builder.d.ts
CHANGED
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"rule-builder.d.ts","sourceRoot":"","sources":["../src/rule-builder.ts"],"names":[],"mappings":"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"}
|