@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/README.md
CHANGED
|
@@ -254,7 +254,7 @@ The rules live in `sentinel`. Each module keeps a **thin, generated stub** per t
|
|
|
254
254
|
|
|
255
255
|
- **Rules in sentinel** — one source of truth, versioned.
|
|
256
256
|
- **Thin stubs per module** — the stub is what keeps the **editor working** (VS Code discovers config by file, real-time lint/type/format stay live) and what **nx** uses to infer targets. Stubs are **generated by `sentinel --init`**, never hand-written; swapping a runner regenerates them.
|
|
257
|
-
- **Drift guard** — sentinel validates that each stub is _only_ the sanctioned `extends`, with nothing
|
|
257
|
+
- **Drift guard** — sentinel validates that each stub is _only_ the sanctioned `extends`, with nothing of the preset's overridden. Unsanctioned drift is flagged in CI; a genuine exception must be **declared in an allowlist** (visible, reviewed), never silent. One addition is sanctioned, in lint: what the preset does not govern (a rule it does not name, a plugin, jsPlugin or setting it does not set) is the module's own, kept by `--init`, not drift, and listed by `--inspect`; a rule the preset names, set to another value, or an entry that collides with the preset's, is drift ([lint-adoption.md](docs/lint-adoption.md#what---inspect-calls-drift-and-what-it-lists-as-yours)).
|
|
258
258
|
- **Per-module install** — `@hublo/sentinel` is added per module, so adoption is **gradual** (migrate lot by lot; a module can adopt sentinel while its neighbour still uses the old config). Root configs are removed only once the **last** module has migrated.
|
|
259
259
|
- **Runner binaries** (`eslint`, `typescript`, `vite`, `vitest`, …) are **resolved from the adopting module** at run time (sentinel looks for the tool in the module, then falls back to `PATH`), so the editor and nx keep using the exact binary the project already installs. sentinel does **not** declare them as dependencies today, so it does not pin their versions: the module still owns its own `typescript`. Having sentinel dictate those versions (as peer dependencies, so the whole toolchain rides the sentinel version) is the intended end state, and it lands with the tool tickets that actually bundle a runner.
|
|
260
260
|
|
|
@@ -467,7 +467,8 @@ preset guessing): for each module it reads the committed `tsconfig` `extends` ch
|
|
|
467
467
|
reports whether it is **adopted** (extends a sentinel preset), which preset, and whether
|
|
468
468
|
it is **conformant** (drift-free, a re-`update` would change nothing), plus a coverage
|
|
469
469
|
footer. This is the **drift guard** as a command, `--status --ci` exits non-zero when an
|
|
470
|
-
adopted module has drifted.
|
|
470
|
+
adopted module has drifted. For lint, what a module adds that its preset does not govern is not
|
|
471
|
+
drift; a rule the preset names, set differently (stricter included, for now), is.
|
|
471
472
|
|
|
472
473
|
```
|
|
473
474
|
✓ host-admin (react) typescript — adopted (react) conformant
|
package/dist/bin/sentinel.js
CHANGED
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
presetNotInstalledYet,
|
|
13
13
|
registerAdapters,
|
|
14
14
|
resolve
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-R7DS7VN4.js";
|
|
16
16
|
import {
|
|
17
17
|
resolveContext
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-67QLOX6F.js";
|
|
19
19
|
import {
|
|
20
20
|
ensureWorkspacePrep,
|
|
21
21
|
findWorkspaceRoot,
|
|
@@ -584,7 +584,7 @@ async function runValidate(ctx) {
|
|
|
584
584
|
);
|
|
585
585
|
}
|
|
586
586
|
if (!ctx.targets.includes("test")) return 1;
|
|
587
|
-
const { validateModuleTests } = await import("../validate-
|
|
587
|
+
const { validateModuleTests } = await import("../validate-NP7X6XCG.js");
|
|
588
588
|
const outcomes = modules.flatMap(
|
|
589
589
|
(module) => validateModuleTests(module.name, module.root)
|
|
590
590
|
);
|
|
@@ -616,7 +616,9 @@ var HEAD_KEYS = /* @__PURE__ */ new Set([
|
|
|
616
616
|
"diagnosticsTruncated"
|
|
617
617
|
]);
|
|
618
618
|
function isRuleList(value) {
|
|
619
|
-
return Array.isArray(value) && value.every(
|
|
619
|
+
return Array.isArray(value) && value.every(
|
|
620
|
+
(entry) => typeof entry === "object" && entry !== null && ("rule" in entry || "entry" in entry)
|
|
621
|
+
);
|
|
620
622
|
}
|
|
621
623
|
var RULE_BLOCKS = [
|
|
622
624
|
{ key: "deferred", label: "deferred (phase 1, non-breaking):" },
|
|
@@ -630,7 +632,11 @@ var RULE_BLOCKS = [
|
|
|
630
632
|
// adopted module can be missing a check nobody in it ever chose to drop. Reduced coverage
|
|
631
633
|
// has to be readable, or the difference between an accepted cost and a regression is only
|
|
632
634
|
// that nobody looked.
|
|
633
|
-
{ key: "unenforced", label: "not checked at all:" }
|
|
635
|
+
{ key: "unenforced", label: "not checked at all:" },
|
|
636
|
+
// The other direction, and listed for the same reason: a rule a module adds to its lint
|
|
637
|
+
// preset is not drift, so nothing else on the row would ever show it was there.
|
|
638
|
+
{ key: "added", label: "added by the module (kept by --init, not drift):" },
|
|
639
|
+
{ key: "addedConfig", label: "config added by the module (kept by --init, not drift):" }
|
|
634
640
|
];
|
|
635
641
|
var MAX_INLINE_WIDTH = 60;
|
|
636
642
|
function renderValue(key, value, p) {
|
|
@@ -674,9 +680,9 @@ function renderSummary(item, p) {
|
|
|
674
680
|
for (const { label, rules } of blocks) {
|
|
675
681
|
if (rules.length === 0) continue;
|
|
676
682
|
lines.push(` ${p.warn(label)}`);
|
|
677
|
-
for (const { rule, phase, reason } of rules) {
|
|
683
|
+
for (const { rule, entry, phase, reason } of rules) {
|
|
678
684
|
const detail = phase === void 0 ? reason : `phase ${phase}: ${reason}`;
|
|
679
|
-
lines.push(` ${p.warn("\u2022")} ${p.strong(rule)} ${p.dim(`\u2014 ${detail}`)}`);
|
|
685
|
+
lines.push(` ${p.warn("\u2022")} ${p.strong(rule ?? entry ?? "?")} ${p.dim(`\u2014 ${detail}`)}`);
|
|
680
686
|
}
|
|
681
687
|
}
|
|
682
688
|
return lines.join("\n");
|