@hublo/sentinel 1.2.0-alpha.23 → 1.2.0-alpha.24

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.
@@ -22,7 +22,7 @@ import {
22
22
  registerAdapters,
23
23
  resolve,
24
24
  resolveBin
25
- } from "../chunk-YBJLWNTQ.js";
25
+ } from "../chunk-ORPLAWRT.js";
26
26
 
27
27
  // bin/sentinel.ts
28
28
  import { program } from "commander";
@@ -238,8 +238,58 @@ function workspaceRootHops(cwd, target) {
238
238
  }
239
239
 
240
240
  // src/roles/build/read-adoption.ts
241
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
242
+ import { join as join5 } from "path";
243
+
244
+ // src/roles/build/adoption-drift.ts
245
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
246
+ import { join as join4 } from "path";
247
+
248
+ // src/core/config/manifest.ts
241
249
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
242
- import { join as join3 } from "path";
250
+ import { basename as basename2, join as join3 } from "path";
251
+ function moduleScripts(cwd) {
252
+ try {
253
+ const pkg = JSON.parse(readFileSync3(join3(cwd, "package.json"), "utf8"));
254
+ return pkg.scripts ?? {};
255
+ } catch {
256
+ return {};
257
+ }
258
+ }
259
+ function moduleName2(cwd) {
260
+ try {
261
+ const pkg = JSON.parse(readFileSync3(join3(cwd, "package.json"), "utf8"));
262
+ return pkg.name;
263
+ } catch {
264
+ return void 0;
265
+ }
266
+ }
267
+ function isSelfAdoption(cwd) {
268
+ return moduleName2(cwd) === readOwnPackage().name;
269
+ }
270
+ function selfCommand(cwd, flags) {
271
+ const own = readOwnPackage();
272
+ if (!isSelfAdoption(cwd) || !own.bin) return void 0;
273
+ return `node ${own.bin.replace(/^\.\//, "")} ${flags}`;
274
+ }
275
+ function adoptedPackageName(cwd) {
276
+ return readProjectPackageJson(cwd).name ?? readNxProjectName(cwd) ?? basename2(cwd);
277
+ }
278
+ function manifestOperation(cwd, scripts) {
279
+ const own = readOwnPackage();
280
+ const value = {
281
+ scripts,
282
+ devDependencies: { [own.name]: isSelfAdoption(cwd) ? "link:." : own.version }
283
+ };
284
+ if (existsSync3(join3(cwd, "package.json"))) {
285
+ return { kind: "merge-json", path: "package.json", value };
286
+ }
287
+ return {
288
+ kind: "merge-json",
289
+ path: "package.json",
290
+ value: { name: adoptedPackageName(cwd), private: true, ...value }
291
+ };
292
+ }
243
293
 
244
294
  // src/roles/build/presets/requirements.json
245
295
  var requirements_default = {
@@ -356,6 +406,60 @@ var SENTINEL_OWNED_BUILD_PACKAGES = OWNED_PACKAGES.map(
356
406
  (entry) => entry.package
357
407
  );
358
408
 
409
+ // src/roles/build/adoption-drift.ts
410
+ function projectTargets(cwd) {
411
+ const path = join4(cwd, "project.json");
412
+ if (!existsSync4(path)) return void 0;
413
+ try {
414
+ return JSON.parse(readFileSync4(path, "utf8")).targets;
415
+ } catch {
416
+ return void 0;
417
+ }
418
+ }
419
+ function buildAdoptionDrift(cwd) {
420
+ const drift = [];
421
+ const manifest = readProjectPackageJson(cwd);
422
+ const script = moduleScripts(cwd)[BUILD_SCRIPT_NAME];
423
+ if (script === void 0) {
424
+ drift.push(
425
+ `has no \`${BUILD_SCRIPT_NAME}\` npm script, so \`pnpm run ${BUILD_SCRIPT_NAME}\` does not build it and only nx can`
426
+ );
427
+ } else if (!script.includes(SENTINEL_BUILD_COMMAND.replace(/ --$/, ""))) {
428
+ drift.push(
429
+ `its \`${BUILD_SCRIPT_NAME}\` script does not invoke sentinel (${script}), so the config points at sentinel while the script runs something else`
430
+ );
431
+ }
432
+ const target = manifest.nx?.targets?.[BUILD_SCRIPT_NAME];
433
+ if (target === void 0) {
434
+ drift.push(
435
+ `declares no \`nx.targets.${BUILD_SCRIPT_NAME}\`, so its build runs on nx's default inputs while every other target it has declares its own`
436
+ );
437
+ } else {
438
+ if (target.cache === true && (target.outputs ?? []).length === 0) {
439
+ drift.push(
440
+ `caches its build and declares no \`outputs\`, so nx stores nothing and a cache hit reports success with no build on disk`
441
+ );
442
+ }
443
+ const inputs = target.inputs ?? [];
444
+ if (inputs.length > 0 && !inputs.includes("^default")) {
445
+ drift.push(
446
+ `declares \`inputs\` without \`^default\`, which REPLACES nx's default and stops hashing its dependencies: the build can replay a stale bundle after one changes`
447
+ );
448
+ }
449
+ if (target.options?.forwardAllArgs !== false) {
450
+ drift.push(
451
+ `does not set \`forwardAllArgs: false\`, so a caller's extra flag reaches the bundler, which refuses it (the image passes \`--generatePackageJson\`)`
452
+ );
453
+ }
454
+ }
455
+ if (projectTargets(cwd)?.[BUILD_SCRIPT_NAME] !== void 0) {
456
+ drift.push(
457
+ `still declares a \`${BUILD_SCRIPT_NAME}\` target in project.json beside the one in package.json, so the module has two and which runs depends on the caller`
458
+ );
459
+ }
460
+ return drift;
461
+ }
462
+
359
463
  // src/roles/build/read-adoption.ts
360
464
  var NOT_ADOPTED = (configFile, unreadable = null) => ({
361
465
  configFile,
@@ -367,7 +471,7 @@ var NOT_ADOPTED = (configFile, unreadable = null) => ({
367
471
  unreadable
368
472
  });
369
473
  function buildConfigFile(cwd) {
370
- return BUILD_CONFIG_FILES.find((name) => existsSync3(join3(cwd, name)));
474
+ return BUILD_CONFIG_FILES.find((name) => existsSync5(join5(cwd, name)));
371
475
  }
372
476
  function importsSpecifier(source, specifier) {
373
477
  const escaped = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -393,7 +497,7 @@ function readBuildConfigSource(cwd) {
393
497
  const configFile = buildConfigFile(cwd);
394
498
  if (!configFile) return void 0;
395
499
  try {
396
- return readFileSync3(join3(cwd, configFile), "utf8");
500
+ return readFileSync5(join5(cwd, configFile), "utf8");
397
501
  } catch {
398
502
  return void 0;
399
503
  }
@@ -403,7 +507,7 @@ function readBuildAdoption(cwd) {
403
507
  if (!configFile) return NOT_ADOPTED(null);
404
508
  let source;
405
509
  try {
406
- source = readFileSync3(join3(cwd, configFile), "utf8");
510
+ source = readFileSync5(join5(cwd, configFile), "utf8");
407
511
  } catch (error) {
408
512
  return NOT_ADOPTED(configFile, error instanceof Error ? error.message : String(error));
409
513
  }
@@ -413,16 +517,20 @@ function readBuildAdoption(cwd) {
413
517
  const ownDeclarations = SENTINEL_OWNED_BUILD_PACKAGES.filter((name) => name in declared).map(
414
518
  (name) => ({ name, version: declared[name] })
415
519
  );
520
+ const drift = [
521
+ ...ownDeclarations.map(
522
+ ({ name, version }) => `declares ${name}@${version} of its own; sentinel owns it, and two copies in one build give the plugins a different Vite than the one running them`
523
+ ),
524
+ ...buildAdoptionDrift(cwd)
525
+ ];
416
526
  return {
417
527
  configFile,
418
528
  // Read from the config rather than assumed: the two presets are adopted the same way and
419
529
  // reporting the wrong one would make `--inspect` lie about what a module builds.
420
530
  preset: declaredBuildPreset(cwd) ?? "react",
421
531
  adopted: true,
422
- conformant: ownDeclarations.length === 0,
423
- drift: ownDeclarations.map(
424
- ({ name, version }) => `declares ${name}@${version} of its own; sentinel owns it, and two copies in one build give the plugins a different Vite than the one running them`
425
- ),
532
+ conformant: drift.length === 0,
533
+ drift,
426
534
  ownDeclarations,
427
535
  unreadable: null
428
536
  };
@@ -432,7 +540,7 @@ function readBuildAdoption(cwd) {
432
540
  import { spawnSync } from "child_process";
433
541
 
434
542
  // src/core/config/tool-args.ts
435
- import { existsSync as existsSync4 } from "fs";
543
+ import { existsSync as existsSync6 } from "fs";
436
544
  import { isAbsolute, resolve as resolve2 } from "path";
437
545
  function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
438
546
  const takesValue = new Set(valueFlags);
@@ -442,7 +550,7 @@ function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
442
550
  for (const arg of toolArgs) {
443
551
  const looksLikeOption = arg.startsWith("-");
444
552
  const target = isAbsolute(arg) ? arg : resolve2(cwd, arg);
445
- if (!previousTakesValue && !looksLikeOption && existsSync4(target)) paths.push(arg);
553
+ if (!previousTakesValue && !looksLikeOption && existsSync6(target)) paths.push(arg);
446
554
  else options.push(arg);
447
555
  previousTakesValue = !arg.includes("=") && takesValue.has(arg);
448
556
  }
@@ -450,15 +558,15 @@ function splitToolArgs(cwd, toolArgs = [], { valueFlags = [] } = {}) {
450
558
  }
451
559
 
452
560
  // src/shared/resolve-bin.ts
453
- import { existsSync as existsSync5 } from "fs";
561
+ import { existsSync as existsSync7 } from "fs";
454
562
  import { createRequire } from "module";
455
- import { delimiter, dirname as dirname2, join as join4 } from "path";
563
+ import { delimiter, dirname as dirname2, join as join6 } from "path";
456
564
  var require2 = createRequire(import.meta.url);
457
565
  function resolveBin(fromDir, name) {
458
566
  let dir = fromDir;
459
567
  for (; ; ) {
460
- const candidate = join4(dir, "node_modules", ".bin", name);
461
- if (existsSync5(candidate)) return candidate;
568
+ const candidate = join6(dir, "node_modules", ".bin", name);
569
+ if (existsSync7(candidate)) return candidate;
462
570
  const parent = dirname2(dir);
463
571
  if (parent === dir) return void 0;
464
572
  dir = parent;
@@ -470,8 +578,8 @@ function binFromOwnInstall(packageName, binName) {
470
578
  const bin = require2(manifest).bin;
471
579
  const relative5 = typeof bin === "string" ? bin : bin?.[binName];
472
580
  if (!relative5) return void 0;
473
- const executable = join4(dirname2(manifest), relative5);
474
- return existsSync5(executable) ? executable : void 0;
581
+ const executable = join6(dirname2(manifest), relative5);
582
+ return existsSync7(executable) ? executable : void 0;
475
583
  } catch {
476
584
  return void 0;
477
585
  }
@@ -483,12 +591,12 @@ function binSearchPath(cwd) {
483
591
  }
484
592
 
485
593
  // src/roles/build/plan.ts
486
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
487
- import { join as join9 } from "path";
594
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
595
+ import { join as join10 } from "path";
488
596
 
489
597
  // src/core/config/existing-command.ts
490
- import { readFileSync as readFileSync5 } from "fs";
491
- import { join as join6 } from "path";
598
+ import { readFileSync as readFileSync6 } from "fs";
599
+ import { join as join7 } from "path";
492
600
 
493
601
  // src/shared/jsonc.ts
494
602
  import { parse, printParseErrorCode } from "jsonc-parser";
@@ -502,58 +610,12 @@ function parseJsonc(text, source = "config") {
502
610
  return value;
503
611
  }
504
612
 
505
- // src/core/config/manifest.ts
506
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
507
- import { basename as basename2, join as join5 } from "path";
508
- function moduleScripts(cwd) {
509
- try {
510
- const pkg = JSON.parse(readFileSync4(join5(cwd, "package.json"), "utf8"));
511
- return pkg.scripts ?? {};
512
- } catch {
513
- return {};
514
- }
515
- }
516
- function moduleName2(cwd) {
517
- try {
518
- const pkg = JSON.parse(readFileSync4(join5(cwd, "package.json"), "utf8"));
519
- return pkg.name;
520
- } catch {
521
- return void 0;
522
- }
523
- }
524
- function isSelfAdoption(cwd) {
525
- return moduleName2(cwd) === readOwnPackage().name;
526
- }
527
- function selfCommand(cwd, flags) {
528
- const own = readOwnPackage();
529
- if (!isSelfAdoption(cwd) || !own.bin) return void 0;
530
- return `node ${own.bin.replace(/^\.\//, "")} ${flags}`;
531
- }
532
- function adoptedPackageName(cwd) {
533
- return readProjectPackageJson(cwd).name ?? readNxProjectName(cwd) ?? basename2(cwd);
534
- }
535
- function manifestOperation(cwd, scripts) {
536
- const own = readOwnPackage();
537
- const value = {
538
- scripts,
539
- devDependencies: { [own.name]: isSelfAdoption(cwd) ? "link:." : own.version }
540
- };
541
- if (existsSync6(join5(cwd, "package.json"))) {
542
- return { kind: "merge-json", path: "package.json", value };
543
- }
544
- return {
545
- kind: "merge-json",
546
- path: "package.json",
547
- value: { name: adoptedPackageName(cwd), private: true, ...value }
548
- };
549
- }
550
-
551
613
  // src/core/config/existing-command.ts
552
614
  function nxTargetCommand(cwd, target) {
553
615
  let project;
554
616
  try {
555
617
  project = parseJsonc(
556
- readFileSync5(join6(cwd, "project.json"), "utf8"),
618
+ readFileSync6(join7(cwd, "project.json"), "utf8"),
557
619
  "project.json"
558
620
  );
559
621
  } catch {
@@ -584,8 +646,8 @@ function existingCommand(cwd, target) {
584
646
  }
585
647
 
586
648
  // src/core/config/nx-target.ts
587
- import { existsSync as existsSync7 } from "fs";
588
- import { join as join7 } from "path";
649
+ import { existsSync as existsSync8 } from "fs";
650
+ import { join as join8 } from "path";
589
651
  function nxTargetMetadataOperations(options) {
590
652
  const { targets } = options;
591
653
  if (Object.keys(targets).length === 0) return [];
@@ -596,7 +658,7 @@ function nxTargetOperations(options) {
596
658
  const names = Object.keys(targets);
597
659
  if (names.length === 0) return [];
598
660
  const operations = [];
599
- if (existsSync7(join7(cwd, "project.json"))) {
661
+ if (existsSync8(join8(cwd, "project.json"))) {
600
662
  operations.push({
601
663
  kind: "remove-json-keys",
602
664
  path: "project.json",
@@ -670,8 +732,8 @@ function composeDevScript(existing, command) {
670
732
  }
671
733
 
672
734
  // src/roles/build/nest/adopt.ts
673
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
674
- import { join as join8 } from "path";
735
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
736
+ import { join as join9 } from "path";
675
737
  var NEST_CONFIG_FILE = "vite.config.mts";
676
738
  function nestConfigSource(cwd, target) {
677
739
  const hops = workspaceRootHops(cwd, target);
@@ -695,9 +757,9 @@ function nestBuildOutputs(target) {
695
757
  }
696
758
  var OUT_DIR_IN_CONFIG = /^\s*outDir:\s*'([^']+)'/m;
697
759
  function nestOutputsFromConfig(cwd) {
698
- const configPath = join8(cwd, NEST_CONFIG_FILE);
699
- if (!existsSync8(configPath)) return void 0;
700
- const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync6(configPath, "utf8"))?.[1];
760
+ const configPath = join9(cwd, NEST_CONFIG_FILE);
761
+ if (!existsSync9(configPath)) return void 0;
762
+ const outDir = OUT_DIR_IN_CONFIG.exec(readFileSync7(configPath, "utf8"))?.[1];
701
763
  return outDir === void 0 ? void 0 : [`{workspaceRoot}/${outDir}`];
702
764
  }
703
765
  function nestAdoptionOperations(cwd, target) {
@@ -997,9 +1059,9 @@ function planNestService(context, webpackTarget) {
997
1059
  };
998
1060
  }
999
1061
  function readConfigSource(cwd, configFile) {
1000
- if (!existsSync9(join9(cwd, configFile))) return "";
1062
+ if (!existsSync10(join10(cwd, configFile))) return "";
1001
1063
  try {
1002
- return readFileSync7(join9(cwd, configFile), "utf8");
1064
+ return readFileSync8(join10(cwd, configFile), "utf8");
1003
1065
  } catch {
1004
1066
  return "";
1005
1067
  }
@@ -1184,12 +1246,12 @@ var ViteDevAdapter = class extends ViteRoleAdapter {
1184
1246
  };
1185
1247
 
1186
1248
  // src/roles/build/declared-outputs.ts
1187
- import { existsSync as existsSync11, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
1188
- import { join as join11 } from "path";
1249
+ import { existsSync as existsSync12, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
1250
+ import { join as join12 } from "path";
1189
1251
 
1190
1252
  // src/core/workspace-prep.ts
1191
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync } from "fs";
1192
- import { dirname as dirname3, join as join10, relative as relative2 } from "path";
1253
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync } from "fs";
1254
+ import { dirname as dirname3, join as join11, relative as relative2 } from "path";
1193
1255
 
1194
1256
  // src/core/settings.ts
1195
1257
  var WORKSPACE_ROOT_MARKER = "nx.json";
@@ -1204,7 +1266,7 @@ var LIST_ITEM = /^(\s*)-\s+(.*?)\s*$/;
1204
1266
  function findWorkspaceRoot(startDir) {
1205
1267
  let dir = startDir;
1206
1268
  for (; ; ) {
1207
- if (existsSync10(join10(dir, WORKSPACE_ROOT_MARKER))) return dir;
1269
+ if (existsSync11(join11(dir, WORKSPACE_ROOT_MARKER))) return dir;
1208
1270
  const parent = dirname3(dir);
1209
1271
  if (parent === dir) return void 0;
1210
1272
  dir = parent;
@@ -1217,9 +1279,9 @@ function declaredNativeTs(pkg) {
1217
1279
  return version || void 0;
1218
1280
  }
1219
1281
  function ensureI18nextSingleton(root, dryRun) {
1220
- const pkgPath = join10(root, "package.json");
1221
- if (!existsSync10(pkgPath)) return void 0;
1222
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
1282
+ const pkgPath = join11(root, "package.json");
1283
+ if (!existsSync11(pkgPath)) return void 0;
1284
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
1223
1285
  const want = declaredNativeTs(pkg);
1224
1286
  if (!want) return void 0;
1225
1287
  const have = pkg.pnpm?.overrides?.[OVERRIDE_KEY];
@@ -1232,10 +1294,10 @@ function ensureI18nextSingleton(root, dryRun) {
1232
1294
  return `pinned ${OVERRIDE_KEY} to ${want} in package.json (i18next singleton)`;
1233
1295
  }
1234
1296
  function ensureReleaseAgeAllowList(root, dryRun) {
1235
- const yamlPath = join10(root, WORKSPACE_YAML);
1236
- if (!existsSync10(yamlPath)) return void 0;
1297
+ const yamlPath = join11(root, WORKSPACE_YAML);
1298
+ if (!existsSync11(yamlPath)) return void 0;
1237
1299
  const own = readOwnPackage().name;
1238
- const lines = readFileSync8(yamlPath, "utf8").split("\n");
1300
+ const lines = readFileSync9(yamlPath, "utf8").split("\n");
1239
1301
  const keyIdx = lines.findIndex((line) => line.replace(/\s+$/, "") === `${RELEASE_AGE_KEY}:`);
1240
1302
  if (keyIdx === -1) return void 0;
1241
1303
  let lastItemIdx = keyIdx;
@@ -1270,11 +1332,11 @@ var ROOT_PRETTIER_CONFIGS = [
1270
1332
  function ensureFormatterExclusion(root, moduleDir, dryRun) {
1271
1333
  const rel = relative2(root, moduleDir).replaceAll("\\", "/");
1272
1334
  if (rel === "" || rel.startsWith("..")) return void 0;
1273
- const ignorePath = join10(root, PRETTIER_IGNORE);
1274
- const hasPrettier = existsSync10(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync10(join10(root, name)));
1335
+ const ignorePath = join11(root, PRETTIER_IGNORE);
1336
+ const hasPrettier = existsSync11(ignorePath) || ROOT_PRETTIER_CONFIGS.some((name) => existsSync11(join11(root, name)));
1275
1337
  if (!hasPrettier) return void 0;
1276
1338
  const pattern = `/${rel}/`;
1277
- const existing = existsSync10(ignorePath) ? readFileSync8(ignorePath, "utf8") : "";
1339
+ const existing = existsSync11(ignorePath) ? readFileSync9(ignorePath, "utf8") : "";
1278
1340
  const lines = existing.split("\n");
1279
1341
  if (lines.some((line) => line.trim().replace(/\/$/, "") === pattern.replace(/\/$/, ""))) {
1280
1342
  return void 0;
@@ -1310,10 +1372,10 @@ function ensureWorkspacePrep(opts) {
1310
1372
  function inspectWorkspacePrep(root) {
1311
1373
  const entries = [];
1312
1374
  let pkg = {};
1313
- const pkgPath = join10(root, "package.json");
1314
- if (existsSync10(pkgPath)) {
1375
+ const pkgPath = join11(root, "package.json");
1376
+ if (existsSync11(pkgPath)) {
1315
1377
  try {
1316
- pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
1378
+ pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
1317
1379
  } catch {
1318
1380
  pkg = {};
1319
1381
  }
@@ -1327,9 +1389,9 @@ function inspectWorkspacePrep(root) {
1327
1389
  });
1328
1390
  }
1329
1391
  const own = readOwnPackage().name;
1330
- const yamlPath = join10(root, WORKSPACE_YAML);
1331
- if (existsSync10(yamlPath)) {
1332
- const yaml = readFileSync8(yamlPath, "utf8");
1392
+ const yamlPath = join11(root, WORKSPACE_YAML);
1393
+ if (existsSync11(yamlPath)) {
1394
+ const yaml = readFileSync9(yamlPath, "utf8");
1333
1395
  const listed = new RegExp(`^\\s*-\\s*['"]?${own.replace("/", "\\/")}['"]?\\s*$`, "m").test(yaml);
1334
1396
  if (listed) {
1335
1397
  const gated = new RegExp(`^\\s*minimumReleaseAge\\s*:`, "m").test(yaml);
@@ -1347,15 +1409,15 @@ function declaredBuildTarget(cwd) {
1347
1409
  return readProjectPackageJson(cwd).nx?.targets?.[BUILD_SCRIPT_NAME];
1348
1410
  }
1349
1411
  function resolveOutputToken(token, cwd) {
1350
- if (token.startsWith("{projectRoot}/")) return join11(cwd, token.slice("{projectRoot}/".length));
1412
+ if (token.startsWith("{projectRoot}/")) return join12(cwd, token.slice("{projectRoot}/".length));
1351
1413
  if (token.startsWith("{workspaceRoot}/")) {
1352
1414
  const root = findWorkspaceRoot(cwd);
1353
- return root === void 0 ? void 0 : join11(root, token.slice("{workspaceRoot}/".length));
1415
+ return root === void 0 ? void 0 : join12(root, token.slice("{workspaceRoot}/".length));
1354
1416
  }
1355
- return join11(cwd, token);
1417
+ return join12(cwd, token);
1356
1418
  }
1357
1419
  function buildStamp(cwd) {
1358
- const marker = join11(cwd, `.sentinel-build-stamp-${process.pid}`);
1420
+ const marker = join12(cwd, `.sentinel-build-stamp-${process.pid}`);
1359
1421
  try {
1360
1422
  writeFileSync2(marker, "");
1361
1423
  const stamp = statSync(marker).mtimeMs;
@@ -1366,7 +1428,7 @@ function buildStamp(cwd) {
1366
1428
  }
1367
1429
  }
1368
1430
  function writtenSince(path, startedAt) {
1369
- if (!existsSync11(path)) return false;
1431
+ if (!existsSync12(path)) return false;
1370
1432
  try {
1371
1433
  return statSync(path).mtimeMs >= startedAt;
1372
1434
  } catch {
@@ -1515,12 +1577,12 @@ function registerBuild() {
1515
1577
 
1516
1578
  // src/roles/format/adapters/oxfmt/oxfmt.adapter.ts
1517
1579
  import { spawnSync as spawnSync3 } from "child_process";
1518
- import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
1519
- import { join as join17 } from "path";
1580
+ import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
1581
+ import { join as join18 } from "path";
1520
1582
 
1521
1583
  // src/core/config/has-source.ts
1522
1584
  import { readdirSync } from "fs";
1523
- import { extname, join as join12, relative as relative3 } from "path";
1585
+ import { extname, join as join13, relative as relative3 } from "path";
1524
1586
  var SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
1525
1587
  "node_modules",
1526
1588
  "dist",
@@ -1571,7 +1633,7 @@ function hasSourceFiles(cwd, extensions) {
1571
1633
  }
1572
1634
  for (const entry of entries) {
1573
1635
  if (entry.isDirectory()) {
1574
- if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join12(dir, entry.name));
1636
+ if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(join13(dir, entry.name));
1575
1637
  continue;
1576
1638
  }
1577
1639
  if (wanted.has(extname(entry.name))) return true;
@@ -1592,7 +1654,7 @@ function listSourceFiles(cwd, extensions) {
1592
1654
  continue;
1593
1655
  }
1594
1656
  for (const entry of entries) {
1595
- const full = join12(dir, entry.name);
1657
+ const full = join13(dir, entry.name);
1596
1658
  if (entry.isDirectory()) {
1597
1659
  if (!SKIP_DIRECTORIES.has(entry.name)) queue.push(full);
1598
1660
  continue;
@@ -1684,8 +1746,8 @@ function writesWhenRewritten(name, command) {
1684
1746
  var CHECK_SCRIPT_NAMES = /* @__PURE__ */ new Set(["lint", "format", "check", "test", "typecheck", "verify"]);
1685
1747
 
1686
1748
  // src/roles/format/inherited-ignores.ts
1687
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
1688
- import { join as join13 } from "path";
1749
+ import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
1750
+ import { join as join14 } from "path";
1689
1751
  var ROOT_IGNORE_FILE = ".prettierignore";
1690
1752
  function isPattern(line) {
1691
1753
  const trimmed = line.trim();
@@ -1700,11 +1762,11 @@ function toModulePattern(pattern) {
1700
1762
  }
1701
1763
  function inheritedIgnorePatterns(workspaceRoot) {
1702
1764
  if (!workspaceRoot) return [];
1703
- const path = join13(workspaceRoot, ROOT_IGNORE_FILE);
1704
- if (!existsSync12(path)) return [];
1765
+ const path = join14(workspaceRoot, ROOT_IGNORE_FILE);
1766
+ if (!existsSync13(path)) return [];
1705
1767
  let contents;
1706
1768
  try {
1707
- contents = readFileSync9(path, "utf8");
1769
+ contents = readFileSync10(path, "utf8");
1708
1770
  } catch {
1709
1771
  return [];
1710
1772
  }
@@ -1791,13 +1853,13 @@ function formatPresetFor(preset) {
1791
1853
  }
1792
1854
 
1793
1855
  // src/roles/format/prettier-config.ts
1794
- import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
1795
- import { join as join15 } from "path";
1856
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
1857
+ import { join as join16 } from "path";
1796
1858
 
1797
1859
  // src/roles/format/resolve-oxfmt.ts
1798
- import { readFileSync as readFileSync10 } from "fs";
1860
+ import { readFileSync as readFileSync11 } from "fs";
1799
1861
  import { createRequire as createRequire2 } from "module";
1800
- import { dirname as dirname4, join as join14 } from "path";
1862
+ import { dirname as dirname4, join as join15 } from "path";
1801
1863
  function resolveOxfmt(cwd) {
1802
1864
  return resolveBin(cwd, "oxfmt") ?? binFromOwnInstall("oxfmt", "oxfmt");
1803
1865
  }
@@ -1826,8 +1888,8 @@ function configSchema() {
1826
1888
  function readConfigSchema() {
1827
1889
  try {
1828
1890
  const manifest = createRequire2(import.meta.url).resolve("oxfmt/package.json");
1829
- const schemaPath = join14(dirname4(manifest), "configuration_schema.json");
1830
- return JSON.parse(readFileSync10(schemaPath, "utf8"));
1891
+ const schemaPath = join15(dirname4(manifest), "configuration_schema.json");
1892
+ return JSON.parse(readFileSync11(schemaPath, "utf8"));
1831
1893
  } catch {
1832
1894
  return void 0;
1833
1895
  }
@@ -1858,14 +1920,14 @@ function toOxfmtOverrides(value) {
1858
1920
  return { overrides, unresolved };
1859
1921
  }
1860
1922
  function readPrettierSettings(cwd) {
1861
- const file = PRETTIER_CONFIG_FILES.find((name) => existsSync13(join15(cwd, name)));
1923
+ const file = PRETTIER_CONFIG_FILES.find((name) => existsSync14(join16(cwd, name)));
1862
1924
  if (!file) return { options: {}, unresolved: [] };
1863
1925
  if (/\.(js|cjs|mjs)$/.test(file)) {
1864
1926
  return { options: {}, file, unresolved: [`${file} is JavaScript, so it was not executed`] };
1865
1927
  }
1866
1928
  let parsed;
1867
1929
  try {
1868
- parsed = parseJsonc(readFileSync11(join15(cwd, file), "utf8"), file);
1930
+ parsed = parseJsonc(readFileSync12(join16(cwd, file), "utf8"), file);
1869
1931
  } catch {
1870
1932
  return { options: {}, file, unresolved: [`${file} could not be parsed`] };
1871
1933
  }
@@ -1895,8 +1957,8 @@ function readPrettierSettings(cwd) {
1895
1957
  }
1896
1958
 
1897
1959
  // src/roles/format/read-adoption.ts
1898
- import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
1899
- import { join as join16 } from "path";
1960
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
1961
+ import { join as join17 } from "path";
1900
1962
  var NOT_ADOPTED2 = (configFile, unreadable = null) => ({
1901
1963
  configFile,
1902
1964
  preset: null,
@@ -1912,11 +1974,11 @@ function sameValue(a, b) {
1912
1974
  return JSON.stringify(a) === JSON.stringify(b);
1913
1975
  }
1914
1976
  function readFormatAdoption(cwd) {
1915
- const path = join16(cwd, FORMAT_CONFIG_FILE);
1916
- if (!existsSync14(path)) return NOT_ADOPTED2(null);
1977
+ const path = join17(cwd, FORMAT_CONFIG_FILE);
1978
+ if (!existsSync15(path)) return NOT_ADOPTED2(null);
1917
1979
  let parsed;
1918
1980
  try {
1919
- parsed = parseJsonc(readFileSync12(path, "utf8"), FORMAT_CONFIG_FILE);
1981
+ parsed = parseJsonc(readFileSync13(path, "utf8"), FORMAT_CONFIG_FILE);
1920
1982
  } catch (error) {
1921
1983
  const reason = error instanceof Error ? error.message : String(error);
1922
1984
  return NOT_ADOPTED2(FORMAT_CONFIG_FILE, `${FORMAT_CONFIG_FILE} could not be parsed (${reason})`);
@@ -2041,7 +2103,7 @@ var OxfmtAdapter = class extends BaseAdapter {
2041
2103
  manifestOperation(context.cwd, this.formatScripts(context.cwd))
2042
2104
  ];
2043
2105
  const prettierConfigs = PRETTIER_CONFIG_FILES.filter(
2044
- (name) => existsSync15(join17(context.cwd, name))
2106
+ (name) => existsSync16(join18(context.cwd, name))
2045
2107
  );
2046
2108
  for (const name of prettierConfigs) operations.push({ kind: "delete", path: name });
2047
2109
  const removableDeps = this.modulePrettierDependencies(context.cwd);
@@ -2281,7 +2343,7 @@ var OxfmtAdapter = class extends BaseAdapter {
2281
2343
  modulePrettierDependencies(cwd) {
2282
2344
  const isPrettierPackage = (name) => name === "prettier" || name.startsWith("prettier-plugin-") || name.startsWith("@prettier/");
2283
2345
  try {
2284
- const manifest = JSON.parse(readFileSync13(join17(cwd, "package.json"), "utf8"));
2346
+ const manifest = JSON.parse(readFileSync14(join18(cwd, "package.json"), "utf8"));
2285
2347
  return Object.keys(manifest.devDependencies ?? {}).filter(isPrettierPackage).map((name) => ["devDependencies", name]);
2286
2348
  } catch {
2287
2349
  return [];
@@ -2363,8 +2425,8 @@ function registerFormat() {
2363
2425
 
2364
2426
  // src/roles/lint/adapters/oxlint/oxlint.adapter.ts
2365
2427
  import { spawnSync as spawnSync4 } from "child_process";
2366
- import { existsSync as existsSync23, readFileSync as readFileSync21, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2367
- import { join as join27 } from "path";
2428
+ import { existsSync as existsSync24, readFileSync as readFileSync22, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2429
+ import { join as join28 } from "path";
2368
2430
 
2369
2431
  // src/core/config/deferred-rules.ts
2370
2432
  function deferredRuleNames(rules) {
@@ -2373,7 +2435,7 @@ function deferredRuleNames(rules) {
2373
2435
 
2374
2436
  // src/core/fix-report.ts
2375
2437
  import { statSync as statSync2 } from "fs";
2376
- import { join as join18 } from "path";
2438
+ import { join as join19 } from "path";
2377
2439
  var CONFIG_REFUSED = /failed to parse .*config|invalid config file/i;
2378
2440
  function readFailure(output) {
2379
2441
  const lines = output.split("\n").map((line2) => line2.trim());
@@ -2393,7 +2455,7 @@ function fingerprint(path) {
2393
2455
  function snapshotFiles(cwd, extensions) {
2394
2456
  const snapshot = /* @__PURE__ */ new Map();
2395
2457
  for (const file of listSourceFiles(cwd, extensions)) {
2396
- const mark = fingerprint(join18(cwd, file));
2458
+ const mark = fingerprint(join19(cwd, file));
2397
2459
  if (mark !== void 0) snapshot.set(file, mark);
2398
2460
  }
2399
2461
  return snapshot;
@@ -2401,7 +2463,7 @@ function snapshotFiles(cwd, extensions) {
2401
2463
  function changedSince(cwd, before, extensions) {
2402
2464
  const changed = [];
2403
2465
  for (const file of listSourceFiles(cwd, extensions)) {
2404
- const now = fingerprint(join18(cwd, file));
2466
+ const now = fingerprint(join19(cwd, file));
2405
2467
  if (now === void 0) continue;
2406
2468
  if (before.get(file) !== now) changed.push(file);
2407
2469
  }
@@ -2420,8 +2482,8 @@ function describeFixOutcome(outcome, toolLabel) {
2420
2482
  }
2421
2483
 
2422
2484
  // src/roles/lint/module-baseline.ts
2423
- import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
2424
- import { join as join19 } from "path";
2485
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
2486
+ import { join as join20 } from "path";
2425
2487
  var LINT_BASELINE_FILE = ".oxlintrc.baseline.json";
2426
2488
  var LINT_MEASURE_FILE = ".oxlintrc.measure.json";
2427
2489
  var LINT_BASELINE_SPECIFIER = `./${LINT_BASELINE_FILE}`;
@@ -2465,11 +2527,11 @@ function describeHolds(holds) {
2465
2527
  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`;
2466
2528
  }
2467
2529
  function heldRules(cwd) {
2468
- const path = join19(cwd, LINT_BASELINE_FILE);
2469
- if (!existsSync16(path)) return [];
2530
+ const path = join20(cwd, LINT_BASELINE_FILE);
2531
+ if (!existsSync17(path)) return [];
2470
2532
  try {
2471
2533
  const parsed = parseJsonc(
2472
- readFileSync14(path, "utf8"),
2534
+ readFileSync15(path, "utf8"),
2473
2535
  LINT_BASELINE_FILE
2474
2536
  );
2475
2537
  return Object.keys(parsed.rules ?? {});
@@ -4295,14 +4357,14 @@ function downgradedRulesFor(preset) {
4295
4357
  }
4296
4358
 
4297
4359
  // src/roles/lint/extra-layers.ts
4298
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
4299
- import { isAbsolute as isAbsolute2, join as join20, resolve as resolve3 } from "path";
4360
+ import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
4361
+ import { isAbsolute as isAbsolute2, join as join21, resolve as resolve3 } from "path";
4300
4362
  function ruleCount(cwd, specifier) {
4301
4363
  const path = isAbsolute2(specifier) ? specifier : resolve3(cwd, specifier);
4302
- if (!existsSync17(path)) return void 0;
4364
+ if (!existsSync18(path)) return void 0;
4303
4365
  try {
4304
4366
  const parsed = parseJsonc(
4305
- readFileSync15(path, "utf8"),
4367
+ readFileSync16(path, "utf8"),
4306
4368
  specifier
4307
4369
  );
4308
4370
  return Object.keys(parsed.rules ?? {}).length;
@@ -4322,7 +4384,7 @@ function extraLayers(cwd, extendsList) {
4322
4384
  function committedExtendsList(cwd, configFile) {
4323
4385
  try {
4324
4386
  const parsed = parseJsonc(
4325
- readFileSync15(join20(cwd, configFile), "utf8"),
4387
+ readFileSync16(join21(cwd, configFile), "utf8"),
4326
4388
  configFile
4327
4389
  );
4328
4390
  return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
@@ -4381,8 +4443,8 @@ function errorCountsByConfigRule(stdout) {
4381
4443
  }
4382
4444
 
4383
4445
  // src/core/config/read-adoption.ts
4384
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
4385
- import { join as join22 } from "path";
4446
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
4447
+ import { join as join23 } from "path";
4386
4448
 
4387
4449
  // src/core/config/owned-keys.ts
4388
4450
  function presetOwnedKeys(config, permitted, presetSets) {
@@ -4397,12 +4459,12 @@ function localOnlyKeys(config, permitted, presetSets) {
4397
4459
  }
4398
4460
 
4399
4461
  // src/core/config/resolve-config-target.ts
4400
- import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
4401
- import { join as join21 } from "path";
4462
+ import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
4463
+ import { join as join22 } from "path";
4402
4464
  function readExtends(absolutePath) {
4403
4465
  let parsed;
4404
4466
  try {
4405
- parsed = parseJsonc(readFileSync16(absolutePath, "utf8"), absolutePath);
4467
+ parsed = parseJsonc(readFileSync17(absolutePath, "utf8"), absolutePath);
4406
4468
  } catch {
4407
4469
  return [];
4408
4470
  }
@@ -4416,8 +4478,8 @@ function resolveConfigTarget(moduleDir, { candidates, markers, fallback }) {
4416
4478
  let existing;
4417
4479
  let existingExtendsSomething = false;
4418
4480
  for (const candidate of candidates) {
4419
- const absolutePath = join21(moduleDir, candidate);
4420
- if (!existsSync18(absolutePath)) continue;
4481
+ const absolutePath = join22(moduleDir, candidate);
4482
+ if (!existsSync19(absolutePath)) continue;
4421
4483
  const chain = readExtends(absolutePath);
4422
4484
  if (existing === void 0) {
4423
4485
  existing = candidate;
@@ -4450,12 +4512,12 @@ var NOT_ADOPTED3 = (configFile, unreadable = null) => ({
4450
4512
  });
4451
4513
  function readAdoption(cwd, options) {
4452
4514
  const target = resolveConfigTarget(cwd, options);
4453
- if (target.reason === "none" || !existsSync19(join22(cwd, target.path))) {
4515
+ if (target.reason === "none" || !existsSync20(join23(cwd, target.path))) {
4454
4516
  return NOT_ADOPTED3(target.reason === "none" ? null : target.path);
4455
4517
  }
4456
4518
  let parsed;
4457
4519
  try {
4458
- parsed = parseJsonc(readFileSync17(join22(cwd, target.path), "utf8"), target.path);
4520
+ parsed = parseJsonc(readFileSync18(join23(cwd, target.path), "utf8"), target.path);
4459
4521
  } catch (error) {
4460
4522
  const reason = error instanceof Error ? error.message : String(error);
4461
4523
  return NOT_ADOPTED3(target.path, `${target.path} could not be parsed (${reason})`);
@@ -4489,9 +4551,9 @@ function readLintAdoption(cwd) {
4489
4551
  }
4490
4552
 
4491
4553
  // src/roles/lint/resolve-oxlint.ts
4492
- import { existsSync as existsSync20 } from "fs";
4554
+ import { existsSync as existsSync21 } from "fs";
4493
4555
  import { createRequire as createRequire3 } from "module";
4494
- import { delimiter as delimiter2, dirname as dirname5, join as join23 } from "path";
4556
+ import { delimiter as delimiter2, dirname as dirname5, join as join24 } from "path";
4495
4557
  import { fileURLToPath as fileURLToPath2 } from "url";
4496
4558
  var PACKAGE_OF = {
4497
4559
  oxlint: "oxlint",
@@ -4516,30 +4578,30 @@ function tsgolintShim(cwd) {
4516
4578
  for (const owner of ["oxlint-tsgolint", "oxlint"]) {
4517
4579
  try {
4518
4580
  const packageDir = dirname5(require3.resolve(`${owner}/package.json`));
4519
- candidates.push(join23(packageDir, "node_modules", ".bin", "tsgolint"));
4520
- candidates.push(join23(packageDir, "..", ".bin", "tsgolint"));
4581
+ candidates.push(join24(packageDir, "node_modules", ".bin", "tsgolint"));
4582
+ candidates.push(join24(packageDir, "..", ".bin", "tsgolint"));
4521
4583
  } catch {
4522
4584
  }
4523
4585
  }
4524
4586
  try {
4525
4587
  const ownRoot = dirname5(require3.resolve("@hublo/sentinel/package.json"));
4526
- candidates.push(join23(ownRoot, "node_modules", ".bin", "tsgolint"));
4588
+ candidates.push(join24(ownRoot, "node_modules", ".bin", "tsgolint"));
4527
4589
  } catch {
4528
4590
  candidates.push(resolveBin(dirname5(fileURLToPath2(import.meta.url)), "tsgolint") ?? "");
4529
4591
  }
4530
- return candidates.find((candidate) => candidate !== "" && existsSync20(candidate));
4592
+ return candidates.find((candidate) => candidate !== "" && existsSync21(candidate));
4531
4593
  }
4532
4594
  function oxlintSearchPath(cwd) {
4533
4595
  return binSearchPath(cwd);
4534
4596
  }
4535
4597
 
4536
4598
  // src/roles/lint/adapters/oxlint/plan.ts
4537
- import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
4538
- import { join as join26 } from "path";
4599
+ import { existsSync as existsSync23, readFileSync as readFileSync21 } from "fs";
4600
+ import { join as join27 } from "path";
4539
4601
 
4540
4602
  // src/roles/lint/eslint-ignores.ts
4541
- import { existsSync as existsSync21, readFileSync as readFileSync18 } from "fs";
4542
- import { join as join24 } from "path";
4603
+ import { existsSync as existsSync22, readFileSync as readFileSync19 } from "fs";
4604
+ import { join as join25 } from "path";
4543
4605
  import { parseSync as parseSync2 } from "oxc-parser";
4544
4606
  var OPAQUE_SOURCE = /\b(includeIgnoreFile)\s*\([^)]*\)/g;
4545
4607
  function toOxlintPattern(pattern) {
@@ -4551,11 +4613,11 @@ function readRootEslintIgnores(root) {
4551
4613
  return { patterns: patterns.filter((pattern) => pattern.startsWith("**/")), unresolved };
4552
4614
  }
4553
4615
  function readEslintIgnores(cwd) {
4554
- const config = ESLINT_CONFIG_FILES.map((name) => join24(cwd, name)).find((path) => existsSync21(path));
4616
+ const config = ESLINT_CONFIG_FILES.map((name) => join25(cwd, name)).find((path) => existsSync22(path));
4555
4617
  if (!config) return { patterns: [], unresolved: [] };
4556
4618
  let source;
4557
4619
  try {
4558
- source = readFileSync18(config, "utf8");
4620
+ source = readFileSync19(config, "utf8");
4559
4621
  } catch {
4560
4622
  return { patterns: [], unresolved: [] };
4561
4623
  }
@@ -4656,8 +4718,8 @@ function lintPresetFor(preset) {
4656
4718
  }
4657
4719
 
4658
4720
  // src/roles/lint/rename-suppressions.ts
4659
- import { readdirSync as readdirSync2, readFileSync as readFileSync19, statSync as statSync3 } from "fs";
4660
- import { join as join25, relative as relative4 } from "path";
4721
+ import { readdirSync as readdirSync2, readFileSync as readFileSync20, statSync as statSync3 } from "fs";
4722
+ import { join as join26, relative as relative4 } from "path";
4661
4723
  var SOURCE_EXTENSIONS = [
4662
4724
  ".ts",
4663
4725
  ".tsx",
@@ -4704,7 +4766,7 @@ function* sourceFiles(dir) {
4704
4766
  return;
4705
4767
  }
4706
4768
  for (const entry of entries) {
4707
- const full = join25(dir, entry);
4769
+ const full = join26(dir, entry);
4708
4770
  let isDirectory;
4709
4771
  try {
4710
4772
  isDirectory = statSync3(full).isDirectory();
@@ -4724,7 +4786,7 @@ function findSuppressionRenames(cwd, renames) {
4724
4786
  for (const file of sourceFiles(cwd)) {
4725
4787
  let content;
4726
4788
  try {
4727
- content = readFileSync19(file, "utf8");
4789
+ content = readFileSync20(file, "utf8");
4728
4790
  } catch {
4729
4791
  continue;
4730
4792
  }
@@ -4852,7 +4914,7 @@ function plan2(context) {
4852
4914
  keys: removableDeps
4853
4915
  });
4854
4916
  }
4855
- const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync22(join26(context.cwd, name)));
4917
+ const eslintConfigs = ESLINT_CONFIG_FILES.filter((name) => existsSync23(join27(context.cwd, name)));
4856
4918
  for (const name of eslintConfigs) operations.push({ kind: "delete", path: name });
4857
4919
  operations.push(
4858
4920
  ...nxTargetOperations({
@@ -4950,7 +5012,7 @@ function lintScripts(cwd) {
4950
5012
  function committedExtends(cwd) {
4951
5013
  try {
4952
5014
  const parsed = parseJsonc(
4953
- readFileSync20(join26(cwd, LINT_CONFIG_FILE), "utf8"),
5015
+ readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
4954
5016
  LINT_CONFIG_FILE
4955
5017
  );
4956
5018
  return Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : [];
@@ -4961,7 +5023,7 @@ function committedExtends(cwd) {
4961
5023
  function committedIgnorePatterns(cwd) {
4962
5024
  try {
4963
5025
  const parsed = parseJsonc(
4964
- readFileSync20(join26(cwd, LINT_CONFIG_FILE), "utf8"),
5026
+ readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
4965
5027
  LINT_CONFIG_FILE
4966
5028
  );
4967
5029
  return Array.isArray(parsed.ignorePatterns) ? parsed.ignorePatterns.filter((entry) => typeof entry === "string") : [];
@@ -4973,7 +5035,7 @@ function moduleEslintDependencies(cwd) {
4973
5035
  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/");
4974
5036
  let manifest;
4975
5037
  try {
4976
- manifest = JSON.parse(readFileSync20(join26(cwd, "package.json"), "utf8"));
5038
+ manifest = JSON.parse(readFileSync21(join27(cwd, "package.json"), "utf8"));
4977
5039
  } catch {
4978
5040
  return [];
4979
5041
  }
@@ -5107,20 +5169,20 @@ ${result.stderr ?? ""}`);
5107
5169
  * build the developer can see, rather than a silent half-adoption they cannot.
5108
5170
  */
5109
5171
  writeModuleBaseline(ctx, oxlint, env) {
5110
- const configPath = join27(ctx.cwd, LINT_CONFIG_FILE);
5111
- const baselinePath = join27(ctx.cwd, LINT_BASELINE_FILE);
5112
- if (!existsSync23(configPath)) return;
5172
+ const configPath = join28(ctx.cwd, LINT_CONFIG_FILE);
5173
+ const baselinePath = join28(ctx.cwd, LINT_BASELINE_FILE);
5174
+ if (!existsSync24(configPath)) return;
5113
5175
  let config;
5114
5176
  try {
5115
5177
  config = parseJsonc(
5116
- readFileSync21(configPath, "utf8"),
5178
+ readFileSync22(configPath, "utf8"),
5117
5179
  LINT_CONFIG_FILE
5118
5180
  );
5119
5181
  } catch {
5120
5182
  return;
5121
5183
  }
5122
5184
  const current = Array.isArray(config.extends) ? config.extends : [];
5123
- const measurePath = join27(ctx.cwd, LINT_MEASURE_FILE);
5185
+ const measurePath = join28(ctx.cwd, LINT_MEASURE_FILE);
5124
5186
  let measured;
5125
5187
  try {
5126
5188
  writeFileSync3(
@@ -5168,7 +5230,7 @@ ${result.stderr ?? ""}`);
5168
5230
  }
5169
5231
  }
5170
5232
  async run(ctx) {
5171
- if (!existsSync23(join27(ctx.cwd, LINT_CONFIG_FILE))) {
5233
+ if (!existsSync24(join28(ctx.cwd, LINT_CONFIG_FILE))) {
5172
5234
  process.stderr.write(
5173
5235
  `sentinel lint(oxlint): no ${LINT_CONFIG_FILE} in this module; run \`sentinel --init --lint\` to adopt.
5174
5236
  `
@@ -5316,7 +5378,7 @@ ${result.stderr ?? ""}`);
5316
5378
  let stub;
5317
5379
  try {
5318
5380
  stub = parseJsonc(
5319
- readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
5381
+ readFileSync22(join28(cwd, LINT_CONFIG_FILE), "utf8"),
5320
5382
  LINT_CONFIG_FILE
5321
5383
  );
5322
5384
  } catch {
@@ -5326,7 +5388,7 @@ ${result.stderr ?? ""}`);
5326
5388
  for (const entry of stub.extends ?? []) {
5327
5389
  try {
5328
5390
  const preset = parseJsonc(
5329
- readFileSync21(join27(cwd, entry), "utf8"),
5391
+ readFileSync22(join28(cwd, entry), "utf8"),
5330
5392
  entry
5331
5393
  );
5332
5394
  for (const rule of Object.keys(preset.rules ?? {})) names.add(rule);
@@ -5396,14 +5458,14 @@ ${result.stderr ?? ""}`);
5396
5458
  let parsed;
5397
5459
  try {
5398
5460
  parsed = parseJsonc(
5399
- readFileSync21(join27(cwd, LINT_CONFIG_FILE), "utf8"),
5461
+ readFileSync22(join28(cwd, LINT_CONFIG_FILE), "utf8"),
5400
5462
  LINT_CONFIG_FILE
5401
5463
  );
5402
5464
  } catch {
5403
5465
  return void 0;
5404
5466
  }
5405
5467
  const targets = Array.isArray(parsed.extends) ? parsed.extends.filter((entry) => typeof entry === "string") : typeof parsed.extends === "string" ? [parsed.extends] : [];
5406
- return targets.find((target) => !existsSync23(join27(cwd, target)));
5468
+ return targets.find((target) => !existsSync24(join28(cwd, target)));
5407
5469
  }
5408
5470
  /** Announce what is not enforced, so reduced coverage is never silent. */
5409
5471
  announceDisabled(preset) {
@@ -5435,9 +5497,9 @@ function registerLint() {
5435
5497
 
5436
5498
  // src/roles/typescript/adapters/tsc/tsc.adapter.ts
5437
5499
  import { spawnSync as spawnSync5 } from "child_process";
5438
- import { existsSync as existsSync24, readFileSync as readFileSync23 } from "fs";
5500
+ import { existsSync as existsSync25, readFileSync as readFileSync24 } from "fs";
5439
5501
  import { createRequire as createRequire4 } from "module";
5440
- import { join as join29 } from "path";
5502
+ import { join as join30 } from "path";
5441
5503
 
5442
5504
  // src/roles/typescript/presets/nest.json
5443
5505
  var nest_default2 = {
@@ -5618,8 +5680,8 @@ function readTsconfigAdoption(cwd) {
5618
5680
  }
5619
5681
 
5620
5682
  // src/roles/typescript/adapters/tsc/plan.ts
5621
- import { readFileSync as readFileSync22 } from "fs";
5622
- import { join as join28 } from "path";
5683
+ import { readFileSync as readFileSync23 } from "fs";
5684
+ import { join as join29 } from "path";
5623
5685
 
5624
5686
  // src/roles/typescript/typecheck-script.ts
5625
5687
  var SENTINEL_TYPECHECK_COMMAND = "sentinel --run --typescript";
@@ -5712,7 +5774,7 @@ function planAdoption(context) {
5712
5774
  };
5713
5775
  }
5714
5776
  const existing = parseJsonc(
5715
- readFileSync22(join28(context.cwd, target.path), "utf8"),
5777
+ readFileSync23(join29(context.cwd, target.path), "utf8"),
5716
5778
  target.path
5717
5779
  );
5718
5780
  const extendsChain = composeExtends(existing.extends, preset);
@@ -5850,7 +5912,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5850
5912
  let chain;
5851
5913
  try {
5852
5914
  const parsed = parseJsonc(
5853
- readFileSync23(join29(cwd, target.path), "utf8"),
5915
+ readFileSync24(join30(cwd, target.path), "utf8"),
5854
5916
  target.path
5855
5917
  );
5856
5918
  chain = parsed.extends;
@@ -5863,7 +5925,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5863
5925
  );
5864
5926
  if (preset === void 0) return void 0;
5865
5927
  try {
5866
- createRequire4(join29(cwd, "noop.js")).resolve(preset);
5928
+ createRequire4(join30(cwd, "noop.js")).resolve(preset);
5867
5929
  return void 0;
5868
5930
  } catch {
5869
5931
  return preset;
@@ -5959,7 +6021,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5959
6021
  referencedProjects(cwd, config) {
5960
6022
  try {
5961
6023
  const parsed = parseJsonc(
5962
- readFileSync23(join29(cwd, config), "utf8"),
6024
+ readFileSync24(join30(cwd, config), "utf8"),
5963
6025
  config
5964
6026
  );
5965
6027
  const referenced = (parsed.references ?? []).map((reference) => reference.path).filter((path) => typeof path === "string" && path.length > 0);
@@ -5975,7 +6037,7 @@ var TscAdapter = class _TscAdapter extends BaseAdapter {
5975
6037
  * check.
5976
6038
  */
5977
6039
  typecheckTarget(cwd) {
5978
- if (existsSync24(join29(cwd, "tsconfig.json"))) return "tsconfig.json";
6040
+ if (existsSync25(join30(cwd, "tsconfig.json"))) return "tsconfig.json";
5979
6041
  const target = resolveTsconfigTarget(cwd);
5980
6042
  return target.reason === "none" ? null : target.path;
5981
6043
  }
@@ -6179,7 +6241,7 @@ function replaceLines(current, replacements) {
6179
6241
  }
6180
6242
 
6181
6243
  // src/core/apply-plan.ts
6182
- import { existsSync as existsSync25, readFileSync as readFileSync24, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
6244
+ import { existsSync as existsSync26, readFileSync as readFileSync25, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
6183
6245
  import { resolve as resolve4, sep } from "path";
6184
6246
  import { applyEdits, findNodeAtLocation, modify, parseTree } from "jsonc-parser";
6185
6247
 
@@ -6198,7 +6260,7 @@ function resolveWithinRoot(cwd, relativePath) {
6198
6260
  return absolutePath;
6199
6261
  }
6200
6262
  function readIfExists(absolutePath) {
6201
- return existsSync25(absolutePath) ? readFileSync24(absolutePath, "utf8") : void 0;
6263
+ return existsSync26(absolutePath) ? readFileSync25(absolutePath, "utf8") : void 0;
6202
6264
  }
6203
6265
  function* leaves(value, prefix = []) {
6204
6266
  for (const [key, keyValue] of Object.entries(value)) {
@@ -6316,8 +6378,8 @@ function applyPlan(cwd, plan3) {
6316
6378
  }
6317
6379
 
6318
6380
  // src/core/config/preset-evidence.ts
6319
- import { existsSync as existsSync26, readdirSync as readdirSync3, readFileSync as readFileSync25 } from "fs";
6320
- import { join as join30 } from "path";
6381
+ import { existsSync as existsSync27, readdirSync as readdirSync3, readFileSync as readFileSync26 } from "fs";
6382
+ import { join as join31 } from "path";
6321
6383
  var PATH_SIGNALS = [
6322
6384
  {
6323
6385
  preset: "nest",
@@ -6331,11 +6393,11 @@ var DEPENDENCY_SIGNALS = [
6331
6393
  { preset: "nest", pattern: /^@nestjs\// }
6332
6394
  ];
6333
6395
  function dependencyNames(cwd) {
6334
- const path = join30(cwd, "package.json");
6335
- if (!existsSync26(path)) return [];
6396
+ const path = join31(cwd, "package.json");
6397
+ if (!existsSync27(path)) return [];
6336
6398
  try {
6337
6399
  const manifest = parseJsonc(
6338
- readFileSync25(path, "utf8"),
6400
+ readFileSync26(path, "utf8"),
6339
6401
  path
6340
6402
  );
6341
6403
  return [
@@ -6358,7 +6420,7 @@ function declaresJsx(cwd) {
6358
6420
  for (const name of entries) {
6359
6421
  try {
6360
6422
  const config = parseJsonc(
6361
- readFileSync25(join30(cwd, name), "utf8"),
6423
+ readFileSync26(join31(cwd, name), "utf8"),
6362
6424
  name
6363
6425
  );
6364
6426
  if (config.compilerOptions?.jsx !== void 0) return true;
@@ -6538,4 +6600,4 @@ export {
6538
6600
  detectFramework,
6539
6601
  dispatch
6540
6602
  };
6541
- //# sourceMappingURL=chunk-YBJLWNTQ.js.map
6603
+ //# sourceMappingURL=chunk-ORPLAWRT.js.map
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  registerAdapters,
8
8
  resolve,
9
9
  setDefaultRunner
10
- } from "./chunk-YBJLWNTQ.js";
10
+ } from "./chunk-ORPLAWRT.js";
11
11
  export {
12
12
  BaseAdapter,
13
13
  all,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hublo/sentinel",
3
- "version": "1.2.0-alpha.23",
3
+ "version": "1.2.0-alpha.24",
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",