@antelopejs/tooling-configs 0.0.9 → 0.2.1

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.
@@ -1,160 +1,92 @@
1
+ import { n as TEST_FILE_GLOBS, t as ASSERTION_FUNCTION_NAMES } from "../shared-BG0Nkzh0.mjs";
1
2
  //#region src/oxc/lint.d.ts
2
3
  /**
3
- * The paths the preset ignores. oxlint does not merge `ignorePatterns` across
4
- * `extends`: a root config that declares its own **replaces** these, so spread
5
- * them when a repository adds patterns of its own.
6
- *
7
- * @example
8
- * ```ts
9
- * export default defineConfig({
10
- * extends: [antelopePreset()],
11
- * ignorePatterns: [...ANTELOPE_IGNORE_PATTERNS, "playground/**"],
12
- * });
13
- * ```
4
+ * oxlint replaces rather than merges ignorePatterns across extends.
5
+ * Spread these patterns when adding repository-specific ignores.
14
6
  */
15
7
  declare const ANTELOPE_IGNORE_PATTERNS: string[];
16
- type Severity = "off" | "warn" | "error";
17
- /**
18
- * Thresholds for the complexity rules. The defaults are deliberately looser than
19
- * oxlint's own (3 parameters, 50 lines per function): AntelopeJS handlers take a
20
- * request context plus its dependencies, and interface files declare long types.
21
- * They are meant to catch the outliers, not to redesign every signature.
22
- */
8
+ type Severity = "off" | "error";
9
+ /** Thresholds allow request contexts and dependencies while rejecting outlier signatures and files. */
23
10
  interface ComplexityThresholds {
24
- /** `eslint/max-params` (oxlint default: 3). */
25
11
  maxParams: number;
26
- /** `eslint/max-lines-per-function` (oxlint default: 50). */
27
12
  maxLinesPerFunction: number;
28
- /** `eslint/max-lines` (oxlint default: 300). */
29
13
  maxLines: number;
30
- /** `eslint/max-depth` (oxlint default: 4). */
31
14
  maxDepth: number;
32
- /** `eslint/complexity`, cyclomatic (oxlint default: 20). */
33
15
  complexity: number;
34
16
  }
35
17
  declare const DEFAULT_COMPLEXITY_THRESHOLDS: ComplexityThresholds;
36
18
  interface AntelopePresetOptions {
19
+ /** All fifteen vendored anti-slop rules. Defaults to true. */
20
+ antiSlop?: boolean;
21
+ /** Comment and test-quality rules. Defaults to true. */
22
+ guardrails?: boolean;
23
+ /** Complexity limits at error. Pass an object to override thresholds, or false to disable. */
24
+ complexity?: boolean | Partial<ComplexityThresholds>;
37
25
  /**
38
- * Vendored anti-slop rules, which reject low-evidence TypeScript (`unknown`
39
- * parameters, unjustified `as` assertions, open dictionaries...).
40
- * `true` maps to `"warn"`: a repository adopting them has findings to work
41
- * through before the gate can be raised to `"error"`.
42
- *
43
- * @default "warn"
44
- */
45
- antiSlop?: boolean | Severity;
46
- /**
47
- * Complexity ceilings. Pass an object to override individual thresholds.
48
- *
49
- * @default "warn" with {@link DEFAULT_COMPLEXITY_THRESHOLDS}
50
- */
51
- complexity?: boolean | (Partial<ComplexityThresholds> & {
52
- severity?: Severity;
53
- });
54
- /**
55
- * Import sorting through `eslint-plugin-perfectionist`, autofixed by
56
- * `oxlint --fix`.
57
- *
58
- * Off by default, because the sort moves value imports across side-effect
59
- * imports and module evaluation order is load-bearing in an AntelopeJS
60
- * module: `import "./components"` is what puts the decorated classes in the
61
- * registry. Running it over the cms/dms repositories moved
62
- * `import { CORE_SCHEMA_NAME } from ".../constants"` from before
63
- * `import "./db"` to after `import "./routes"` -- in a file whose comment
64
- * says the position is deliberate -- and broke the package at require time.
65
- * Nothing in a typecheck or a build catches it.
66
- *
67
- * `sortSideEffects: false` is not enough: it keeps side-effect imports in
68
- * place (verified across 1402 files, none moved) but lets everything else
69
- * cross them. `partitionByNewLine`, which would fix that, is refused by
70
- * perfectionist 5.11 -- it conflicts with both `newlinesBetween` and
71
- * `newlinesInside`. Turn this back on when the rule can guarantee that no
72
- * import crosses a side-effect import.
73
- *
74
- * The plugin is an optional peer dependency: it pulls ESLint and
75
- * typescript-eslint in with it, which a repository leaving this off has no
76
- * reason to install. Add `eslint-plugin-perfectionist` alongside this package
77
- * when turning it on.
78
- *
79
- * @default false
26
+ * Import sorting through eslint-plugin-perfectionist, autofixed by oxlint --fix.
27
+ * Off by default because sorting value imports across side-effect imports
28
+ * changes module registration order and breaks AntelopeJS packages at require time.
29
+ * sortSideEffects: false keeps side-effect imports in place but lets values cross them.
30
+ * perfectionist 5.11 refuses partitionByNewLine with newlinesBetween or newlinesInside.
31
+ * Enable only when no import can cross a side-effect import, and install the optional
32
+ * eslint-plugin-perfectionist peer dependency alongside this package.
80
33
  */
81
34
  importSorting?: boolean;
35
+ /** Import cycles fail at runtime. Defaults to true. */
36
+ importCycles?: boolean;
82
37
  /**
83
- * Severity of `import/no-cycle`. A cycle only shows up at runtime, in a
84
- * consumer's process, so it ships as an error — but a repository that already
85
- * has cycles needs to see them without a red pipeline while it untangles them.
86
- *
87
- * @default "error"
88
- */
89
- importCycles?: boolean | Severity;
90
- /**
91
- * `typescript/no-floating-promises`, which needs type information. The
92
- * consuming repository must also set `options.typeAware` in its own root
93
- * config: oxlint only reads that field there, never from an extended preset.
94
- *
95
- * @default true
38
+ * Type-aware rules. Defaults to true. Consumers must also set options.typeAware
39
+ * in their root config because oxlint never reads that field from extends.
96
40
  */
97
41
  typeAware?: boolean;
98
42
  }
99
- /** Every generic anti-slop rule, exported so this package can lint itself. */
100
- /**
101
- * The anti-slop rules left off by default.
102
- *
103
- * Measured across the sixteen cms/dms repositories: these seven produced 3038
104
- * of the 3429 anti-slop findings, and every sample we read was either the
105
- * correct idiom or a design change well beyond a lint pass.
106
- *
107
- * - `require-safety-comment-for-type-assertion` (1283) is satisfied by writing
108
- * a comment, so at that volume it manufactures the noise it exists to fight.
109
- * Removing assertions is the goal; annotating them is not.
110
- * - `no-unknown-parameters` (566) and `no-unknown-returns` (104) fire on catch
111
- * handlers, where `unknown` is the only correct type, and on the parsers
112
- * whose whole job is to take unknown in and hand typed values out.
113
- * - `no-runtime-typeof` (460) assumes a validation layer above the check. In a
114
- * CMS reading Vault responses, WebSocket frames and user-defined rows, the
115
- * `typeof` *is* that layer.
116
- * - `no-unsafe-dictionary-type` (442) is right in a business application and
117
- * wrong here: tables and columns defined at run time have no compile-time
118
- * schema, which is the product, not a typing gap.
119
- * - `no-shape-in-symbol-names` (104) matches a substring in identifiers and
120
- * catches domain words such as `BlueGreenShape`.
121
- * - `no-module-mocking` (79) is a test-architecture position, not cleanup.
122
- * - `no-known-value-widening` (201) is the near miss. Of 174 sampled, 96 are
123
- * `return accumulator` where the object was filled in a loop from run-time
124
- * keys, so the open dictionary is the honest type and there is no evidence to
125
- * preserve; the rule reads them as stable consts because assigning a property
126
- * is not a write to the binding. The 53 real ones -- annotated object
127
- * literals that should use `satisfies` -- are worth fixing by hand, and are,
128
- * but not at the price of 96 suppressions. Narrowing the rule to literals
129
- * would make it worth turning back on.
130
- *
131
- * A repository that wants one back enables it in its own `rules` block.
132
- */
133
- declare const ANTI_SLOP_RULES_OFF_BY_DEFAULT: readonly ["no-known-value-widening", "no-module-mocking", "no-runtime-typeof", "no-shape-in-symbol-names", "no-unknown-parameters", "no-unknown-returns", "no-unsafe-dictionary-type", "require-safety-comment-for-type-assertion"];
43
+ /** Every vendored anti-slop rule, also used to lint this package from source. */
134
44
  declare const ANTI_SLOP_RULES: readonly ["no-chained-type-assertions", "no-conditional-empty-object-spread", "no-known-value-widening", "no-module-mocking", "no-object-parameters", "no-reflect-apply", "no-reflect-get", "no-runtime-typeof", "no-shape-in-symbol-names", "no-unknown-parameters", "no-unknown-returns", "no-unknown-type-aliases", "no-unsafe-dictionary-type", "no-widen-then-assert", "require-safety-comment-for-type-assertion"];
135
- /**
136
- * The anti-slop rules at one severity. Exported for this repository's own config:
137
- * it registers the plugin from source rather than through the package exports,
138
- * so linting never waits on a build.
139
- */
140
- declare function antiSlopRules(severity: Severity): Record<string, Severity>;
141
- /**
142
- * The shared AntelopeJS oxlint preset: oxc's own defaults (the `correctness`
143
- * category), plus import hygiene, complexity ceilings, import sorting, and the
144
- * vendored anti-slop rules.
145
- *
146
- * @example
147
- * ```ts
148
- * // oxlint.config.ts
149
- * import { defineConfig } from "oxlint";
150
- * import { antelopePreset } from "@antelopejs/tooling-configs/oxc/lint";
151
- *
152
- * export default defineConfig({
153
- * extends: [antelopePreset()],
154
- * options: { typeAware: true },
155
- * });
156
- * ```
157
- */
45
+ /** All vendored rules at one severity, without resolving the published plugin. */
46
+ declare function antiSlopRules(severity?: Severity): Record<string, Severity>;
47
+ /** Jest matcher semantics and module restrictions are not portable to Mocha, Chai, and Vitest. */
48
+ declare const FRAMEWORK_SPECIFIC_JEST_RULES: {
49
+ readonly "jest/no-conditional-expect": "off";
50
+ readonly "jest/no-export": "off";
51
+ readonly "jest/no-standalone-expect": "off";
52
+ readonly "jest/prefer-snapshot-hint": "off";
53
+ readonly "jest/require-to-throw-message": "off";
54
+ readonly "jest/valid-expect": "off";
55
+ readonly "jest/valid-expect-in-promise": "off";
56
+ };
57
+ /** Source and published registration share test overrides without Jest framework detection. */
58
+ declare function guardrailsRules(): {
59
+ plugins: "jest"[];
60
+ rules: {
61
+ "jest/expect-expect": "off";
62
+ "antelopejs/no-comments": "error";
63
+ "jest/no-conditional-expect": "off";
64
+ "jest/no-export": "off";
65
+ "jest/no-standalone-expect": "off";
66
+ "jest/prefer-snapshot-hint": "off";
67
+ "jest/require-to-throw-message": "off";
68
+ "jest/valid-expect": "off";
69
+ "jest/valid-expect-in-promise": "off";
70
+ };
71
+ overrides: ({
72
+ files: string[];
73
+ rules: {
74
+ "antelopejs/no-fs-read-in-tests": "error";
75
+ "antelopejs/no-constant-value-assertion": "error";
76
+ "antelopejs/no-typeof-function-only-test": "error";
77
+ "antelopejs/require-assertion": "error";
78
+ };
79
+ } | {
80
+ files: string[];
81
+ rules: {
82
+ "antelopejs/no-fs-read-in-tests": "off";
83
+ "antelopejs/no-constant-value-assertion"?: undefined;
84
+ "antelopejs/no-typeof-function-only-test"?: undefined;
85
+ "antelopejs/require-assertion"?: undefined;
86
+ };
87
+ })[];
88
+ };
89
+ /** The shared AntelopeJS preset. Every enabled rule fails CI; recorded debt is enforced by the ratchet. */
158
90
  declare function antelopePreset(options?: AntelopePresetOptions): {
159
91
  extends: ({
160
92
  categories: {
@@ -174,21 +106,21 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
174
106
  }];
175
107
  "eslint/radix": "error";
176
108
  "eslint/prefer-regex-literals": "error";
177
- "import/no-cycle": Severity;
109
+ "import/no-cycle": "off" | "error";
178
110
  "import/no-self-import": "error";
179
111
  "import/no-duplicates": "error";
180
112
  };
181
113
  } | {
182
114
  rules: {
183
115
  "typescript/no-floating-promises": "error";
184
- "typescript/await-thenable": "warn";
185
- "typescript/unbound-method": "warn";
186
- "typescript/no-meaningless-void-operator": "warn";
187
- "typescript/no-misused-spread": "warn";
188
- "typescript/no-base-to-string": "warn";
189
- "typescript/no-redundant-type-constituents": "warn";
190
- "typescript/restrict-template-expressions": "warn";
191
- "typescript/require-array-sort-compare": "warn";
116
+ "typescript/await-thenable": "error";
117
+ "typescript/unbound-method": "error";
118
+ "typescript/no-meaningless-void-operator": "error";
119
+ "typescript/no-misused-spread": "error";
120
+ "typescript/no-base-to-string": "error";
121
+ "typescript/no-redundant-type-constituents": "error";
122
+ "typescript/restrict-template-expressions": "error";
123
+ "typescript/require-array-sort-compare": "error";
192
124
  };
193
125
  } | {
194
126
  jsPlugins: {
@@ -196,25 +128,61 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
196
128
  specifier: string;
197
129
  }[];
198
130
  rules: Record<string, Severity>;
131
+ } | {
132
+ extends: {
133
+ plugins: "jest"[];
134
+ rules: {
135
+ "jest/expect-expect": "off";
136
+ "antelopejs/no-comments": "error";
137
+ "jest/no-conditional-expect": "off";
138
+ "jest/no-export": "off";
139
+ "jest/no-standalone-expect": "off";
140
+ "jest/prefer-snapshot-hint": "off";
141
+ "jest/require-to-throw-message": "off";
142
+ "jest/valid-expect": "off";
143
+ "jest/valid-expect-in-promise": "off";
144
+ };
145
+ overrides: ({
146
+ files: string[];
147
+ rules: {
148
+ "antelopejs/no-fs-read-in-tests": "error";
149
+ "antelopejs/no-constant-value-assertion": "error";
150
+ "antelopejs/no-typeof-function-only-test": "error";
151
+ "antelopejs/require-assertion": "error";
152
+ };
153
+ } | {
154
+ files: string[];
155
+ rules: {
156
+ "antelopejs/no-fs-read-in-tests": "off";
157
+ "antelopejs/no-constant-value-assertion"?: undefined;
158
+ "antelopejs/no-typeof-function-only-test"?: undefined;
159
+ "antelopejs/require-assertion"?: undefined;
160
+ };
161
+ })[];
162
+ }[];
163
+ jsPlugins: {
164
+ name: string;
165
+ specifier: string;
166
+ }[];
199
167
  } | {
200
168
  rules: {
201
- "eslint/max-params": [Severity, {
169
+ "eslint/max-params": ["error", {
202
170
  max: number;
203
171
  }];
204
- "eslint/max-lines-per-function": [Severity, {
172
+ "eslint/max-lines-per-function": ["error", {
205
173
  max: number;
206
174
  skipBlankLines: true;
207
175
  skipComments: true;
208
176
  }];
209
- "eslint/max-lines": [Severity, {
177
+ "eslint/max-lines": ["error", {
210
178
  max: number;
211
179
  skipBlankLines: true;
212
180
  skipComments: true;
213
181
  }];
214
- "eslint/max-depth": [Severity, {
182
+ "eslint/max-depth": ["error", {
215
183
  max: number;
216
184
  }];
217
- "eslint/complexity": [Severity, {
185
+ "eslint/complexity": ["error", {
218
186
  max: number;
219
187
  }];
220
188
  };
@@ -233,6 +201,15 @@ declare function antelopePreset(options?: AntelopePresetOptions): {
233
201
  rules: {
234
202
  "typescript/no-floating-promises": "off" | "error";
235
203
  };
204
+ overrides: ({
205
+ files: string[];
206
+ rules: {
207
+ "eslint/max-lines": "off";
208
+ };
209
+ } | {
210
+ files: string[];
211
+ rules: Record<string, "off">;
212
+ })[];
236
213
  };
237
214
  //#endregion
238
- export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ANTI_SLOP_RULES_OFF_BY_DEFAULT, AntelopePresetOptions, ComplexityThresholds, DEFAULT_COMPLEXITY_THRESHOLDS, antelopePreset, antiSlopRules };
215
+ export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ASSERTION_FUNCTION_NAMES, AntelopePresetOptions, ComplexityThresholds, DEFAULT_COMPLEXITY_THRESHOLDS, FRAMEWORK_SPECIFIC_JEST_RULES, TEST_FILE_GLOBS, antelopePreset, antiSlopRules, guardrailsRules };
package/dist/oxc/lint.mjs CHANGED
@@ -1,18 +1,11 @@
1
- import { n as IGNORE_PATTERNS, t as AGENT_IGNORE_PATTERNS } from "../shared-Ch-ZcMQb.mjs";
1
+ import { i as findGitRoot, o as readCeilings } from "../ceilings--pJmhSde.mjs";
2
+ import { n as TEST_FILE_GLOBS, t as ASSERTION_FUNCTION_NAMES } from "../shared-WC0z3y9F.mjs";
3
+ import { n as IGNORE_PATTERNS, t as AGENT_IGNORE_PATTERNS } from "../shared-NC0T8ykm.mjs";
2
4
  import { defineConfig } from "oxlint";
3
5
  //#region src/oxc/lint.ts
4
6
  /**
5
- * The paths the preset ignores. oxlint does not merge `ignorePatterns` across
6
- * `extends`: a root config that declares its own **replaces** these, so spread
7
- * them when a repository adds patterns of its own.
8
- *
9
- * @example
10
- * ```ts
11
- * export default defineConfig({
12
- * extends: [antelopePreset()],
13
- * ignorePatterns: [...ANTELOPE_IGNORE_PATTERNS, "playground/**"],
14
- * });
15
- * ```
7
+ * oxlint replaces rather than merges ignorePatterns across extends.
8
+ * Spread these patterns when adding repository-specific ignores.
16
9
  */
17
10
  const ANTELOPE_IGNORE_PATTERNS = [...IGNORE_PATTERNS, ...AGENT_IGNORE_PATTERNS];
18
11
  const DEFAULT_COMPLEXITY_THRESHOLDS = {
@@ -22,50 +15,7 @@ const DEFAULT_COMPLEXITY_THRESHOLDS = {
22
15
  maxDepth: 4,
23
16
  complexity: 20
24
17
  };
25
- /** Every generic anti-slop rule, exported so this package can lint itself. */
26
- /**
27
- * The anti-slop rules left off by default.
28
- *
29
- * Measured across the sixteen cms/dms repositories: these seven produced 3038
30
- * of the 3429 anti-slop findings, and every sample we read was either the
31
- * correct idiom or a design change well beyond a lint pass.
32
- *
33
- * - `require-safety-comment-for-type-assertion` (1283) is satisfied by writing
34
- * a comment, so at that volume it manufactures the noise it exists to fight.
35
- * Removing assertions is the goal; annotating them is not.
36
- * - `no-unknown-parameters` (566) and `no-unknown-returns` (104) fire on catch
37
- * handlers, where `unknown` is the only correct type, and on the parsers
38
- * whose whole job is to take unknown in and hand typed values out.
39
- * - `no-runtime-typeof` (460) assumes a validation layer above the check. In a
40
- * CMS reading Vault responses, WebSocket frames and user-defined rows, the
41
- * `typeof` *is* that layer.
42
- * - `no-unsafe-dictionary-type` (442) is right in a business application and
43
- * wrong here: tables and columns defined at run time have no compile-time
44
- * schema, which is the product, not a typing gap.
45
- * - `no-shape-in-symbol-names` (104) matches a substring in identifiers and
46
- * catches domain words such as `BlueGreenShape`.
47
- * - `no-module-mocking` (79) is a test-architecture position, not cleanup.
48
- * - `no-known-value-widening` (201) is the near miss. Of 174 sampled, 96 are
49
- * `return accumulator` where the object was filled in a loop from run-time
50
- * keys, so the open dictionary is the honest type and there is no evidence to
51
- * preserve; the rule reads them as stable consts because assigning a property
52
- * is not a write to the binding. The 53 real ones -- annotated object
53
- * literals that should use `satisfies` -- are worth fixing by hand, and are,
54
- * but not at the price of 96 suppressions. Narrowing the rule to literals
55
- * would make it worth turning back on.
56
- *
57
- * A repository that wants one back enables it in its own `rules` block.
58
- */
59
- const ANTI_SLOP_RULES_OFF_BY_DEFAULT = [
60
- "no-known-value-widening",
61
- "no-module-mocking",
62
- "no-runtime-typeof",
63
- "no-shape-in-symbol-names",
64
- "no-unknown-parameters",
65
- "no-unknown-returns",
66
- "no-unsafe-dictionary-type",
67
- "require-safety-comment-for-type-assertion"
68
- ];
18
+ /** Every vendored anti-slop rule, also used to lint this package from source. */
69
19
  const ANTI_SLOP_RULES = [
70
20
  "no-chained-type-assertions",
71
21
  "no-conditional-empty-object-spread",
@@ -83,14 +33,8 @@ const ANTI_SLOP_RULES = [
83
33
  "no-widen-then-assert",
84
34
  "require-safety-comment-for-type-assertion"
85
35
  ];
86
- /** Shared empty override set, so the threshold spread is never conditional. */
87
- const EMPTY_THRESHOLDS = {};
88
- function severityOf(option, fallback) {
89
- if (option === void 0 || option === true) return fallback;
90
- if (option === false) return "off";
91
- return option;
92
- }
93
- function basePreset(cycleSeverity) {
36
+ /** Correctness must fail CI; underscore bindings and omitted rest siblings are intentional. */
37
+ function basePreset(importCycles) {
94
38
  return defineConfig({
95
39
  categories: { correctness: "error" },
96
40
  ignorePatterns: ANTELOPE_IGNORE_PATTERNS,
@@ -116,66 +60,102 @@ function basePreset(cycleSeverity) {
116
60
  ],
117
61
  "eslint/radix": "error",
118
62
  "eslint/prefer-regex-literals": "error",
119
- "import/no-cycle": cycleSeverity,
63
+ "import/no-cycle": importCycles ? "error" : "off",
120
64
  "import/no-self-import": "error",
121
65
  "import/no-duplicates": "error"
122
66
  }
123
67
  });
124
68
  }
125
- /**
126
- * The anti-slop rules at one severity. Exported for this repository's own config:
127
- * it registers the plugin from source rather than through the package exports,
128
- * so linting never waits on a build.
129
- */
130
- function antiSlopRules(severity) {
131
- const off = new Set(ANTI_SLOP_RULES_OFF_BY_DEFAULT);
132
- return Object.fromEntries(ANTI_SLOP_RULES.map((rule) => [`anti-slop/${rule}`, off.has(rule) ? "off" : severity]));
69
+ /** All vendored rules at one severity, without resolving the published plugin. */
70
+ function antiSlopRules(severity = "error") {
71
+ return Object.fromEntries(ANTI_SLOP_RULES.map((rule) => [`anti-slop/${rule}`, severity]));
133
72
  }
134
- function antiSlopPreset(severity) {
73
+ function antiSlopPreset() {
135
74
  return defineConfig({
136
75
  jsPlugins: [{
137
76
  name: "anti-slop",
138
77
  specifier: "@antelopejs/tooling-configs/oxc/anti-slop"
139
78
  }],
140
- rules: antiSlopRules(severity)
79
+ rules: antiSlopRules()
141
80
  });
142
81
  }
143
- function complexityPreset(thresholds, severity) {
82
+ /** Jest matcher semantics and module restrictions are not portable to Mocha, Chai, and Vitest. */
83
+ const FRAMEWORK_SPECIFIC_JEST_RULES = {
84
+ "jest/no-conditional-expect": "off",
85
+ "jest/no-export": "off",
86
+ "jest/no-standalone-expect": "off",
87
+ "jest/prefer-snapshot-hint": "off",
88
+ "jest/require-to-throw-message": "off",
89
+ "jest/valid-expect": "off",
90
+ "jest/valid-expect-in-promise": "off"
91
+ };
92
+ /** Source and published registration share test overrides without Jest framework detection. */
93
+ function guardrailsRules() {
94
+ return defineConfig({
95
+ plugins: ["jest"],
96
+ rules: {
97
+ ...FRAMEWORK_SPECIFIC_JEST_RULES,
98
+ "jest/expect-expect": "off",
99
+ "antelopejs/no-comments": "error"
100
+ },
101
+ overrides: [{
102
+ files: TEST_FILE_GLOBS,
103
+ rules: {
104
+ "antelopejs/no-fs-read-in-tests": "error",
105
+ "antelopejs/no-constant-value-assertion": "error",
106
+ "antelopejs/no-typeof-function-only-test": "error",
107
+ "antelopejs/require-assertion": "error"
108
+ }
109
+ }, {
110
+ files: [
111
+ "**/fixtures/**",
112
+ "**/helpers/**",
113
+ "**/locales/**"
114
+ ],
115
+ rules: { "antelopejs/no-fs-read-in-tests": "off" }
116
+ }]
117
+ });
118
+ }
119
+ function guardrailsPreset() {
120
+ return defineConfig({
121
+ extends: [guardrailsRules()],
122
+ jsPlugins: [{
123
+ name: "antelopejs",
124
+ specifier: "@antelopejs/tooling-configs/oxc/guardrails"
125
+ }]
126
+ });
127
+ }
128
+ function complexityPreset(thresholds) {
144
129
  return defineConfig({ rules: {
145
- "eslint/max-params": [severity, { max: thresholds.maxParams }],
146
- "eslint/max-lines-per-function": [severity, {
130
+ "eslint/max-params": ["error", { max: thresholds.maxParams }],
131
+ "eslint/max-lines-per-function": ["error", {
147
132
  max: thresholds.maxLinesPerFunction,
148
133
  skipBlankLines: true,
149
134
  skipComments: true
150
135
  }],
151
- "eslint/max-lines": [severity, {
136
+ "eslint/max-lines": ["error", {
152
137
  max: thresholds.maxLines,
153
138
  skipBlankLines: true,
154
139
  skipComments: true
155
140
  }],
156
- "eslint/max-depth": [severity, { max: thresholds.maxDepth }],
157
- "eslint/complexity": [severity, { max: thresholds.complexity }]
141
+ "eslint/max-depth": ["error", { max: thresholds.maxDepth }],
142
+ "eslint/complexity": ["error", { max: thresholds.complexity }]
158
143
  } });
159
144
  }
160
- /**
161
- * Turning on type information enables a whole family of rules, not just the one
162
- * worth the setup. `no-floating-promises` catches a promise whose rejection is
163
- * lost, which is why type-aware linting is worth running at all; the rest report
164
- * until a repository has worked through them, like every other backlog here.
165
- */
166
145
  function typeAwarePreset() {
167
146
  return defineConfig({ rules: {
168
147
  "typescript/no-floating-promises": "error",
169
- "typescript/await-thenable": "warn",
170
- "typescript/unbound-method": "warn",
171
- "typescript/no-meaningless-void-operator": "warn",
172
- "typescript/no-misused-spread": "warn",
173
- "typescript/no-base-to-string": "warn",
174
- "typescript/no-redundant-type-constituents": "warn",
175
- "typescript/restrict-template-expressions": "warn",
176
- "typescript/require-array-sort-compare": "warn"
148
+ "typescript/await-thenable": "error",
149
+ "typescript/unbound-method": "error",
150
+ "typescript/no-meaningless-void-operator": "error",
151
+ "typescript/no-misused-spread": "error",
152
+ "typescript/no-base-to-string": "error",
153
+ "typescript/no-redundant-type-constituents": "error",
154
+ "typescript/restrict-template-expressions": "error",
155
+ "typescript/require-array-sort-compare": "error"
177
156
  } });
178
157
  }
158
+ /** Side-effect imports register classes, so sorting may never relocate them. */
179
159
  function importSortingPreset() {
180
160
  return defineConfig({
181
161
  jsPlugins: ["eslint-plugin-perfectionist"],
@@ -196,43 +176,38 @@ function importSortingPreset() {
196
176
  }] }
197
177
  });
198
178
  }
199
- /**
200
- * The shared AntelopeJS oxlint preset: oxc's own defaults (the `correctness`
201
- * category), plus import hygiene, complexity ceilings, import sorting, and the
202
- * vendored anti-slop rules.
203
- *
204
- * @example
205
- * ```ts
206
- * // oxlint.config.ts
207
- * import { defineConfig } from "oxlint";
208
- * import { antelopePreset } from "@antelopejs/tooling-configs/oxc/lint";
209
- *
210
- * export default defineConfig({
211
- * extends: [antelopePreset()],
212
- * options: { typeAware: true },
213
- * });
214
- * ```
215
- */
179
+ /** Overrides run after rules, including test-specific rules; measurement bypasses all ceilings. */
180
+ function ratchetOverrides() {
181
+ if (process.env["ANTELOPEJS_RATCHET_MEASURE"] !== void 0) return [];
182
+ const ceilings = readCeilings(findGitRoot());
183
+ const rules = Object.fromEntries(Object.keys(ceilings.rules).map((rule) => [rule, "off"]));
184
+ return [...Object.keys(ceilings.oversizeFiles).map((path) => ({
185
+ files: [path.replaceAll(/([*?[\]{}])/gu, "\\$1")],
186
+ rules: { "eslint/max-lines": "off" }
187
+ })), {
188
+ files: ["**/*"],
189
+ rules
190
+ }];
191
+ }
192
+ /** The shared AntelopeJS preset. Every enabled rule fails CI; recorded debt is enforced by the ratchet. */
216
193
  function antelopePreset(options = {}) {
217
- const complexity = options.complexity ?? true;
218
- const isToggle = complexity === true || complexity === false;
219
- const overrides = isToggle ? EMPTY_THRESHOLDS : complexity;
220
- const complexityThresholds = {
221
- ...DEFAULT_COMPLEXITY_THRESHOLDS,
222
- ...overrides
194
+ let thresholds = DEFAULT_COMPLEXITY_THRESHOLDS;
195
+ if (options.complexity !== true && options.complexity !== false && options.complexity !== void 0) thresholds = {
196
+ ...thresholds,
197
+ ...options.complexity
223
198
  };
224
- const complexitySeverity = severityOf(isToggle ? complexity : overrides.severity ?? true, "warn");
225
- const antiSlopSeverity = severityOf(options.antiSlop, "warn");
226
199
  return defineConfig({
227
200
  extends: [
228
- basePreset(severityOf(options.importCycles, "error")),
201
+ basePreset(options.importCycles !== false),
229
202
  options.typeAware === false ? null : typeAwarePreset(),
230
- antiSlopSeverity === "off" ? null : antiSlopPreset(antiSlopSeverity),
231
- complexitySeverity === "off" ? null : complexityPreset(complexityThresholds, complexitySeverity),
203
+ options.antiSlop === false ? null : antiSlopPreset(),
204
+ options.guardrails === false ? null : guardrailsPreset(),
205
+ options.complexity === false ? null : complexityPreset(thresholds),
232
206
  options.importSorting === true ? importSortingPreset() : null
233
207
  ].filter((config) => config !== null),
234
- rules: { "typescript/no-floating-promises": options.typeAware === false ? "off" : "error" }
208
+ rules: { "typescript/no-floating-promises": options.typeAware === false ? "off" : "error" },
209
+ overrides: ratchetOverrides()
235
210
  });
236
211
  }
237
212
  //#endregion
238
- export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ANTI_SLOP_RULES_OFF_BY_DEFAULT, DEFAULT_COMPLEXITY_THRESHOLDS, antelopePreset, antiSlopRules };
213
+ export { ANTELOPE_IGNORE_PATTERNS, ANTI_SLOP_RULES, ASSERTION_FUNCTION_NAMES, DEFAULT_COMPLEXITY_THRESHOLDS, FRAMEWORK_SPECIFIC_JEST_RULES, TEST_FILE_GLOBS, antelopePreset, antiSlopRules, guardrailsRules };