@hublo/sentinel 1.6.0-alpha.1 → 1.6.0-alpha.2
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 +3 -2
- package/dist/bin/sentinel.js +13 -7
- package/dist/{chunk-P7NYSMLS.js → chunk-67QLOX6F.js} +2737 -28
- package/dist/{chunk-5VNYQIFD.js → chunk-EESVRILJ.js} +1 -1
- package/dist/{chunk-5VNYQIFD.js.map → chunk-EESVRILJ.js.map} +1 -1
- package/dist/{chunk-5267A6X3.js → chunk-R7DS7VN4.js} +53 -2565
- package/dist/index.js +2 -2
- package/dist/roles/test/nest/toolchain.js +1 -1
- package/dist/roles/test/react/toolchain.js +1 -1
- package/dist/roles/test/shared-test-config.js +1 -1
- package/dist/{validate-5SD5CTTO.js → validate-NP7X6XCG.js} +1 -1
- package/docs/env-adoption.md +11 -5
- package/docs/lint-adoption.md +87 -6
- package/docs/using-sentinel.md +10 -10
- package/docs/validating-a-change.md +89 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
registerAdapters,
|
|
7
7
|
resolve,
|
|
8
8
|
setDefaultRunner
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-R7DS7VN4.js";
|
|
10
10
|
import {
|
|
11
11
|
BaseAdapter
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-67QLOX6F.js";
|
|
13
13
|
import "./chunk-JRZI5IIN.js";
|
|
14
14
|
import "./chunk-7E6YTTAK.js";
|
|
15
15
|
import "./chunk-4EIY7TTR.js";
|
package/docs/env-adoption.md
CHANGED
|
@@ -160,9 +160,13 @@ repository. The migration of the monorepo onto the role is where they are revisi
|
|
|
160
160
|
`PASSWORD`, `PRIVATE_?KEY`, `ACCESS_?KEY`, `API_?KEY`), so serviceapp's `facturationPassword` and a
|
|
161
161
|
camel-case `apiKey` are seen. The scans read `.ts .tsx .mts .cts .js .jsx .mjs .cjs` (and `.svelte`,
|
|
162
162
|
`.vue` for direct reads) across the whole repository, with test files left out of the reader scan:
|
|
163
|
-
`.test.<ext>` and `.spec.<ext>` for each of those eight extensions. A value is read
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
`.test.<ext>` and `.spec.<ext>` for each of those eight extensions. A value is read from what is
|
|
164
|
+
written in the committed file: a quoted one ends at its closing quote, an unquoted one at a `#`
|
|
165
|
+
preceded by whitespace. So `API_TOKEN= # filled by the vault` and `API_TOKEN=` are blank,
|
|
166
|
+
`API_TOKEN=abc #def` is `abc`, and `API_TOKEN=abc#def` and `DATABASE_PASSWORD=#Pa55word!` are
|
|
167
|
+
filled. This deliberately differs from dotenv on a `#` with no whitespace before it: dotenv's
|
|
168
|
+
README says "Comments begin where a `#` exists", so dotenv loads `DATABASE_PASSWORD=#Pa55word!` as
|
|
169
|
+
blank, and a secret committed in clear text would go unreported by rule 6.
|
|
166
170
|
|
|
167
171
|
## In CI
|
|
168
172
|
|
|
@@ -227,9 +231,11 @@ the same single difference.
|
|
|
227
231
|
- Rule 6 reads every committed env file, not only contracts, and no contract at all is a note
|
|
228
232
|
rather than a refusal to run.
|
|
229
233
|
- Every finding has a line, so an annotation lands on it.
|
|
230
|
-
- A comment after a value is a comment
|
|
234
|
+
- A comment after a value, after whitespace, is a comment: `KEY= # note` is blank, not a committed
|
|
231
235
|
secret. And a quoted value followed by one, `KEY="" # note`, no longer opens a multi-line value
|
|
232
|
-
that hid every key after it in the file. The original read `KEY= # note` as filled.
|
|
236
|
+
that hid every key after it in the file. The original read `KEY= # note` as filled. A `#` with no
|
|
237
|
+
whitespace before it stays part of the value, as in the original and unlike dotenv:
|
|
238
|
+
`KEY=#Pa55word!` is filled (see Sentinel's defaults).
|
|
233
239
|
- Test files are left out of the reader scan for every extension it reads; the original read
|
|
234
240
|
`.ts` and `.tsx` only, and left out `.spec.ts` and `.test.ts`.
|
|
235
241
|
|
package/docs/lint-adoption.md
CHANGED
|
@@ -158,10 +158,12 @@ a **layer above the preset**, the way the planning team did:
|
|
|
158
158
|
Order matters, sentinel's preset first, or your layer cannot override anything. `--inspect`
|
|
159
159
|
reports the layer so it stays visible.
|
|
160
160
|
|
|
161
|
-
A rule set directly in `.oxlintrc.json
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
A rule can also be set directly in `.oxlintrc.json`. Since 1.5.1 a re-`init` keeps it, in your
|
|
162
|
+
order, and says so, when the preset does not name that rule; `--inspect` lists it as added by
|
|
163
|
+
the module and does not call it drift (see
|
|
164
|
+
[What `--inspect` calls drift](#what---inspect-calls-drift-and-what-it-lists-as-yours)). A rule
|
|
165
|
+
the preset does name is dropped, as before, and named: set in the stub, it would override the
|
|
166
|
+
preset and the baseline both. To change one of those for your module, a layer is the place.
|
|
165
167
|
|
|
166
168
|
Think of it as a queue rather than a fork: a rule promoted into the preset is deleted from the
|
|
167
169
|
layer. It is the exact mirror of `.oxlintrc.baseline.json`, which holds rules **below** the
|
|
@@ -233,6 +235,85 @@ Two limits, both the preset's governance:
|
|
|
233
235
|
rather than replace them. The planning layer's notes say overrides do not cross `extends`; that
|
|
234
236
|
is not what 1.77.0 does.
|
|
235
237
|
|
|
238
|
+
### What `--inspect` calls drift, and what it lists as yours
|
|
239
|
+
|
|
240
|
+
Since 1.5.1, `--inspect` (and `--status`) judge what you add to `.oxlintrc.json` (`rules`,
|
|
241
|
+
`plugins`, `jsPlugins`, `settings`, `overrides`) by the criterion a re-`init` keeps or drops it
|
|
242
|
+
by, so the two never disagree. It rests on how every
|
|
243
|
+
preset is built: each one turns every oxlint category off and names every rule it runs. A rule
|
|
244
|
+
the preset does not name is therefore off unless you turn it on, and setting it takes nothing
|
|
245
|
+
from the preset. Nobody maintains a list: "the preset names it" is read from the preset, by the
|
|
246
|
+
rule oxlint runs (so an alias counts as the rule it stands for).
|
|
247
|
+
|
|
248
|
+
**A rule the preset names is governed.** Whatever value you give it, a re-`init` drops it.
|
|
249
|
+
`--inspect` compares it with the preset:
|
|
250
|
+
|
|
251
|
+
| you set a rule the preset names... | `--inspect` |
|
|
252
|
+
| ----------------------------------------------------------------- | ---------------------------------------- |
|
|
253
|
+
| to the preset's own value and options (`deny` is `error`) | redundant: not drift, still conformant |
|
|
254
|
+
| to `off` | conflict: drift, not conformant |
|
|
255
|
+
| to `warn` where the preset says `error`, or the reverse | conflict: drift, not conformant |
|
|
256
|
+
| with other options (another `no-restricted-imports` pattern list) | conflict: drift, not conformant |
|
|
257
|
+
| under an alias (`eslint/no-var`, `typescript/no-restricted-...`) | the same as the name it stands for |
|
|
258
|
+
| stricter than the preset (`no-console: error` where it is `off`) | conflict: drift, not conformant, for now |
|
|
259
|
+
|
|
260
|
+
**A rule the preset does not name is added by the module.** A re-`init` keeps it, `--inspect`
|
|
261
|
+
does not call it drift, and lists it, with its value, so it stays visible:
|
|
262
|
+
|
|
263
|
+
| you set a rule the preset does not name... | `--inspect` |
|
|
264
|
+
| ------------------------------------------ | --------------------------------------------------------- |
|
|
265
|
+
| at any severity, with any options | added by the module: not drift, listed under `added` |
|
|
266
|
+
| to `off` | the same, listed, and the line says `off` changes nothing |
|
|
267
|
+
| in one of your `overrides` blocks | the same, listed with the block's `files` |
|
|
268
|
+
|
|
269
|
+
console, after its re-`init`:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
✓ console (react) lint — ... added=2 ... conformant=true drift=[] ...
|
|
273
|
+
added by the module (kept by --init, not drift):
|
|
274
|
+
• import/no-cycle — "error": the preset does not name this rule
|
|
275
|
+
• oxc/no-barrel-file — ["error",{"threshold":0}]: the preset does not name this rule
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`--inspect --lint --json` carries the same list as `added: [{ rule, value, files?, reason }]`.
|
|
279
|
+
|
|
280
|
+
**The other blocks follow the re-`init` exactly**: what it keeps is added by the module, listed
|
|
281
|
+
under `addedConfig` ("config added by the module" on the console); what it drops as the
|
|
282
|
+
preset's is a collision, and drift.
|
|
283
|
+
|
|
284
|
+
| you add... | `--inspect` |
|
|
285
|
+
| ------------------------------------------------------------- | ---------------------------------------- |
|
|
286
|
+
| a `plugins` entry the preset does not enable | added, listed |
|
|
287
|
+
| a `plugins` entry the preset already enables | redundant: not drift, not listed |
|
|
288
|
+
| a `jsPlugins` entry under a name the preset does not register | added, listed |
|
|
289
|
+
| a `jsPlugins` entry under a name the preset registers | collision: drift (a re-`init` drops it) |
|
|
290
|
+
| a `settings` key the preset does not set | added, listed |
|
|
291
|
+
| a `settings` key the preset sets | collision: drift (a re-`init` drops it) |
|
|
292
|
+
| a key of an `overrides` block other than `files` and `rules` | added, listed with the block's `files` |
|
|
293
|
+
| a block without `files`, or a top-level key such as `env` | drift: a re-`init` does not read it back |
|
|
294
|
+
|
|
295
|
+
host-admin at monorepo#23342 shows both sides. Its planning `jsPlugins` entry and the planning
|
|
296
|
+
rules of its override blocks are additions, kept and listed. Its top-level `rules` set 46 rules
|
|
297
|
+
the react preset names, 41 of them at another value (the TanStack Query set at `error` where the
|
|
298
|
+
preset holds `warn`, `no-explicit-any`, `no-console`, the MUI barrel bans added to
|
|
299
|
+
`no-restricted-imports`, ...), and five of its ten blocks set `no-restricted-imports` or
|
|
300
|
+
`switch-exhaustiveness-check` (six entries): conflicts, drift. A re-`init` drops all 46 top-level ones
|
|
301
|
+
and the 12 override entries the preset governs, the redundant ones included (measured, `--dry-run`). Raising what the
|
|
302
|
+
preset governs belongs in a layer above the preset, where a re-`init` keeps it.
|
|
303
|
+
|
|
304
|
+
Three details:
|
|
305
|
+
|
|
306
|
+
- **Stricter is still a conflict, for now.** Raising a rule the preset governs, even one it
|
|
307
|
+
parks `off`, is reported as drift: the preset is where that decision is made, for every
|
|
308
|
+
module, and a layer above the preset is where a team makes it for itself.
|
|
309
|
+
- **An `overrides` block** is judged the same way, rule by rule. A governed rule in it is
|
|
310
|
+
compared with the preset's override for the same `files` when the preset has one that names
|
|
311
|
+
the rule, else with the preset's top-level value; a rule the preset names only in one of its
|
|
312
|
+
own overrides, set at another scope, is a conflict.
|
|
313
|
+
- **What stays drift**: any top-level key a re-`init` does not read back (`env`, `globals`,
|
|
314
|
+
`categories`, ...), and everything a module on a preset sentinel does not ship adds, since
|
|
315
|
+
there is nothing to compare it with.
|
|
316
|
+
|
|
236
317
|
## What a preset does not enforce
|
|
237
318
|
|
|
238
319
|
Every unenforced rule carries a reason, readable with `sentinel --inspect --lint`:
|
|
@@ -290,8 +371,8 @@ things follow, and they are the point:
|
|
|
290
371
|
predates the migration. A hold is never `off`;
|
|
291
372
|
- the file is **regenerated, not accumulated**. Fix the last violation, re-run
|
|
292
373
|
`sentinel --init --lint`, and the rule drops out and returns to the preset severity;
|
|
293
|
-
- your own config stays `extends` + `ignorePatterns`, so a rule **you** change by hand
|
|
294
|
-
still reported as drift and is never confused with a hold sentinel made;
|
|
374
|
+
- your own config stays `extends` + `ignorePatterns`, so a preset rule **you** change by hand
|
|
375
|
+
is still reported as drift and is never confused with a hold sentinel made;
|
|
295
376
|
- `--init` says what it held and how many violations each hold covers, so the debt is
|
|
296
377
|
announced rather than discovered;
|
|
297
378
|
- a hold is written under the **preset's** name for the rule (since 1.5.1). Oxlint reports
|
package/docs/using-sentinel.md
CHANGED
|
@@ -23,16 +23,16 @@ sentinel --run # no target -> every wired tar
|
|
|
23
23
|
Read it by target, since that is what you pick first. `--report` and `--status` are deprecated
|
|
24
24
|
everywhere (`--run --json` and `--inspect` answer them), and `--migrate` is refused everywhere.
|
|
25
25
|
|
|
26
|
-
| Target | `--init` writes | `--run` does | `--inspect` shows
|
|
27
|
-
| ------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
-
| `--lint` | stub + scripts + nx metadata, removes the ESLint config and the module's ESLint deps, then autofixes once | lints; `--fix` autofixes in the same pass | rule count, what is disabled or downgraded and **why**, drift
|
|
29
|
-
| `--format` | materializes the preset + scripts + nx metadata, removes the Prettier config and deps, then formats once | **checks**; `--fix` writes | effective options, every departure from the standard and why
|
|
30
|
-
| `--typescript` | writes/extends the tsconfig + `typecheck` script | typechecks | resolved options, what is deferred, drift
|
|
31
|
-
| `--build` | points the module's Vite config at sentinel's toolchain + scripts + nx metadata | builds | runner, config file, whose Vite, how many overrides, adoption
|
|
32
|
-
| `--dev` | adopts the BUILD too: one plan writes both `build` and `serve` | serves; long-running, so never swept by an unqualified `--run` | refuses, and sends you to `--inspect --build`: it is that config
|
|
33
|
-
| `--test` | the Vitest config + scripts + nx metadata, and migrates every spec file | runs Vitest | runner, which configs were found, adoption state, drift
|
|
34
|
-
| `--static-analysis` | the config stub + three scripts + nx metadata, and ignores the report directory at the repository root | measures and reports; never exits non-zero on a finding | runner, config file, resolved settings, what this module moved
|
|
35
|
-
| `--env` | refuses: it writes no config (an optional `env.config.mjs` at the repository root declares exceptions) | checks the whole REPOSITORY, from its git root only; exits 1 on a blocking finding at `SENTINEL_ENV_LEVEL=error`; an invalid level refuses the whole run, a bare root `--run` included | refuses: nothing to inspect
|
|
26
|
+
| Target | `--init` writes | `--run` does | `--inspect` shows |
|
|
27
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
28
|
+
| `--lint` | stub + scripts + nx metadata, removes the ESLint config and the module's ESLint deps, then autofixes once | lints; `--fix` autofixes in the same pass | rule count, what is disabled or downgraded and **why**, what the module adds, drift |
|
|
29
|
+
| `--format` | materializes the preset + scripts + nx metadata, removes the Prettier config and deps, then formats once | **checks**; `--fix` writes | effective options, every departure from the standard and why |
|
|
30
|
+
| `--typescript` | writes/extends the tsconfig + `typecheck` script | typechecks | resolved options, what is deferred, drift |
|
|
31
|
+
| `--build` | points the module's Vite config at sentinel's toolchain + scripts + nx metadata | builds | runner, config file, whose Vite, how many overrides, adoption |
|
|
32
|
+
| `--dev` | adopts the BUILD too: one plan writes both `build` and `serve` | serves; long-running, so never swept by an unqualified `--run` | refuses, and sends you to `--inspect --build`: it is that config |
|
|
33
|
+
| `--test` | the Vitest config + scripts + nx metadata, and migrates every spec file | runs Vitest | runner, which configs were found, adoption state, drift |
|
|
34
|
+
| `--static-analysis` | the config stub + three scripts + nx metadata, and ignores the report directory at the repository root | measures and reports; never exits non-zero on a finding | runner, config file, resolved settings, what this module moved |
|
|
35
|
+
| `--env` | refuses: it writes no config (an optional `env.config.mjs` at the repository root declares exceptions) | checks the whole REPOSITORY, from its git root only; exits 1 on a blocking finding at `SENTINEL_ENV_LEVEL=error`; an invalid level refuses the whole run, a bare root `--run` included | refuses: nothing to inspect |
|
|
36
36
|
|
|
37
37
|
`--json` works for every verb, and stdout carries **only** the envelope, so `| jq` always
|
|
38
38
|
parses. `--dry-run` applies to `--init` and writes nothing. Besides the config diffs, it says
|
|
@@ -141,10 +141,10 @@ Every cell is a test in `tests/e2e/env.e2e.test.ts`, against the built CLI, on g
|
|
|
141
141
|
serviceapp-shaped repository (not nx, committed `variables/*.env`), the same with a package below
|
|
142
142
|
its root, an nx workspace with a module, and a directory in no repository. `SENTINEL_ENV_LEVEL` and
|
|
143
143
|
`GITHUB_ACTIONS` are pinned on every call, and "unset" removes the variable from the child's
|
|
144
|
-
environment, which is a different input from the empty string.
|
|
145
|
-
one more refused verb, 19 new ones, the rule 1 note,
|
|
144
|
+
environment, which is a different input from the empty string. 58 cells: the 31 of the first draft,
|
|
145
|
+
one more refused verb, 19 new ones, the rule 1 note, the 5 of the first adopter's feedback
|
|
146
146
|
(a refused config's row, in console and `--json`; test files of every extension; a comment after a
|
|
147
|
-
value; the summary annotation past GitHub's cap)
|
|
147
|
+
value; the summary annotation past GitHub's cap), and a secret whose value starts with `#`.
|
|
148
148
|
|
|
149
149
|
### verb, from the repository root
|
|
150
150
|
|
|
@@ -205,6 +205,7 @@ fails nothing would be decoration; none is, and every new cell fails under at le
|
|
|
205
205
|
| the rule 1 note, always emitted (unit + e2e) | 2 |
|
|
206
206
|
| test files of every extension (suffixes reverted) | 2 |
|
|
207
207
|
| a comment after a value (parser reverted) | 5 |
|
|
208
|
+
| a `#` with no whitespace before it (dotenv's rule) | 4 |
|
|
208
209
|
| the refusal's `error` on the row (adapter reverted) | 2 |
|
|
209
210
|
| no `undefined` key on the row (orchestrate reverted) | 1 |
|
|
210
211
|
| a refusal names the kind found (define reverted) | 4 |
|
|
@@ -214,6 +215,9 @@ The `COPY` fix is unit (`env-checks-fixes`): reverted, its 3 tests fail and the
|
|
|
214
215
|
The six feedback controls ran unit and e2e together over the six env suites (187 tests, 193 for
|
|
215
216
|
the last one, once the summary cells existed): each failed only its own new cells, and no cell that existed before. The two
|
|
216
217
|
summary-annotation guards (nothing at exactly 10, nothing at `info`) pass reverted, as guards do.
|
|
218
|
+
The `#` control restored dotenv's rule (an unquoted value ends at its first `#`) over the six env
|
|
219
|
+
suites, 203 tests: its 4 new cells fail, 199 pass. One existing cell changed, on purpose: it
|
|
220
|
+
asserted dotenv's reading of `B_TOKEN=#c` as blank, which is the reading this rule refuses.
|
|
217
221
|
|
|
218
222
|
### Against real repositories, from the packed tarball
|
|
219
223
|
|
|
@@ -251,7 +255,7 @@ Rule 8 against a real nx ran on the monorepo only (nx installed in a throwaway w
|
|
|
251
255
|
|
|
252
256
|
## The `--init` matrix for 1.5.1, 29 October 2026
|
|
253
257
|
|
|
254
|
-
Six fixes, then a seventh (below) found by the alpha.1 validation. Found by re-initializing the monorepo's 63 adopted modules with 1.5.1-alpha.0. Every
|
|
258
|
+
Six fixes, then a seventh (below) found by the alpha.1 validation and an eighth found by the alpha.2 one. Found by re-initializing the monorepo's 63 adopted modules with 1.5.1-alpha.0. Every
|
|
255
259
|
cell below is a test in this repo, against the built CLI unless it says unit, and every fix has a
|
|
256
260
|
negative control: the fix reverted in the source, the cells run again, and the cells that must
|
|
257
261
|
fail do. No existing cell changed: against the alpha, the test tree gains lines and loses none
|
|
@@ -395,6 +399,87 @@ Checked in the monorepo at 7177eb86038: none of the 66 committed `.oxlintrc*.jso
|
|
|
395
399
|
team layers spells a governed rule under another name, so no adopted module carries the gap
|
|
396
400
|
today.
|
|
397
401
|
|
|
402
|
+
### 8. `--inspect` judges a module's own rules as a re-init does (`inspect-lint-module-additions`, unit `lint-module-rule-standing`)
|
|
403
|
+
|
|
404
|
+
Found by the alpha.2 sweep: `--init` kept console's `import/no-cycle` and `oxc/no-barrel-file`
|
|
405
|
+
("kept 2 rule(s)"), and `--inspect` reported console's lint `status: failed, conformant: false,
|
|
406
|
+
drift: ["rules"]`, because any `rules` key was drift. The criterion is now the re-init's
|
|
407
|
+
(`governedRules`, by `canonicalRuleName`): it holds because every preset turns every oxlint
|
|
408
|
+
category off and names every rule it runs, checked first on all six shipped presets against
|
|
409
|
+
oxlint 1.77.0's seven categories (a unit cell), and on the binary: `no-const-assign`, a
|
|
410
|
+
correctness rule react does not name, fires under bare oxlint and not under console's stub.
|
|
411
|
+
|
|
412
|
+
| the module's `.oxlintrc.json` sets, react preset | `conformant`, `drift` | listed in `added` |
|
|
413
|
+
| ---------------------------------------------------------------------------------- | ---------------------------- | ---------------------- |
|
|
414
|
+
| console's two rules, which the preset does not name | true, `[]` | both, with values |
|
|
415
|
+
| an unnamed rule at `off` | true, `[]` | yes, "changes nothing" |
|
|
416
|
+
| an unnamed rule in an `overrides` block | true, `[]` | yes, with `files` |
|
|
417
|
+
| `no-var` at the preset's `error` (unit: also `deny`, `["error"]`, `eslint/no-var`) | true, `[]` | no |
|
|
418
|
+
| unit: `no-restricted-imports` at the preset's options | true, `[]` | no |
|
|
419
|
+
| `no-var` at `off`, at `warn` | false, `["rules"]` | no |
|
|
420
|
+
| `no-restricted-imports` with other options (unit: also as `typescript/...`) | false, `["rules"]` | no |
|
|
421
|
+
| `eslint/no-var: off` | false, `["rules"]` | no |
|
|
422
|
+
| `no-console: error`, stricter than the preset's `off` (a conflict for now) | false, `["rules"]` | no |
|
|
423
|
+
| unit: a rule the preset names only in its test override, set at the top level | false, `["rules"]` | no |
|
|
424
|
+
| the same rows inside an `overrides` block (unit; e2e: `no-var: off`) | the same, `["overrides"]` | the same |
|
|
425
|
+
| unit: the preset override's rule at its own value, for its own `files` | true, `[]` | no |
|
|
426
|
+
| unit: rules under a preset sentinel does not ship | drift `["rules"]`, as before | n/a |
|
|
427
|
+
| `--status`, console's two rules | `1/1 conformant` | |
|
|
428
|
+
| re-init of console's shape, then `--inspect` | kept 2, then true, `[]` | both |
|
|
429
|
+
|
|
430
|
+
Negative control, the source reverted (`git stash` of `src/`, new tests kept, rebuilt): 27 of
|
|
431
|
+
the 47 new cells fail, every cell that expects "not drift" or the `added` list. The 20 that pass
|
|
432
|
+
are the conflict cells, which were drift before too, the category check, the unshipped preset
|
|
433
|
+
and the block carrying `env`. No existing cell changed: `lint-adoption-read`,
|
|
434
|
+
`adoption-contract` and `lint.e2e` set `no-debugger: off` and `no-console: off` on nest, both
|
|
435
|
+
named there at another value, so they are conflicts and still drift.
|
|
436
|
+
|
|
437
|
+
On the monorepo, `--inspect --json` from each of the 63 modules of the alpha.2 sweep worktree,
|
|
438
|
+
with this branch's built CLI, nothing written (`git status` hash unchanged): console's lint row
|
|
439
|
+
goes `failed` to `ok`, `conformant` true, `drift` `[]`, its two rules listed, and the workspace
|
|
440
|
+
coverage footer of console's own run reads 4 of 4 adopted roles conformant instead of 3. The 62 other modules differ from the
|
|
441
|
+
alpha.2 run only by an empty `added: []` on their lint row.
|
|
442
|
+
|
|
443
|
+
**The other blocks a re-init reads back**, the same criterion, from `moduleOwnBlocks` itself (no
|
|
444
|
+
second definition): what it keeps is an addition, listed under `addedConfig`; what it drops as
|
|
445
|
+
the preset's is a collision, and drift. Found on host-admin at monorepo#23342, whose planning
|
|
446
|
+
`jsPlugins` entry a re-init keeps and `--inspect` called drift.
|
|
447
|
+
|
|
448
|
+
| the module's `.oxlintrc.json` adds, react preset | `conformant`, `drift` | listed in `addedConfig` |
|
|
449
|
+
| ------------------------------------------------------------------------------ | ---------------------- | ------------------------------------- |
|
|
450
|
+
| host-admin's planning jsPlugin (a path) and a named one | true, `[]` | yes |
|
|
451
|
+
| a `plugins` entry the preset does not enable | true, `[]` | yes |
|
|
452
|
+
| `plugins: ["import"]`, already enabled | true, `[]` | no |
|
|
453
|
+
| a `settings` key the preset does not set | true, `[]` | yes |
|
|
454
|
+
| an override block key beyond `files` and `rules` (`env`) | true, `[]` | yes, with `files` |
|
|
455
|
+
| a jsPlugin under a name the preset registers (`nx`), or the preset's own path | false, `["jsPlugins"]` | no |
|
|
456
|
+
| unit: a `settings` key the preset sets (synthetic preset: none ships settings) | drift `["settings"]` | no |
|
|
457
|
+
| unit: `plugins` not a list of names, `settings` not an object | drift | n/a |
|
|
458
|
+
| unit: an override block without `files`; a top-level `env` or `categories` | drift | n/a |
|
|
459
|
+
| an addition at `off` in an override block | true, `[]` | in `added`, without "changes nothing" |
|
|
460
|
+
|
|
461
|
+
host-admin's committed config at #23342, in a fixture copy with its planning plugin, before and
|
|
462
|
+
after this change: `drift: ["jsPlugins", "rules", "overrides"]` becomes `["rules", "overrides"]`,
|
|
463
|
+
with 18 rule additions and the jsPlugin listed. What remains is real: its top-level `rules` set
|
|
464
|
+
46 rules the react preset names, 41 at another value (the TanStack Query set at `error`, the
|
|
465
|
+
`no-unsafe-*` set, `no-explicit-any`, `no-console`, `no-restricted-imports` with the MUI barrel
|
|
466
|
+
bans, ...), and 5 of its 10 blocks set `no-restricted-imports` or
|
|
467
|
+
`switch-exhaustiveness-check` (6 entries). A re-init's `--dry-run` on the same copy drops those
|
|
468
|
+
46 rules and 12 governed override entries and keeps the jsPlugin and 4 blocks.
|
|
469
|
+
|
|
470
|
+
Negative control for this part, the source at 3060996 (`git stash` of `src/`, rebuilt): 15 of
|
|
471
|
+
the 64 cells fail, the 12 new ones that expect "not drift" or an `addedConfig` list, and the
|
|
472
|
+
three existing cells of 3060996 whose expectation this changes. The 49 that pass include the
|
|
473
|
+
collision cells and the unread shapes, drift before too. Four cells of 3060996 changed, all in
|
|
474
|
+
this PR's own new files and all asserting what this part reverses: the override block with `env`
|
|
475
|
+
(drift then, an addition now), the `settings: { team }` cell (replaced by `env` and `categories`,
|
|
476
|
+
which a re-init does not read back), and the two `readModuleAdditions` cells (it now returns
|
|
477
|
+
`{ rules, config }`).
|
|
478
|
+
|
|
479
|
+
The 63-module inspect, re-run with this build: identical to the run above for every module,
|
|
480
|
+
console included, except an empty `addedConfig: []` on each lint row; `git status` hash
|
|
481
|
+
unchanged, 63 of 63 exit 0.
|
|
482
|
+
|
|
398
483
|
### against the consumer, the 63 adopted modules
|
|
399
484
|
|
|
400
485
|
The packed branch, through a pnpm `file:` override, on a fresh worktree of the monorepo at
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hublo/sentinel",
|
|
3
|
-
"version": "1.6.0-alpha.
|
|
3
|
+
"version": "1.6.0-alpha.2",
|
|
4
4
|
"description": "One CLI that guards code health across Hublo repos: shared lint/typescript/build/test presets, static & dynamic analysis, and architecture checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|