@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 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 added or overridden. Unsanctioned drift is flagged in CI; a genuine exception must be **declared in an allowlist** (visible, reviewed), never silent.
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
@@ -12,10 +12,10 @@ import {
12
12
  presetNotInstalledYet,
13
13
  registerAdapters,
14
14
  resolve
15
- } from "../chunk-5267A6X3.js";
15
+ } from "../chunk-R7DS7VN4.js";
16
16
  import {
17
17
  resolveContext
18
- } from "../chunk-P7NYSMLS.js";
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-5SD5CTTO.js");
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((entry) => typeof entry === "object" && entry !== null && "rule" in entry);
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");