@hublo/sentinel 1.4.0-alpha.35 → 1.4.0-alpha.37

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.
@@ -15,10 +15,10 @@ import {
15
15
  palette,
16
16
  registerAdapters,
17
17
  resolve
18
- } from "../chunk-ZMUTKBZ2.js";
18
+ } from "../chunk-2N5D63HC.js";
19
19
  import {
20
20
  resolveContext
21
- } from "../chunk-OORAEYSU.js";
21
+ } from "../chunk-YMSI5ZCB.js";
22
22
  import "../chunk-O7REVMOC.js";
23
23
  import "../chunk-QXFCZON7.js";
24
24
  import {
@@ -145,7 +145,7 @@ async function runValidate(ctx) {
145
145
  );
146
146
  }
147
147
  if (!ctx.targets.includes("test")) return 1;
148
- const { validateModuleTests } = await import("../validate-2RTPM5EB.js");
148
+ const { validateModuleTests } = await import("../validate-MTAEHEMX.js");
149
149
  const outcomes = modules.flatMap(
150
150
  (module) => validateModuleTests(module.name, module.root)
151
151
  );
@@ -1,9 +1,15 @@
1
1
  import {
2
2
  ALWAYS_LOCAL_KEYS,
3
3
  BaseAdapter,
4
+ ESLINT_CONFIG_FILES,
4
5
  FORMAT_CONFIG_FILE,
5
6
  FORMAT_DEFAULT_IGNORES,
6
7
  FORMAT_SCRIPT_NAME,
8
+ LINT_BASELINE_FILE,
9
+ LINT_BASELINE_SPECIFIER,
10
+ LINT_CONFIG_FILE,
11
+ LINT_MEASURE_FILE,
12
+ LINT_SCRIPT_NAME,
7
13
  PERMITTED_LOCAL_KEYS,
8
14
  PRETTIER_CONFIG_FILES,
9
15
  PROVENANCE_KEY,
@@ -11,22 +17,43 @@ import {
11
17
  adoptedPackageName,
12
18
  binFromOwnInstall,
13
19
  binSearchPath,
20
+ canRunTypeAware,
21
+ describeHolds,
22
+ extendsWithBaseline,
23
+ extendsWithPreset,
14
24
  formatPresetFor,
15
25
  formatPresetName,
16
26
  formatTargets,
27
+ heldRules,
28
+ holdsFrom,
29
+ isSentinelPreset,
30
+ lintTarget,
31
+ localOnlyKeys,
17
32
  manifestOperation,
18
33
  moduleScripts,
19
34
  nxTargetOperations,
20
35
  oxfmtRejects,
36
+ oxlintPath,
37
+ oxlintSearchPath,
38
+ presetNameFromPath,
39
+ presetOfVariant,
40
+ presetOwnedKeys,
41
+ presetPath,
42
+ presetVariant,
21
43
  projectTargets,
44
+ readAdoption,
22
45
  readFormatAdoption,
46
+ readLintAdoption,
47
+ renderBaseline,
23
48
  resolveBin,
49
+ resolveConfigTarget,
24
50
  resolveOxfmt,
51
+ resolveOxlint,
25
52
  rewriteToolchainImports,
26
53
  selfCommand,
27
54
  splitToolArgs,
28
55
  walk
29
- } from "./chunk-OORAEYSU.js";
56
+ } from "./chunk-YMSI5ZCB.js";
30
57
  import {
31
58
  parseJsonc
32
59
  } from "./chunk-QXFCZON7.js";
@@ -1897,8 +1924,8 @@ function registerFormat() {
1897
1924
 
1898
1925
  // src/roles/lint/adapters/oxlint/oxlint.adapter.ts
1899
1926
  import { spawnSync as spawnSync4 } from "node:child_process";
1900
- import { existsSync as existsSync16, readFileSync as readFileSync16, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
1901
- import { join as join20 } from "node:path";
1927
+ import { existsSync as existsSync12, readFileSync as readFileSync13, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
1928
+ import { join as join16 } from "node:path";
1902
1929
 
1903
1930
  // src/core/config/deferred-rules.ts
1904
1931
  function deferredRuleNames(rules) {
@@ -1957,104 +1984,6 @@ function describeFixOutcome(outcome, toolLabel) {
1957
1984
  return `the ${toolLabel} autofix rewrote ${outcome.changed.length} file${outcome.changed.length === 1 ? "" : "s"}: ${listed}. Review the diff before committing: rules this module used to have switched off are enforced from now on.`;
1958
1985
  }
1959
1986
 
1960
- // src/roles/lint/module-baseline.ts
1961
- import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
1962
- import { join as join12 } from "node:path";
1963
- var LINT_BASELINE_FILE = ".oxlintrc.baseline.json";
1964
- var LINT_MEASURE_FILE = ".oxlintrc.measure.json";
1965
- var LINT_BASELINE_SPECIFIER = `./${LINT_BASELINE_FILE}`;
1966
- function holdsFrom(errorCounts) {
1967
- return [...errorCounts].map(([rule, count]) => ({ rule, count })).sort((left, right) => right.count - left.count || left.rule.localeCompare(right.rule));
1968
- }
1969
- function renderBaseline(holds, version) {
1970
- const entries = holds.map(({ rule }) => ` ${JSON.stringify(rule)}: "warn"`).join(",\n");
1971
- return [
1972
- "{",
1973
- ` // Written by @hublo/sentinel@${version}. Do not edit by hand: \`sentinel --init --lint\``,
1974
- " // regenerates it from a fresh measurement, and a rule you have since fixed drops out",
1975
- " // and returns to `error` on its own.",
1976
- " //",
1977
- " // These rules are held at `warn` because this module ALREADY violated them when it",
1978
- " // adopted. They still run and still report, so the build cannot fail on them.",
1979
- " //",
1980
- " // The hold is per RULE, not per occurrence: oxlint cannot freeze a specific list of",
1981
- " // violations, so a NEW violation of one of these rules is covered too, and will only",
1982
- " // warn. That is the cost of adopting without a red build, and the reason to clear this",
1983
- " // file rather than live with it.",
1984
- " //",
1985
- " // `sentinel --inspect --lint` lists what is held; `sentinel --run --lint --json` counts",
1986
- " // what is left, per rule. Fix them and re-run `--init --lint` to get the severity back.",
1987
- ' "rules": {',
1988
- entries,
1989
- " }",
1990
- "}",
1991
- ""
1992
- ].join("\n");
1993
- }
1994
- function extendsWithBaseline(current, hasHolds) {
1995
- const withoutBaseline = current.filter((entry) => entry !== LINT_BASELINE_SPECIFIER);
1996
- return hasHolds ? [...withoutBaseline, LINT_BASELINE_SPECIFIER] : withoutBaseline;
1997
- }
1998
- function describeHolds(holds) {
1999
- if (holds.length === 0) return "";
2000
- const total = holds.reduce((sum, hold) => sum + hold.count, 0);
2001
- const listed = holds.slice(0, 5).map(({ rule, count }) => `${rule} (${count})`).join(", ");
2002
- const rest = holds.length > 5 ? `, and ${holds.length - 5} more` : "";
2003
- return `held ${holds.length} rule(s) at \`warn\` for this module, covering ${total} violation(s) that were already there: ${listed}${rest}. They are written to ${LINT_BASELINE_FILE}, they still report, and they return to \`error\` once fixed and re-initialized`;
2004
- }
2005
- function heldRules(cwd) {
2006
- const path = join12(cwd, LINT_BASELINE_FILE);
2007
- if (!existsSync9(path)) return [];
2008
- try {
2009
- const parsed = parseJsonc(
2010
- readFileSync9(path, "utf8"),
2011
- LINT_BASELINE_FILE
2012
- );
2013
- return Object.keys(parsed.rules ?? {});
2014
- } catch {
2015
- return [];
2016
- }
2017
- }
2018
-
2019
- // src/roles/lint/config-policy.ts
2020
- var LINT_CONFIG_FILE = ".oxlintrc.json";
2021
- var LINT_SCRIPT_NAME = "lint";
2022
- var PRESET_DIR = "./node_modules/@hublo/sentinel/lint";
2023
- function presetPath(preset) {
2024
- return `${PRESET_DIR}/${preset}.json`;
2025
- }
2026
- function isSentinelPreset(entry) {
2027
- return /@hublo\/sentinel\/(lint|oxlint)\//.test(entry);
2028
- }
2029
- function extendsWithPreset(current, variant) {
2030
- const own = presetPath(variant);
2031
- const others = [...new Set(current.filter((entry) => entry !== own && !isSentinelPreset(entry)))];
2032
- const baseline = others.filter((entry) => entry === LINT_BASELINE_SPECIFIER);
2033
- const rest = others.filter((entry) => entry !== LINT_BASELINE_SPECIFIER);
2034
- return [own, ...rest, ...baseline];
2035
- }
2036
- function presetVariant(preset, cwd) {
2037
- const normalised = cwd.replaceAll("\\", "/");
2038
- return preset === "react" && /(^|\/)libs\//.test(normalised) ? "react-lib" : preset;
2039
- }
2040
- function presetOfVariant(variant) {
2041
- return variant === "react-lib" ? "react" : variant;
2042
- }
2043
- var SENTINEL_LINT_PRESET = /@hublo\/sentinel\/(?:lint|oxlint)\/([a-z-]+)\.json$/;
2044
- function presetNameFromPath(preset) {
2045
- return preset ? SENTINEL_LINT_PRESET.exec(preset)?.[1] ?? void 0 : void 0;
2046
- }
2047
- var PERMITTED_LOCAL_KEYS2 = ["extends", "ignorePatterns"];
2048
- var ESLINT_CONFIG_FILES = [
2049
- "eslint.config.js",
2050
- "eslint.config.mjs",
2051
- "eslint.config.cjs",
2052
- "eslint.config.ts"
2053
- ];
2054
- function lintTarget() {
2055
- return { cache: true, inputs: ["default", "^default", `{projectRoot}/${LINT_CONFIG_FILE}`] };
2056
- }
2057
-
2058
1987
  // src/roles/lint/presets/nest.json
2059
1988
  var nest_default = {
2060
1989
  plugins: ["typescript", "jest", "import", "unicorn", "oxc", "node"],
@@ -3833,14 +3762,14 @@ function downgradedRulesFor(preset) {
3833
3762
  }
3834
3763
 
3835
3764
  // src/roles/lint/extra-layers.ts
3836
- import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
3837
- import { isAbsolute, join as join13, resolve as resolve2 } from "node:path";
3765
+ import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
3766
+ import { isAbsolute, join as join12, resolve as resolve2 } from "node:path";
3838
3767
  function ruleCount(cwd, specifier) {
3839
3768
  const path = isAbsolute(specifier) ? specifier : resolve2(cwd, specifier);
3840
- if (!existsSync10(path)) return void 0;
3769
+ if (!existsSync9(path)) return void 0;
3841
3770
  try {
3842
3771
  const parsed = parseJsonc(
3843
- readFileSync10(path, "utf8"),
3772
+ readFileSync9(path, "utf8"),
3844
3773
  specifier
3845
3774
  );
3846
3775
  return Object.keys(parsed.rules ?? {}).length;
@@ -3860,7 +3789,7 @@ function extraLayers(cwd, extendsList) {
3860
3789
  function committedExtendsList(cwd, configFile) {
3861
3790
  try {
3862
3791
  const parsed = parseJsonc(
3863
- readFileSync10(join13(cwd, configFile), "utf8"),
3792
+ readFileSync9(join12(cwd, configFile), "utf8"),
3864
3793
  configFile
3865
3794
  );
3866
3795
  return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
@@ -3918,166 +3847,13 @@ function errorCountsByConfigRule(stdout) {
3918
3847
  return counts;
3919
3848
  }
3920
3849
 
3921
- // src/core/config/read-adoption.ts
3922
- import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
3923
- import { join as join15 } from "node:path";
3924
-
3925
- // src/core/config/owned-keys.ts
3926
- function presetOwnedKeys(config, permitted, presetSets) {
3927
- if (!config) return [];
3928
- return Object.keys(config).filter(
3929
- (key) => !permitted.includes(key) && (presetSets === void 0 || presetSets.includes(key))
3930
- );
3931
- }
3932
- function localOnlyKeys(config, permitted, presetSets) {
3933
- if (!config) return [];
3934
- return Object.keys(config).filter((key) => !permitted.includes(key) && !presetSets.includes(key));
3935
- }
3936
-
3937
- // src/core/config/resolve-config-target.ts
3938
- import { existsSync as existsSync11, readFileSync as readFileSync11 } from "node:fs";
3939
- import { join as join14 } from "node:path";
3940
- function readExtends(absolutePath) {
3941
- let parsed;
3942
- try {
3943
- parsed = parseJsonc(readFileSync11(absolutePath, "utf8"), absolutePath);
3944
- } catch {
3945
- return [];
3946
- }
3947
- if (typeof parsed.extends === "string") return [parsed.extends];
3948
- if (Array.isArray(parsed.extends)) {
3949
- return parsed.extends.filter((entry) => typeof entry === "string");
3950
- }
3951
- return [];
3952
- }
3953
- function resolveConfigTarget(moduleDir, { candidates, markers, fallback }) {
3954
- let existing;
3955
- let existingExtendsSomething = false;
3956
- for (const candidate of candidates) {
3957
- const absolutePath = join14(moduleDir, candidate);
3958
- if (!existsSync11(absolutePath)) continue;
3959
- const chain = readExtends(absolutePath);
3960
- if (existing === void 0) {
3961
- existing = candidate;
3962
- existingExtendsSomething = chain.length > 0;
3963
- }
3964
- const extendsBase = chain.some((value) => markers.some((marker) => value.includes(marker)));
3965
- if (extendsBase) return { path: candidate, reason: "extends-base" };
3966
- }
3967
- if (existing) {
3968
- return { path: existing, reason: existingExtendsSomething ? "other-chain" : "no-extends" };
3969
- }
3970
- return { path: fallback, reason: "none" };
3971
- }
3972
-
3973
- // src/core/config/read-adoption.ts
3974
- function normaliseExtends(value) {
3975
- if (typeof value === "string") return [value];
3976
- if (Array.isArray(value)) {
3977
- return value.filter((entry) => typeof entry === "string");
3978
- }
3979
- return [];
3980
- }
3981
- var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
3982
- configFile,
3983
- preset: null,
3984
- adopted: false,
3985
- conformant: false,
3986
- drift: [],
3987
- unreadable
3988
- });
3989
- function readAdoption(cwd, options) {
3990
- const target = resolveConfigTarget(cwd, options);
3991
- if (target.reason === "none" || !existsSync12(join15(cwd, target.path))) {
3992
- return NOT_ADOPTED2(target.reason === "none" ? null : target.path);
3993
- }
3994
- let parsed;
3995
- try {
3996
- parsed = parseJsonc(readFileSync12(join15(cwd, target.path), "utf8"), target.path);
3997
- } catch (error) {
3998
- const reason = error instanceof Error ? error.message : String(error);
3999
- return NOT_ADOPTED2(target.path, `${target.path} could not be parsed (${reason})`);
4000
- }
4001
- const preset = normaliseExtends(parsed.extends).find((entry) => options.presetPattern.test(entry)) ?? null;
4002
- if (preset === null) return NOT_ADOPTED2(target.path);
4003
- const settings = options.settingsKey === null ? parsed : parsed[options.settingsKey];
4004
- const drift = presetOwnedKeys(settings, options.permitted, options.presetOwns?.(preset));
4005
- return {
4006
- configFile: target.path,
4007
- preset,
4008
- adopted: true,
4009
- conformant: drift.length === 0,
4010
- drift,
4011
- unreadable: null
4012
- };
4013
- }
4014
-
4015
- // src/roles/lint/read-adoption.ts
4016
- function readLintAdoption(cwd) {
4017
- return readAdoption(cwd, {
4018
- candidates: [LINT_CONFIG_FILE],
4019
- markers: ["@hublo/sentinel/oxlint/"],
4020
- fallback: LINT_CONFIG_FILE,
4021
- presetPattern: SENTINEL_LINT_PRESET,
4022
- // Drift for lint is any TOP-LEVEL key beyond `extends`, so the settings the shared
4023
- // reader inspects are the config's own root rather than a nested options object.
4024
- settingsKey: null,
4025
- permitted: PERMITTED_LOCAL_KEYS2
4026
- });
4027
- }
4028
-
4029
- // src/roles/lint/resolve-oxlint.ts
4030
- import { existsSync as existsSync13 } from "node:fs";
4031
- import { createRequire } from "node:module";
4032
- import { delimiter, dirname, join as join16 } from "node:path";
4033
- import { fileURLToPath } from "node:url";
4034
- var PACKAGE_OF = {
4035
- oxlint: "oxlint",
4036
- tsgolint: "oxlint-tsgolint"
4037
- };
4038
- var require2 = createRequire(import.meta.url);
4039
- function resolveOxlint(cwd, name = "oxlint") {
4040
- return resolveBin(cwd, name) ?? binFromOwnInstall(PACKAGE_OF[name], name);
4041
- }
4042
- function canRunTypeAware(cwd) {
4043
- return tsgolintShim(cwd) !== void 0;
4044
- }
4045
- function oxlintPath(cwd, env) {
4046
- const shim = tsgolintShim(cwd);
4047
- if (!shim) return env.PATH;
4048
- return [dirname(shim), env.PATH].filter(Boolean).join(delimiter);
4049
- }
4050
- function tsgolintShim(cwd) {
4051
- const fromModule = resolveBin(cwd, "tsgolint");
4052
- if (fromModule) return fromModule;
4053
- const candidates = [];
4054
- for (const owner of ["oxlint-tsgolint", "oxlint"]) {
4055
- try {
4056
- const packageDir = dirname(require2.resolve(`${owner}/package.json`));
4057
- candidates.push(join16(packageDir, "node_modules", ".bin", "tsgolint"));
4058
- candidates.push(join16(packageDir, "..", ".bin", "tsgolint"));
4059
- } catch {
4060
- }
4061
- }
4062
- try {
4063
- const ownRoot = dirname(require2.resolve("@hublo/sentinel/package.json"));
4064
- candidates.push(join16(ownRoot, "node_modules", ".bin", "tsgolint"));
4065
- } catch {
4066
- candidates.push(resolveBin(dirname(fileURLToPath(import.meta.url)), "tsgolint") ?? "");
4067
- }
4068
- return candidates.find((candidate) => candidate !== "" && existsSync13(candidate));
4069
- }
4070
- function oxlintSearchPath(cwd) {
4071
- return binSearchPath(cwd);
4072
- }
4073
-
4074
3850
  // src/roles/lint/adapters/oxlint/plan.ts
4075
- import { existsSync as existsSync15, readFileSync as readFileSync15 } from "node:fs";
4076
- import { join as join19 } from "node:path";
3851
+ import { existsSync as existsSync11, readFileSync as readFileSync12 } from "node:fs";
3852
+ import { join as join15 } from "node:path";
4077
3853
 
4078
3854
  // src/roles/lint/eslint-ignores.ts
4079
- import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
4080
- import { join as join17 } from "node:path";
3855
+ import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
3856
+ import { join as join13 } from "node:path";
4081
3857
  import { parseSync } from "oxc-parser";
4082
3858
  var OPAQUE_SOURCE = /\b(includeIgnoreFile)\s*\([^)]*\)/g;
4083
3859
  function toOxlintPattern(pattern) {
@@ -4089,11 +3865,11 @@ function readRootEslintIgnores(root) {
4089
3865
  return { patterns: patterns.filter((pattern) => pattern.startsWith("**/")), unresolved };
4090
3866
  }
4091
3867
  function readEslintIgnores(cwd) {
4092
- const config = ESLINT_CONFIG_FILES.map((name) => join17(cwd, name)).find((path) => existsSync14(path));
3868
+ const config = ESLINT_CONFIG_FILES.map((name) => join13(cwd, name)).find((path) => existsSync10(path));
4093
3869
  if (!config) return { patterns: [], unresolved: [] };
4094
3870
  let source;
4095
3871
  try {
4096
- source = readFileSync13(config, "utf8");
3872
+ source = readFileSync10(config, "utf8");
4097
3873
  } catch {
4098
3874
  return { patterns: [], unresolved: [] };
4099
3875
  }
@@ -4184,8 +3960,8 @@ function lintPresetFor(preset) {
4184
3960
  }
4185
3961
 
4186
3962
  // src/roles/lint/rename-suppressions.ts
4187
- import { readdirSync as readdirSync2, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
4188
- import { join as join18, relative as relative3 } from "node:path";
3963
+ import { readdirSync as readdirSync2, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
3964
+ import { join as join14, relative as relative3 } from "node:path";
4189
3965
  var SOURCE_EXTENSIONS = [
4190
3966
  ".ts",
4191
3967
  ".tsx",
@@ -4232,7 +4008,7 @@ function* sourceFiles(dir) {
4232
4008
  return;
4233
4009
  }
4234
4010
  for (const entry of entries) {
4235
- const full = join18(dir, entry);
4011
+ const full = join14(dir, entry);
4236
4012
  let isDirectory;
4237
4013
  try {
4238
4014
  isDirectory = statSync3(full).isDirectory();
@@ -4252,7 +4028,7 @@ function findSuppressionRenames(cwd, renames) {
4252
4028
  for (const file of sourceFiles(cwd)) {
4253
4029
  let content;
4254
4030
  try {
4255
- content = readFileSync14(file, "utf8");
4031
+ content = readFileSync11(file, "utf8");
4256
4032
  } catch {
4257
4033
  continue;
4258
4034
  }
@@ -4380,7 +4156,7 @@ function plan2(context) {
4380
4156
  keys: removableDeps
4381
4157
  });
4382
4158
  }
4383
- const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync15(join19(context.cwd, name)));
4159
+ const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync11(join15(context.cwd, name)));
4384
4160
  for (const name of eslintConfigs) operations.push({ kind: "delete", path: name });
4385
4161
  operations.push(
4386
4162
  ...nxTargetOperations({
@@ -4478,7 +4254,7 @@ function lintScripts(cwd) {
4478
4254
  function committedExtends(cwd) {
4479
4255
  try {
4480
4256
  const parsed = parseJsonc(
4481
- readFileSync15(join19(cwd, LINT_CONFIG_FILE), "utf8"),
4257
+ readFileSync12(join15(cwd, LINT_CONFIG_FILE), "utf8"),
4482
4258
  LINT_CONFIG_FILE
4483
4259
  );
4484
4260
  return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
@@ -4489,7 +4265,7 @@ function committedExtends(cwd) {
4489
4265
  function committedIgnorePatterns(cwd) {
4490
4266
  try {
4491
4267
  const parsed = parseJsonc(
4492
- readFileSync15(join19(cwd, LINT_CONFIG_FILE), "utf8"),
4268
+ readFileSync12(join15(cwd, LINT_CONFIG_FILE), "utf8"),
4493
4269
  LINT_CONFIG_FILE
4494
4270
  );
4495
4271
  return Array.isArray(parsed.ignorePatterns) ? parsed.ignorePatterns.filter((entry) => typeof entry === "string") : [];
@@ -4501,7 +4277,7 @@ function moduleEslintDependencies(cwd) {
4501
4277
  const isEslintPackage = (name) => name === "eslint" || name === "@types/eslint" || name === "typescript-eslint" || name.startsWith("@typescript-eslint/") || name.startsWith("eslint-plugin-") || name.startsWith("eslint-config-") || name.startsWith("@eslint/");
4502
4278
  let manifest;
4503
4279
  try {
4504
- manifest = JSON.parse(readFileSync15(join19(cwd, "package.json"), "utf8"));
4280
+ manifest = JSON.parse(readFileSync12(join15(cwd, "package.json"), "utf8"));
4505
4281
  } catch {
4506
4282
  return [];
4507
4283
  }
@@ -4635,20 +4411,20 @@ ${result.stderr ?? ""}`);
4635
4411
  * build the developer can see, rather than a silent half-adoption they cannot.
4636
4412
  */
4637
4413
  writeModuleBaseline(ctx, oxlint, env) {
4638
- const configPath = join20(ctx.cwd, LINT_CONFIG_FILE);
4639
- const baselinePath = join20(ctx.cwd, LINT_BASELINE_FILE);
4640
- if (!existsSync16(configPath)) return;
4414
+ const configPath = join16(ctx.cwd, LINT_CONFIG_FILE);
4415
+ const baselinePath = join16(ctx.cwd, LINT_BASELINE_FILE);
4416
+ if (!existsSync12(configPath)) return;
4641
4417
  let config;
4642
4418
  try {
4643
4419
  config = parseJsonc(
4644
- readFileSync16(configPath, "utf8"),
4420
+ readFileSync13(configPath, "utf8"),
4645
4421
  LINT_CONFIG_FILE
4646
4422
  );
4647
4423
  } catch {
4648
4424
  return;
4649
4425
  }
4650
4426
  const current = Array.isArray(config.extends) ? config.extends : [];
4651
- const measurePath = join20(ctx.cwd, LINT_MEASURE_FILE);
4427
+ const measurePath = join16(ctx.cwd, LINT_MEASURE_FILE);
4652
4428
  let measured;
4653
4429
  try {
4654
4430
  writeFileSync2(
@@ -4696,7 +4472,7 @@ ${result.stderr ?? ""}`);
4696
4472
  }
4697
4473
  }
4698
4474
  async run(ctx) {
4699
- if (!existsSync16(join20(ctx.cwd, LINT_CONFIG_FILE))) {
4475
+ if (!existsSync12(join16(ctx.cwd, LINT_CONFIG_FILE))) {
4700
4476
  process.stderr.write(
4701
4477
  `sentinel lint(oxlint): no ${LINT_CONFIG_FILE} in this module; run \`sentinel --init --lint\` to adopt.
4702
4478
  `
@@ -4844,7 +4620,7 @@ ${result.stderr ?? ""}`);
4844
4620
  let stub;
4845
4621
  try {
4846
4622
  stub = parseJsonc(
4847
- readFileSync16(join20(cwd, LINT_CONFIG_FILE), "utf8"),
4623
+ readFileSync13(join16(cwd, LINT_CONFIG_FILE), "utf8"),
4848
4624
  LINT_CONFIG_FILE
4849
4625
  );
4850
4626
  } catch {
@@ -4854,7 +4630,7 @@ ${result.stderr ?? ""}`);
4854
4630
  for (const entry of stub.extends ?? []) {
4855
4631
  try {
4856
4632
  const preset = parseJsonc(
4857
- readFileSync16(join20(cwd, entry), "utf8"),
4633
+ readFileSync13(join16(cwd, entry), "utf8"),
4858
4634
  entry
4859
4635
  );
4860
4636
  for (const rule of Object.keys(preset.rules ?? {})) names.add(rule);
@@ -4924,14 +4700,14 @@ ${result.stderr ?? ""}`);
4924
4700
  let parsed;
4925
4701
  try {
4926
4702
  parsed = parseJsonc(
4927
- readFileSync16(join20(cwd, LINT_CONFIG_FILE), "utf8"),
4703
+ readFileSync13(join16(cwd, LINT_CONFIG_FILE), "utf8"),
4928
4704
  LINT_CONFIG_FILE
4929
4705
  );
4930
4706
  } catch {
4931
4707
  return void 0;
4932
4708
  }
4933
4709
  const targets = Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : typeof parsed.extends === "string" ? [parsed.extends] : [];
4934
- return targets.find((target) => !existsSync16(join20(cwd, target)));
4710
+ return targets.find((target) => !existsSync12(join16(cwd, target)));
4935
4711
  }
4936
4712
  /** Announce what is not enforced, so reduced coverage is never silent. */
4937
4713
  announceDisabled(preset) {
@@ -4969,9 +4745,9 @@ function registerTest() {
4969
4745
 
4970
4746
  // src/roles/typescript/adapters/tsc/tsc.adapter.ts
4971
4747
  import { spawnSync as spawnSync5 } from "node:child_process";
4972
- import { existsSync as existsSync17, readFileSync as readFileSync18 } from "node:fs";
4973
- import { createRequire as createRequire2 } from "node:module";
4974
- import { join as join22 } from "node:path";
4748
+ import { existsSync as existsSync13, readFileSync as readFileSync15 } from "node:fs";
4749
+ import { createRequire } from "node:module";
4750
+ import { join as join18 } from "node:path";
4975
4751
 
4976
4752
  // src/roles/typescript/presets/nest.json
4977
4753
  var nest_default2 = {
@@ -5152,8 +4928,8 @@ function readTsconfigAdoption(cwd) {
5152
4928
  }
5153
4929
 
5154
4930
  // src/roles/typescript/adapters/tsc/plan.ts
5155
- import { readFileSync as readFileSync17 } from "node:fs";
5156
- import { join as join21 } from "node:path";
4931
+ import { readFileSync as readFileSync14 } from "node:fs";
4932
+ import { join as join17 } from "node:path";
5157
4933
 
5158
4934
  // src/roles/typescript/typecheck-script.ts
5159
4935
  var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
@@ -5246,7 +5022,7 @@ function planAdoption(context) {
5246
5022
  };
5247
5023
  }
5248
5024
  const existing = parseJsonc(
5249
- readFileSync17(join21(context.cwd, target.path), "utf8"),
5025
+ readFileSync14(join17(context.cwd, target.path), "utf8"),
5250
5026
  target.path
5251
5027
  );
5252
5028
  const extendsChain = composeExtends(existing.extends, preset);
@@ -5384,7 +5160,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5384
5160
  let chain;
5385
5161
  try {
5386
5162
  const parsed = parseJsonc(
5387
- readFileSync18(join22(cwd, target.path), "utf8"),
5163
+ readFileSync15(join18(cwd, target.path), "utf8"),
5388
5164
  target.path
5389
5165
  );
5390
5166
  chain = parsed.extends;
@@ -5397,7 +5173,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5397
5173
  );
5398
5174
  if (preset === void 0) return void 0;
5399
5175
  try {
5400
- createRequire2(join22(cwd, "noop.js")).resolve(preset);
5176
+ createRequire(join18(cwd, "noop.js")).resolve(preset);
5401
5177
  return void 0;
5402
5178
  } catch {
5403
5179
  return preset;
@@ -5493,7 +5269,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5493
5269
  referencedProjects(cwd, config) {
5494
5270
  try {
5495
5271
  const parsed = parseJsonc(
5496
- readFileSync18(join22(cwd, config), "utf8"),
5272
+ readFileSync15(join18(cwd, config), "utf8"),
5497
5273
  config
5498
5274
  );
5499
5275
  const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
@@ -5509,7 +5285,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5509
5285
  * check.
5510
5286
  */
5511
5287
  typecheckTarget(cwd) {
5512
- if (existsSync17(join22(cwd, "tsconfig.json"))) return "tsconfig.json";
5288
+ if (existsSync13(join18(cwd, "tsconfig.json"))) return "tsconfig.json";
5513
5289
  const target = resolveTsconfigTarget(cwd);
5514
5290
  return target.reason === "none" ? null : target.path;
5515
5291
  }
@@ -5714,7 +5490,7 @@ function replaceLines(current, replacements) {
5714
5490
  }
5715
5491
 
5716
5492
  // src/core/apply-plan.ts
5717
- import { existsSync as existsSync18, readFileSync as readFileSync19, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
5493
+ import { existsSync as existsSync14, readFileSync as readFileSync16, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
5718
5494
  import { resolve as resolve3, sep } from "node:path";
5719
5495
  import { applyEdits, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
5720
5496
 
@@ -5733,7 +5509,7 @@ function resolveWithinRoot(cwd, relativePath) {
5733
5509
  return absolutePath;
5734
5510
  }
5735
5511
  function readIfExists(absolutePath) {
5736
- return existsSync18(absolutePath) ? readFileSync19(absolutePath, "utf8") : void 0;
5512
+ return existsSync14(absolutePath) ? readFileSync16(absolutePath, "utf8") : void 0;
5737
5513
  }
5738
5514
  function* leaves(value, prefix = []) {
5739
5515
  for (const [key, keyValue] of Object.entries(value)) {
@@ -5851,8 +5627,8 @@ function applyPlan(cwd, plan3) {
5851
5627
  }
5852
5628
 
5853
5629
  // src/core/config/preset-evidence.ts
5854
- import { existsSync as existsSync19, readdirSync as readdirSync3, readFileSync as readFileSync20 } from "node:fs";
5855
- import { join as join23 } from "node:path";
5630
+ import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync17 } from "node:fs";
5631
+ import { join as join19 } from "node:path";
5856
5632
  var PATH_SIGNALS = [
5857
5633
  {
5858
5634
  preset: "nest",
@@ -5886,12 +5662,12 @@ function sourceImports(cwd, pattern) {
5886
5662
  }
5887
5663
  for (const entry of entries) {
5888
5664
  if (entry.isDirectory()) {
5889
- if (!NOT_SCANNED.has(entry.name)) stack.push(join23(dir, entry.name));
5665
+ if (!NOT_SCANNED.has(entry.name)) stack.push(join19(dir, entry.name));
5890
5666
  continue;
5891
5667
  }
5892
5668
  if (!SOURCE_FILE.test(entry.name)) continue;
5893
5669
  try {
5894
- if (pattern.test(readFileSync20(join23(dir, entry.name), "utf8"))) return true;
5670
+ if (pattern.test(readFileSync17(join19(dir, entry.name), "utf8"))) return true;
5895
5671
  } catch {
5896
5672
  continue;
5897
5673
  }
@@ -5900,11 +5676,11 @@ function sourceImports(cwd, pattern) {
5900
5676
  return false;
5901
5677
  }
5902
5678
  function dependencyNames(cwd) {
5903
- const path = join23(cwd, "package.json");
5904
- if (!existsSync19(path)) return [];
5679
+ const path = join19(cwd, "package.json");
5680
+ if (!existsSync15(path)) return [];
5905
5681
  try {
5906
5682
  const manifest = parseJsonc(
5907
- readFileSync20(path, "utf8"),
5683
+ readFileSync17(path, "utf8"),
5908
5684
  path
5909
5685
  );
5910
5686
  return [
@@ -5927,7 +5703,7 @@ function declaresJsx(cwd) {
5927
5703
  for (const name of entries) {
5928
5704
  try {
5929
5705
  const config = parseJsonc(
5930
- readFileSync20(join23(cwd, name), "utf8"),
5706
+ readFileSync17(join19(cwd, name), "utf8"),
5931
5707
  name
5932
5708
  );
5933
5709
  if (config.compilerOptions?.jsx !== void 0) return true;