@archwall/core 0.1.0 → 0.2.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/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as THIRD_PARTY_KINDS, A as primarySourceLocation, B as GraphDelivery, C as ViolationLocation, D as locationsOf, E as fingerprintOf, F as defineClassifier, G as MODULE_ID_SCHEMES, H as GraphMutation, I as Capability, J as ModuleKind, K as ModuleId, L as Edge, M as Classifier, N as ClassifierContext, O as primaryEdge, P as TagPatch, Q as SourceLocation, R as EdgeKind, S as ViolationInput, T as countBySeverity, U as HostInfo, W as IR_VERSION, X as ProjectGraph, Y as ModuleNode, Z as ProjectGraphInit, _ as WellKnownDiagnosticCode, a as defineGraphComputation, at as isFirstParty, b as SeverityCounts, c as GraphQuery, et as WellKnownCapability, f as Diagnostic, g as RuleSkippedDetails, h as EmptyScopeDetails, i as GraphComputation, it as irMajor, j as renderMessage, k as primaryModule, l as ModuleFilter, m as DiagnosticSeverity, n as TransformContext, nt as assertIrCompatible, o as EdgeFilter, ot as isThirdParty, p as DiagnosticCode, q as ModuleIdScheme, r as defineTransform, rt as displayModuleId, st as parseModuleId, t as GraphTransform, tt as WellKnownEdgeKind, u as ModuleSelection, v as FINGERPRINT_SCHEME, w as compareViolations, x as Violation, y as Severity, z as FIRST_PARTY_KINDS } from "./transform-CnUPOO0E.cjs";
1
+ import { $ as ProjectGraph, A as primaryEdge, B as EdgeAttributes, C as Violation, D as countBySeverity, E as compareViolations, F as ClassifierContext, G as GraphMutation, H as FIRST_PARTY_KINDS, I as TagPatch, J as MODULE_ID_SCHEMES, K as HostInfo, L as defineClassifier, M as primarySourceLocation, N as renderMessage, O as fingerprintOf, P as Classifier, Q as ModuleNode, R as Capability, S as SeverityCounts, T as ViolationLocation, U as GraphDelivery, V as EdgeKind, X as ModuleIdScheme, Y as ModuleId, Z as ModuleKind, _ as RuleSkippedDetails, a as defineGraphComputation, at as assertIrCompatible, b as FINGERPRINT_SCHEME, ct as isFirstParty, d as ModuleSelection, et as ProjectGraphInit, g as EmptyScopeDetails, h as DiagnosticSeverity, i as GraphComputation, it as WellKnownEdgeKind, j as primaryModule, k as locationsOf, l as GraphView, lt as isThirdParty, m as DiagnosticCode, n as TransformContext, nt as THIRD_PARTY_KINDS, o as EdgeFilter, ot as displayModuleId, p as Diagnostic, q as IR_VERSION, r as defineTransform, rt as WellKnownCapability, st as irMajor, t as GraphTransform, tt as SourceLocation, u as ModuleFilter, ut as parseModuleId, v as UnscannableFilesDetails, w as ViolationInput, x as Severity, y as WellKnownDiagnosticCode, z as Edge } from "./transform-CzxyWbUC.cjs";
2
2
  //#region src/analysis/scc.d.ts
3
3
  /**
4
4
  * Strongly connected components over static+reexport edges (a dynamic import is a
@@ -110,8 +110,26 @@ interface RuleRunInfo {
110
110
  deprecated?: boolean;
111
111
  }
112
112
  interface AnalysisResult {
113
- /** Deterministically ordered; see `compareViolations`. */
113
+ /**
114
+ * Findings that COUNT — the ones `failOn` gates and reporters lead with. Deterministically
115
+ * ordered; see `compareViolations`.
116
+ */
114
117
  violations: readonly Violation[];
118
+ /**
119
+ * Findings matched by the baseline and therefore not counted, in the same order.
120
+ *
121
+ * Separate from `violations` rather than a flag on them, because every consumer that exists
122
+ * wants the un-suppressed set by default: a reporter that had to remember to filter would
123
+ * eventually forget, and the failure would be an enforcement tool quietly counting findings
124
+ * the user already accepted.
125
+ *
126
+ * Always present, empty when no baseline is configured — so a reporter written today needs
127
+ * no change when baselines arrive, and `violations.length + suppressed.length` is the total
128
+ * the analysis actually found.
129
+ *
130
+ * @see UserConfig.baseline
131
+ */
132
+ suppressed: readonly Violation[];
115
133
  /** Everything that is not a violation: skipped rules, crashed rules, config problems. */
116
134
  diagnostics: readonly Diagnostic[];
117
135
  stats: AnalysisStats;
@@ -205,7 +223,7 @@ interface RuleMeta<Options> {
205
223
  }
206
224
  interface RuleContext<Options> {
207
225
  options: Options;
208
- graph: GraphQuery;
226
+ graph: GraphView;
209
227
  /**
210
228
  * Absolute source root. The base for any path *pattern* a rule matches against, so that
211
229
  * rule options read the same way as classifier patterns and `include`/`exclude`.
@@ -443,6 +461,23 @@ interface FailOnDiagnostics {
443
461
  invalidConfig?: boolean;
444
462
  /** A configured rule is deprecated. Default false. */
445
463
  deprecated?: boolean;
464
+ /**
465
+ * In-boundary files the producer could not read, and so never analysed. Default false.
466
+ *
467
+ * Default false only because turning it on would fail CI for every Vue/Svelte/Astro project
468
+ * the moment they upgrade, and a warning they can see beats an error they revert. Turn it on
469
+ * in any repository where "ArchWall looked at all of it" is load-bearing — which, for a tool
470
+ * whose whole failure mode is passing green without looking, is most of them.
471
+ */
472
+ unscannableFiles?: boolean;
473
+ /**
474
+ * The baseline contains entries this run did not match. Default false.
475
+ *
476
+ * False by default because the common cause is the good one — somebody fixed something — and
477
+ * failing CI for that punishes exactly the behaviour the baseline exists to encourage. Teams
478
+ * that want the file kept honest turn it on and prune as they go.
479
+ */
480
+ baselineStale?: boolean;
446
481
  }
447
482
  interface ResolvedFailOnDiagnostics {
448
483
  ruleFailed: boolean;
@@ -452,6 +487,8 @@ interface ResolvedFailOnDiagnostics {
452
487
  invalidOptions: boolean;
453
488
  invalidConfig: boolean;
454
489
  deprecated: boolean;
490
+ unscannableFiles: boolean;
491
+ baselineStale: boolean;
455
492
  }
456
493
  /**
457
494
  * Which diagnostic codes each `failOnDiagnostics` switch governs, and whether it is on by
@@ -494,6 +531,14 @@ declare const DIAGNOSTIC_GATES: {
494
531
  readonly codes: readonly ["rule-deprecated"];
495
532
  readonly default: false;
496
533
  };
534
+ readonly unscannableFiles: {
535
+ readonly codes: readonly ["unscannable-files"];
536
+ readonly default: false;
537
+ };
538
+ readonly baselineStale: {
539
+ readonly codes: readonly ["baseline-stale"];
540
+ readonly default: false;
541
+ };
497
542
  };
498
543
  /**
499
544
  * Applies {@link DIAGNOSTIC_GATES}' defaults to whatever the user left unset.
@@ -587,6 +632,18 @@ interface UserConfig {
587
632
  * `{ reporter, output }` to send one somewhere other than stdout. Default ["console"].
588
633
  */
589
634
  reporters?: ReporterSpec[];
635
+ /**
636
+ * Path to a baseline file of accepted violations, relative to {@link repoRoot}.
637
+ *
638
+ * RESERVED — declared, resolved, and carried on `ResolvedConfig`, but not yet read. See
639
+ * `AnalysisResult.suppressed`.
640
+ *
641
+ * A graph-based linter has no other suppression mechanism available: with no source text
642
+ * there can be no `// archwall-ignore`, so accepting existing findings has to be a file
643
+ * keyed on violation fingerprints. That is what makes ArchWall adoptable on a codebase that
644
+ * did not start with it — the alternative is 400 violations on day one and an uninstall.
645
+ */
646
+ baseline?: string;
590
647
  /** Which VIOLATION severity gates the run. `info` findings never fail it. */
591
648
  failOn?: FailOn;
592
649
  /** Which DIAGNOSTICS gate the run, regardless of `failOn`. */
@@ -607,6 +664,8 @@ interface ResolvedRule {
607
664
  interface ResolvedConfig {
608
665
  /** Absolute. Base for reported paths and fingerprints. */
609
666
  repoRoot: string;
667
+ /** Absolute path to the baseline file, or null. RESERVED; see {@link UserConfig.baseline}. */
668
+ baseline: string | null;
610
669
  /** Absolute, at or below {@link repoRoot}. Base for the boundary and classifiers. */
611
670
  sourceRoot: string;
612
671
  include: string[];
@@ -633,12 +692,41 @@ declare function resolveConfig(user: UserConfig, opts?: {
633
692
  }): ResolvedConfig;
634
693
  //#endregion
635
694
  //#region src/engine/analyze.d.ts
695
+ /**
696
+ * Per-call knobs, kept OUT of {@link ResolvedConfig}.
697
+ *
698
+ * The distinction is load-bearing: `ResolvedConfig` is the user's declared policy, is
699
+ * serialisable, and is the same for every run. These are properties of one invocation. Folding
700
+ * a cancellation token into the config would make the config unserialisable and would mean two
701
+ * runs of "the same configuration" were not comparable.
702
+ *
703
+ * The parameter exists now, ahead of most of its contents, on purpose: adding a third parameter
704
+ * later is free, but adding it *after* third parties have wrapped `analyze` is not, and every
705
+ * capability that wants a per-call channel (progress, logging, cancellation, incremental reuse)
706
+ * would otherwise arrive as its own breaking change.
707
+ */
708
+ interface AnalyzeOptions {
709
+ /**
710
+ * Aborts the run between rules. Honoured at rule-dispatch boundaries, not mid-traversal:
711
+ * a rule sees the whole slice it was given or none of it, so a cancelled run never produces
712
+ * the partial findings {@link RuleRun.crashed} exists to discard.
713
+ */
714
+ signal?: AbortSignal;
715
+ /**
716
+ * RESERVED, and currently ignored. The previous run's result, for incremental reuse.
717
+ *
718
+ * Declared before it is honoured so that the eventual implementation is a behaviour change
719
+ * rather than a signature change. Passing it today is safe and does nothing; do not write
720
+ * code that depends on it having an effect.
721
+ */
722
+ previous?: AnalysisResult;
723
+ }
636
724
  /**
637
725
  * The engine: prepare the graph (boundary → transforms → classify), then check it.
638
726
  *
639
727
  * Pure — no I/O, no reporter calls; reporters are driven by the run edge (integration-kit).
640
728
  */
641
- declare function analyze(graph: ProjectGraph, config: ResolvedConfig): Promise<AnalysisResult>;
729
+ declare function analyze(graph: ProjectGraph, config: ResolvedConfig, options?: AnalyzeOptions): Promise<AnalysisResult>;
642
730
  //#endregion
643
731
  //#region src/errors.d.ts
644
732
  declare class ArchWallError extends Error {
@@ -717,5 +805,29 @@ declare function sarifReporter(sink: OutputSink): Reporter;
717
805
  */
718
806
  declare function dropSelfEdges(): GraphTransform;
719
807
  //#endregion
720
- export { type AnalysisResult, type AnalysisStats, ArchWallError, BUILTIN_REPORTER_NAMES, type BuiltinReporterName, type CallableRule, type Capability, type Classifier, type ClassifierContext, type ConfiguredRule, DIAGNOSTIC_GATES, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type Edge, type EdgeFilter, type EdgeKind, type EmptyScopeDetails, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, type FailOn, type FailOnDiagnostics, type GraphComputation, type GraphDelivery, type GraphMutation, GraphQuery, type GraphTransform, type HostInfo, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, type ModuleFilter, type ModuleId, type ModuleIdScheme, type ModuleKind, type ModuleNode, type ModuleSelection, type OutputDestination, type OutputSink, type PathClassifierOptions, type PathPattern, type Preset, type PresetMeta, type PresetSpec, ProjectGraph, type ProjectGraphInit, type Reporter, type ReporterIO, type ReporterOutputSpec, type ReporterSpec, type ResolvedConfig, type ResolvedFailOnDiagnostics, type ResolvedReporters, type ResolvedRule, type Rule, type RuleContext, type RuleDeprecation, type RuleMeta, type RuleOverride, type RuleRunInfo, type RuleScope, type RuleSettings, type RuleSkippedDetails, type RuleSpec, type RuleVisitors, type RunInfo, type Severity, type SeverityCounts, type SourceLocation, type StandardSchemaIssue, type StandardSchemaResult, type StandardSchemaV1, THIRD_PARTY_KINDS, type TagPatch, type TransformContext, type UserConfig, type Violation, type ViolationInput, type ViolationLocation, type WellKnownCapability, type WellKnownDiagnosticCode, type WellKnownEdgeKind, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
808
+ //#region src/transforms/drop-type-only-edges.d.ts
809
+ /**
810
+ * Removes edges the host marked `attributes.typeOnly`.
811
+ *
812
+ * This is the *policy* half of type-only support, deliberately separated from the *fact* half.
813
+ * Producers report what the code says; whether an erased import counts as a dependency is a
814
+ * question about the user's architecture, and different answers are legitimately right:
815
+ *
816
+ * - A layering rule usually SHOULD see type-only edges — `domain` importing an
817
+ * `infrastructure` type still couples the two at design time, which is the thing layering
818
+ * exists to prevent.
819
+ * - A cycle rule usually should NOT — a type-only cycle costs nothing at runtime and
820
+ * `no-cycles` flagging one is the most common false positive in this whole category of tool.
821
+ *
822
+ * So it is off by default and opted into per config, rather than being baked into a producer.
823
+ * Before this existed the CLI simply never emitted type-only edges, which made that choice for
824
+ * everyone, made the CLI disagree with every bundler adapter, and left no way to get the
825
+ * edges back.
826
+ *
827
+ * Only meaningful when the host declares `type-only-edges`; against a host that erased type
828
+ * imports before ArchWall saw them, there is nothing here to remove and this is a no-op.
829
+ */
830
+ declare function dropTypeOnlyEdges(): GraphTransform;
831
+ //#endregion
832
+ export { type AnalysisResult, type AnalysisStats, type AnalyzeOptions, ArchWallError, BUILTIN_REPORTER_NAMES, type BuiltinReporterName, type CallableRule, type Capability, type Classifier, type ClassifierContext, type ConfiguredRule, DIAGNOSTIC_GATES, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type Edge, type EdgeAttributes, type EdgeFilter, type EdgeKind, type EmptyScopeDetails, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, type FailOn, type FailOnDiagnostics, type GraphComputation, type GraphDelivery, type GraphMutation, type GraphTransform, type GraphView, type HostInfo, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, type ModuleFilter, type ModuleId, type ModuleIdScheme, type ModuleKind, type ModuleNode, type ModuleSelection, type OutputDestination, type OutputSink, type PathClassifierOptions, type PathPattern, type Preset, type PresetMeta, type PresetSpec, ProjectGraph, type ProjectGraphInit, type Reporter, type ReporterIO, type ReporterOutputSpec, type ReporterSpec, type ResolvedConfig, type ResolvedFailOnDiagnostics, type ResolvedReporters, type ResolvedRule, type Rule, type RuleContext, type RuleDeprecation, type RuleMeta, type RuleOverride, type RuleRunInfo, type RuleScope, type RuleSettings, type RuleSkippedDetails, type RuleSpec, type RuleVisitors, type RunInfo, type Severity, type SeverityCounts, type SourceLocation, type StandardSchemaIssue, type StandardSchemaResult, type StandardSchemaV1, THIRD_PARTY_KINDS, type TagPatch, type TransformContext, type UnscannableFilesDetails, type UserConfig, type Violation, type ViolationInput, type ViolationLocation, type WellKnownCapability, type WellKnownDiagnosticCode, type WellKnownEdgeKind, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, dropTypeOnlyEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
721
833
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as THIRD_PARTY_KINDS, A as primarySourceLocation, B as GraphDelivery, C as ViolationLocation, D as locationsOf, E as fingerprintOf, F as defineClassifier, G as MODULE_ID_SCHEMES, H as GraphMutation, I as Capability, J as ModuleKind, K as ModuleId, L as Edge, M as Classifier, N as ClassifierContext, O as primaryEdge, P as TagPatch, Q as SourceLocation, R as EdgeKind, S as ViolationInput, T as countBySeverity, U as HostInfo, W as IR_VERSION, X as ProjectGraph, Y as ModuleNode, Z as ProjectGraphInit, _ as WellKnownDiagnosticCode, a as defineGraphComputation, at as isFirstParty, b as SeverityCounts, c as GraphQuery, et as WellKnownCapability, f as Diagnostic, g as RuleSkippedDetails, h as EmptyScopeDetails, i as GraphComputation, it as irMajor, j as renderMessage, k as primaryModule, l as ModuleFilter, m as DiagnosticSeverity, n as TransformContext, nt as assertIrCompatible, o as EdgeFilter, ot as isThirdParty, p as DiagnosticCode, q as ModuleIdScheme, r as defineTransform, rt as displayModuleId, st as parseModuleId, t as GraphTransform, tt as WellKnownEdgeKind, u as ModuleSelection, v as FINGERPRINT_SCHEME, w as compareViolations, x as Violation, y as Severity, z as FIRST_PARTY_KINDS } from "./transform-CnUPOO0E.mjs";
1
+ import { $ as ProjectGraph, A as primaryEdge, B as EdgeAttributes, C as Violation, D as countBySeverity, E as compareViolations, F as ClassifierContext, G as GraphMutation, H as FIRST_PARTY_KINDS, I as TagPatch, J as MODULE_ID_SCHEMES, K as HostInfo, L as defineClassifier, M as primarySourceLocation, N as renderMessage, O as fingerprintOf, P as Classifier, Q as ModuleNode, R as Capability, S as SeverityCounts, T as ViolationLocation, U as GraphDelivery, V as EdgeKind, X as ModuleIdScheme, Y as ModuleId, Z as ModuleKind, _ as RuleSkippedDetails, a as defineGraphComputation, at as assertIrCompatible, b as FINGERPRINT_SCHEME, ct as isFirstParty, d as ModuleSelection, et as ProjectGraphInit, g as EmptyScopeDetails, h as DiagnosticSeverity, i as GraphComputation, it as WellKnownEdgeKind, j as primaryModule, k as locationsOf, l as GraphView, lt as isThirdParty, m as DiagnosticCode, n as TransformContext, nt as THIRD_PARTY_KINDS, o as EdgeFilter, ot as displayModuleId, p as Diagnostic, q as IR_VERSION, r as defineTransform, rt as WellKnownCapability, st as irMajor, t as GraphTransform, tt as SourceLocation, u as ModuleFilter, ut as parseModuleId, v as UnscannableFilesDetails, w as ViolationInput, x as Severity, y as WellKnownDiagnosticCode, z as Edge } from "./transform-CzxyWbUC.mjs";
2
2
  //#region src/analysis/scc.d.ts
3
3
  /**
4
4
  * Strongly connected components over static+reexport edges (a dynamic import is a
@@ -110,8 +110,26 @@ interface RuleRunInfo {
110
110
  deprecated?: boolean;
111
111
  }
112
112
  interface AnalysisResult {
113
- /** Deterministically ordered; see `compareViolations`. */
113
+ /**
114
+ * Findings that COUNT — the ones `failOn` gates and reporters lead with. Deterministically
115
+ * ordered; see `compareViolations`.
116
+ */
114
117
  violations: readonly Violation[];
118
+ /**
119
+ * Findings matched by the baseline and therefore not counted, in the same order.
120
+ *
121
+ * Separate from `violations` rather than a flag on them, because every consumer that exists
122
+ * wants the un-suppressed set by default: a reporter that had to remember to filter would
123
+ * eventually forget, and the failure would be an enforcement tool quietly counting findings
124
+ * the user already accepted.
125
+ *
126
+ * Always present, empty when no baseline is configured — so a reporter written today needs
127
+ * no change when baselines arrive, and `violations.length + suppressed.length` is the total
128
+ * the analysis actually found.
129
+ *
130
+ * @see UserConfig.baseline
131
+ */
132
+ suppressed: readonly Violation[];
115
133
  /** Everything that is not a violation: skipped rules, crashed rules, config problems. */
116
134
  diagnostics: readonly Diagnostic[];
117
135
  stats: AnalysisStats;
@@ -205,7 +223,7 @@ interface RuleMeta<Options> {
205
223
  }
206
224
  interface RuleContext<Options> {
207
225
  options: Options;
208
- graph: GraphQuery;
226
+ graph: GraphView;
209
227
  /**
210
228
  * Absolute source root. The base for any path *pattern* a rule matches against, so that
211
229
  * rule options read the same way as classifier patterns and `include`/`exclude`.
@@ -443,6 +461,23 @@ interface FailOnDiagnostics {
443
461
  invalidConfig?: boolean;
444
462
  /** A configured rule is deprecated. Default false. */
445
463
  deprecated?: boolean;
464
+ /**
465
+ * In-boundary files the producer could not read, and so never analysed. Default false.
466
+ *
467
+ * Default false only because turning it on would fail CI for every Vue/Svelte/Astro project
468
+ * the moment they upgrade, and a warning they can see beats an error they revert. Turn it on
469
+ * in any repository where "ArchWall looked at all of it" is load-bearing — which, for a tool
470
+ * whose whole failure mode is passing green without looking, is most of them.
471
+ */
472
+ unscannableFiles?: boolean;
473
+ /**
474
+ * The baseline contains entries this run did not match. Default false.
475
+ *
476
+ * False by default because the common cause is the good one — somebody fixed something — and
477
+ * failing CI for that punishes exactly the behaviour the baseline exists to encourage. Teams
478
+ * that want the file kept honest turn it on and prune as they go.
479
+ */
480
+ baselineStale?: boolean;
446
481
  }
447
482
  interface ResolvedFailOnDiagnostics {
448
483
  ruleFailed: boolean;
@@ -452,6 +487,8 @@ interface ResolvedFailOnDiagnostics {
452
487
  invalidOptions: boolean;
453
488
  invalidConfig: boolean;
454
489
  deprecated: boolean;
490
+ unscannableFiles: boolean;
491
+ baselineStale: boolean;
455
492
  }
456
493
  /**
457
494
  * Which diagnostic codes each `failOnDiagnostics` switch governs, and whether it is on by
@@ -494,6 +531,14 @@ declare const DIAGNOSTIC_GATES: {
494
531
  readonly codes: readonly ["rule-deprecated"];
495
532
  readonly default: false;
496
533
  };
534
+ readonly unscannableFiles: {
535
+ readonly codes: readonly ["unscannable-files"];
536
+ readonly default: false;
537
+ };
538
+ readonly baselineStale: {
539
+ readonly codes: readonly ["baseline-stale"];
540
+ readonly default: false;
541
+ };
497
542
  };
498
543
  /**
499
544
  * Applies {@link DIAGNOSTIC_GATES}' defaults to whatever the user left unset.
@@ -587,6 +632,18 @@ interface UserConfig {
587
632
  * `{ reporter, output }` to send one somewhere other than stdout. Default ["console"].
588
633
  */
589
634
  reporters?: ReporterSpec[];
635
+ /**
636
+ * Path to a baseline file of accepted violations, relative to {@link repoRoot}.
637
+ *
638
+ * RESERVED — declared, resolved, and carried on `ResolvedConfig`, but not yet read. See
639
+ * `AnalysisResult.suppressed`.
640
+ *
641
+ * A graph-based linter has no other suppression mechanism available: with no source text
642
+ * there can be no `// archwall-ignore`, so accepting existing findings has to be a file
643
+ * keyed on violation fingerprints. That is what makes ArchWall adoptable on a codebase that
644
+ * did not start with it — the alternative is 400 violations on day one and an uninstall.
645
+ */
646
+ baseline?: string;
590
647
  /** Which VIOLATION severity gates the run. `info` findings never fail it. */
591
648
  failOn?: FailOn;
592
649
  /** Which DIAGNOSTICS gate the run, regardless of `failOn`. */
@@ -607,6 +664,8 @@ interface ResolvedRule {
607
664
  interface ResolvedConfig {
608
665
  /** Absolute. Base for reported paths and fingerprints. */
609
666
  repoRoot: string;
667
+ /** Absolute path to the baseline file, or null. RESERVED; see {@link UserConfig.baseline}. */
668
+ baseline: string | null;
610
669
  /** Absolute, at or below {@link repoRoot}. Base for the boundary and classifiers. */
611
670
  sourceRoot: string;
612
671
  include: string[];
@@ -633,12 +692,41 @@ declare function resolveConfig(user: UserConfig, opts?: {
633
692
  }): ResolvedConfig;
634
693
  //#endregion
635
694
  //#region src/engine/analyze.d.ts
695
+ /**
696
+ * Per-call knobs, kept OUT of {@link ResolvedConfig}.
697
+ *
698
+ * The distinction is load-bearing: `ResolvedConfig` is the user's declared policy, is
699
+ * serialisable, and is the same for every run. These are properties of one invocation. Folding
700
+ * a cancellation token into the config would make the config unserialisable and would mean two
701
+ * runs of "the same configuration" were not comparable.
702
+ *
703
+ * The parameter exists now, ahead of most of its contents, on purpose: adding a third parameter
704
+ * later is free, but adding it *after* third parties have wrapped `analyze` is not, and every
705
+ * capability that wants a per-call channel (progress, logging, cancellation, incremental reuse)
706
+ * would otherwise arrive as its own breaking change.
707
+ */
708
+ interface AnalyzeOptions {
709
+ /**
710
+ * Aborts the run between rules. Honoured at rule-dispatch boundaries, not mid-traversal:
711
+ * a rule sees the whole slice it was given or none of it, so a cancelled run never produces
712
+ * the partial findings {@link RuleRun.crashed} exists to discard.
713
+ */
714
+ signal?: AbortSignal;
715
+ /**
716
+ * RESERVED, and currently ignored. The previous run's result, for incremental reuse.
717
+ *
718
+ * Declared before it is honoured so that the eventual implementation is a behaviour change
719
+ * rather than a signature change. Passing it today is safe and does nothing; do not write
720
+ * code that depends on it having an effect.
721
+ */
722
+ previous?: AnalysisResult;
723
+ }
636
724
  /**
637
725
  * The engine: prepare the graph (boundary → transforms → classify), then check it.
638
726
  *
639
727
  * Pure — no I/O, no reporter calls; reporters are driven by the run edge (integration-kit).
640
728
  */
641
- declare function analyze(graph: ProjectGraph, config: ResolvedConfig): Promise<AnalysisResult>;
729
+ declare function analyze(graph: ProjectGraph, config: ResolvedConfig, options?: AnalyzeOptions): Promise<AnalysisResult>;
642
730
  //#endregion
643
731
  //#region src/errors.d.ts
644
732
  declare class ArchWallError extends Error {
@@ -717,5 +805,29 @@ declare function sarifReporter(sink: OutputSink): Reporter;
717
805
  */
718
806
  declare function dropSelfEdges(): GraphTransform;
719
807
  //#endregion
720
- export { type AnalysisResult, type AnalysisStats, ArchWallError, BUILTIN_REPORTER_NAMES, type BuiltinReporterName, type CallableRule, type Capability, type Classifier, type ClassifierContext, type ConfiguredRule, DIAGNOSTIC_GATES, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type Edge, type EdgeFilter, type EdgeKind, type EmptyScopeDetails, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, type FailOn, type FailOnDiagnostics, type GraphComputation, type GraphDelivery, type GraphMutation, GraphQuery, type GraphTransform, type HostInfo, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, type ModuleFilter, type ModuleId, type ModuleIdScheme, type ModuleKind, type ModuleNode, type ModuleSelection, type OutputDestination, type OutputSink, type PathClassifierOptions, type PathPattern, type Preset, type PresetMeta, type PresetSpec, ProjectGraph, type ProjectGraphInit, type Reporter, type ReporterIO, type ReporterOutputSpec, type ReporterSpec, type ResolvedConfig, type ResolvedFailOnDiagnostics, type ResolvedReporters, type ResolvedRule, type Rule, type RuleContext, type RuleDeprecation, type RuleMeta, type RuleOverride, type RuleRunInfo, type RuleScope, type RuleSettings, type RuleSkippedDetails, type RuleSpec, type RuleVisitors, type RunInfo, type Severity, type SeverityCounts, type SourceLocation, type StandardSchemaIssue, type StandardSchemaResult, type StandardSchemaV1, THIRD_PARTY_KINDS, type TagPatch, type TransformContext, type UserConfig, type Violation, type ViolationInput, type ViolationLocation, type WellKnownCapability, type WellKnownDiagnosticCode, type WellKnownEdgeKind, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
808
+ //#region src/transforms/drop-type-only-edges.d.ts
809
+ /**
810
+ * Removes edges the host marked `attributes.typeOnly`.
811
+ *
812
+ * This is the *policy* half of type-only support, deliberately separated from the *fact* half.
813
+ * Producers report what the code says; whether an erased import counts as a dependency is a
814
+ * question about the user's architecture, and different answers are legitimately right:
815
+ *
816
+ * - A layering rule usually SHOULD see type-only edges — `domain` importing an
817
+ * `infrastructure` type still couples the two at design time, which is the thing layering
818
+ * exists to prevent.
819
+ * - A cycle rule usually should NOT — a type-only cycle costs nothing at runtime and
820
+ * `no-cycles` flagging one is the most common false positive in this whole category of tool.
821
+ *
822
+ * So it is off by default and opted into per config, rather than being baked into a producer.
823
+ * Before this existed the CLI simply never emitted type-only edges, which made that choice for
824
+ * everyone, made the CLI disagree with every bundler adapter, and left no way to get the
825
+ * edges back.
826
+ *
827
+ * Only meaningful when the host declares `type-only-edges`; against a host that erased type
828
+ * imports before ArchWall saw them, there is nothing here to remove and this is a no-op.
829
+ */
830
+ declare function dropTypeOnlyEdges(): GraphTransform;
831
+ //#endregion
832
+ export { type AnalysisResult, type AnalysisStats, type AnalyzeOptions, ArchWallError, BUILTIN_REPORTER_NAMES, type BuiltinReporterName, type CallableRule, type Capability, type Classifier, type ClassifierContext, type ConfiguredRule, DIAGNOSTIC_GATES, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type Edge, type EdgeAttributes, type EdgeFilter, type EdgeKind, type EmptyScopeDetails, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, type FailOn, type FailOnDiagnostics, type GraphComputation, type GraphDelivery, type GraphMutation, type GraphTransform, type GraphView, type HostInfo, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, type ModuleFilter, type ModuleId, type ModuleIdScheme, type ModuleKind, type ModuleNode, type ModuleSelection, type OutputDestination, type OutputSink, type PathClassifierOptions, type PathPattern, type Preset, type PresetMeta, type PresetSpec, ProjectGraph, type ProjectGraphInit, type Reporter, type ReporterIO, type ReporterOutputSpec, type ReporterSpec, type ResolvedConfig, type ResolvedFailOnDiagnostics, type ResolvedReporters, type ResolvedRule, type Rule, type RuleContext, type RuleDeprecation, type RuleMeta, type RuleOverride, type RuleRunInfo, type RuleScope, type RuleSettings, type RuleSkippedDetails, type RuleSpec, type RuleVisitors, type RunInfo, type Severity, type SeverityCounts, type SourceLocation, type StandardSchemaIssue, type StandardSchemaResult, type StandardSchemaV1, THIRD_PARTY_KINDS, type TagPatch, type TransformContext, type UnscannableFilesDetails, type UserConfig, type Violation, type ViolationInput, type ViolationLocation, type WellKnownCapability, type WellKnownDiagnosticCode, type WellKnownEdgeKind, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, dropTypeOnlyEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
721
833
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { S as sourceRelative, _ as isThirdParty, a as filterKey, b as IrVersionMismatchError, d as ProjectGraph, f as THIRD_PARTY_KINDS, g as isFirstParty, h as irMajor, i as GraphQuery, l as IR_VERSION, m as displayModuleId, n as prepareGraph, o as GraphComputationCache, p as assertIrCompatible, s as FIRST_PARTY_KINDS, u as MODULE_ID_SCHEMES, v as parseModuleId, w as toRelative, x as hashParts, y as ArchWallError } from "./prepare-BJHgDEui.mjs";
1
+ import { S as sourceRelative, _ as isThirdParty, a as filterKey, b as IrVersionMismatchError, d as ProjectGraph, f as THIRD_PARTY_KINDS, g as isFirstParty, h as irMajor, i as GraphQuery, l as IR_VERSION, m as displayModuleId, n as prepareGraph, o as GraphComputationCache, p as assertIrCompatible, s as FIRST_PARTY_KINDS, u as MODULE_ID_SCHEMES, v as parseModuleId, w as toRelative, x as hashParts, y as ArchWallError } from "./prepare-BjMxyYOm.mjs";
2
2
  import * as path from "node:path";
3
3
  import picomatch from "picomatch";
4
4
  //#region src/contracts/analysis.ts
@@ -326,8 +326,7 @@ function renderMessage(template, data) {
326
326
  * Fingerprint scheme version. Bump when the algorithm changes so that a stale baseline
327
327
  * ERRORS instead of silently mismatching every entry.
328
328
  *
329
- * `aw3` is the first scheme over canonical module ids
330
- * (docs/adr/0012-canonical-module-identity.md). Before it, a violation about `react` hashed the
329
+ * `aw3` is the first scheme over canonical module ids. Before it, a violation about `react` hashed the
331
330
  * host's own id — a resolved `node_modules` path under the CLI, the bare specifier under esbuild
332
331
  * — so the same finding fingerprinted differently under two bundlers.
333
332
  */
@@ -681,6 +680,14 @@ const DIAGNOSTIC_GATES = {
681
680
  deprecated: {
682
681
  codes: ["rule-deprecated"],
683
682
  default: false
683
+ },
684
+ unscannableFiles: {
685
+ codes: ["unscannable-files"],
686
+ default: false
687
+ },
688
+ baselineStale: {
689
+ codes: ["baseline-stale"],
690
+ default: false
684
691
  }
685
692
  };
686
693
  const GATE_KEYS = Object.keys(DIAGNOSTIC_GATES);
@@ -700,7 +707,9 @@ function resolveFailOnDiagnostics(user) {
700
707
  emptyScope: gate("emptyScope"),
701
708
  invalidOptions: gate("invalidOptions"),
702
709
  invalidConfig: gate("invalidConfig"),
703
- deprecated: gate("deprecated")
710
+ deprecated: gate("deprecated"),
711
+ unscannableFiles: gate("unscannableFiles"),
712
+ baselineStale: gate("baselineStale")
704
713
  };
705
714
  }
706
715
  /** The diagnostic codes that should fail a run, given the resolved gates. */
@@ -904,6 +913,7 @@ function resolveConfig(user, opts) {
904
913
  const repoRoot = path.resolve(cwd, user.repoRoot ?? ".");
905
914
  return {
906
915
  repoRoot,
916
+ baseline: user.baseline !== void 0 ? path.resolve(repoRoot, user.baseline) : null,
907
917
  sourceRoot: path.resolve(repoRoot, user.sourceRoot ?? "."),
908
918
  include: user.include ?? [...DEFAULT_INCLUDE],
909
919
  exclude: [...user.excludeDefaults === false ? [] : DEFAULT_EXCLUDE, ...user.exclude ?? []],
@@ -954,8 +964,9 @@ function defineTransform(transform) {
954
964
  *
955
965
  * Pure — no I/O, no reporter calls; reporters are driven by the run edge (integration-kit).
956
966
  */
957
- async function analyze(graph, config) {
967
+ async function analyze(graph, config, options = {}) {
958
968
  const started = performance.now();
969
+ options.signal?.throwIfAborted();
959
970
  assertIrCompatible(graph.irVersion);
960
971
  const diagnostics = [...config.diagnostics];
961
972
  const effective = new Set(graph.host.capabilities);
@@ -1124,9 +1135,10 @@ async function analyze(graph, config) {
1124
1135
  });
1125
1136
  }
1126
1137
  const active = runs.filter((r) => !r.halted);
1127
- dispatchVisitors(active, diagnostics, scopeKeyOf);
1138
+ dispatchVisitors(active, diagnostics, scopeKeyOf, options.signal);
1128
1139
  for (const run of active) {
1129
1140
  if (run.halted || run.resolved.rule.check === void 0) continue;
1141
+ options.signal?.throwIfAborted();
1130
1142
  const startedRule = performance.now();
1131
1143
  try {
1132
1144
  await run.resolved.rule.check(run.ctx);
@@ -1143,6 +1155,7 @@ async function analyze(graph, config) {
1143
1155
  diagnostics.push(...auditClassification(classified));
1144
1156
  return {
1145
1157
  violations: kept.sort(compareViolations),
1158
+ suppressed: [],
1146
1159
  diagnostics,
1147
1160
  rules: runs.map((r) => r.info),
1148
1161
  repoRoot: config.repoRoot,
@@ -1167,7 +1180,7 @@ async function analyze(graph, config) {
1167
1180
  * slice, so a rule that throws stops and is marked failed while the other thirty-nine keep
1168
1181
  * their results — without paying for exception handling on every edge.
1169
1182
  */
1170
- function dispatchVisitors(runs, diagnostics, scopeKeyOf) {
1183
+ function dispatchVisitors(runs, diagnostics, scopeKeyOf, signal) {
1171
1184
  const edgeBuckets = /* @__PURE__ */ new Map();
1172
1185
  const moduleBuckets = /* @__PURE__ */ new Map();
1173
1186
  for (const run of runs) {
@@ -1220,6 +1233,7 @@ function dispatchVisitors(runs, diagnostics, scopeKeyOf) {
1220
1233
  const items = bucket.slice();
1221
1234
  for (const { run, visit } of bucket.members) {
1222
1235
  if (run.halted) continue;
1236
+ signal?.throwIfAborted();
1223
1237
  const startedRule = performance.now();
1224
1238
  try {
1225
1239
  for (const item of items) visit(item, run.ctx);
@@ -1344,6 +1358,37 @@ function dropSelfEdges() {
1344
1358
  });
1345
1359
  }
1346
1360
  //#endregion
1347
- export { ArchWallError, BUILTIN_REPORTER_NAMES, DIAGNOSTIC_GATES, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, GraphQuery, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, ProjectGraph, THIRD_PARTY_KINDS, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
1361
+ //#region src/transforms/drop-type-only-edges.ts
1362
+ /**
1363
+ * Removes edges the host marked `attributes.typeOnly`.
1364
+ *
1365
+ * This is the *policy* half of type-only support, deliberately separated from the *fact* half.
1366
+ * Producers report what the code says; whether an erased import counts as a dependency is a
1367
+ * question about the user's architecture, and different answers are legitimately right:
1368
+ *
1369
+ * - A layering rule usually SHOULD see type-only edges — `domain` importing an
1370
+ * `infrastructure` type still couples the two at design time, which is the thing layering
1371
+ * exists to prevent.
1372
+ * - A cycle rule usually should NOT — a type-only cycle costs nothing at runtime and
1373
+ * `no-cycles` flagging one is the most common false positive in this whole category of tool.
1374
+ *
1375
+ * So it is off by default and opted into per config, rather than being baked into a producer.
1376
+ * Before this existed the CLI simply never emitted type-only edges, which made that choice for
1377
+ * everyone, made the CLI disagree with every bundler adapter, and left no way to get the
1378
+ * edges back.
1379
+ *
1380
+ * Only meaningful when the host declares `type-only-edges`; against a host that erased type
1381
+ * imports before ArchWall saw them, there is nothing here to remove and this is a no-op.
1382
+ */
1383
+ function dropTypeOnlyEdges() {
1384
+ return defineTransform({
1385
+ name: "drop-type-only-edges",
1386
+ transform(graph) {
1387
+ graph.removeEdges((e) => e.attributes?.typeOnly === true);
1388
+ }
1389
+ });
1390
+ }
1391
+ //#endregion
1392
+ export { ArchWallError, BUILTIN_REPORTER_NAMES, DIAGNOSTIC_GATES, FINGERPRINT_SCHEME, FIRST_PARTY_KINDS, IR_VERSION, IrVersionMismatchError, MODULE_ID_SCHEMES, ProjectGraph, THIRD_PARTY_KINDS, analyze, assertIrCompatible, compareViolations, configureRule, consoleReporter, countBySeverity, defaultIO, defineClassifier, defineConfig, defineGraphComputation, definePreset, defineReporter, defineRule, defineTransform, displayModuleId, dropSelfEdges, dropTypeOnlyEdges, failingDiagnosticCodes, fingerprintOf, formatViolation, irMajor, isBuiltinReporterName, isFirstParty, isThirdParty, jsonReporter, locationsOf, matchCaptures, matchesPattern, parseModuleId, pathClassifier, primaryEdge, primaryModule, primarySourceLocation, renderMessage, resolveConfig, resolveFailOnDiagnostics, resolveReporters, sarifReporter, stronglyConnectedComponents };
1348
1393
 
1349
1394
  //# sourceMappingURL=index.mjs.map