@cascivo/eslint-config 0.2.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- generated by scripts/readme/generate.ts — edit readme.body.md, not this file -->
2
2
 
3
3
  <div align="center">
4
- <a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="72" height="72" alt="cascivo logo"></a>
4
+ <a href="https://cascivo.com"><img src="https://cascivo.com/logo-mark-img-accent.svg" width="72" height="72" alt="cascivo logo"></a>
5
5
  <h1>@cascivo/eslint-config</h1>
6
6
  <p><strong>Flat ESLint config for apps using cascivo — reconciles the signal-based reactivity contract with eslint-plugin-react-hooks 7</strong></p>
7
7
 
@@ -26,4 +26,4 @@ pnpm add @cascivo/eslint-config
26
26
 
27
27
  [cascivo.com](https://cascivo.com) · [Docs](https://cascivo.com/docs) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo) · AI agents: read [`llms.txt`](https://cascivo.com/llms.txt) (install steps + component index, plain text) or use [`@cascivo/mcp`](https://github.com/cascivo/cascivo/tree/main/packages/mcp) and [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json) · MIT
28
28
 
29
- <div align="center"><a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="28" height="28" alt="cascivo"></a></div>
29
+ <div align="center"><a href="https://cascivo.com"><img src="https://cascivo.com/logo-mark-img.svg" width="28" height="28" alt="cascivo"></a></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascivo/eslint-config",
3
- "version": "0.2.4",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Flat ESLint config for apps using cascivo — reconciles the signal-based reactivity contract with eslint-plugin-react-hooks 7",
6
6
  "keywords": [
@@ -24,6 +24,7 @@
24
24
  "files": [
25
25
  "src/**/*.js",
26
26
  "src/**/*.d.ts",
27
+ "src/**/*.json",
27
28
  "!src/**/*.test.js"
28
29
  ],
29
30
  "type": "module",
@@ -32,12 +33,16 @@
32
33
  ".": {
33
34
  "types": "./src/index.d.ts",
34
35
  "default": "./src/index.js"
35
- }
36
+ },
37
+ "./oxlintrc.json": "./src/oxlintrc.json"
36
38
  },
37
39
  "publishConfig": {
38
40
  "access": "public",
39
41
  "provenance": true
40
42
  },
43
+ "dependencies": {
44
+ "@cascivo/eslint-plugin": "0.2.0"
45
+ },
41
46
  "scripts": {
42
47
  "build": "echo 'eslint-config: plain ESM, no build'",
43
48
  "test": "node --test src/index.test.js"
package/src/index.d.ts CHANGED
@@ -22,6 +22,22 @@ export interface CascadeFlatConfig {
22
22
  */
23
23
  export declare const cascivoSignals: CascadeFlatConfig
24
24
 
25
+ /**
26
+ * Enables `cascivo/prop-vocabulary` at **warn** — the rule that answers a wrong prop guess
27
+ * with the prop that exists (`<Text tone=…>` → `muted`, `gap="4"` → `gap={4}`,
28
+ * `const { theme } = useTheme()` → the tuple). Kept at `warn` deliberately: an error over a
29
+ * naming opinion gets this whole config deleted.
30
+ */
31
+ export declare const cascivoPropVocabulary: CascadeFlatConfig
32
+
33
+ /**
34
+ * Enables `cascivo/token-values` at **warn** — the rule that reports a `--cascivo-*` custom
35
+ * property that does not exist. CSS drops an unknown custom property silently, so a
36
+ * misspelled token is not an error anywhere: it simply has no effect. Kept at `warn` for the
37
+ * same reason as `cascivoPropVocabulary`.
38
+ */
39
+ export declare const cascivoTokenValues: CascadeFlatConfig
40
+
25
41
  /**
26
42
  * Scopes host stylistic rules off source vendored by `cascivo add`. Copy-paste path only.
27
43
  *
@@ -29,6 +45,6 @@ export declare const cascivoSignals: CascadeFlatConfig
29
45
  */
30
46
  export declare function cascivoVendoredSource(glob?: string): CascadeFlatConfig
31
47
 
32
- /** Both fragments. Spread last in your flat config — last-wins. */
48
+ /** Every fragment. Spread last in your flat config — last-wins. */
33
49
  declare const cascivo: CascadeFlatConfig[]
34
50
  export default cascivo
package/src/index.js CHANGED
@@ -47,10 +47,11 @@
47
47
  * Prefer the pieces individually when you only vendor source, or only use the package:
48
48
  *
49
49
  * ```js
50
- * import { cascivoSignals, cascivoVendoredSource } from '@cascivo/eslint-config'
51
- * export default [...yourConfig, cascivoSignals, cascivoVendoredSource()]
50
+ * import { cascivoSignals, cascivoPropVocabulary, cascivoTokenValues, cascivoVendoredSource } from '@cascivo/eslint-config'
51
+ * export default [...yourConfig, cascivoSignals, cascivoPropVocabulary, cascivoTokenValues, cascivoVendoredSource()]
52
52
  * ```
53
53
  */
54
+ import cascivoPlugin from '@cascivo/eslint-plugin'
54
55
 
55
56
  /**
56
57
  * Reconciles `eslint-plugin-react-hooks@7` with cascivo's signal-based reactivity.
@@ -147,7 +148,49 @@ export function cascivoVendoredSource(glob = 'src/components/ui/**') {
147
148
  }
148
149
  }
149
150
 
150
- /** Both fragments, in the order flat config wants them. Spread last. */
151
- const cascivo = [cascivoSignals, cascivoVendoredSource()]
151
+ /**
152
+ * The near-miss prop messages, at `warn`.
153
+ *
154
+ * `<Text tone="subtle">` is a correct TypeScript error whose text — "Property 'tone' does not
155
+ * exist on type 'TextProps'" — names the mistake and teaches nothing, so the adopter goes
156
+ * looking for the docs. That is the dependency the 2026-08-21 report named: "the docs are
157
+ * doing work the API should eventually do itself." Most of that work moved into the types;
158
+ * this rule carries the part TypeScript structurally cannot say. See
159
+ * `@cascivo/eslint-plugin`'s `prop-vocabulary.js` for the full rationale.
160
+ *
161
+ * **`warn`, never `error`.** A lint rule that fails somebody's build over a naming opinion
162
+ * gets the whole config deleted — and that takes `react-hooks/immutability` with it, which is
163
+ * the thing this package exists for. Raise it yourself if you want it enforced.
164
+ */
165
+ export const cascivoPropVocabulary = {
166
+ name: 'cascivo/prop-vocabulary',
167
+ plugins: { cascivo: cascivoPlugin },
168
+ rules: { 'cascivo/prop-vocabulary': 'warn' },
169
+ }
170
+
171
+ /**
172
+ * The unknown-token messages, at `warn`.
173
+ *
174
+ * `--cascivo-color-acent` is not a type error, not a build error, and not a runtime error:
175
+ * CSS drops an unknown custom property silently, so a misspelled token simply has no effect
176
+ * and the search for the cause starts in the component. React's `CSSProperties` has no index
177
+ * signature for `--*` keys either, so every custom property in a `style` prop reaches the DOM
178
+ * through a cast the adopter wrote — and a cast launders a typo by definition.
179
+ *
180
+ * This rule is the editor-time half of that gap; `CascivoTokenStyle` + `satisfies` (from
181
+ * `@cascivo/tokens/style-contract`) is the compile-time half, and `cascivo audit --ai` is the
182
+ * gate. See `@cascivo/eslint-plugin`'s `token-values.js` for the full rationale.
183
+ *
184
+ * **`warn`, never `error`**, for the same reason as `prop-vocabulary`: a rule that fails a
185
+ * build gets this config deleted, and that takes `react-hooks/immutability` with it.
186
+ */
187
+ export const cascivoTokenValues = {
188
+ name: 'cascivo/token-values',
189
+ plugins: { cascivo: cascivoPlugin },
190
+ rules: { 'cascivo/token-values': 'warn' },
191
+ }
192
+
193
+ /** Every fragment, in the order flat config wants them. Spread last. */
194
+ const cascivo = [cascivoSignals, cascivoPropVocabulary, cascivoTokenValues, cascivoVendoredSource()]
152
195
 
153
196
  export default cascivo
@@ -0,0 +1,30 @@
1
+ {
2
+ // oxlint fragment for apps that use cascivo — the oxlint half of this package.
3
+ //
4
+ // `pnpm create vite --template react-ts` scaffolds oxlint with a `.oxlintrc.json`, not
5
+ // ESLint, so the documented remedy for the signals idiom ("add @cascivo/eslint-config and
6
+ // spread it into eslint.config.js") did not apply to the most common way to start a
7
+ // project in 2026 — the adopter had no eslint.config.js to spread into and worked the rule
8
+ // id out themselves (2026-08-31 report §13).
9
+ //
10
+ // Extend it from your own config:
11
+ //
12
+ // {
13
+ // "extends": ["./node_modules/@cascivo/eslint-config/src/oxlintrc.json"],
14
+ // "categories": { "correctness": "error" }
15
+ // }
16
+ //
17
+ // Or copy the one rule below — that is all this file is.
18
+ //
19
+ // ⚠ oxlint REJECTS a config that names a rule its build does not implement
20
+ // ("Rule 'immutability' not found in plugin 'react'"), so this fragment needs an oxlint
21
+ // recent enough to ship `react/immutability`. On an older oxlint the rule does not fire in
22
+ // the first place, so you need neither the fragment nor the rule.
23
+ "rules": {
24
+ // oxlint's port of `react-hooks/immutability`. It reports every `signal.value = next` —
25
+ // cascivo's mandatory state idiom — as "This value cannot be modified". See
26
+ // docs/USING-WITH-STRICT-ESLINT.md §1 for what turning it off costs; the reasoning is
27
+ // identical to the ESLint half of this package.
28
+ "react/immutability": "off"
29
+ }
30
+ }