slopbrick 0.41.0 → 0.43.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
@@ -776,6 +776,101 @@ interface Rule<Context = unknown> {
776
776
  create(context: RuleContext): Context;
777
777
  analyze(context: Context, facts: ScanFacts): Issue[];
778
778
  }
779
+ /**
780
+ * v0.42.0 (Sprint 3, task 3b.1): composite rule type. A composite
781
+ * fires when *at least `minMatch`* of its member `ruleIds` fire on the
782
+ * same file. Members are referenced by their existing `Rule.id`.
783
+ *
784
+ * Structurally parallel to `Rule<Context>` so the `RuleRegistry`
785
+ * treats it uniformly: same `create` + `analyze` lifecycle, same
786
+ * `defaultOff` opt-in semantics, same `severity` for reporter
787
+ * weighting. The engine wires composites after per-file `RuleRegistry`
788
+ * (see `engine/worker.ts` + task 3b.5).
789
+ *
790
+ * Design choice: `CompositeRule<Context>` is its own interface rather
791
+ * than a `Rule<Context>` variant because (a) it carries member-rule
792
+ * metadata (`ruleIds`, `minMatch`) that vanilla rules do not, and
793
+ * (b) the union of the two types would force every consumer to
794
+ * narrow, defeating the structural-parallelism goal.
795
+ */
796
+ interface CompositeRule<Context = unknown> {
797
+ id: string;
798
+ category: Category;
799
+ severity: Severity;
800
+ aiSpecific: boolean;
801
+ /** Short description shown by `slopbrick rules`. */
802
+ description?: string;
803
+ /** v0.42.0: composite rules are opt-in by default. */
804
+ defaultOff?: boolean;
805
+ /** Member rule IDs (sorted, unique). The composite fires when
806
+ * at least `minMatch` of these fire on the same file. */
807
+ ruleIds: string[];
808
+ /** Minimum number of `ruleIds` that must fire together. */
809
+ minMatch: number;
810
+ create(context: RuleContext): Context;
811
+ analyze(context: Context, facts: ScanFacts): Issue[];
812
+ }
813
+ /**
814
+ * v0.42.0 (Sprint 3, task 3b.3): clusterer-emitted composite rule
815
+ * entry. The shape that `engine/cluster.ts` produces and that the
816
+ * `RuleRegistry` loader materializes into `CompositeRule<Context>`
817
+ * instances. Lives next to `CompositeRule<Context>` so the public
818
+ * type surface for empirical composites is in one place.
819
+ *
820
+ * Fields mirror the spec in `docs/superpowers/sprint-0.41-0.42.md`
821
+ * §3b STEP 5: id, ruleIds, minMatch, severity, defaultOff,
822
+ * description, calibration, provenance.
823
+ */
824
+ interface CompositeRuleEntry {
825
+ id: string;
826
+ ruleIds: string[];
827
+ minMatch: number;
828
+ severity: Severity;
829
+ defaultOff: true;
830
+ description: string;
831
+ calibration: {
832
+ recall: number;
833
+ /** False-positive rate, FP / neg_count. */
834
+ FP: number;
835
+ precision: number;
836
+ F1: number;
837
+ nFiles: number;
838
+ };
839
+ provenance: {
840
+ seed: 'auto-cluster' | 'hand-curated-by-brief';
841
+ discoveredAt: string;
842
+ nFiles: number;
843
+ members: number;
844
+ /** Strongest NPMI edge among cluster members (0 if singleton). */
845
+ npmi: number;
846
+ /** Strongest-edge Fisher's p (1 if singleton). */
847
+ fisherP: number;
848
+ };
849
+ }
850
+ /**
851
+ * v0.42.0 (Sprint 3, task 3b.2): input to the empirical composite
852
+ * clusterer. `fireMatrix` is the per-file fired-rule-set map; the
853
+ * other fields are optional inputs to STEP 4 calibration.
854
+ */
855
+ interface ClusterInput {
856
+ /** Per-file fired-rule-set map (file id → set of rule IDs that fired). */
857
+ fireMatrix: ReadonlyMap<string, ReadonlySet<string>>;
858
+ /** Positive (gold-standard) file IDs for recall/precision. */
859
+ positiveFiles?: ReadonlySet<string>;
860
+ /** Severity of each member rule; used to pick `severity = worst`. */
861
+ memberSeverities?: ReadonlyMap<string, Severity>;
862
+ /** Algorithm parameter overrides (all optional). */
863
+ params?: ClusterParamOverrides;
864
+ /** ISO timestamp embedded in `provenance.discoveredAt` for tests. */
865
+ now?: string;
866
+ }
867
+ type ClusterParams = {
868
+ minSupport: number;
869
+ minNPMI: number;
870
+ fisherAlpha: number;
871
+ minClusterSize: number;
872
+ };
873
+ type ClusterParamOverrides = Partial<ClusterParams>;
779
874
  interface ResolvedConfig {
780
875
  framework?: string;
781
876
  hasTailwind?: boolean;
@@ -1060,9 +1155,8 @@ type AiDebt = 'low' | 'medium' | 'high' | 'critical';
1060
1155
  declare const AI_SECURITY_NUMERIC: Record<'low' | 'medium' | 'high' | 'critical', number>;
1061
1156
  /** Inputs to the pure `buildRepositoryHealth` function. Every input is optional. */
1062
1157
  interface RepositoryHealthInputs {
1063
- /** v0.15.0 U.4+: 0-100, higher = better. The new headline score
1064
- * that replaces slopIndex. Tests and callers should pass this
1065
- * going forward. */
1158
+ /** v0.21.0: 0-100, lower = better (raw amount of slop).
1159
+ * Replaces the v0.15-v0.20.1 inverted cleanliness reading. */
1066
1160
  aiSlopScore?: number;
1067
1161
  /** v0.15.0 U.4+: 0-100, higher = better. */
1068
1162
  engineeringHygiene?: number;
@@ -1306,15 +1400,15 @@ interface ProjectReport {
1306
1400
  generatedAt: string;
1307
1401
  configPath?: string;
1308
1402
  /**
1309
- * v0.20.0: renamed from `aiSlopScore` to `aiSlopScore` because the
1310
- * old name implied a property of the *code* (quality) when it
1311
- * actually measures a property of the *tool's detection* (how
1312
- * many AI-detection rules fire on this codebase). 0-100, higher
1313
- * is better — but 'better' means 'fewer rule fires', not
1314
- * 'higher quality code'. The name "AI Slop Score" matches the
1315
- * existing description ("measures AI-slop signatures") and the
1316
- * slopbrick brand. See the pre-publish checklist in
1317
- * CONTRIBUTING.md for the full rationale.
1403
+ * v0.21.0: 0-100, **lower = better** (raw amount of slop).
1404
+ * The CI gate is `aiSlopScore <= meanSlop` (where meanSlop defaults
1405
+ * to 30). Higher values mean more AI-detection rules fired on this
1406
+ * codebase. The previous v0.15-v0.20.1 reading inverted this to
1407
+ * "cleanliness" (higher = better), which made the JSON output and
1408
+ * the CLI gate disagree. This field has been lower-is-better
1409
+ * since v0.21.0; the JSDoc that said "0-100, higher is better"
1410
+ * was a stale v0.15-era comment that survived past the inversion.
1411
+ * Fixed in v0.42.0.
1318
1412
  */
1319
1413
  aiSlopScore: number;
1320
1414
  engineeringHygiene: number;
@@ -1483,6 +1577,18 @@ interface ProjectReport {
1483
1577
  p90Slop: number;
1484
1578
  individualSlopThreshold: number;
1485
1579
  };
1580
+ /**
1581
+ * v0.42.0 (user-review fix): names of thresholds that tripped in this
1582
+ * scan. Optional for backward compat with v0.41 and earlier reports.
1583
+ * Empty/undefined means all gates passed.
1584
+ *
1585
+ * Possible values: 'meanSlop', 'p90Slop', 'individualSlopThreshold',
1586
+ * 'category:<name>' (per-category thresholds).
1587
+ *
1588
+ * CI consumers can grep this field directly instead of parsing the
1589
+ * stderr message. See threshold.ts#failedThresholds for source.
1590
+ */
1591
+ failedThresholds?: string[];
1486
1592
  /** Research/flywheel snapshot — present when the flywheel directory has artifacts. */
1487
1593
  research?: ResearchMetrics;
1488
1594
  topOffenders?: TopOffender[];
@@ -1559,9 +1665,12 @@ interface ProjectReport {
1559
1665
  /** v0.14.5i — Number of distinct rules marked defaultOff. The ratio
1560
1666
  * suppressedCount / defaultOffRuleCount is the calibration coverage. */
1561
1667
  defaultOffRuleCount?: number;
1562
- /** v0.14.5j — The previous run's Slop Index, if any. Used by
1668
+ /** v0.14.5j — The previous run's value, if any. Used by
1563
1669
  * formatPretty to render a "±N from last run" delta so the user
1564
- * can see the trajectory without grep'ing the run log. */
1670
+ * can see the trajectory without grep'ing the run log. The
1671
+ * name is kept as `previousSlopIndex` for backward compat with
1672
+ * telemetry consumers, but the value is the previous
1673
+ * aiSlopScore (since v0.21: lower = cleaner). */
1565
1674
  previousSlopIndex?: number;
1566
1675
  /** v0.14.5j — ISO timestamp of the previous run, paired with
1567
1676
  * previousSlopIndex so the delta line can say "vs 2026-06-27". */
@@ -1612,6 +1721,13 @@ interface ScanProjectOptions {
1612
1721
  noIncrease?: boolean;
1613
1722
  cache?: boolean;
1614
1723
  telemetry?: boolean;
1724
+ /** v0.42.0 (§3a.4): opt-in flag for the AGENTS.md auto-refresh hook.
1725
+ * When true, `slopbrick scan` writes the freshly-built snippet body
1726
+ * inside the `<!-- slopbrick:begin:v3 --> ... -->` block in
1727
+ * AGENTS.md / CLAUDE.md, replacing only that block (user-edited
1728
+ * content outside the markers is preserved). Default false so
1729
+ * first-time users aren't surprised. */
1730
+ autoRefreshSnippets?: boolean;
1615
1731
  }
1616
1732
 
1617
1733
  declare function scanProject(options: ScanProjectOptions): Promise<ProjectReport>;
@@ -1627,6 +1743,16 @@ declare function runCli({ start }: {
1627
1743
 
1628
1744
  declare function thresholdExceeded(report: ProjectReport, config: ResolvedConfig): boolean;
1629
1745
  declare function failedThresholdCount(report: ProjectReport, config: ResolvedConfig): number;
1746
+ /**
1747
+ * v0.42.0 (user-review fix): failedThresholdCount() returned just the
1748
+ * count. The CLI then printed "{n} threshold(s) failed. See details
1749
+ * above." — but in --brief the user sees only the headline CI gate
1750
+ * ("AI Slop Score <= 15 -> fail"), not the per-threshold list.
1751
+ *
1752
+ * This function returns the actual list of failed threshold names so
1753
+ * the caller can name them in the final error message.
1754
+ */
1755
+ declare function failedThresholds(report: ProjectReport, config: ResolvedConfig): string[];
1630
1756
  declare function baselineStatusMessage(baseline: BaselineMeta): string;
1631
1757
  interface StagedGatingResult {
1632
1758
  failed: boolean;
@@ -1674,4 +1800,4 @@ declare function formatBadge(report: ProjectReport): string;
1674
1800
  /** Render an array of values as a Unicode sparkline (▁▂▃▄▅▆▇█). */
1675
1801
  declare function formatSparkline(values: number[]): string;
1676
1802
 
1677
- export { AI_SECURITY_NUMERIC, type AiDebt, type AiMaintenanceCost, type AiMaintenanceCostResult, type AstroComponentFact, type AutoRelaxedRule, type AutoTunedRule, type BaselineCache, type BaselineMeta, type CachedFile, type Category, type ClassNameFact, type CommentFact, type ComponentFacts, type ComponentScore, type ComponentSizeFact, type ConsoleCallFact, type Constitution, DEFAULT_CONFIG, type DangerouslySetInnerHtmlFact, type DbDriftLevel, type DbFinding, type DialogCallFact, type DisabledLintRuleFact, type DocDriftLevel, type DocFinding, type DomQueryFact, type ElementFact, type EvalCallFact, type ExplicitAnyFact, type FetchCallFact, type FileScanResult, type FixSuggestion, type FlywheelOutput, type FlywheelState, type Framework$1 as Framework, type HealthFile, type HookCallFact, type HookDependencyArrayFact, type HookFact, type ImportFact, type InlineEventHandlerFact, type Issue, type JsxAttributeStringLiteralFact, type JsxTextLiteralFact, type KeyPropFact, type LogicalExpressionFact, type MagicNumberSpacingConfig, type MaintenanceAxes, type MaintenanceAxisHealth, type NonNullAssertionFact, type OptimisticUpdateFact, type ProjectReport, type PropMutationFact, type PropPassThroughFact, REPOSITORY_HEALTH_WEIGHTS, type ReportReadResult, type RepositoryHealth, type RepositoryHealthInputs, type ResearchMetrics, type ResolvedConfig, type Rule, type RuleContext, type RuleSeverity, type RuleSuggestion, type ScanCache, type ScanFacts, type ScanProjectOptions, type ScanSelfScanConfig, type Severity, type SlopAuditRun, type StateBinding, type StateBindingFact, type StringLiteralFact, type StylePropFact, type TamaguiStylePropFact, type TopOffender, type UseEffectBodyFact, VERSION, baselineStatusMessage, colorForSlop, failedThresholdCount, filterByDisabledDirectives, filterIssues, formatBadge, formatReportFromFile, formatSparkline, loadConfig, readReportFile, runCli, runInitWizard, scanProject, serializeConfig, stagedGating, thresholdExceeded };
1803
+ export { AI_SECURITY_NUMERIC, type AiDebt, type AiMaintenanceCost, type AiMaintenanceCostResult, type AstroComponentFact, type AutoRelaxedRule, type AutoTunedRule, type BaselineCache, type BaselineMeta, type CachedFile, type Category, type ClassNameFact, type ClusterInput, type ClusterParamOverrides, type ClusterParams, type CommentFact, type ComponentFacts, type ComponentScore, type ComponentSizeFact, type CompositeRule, type CompositeRuleEntry, type ConsoleCallFact, type Constitution, DEFAULT_CONFIG, type DangerouslySetInnerHtmlFact, type DbDriftLevel, type DbFinding, type DialogCallFact, type DisabledLintRuleFact, type DocDriftLevel, type DocFinding, type DomQueryFact, type ElementFact, type EvalCallFact, type ExplicitAnyFact, type FetchCallFact, type FileScanResult, type FixSuggestion, type FlywheelOutput, type FlywheelState, type Framework$1 as Framework, type HealthFile, type HookCallFact, type HookDependencyArrayFact, type HookFact, type ImportFact, type InlineEventHandlerFact, type Issue, type JsxAttributeStringLiteralFact, type JsxTextLiteralFact, type KeyPropFact, type LogicalExpressionFact, type MagicNumberSpacingConfig, type MaintenanceAxes, type MaintenanceAxisHealth, type NonNullAssertionFact, type OptimisticUpdateFact, type ProjectReport, type PropMutationFact, type PropPassThroughFact, REPOSITORY_HEALTH_WEIGHTS, type ReportReadResult, type RepositoryHealth, type RepositoryHealthInputs, type ResearchMetrics, type ResolvedConfig, type Rule, type RuleContext, type RuleSeverity, type RuleSuggestion, type ScanCache, type ScanFacts, type ScanProjectOptions, type ScanSelfScanConfig, type Severity, type SlopAuditRun, type StateBinding, type StateBindingFact, type StringLiteralFact, type StylePropFact, type TamaguiStylePropFact, type TopOffender, type UseEffectBodyFact, VERSION, baselineStatusMessage, colorForSlop, failedThresholdCount, failedThresholds, filterByDisabledDirectives, filterIssues, formatBadge, formatReportFromFile, formatSparkline, loadConfig, readReportFile, runCli, runInitWizard, scanProject, serializeConfig, stagedGating, thresholdExceeded };
package/dist/index.d.ts CHANGED
@@ -776,6 +776,101 @@ interface Rule<Context = unknown> {
776
776
  create(context: RuleContext): Context;
777
777
  analyze(context: Context, facts: ScanFacts): Issue[];
778
778
  }
779
+ /**
780
+ * v0.42.0 (Sprint 3, task 3b.1): composite rule type. A composite
781
+ * fires when *at least `minMatch`* of its member `ruleIds` fire on the
782
+ * same file. Members are referenced by their existing `Rule.id`.
783
+ *
784
+ * Structurally parallel to `Rule<Context>` so the `RuleRegistry`
785
+ * treats it uniformly: same `create` + `analyze` lifecycle, same
786
+ * `defaultOff` opt-in semantics, same `severity` for reporter
787
+ * weighting. The engine wires composites after per-file `RuleRegistry`
788
+ * (see `engine/worker.ts` + task 3b.5).
789
+ *
790
+ * Design choice: `CompositeRule<Context>` is its own interface rather
791
+ * than a `Rule<Context>` variant because (a) it carries member-rule
792
+ * metadata (`ruleIds`, `minMatch`) that vanilla rules do not, and
793
+ * (b) the union of the two types would force every consumer to
794
+ * narrow, defeating the structural-parallelism goal.
795
+ */
796
+ interface CompositeRule<Context = unknown> {
797
+ id: string;
798
+ category: Category;
799
+ severity: Severity;
800
+ aiSpecific: boolean;
801
+ /** Short description shown by `slopbrick rules`. */
802
+ description?: string;
803
+ /** v0.42.0: composite rules are opt-in by default. */
804
+ defaultOff?: boolean;
805
+ /** Member rule IDs (sorted, unique). The composite fires when
806
+ * at least `minMatch` of these fire on the same file. */
807
+ ruleIds: string[];
808
+ /** Minimum number of `ruleIds` that must fire together. */
809
+ minMatch: number;
810
+ create(context: RuleContext): Context;
811
+ analyze(context: Context, facts: ScanFacts): Issue[];
812
+ }
813
+ /**
814
+ * v0.42.0 (Sprint 3, task 3b.3): clusterer-emitted composite rule
815
+ * entry. The shape that `engine/cluster.ts` produces and that the
816
+ * `RuleRegistry` loader materializes into `CompositeRule<Context>`
817
+ * instances. Lives next to `CompositeRule<Context>` so the public
818
+ * type surface for empirical composites is in one place.
819
+ *
820
+ * Fields mirror the spec in `docs/superpowers/sprint-0.41-0.42.md`
821
+ * §3b STEP 5: id, ruleIds, minMatch, severity, defaultOff,
822
+ * description, calibration, provenance.
823
+ */
824
+ interface CompositeRuleEntry {
825
+ id: string;
826
+ ruleIds: string[];
827
+ minMatch: number;
828
+ severity: Severity;
829
+ defaultOff: true;
830
+ description: string;
831
+ calibration: {
832
+ recall: number;
833
+ /** False-positive rate, FP / neg_count. */
834
+ FP: number;
835
+ precision: number;
836
+ F1: number;
837
+ nFiles: number;
838
+ };
839
+ provenance: {
840
+ seed: 'auto-cluster' | 'hand-curated-by-brief';
841
+ discoveredAt: string;
842
+ nFiles: number;
843
+ members: number;
844
+ /** Strongest NPMI edge among cluster members (0 if singleton). */
845
+ npmi: number;
846
+ /** Strongest-edge Fisher's p (1 if singleton). */
847
+ fisherP: number;
848
+ };
849
+ }
850
+ /**
851
+ * v0.42.0 (Sprint 3, task 3b.2): input to the empirical composite
852
+ * clusterer. `fireMatrix` is the per-file fired-rule-set map; the
853
+ * other fields are optional inputs to STEP 4 calibration.
854
+ */
855
+ interface ClusterInput {
856
+ /** Per-file fired-rule-set map (file id → set of rule IDs that fired). */
857
+ fireMatrix: ReadonlyMap<string, ReadonlySet<string>>;
858
+ /** Positive (gold-standard) file IDs for recall/precision. */
859
+ positiveFiles?: ReadonlySet<string>;
860
+ /** Severity of each member rule; used to pick `severity = worst`. */
861
+ memberSeverities?: ReadonlyMap<string, Severity>;
862
+ /** Algorithm parameter overrides (all optional). */
863
+ params?: ClusterParamOverrides;
864
+ /** ISO timestamp embedded in `provenance.discoveredAt` for tests. */
865
+ now?: string;
866
+ }
867
+ type ClusterParams = {
868
+ minSupport: number;
869
+ minNPMI: number;
870
+ fisherAlpha: number;
871
+ minClusterSize: number;
872
+ };
873
+ type ClusterParamOverrides = Partial<ClusterParams>;
779
874
  interface ResolvedConfig {
780
875
  framework?: string;
781
876
  hasTailwind?: boolean;
@@ -1060,9 +1155,8 @@ type AiDebt = 'low' | 'medium' | 'high' | 'critical';
1060
1155
  declare const AI_SECURITY_NUMERIC: Record<'low' | 'medium' | 'high' | 'critical', number>;
1061
1156
  /** Inputs to the pure `buildRepositoryHealth` function. Every input is optional. */
1062
1157
  interface RepositoryHealthInputs {
1063
- /** v0.15.0 U.4+: 0-100, higher = better. The new headline score
1064
- * that replaces slopIndex. Tests and callers should pass this
1065
- * going forward. */
1158
+ /** v0.21.0: 0-100, lower = better (raw amount of slop).
1159
+ * Replaces the v0.15-v0.20.1 inverted cleanliness reading. */
1066
1160
  aiSlopScore?: number;
1067
1161
  /** v0.15.0 U.4+: 0-100, higher = better. */
1068
1162
  engineeringHygiene?: number;
@@ -1306,15 +1400,15 @@ interface ProjectReport {
1306
1400
  generatedAt: string;
1307
1401
  configPath?: string;
1308
1402
  /**
1309
- * v0.20.0: renamed from `aiSlopScore` to `aiSlopScore` because the
1310
- * old name implied a property of the *code* (quality) when it
1311
- * actually measures a property of the *tool's detection* (how
1312
- * many AI-detection rules fire on this codebase). 0-100, higher
1313
- * is better — but 'better' means 'fewer rule fires', not
1314
- * 'higher quality code'. The name "AI Slop Score" matches the
1315
- * existing description ("measures AI-slop signatures") and the
1316
- * slopbrick brand. See the pre-publish checklist in
1317
- * CONTRIBUTING.md for the full rationale.
1403
+ * v0.21.0: 0-100, **lower = better** (raw amount of slop).
1404
+ * The CI gate is `aiSlopScore <= meanSlop` (where meanSlop defaults
1405
+ * to 30). Higher values mean more AI-detection rules fired on this
1406
+ * codebase. The previous v0.15-v0.20.1 reading inverted this to
1407
+ * "cleanliness" (higher = better), which made the JSON output and
1408
+ * the CLI gate disagree. This field has been lower-is-better
1409
+ * since v0.21.0; the JSDoc that said "0-100, higher is better"
1410
+ * was a stale v0.15-era comment that survived past the inversion.
1411
+ * Fixed in v0.42.0.
1318
1412
  */
1319
1413
  aiSlopScore: number;
1320
1414
  engineeringHygiene: number;
@@ -1483,6 +1577,18 @@ interface ProjectReport {
1483
1577
  p90Slop: number;
1484
1578
  individualSlopThreshold: number;
1485
1579
  };
1580
+ /**
1581
+ * v0.42.0 (user-review fix): names of thresholds that tripped in this
1582
+ * scan. Optional for backward compat with v0.41 and earlier reports.
1583
+ * Empty/undefined means all gates passed.
1584
+ *
1585
+ * Possible values: 'meanSlop', 'p90Slop', 'individualSlopThreshold',
1586
+ * 'category:<name>' (per-category thresholds).
1587
+ *
1588
+ * CI consumers can grep this field directly instead of parsing the
1589
+ * stderr message. See threshold.ts#failedThresholds for source.
1590
+ */
1591
+ failedThresholds?: string[];
1486
1592
  /** Research/flywheel snapshot — present when the flywheel directory has artifacts. */
1487
1593
  research?: ResearchMetrics;
1488
1594
  topOffenders?: TopOffender[];
@@ -1559,9 +1665,12 @@ interface ProjectReport {
1559
1665
  /** v0.14.5i — Number of distinct rules marked defaultOff. The ratio
1560
1666
  * suppressedCount / defaultOffRuleCount is the calibration coverage. */
1561
1667
  defaultOffRuleCount?: number;
1562
- /** v0.14.5j — The previous run's Slop Index, if any. Used by
1668
+ /** v0.14.5j — The previous run's value, if any. Used by
1563
1669
  * formatPretty to render a "±N from last run" delta so the user
1564
- * can see the trajectory without grep'ing the run log. */
1670
+ * can see the trajectory without grep'ing the run log. The
1671
+ * name is kept as `previousSlopIndex` for backward compat with
1672
+ * telemetry consumers, but the value is the previous
1673
+ * aiSlopScore (since v0.21: lower = cleaner). */
1565
1674
  previousSlopIndex?: number;
1566
1675
  /** v0.14.5j — ISO timestamp of the previous run, paired with
1567
1676
  * previousSlopIndex so the delta line can say "vs 2026-06-27". */
@@ -1612,6 +1721,13 @@ interface ScanProjectOptions {
1612
1721
  noIncrease?: boolean;
1613
1722
  cache?: boolean;
1614
1723
  telemetry?: boolean;
1724
+ /** v0.42.0 (§3a.4): opt-in flag for the AGENTS.md auto-refresh hook.
1725
+ * When true, `slopbrick scan` writes the freshly-built snippet body
1726
+ * inside the `<!-- slopbrick:begin:v3 --> ... -->` block in
1727
+ * AGENTS.md / CLAUDE.md, replacing only that block (user-edited
1728
+ * content outside the markers is preserved). Default false so
1729
+ * first-time users aren't surprised. */
1730
+ autoRefreshSnippets?: boolean;
1615
1731
  }
1616
1732
 
1617
1733
  declare function scanProject(options: ScanProjectOptions): Promise<ProjectReport>;
@@ -1627,6 +1743,16 @@ declare function runCli({ start }: {
1627
1743
 
1628
1744
  declare function thresholdExceeded(report: ProjectReport, config: ResolvedConfig): boolean;
1629
1745
  declare function failedThresholdCount(report: ProjectReport, config: ResolvedConfig): number;
1746
+ /**
1747
+ * v0.42.0 (user-review fix): failedThresholdCount() returned just the
1748
+ * count. The CLI then printed "{n} threshold(s) failed. See details
1749
+ * above." — but in --brief the user sees only the headline CI gate
1750
+ * ("AI Slop Score <= 15 -> fail"), not the per-threshold list.
1751
+ *
1752
+ * This function returns the actual list of failed threshold names so
1753
+ * the caller can name them in the final error message.
1754
+ */
1755
+ declare function failedThresholds(report: ProjectReport, config: ResolvedConfig): string[];
1630
1756
  declare function baselineStatusMessage(baseline: BaselineMeta): string;
1631
1757
  interface StagedGatingResult {
1632
1758
  failed: boolean;
@@ -1674,4 +1800,4 @@ declare function formatBadge(report: ProjectReport): string;
1674
1800
  /** Render an array of values as a Unicode sparkline (▁▂▃▄▅▆▇█). */
1675
1801
  declare function formatSparkline(values: number[]): string;
1676
1802
 
1677
- export { AI_SECURITY_NUMERIC, type AiDebt, type AiMaintenanceCost, type AiMaintenanceCostResult, type AstroComponentFact, type AutoRelaxedRule, type AutoTunedRule, type BaselineCache, type BaselineMeta, type CachedFile, type Category, type ClassNameFact, type CommentFact, type ComponentFacts, type ComponentScore, type ComponentSizeFact, type ConsoleCallFact, type Constitution, DEFAULT_CONFIG, type DangerouslySetInnerHtmlFact, type DbDriftLevel, type DbFinding, type DialogCallFact, type DisabledLintRuleFact, type DocDriftLevel, type DocFinding, type DomQueryFact, type ElementFact, type EvalCallFact, type ExplicitAnyFact, type FetchCallFact, type FileScanResult, type FixSuggestion, type FlywheelOutput, type FlywheelState, type Framework$1 as Framework, type HealthFile, type HookCallFact, type HookDependencyArrayFact, type HookFact, type ImportFact, type InlineEventHandlerFact, type Issue, type JsxAttributeStringLiteralFact, type JsxTextLiteralFact, type KeyPropFact, type LogicalExpressionFact, type MagicNumberSpacingConfig, type MaintenanceAxes, type MaintenanceAxisHealth, type NonNullAssertionFact, type OptimisticUpdateFact, type ProjectReport, type PropMutationFact, type PropPassThroughFact, REPOSITORY_HEALTH_WEIGHTS, type ReportReadResult, type RepositoryHealth, type RepositoryHealthInputs, type ResearchMetrics, type ResolvedConfig, type Rule, type RuleContext, type RuleSeverity, type RuleSuggestion, type ScanCache, type ScanFacts, type ScanProjectOptions, type ScanSelfScanConfig, type Severity, type SlopAuditRun, type StateBinding, type StateBindingFact, type StringLiteralFact, type StylePropFact, type TamaguiStylePropFact, type TopOffender, type UseEffectBodyFact, VERSION, baselineStatusMessage, colorForSlop, failedThresholdCount, filterByDisabledDirectives, filterIssues, formatBadge, formatReportFromFile, formatSparkline, loadConfig, readReportFile, runCli, runInitWizard, scanProject, serializeConfig, stagedGating, thresholdExceeded };
1803
+ export { AI_SECURITY_NUMERIC, type AiDebt, type AiMaintenanceCost, type AiMaintenanceCostResult, type AstroComponentFact, type AutoRelaxedRule, type AutoTunedRule, type BaselineCache, type BaselineMeta, type CachedFile, type Category, type ClassNameFact, type ClusterInput, type ClusterParamOverrides, type ClusterParams, type CommentFact, type ComponentFacts, type ComponentScore, type ComponentSizeFact, type CompositeRule, type CompositeRuleEntry, type ConsoleCallFact, type Constitution, DEFAULT_CONFIG, type DangerouslySetInnerHtmlFact, type DbDriftLevel, type DbFinding, type DialogCallFact, type DisabledLintRuleFact, type DocDriftLevel, type DocFinding, type DomQueryFact, type ElementFact, type EvalCallFact, type ExplicitAnyFact, type FetchCallFact, type FileScanResult, type FixSuggestion, type FlywheelOutput, type FlywheelState, type Framework$1 as Framework, type HealthFile, type HookCallFact, type HookDependencyArrayFact, type HookFact, type ImportFact, type InlineEventHandlerFact, type Issue, type JsxAttributeStringLiteralFact, type JsxTextLiteralFact, type KeyPropFact, type LogicalExpressionFact, type MagicNumberSpacingConfig, type MaintenanceAxes, type MaintenanceAxisHealth, type NonNullAssertionFact, type OptimisticUpdateFact, type ProjectReport, type PropMutationFact, type PropPassThroughFact, REPOSITORY_HEALTH_WEIGHTS, type ReportReadResult, type RepositoryHealth, type RepositoryHealthInputs, type ResearchMetrics, type ResolvedConfig, type Rule, type RuleContext, type RuleSeverity, type RuleSuggestion, type ScanCache, type ScanFacts, type ScanProjectOptions, type ScanSelfScanConfig, type Severity, type SlopAuditRun, type StateBinding, type StateBindingFact, type StringLiteralFact, type StylePropFact, type TamaguiStylePropFact, type TopOffender, type UseEffectBodyFact, VERSION, baselineStatusMessage, colorForSlop, failedThresholdCount, failedThresholds, filterByDisabledDirectives, filterIssues, formatBadge, formatReportFromFile, formatSparkline, loadConfig, readReportFile, runCli, runInitWizard, scanProject, serializeConfig, stagedGating, thresholdExceeded };