@yawlabs/ctxlint 0.19.0 → 0.20.0

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/dist/index.js CHANGED
@@ -1330,8 +1330,8 @@ var require_semaphore = __commonJS({
1330
1330
  this._waiting = [];
1331
1331
  }
1332
1332
  lock(thunk) {
1333
- return new Promise((resolve18, reject) => {
1334
- this._waiting.push({ thunk, resolve: resolve18, reject });
1333
+ return new Promise((resolve19, reject) => {
1334
+ this._waiting.push({ thunk, resolve: resolve19, reject });
1335
1335
  this.runNext();
1336
1336
  });
1337
1337
  }
@@ -2960,9 +2960,9 @@ ${JSON.stringify(message, null, 4)}`);
2960
2960
  if (typeof cancellationStrategy.sender.enableCancellation === "function") {
2961
2961
  cancellationStrategy.sender.enableCancellation(requestMessage);
2962
2962
  }
2963
- return new Promise(async (resolve18, reject) => {
2963
+ return new Promise(async (resolve19, reject) => {
2964
2964
  const resolveWithCleanup = (r2) => {
2965
- resolve18(r2);
2965
+ resolve19(r2);
2966
2966
  cancellationStrategy.sender.cleanup(id);
2967
2967
  disposable?.dispose();
2968
2968
  };
@@ -8089,7 +8089,7 @@ var require_server = __commonJS({
8089
8089
  exports.createConnection = createConnection2;
8090
8090
  var vscode_languageserver_protocol_1 = require_api2();
8091
8091
  var Is3 = __importStar(require_is());
8092
- var UUID = __importStar(require_uuid());
8092
+ var UUID2 = __importStar(require_uuid());
8093
8093
  var progress_1 = require_progress();
8094
8094
  var configuration_1 = require_configuration();
8095
8095
  var workspaceFolder_1 = require_workspaceFolder();
@@ -8231,7 +8231,7 @@ var require_server = __commonJS({
8231
8231
  if (this._registered.has(method)) {
8232
8232
  throw new Error(`${method} is already added to this registration`);
8233
8233
  }
8234
- const id = UUID.generateUuid();
8234
+ const id = UUID2.generateUuid();
8235
8235
  this._registrations.push({
8236
8236
  id,
8237
8237
  method,
@@ -8325,7 +8325,7 @@ var require_server = __commonJS({
8325
8325
  }
8326
8326
  registerSingle1(unregistration, type, registerOptions) {
8327
8327
  const method = Is3.string(type) ? type : type.method;
8328
- const id = UUID.generateUuid();
8328
+ const id = UUID2.generateUuid();
8329
8329
  const params = {
8330
8330
  registrations: [{ id, method, registerOptions: registerOptions || {} }]
8331
8331
  };
@@ -8342,7 +8342,7 @@ var require_server = __commonJS({
8342
8342
  }
8343
8343
  registerSingle2(type, registerOptions) {
8344
8344
  const method = Is3.string(type) ? type : type.method;
8345
- const id = UUID.generateUuid();
8345
+ const id = UUID2.generateUuid();
8346
8346
  const params = {
8347
8347
  registrations: [{ id, method, registerOptions: registerOptions || {} }]
8348
8348
  };
@@ -8590,8 +8590,8 @@ var require_server = __commonJS({
8590
8590
  if (value instanceof Promise) {
8591
8591
  return value;
8592
8592
  } else if (Is3.thenable(value)) {
8593
- return new Promise((resolve18, reject) => {
8594
- value.then((resolved) => resolve18(resolved), (error52) => reject(error52));
8593
+ return new Promise((resolve19, reject) => {
8594
+ value.then((resolved) => resolve19(resolved), (error52) => reject(error52));
8595
8595
  });
8596
8596
  } else {
8597
8597
  return Promise.resolve(value);
@@ -8873,13 +8873,13 @@ var require_files = __commonJS({
8873
8873
  Object.defineProperty(exports, "__esModule", { value: true });
8874
8874
  exports.FileSystem = void 0;
8875
8875
  exports.uriToFilePath = uriToFilePath;
8876
- exports.resolve = resolve18;
8876
+ exports.resolve = resolve19;
8877
8877
  exports.resolveGlobalNodePath = resolveGlobalNodePath;
8878
8878
  exports.resolveGlobalYarnPath = resolveGlobalYarnPath;
8879
8879
  exports.resolveModulePath = resolveModulePath;
8880
8880
  var url2 = __importStar(__require("url"));
8881
- var path20 = __importStar(__require("path"));
8882
- var fs15 = __importStar(__require("fs"));
8881
+ var path21 = __importStar(__require("path"));
8882
+ var fs16 = __importStar(__require("fs"));
8883
8883
  var child_process_1 = __require("child_process");
8884
8884
  function uriToFilePath(uri) {
8885
8885
  const parsed = url2.parse(uri);
@@ -8897,12 +8897,12 @@ var require_files = __commonJS({
8897
8897
  segments.shift();
8898
8898
  }
8899
8899
  }
8900
- return path20.normalize(segments.join("/"));
8900
+ return path21.normalize(segments.join("/"));
8901
8901
  }
8902
8902
  function isWindows() {
8903
8903
  return process.platform === "win32";
8904
8904
  }
8905
- function resolve18(moduleName, nodePath, cwd, tracer) {
8905
+ function resolve19(moduleName, nodePath, cwd, tracer) {
8906
8906
  const nodePathKey = "NODE_PATH";
8907
8907
  const app = [
8908
8908
  "var p = process;",
@@ -8921,13 +8921,13 @@ var require_files = __commonJS({
8921
8921
  "}",
8922
8922
  "});"
8923
8923
  ].join("");
8924
- return new Promise((resolve19, reject) => {
8924
+ return new Promise((resolve20, reject) => {
8925
8925
  const env2 = process.env;
8926
8926
  const newEnv = /* @__PURE__ */ Object.create(null);
8927
8927
  Object.keys(env2).forEach((key) => newEnv[key] = env2[key]);
8928
- if (nodePath && fs15.existsSync(nodePath)) {
8928
+ if (nodePath && fs16.existsSync(nodePath)) {
8929
8929
  if (newEnv[nodePathKey]) {
8930
- newEnv[nodePathKey] = nodePath + path20.delimiter + newEnv[nodePathKey];
8930
+ newEnv[nodePathKey] = nodePath + path21.delimiter + newEnv[nodePathKey];
8931
8931
  } else {
8932
8932
  newEnv[nodePathKey] = nodePath;
8933
8933
  }
@@ -8953,7 +8953,7 @@ var require_files = __commonJS({
8953
8953
  if (message2.c === "r") {
8954
8954
  cp.send({ c: "e" });
8955
8955
  if (message2.s) {
8956
- resolve19(message2.r);
8956
+ resolve20(message2.r);
8957
8957
  } else {
8958
8958
  reject(new Error(`Failed to resolve module: ${moduleName}`));
8959
8959
  }
@@ -8999,9 +8999,9 @@ var require_files = __commonJS({
8999
8999
  }
9000
9000
  if (prefix.length > 0) {
9001
9001
  if (isWindows()) {
9002
- return path20.join(prefix, "node_modules");
9002
+ return path21.join(prefix, "node_modules");
9003
9003
  } else {
9004
- return path20.join(prefix, "lib", "node_modules");
9004
+ return path21.join(prefix, "lib", "node_modules");
9005
9005
  }
9006
9006
  }
9007
9007
  return void 0;
@@ -9040,7 +9040,7 @@ var require_files = __commonJS({
9040
9040
  try {
9041
9041
  const yarn = JSON.parse(line);
9042
9042
  if (yarn.type === "log") {
9043
- return path20.join(yarn.data, "node_modules");
9043
+ return path21.join(yarn.data, "node_modules");
9044
9044
  }
9045
9045
  } catch (e) {
9046
9046
  }
@@ -9062,36 +9062,36 @@ var require_files = __commonJS({
9062
9062
  if (process.platform === "win32") {
9063
9063
  _isCaseSensitive = false;
9064
9064
  } else {
9065
- _isCaseSensitive = !fs15.existsSync(__filename.toUpperCase()) || !fs15.existsSync(__filename.toLowerCase());
9065
+ _isCaseSensitive = !fs16.existsSync(__filename.toUpperCase()) || !fs16.existsSync(__filename.toLowerCase());
9066
9066
  }
9067
9067
  return _isCaseSensitive;
9068
9068
  }
9069
9069
  FileSystem2.isCaseSensitive = isCaseSensitive;
9070
9070
  function isParent(parent, child) {
9071
9071
  if (isCaseSensitive()) {
9072
- return path20.normalize(child).indexOf(path20.normalize(parent)) === 0;
9072
+ return path21.normalize(child).indexOf(path21.normalize(parent)) === 0;
9073
9073
  } else {
9074
- return path20.normalize(child).toLowerCase().indexOf(path20.normalize(parent).toLowerCase()) === 0;
9074
+ return path21.normalize(child).toLowerCase().indexOf(path21.normalize(parent).toLowerCase()) === 0;
9075
9075
  }
9076
9076
  }
9077
9077
  FileSystem2.isParent = isParent;
9078
9078
  })(FileSystem || (exports.FileSystem = FileSystem = {}));
9079
9079
  function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) {
9080
9080
  if (nodePath) {
9081
- if (!path20.isAbsolute(nodePath)) {
9082
- nodePath = path20.join(workspaceRoot, nodePath);
9081
+ if (!path21.isAbsolute(nodePath)) {
9082
+ nodePath = path21.join(workspaceRoot, nodePath);
9083
9083
  }
9084
- return resolve18(moduleName, nodePath, nodePath, tracer).then((value) => {
9084
+ return resolve19(moduleName, nodePath, nodePath, tracer).then((value) => {
9085
9085
  if (FileSystem.isParent(nodePath, value)) {
9086
9086
  return value;
9087
9087
  } else {
9088
9088
  return Promise.reject(new Error(`Failed to load ${moduleName} from node path location.`));
9089
9089
  }
9090
9090
  }).then(void 0, (_error) => {
9091
- return resolve18(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
9091
+ return resolve19(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
9092
9092
  });
9093
9093
  } else {
9094
- return resolve18(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
9094
+ return resolve19(moduleName, resolveGlobalNodePath(tracer), workspaceRoot, tracer);
9095
9095
  }
9096
9096
  }
9097
9097
  }
@@ -9174,10 +9174,10 @@ var require_ril = __commonJS({
9174
9174
  return api_1.Disposable.create(() => this.stream.off("end", listener));
9175
9175
  }
9176
9176
  write(data, encoding) {
9177
- return new Promise((resolve18, reject) => {
9177
+ return new Promise((resolve19, reject) => {
9178
9178
  const callback = (error52) => {
9179
9179
  if (error52 === void 0 || error52 === null) {
9180
- resolve18();
9180
+ resolve19();
9181
9181
  } else {
9182
9182
  reject(error52);
9183
9183
  }
@@ -9314,9 +9314,9 @@ var require_main = __commonJS({
9314
9314
  exports.createMessageConnection = createMessageConnection;
9315
9315
  var ril_1 = __importDefault(require_ril());
9316
9316
  ril_1.default.install();
9317
- var path20 = __importStar(__require("path"));
9317
+ var path21 = __importStar(__require("path"));
9318
9318
  var os7 = __importStar(__require("os"));
9319
- var fs15 = __importStar(__require("fs"));
9319
+ var fs16 = __importStar(__require("fs"));
9320
9320
  var crypto_1 = __require("crypto");
9321
9321
  var net_1 = __require("net");
9322
9322
  var api_1 = require_api();
@@ -9457,7 +9457,7 @@ var require_main = __commonJS({
9457
9457
  }
9458
9458
  let randomLength = 32;
9459
9459
  const fixedLength = "/lsp-.sock".length;
9460
- const tmpDir = fs15.realpathSync(XDG_RUNTIME_DIR ?? os7.tmpdir());
9460
+ const tmpDir = fs16.realpathSync(XDG_RUNTIME_DIR ?? os7.tmpdir());
9461
9461
  const limit = safeIpcPathLengths.get(process.platform);
9462
9462
  if (limit !== void 0) {
9463
9463
  randomLength = Math.min(limit - tmpDir.length - fixedLength, randomLength);
@@ -9466,14 +9466,14 @@ var require_main = __commonJS({
9466
9466
  throw new Error(`Unable to generate a random pipe name with ${randomLength} characters.`);
9467
9467
  }
9468
9468
  const randomSuffix = (0, crypto_1.randomBytes)(Math.floor(randomLength / 2)).toString("hex");
9469
- return path20.join(tmpDir, `lsp-${randomSuffix}.sock`);
9469
+ return path21.join(tmpDir, `lsp-${randomSuffix}.sock`);
9470
9470
  }
9471
9471
  function createClientPipeTransport(pipeName, encoding = "utf-8") {
9472
9472
  let connectResolve;
9473
- const connected = new Promise((resolve18, _reject) => {
9474
- connectResolve = resolve18;
9473
+ const connected = new Promise((resolve19, _reject) => {
9474
+ connectResolve = resolve19;
9475
9475
  });
9476
- return new Promise((resolve18, reject) => {
9476
+ return new Promise((resolve19, reject) => {
9477
9477
  const server2 = (0, net_1.createServer)((socket) => {
9478
9478
  server2.close();
9479
9479
  connectResolve([
@@ -9484,7 +9484,7 @@ var require_main = __commonJS({
9484
9484
  server2.on("error", reject);
9485
9485
  server2.listen(pipeName, () => {
9486
9486
  server2.removeListener("error", reject);
9487
- resolve18({
9487
+ resolve19({
9488
9488
  onConnected: () => {
9489
9489
  return connected;
9490
9490
  }
@@ -9501,10 +9501,10 @@ var require_main = __commonJS({
9501
9501
  }
9502
9502
  function createClientSocketTransport(port, encoding = "utf-8") {
9503
9503
  let connectResolve;
9504
- const connected = new Promise((resolve18, _reject) => {
9505
- connectResolve = resolve18;
9504
+ const connected = new Promise((resolve19, _reject) => {
9505
+ connectResolve = resolve19;
9506
9506
  });
9507
- return new Promise((resolve18, reject) => {
9507
+ return new Promise((resolve19, reject) => {
9508
9508
  const server2 = (0, net_1.createServer)((socket) => {
9509
9509
  server2.close();
9510
9510
  connectResolve([
@@ -9515,7 +9515,7 @@ var require_main = __commonJS({
9515
9515
  server2.on("error", reject);
9516
9516
  server2.listen(port, "127.0.0.1", () => {
9517
9517
  server2.removeListener("error", reject);
9518
- resolve18({
9518
+ resolve19({
9519
9519
  onConnected: () => {
9520
9520
  return connected;
9521
9521
  }
@@ -14733,10 +14733,10 @@ var require_src2 = __commonJS({
14733
14733
  var fs_1 = __require("fs");
14734
14734
  var debug_1 = __importDefault(require_src());
14735
14735
  var log = debug_1.default("@kwsites/file-exists");
14736
- function check2(path20, isFile, isDirectory2) {
14737
- log(`checking %s`, path20);
14736
+ function check2(path21, isFile, isDirectory2) {
14737
+ log(`checking %s`, path21);
14738
14738
  try {
14739
- const stat3 = fs_1.statSync(path20);
14739
+ const stat3 = fs_1.statSync(path21);
14740
14740
  if (stat3.isFile() && isFile) {
14741
14741
  log(`[OK] path represents a file`);
14742
14742
  return true;
@@ -14756,8 +14756,8 @@ var require_src2 = __commonJS({
14756
14756
  throw e;
14757
14757
  }
14758
14758
  }
14759
- function exists2(path20, type = exports.READABLE) {
14760
- return check2(path20, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
14759
+ function exists2(path21, type = exports.READABLE) {
14760
+ return check2(path21, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
14761
14761
  }
14762
14762
  exports.exists = exists2;
14763
14763
  exports.FILE = 1;
@@ -15355,8 +15355,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
15355
15355
  function forEachLineWithContent(input, callback) {
15356
15356
  return toLinesWithContent(input, true).map((line) => callback(line));
15357
15357
  }
15358
- function folderExists(path20) {
15359
- return (0, import_file_exists.exists)(path20, import_file_exists.FOLDER);
15358
+ function folderExists(path21) {
15359
+ return (0, import_file_exists.exists)(path21, import_file_exists.FOLDER);
15360
15360
  }
15361
15361
  function append(target, item) {
15362
15362
  if (Array.isArray(target)) {
@@ -15547,8 +15547,8 @@ function checkIsRepoRootTask() {
15547
15547
  commands,
15548
15548
  format: "utf-8",
15549
15549
  onError,
15550
- parser(path20) {
15551
- return /^\.(git)?$/.test(path20.trim());
15550
+ parser(path21) {
15551
+ return /^\.(git)?$/.test(path21.trim());
15552
15552
  }
15553
15553
  };
15554
15554
  }
@@ -15804,11 +15804,11 @@ function parseGrep(grep) {
15804
15804
  const paths = /* @__PURE__ */ new Set();
15805
15805
  const results = {};
15806
15806
  forEachLineWithContent(grep, (input) => {
15807
- const [path20, line, preview] = input.split(NULL);
15808
- paths.add(path20);
15809
- (results[path20] = results[path20] || []).push({
15807
+ const [path21, line, preview] = input.split(NULL);
15808
+ paths.add(path21);
15809
+ (results[path21] = results[path21] || []).push({
15810
15810
  line: asNumber(line),
15811
- path: path20,
15811
+ path: path21,
15812
15812
  preview
15813
15813
  });
15814
15814
  });
@@ -16105,14 +16105,14 @@ function hashObjectTask(filePath, write) {
16105
16105
  }
16106
16106
  return straightThroughStringTask(commands, true);
16107
16107
  }
16108
- function parseInit(bare, path20, text) {
16108
+ function parseInit(bare, path21, text) {
16109
16109
  const response = String(text).trim();
16110
16110
  let result;
16111
16111
  if (result = initResponseRegex.exec(response)) {
16112
- return new InitSummary(bare, path20, false, result[1]);
16112
+ return new InitSummary(bare, path21, false, result[1]);
16113
16113
  }
16114
16114
  if (result = reInitResponseRegex.exec(response)) {
16115
- return new InitSummary(bare, path20, true, result[1]);
16115
+ return new InitSummary(bare, path21, true, result[1]);
16116
16116
  }
16117
16117
  let gitDir = "";
16118
16118
  const tokens = response.split(" ");
@@ -16123,12 +16123,12 @@ function parseInit(bare, path20, text) {
16123
16123
  break;
16124
16124
  }
16125
16125
  }
16126
- return new InitSummary(bare, path20, /^re/i.test(response), gitDir);
16126
+ return new InitSummary(bare, path21, /^re/i.test(response), gitDir);
16127
16127
  }
16128
16128
  function hasBareCommand(command) {
16129
16129
  return command.includes(bareCommand);
16130
16130
  }
16131
- function initTask(bare = false, path20, customArgs) {
16131
+ function initTask(bare = false, path21, customArgs) {
16132
16132
  const commands = ["init", ...customArgs];
16133
16133
  if (bare && !hasBareCommand(commands)) {
16134
16134
  commands.splice(1, 0, bareCommand);
@@ -16137,7 +16137,7 @@ function initTask(bare = false, path20, customArgs) {
16137
16137
  commands,
16138
16138
  format: "utf-8",
16139
16139
  parser(text) {
16140
- return parseInit(commands.includes("--bare"), path20, text);
16140
+ return parseInit(commands.includes("--bare"), path21, text);
16141
16141
  }
16142
16142
  };
16143
16143
  }
@@ -16416,14 +16416,14 @@ function splitLine(result, lineStr) {
16416
16416
  default:
16417
16417
  return;
16418
16418
  }
16419
- function data(index, workingDir, path20) {
16419
+ function data(index, workingDir, path21) {
16420
16420
  const raw = `${index}${workingDir}`;
16421
16421
  const handler = parsers6.get(raw);
16422
16422
  if (handler) {
16423
- handler(result, path20);
16423
+ handler(result, path21);
16424
16424
  }
16425
16425
  if (raw !== "##" && raw !== "!!") {
16426
- result.files.push(new FileStatusSummary(path20, index, workingDir));
16426
+ result.files.push(new FileStatusSummary(path21, index, workingDir));
16427
16427
  }
16428
16428
  }
16429
16429
  }
@@ -16610,8 +16610,8 @@ function deleteBranchTask(branch, forceDelete = false) {
16610
16610
  return task;
16611
16611
  }
16612
16612
  function toPath(input) {
16613
- const path20 = input.trim().replace(/^["']|["']$/g, "");
16614
- return path20 && normalize2(path20);
16613
+ const path21 = input.trim().replace(/^["']|["']$/g, "");
16614
+ return path21 && normalize2(path21);
16615
16615
  }
16616
16616
  function checkIgnoreTask(paths) {
16617
16617
  return {
@@ -16750,8 +16750,8 @@ function stashListTask(opt = {}, customArgs) {
16750
16750
  parser: parser4
16751
16751
  };
16752
16752
  }
16753
- function addSubModuleTask(repo, path20) {
16754
- return subModuleTask(["add", repo, path20]);
16753
+ function addSubModuleTask(repo, path21) {
16754
+ return subModuleTask(["add", repo, path21]);
16755
16755
  }
16756
16756
  function initSubModuleTask(customArgs) {
16757
16757
  return subModuleTask(["init", ...customArgs]);
@@ -18014,9 +18014,9 @@ var init_esm = __esm({
18014
18014
  "src/lib/responses/InitSummary.ts"() {
18015
18015
  "use strict";
18016
18016
  InitSummary = class {
18017
- constructor(bare, path20, existing, gitDir) {
18017
+ constructor(bare, path21, existing, gitDir) {
18018
18018
  this.bare = bare;
18019
- this.path = path20;
18019
+ this.path = path21;
18020
18020
  this.existing = existing;
18021
18021
  this.gitDir = gitDir;
18022
18022
  }
@@ -18549,12 +18549,12 @@ var init_esm = __esm({
18549
18549
  "use strict";
18550
18550
  fromPathRegex = /^(.+)\0(.+)$/;
18551
18551
  FileStatusSummary = class {
18552
- constructor(path20, index, working_dir) {
18553
- this.path = path20;
18552
+ constructor(path21, index, working_dir) {
18553
+ this.path = path21;
18554
18554
  this.index = index;
18555
18555
  this.working_dir = working_dir;
18556
18556
  if (index === "R" || working_dir === "R") {
18557
- const detail = fromPathRegex.exec(path20) || [null, path20, path20];
18557
+ const detail = fromPathRegex.exec(path21) || [null, path21, path21];
18558
18558
  this.from = detail[2] || "";
18559
18559
  this.path = detail[1] || "";
18560
18560
  }
@@ -18816,9 +18816,9 @@ var init_esm = __esm({
18816
18816
  next
18817
18817
  );
18818
18818
  }
18819
- hashObject(path20, write) {
18819
+ hashObject(path21, write) {
18820
18820
  return this._runTask(
18821
- hashObjectTask(path20, write === true),
18821
+ hashObjectTask(path21, write === true),
18822
18822
  trailingFunctionArgument(arguments)
18823
18823
  );
18824
18824
  }
@@ -19455,8 +19455,8 @@ var init_esm = __esm({
19455
19455
  }
19456
19456
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
19457
19457
  };
19458
- Git2.prototype.submoduleAdd = function(repo, path20, then) {
19459
- return this._runTask(addSubModuleTask2(repo, path20), trailingFunctionArgument2(arguments));
19458
+ Git2.prototype.submoduleAdd = function(repo, path21, then) {
19459
+ return this._runTask(addSubModuleTask2(repo, path21), trailingFunctionArgument2(arguments));
19460
19460
  };
19461
19461
  Git2.prototype.submoduleUpdate = function(args2, then) {
19462
19462
  return this._runTask(
@@ -19772,7 +19772,7 @@ async function getCommitsSinceBatch(projectRoot, paths, since) {
19772
19772
  }
19773
19773
  try {
19774
19774
  const git = getGit(projectRoot);
19775
- const SENTINEL = "___CTXLINT_COMMIT___";
19775
+ const SENTINEL2 = "___CTXLINT_COMMIT___";
19776
19776
  const pathspecs = [];
19777
19777
  for (const p2 of paths) {
19778
19778
  const spec = toGitPathspec(p2, projectRoot);
@@ -19791,7 +19791,7 @@ async function getCommitsSinceBatch(projectRoot, paths, since) {
19791
19791
  // %n emits a newline; prefixing with a valid format placeholder is
19792
19792
  // what keeps git from rejecting the sentinel as an invalid --pretty
19793
19793
  // format ("fatal: invalid --pretty format: ___CTXLINT_COMMIT___").
19794
- `--format=%n${SENTINEL}`
19794
+ `--format=%n${SENTINEL2}`
19795
19795
  ];
19796
19796
  if (pathspecs.length > 0) {
19797
19797
  logArgs.push("--", ...pathspecs);
@@ -19808,7 +19808,7 @@ async function getCommitsSinceBatch(projectRoot, paths, since) {
19808
19808
  seenThisCommit.clear();
19809
19809
  };
19810
19810
  for (const line of lines) {
19811
- if (line === SENTINEL) {
19811
+ if (line === SENTINEL2) {
19812
19812
  if (inCommit) flush();
19813
19813
  inCommit = true;
19814
19814
  continue;
@@ -21258,12 +21258,12 @@ function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
21258
21258
  }
21259
21259
  return result;
21260
21260
  }
21261
- function findNodeAtLocation(root, path20) {
21261
+ function findNodeAtLocation(root, path21) {
21262
21262
  if (!root) {
21263
21263
  return void 0;
21264
21264
  }
21265
21265
  let node = root;
21266
- for (let segment of path20) {
21266
+ for (let segment of path21) {
21267
21267
  if (typeof segment === "string") {
21268
21268
  if (node.type !== "object" || !Array.isArray(node.children)) {
21269
21269
  return void 0;
@@ -21760,9 +21760,495 @@ var init_main3 = __esm({
21760
21760
  }
21761
21761
  });
21762
21762
 
21763
- // src/core/checks/commands.ts
21763
+ // src/core/checks/exit-status.ts
21764
+ function splitSegments(cmd) {
21765
+ const out = [];
21766
+ let buf = "";
21767
+ let op = "";
21768
+ let quote = null;
21769
+ for (let i2 = 0; i2 < cmd.length; i2++) {
21770
+ const ch = cmd[i2];
21771
+ if (quote) {
21772
+ buf += ch;
21773
+ if (ch === "\\" && quote !== "'") {
21774
+ if (i2 + 1 < cmd.length) buf += cmd[++i2];
21775
+ continue;
21776
+ }
21777
+ if (ch === quote) quote = null;
21778
+ continue;
21779
+ }
21780
+ if (ch === '"' || ch === "'" || ch === "`") {
21781
+ quote = ch;
21782
+ buf += ch;
21783
+ continue;
21784
+ }
21785
+ if (ch === "\\" && i2 + 1 < cmd.length) {
21786
+ buf += ch + cmd[++i2];
21787
+ continue;
21788
+ }
21789
+ if (ch === "&" && cmd[i2 + 1] === "&") {
21790
+ out.push({ op, text: buf.trim() });
21791
+ op = "&&";
21792
+ buf = "";
21793
+ i2++;
21794
+ continue;
21795
+ }
21796
+ if (ch === "|" && cmd[i2 + 1] === "|") {
21797
+ out.push({ op, text: buf.trim() });
21798
+ op = "||";
21799
+ buf = "";
21800
+ i2++;
21801
+ continue;
21802
+ }
21803
+ if (ch === ";") {
21804
+ out.push({ op, text: buf.trim() });
21805
+ op = ";";
21806
+ buf = "";
21807
+ continue;
21808
+ }
21809
+ buf += ch;
21810
+ }
21811
+ out.push({ op, text: buf.trim() });
21812
+ return out.filter((s) => s.text.length > 0);
21813
+ }
21814
+ function splitPipes(segment) {
21815
+ const out = [];
21816
+ let buf = "";
21817
+ let quote = null;
21818
+ for (let i2 = 0; i2 < segment.length; i2++) {
21819
+ const ch = segment[i2];
21820
+ if (quote) {
21821
+ buf += ch;
21822
+ if (ch === "\\" && quote !== "'") {
21823
+ if (i2 + 1 < segment.length) buf += segment[++i2];
21824
+ continue;
21825
+ }
21826
+ if (ch === quote) quote = null;
21827
+ continue;
21828
+ }
21829
+ if (ch === '"' || ch === "'" || ch === "`") {
21830
+ quote = ch;
21831
+ buf += ch;
21832
+ continue;
21833
+ }
21834
+ if (ch === "\\" && i2 + 1 < segment.length) {
21835
+ buf += ch + segment[++i2];
21836
+ continue;
21837
+ }
21838
+ if (ch === "|") {
21839
+ out.push(buf.trim());
21840
+ buf = "";
21841
+ continue;
21842
+ }
21843
+ buf += ch;
21844
+ }
21845
+ out.push(buf.trim());
21846
+ return out.map((s) => s.trim());
21847
+ }
21848
+ function unwrap(part) {
21849
+ let s = part.trim();
21850
+ s = s.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=(?:"[^"]*"|'[^']*'|\S*)\s+)+/, "");
21851
+ const execMatch = s.match(EXEC_WRAPPER_PATTERN);
21852
+ if (execMatch) s = s.slice(execMatch[0].length).trim();
21853
+ while (WRAPPER_PATTERN.test(s)) {
21854
+ const tokens = s.split(/\s+/).slice(1);
21855
+ let i2 = 0;
21856
+ while (i2 < tokens.length && tokens[i2].startsWith("-")) {
21857
+ if (tokens[i2] === "-p" || tokens[i2] === "--package") i2++;
21858
+ i2++;
21859
+ }
21860
+ const next = tokens.slice(i2).join(" ");
21861
+ if (!next || next === s) break;
21862
+ s = next;
21863
+ }
21864
+ return s.trim();
21865
+ }
21866
+ function verifierName(part, scripts) {
21867
+ const s = unwrap(part);
21868
+ if (!s) return null;
21869
+ for (const re2 of VERIFIER_PAIRS) {
21870
+ const m = s.match(re2);
21871
+ if (m) return m[0].replace(/\s+/g, " ");
21872
+ }
21873
+ const direct = s.match(VERIFIER_PATTERN);
21874
+ if (direct) return direct[1];
21875
+ const scriptName = (s.match(SCRIPT_RUNNER) ?? s.match(SCRIPT_SHORTHAND))?.[1];
21876
+ if (scriptName && scripts) {
21877
+ const body = scripts[scriptName];
21878
+ if (typeof body === "string") {
21879
+ const first2 = splitPipes(splitSegments(body)[0]?.text ?? "")[0] ?? "";
21880
+ const inner = unwrap(first2);
21881
+ for (const re2 of VERIFIER_PAIRS) {
21882
+ const m = inner.match(re2);
21883
+ if (m) return m[0].replace(/\s+/g, " ");
21884
+ }
21885
+ const d = inner.match(VERIFIER_PATTERN);
21886
+ if (d) return d[1];
21887
+ }
21888
+ }
21889
+ return null;
21890
+ }
21891
+ function filterName(part) {
21892
+ const m = unwrap(part).match(FILTER_PATTERN);
21893
+ return m ? m[1] : null;
21894
+ }
21895
+ function isSuccessClaim(segment) {
21896
+ if (!/^(echo|printf)\b/.test(unwrap(segment))) return false;
21897
+ return SUCCESS_WORD.test(segment);
21898
+ }
21899
+ function isStatusEcho(segment) {
21900
+ if (!/^(echo|printf)\b/.test(unwrap(segment))) return false;
21901
+ if (/PIPESTATUS/.test(segment)) return false;
21902
+ return /\$\?/.test(segment);
21903
+ }
21904
+ function analyzeMaskedExitStatus(cmd, scripts) {
21905
+ const segments = splitSegments(cmd);
21906
+ if (segments.length < 2) return null;
21907
+ for (let i2 = 0; i2 < segments.length - 1; i2++) {
21908
+ if (segments.slice(0, i2 + 1).some((s) => PIPEFAIL.test(s.text))) return null;
21909
+ const parts = splitPipes(segments[i2].text);
21910
+ if (parts.length < 2) continue;
21911
+ const verifier = verifierName(parts[0], scripts);
21912
+ if (!verifier) continue;
21913
+ const filter = filterName(parts[parts.length - 1]);
21914
+ if (!filter) continue;
21915
+ const next = segments[i2 + 1];
21916
+ if (next.op !== "&&" && next.op !== ";") continue;
21917
+ if (next.op === "&&" && isSuccessClaim(next.text)) {
21918
+ return { verifier, filter, claim: next.text, kind: "success-claim" };
21919
+ }
21920
+ if (isStatusEcho(next.text)) {
21921
+ return { verifier, filter, claim: next.text, kind: "status-echo" };
21922
+ }
21923
+ }
21924
+ return null;
21925
+ }
21926
+ function pipefailInScope(content, line) {
21927
+ const lines = content.split("\n");
21928
+ const idx = line - 1;
21929
+ if (idx < 0 || idx >= lines.length) return false;
21930
+ let fenceStart = -1;
21931
+ let open = false;
21932
+ for (let i2 = 0; i2 < idx; i2++) {
21933
+ if (/^\s*```/.test(lines[i2])) {
21934
+ open = !open;
21935
+ fenceStart = open ? i2 + 1 : -1;
21936
+ }
21937
+ }
21938
+ if (!open || fenceStart < 0) return false;
21939
+ for (let i2 = fenceStart; i2 < idx; i2++) {
21940
+ if (PIPEFAIL.test(lines[i2])) return true;
21941
+ }
21942
+ return false;
21943
+ }
21944
+ var VERIFIER_PATTERN, VERIFIER_PAIRS, FILTER_PATTERN, SCRIPT_RUNNER, SCRIPT_SHORTHAND, WRAPPER_PATTERN, EXEC_WRAPPER_PATTERN, SUCCESS_WORD, PIPEFAIL;
21945
+ var init_exit_status = __esm({
21946
+ "src/core/checks/exit-status.ts"() {
21947
+ "use strict";
21948
+ init_define_WEB_FIRST_SEGMENTS();
21949
+ VERIFIER_PATTERN = /^(tsc|eslint|biome|vitest|jest|pytest|mypy|ruff|oxlint)\b/;
21950
+ VERIFIER_PAIRS = [/^cargo\s+(test|clippy|check)\b/, /^go\s+(test|vet|build)\b/];
21951
+ FILTER_PATTERN = /^(head|tail|grep|egrep|fgrep|sed|awk|less|more|cat|tee|wc)\b/;
21952
+ SCRIPT_RUNNER = /^(?:npm\s+run|(?:pnpm|yarn|bun)(?:\s+run)?)\s+(\S+)/;
21953
+ SCRIPT_SHORTHAND = /^(?:npm|pnpm|yarn|bun)\s+(test|start|build|dev|lint|format|check|typecheck|type-check|clean|serve|preview|e2e)\b/;
21954
+ WRAPPER_PATTERN = /^(npx|bunx|sudo|time|command|nice)\b/;
21955
+ EXEC_WRAPPER_PATTERN = /^(?:pnpm|npm|yarn|bun)\s+(?:exec|dlx)\b/;
21956
+ SUCCESS_WORD = /\b(ok|okay|clean|pass|passed|passes|passing|green|success|successful|done|all\s+good|no\s+errors|looks\s+good)\b/i;
21957
+ PIPEFAIL = /\bset\s+[-\w\s]*\bpipefail\b/;
21958
+ }
21959
+ });
21960
+
21961
+ // src/core/checks/cli-subcommands.ts
21764
21962
  import * as fs4 from "node:fs";
21765
21963
  import * as path5 from "node:path";
21964
+ function ownedBins(pkgJson) {
21965
+ if (!pkgJson || !pkgJson.bin) return [];
21966
+ const out = [];
21967
+ if (typeof pkgJson.bin === "string") {
21968
+ const raw = pkgJson.name ?? "";
21969
+ const name = raw.includes("/") ? raw.slice(raw.lastIndexOf("/") + 1) : raw;
21970
+ if (name) out.push({ name, entry: pkgJson.bin });
21971
+ return out;
21972
+ }
21973
+ for (const [name, entry] of Object.entries(pkgJson.bin)) {
21974
+ if (typeof entry === "string" && name) out.push({ name, entry });
21975
+ }
21976
+ return out;
21977
+ }
21978
+ function commandNameOf(token) {
21979
+ let t2 = token.trim().replace(/^["']|["']$/g, "");
21980
+ if (!t2) return null;
21981
+ const cut = Math.max(t2.lastIndexOf("/"), t2.lastIndexOf("\\"));
21982
+ if (cut >= 0) t2 = t2.slice(cut + 1);
21983
+ t2 = t2.replace(BIN_EXT, "");
21984
+ return t2 || null;
21985
+ }
21986
+ function resolveEntry(projectRoot, entry) {
21987
+ const base = path5.resolve(projectRoot, entry);
21988
+ const candidates = [base, `${base}.js`, `${base}.mjs`, `${base}.cjs`, `${base}.ts`];
21989
+ for (const c3 of candidates) {
21990
+ try {
21991
+ if (fs4.statSync(c3).isFile()) return c3;
21992
+ } catch {
21993
+ }
21994
+ }
21995
+ return null;
21996
+ }
21997
+ function readEntry(abs) {
21998
+ let src;
21999
+ try {
22000
+ const stat3 = fs4.statSync(abs);
22001
+ if (stat3.size > MAX_ENTRY_BYTES) return null;
22002
+ src = stripBom(fs4.readFileSync(abs, "utf-8"));
22003
+ } catch {
22004
+ return null;
22005
+ }
22006
+ for (const line of src.split("\n")) {
22007
+ if (line.length > MAX_ENTRY_LINE) return null;
22008
+ }
22009
+ return src;
22010
+ }
22011
+ function shimTarget(src) {
22012
+ const meaningful = src.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#!") && !l.startsWith("//") && !l.startsWith("*"));
22013
+ if (meaningful.length > 12) return null;
22014
+ const specs = /* @__PURE__ */ new Set();
22015
+ for (const m of src.matchAll(/(?:^|\s)(?:import|require)\s*\(?\s*['"](\.[^'"]+)['"]/g)) {
22016
+ specs.add(m[1]);
22017
+ }
22018
+ for (const m of src.matchAll(/^\s*import\s+[^'"]*from\s*['"](\.[^'"]+)['"]/gm)) {
22019
+ specs.add(m[1]);
22020
+ }
22021
+ return specs.size === 1 ? [...specs][0] : null;
22022
+ }
22023
+ function stripComments2(src) {
22024
+ let code = "";
22025
+ let literals = "";
22026
+ let i2 = 0;
22027
+ const push = (ch, inString) => {
22028
+ literals += ch;
22029
+ code += inString && ch !== "\n" ? " " : ch;
22030
+ };
22031
+ while (i2 < src.length) {
22032
+ const ch = src[i2];
22033
+ const next = src[i2 + 1];
22034
+ if (ch === "/" && next === "/") {
22035
+ while (i2 < src.length && src[i2] !== "\n") i2++;
22036
+ continue;
22037
+ }
22038
+ if (ch === "/" && next === "*") {
22039
+ i2 += 2;
22040
+ while (i2 < src.length && !(src[i2] === "*" && src[i2 + 1] === "/")) {
22041
+ if (src[i2] === "\n") push("\n", false);
22042
+ i2++;
22043
+ }
22044
+ i2 += 2;
22045
+ continue;
22046
+ }
22047
+ if (ch === '"' || ch === "'" || ch === "`") {
22048
+ const quote = ch;
22049
+ push(ch, false);
22050
+ i2++;
22051
+ while (i2 < src.length) {
22052
+ if (src[i2] === "\\") {
22053
+ push(src[i2], true);
22054
+ if (i2 + 1 < src.length) push(src[i2 + 1], true);
22055
+ i2 += 2;
22056
+ continue;
22057
+ }
22058
+ if (src[i2] === quote) break;
22059
+ push(src[i2], true);
22060
+ i2++;
22061
+ }
22062
+ if (i2 < src.length) push(src[i2], false);
22063
+ i2++;
22064
+ continue;
22065
+ }
22066
+ push(ch, false);
22067
+ i2++;
22068
+ }
22069
+ return { code, literals };
22070
+ }
22071
+ function commanderIsOpen(code) {
22072
+ return /\.command\(\s*[^'"`\s)]/.test(code);
22073
+ }
22074
+ function commanderSubcommands(code, literals) {
22075
+ if (commanderIsOpen(code)) return null;
22076
+ const found = /* @__PURE__ */ new Set();
22077
+ for (const m of literals.matchAll(/\.command\(\s*(['"`])([^'"`\n]+)\1/g)) {
22078
+ const name = m[2].trim().split(/\s+/)[0];
22079
+ if (name && !name.startsWith("<") && !name.startsWith("[")) found.add(name);
22080
+ }
22081
+ return found.size > 0 ? found : null;
22082
+ }
22083
+ function argvSubcommands(code, literals) {
22084
+ const aliases = /* @__PURE__ */ new Set();
22085
+ for (const m of code.matchAll(
22086
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:process\.)?argv\[2\]/g
22087
+ )) {
22088
+ aliases.add(m[1]);
22089
+ }
22090
+ for (const m of code.matchAll(
22091
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:process\.)?argv\.slice\(\s*2\s*\)\s*\[\s*0\s*\]/g
22092
+ )) {
22093
+ aliases.add(m[1]);
22094
+ }
22095
+ for (const m of code.matchAll(
22096
+ /\b(?:const|let|var)\s*\[\s*,\s*,\s*([A-Za-z_$][\w$]*)\s*\]\s*=\s*process\.argv/g
22097
+ )) {
22098
+ aliases.add(m[1]);
22099
+ }
22100
+ const tokens = [...aliases].map((a) => `\\b${a}\\b`);
22101
+ if (/(?:process\.)?argv\[2\]/.test(code)) tokens.push("(?:process\\.)?argv\\[2\\]");
22102
+ if (tokens.length === 0) return null;
22103
+ const tok = `(?:${tokens.join("|")})`;
22104
+ const cmpIdent = new RegExp(`${tok}\\s*[=!]==?\\s*([A-Za-z_$][\\w$.]*)`, "g");
22105
+ for (const m of code.matchAll(cmpIdent)) {
22106
+ if (!SENTINEL.test(m[1])) return null;
22107
+ }
22108
+ const identCmp = new RegExp(`([A-Za-z_$][\\w$.]*)\\s*[=!]==?\\s*${tok}`, "g");
22109
+ for (const m of code.matchAll(identCmp)) {
22110
+ if (!SENTINEL.test(m[1])) return null;
22111
+ }
22112
+ if (new RegExp(`\\[\\s*${tok}\\s*\\]`).test(code)) return null;
22113
+ if (new RegExp(`Object\\.(keys|values|entries)\\([^)]*\\)[^\\n]*${tok}`).test(code)) return null;
22114
+ if (new RegExp(`${tok}\\s+in\\s+`).test(code)) return null;
22115
+ if (new RegExp(`\\bhasOwnProperty\\(\\s*${tok}`).test(code)) return null;
22116
+ const includesRe = new RegExp(`(\\S*)\\.includes\\(\\s*${tok}\\s*\\)`, "g");
22117
+ for (const m of code.matchAll(includesRe)) {
22118
+ if (!m[1].endsWith("]")) return null;
22119
+ }
22120
+ const found = /* @__PURE__ */ new Set();
22121
+ const eqLit = new RegExp(`${tok}\\s*[=!]==?\\s*(['"\`])([^'"\`\\n]*)\\1`, "g");
22122
+ for (const m of literals.matchAll(eqLit)) if (m[2]) found.add(m[2]);
22123
+ const litEq = new RegExp(`(['"\`])([^'"\`\\n]*)\\1\\s*[=!]==?\\s*${tok}`, "g");
22124
+ for (const m of literals.matchAll(litEq)) if (m[2]) found.add(m[2]);
22125
+ const switchRe = new RegExp(`switch\\s*\\(\\s*${tok}\\s*\\)\\s*\\{`, "g");
22126
+ for (const m of literals.matchAll(switchRe)) {
22127
+ const body = literals.slice((m.index ?? 0) + m[0].length);
22128
+ const end = body.indexOf("\n}");
22129
+ const block = end >= 0 ? body.slice(0, end) : body;
22130
+ for (const c3 of block.matchAll(/\bcase\s+(['"`])([^'"`\n]*)\1/g)) {
22131
+ if (c3[2]) found.add(c3[2]);
22132
+ }
22133
+ }
22134
+ const arrIncludes = new RegExp(`\\[([^\\]\\n]*)\\]\\.includes\\(\\s*${tok}\\s*\\)`, "g");
22135
+ for (const m of literals.matchAll(arrIncludes)) {
22136
+ for (const lit of m[1].matchAll(/(['"`])([^'"`]*)\1/g)) {
22137
+ if (lit[2]) found.add(lit[2]);
22138
+ }
22139
+ }
22140
+ return found.size > 0 ? found : null;
22141
+ }
22142
+ function knownSubcommands(projectRoot, entry) {
22143
+ let abs = resolveEntry(projectRoot, entry);
22144
+ for (let hop = 0; abs && hop <= MAX_FOLLOW; hop++) {
22145
+ const src = readEntry(abs);
22146
+ if (src === null) return null;
22147
+ const { code, literals } = stripComments2(src);
22148
+ const commander = commanderSubcommands(code, literals);
22149
+ if (commander) return commander;
22150
+ if (commanderIsOpen(code)) return null;
22151
+ const argv = argvSubcommands(code, literals);
22152
+ if (argv) return argv;
22153
+ if (hop === MAX_FOLLOW) break;
22154
+ const target = shimTarget(src);
22155
+ if (!target) break;
22156
+ abs = resolveEntry(path5.dirname(abs), target);
22157
+ }
22158
+ return null;
22159
+ }
22160
+ function findBinInvocations(content, binNames) {
22161
+ if (binNames.size === 0) return [];
22162
+ const out = [];
22163
+ const lines = content.split("\n");
22164
+ let inFence = false;
22165
+ let fenceLang = "";
22166
+ let inHtmlComment = false;
22167
+ for (let i2 = 0; i2 < lines.length; i2++) {
22168
+ const line = lines[i2];
22169
+ const trimmed2 = line.trim();
22170
+ if (!inHtmlComment && trimmed2.includes("<!--")) {
22171
+ inHtmlComment = !trimmed2.includes("-->");
22172
+ continue;
22173
+ }
22174
+ if (inHtmlComment) {
22175
+ if (trimmed2.includes("-->")) inHtmlComment = false;
22176
+ continue;
22177
+ }
22178
+ if (trimmed2.startsWith("```")) {
22179
+ if (!inFence) {
22180
+ inFence = true;
22181
+ fenceLang = trimmed2.slice(3).trim().toLowerCase();
22182
+ } else {
22183
+ inFence = false;
22184
+ fenceLang = "";
22185
+ }
22186
+ continue;
22187
+ }
22188
+ const candidates = [];
22189
+ if (inFence) {
22190
+ if (["bash", "sh", "shell", "zsh", "console", ""].includes(fenceLang)) {
22191
+ if (trimmed2 && !trimmed2.startsWith("#") && !trimmed2.startsWith("//")) {
22192
+ candidates.push(trimmed2.replace(/^[$>]\s*/, ""));
22193
+ }
22194
+ }
22195
+ } else {
22196
+ if (/^[$>]\s+/.test(trimmed2)) candidates.push(trimmed2.replace(/^[$>]\s*/, ""));
22197
+ for (const m of line.matchAll(/`([^`]+)`/g)) candidates.push(m[1].trim());
22198
+ }
22199
+ for (const candidate of candidates) {
22200
+ const hit = matchBinInvocation(candidate, binNames);
22201
+ if (hit) out.push({ ...hit, cmd: candidate, line: i2 + 1 });
22202
+ }
22203
+ }
22204
+ return out;
22205
+ }
22206
+ function matchBinInvocation(candidate, binNames) {
22207
+ let s = candidate.trim();
22208
+ const stop = s.search(/&&|\|\||[;|]/);
22209
+ if (stop >= 0) s = s.slice(0, stop).trim();
22210
+ s = s.replace(TWO_TOKEN_DELEGATORS, "");
22211
+ let tokens = s.split(/\s+/).filter(Boolean);
22212
+ while (tokens.length > 0) {
22213
+ const head = commandNameOf(tokens[0]);
22214
+ if (head && DELEGATORS.has(head)) {
22215
+ tokens = tokens.slice(1);
22216
+ while (tokens.length > 0 && tokens[0].startsWith("-")) tokens = tokens.slice(1);
22217
+ continue;
22218
+ }
22219
+ break;
22220
+ }
22221
+ if (tokens.length < 2) return null;
22222
+ const bin = commandNameOf(tokens[0]);
22223
+ if (!bin || !binNames.has(bin)) return null;
22224
+ for (const raw of tokens.slice(1)) {
22225
+ if (raw.startsWith("-")) continue;
22226
+ const t2 = raw.replace(/^["']|["']$/g, "");
22227
+ if (!SUBCOMMAND_SHAPE.test(t2)) return null;
22228
+ return { bin, sub: t2 };
22229
+ }
22230
+ return null;
22231
+ }
22232
+ var BIN_EXT, MAX_ENTRY_BYTES, MAX_ENTRY_LINE, MAX_FOLLOW, SENTINEL, DELEGATORS, TWO_TOKEN_DELEGATORS, SUBCOMMAND_SHAPE;
22233
+ var init_cli_subcommands = __esm({
22234
+ "src/core/checks/cli-subcommands.ts"() {
22235
+ "use strict";
22236
+ init_define_WEB_FIRST_SEGMENTS();
22237
+ init_fs();
22238
+ BIN_EXT = /\.(exe|cmd|bat|ps1|js|mjs|cjs|ts)$/i;
22239
+ MAX_ENTRY_BYTES = 15e4;
22240
+ MAX_ENTRY_LINE = 500;
22241
+ MAX_FOLLOW = 1;
22242
+ SENTINEL = /^(undefined|null|NaN|void)$/;
22243
+ DELEGATORS = /* @__PURE__ */ new Set(["npx", "bunx", "sudo", "time"]);
22244
+ TWO_TOKEN_DELEGATORS = /^(?:pnpm|npm|yarn|bun)\s+(?:exec|dlx)\s+/;
22245
+ SUBCOMMAND_SHAPE = /^[a-z][a-z0-9:_-]*$/i;
22246
+ }
22247
+ });
22248
+
22249
+ // src/core/checks/commands.ts
22250
+ import * as fs5 from "node:fs";
22251
+ import * as path6 from "node:path";
21766
22252
  function isManagerBuiltin(manager, sub) {
21767
22253
  return PM_MANAGER_BUILTINS[manager]?.has(sub) ?? false;
21768
22254
  }
@@ -21803,7 +22289,7 @@ function loadDeniedCommandPrefixes(projectRoot) {
21803
22289
  for (const rel of ["settings.json", "settings.local.json"]) {
21804
22290
  let content;
21805
22291
  try {
21806
- content = stripBom(fs4.readFileSync(path5.join(projectRoot, ".claude", rel), "utf-8"));
22292
+ content = stripBom(fs5.readFileSync(path6.join(projectRoot, ".claude", rel), "utf-8"));
21807
22293
  } catch {
21808
22294
  continue;
21809
22295
  }
@@ -21840,8 +22326,21 @@ async function checkCommands(file2, projectRoot) {
21840
22326
  });
21841
22327
  }
21842
22328
  }
22329
+ issues.push(...checkUnknownSubcommand(file2, projectRoot, pkgJson));
21843
22330
  for (const ref of file2.references.commands) {
21844
22331
  const cmd = ref.value;
22332
+ const masked = analyzeMaskedExitStatus(cmd, pkgJson?.scripts);
22333
+ if (masked && !pipefailInScope(file2.content, ref.line)) {
22334
+ const why = masked.kind === "success-claim" ? "the success claim cannot fail" : "`$?` reports the filter, not the verifier";
22335
+ issues.push({
22336
+ severity: "warning",
22337
+ check: "commands",
22338
+ ruleId: "commands/exit-status-masked",
22339
+ line: ref.line,
22340
+ message: `"${cmd}" \u2014 exit status comes from "${masked.filter}", not "${masked.verifier}"; ${why}`,
22341
+ suggestion: "Add `set -o pipefail` before the pipeline, drop the filter, or read `${PIPESTATUS[0]}` instead of `$?`."
22342
+ });
22343
+ }
21845
22344
  const scriptMatch = cmd.match(NPM_SCRIPT_PATTERN);
21846
22345
  if (scriptMatch && pkgJson) {
21847
22346
  const scriptName = scriptNameFromMatch(scriptMatch);
@@ -21885,9 +22384,9 @@ async function checkCommands(file2, projectRoot) {
21885
22384
  };
21886
22385
  if (!(pkgName in allDeps)) {
21887
22386
  if (isDeniedCommand(cmd, deniedPrefixes)) continue;
21888
- const binPath = path5.join(projectRoot, "node_modules", ".bin", pkgName);
22387
+ const binPath = path6.join(projectRoot, "node_modules", ".bin", pkgName);
21889
22388
  try {
21890
- fs4.accessSync(binPath);
22389
+ fs5.accessSync(binPath);
21891
22390
  } catch {
21892
22391
  issues.push({
21893
22392
  severity: "warning",
@@ -21935,9 +22434,9 @@ async function checkCommands(file2, projectRoot) {
21935
22434
  ...pkgJson.optionalDependencies
21936
22435
  };
21937
22436
  if (!(pkgName in allDeps)) {
21938
- const binPath = path5.join(projectRoot, "node_modules", ".bin", tool);
22437
+ const binPath = path6.join(projectRoot, "node_modules", ".bin", tool);
21939
22438
  try {
21940
- fs4.accessSync(binPath);
22439
+ fs5.accessSync(binPath);
21941
22440
  } catch {
21942
22441
  issues.push({
21943
22442
  severity: "warning",
@@ -21952,9 +22451,36 @@ async function checkCommands(file2, projectRoot) {
21952
22451
  }
21953
22452
  return issues;
21954
22453
  }
22454
+ function checkUnknownSubcommand(file2, projectRoot, pkgJson) {
22455
+ const bins = ownedBins(pkgJson);
22456
+ if (bins.length === 0) return [];
22457
+ const invocations = findBinInvocations(file2.content, new Set(bins.map((b2) => b2.name)));
22458
+ if (invocations.length === 0) return [];
22459
+ const resolved = /* @__PURE__ */ new Map();
22460
+ const issues = [];
22461
+ for (const inv of invocations) {
22462
+ if (!resolved.has(inv.bin)) {
22463
+ const bin = bins.find((b2) => b2.name === inv.bin);
22464
+ resolved.set(inv.bin, bin ? knownSubcommands(projectRoot, bin.entry) : null);
22465
+ }
22466
+ const known = resolved.get(inv.bin);
22467
+ if (!known || known.size === 0) continue;
22468
+ if (known.has(inv.sub)) continue;
22469
+ const listed = [...known].sort().join(", ");
22470
+ issues.push({
22471
+ severity: "error",
22472
+ check: "commands",
22473
+ ruleId: "commands/unknown-subcommand",
22474
+ line: inv.line,
22475
+ message: `"${inv.cmd}" \u2014 "${inv.sub}" is not a subcommand of ${inv.bin} (known: ${listed})`,
22476
+ suggestion: `Use one of the subcommands ${inv.bin} implements, or remove the invocation.`
22477
+ });
22478
+ }
22479
+ return issues;
22480
+ }
21955
22481
  function loadMakefile(projectRoot) {
21956
22482
  try {
21957
- return stripBom(fs4.readFileSync(path5.join(projectRoot, "Makefile"), "utf-8"));
22483
+ return stripBom(fs5.readFileSync(path6.join(projectRoot, "Makefile"), "utf-8"));
21958
22484
  } catch {
21959
22485
  return null;
21960
22486
  }
@@ -21979,6 +22505,8 @@ var init_commands = __esm({
21979
22505
  init_define_WEB_FIRST_SEGMENTS();
21980
22506
  init_main3();
21981
22507
  init_fs();
22508
+ init_exit_status();
22509
+ init_cli_subcommands();
21982
22510
  NPM_SCRIPT_PATTERN = /^(?:npm\s+run|(pnpm|yarn|bun)(?:\s+(run))?)\s+(\S+)/;
21983
22511
  MAKE_PATTERN = /^make\s+\S/;
21984
22512
  PM_BUILTIN_SUBCOMMANDS = /* @__PURE__ */ new Set([
@@ -22052,13 +22580,13 @@ var init_commands = __esm({
22052
22580
  });
22053
22581
 
22054
22582
  // src/core/checks/staleness.ts
22055
- import * as path6 from "node:path";
22583
+ import * as path7 from "node:path";
22056
22584
  async function checkStaleness(file2, projectRoot) {
22057
22585
  const issues = [];
22058
22586
  if (!await isGitRepo(projectRoot)) {
22059
22587
  return issues;
22060
22588
  }
22061
- const relativePath = path6.relative(projectRoot, file2.filePath).replace(/\\/g, "/");
22589
+ const relativePath = path7.relative(projectRoot, file2.filePath).replace(/\\/g, "/");
22062
22590
  const lastModified = await getFileLastModified(projectRoot, relativePath);
22063
22591
  if (!lastModified || isNaN(lastModified.getTime())) {
22064
22592
  return issues;
@@ -22249,9 +22777,9 @@ var init_tokens2 = __esm({
22249
22777
  });
22250
22778
 
22251
22779
  // src/core/checks/tier-tokens.ts
22252
- import * as fs5 from "node:fs";
22780
+ import * as fs6 from "node:fs";
22253
22781
  import * as os2 from "node:os";
22254
- import * as path7 from "node:path";
22782
+ import * as path8 from "node:path";
22255
22783
  function hasFrontmatterList(content, field) {
22256
22784
  const lines = content.split("\n");
22257
22785
  if (lines[0]?.trim() !== "---") return false;
@@ -22321,7 +22849,7 @@ function computeSectionCosts(file2) {
22321
22849
  function fingerprintFiles(paths) {
22322
22850
  return paths.map((p2) => {
22323
22851
  try {
22324
- const st2 = fs5.statSync(p2);
22852
+ const st2 = fs6.statSync(p2);
22325
22853
  return `${st2.mtimeMs}:${st2.size}`;
22326
22854
  } catch {
22327
22855
  return "absent";
@@ -22330,11 +22858,11 @@ function fingerprintFiles(paths) {
22330
22858
  }
22331
22859
  function loadSettingsSources(projectRoot, includeGlobal) {
22332
22860
  const candidates = [
22333
- path7.join(projectRoot, ".claude", "settings.json"),
22334
- path7.join(projectRoot, ".claude", "settings.local.json")
22861
+ path8.join(projectRoot, ".claude", "settings.json"),
22862
+ path8.join(projectRoot, ".claude", "settings.local.json")
22335
22863
  ];
22336
22864
  if (includeGlobal) {
22337
- candidates.push(path7.join(os2.homedir(), ".claude", "settings.json"));
22865
+ candidates.push(path8.join(os2.homedir(), ".claude", "settings.json"));
22338
22866
  }
22339
22867
  const fingerprint = fingerprintFiles(candidates);
22340
22868
  if (settingsCache?.root === projectRoot && settingsCache.includeGlobal === includeGlobal && settingsCache.fingerprint === fingerprint) {
@@ -22344,7 +22872,7 @@ function loadSettingsSources(projectRoot, includeGlobal) {
22344
22872
  for (const p2 of candidates) {
22345
22873
  let content;
22346
22874
  try {
22347
- content = stripBom(fs5.readFileSync(p2, "utf-8"));
22875
+ content = stripBom(fs6.readFileSync(p2, "utf-8"));
22348
22876
  } catch {
22349
22877
  continue;
22350
22878
  }
@@ -22518,7 +23046,7 @@ var init_similarity = __esm({
22518
23046
  });
22519
23047
 
22520
23048
  // src/core/checks/redundancy.ts
22521
- import * as path8 from "node:path";
23049
+ import * as path9 from "node:path";
22522
23050
  function compilePatterns(allDeps) {
22523
23051
  const compiled = [];
22524
23052
  for (const [pkg, mentions] of Object.entries(PACKAGE_TECH_MAP)) {
@@ -22598,8 +23126,8 @@ async function checkRedundancy(file2, projectRoot) {
22598
23126
  );
22599
23127
  if (dirMatch) {
22600
23128
  const dir = dirMatch[1].replace(/[`"]/g, "");
22601
- const baseDir = dir.startsWith("./") || dir.startsWith("../") ? path8.dirname(file2.filePath) : projectRoot;
22602
- const fullPath = path8.resolve(baseDir, dir);
23129
+ const baseDir = dir.startsWith("./") || dir.startsWith("../") ? path9.dirname(file2.filePath) : projectRoot;
23130
+ const fullPath = path9.resolve(baseDir, dir);
22603
23131
  if (isDirectory(fullPath)) {
22604
23132
  issues.push({
22605
23133
  severity: "info",
@@ -23627,8 +24155,8 @@ var init_security = __esm({
23627
24155
  });
23628
24156
 
23629
24157
  // src/core/checks/mcp/commands.ts
23630
- import * as fs6 from "node:fs";
23631
- import * as path9 from "node:path";
24158
+ import * as fs7 from "node:fs";
24159
+ import * as path10 from "node:path";
23632
24160
  async function checkMcpCommands(config2, projectRoot) {
23633
24161
  const issues = [];
23634
24162
  if (config2.parseErrors.length > 0) return issues;
@@ -23645,7 +24173,7 @@ async function checkMcpCommands(config2, projectRoot) {
23645
24173
  });
23646
24174
  }
23647
24175
  if (config2.scope === "project" && LOCAL_PATH_PATTERN.test(server2.command)) {
23648
- const resolved = path9.resolve(projectRoot, server2.command);
24176
+ const resolved = path10.resolve(projectRoot, server2.command);
23649
24177
  if (!fileExistsSafe(resolved)) {
23650
24178
  issues.push({
23651
24179
  severity: "warning",
@@ -23660,8 +24188,8 @@ async function checkMcpCommands(config2, projectRoot) {
23660
24188
  for (const arg of server2.args) {
23661
24189
  if (URL_PREFIX.test(arg)) continue;
23662
24190
  if (!LOCAL_PATH_PATTERN.test(arg) && !FILE_PATH_PATTERN.test(arg)) continue;
23663
- if (config2.scope !== "project" && !path9.isAbsolute(arg)) continue;
23664
- const resolved = path9.resolve(projectRoot, arg);
24191
+ if (config2.scope !== "project" && !path10.isAbsolute(arg)) continue;
24192
+ const resolved = path10.resolve(projectRoot, arg);
23665
24193
  if (!fileExistsSafe(resolved)) {
23666
24194
  issues.push({
23667
24195
  severity: "warning",
@@ -23678,7 +24206,7 @@ async function checkMcpCommands(config2, projectRoot) {
23678
24206
  }
23679
24207
  function fileExistsSafe(filePath) {
23680
24208
  try {
23681
- fs6.accessSync(filePath);
24209
+ fs7.accessSync(filePath);
23682
24210
  return true;
23683
24211
  } catch {
23684
24212
  return false;
@@ -24109,16 +24637,16 @@ var init_redundancy2 = __esm({
24109
24637
 
24110
24638
  // src/core/session-parser.ts
24111
24639
  import { readFile } from "node:fs/promises";
24112
- import { readFileSync as readFileSync4 } from "node:fs";
24113
- import { dirname as dirname3, resolve as resolve6 } from "node:path";
24640
+ import { readFileSync as readFileSync5 } from "node:fs";
24641
+ import { dirname as dirname4, resolve as resolve7 } from "node:path";
24114
24642
  import { fileURLToPath } from "node:url";
24115
24643
  function loadWebFirstSegments() {
24116
24644
  if (typeof define_WEB_FIRST_SEGMENTS_default !== "undefined") {
24117
24645
  return new Set(define_WEB_FIRST_SEGMENTS_default);
24118
24646
  }
24119
- const __dir = dirname3(fileURLToPath(import.meta.url));
24120
- const fixturePath = resolve6(__dir, "../../tests/fixtures/web-first-segments.json");
24121
- const raw = JSON.parse(readFileSync4(fixturePath, "utf-8"));
24647
+ const __dir = dirname4(fileURLToPath(import.meta.url));
24648
+ const fixturePath = resolve7(__dir, "../../tests/fixtures/web-first-segments.json");
24649
+ const raw = JSON.parse(readFileSync5(fixturePath, "utf-8"));
24122
24650
  const list = Array.isArray(raw) ? raw : raw.segments;
24123
24651
  return new Set(list);
24124
24652
  }
@@ -24240,7 +24768,7 @@ import { readdir, stat } from "node:fs/promises";
24240
24768
  import { createReadStream } from "node:fs";
24241
24769
  import { homedir as homedir3 } from "node:os";
24242
24770
  import { createInterface } from "node:readline";
24243
- import { dirname as dirname4, join as join5, resolve as resolve7 } from "node:path";
24771
+ import { dirname as dirname5, join as join5, resolve as resolve8 } from "node:path";
24244
24772
  import { existsSync } from "node:fs";
24245
24773
  function detectProviders() {
24246
24774
  if (!home) return [];
@@ -24355,7 +24883,7 @@ async function mapWithConcurrency(items, limit, fn) {
24355
24883
  return results;
24356
24884
  }
24357
24885
  async function detectSiblings(projectRoot) {
24358
- const parentDir = dirname4(resolve7(projectRoot));
24886
+ const parentDir = dirname5(resolve8(projectRoot));
24359
24887
  let entries;
24360
24888
  try {
24361
24889
  entries = await readdir(parentDir);
@@ -24366,8 +24894,8 @@ async function detectSiblings(projectRoot) {
24366
24894
  for (const entry of entries) {
24367
24895
  if (entry.startsWith(".") || entry === "node_modules") continue;
24368
24896
  const fullPath = join5(parentDir, entry);
24369
- const entryPath = resolve7(fullPath);
24370
- if (entryPath === resolve7(projectRoot)) continue;
24897
+ const entryPath = resolve8(fullPath);
24898
+ if (entryPath === resolve8(projectRoot)) continue;
24371
24899
  try {
24372
24900
  const s = await stat(fullPath);
24373
24901
  if (!s.isDirectory()) continue;
@@ -24434,7 +24962,7 @@ async function scanSessionData(projectRoot) {
24434
24962
  history: histories,
24435
24963
  memories,
24436
24964
  siblings,
24437
- currentProject: resolve7(projectRoot).replace(/\\/g, "/"),
24965
+ currentProject: resolve8(projectRoot).replace(/\\/g, "/"),
24438
24966
  providers
24439
24967
  };
24440
24968
  }
@@ -24475,9 +25003,9 @@ var init_session_scanner = __esm({
24475
25003
  });
24476
25004
 
24477
25005
  // src/core/checks/session/missing-secret.ts
24478
- import { resolve as resolve8, basename as basename3 } from "node:path";
25006
+ import { resolve as resolve9, basename as basename3 } from "node:path";
24479
25007
  function normalizePath2(p2) {
24480
- return resolve8(p2).replace(/\\/g, "/").toLowerCase();
25008
+ return resolve9(p2).replace(/\\/g, "/").toLowerCase();
24481
25009
  }
24482
25010
  function extractSecretName(display) {
24483
25011
  const prefixMatch = display.match(SECRET_SET_PREFIX);
@@ -24595,7 +25123,7 @@ var init_missing_secret = __esm({
24595
25123
 
24596
25124
  // src/core/checks/session/diverged-file.ts
24597
25125
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
24598
- import { join as join6, resolve as resolve9 } from "node:path";
25126
+ import { join as join6, resolve as resolve10 } from "node:path";
24599
25127
  import { existsSync as existsSync2 } from "node:fs";
24600
25128
  async function loadLineSet(absPath) {
24601
25129
  let mtimeMs;
@@ -24647,7 +25175,7 @@ async function checkDivergedFile(ctx) {
24647
25175
  diverged.push({
24648
25176
  sibling: sib.name,
24649
25177
  overlap: Math.round(overlap * 100),
24650
- path: resolve9(sibPath)
25178
+ path: resolve10(sibPath)
24651
25179
  });
24652
25180
  }
24653
25181
  }
@@ -24662,7 +25190,7 @@ async function checkDivergedFile(ctx) {
24662
25190
  line: 0,
24663
25191
  message: `${fileName} has diverged from sibling repos: ${details}`,
24664
25192
  suggestion: `Compare with sibling versions to identify unintentional drift`,
24665
- detail: `File: ${resolve9(currentPath)}
25193
+ detail: `File: ${resolve10(currentPath)}
24666
25194
  Diverged siblings:
24667
25195
  ${sibPaths}`
24668
25196
  });
@@ -24752,15 +25280,15 @@ var init_missing_workflow = __esm({
24752
25280
  // src/core/checks/session/stale-memory.ts
24753
25281
  import { existsSync as existsSync4 } from "node:fs";
24754
25282
  import { homedir as homedir4 } from "node:os";
24755
- import { resolve as resolve10, isAbsolute as isAbsolute5 } from "node:path";
25283
+ import { resolve as resolve11, isAbsolute as isAbsolute5 } from "node:path";
24756
25284
  function resolveRef(ref, projectRoot) {
24757
25285
  if (ref.startsWith("~/") || ref === "~") {
24758
25286
  const home2 = process.env.HOME || process.env.USERPROFILE || homedir4();
24759
25287
  if (!home2) return null;
24760
- return ref === "~" ? home2 : resolve10(home2, ref.slice(2));
25288
+ return ref === "~" ? home2 : resolve11(home2, ref.slice(2));
24761
25289
  }
24762
25290
  if (isAbsolute5(ref)) return ref;
24763
- return resolve10(projectRoot, ref);
25291
+ return resolve11(projectRoot, ref);
24764
25292
  }
24765
25293
  async function checkStaleMemory(ctx) {
24766
25294
  const issues = [];
@@ -24857,9 +25385,9 @@ var init_duplicate_memory = __esm({
24857
25385
  });
24858
25386
 
24859
25387
  // src/core/checks/session/loop-detection.ts
24860
- import { resolve as resolve11 } from "node:path";
25388
+ import { resolve as resolve12 } from "node:path";
24861
25389
  function normalizeProject(p2) {
24862
- return resolve11(p2).replace(/\\/g, "/");
25390
+ return resolve12(p2).replace(/\\/g, "/");
24863
25391
  }
24864
25392
  function findConsecutiveRepeats(displays) {
24865
25393
  const results = [];
@@ -25074,7 +25602,7 @@ var init_memory_index_overflow = __esm({
25074
25602
  });
25075
25603
 
25076
25604
  // src/core/transcript.ts
25077
- import { createReadStream as createReadStream2, existsSync as existsSync5, statSync as statSync4 } from "node:fs";
25605
+ import { createReadStream as createReadStream2, existsSync as existsSync5, statSync as statSync5 } from "node:fs";
25078
25606
  import { readdir as readdir3 } from "node:fs/promises";
25079
25607
  import { homedir as homedir6 } from "node:os";
25080
25608
  import { join as join9 } from "node:path";
@@ -25116,7 +25644,7 @@ async function readUncached(project, home2) {
25116
25644
  const files = names.filter(({ name }) => name.endsWith(".jsonl")).map(({ dir, name }) => {
25117
25645
  const p2 = join9(dir, name);
25118
25646
  try {
25119
- return { p: p2, mtime: statSync4(p2).mtimeMs };
25647
+ return { p: p2, mtime: statSync5(p2).mtimeMs };
25120
25648
  } catch {
25121
25649
  return null;
25122
25650
  }
@@ -25486,6 +26014,106 @@ var init_default_branch_accumulation = __esm({
25486
26014
  }
25487
26015
  });
25488
26016
 
26017
+ // src/core/checks/session/unresolvable-sha.ts
26018
+ function stripFences(text) {
26019
+ const lines = text.split("\n");
26020
+ let inFence = false;
26021
+ return lines.map((line) => {
26022
+ if (line.trimStart().startsWith("```")) {
26023
+ inFence = !inFence;
26024
+ return "";
26025
+ }
26026
+ return inFence ? "" : line;
26027
+ }).join("\n");
26028
+ }
26029
+ function extractShaCitations(text) {
26030
+ const out = [];
26031
+ const seen = /* @__PURE__ */ new Set();
26032
+ for (const rawLine of stripFences(text).split("\n")) {
26033
+ const line = rawLine.replace(UUID, " ");
26034
+ HEX_TOKEN.lastIndex = 0;
26035
+ for (const m of line.matchAll(HEX_TOKEN)) {
26036
+ const sha = m[0];
26037
+ const start = m.index ?? 0;
26038
+ const before = line.slice(0, start);
26039
+ const after = line.slice(start + sha.length);
26040
+ if (/^\d+$/.test(sha)) continue;
26041
+ if (/[#]$/.test(before) || /0x$/i.test(before)) continue;
26042
+ if (DIGEST_PREFIX.test(before)) continue;
26043
+ if (/[-.]$/.test(before) && /[\w]$/.test(before.slice(0, -1))) continue;
26044
+ if (/^[-.][0-9a-z]/i.test(after)) continue;
26045
+ if (/[/\\]$/.test(before) && /^[/\\]/.test(after)) continue;
26046
+ const window2 = before.slice(-CUE_WINDOW);
26047
+ if (!CITATION_CUE.test(window2)) continue;
26048
+ if (seen.has(sha)) continue;
26049
+ seen.add(sha);
26050
+ out.push({ sha, context: rawLine.trim().slice(0, 160) });
26051
+ }
26052
+ }
26053
+ return out;
26054
+ }
26055
+ async function checkUnresolvableSha(ctx) {
26056
+ const projectMemories = ctx.memories.filter(
26057
+ (m) => projectDirMatchesPath(m.projectDir, ctx.currentProject)
26058
+ );
26059
+ if (projectMemories.length === 0) return [];
26060
+ if (!await isGitRepo(ctx.currentProject)) return [];
26061
+ const git = getGit(ctx.currentProject);
26062
+ const resolvedCache = /* @__PURE__ */ new Map();
26063
+ let budget = MAX_RESOLVE;
26064
+ async function resolves(sha) {
26065
+ const cached2 = resolvedCache.get(sha);
26066
+ if (cached2 !== void 0) return cached2;
26067
+ if (budget <= 0) return null;
26068
+ budget--;
26069
+ let ok;
26070
+ try {
26071
+ const type = await git.raw(["cat-file", "-t", sha]);
26072
+ ok = type.trim().length > 0;
26073
+ } catch {
26074
+ ok = false;
26075
+ }
26076
+ resolvedCache.set(sha, ok);
26077
+ return ok;
26078
+ }
26079
+ const issues = [];
26080
+ for (const mem of projectMemories) {
26081
+ const dead = [];
26082
+ for (const cite of extractShaCitations(mem.content)) {
26083
+ const ok = await resolves(cite.sha);
26084
+ if (ok === false) dead.push(cite);
26085
+ }
26086
+ if (dead.length === 0) continue;
26087
+ const name = mem.name || mem.filePath.split(/[/\\]/).pop() || "unknown";
26088
+ const list = dead.map((d) => d.sha).join(", ");
26089
+ issues.push({
26090
+ severity: "warning",
26091
+ check: "session-unresolvable-sha",
26092
+ ruleId: "session-unresolvable-sha/unresolvable-sha",
26093
+ line: 0,
26094
+ message: `Memory "${name}" cites ${dead.length} commit(s) that do not resolve in this repository: ${list}`,
26095
+ detail: dead.map((d) => `${d.sha}: ${d.context}`).join("\n"),
26096
+ suggestion: `Re-resolve the citation and update ${mem.filePath}. A squash-merge or rebase rewrites SHAs, so a memory written before the merge points at a commit that no longer exists -- cite the landed commit, or the PR number, which survives the rewrite.`
26097
+ });
26098
+ }
26099
+ return issues;
26100
+ }
26101
+ var HEX_TOKEN, UUID, CITATION_CUE, CUE_WINDOW, DIGEST_PREFIX, MAX_RESOLVE;
26102
+ var init_unresolvable_sha = __esm({
26103
+ "src/core/checks/session/unresolvable-sha.ts"() {
26104
+ "use strict";
26105
+ init_define_WEB_FIRST_SEGMENTS();
26106
+ init_git();
26107
+ init_session_parser();
26108
+ HEX_TOKEN = /\b[0-9a-f]{7,40}\b/g;
26109
+ UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
26110
+ CITATION_CUE = /\b(commit|commits|committed|sha|revision|revs?|git|head|tag|tagged|branch|pr|landed|merged|shipped|introduced|reverted|cherry-?picked|backported|fixed|removed|added|renamed|bumped|released)\b/i;
26111
+ CUE_WINDOW = 80;
26112
+ DIGEST_PREFIX = /(sha\d{3}|md5|blake\d*|crc\d*)\s*[:=]\s*$/i;
26113
+ MAX_RESOLVE = 40;
26114
+ }
26115
+ });
26116
+
25489
26117
  // src/core/checks/ci-coverage.ts
25490
26118
  import { readdir as readdir4, readFile as readFile4 } from "node:fs/promises";
25491
26119
  import { join as join10 } from "node:path";
@@ -25897,26 +26525,26 @@ var init_positions = __esm({
25897
26525
  });
25898
26526
 
25899
26527
  // src/core/checks/hook-coverage.ts
25900
- import * as fs7 from "node:fs";
26528
+ import * as fs8 from "node:fs";
25901
26529
  import * as os3 from "node:os";
25902
- import * as path10 from "node:path";
26530
+ import * as path11 from "node:path";
25903
26531
  function loadSettingsSources2(projectRoot, homeDir, includeUserGlobal) {
25904
26532
  const home2 = homeDir;
25905
26533
  const candidates = [
25906
26534
  {
25907
- filePath: path10.join(projectRoot, ".claude", "settings.json"),
25908
- displayPath: path10.join(".claude", "settings.json"),
26535
+ filePath: path11.join(projectRoot, ".claude", "settings.json"),
26536
+ displayPath: path11.join(".claude", "settings.json"),
25909
26537
  isUserGlobal: false
25910
26538
  },
25911
26539
  {
25912
- filePath: path10.join(projectRoot, ".claude", "settings.local.json"),
25913
- displayPath: path10.join(".claude", "settings.local.json"),
26540
+ filePath: path11.join(projectRoot, ".claude", "settings.local.json"),
26541
+ displayPath: path11.join(".claude", "settings.local.json"),
25914
26542
  isUserGlobal: false
25915
26543
  }
25916
26544
  ];
25917
26545
  if (includeUserGlobal) {
25918
26546
  candidates.push({
25919
- filePath: path10.join(home2, ".claude", "settings.json"),
26547
+ filePath: path11.join(home2, ".claude", "settings.json"),
25920
26548
  displayPath: "~/.claude/settings.json",
25921
26549
  isUserGlobal: true
25922
26550
  });
@@ -25925,7 +26553,7 @@ function loadSettingsSources2(projectRoot, homeDir, includeUserGlobal) {
25925
26553
  for (const c3 of candidates) {
25926
26554
  let content;
25927
26555
  try {
25928
- content = stripBom(fs7.readFileSync(c3.filePath, "utf-8"));
26556
+ content = stripBom(fs8.readFileSync(c3.filePath, "utf-8"));
25929
26557
  } catch {
25930
26558
  continue;
25931
26559
  }
@@ -25937,11 +26565,11 @@ function loadSettingsSources2(projectRoot, homeDir, includeUserGlobal) {
25937
26565
  function expandPath(raw, projectRoot, homeDir, platform) {
25938
26566
  let s = raw;
25939
26567
  if (s === "~" || s.startsWith("~/") || s.startsWith("~\\")) {
25940
- s = path10.join(homeDir, s.slice(1));
26568
+ s = path11.join(homeDir, s.slice(1));
25941
26569
  }
25942
26570
  const replacements = {
25943
26571
  CLAUDE_PROJECT_DIR: projectRoot,
25944
- CLAUDE_CONFIG_DIR: path10.join(homeDir, ".claude"),
26572
+ CLAUDE_CONFIG_DIR: path11.join(homeDir, ".claude"),
25945
26573
  HOME: homeDir,
25946
26574
  USERPROFILE: homeDir
25947
26575
  };
@@ -25956,7 +26584,7 @@ function expandPath(raw, projectRoot, homeDir, platform) {
25956
26584
  if (/\$\{?[A-Za-z_]/.test(s)) return null;
25957
26585
  if (/%[A-Za-z_][A-Za-z0-9_]*%/.test(s)) return null;
25958
26586
  s = translateMsysDrivePath(s, platform);
25959
- if (!path10.isAbsolute(s)) s = path10.resolve(projectRoot, s);
26587
+ if (!path11.isAbsolute(s)) s = path11.resolve(projectRoot, s);
25960
26588
  return s;
25961
26589
  }
25962
26590
  function looksLikePath(token) {
@@ -26094,19 +26722,19 @@ var init_hook_coverage = __esm({
26094
26722
  });
26095
26723
 
26096
26724
  // src/core/skill-scanner.ts
26097
- import * as fs8 from "node:fs";
26725
+ import * as fs9 from "node:fs";
26098
26726
  import * as os4 from "node:os";
26099
- import * as path11 from "node:path";
26727
+ import * as path12 from "node:path";
26100
26728
  function defaultHome() {
26101
26729
  return process.env.HOME || process.env.USERPROFILE || os4.homedir();
26102
26730
  }
26103
26731
  function scanSkillFiles(homeDir = defaultHome()) {
26104
26732
  const files = [];
26105
26733
  const orphanedSkillDirs = [];
26106
- const claudeDir = path11.join(homeDir, ".claude");
26107
- const skillsRoot = path11.join(claudeDir, "skills");
26734
+ const claudeDir = path12.join(homeDir, ".claude");
26735
+ const skillsRoot = path12.join(claudeDir, "skills");
26108
26736
  for (const name of safeReadDir(skillsRoot, "dir")) {
26109
- const skillMd = path11.join(skillsRoot, name, "SKILL.md");
26737
+ const skillMd = path12.join(skillsRoot, name, "SKILL.md");
26110
26738
  const content = safeRead(skillMd);
26111
26739
  if (content === null) {
26112
26740
  orphanedSkillDirs.push({ name, displayPath: `~/.claude/skills/${name}/` });
@@ -26120,10 +26748,10 @@ function scanSkillFiles(homeDir = defaultHome()) {
26120
26748
  content
26121
26749
  });
26122
26750
  }
26123
- const agentsRoot = path11.join(claudeDir, "agents");
26751
+ const agentsRoot = path12.join(claudeDir, "agents");
26124
26752
  for (const fileName of safeReadDir(agentsRoot, "file")) {
26125
26753
  if (!fileName.endsWith(".md")) continue;
26126
- const agentMd = path11.join(agentsRoot, fileName);
26754
+ const agentMd = path12.join(agentsRoot, fileName);
26127
26755
  const content = safeRead(agentMd);
26128
26756
  if (content === null) continue;
26129
26757
  files.push({
@@ -26139,7 +26767,7 @@ function scanSkillFiles(homeDir = defaultHome()) {
26139
26767
  function safeReadDir(dir, want) {
26140
26768
  let entries;
26141
26769
  try {
26142
- entries = fs8.readdirSync(dir, { withFileTypes: true });
26770
+ entries = fs9.readdirSync(dir, { withFileTypes: true });
26143
26771
  } catch {
26144
26772
  return [];
26145
26773
  }
@@ -26147,7 +26775,7 @@ function safeReadDir(dir, want) {
26147
26775
  if (want === "dir" ? e.isDirectory() : e.isFile()) return true;
26148
26776
  if (!e.isSymbolicLink()) return false;
26149
26777
  try {
26150
- const target = fs8.statSync(path11.join(dir, e.name));
26778
+ const target = fs9.statSync(path12.join(dir, e.name));
26151
26779
  return want === "dir" ? target.isDirectory() : target.isFile();
26152
26780
  } catch {
26153
26781
  return false;
@@ -26156,7 +26784,7 @@ function safeReadDir(dir, want) {
26156
26784
  }
26157
26785
  function safeRead(file2) {
26158
26786
  try {
26159
- return stripBom(fs8.readFileSync(file2, "utf-8"));
26787
+ return stripBom(fs9.readFileSync(file2, "utf-8"));
26160
26788
  } catch {
26161
26789
  return null;
26162
26790
  }
@@ -26170,7 +26798,7 @@ var init_skill_scanner = __esm({
26170
26798
  });
26171
26799
 
26172
26800
  // src/core/checks/skills.ts
26173
- import * as path12 from "node:path";
26801
+ import * as path13 from "node:path";
26174
26802
  function parseFrontmatter3(content) {
26175
26803
  const lines = content.split("\n");
26176
26804
  if (lines[0]?.trim() !== "---") {
@@ -26247,7 +26875,7 @@ function checkMissingFrontmatter(file2, fm) {
26247
26875
  }
26248
26876
  function checkBrokenRefs(file2, fmEndLine) {
26249
26877
  const issues = [];
26250
- const skillDir = path12.dirname(file2.filePath);
26878
+ const skillDir = path13.dirname(file2.filePath);
26251
26879
  const lines = file2.content.split("\n");
26252
26880
  let inCode = false;
26253
26881
  let codeLang = "";
@@ -26267,7 +26895,7 @@ function checkBrokenRefs(file2, fmEndLine) {
26267
26895
  if (PATH_SKIP.test(value)) continue;
26268
26896
  if (!value.startsWith("./") && !value.startsWith("../")) continue;
26269
26897
  while (/[.,;:]$/.test(value)) value = value.slice(0, -1);
26270
- const resolved = path12.resolve(skillDir, value);
26898
+ const resolved = path13.resolve(skillDir, value);
26271
26899
  if (fileExists(resolved) || isDirectory(resolved)) continue;
26272
26900
  issues.push({
26273
26901
  severity: "warning",
@@ -26775,8 +27403,8 @@ var require_utils = __commonJS({
26775
27403
  }
26776
27404
  return output;
26777
27405
  };
26778
- exports.basename = (path20, { windows } = {}) => {
26779
- const segs = path20.split(windows ? /[\\/]/ : "/");
27406
+ exports.basename = (path21, { windows } = {}) => {
27407
+ const segs = path21.split(windows ? /[\\/]/ : "/");
26780
27408
  const last2 = segs[segs.length - 1];
26781
27409
  if (last2 === "") {
26782
27410
  return segs[segs.length - 2];
@@ -28275,16 +28903,16 @@ var require_picomatch2 = __commonJS({
28275
28903
  });
28276
28904
 
28277
28905
  // src/core/ignore-file.ts
28278
- import fs9 from "node:fs";
28279
- import path13 from "node:path";
28906
+ import fs10 from "node:fs";
28907
+ import path14 from "node:path";
28280
28908
  function matchesGlob(filePath, glob) {
28281
28909
  return (0, import_picomatch.default)(glob, { dot: true })(filePath);
28282
28910
  }
28283
28911
  function loadIgnoreFile(projectRoot) {
28284
- const ignoreFilePath = path13.join(projectRoot, ".ctxlintignore");
28912
+ const ignoreFilePath = path14.join(projectRoot, ".ctxlintignore");
28285
28913
  let content;
28286
28914
  try {
28287
- content = fs9.readFileSync(ignoreFilePath, "utf-8");
28915
+ content = fs10.readFileSync(ignoreFilePath, "utf-8");
28288
28916
  } catch {
28289
28917
  return [];
28290
28918
  }
@@ -28330,15 +28958,15 @@ var init_types = __esm({
28330
28958
  });
28331
28959
 
28332
28960
  // src/version.ts
28333
- import { readFileSync as readFileSync7 } from "node:fs";
28334
- import { resolve as resolve14, dirname as dirname6 } from "node:path";
28961
+ import { readFileSync as readFileSync8 } from "node:fs";
28962
+ import { resolve as resolve15, dirname as dirname7 } from "node:path";
28335
28963
  import { fileURLToPath as fileURLToPath2 } from "node:url";
28336
28964
  function loadVersion() {
28337
- if (true) return "0.18.7";
28965
+ if (true) return "0.19.0";
28338
28966
  try {
28339
- const __dir = dirname6(fileURLToPath2(import.meta.url));
28340
- const pkgPath = resolve14(__dir, "../package.json");
28341
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
28967
+ const __dir = dirname7(fileURLToPath2(import.meta.url));
28968
+ const pkgPath = resolve15(__dir, "../package.json");
28969
+ const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
28342
28970
  return pkg.version ?? "0.0.0-dev";
28343
28971
  } catch {
28344
28972
  return "0.0.0-dev";
@@ -28354,9 +28982,9 @@ var init_version2 = __esm({
28354
28982
  });
28355
28983
 
28356
28984
  // src/core/audit.ts
28357
- import * as fs10 from "node:fs";
28985
+ import * as fs11 from "node:fs";
28358
28986
  import * as os5 from "node:os";
28359
- import * as path14 from "node:path";
28987
+ import * as path15 from "node:path";
28360
28988
  function hasMcpChecks(checks) {
28361
28989
  return checks.some((c3) => c3.startsWith("mcp-"));
28362
28990
  }
@@ -28392,7 +29020,7 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
28392
29020
  const absPath = discoveredFile.absolutePath;
28393
29021
  let stat3 = null;
28394
29022
  try {
28395
- const s = fs10.statSync(absPath);
29023
+ const s = fs11.statSync(absPath);
28396
29024
  stat3 = { mtimeMs: s.mtimeMs, size: s.size };
28397
29025
  } catch {
28398
29026
  }
@@ -28405,7 +29033,8 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
28405
29033
  const parseResult = parseContextFile(discoveredFile);
28406
29034
  parsed.push(parseResult);
28407
29035
  const checkPromises = [];
28408
- if (activeChecks.includes("paths")) checkPromises.push(checkPaths(parseResult, projectRoot));
29036
+ if (activeChecks.includes("paths"))
29037
+ checkPromises.push(checkPaths(parseResult, projectRoot));
28409
29038
  if (activeChecks.includes("commands"))
28410
29039
  checkPromises.push(checkCommands(parseResult, projectRoot));
28411
29040
  if (activeChecks.includes("staleness"))
@@ -28579,6 +29208,8 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
28579
29208
  sessionPromises.push(checkUnverifiedGateClaimedClean(sessionCtx));
28580
29209
  if (sessionChecksToRun.includes("session-default-branch-accumulation"))
28581
29210
  sessionPromises.push(checkDefaultBranchAccumulation(sessionCtx));
29211
+ if (sessionChecksToRun.includes("session-unresolvable-sha"))
29212
+ sessionPromises.push(checkUnresolvableSha(sessionCtx));
28582
29213
  const sessionResults = await Promise.all(sessionPromises);
28583
29214
  const sessionIssues = sessionResults.flat();
28584
29215
  fileResults.push({
@@ -28640,10 +29271,7 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
28640
29271
  globUnusedRules = globScopedRules.filter((r2) => !firedGlobRules.has(r2)).map(({ _fileGlob: _unused, ...rest }) => rest);
28641
29272
  globRulesMissingReason = globScopedRules.filter((r2) => !r2.reason).map(({ _fileGlob: _unused, ...rest }) => rest);
28642
29273
  }
28643
- const allIgnoreRules = [
28644
- ...options.ignoreRules ?? [],
28645
- ...globalFileRules
28646
- ];
29274
+ const allIgnoreRules = [...options.ignoreRules ?? [], ...globalFileRules];
28647
29275
  let ignoreReport;
28648
29276
  if (allIgnoreRules.length > 0 || globDropped > 0) {
28649
29277
  let flatDropped = 0;
@@ -28717,29 +29345,33 @@ async function runAudit(projectRoot, activeChecks, options = {}) {
28717
29345
  return result;
28718
29346
  }
28719
29347
  async function runAuditOnContent(filePath, content, projectRoot, options = {}) {
28720
- const tmpDir = fs10.mkdtempSync(path14.join(os5.tmpdir(), "ctxlint-lsp-"));
28721
- const ext = path14.extname(filePath) || ".md";
28722
- const tmpFile = path14.join(tmpDir, "content" + ext);
29348
+ const tmpDir = fs11.mkdtempSync(path15.join(os5.tmpdir(), "ctxlint-lsp-"));
29349
+ const ext = path15.extname(filePath) || ".md";
29350
+ const tmpFile = path15.join(tmpDir, "content" + ext);
28723
29351
  try {
28724
- fs10.writeFileSync(tmpFile, content, "utf-8");
28725
- const tmpRelative = path14.relative(tmpDir, tmpFile);
28726
- const rawResult = await runAudit(tmpDir, options.depth !== void 0 ? ALL_CHECKS : ALL_CHECKS, {
28727
- ...options,
28728
- extraPatterns: [tmpRelative],
28729
- // Disable cross-project checks that need the real project tree.
28730
- session: false,
28731
- sessionOnly: false,
28732
- skills: false,
28733
- skillsOnly: false
28734
- });
29352
+ fs11.writeFileSync(tmpFile, content, "utf-8");
29353
+ const tmpRelative = path15.relative(tmpDir, tmpFile);
29354
+ const rawResult = await runAudit(
29355
+ tmpDir,
29356
+ options.depth !== void 0 ? ALL_CHECKS : ALL_CHECKS,
29357
+ {
29358
+ ...options,
29359
+ extraPatterns: [tmpRelative],
29360
+ // Disable cross-project checks that need the real project tree.
29361
+ session: false,
29362
+ sessionOnly: false,
29363
+ skills: false,
29364
+ skillsOnly: false
29365
+ }
29366
+ );
28735
29367
  const remapped = rawResult.files.map((fr) => {
28736
- const isTmp = fr.path === tmpRelative || fr.path === tmpFile || path14.resolve(tmpDir, fr.path) === tmpFile;
29368
+ const isTmp = fr.path === tmpRelative || fr.path === tmpFile || path15.resolve(tmpDir, fr.path) === tmpFile;
28737
29369
  return isTmp ? { ...fr, path: filePath } : fr;
28738
29370
  });
28739
29371
  return { ...rawResult, files: remapped, projectRoot };
28740
29372
  } finally {
28741
29373
  try {
28742
- fs10.rmSync(tmpDir, { recursive: true, force: true });
29374
+ fs11.rmSync(tmpDir, { recursive: true, force: true });
28743
29375
  } catch {
28744
29376
  }
28745
29377
  }
@@ -28782,6 +29414,7 @@ var init_audit = __esm({
28782
29414
  init_shared_temp_path();
28783
29415
  init_unverified_gate_claimed_clean();
28784
29416
  init_default_branch_accumulation();
29417
+ init_unresolvable_sha();
28785
29418
  init_ci_coverage();
28786
29419
  init_ci_secrets();
28787
29420
  init_content_secrets();
@@ -28826,7 +29459,8 @@ var init_audit = __esm({
28826
29459
  "session-memory-index-overflow",
28827
29460
  "session-shared-temp-path",
28828
29461
  "session-unverified-gate-claimed-clean",
28829
- "session-default-branch-accumulation"
29462
+ "session-default-branch-accumulation",
29463
+ "session-unresolvable-sha"
28830
29464
  ];
28831
29465
  ALL_SKILL_CHECKS = [
28832
29466
  "skill-frontmatter",
@@ -28843,7 +29477,7 @@ var server_exports = {};
28843
29477
  __export(server_exports, {
28844
29478
  startLspServer: () => startLspServer
28845
29479
  });
28846
- import * as path15 from "node:path";
29480
+ import * as path16 from "node:path";
28847
29481
  async function startLspServer() {
28848
29482
  const connection = (0, import_node.createConnection)(import_node.ProposedFeatures.all);
28849
29483
  const documents = new import_node.TextDocuments(TextDocument2);
@@ -28858,7 +29492,7 @@ async function startLspServer() {
28858
29492
  const uri = doc.uri;
28859
29493
  let filePath = uri.startsWith("file://") ? decodeURIComponent(uri.slice(7)) : uri;
28860
29494
  filePath = filePath.replace(/^\/([A-Za-z]:)/, "$1");
28861
- const projectRoot = path15.dirname(filePath);
29495
+ const projectRoot = path16.dirname(filePath);
28862
29496
  try {
28863
29497
  const result = await runAuditOnContent(filePath, doc.getText(), projectRoot, {
28864
29498
  depth: 2
@@ -29310,8 +29944,8 @@ var init_parseUtil = __esm({
29310
29944
  init_errors();
29311
29945
  init_en();
29312
29946
  makeIssue = (params) => {
29313
- const { data, path: path20, errorMaps, issueData } = params;
29314
- const fullPath = [...path20, ...issueData.path || []];
29947
+ const { data, path: path21, errorMaps, issueData } = params;
29948
+ const fullPath = [...path21, ...issueData.path || []];
29315
29949
  const fullIssue = {
29316
29950
  ...issueData,
29317
29951
  path: fullPath
@@ -29594,11 +30228,11 @@ var init_types2 = __esm({
29594
30228
  init_parseUtil();
29595
30229
  init_util2();
29596
30230
  ParseInputLazyPath = class {
29597
- constructor(parent, value, path20, key) {
30231
+ constructor(parent, value, path21, key) {
29598
30232
  this._cachedPath = [];
29599
30233
  this.parent = parent;
29600
30234
  this.data = value;
29601
- this._path = path20;
30235
+ this._path = path21;
29602
30236
  this._key = key;
29603
30237
  }
29604
30238
  get path() {
@@ -33100,10 +33734,10 @@ function mergeDefs(...defs) {
33100
33734
  function cloneDef(schema) {
33101
33735
  return mergeDefs(schema._zod.def);
33102
33736
  }
33103
- function getElementAtPath(obj, path20) {
33104
- if (!path20)
33737
+ function getElementAtPath(obj, path21) {
33738
+ if (!path21)
33105
33739
  return obj;
33106
- return path20.reduce((acc, key) => acc?.[key], obj);
33740
+ return path21.reduce((acc, key) => acc?.[key], obj);
33107
33741
  }
33108
33742
  function promiseAllObject(promisesObj) {
33109
33743
  const keys = Object.keys(promisesObj);
@@ -33431,11 +34065,11 @@ function explicitlyAborted(x3, startIndex = 0) {
33431
34065
  }
33432
34066
  return false;
33433
34067
  }
33434
- function prefixIssues(path20, issues) {
34068
+ function prefixIssues(path21, issues) {
33435
34069
  return issues.map((iss) => {
33436
34070
  var _a4;
33437
34071
  (_a4 = iss).path ?? (_a4.path = []);
33438
- iss.path.unshift(path20);
34072
+ iss.path.unshift(path21);
33439
34073
  return iss;
33440
34074
  });
33441
34075
  }
@@ -33653,16 +34287,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
33653
34287
  }
33654
34288
  function formatError(error52, mapper = (issue2) => issue2.message) {
33655
34289
  const fieldErrors = { _errors: [] };
33656
- const processError = (error53, path20 = []) => {
34290
+ const processError = (error53, path21 = []) => {
33657
34291
  for (const issue2 of error53.issues) {
33658
34292
  if (issue2.code === "invalid_union" && issue2.errors.length) {
33659
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
34293
+ issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
33660
34294
  } else if (issue2.code === "invalid_key") {
33661
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
34295
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
33662
34296
  } else if (issue2.code === "invalid_element") {
33663
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
34297
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
33664
34298
  } else {
33665
- const fullpath = [...path20, ...issue2.path];
34299
+ const fullpath = [...path21, ...issue2.path];
33666
34300
  if (fullpath.length === 0) {
33667
34301
  fieldErrors._errors.push(mapper(issue2));
33668
34302
  } else {
@@ -33689,17 +34323,17 @@ function formatError(error52, mapper = (issue2) => issue2.message) {
33689
34323
  }
33690
34324
  function treeifyError(error52, mapper = (issue2) => issue2.message) {
33691
34325
  const result = { errors: [] };
33692
- const processError = (error53, path20 = []) => {
34326
+ const processError = (error53, path21 = []) => {
33693
34327
  var _a4, _b;
33694
34328
  for (const issue2 of error53.issues) {
33695
34329
  if (issue2.code === "invalid_union" && issue2.errors.length) {
33696
- issue2.errors.map((issues) => processError({ issues }, [...path20, ...issue2.path]));
34330
+ issue2.errors.map((issues) => processError({ issues }, [...path21, ...issue2.path]));
33697
34331
  } else if (issue2.code === "invalid_key") {
33698
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
34332
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
33699
34333
  } else if (issue2.code === "invalid_element") {
33700
- processError({ issues: issue2.issues }, [...path20, ...issue2.path]);
34334
+ processError({ issues: issue2.issues }, [...path21, ...issue2.path]);
33701
34335
  } else {
33702
- const fullpath = [...path20, ...issue2.path];
34336
+ const fullpath = [...path21, ...issue2.path];
33703
34337
  if (fullpath.length === 0) {
33704
34338
  result.errors.push(mapper(issue2));
33705
34339
  continue;
@@ -33731,8 +34365,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
33731
34365
  }
33732
34366
  function toDotPath(_path) {
33733
34367
  const segs = [];
33734
- const path20 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
33735
- for (const seg of path20) {
34368
+ const path21 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
34369
+ for (const seg of path21) {
33736
34370
  if (typeof seg === "number")
33737
34371
  segs.push(`[${seg}]`);
33738
34372
  else if (typeof seg === "symbol")
@@ -47493,13 +48127,13 @@ function resolveRef2(ref, ctx) {
47493
48127
  if (!ref.startsWith("#")) {
47494
48128
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
47495
48129
  }
47496
- const path20 = ref.slice(1).split("/").filter(Boolean);
47497
- if (path20.length === 0) {
48130
+ const path21 = ref.slice(1).split("/").filter(Boolean);
48131
+ if (path21.length === 0) {
47498
48132
  return ctx.rootSchema;
47499
48133
  }
47500
48134
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
47501
- if (path20[0] === defsKey) {
47502
- const key = path20[1];
48135
+ if (path21[0] === defsKey) {
48136
+ const key = path21[1];
47503
48137
  if (!key || !ctx.defs[key]) {
47504
48138
  throw new Error(`Reference not found: ${ref}`);
47505
48139
  }
@@ -52013,7 +52647,7 @@ var init_protocol = __esm({
52013
52647
  return;
52014
52648
  }
52015
52649
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
52016
- await new Promise((resolve18) => setTimeout(resolve18, pollInterval));
52650
+ await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
52017
52651
  options?.signal?.throwIfAborted();
52018
52652
  }
52019
52653
  } catch (error52) {
@@ -52030,7 +52664,7 @@ var init_protocol = __esm({
52030
52664
  */
52031
52665
  request(request, resultSchema, options) {
52032
52666
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
52033
- return new Promise((resolve18, reject) => {
52667
+ return new Promise((resolve19, reject) => {
52034
52668
  const earlyReject = (error52) => {
52035
52669
  reject(error52);
52036
52670
  };
@@ -52108,7 +52742,7 @@ var init_protocol = __esm({
52108
52742
  if (!parseResult.success) {
52109
52743
  reject(parseResult.error);
52110
52744
  } else {
52111
- resolve18(parseResult.data);
52745
+ resolve19(parseResult.data);
52112
52746
  }
52113
52747
  } catch (error52) {
52114
52748
  reject(error52);
@@ -52369,12 +53003,12 @@ var init_protocol = __esm({
52369
53003
  }
52370
53004
  } catch {
52371
53005
  }
52372
- return new Promise((resolve18, reject) => {
53006
+ return new Promise((resolve19, reject) => {
52373
53007
  if (signal.aborted) {
52374
53008
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
52375
53009
  return;
52376
53010
  }
52377
- const timeoutId = setTimeout(resolve18, interval);
53011
+ const timeoutId = setTimeout(resolve19, interval);
52378
53012
  signal.addEventListener("abort", () => {
52379
53013
  clearTimeout(timeoutId);
52380
53014
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -55422,7 +56056,7 @@ var require_compile = __commonJS({
55422
56056
  const schOrFunc = root.refs[ref];
55423
56057
  if (schOrFunc)
55424
56058
  return schOrFunc;
55425
- let _sch = resolve18.call(this, root, ref);
56059
+ let _sch = resolve19.call(this, root, ref);
55426
56060
  if (_sch === void 0) {
55427
56061
  const schema = (_a4 = root.localRefs) === null || _a4 === void 0 ? void 0 : _a4[ref];
55428
56062
  const { schemaId } = this.opts;
@@ -55449,7 +56083,7 @@ var require_compile = __commonJS({
55449
56083
  function sameSchemaEnv(s1, s2) {
55450
56084
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
55451
56085
  }
55452
- function resolve18(root, ref) {
56086
+ function resolve19(root, ref) {
55453
56087
  let sch;
55454
56088
  while (typeof (sch = this.refs[ref]) == "string")
55455
56089
  ref = sch;
@@ -55668,8 +56302,8 @@ var require_utils2 = __commonJS({
55668
56302
  }
55669
56303
  return ind;
55670
56304
  }
55671
- function removeDotSegments(path20) {
55672
- let input = path20;
56305
+ function removeDotSegments(path21) {
56306
+ let input = path21;
55673
56307
  const output = [];
55674
56308
  let nextSlash = -1;
55675
56309
  let len = 0;
@@ -55922,8 +56556,8 @@ var require_schemes = __commonJS({
55922
56556
  wsComponent.secure = void 0;
55923
56557
  }
55924
56558
  if (wsComponent.resourceName) {
55925
- const [path20, query] = wsComponent.resourceName.split("?");
55926
- wsComponent.path = path20 && path20 !== "/" ? path20 : void 0;
56559
+ const [path21, query] = wsComponent.resourceName.split("?");
56560
+ wsComponent.path = path21 && path21 !== "/" ? path21 : void 0;
55927
56561
  wsComponent.query = query;
55928
56562
  wsComponent.resourceName = void 0;
55929
56563
  }
@@ -56083,7 +56717,7 @@ var require_fast_uri = __commonJS({
56083
56717
  }
56084
56718
  return uri;
56085
56719
  }
56086
- function resolve18(baseURI, relativeURI, options) {
56720
+ function resolve19(baseURI, relativeURI, options) {
56087
56721
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
56088
56722
  const resolved = resolveComponent(parse5(baseURI, schemelessOptions), parse5(relativeURI, schemelessOptions), schemelessOptions, true);
56089
56723
  schemelessOptions.skipEscape = true;
@@ -56341,7 +56975,7 @@ var require_fast_uri = __commonJS({
56341
56975
  var fastUri = {
56342
56976
  SCHEMES,
56343
56977
  normalize: normalize4,
56344
- resolve: resolve18,
56978
+ resolve: resolve19,
56345
56979
  resolveComponent,
56346
56980
  equal,
56347
56981
  serialize,
@@ -59362,12 +59996,12 @@ var require_dist3 = __commonJS({
59362
59996
  throw new Error(`Unknown format "${name}"`);
59363
59997
  return f;
59364
59998
  };
59365
- function addFormats(ajv, list, fs15, exportName) {
59999
+ function addFormats(ajv, list, fs16, exportName) {
59366
60000
  var _a4;
59367
60001
  var _b;
59368
60002
  (_a4 = (_b = ajv.opts.code).formats) !== null && _a4 !== void 0 ? _a4 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
59369
60003
  for (const f of list)
59370
- ajv.addFormat(f, fs15[f]);
60004
+ ajv.addFormat(f, fs16[f]);
59371
60005
  }
59372
60006
  module.exports = exports = formatsPlugin;
59373
60007
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -60523,7 +61157,7 @@ var init_mcp = __esm({
60523
61157
  let task = createTaskResult.task;
60524
61158
  const pollInterval = task.pollInterval ?? 5e3;
60525
61159
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
60526
- await new Promise((resolve18) => setTimeout(resolve18, pollInterval));
61160
+ await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
60527
61161
  const updatedTask = await extra.taskStore.getTask(taskId);
60528
61162
  if (!updatedTask) {
60529
61163
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -61119,12 +61753,12 @@ var init_stdio2 = __esm({
61119
61753
  this.onclose?.();
61120
61754
  }
61121
61755
  send(message) {
61122
- return new Promise((resolve18) => {
61756
+ return new Promise((resolve19) => {
61123
61757
  const json2 = serializeMessage(message);
61124
61758
  if (this._stdout.write(json2)) {
61125
- resolve18();
61759
+ resolve19();
61126
61760
  } else {
61127
- this._stdout.once("drain", resolve18);
61761
+ this._stdout.once("drain", resolve19);
61128
61762
  }
61129
61763
  });
61130
61764
  }
@@ -61675,7 +62309,7 @@ var init_source = __esm({
61675
62309
  });
61676
62310
 
61677
62311
  // src/core/fixer.ts
61678
- import * as fs11 from "node:fs";
62312
+ import * as fs12 from "node:fs";
61679
62313
  function applyFixes(result, options = {}) {
61680
62314
  const log = options.quiet ? () => {
61681
62315
  } : console.log.bind(console);
@@ -61713,7 +62347,7 @@ function applyFixes(result, options = {}) {
61713
62347
  for (const [filePath, fixes] of fixesByFile) {
61714
62348
  let content;
61715
62349
  try {
61716
- content = fs11.readFileSync(filePath, "utf-8");
62350
+ content = fs12.readFileSync(filePath, "utf-8");
61717
62351
  } catch (err) {
61718
62352
  log(source_default.yellow(" Skipped") + ` ${filePath}: ${err.message}`);
61719
62353
  continue;
@@ -61798,7 +62432,7 @@ function applyFixes(result, options = {}) {
61798
62432
  }
61799
62433
  if (!dryRun) {
61800
62434
  try {
61801
- fs11.writeFileSync(filePath, newContent, "utf-8");
62435
+ fs12.writeFileSync(filePath, newContent, "utf-8");
61802
62436
  } catch (err) {
61803
62437
  log(source_default.yellow(" Skipped") + ` ${filePath}: ${err.message}`);
61804
62438
  continue;
@@ -61820,8 +62454,8 @@ var init_fixer = __esm({
61820
62454
  });
61821
62455
 
61822
62456
  // src/core/config.ts
61823
- import * as fs12 from "node:fs";
61824
- import * as path16 from "node:path";
62457
+ import * as fs13 from "node:fs";
62458
+ import * as path17 from "node:path";
61825
62459
  function formatJsonError(content, err) {
61826
62460
  const msg = err instanceof Error ? err.message : String(err);
61827
62461
  const posMatch = msg.match(/position (\d+)/);
@@ -61919,10 +62553,10 @@ function warnIgnoreRulePathPatternMisuse(config2, source) {
61919
62553
  }
61920
62554
  function loadConfig(projectRoot) {
61921
62555
  for (const filename of CONFIG_FILENAMES) {
61922
- const filePath = path16.join(projectRoot, filename);
62556
+ const filePath = path17.join(projectRoot, filename);
61923
62557
  let content;
61924
62558
  try {
61925
- content = stripBom(fs12.readFileSync(filePath, "utf-8"));
62559
+ content = stripBom(fs13.readFileSync(filePath, "utf-8"));
61926
62560
  } catch {
61927
62561
  continue;
61928
62562
  }
@@ -61933,7 +62567,7 @@ function loadConfig(projectRoot) {
61933
62567
  function loadConfigFromExplicitPath(configPath) {
61934
62568
  let content;
61935
62569
  try {
61936
- content = stripBom(fs12.readFileSync(configPath, "utf-8"));
62570
+ content = stripBom(fs13.readFileSync(configPath, "utf-8"));
61937
62571
  } catch (err) {
61938
62572
  const detail = err instanceof Error ? err.message : String(err);
61939
62573
  throw new Error(`could not load config from ${configPath}: ${detail}`, { cause: err });
@@ -61975,7 +62609,7 @@ __export(server_exports2, {
61975
62609
  server: () => server,
61976
62610
  startServer: () => startServer
61977
62611
  });
61978
- import * as path17 from "node:path";
62612
+ import * as path18 from "node:path";
61979
62613
  function describeDisallowed(rawPath) {
61980
62614
  const m = rawPath.match(PATH_DISALLOWED);
61981
62615
  if (!m) return "unknown";
@@ -61988,7 +62622,7 @@ function validateProjectPath(rawPath) {
61988
62622
  `projectPath contains disallowed character ${describeDisallowed(rawPath)} (control chars and shell metacharacters are rejected)`
61989
62623
  );
61990
62624
  }
61991
- const resolved = path17.resolve(rawPath);
62625
+ const resolved = path18.resolve(rawPath);
61992
62626
  if (!isDirectory(resolved)) {
61993
62627
  throw new Error("projectPath is not an existing directory");
61994
62628
  }
@@ -62012,10 +62646,10 @@ function validateFilePathInput(rawPath) {
62012
62646
  }
62013
62647
  }
62014
62648
  function resolveWithinRoot(filePath, root) {
62015
- const resolvedRoot = path17.resolve(root);
62016
- const resolved = path17.resolve(resolvedRoot, filePath);
62017
- const rel = path17.relative(resolvedRoot, resolved);
62018
- if (rel.startsWith("..") || path17.isAbsolute(rel)) {
62649
+ const resolvedRoot = path18.resolve(root);
62650
+ const resolved = path18.resolve(resolvedRoot, filePath);
62651
+ const rel = path18.relative(resolvedRoot, resolved);
62652
+ if (rel.startsWith("..") || path18.isAbsolute(rel)) {
62019
62653
  throw new Error("path escapes the project root");
62020
62654
  }
62021
62655
  return resolved;
@@ -62112,7 +62746,7 @@ var init_server4 = __esm({
62112
62746
  exists: fileExists(resolved) || isDirectory(resolved)
62113
62747
  };
62114
62748
  if (!result.exists) {
62115
- const rename = await findRenames(root, path17.relative(root, resolved));
62749
+ const rename = await findRenames(root, path18.relative(root, resolved));
62116
62750
  if (rename) {
62117
62751
  result.renamed = true;
62118
62752
  result.newPath = rename.newPath;
@@ -63530,8 +64164,8 @@ var init_suggestSimilar = __esm({
63530
64164
  // node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/command.js
63531
64165
  import { EventEmitter as EventEmitter2 } from "node:events";
63532
64166
  import childProcess from "node:child_process";
63533
- import path18 from "node:path";
63534
- import fs13 from "node:fs";
64167
+ import path19 from "node:path";
64168
+ import fs14 from "node:fs";
63535
64169
  import process5 from "node:process";
63536
64170
  import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
63537
64171
  function incrementNodeInspectorPort(args2) {
@@ -64569,7 +65203,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
64569
65203
  * @param {string} subcommandName
64570
65204
  */
64571
65205
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
64572
- if (fs13.existsSync(executableFile)) return;
65206
+ if (fs14.existsSync(executableFile)) return;
64573
65207
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
64574
65208
  const executableMissing = `'${executableFile}' does not exist
64575
65209
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -64586,11 +65220,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
64586
65220
  args2 = args2.slice();
64587
65221
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
64588
65222
  function findFile(baseDir, baseName) {
64589
- const localBin = path18.resolve(baseDir, baseName);
64590
- if (fs13.existsSync(localBin)) return localBin;
64591
- if (sourceExt.includes(path18.extname(baseName))) return void 0;
65223
+ const localBin = path19.resolve(baseDir, baseName);
65224
+ if (fs14.existsSync(localBin)) return localBin;
65225
+ if (sourceExt.includes(path19.extname(baseName))) return void 0;
64592
65226
  const foundExt = sourceExt.find(
64593
- (ext) => fs13.existsSync(`${localBin}${ext}`)
65227
+ (ext) => fs14.existsSync(`${localBin}${ext}`)
64594
65228
  );
64595
65229
  if (foundExt) return `${localBin}${foundExt}`;
64596
65230
  return void 0;
@@ -64602,21 +65236,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
64602
65236
  if (this._scriptPath) {
64603
65237
  let resolvedScriptPath;
64604
65238
  try {
64605
- resolvedScriptPath = fs13.realpathSync(this._scriptPath);
65239
+ resolvedScriptPath = fs14.realpathSync(this._scriptPath);
64606
65240
  } catch {
64607
65241
  resolvedScriptPath = this._scriptPath;
64608
65242
  }
64609
- executableDir = path18.resolve(
64610
- path18.dirname(resolvedScriptPath),
65243
+ executableDir = path19.resolve(
65244
+ path19.dirname(resolvedScriptPath),
64611
65245
  executableDir
64612
65246
  );
64613
65247
  }
64614
65248
  if (executableDir) {
64615
65249
  let localFile = findFile(executableDir, executableFile);
64616
65250
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
64617
- const legacyName = path18.basename(
65251
+ const legacyName = path19.basename(
64618
65252
  this._scriptPath,
64619
- path18.extname(this._scriptPath)
65253
+ path19.extname(this._scriptPath)
64620
65254
  );
64621
65255
  if (legacyName !== this._name) {
64622
65256
  localFile = findFile(
@@ -64627,7 +65261,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
64627
65261
  }
64628
65262
  executableFile = localFile || executableFile;
64629
65263
  }
64630
- const launchWithNode = sourceExt.includes(path18.extname(executableFile));
65264
+ const launchWithNode = sourceExt.includes(path19.extname(executableFile));
64631
65265
  let proc;
64632
65266
  if (process5.platform !== "win32") {
64633
65267
  if (launchWithNode) {
@@ -65544,7 +66178,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
65544
66178
  * @return {Command}
65545
66179
  */
65546
66180
  nameFromFilename(filename) {
65547
- this._name = path18.basename(filename, path18.extname(filename));
66181
+ this._name = path19.basename(filename, path19.extname(filename));
65548
66182
  return this;
65549
66183
  }
65550
66184
  /**
@@ -65558,9 +66192,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
65558
66192
  * @param {string} [path]
65559
66193
  * @return {(string|null|Command)}
65560
66194
  */
65561
- executableDir(path20) {
65562
- if (path20 === void 0) return this._executableDir;
65563
- this._executableDir = path20;
66195
+ executableDir(path21) {
66196
+ if (path21 === void 0) return this._executableDir;
66197
+ this._executableDir = path21;
65564
66198
  return this;
65565
66199
  }
65566
66200
  /**
@@ -68893,7 +69527,7 @@ var init_ora = __esm({
68893
69527
  });
68894
69528
 
68895
69529
  // src/core/reporter.ts
68896
- import { existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
69530
+ import { existsSync as existsSync8, readFileSync as readFileSync11 } from "node:fs";
68897
69531
  import { join as join16 } from "node:path";
68898
69532
  function classifyFile(f) {
68899
69533
  if (f.path === "(project)") return "context";
@@ -68920,7 +69554,7 @@ function detectVersionSkew(projectRoot, runningVersion) {
68920
69554
  try {
68921
69555
  const pkgPath = join16(projectRoot, "package.json");
68922
69556
  if (!existsSync8(pkgPath)) return null;
68923
- const raw = readFileSync10(pkgPath, "utf8").replace(/^\uFEFF/, "");
69557
+ const raw = readFileSync11(pkgPath, "utf8").replace(/^\uFEFF/, "");
68924
69558
  const pkg = JSON.parse(raw);
68925
69559
  const name = pkg.name ?? "";
68926
69560
  if (name !== "ctxlint" && name !== "@yawlabs/ctxlint") return null;
@@ -69336,6 +69970,13 @@ function buildRuleDescriptors() {
69336
69970
  },
69337
69971
  helpUri: "https://github.com/yawlabs/ctxlint#what-it-checks"
69338
69972
  },
69973
+ {
69974
+ id: "ctxlint/session-unresolvable-sha",
69975
+ shortDescription: {
69976
+ text: "Memory cites a git SHA that no longer resolves in the repository"
69977
+ },
69978
+ helpUri: "https://github.com/yawlabs/ctxlint#what-it-checks"
69979
+ },
69339
69980
  {
69340
69981
  id: "ctxlint/skill-frontmatter",
69341
69982
  shortDescription: { text: "Skill/agent definition missing required frontmatter" },
@@ -69406,8 +70047,8 @@ __export(cli_exports, {
69406
70047
  promptYesNo: () => promptYesNo,
69407
70048
  runCli: () => runCli
69408
70049
  });
69409
- import * as fs14 from "node:fs";
69410
- import * as path19 from "node:path";
70050
+ import * as fs15 from "node:fs";
70051
+ import * as path20 from "node:path";
69411
70052
  function validateCheckNames(names, source) {
69412
70053
  const invalid = names.filter((n7) => n7 && !VALID_CHECKS.has(n7));
69413
70054
  if (invalid.length > 0) {
@@ -69430,7 +70071,7 @@ async function runCli() {
69430
70071
  "Also scan the user-global ~/.claude/settings.json in the dead-hook check (off by default; the standard run only reads project .claude/settings.json[.local])",
69431
70072
  false
69432
70073
  ).option("--no-ignore-file", "Disable .ctxlintignore suppression (see all findings)").option("--watch", "Re-lint on context file changes", false).action(async (projectPath, opts) => {
69433
- const resolvedPath = path19.resolve(projectPath);
70074
+ const resolvedPath = path20.resolve(projectPath);
69434
70075
  const { config: config2, options, activeChecks } = resolveSession(resolvedPath, opts);
69435
70076
  const spinner = options.format === "text" && !options.quiet ? ora("Scanning for context files...").start() : void 0;
69436
70077
  try {
@@ -69561,41 +70202,41 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
69561
70202
  const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
69562
70203
  console.log(chalk2.dim("\nWatching for changes... (Ctrl+C to stop)\n"));
69563
70204
  const watchPaths = [
69564
- path19.join(resolvedPath, "CLAUDE.md"),
69565
- path19.join(resolvedPath, "CLAUDE.local.md"),
69566
- path19.join(resolvedPath, "AGENTS.md"),
69567
- path19.join(resolvedPath, "AGENT.md"),
69568
- path19.join(resolvedPath, ".cursorrules"),
69569
- path19.join(resolvedPath, ".windsurfrules"),
69570
- path19.join(resolvedPath, ".clinerules"),
69571
- path19.join(resolvedPath, ".aiderules"),
69572
- path19.join(resolvedPath, ".continuerules"),
69573
- path19.join(resolvedPath, ".rules"),
69574
- path19.join(resolvedPath, ".goosehints"),
69575
- path19.join(resolvedPath, "GEMINI.md"),
69576
- path19.join(resolvedPath, "replit.md"),
69577
- path19.join(resolvedPath, "package.json"),
69578
- path19.join(resolvedPath, ".mcp.json"),
70205
+ path20.join(resolvedPath, "CLAUDE.md"),
70206
+ path20.join(resolvedPath, "CLAUDE.local.md"),
70207
+ path20.join(resolvedPath, "AGENTS.md"),
70208
+ path20.join(resolvedPath, "AGENT.md"),
70209
+ path20.join(resolvedPath, ".cursorrules"),
70210
+ path20.join(resolvedPath, ".windsurfrules"),
70211
+ path20.join(resolvedPath, ".clinerules"),
70212
+ path20.join(resolvedPath, ".aiderules"),
70213
+ path20.join(resolvedPath, ".continuerules"),
70214
+ path20.join(resolvedPath, ".rules"),
70215
+ path20.join(resolvedPath, ".goosehints"),
70216
+ path20.join(resolvedPath, "GEMINI.md"),
70217
+ path20.join(resolvedPath, "replit.md"),
70218
+ path20.join(resolvedPath, "package.json"),
70219
+ path20.join(resolvedPath, ".mcp.json"),
69579
70220
  // ctxlint config — re-resolve on edit so threshold changes,
69580
70221
  // ignore-list edits, and check-list overrides take effect without
69581
70222
  // restarting the watcher.
69582
- path19.join(resolvedPath, ".ctxlintrc"),
69583
- path19.join(resolvedPath, ".ctxlintrc.json"),
70223
+ path20.join(resolvedPath, ".ctxlintrc"),
70224
+ path20.join(resolvedPath, ".ctxlintrc.json"),
69584
70225
  // .ctxlintignore — re-lint when suppression rules change.
69585
- path19.join(resolvedPath, ".ctxlintignore")
70226
+ path20.join(resolvedPath, ".ctxlintignore")
69586
70227
  ];
69587
70228
  const watchDirs = [
69588
- path19.join(resolvedPath, ".claude"),
69589
- path19.join(resolvedPath, ".cursor"),
69590
- path19.join(resolvedPath, ".github"),
69591
- path19.join(resolvedPath, ".windsurf"),
69592
- path19.join(resolvedPath, ".aide"),
69593
- path19.join(resolvedPath, ".amazonq"),
69594
- path19.join(resolvedPath, ".goose"),
69595
- path19.join(resolvedPath, ".junie"),
69596
- path19.join(resolvedPath, ".aiassistant"),
69597
- path19.join(resolvedPath, ".continue"),
69598
- path19.join(resolvedPath, ".vscode")
70229
+ path20.join(resolvedPath, ".claude"),
70230
+ path20.join(resolvedPath, ".cursor"),
70231
+ path20.join(resolvedPath, ".github"),
70232
+ path20.join(resolvedPath, ".windsurf"),
70233
+ path20.join(resolvedPath, ".aide"),
70234
+ path20.join(resolvedPath, ".amazonq"),
70235
+ path20.join(resolvedPath, ".goose"),
70236
+ path20.join(resolvedPath, ".junie"),
70237
+ path20.join(resolvedPath, ".aiassistant"),
70238
+ path20.join(resolvedPath, ".continue"),
70239
+ path20.join(resolvedPath, ".vscode")
69599
70240
  ];
69600
70241
  const watchers = [];
69601
70242
  let debounceTimer = null;
@@ -69657,13 +70298,13 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
69657
70298
  };
69658
70299
  for (const filePath of watchPaths) {
69659
70300
  try {
69660
- watchers.push(fs14.watch(filePath, rerun));
70301
+ watchers.push(fs15.watch(filePath, rerun));
69661
70302
  } catch {
69662
70303
  }
69663
70304
  }
69664
70305
  for (const dir of watchDirs) {
69665
70306
  try {
69666
- watchers.push(fs14.watch(dir, { recursive: true }, rerun));
70307
+ watchers.push(fs15.watch(dir, { recursive: true }, rerun));
69667
70308
  } catch {
69668
70309
  }
69669
70310
  }
@@ -69684,17 +70325,17 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
69684
70325
  }
69685
70326
  });
69686
70327
  program2.command("init").description("Set up a git pre-commit hook that runs ctxlint --strict").argument("[path]", "Project directory", ".").action(async (projectPath) => {
69687
- const resolvedRoot = path19.resolve(projectPath);
69688
- const gitDir = path19.join(resolvedRoot, ".git");
69689
- const hooksDir = path19.join(gitDir, "hooks");
69690
- if (!fs14.existsSync(gitDir)) {
70328
+ const resolvedRoot = path20.resolve(projectPath);
70329
+ const gitDir = path20.join(resolvedRoot, ".git");
70330
+ const hooksDir = path20.join(gitDir, "hooks");
70331
+ if (!fs15.existsSync(gitDir)) {
69691
70332
  console.error('Error: not a git repository. Run "git init" first.');
69692
70333
  process.exit(1);
69693
70334
  }
69694
- if (!fs14.existsSync(hooksDir)) {
69695
- fs14.mkdirSync(hooksDir, { recursive: true });
70335
+ if (!fs15.existsSync(hooksDir)) {
70336
+ fs15.mkdirSync(hooksDir, { recursive: true });
69696
70337
  }
69697
- const hookPath = path19.join(hooksDir, "pre-commit");
70338
+ const hookPath = path20.join(hooksDir, "pre-commit");
69698
70339
  const fullHookContent = `#!/bin/sh
69699
70340
  # ctxlint pre-commit hook
69700
70341
  npx @yawlabs/ctxlint@${VERSION} --strict
@@ -69703,15 +70344,15 @@ npx @yawlabs/ctxlint@${VERSION} --strict
69703
70344
  # ctxlint pre-commit hook
69704
70345
  npx @yawlabs/ctxlint@${VERSION} --strict
69705
70346
  `;
69706
- if (fs14.existsSync(hookPath)) {
69707
- const existing = fs14.readFileSync(hookPath, "utf-8");
70347
+ if (fs15.existsSync(hookPath)) {
70348
+ const existing = fs15.readFileSync(hookPath, "utf-8");
69708
70349
  const installed = existing.match(
69709
70350
  /^[^#\r\n]*\bnpx\s+(?:-y\s+|--yes\s+)?@yawlabs\/ctxlint(?:@(\d+\.\d+\.\d+))?/m
69710
70351
  );
69711
70352
  if (installed) {
69712
70353
  const pinned = installed[1];
69713
70354
  if (pinned && pinned !== VERSION) {
69714
- fs14.writeFileSync(
70355
+ fs15.writeFileSync(
69715
70356
  hookPath,
69716
70357
  existing.replace(/(@yawlabs\/ctxlint@)\d+\.\d+\.\d+/g, `$1${VERSION}`)
69717
70358
  );
@@ -69721,10 +70362,10 @@ npx @yawlabs/ctxlint@${VERSION} --strict
69721
70362
  }
69722
70363
  return;
69723
70364
  }
69724
- fs14.appendFileSync(hookPath, appendHookContent);
70365
+ fs15.appendFileSync(hookPath, appendHookContent);
69725
70366
  console.log("Added ctxlint to existing pre-commit hook.");
69726
70367
  } else {
69727
- fs14.writeFileSync(hookPath, fullHookContent, { mode: 493 });
70368
+ fs15.writeFileSync(hookPath, fullHookContent, { mode: 493 });
69728
70369
  console.log("Created pre-commit hook at .git/hooks/pre-commit");
69729
70370
  }
69730
70371
  console.log("ctxlint will now run automatically before each commit.");
@@ -69746,7 +70387,7 @@ function resolveDepth(raw) {
69746
70387
  return Number.isNaN(parsed) ? 2 : Math.max(0, Math.min(parsed, 10));
69747
70388
  }
69748
70389
  function resolveSession(resolvedPath, opts, throwOnConfigError = false) {
69749
- const configPath = opts.config ? path19.resolve(opts.config) : void 0;
70390
+ const configPath = opts.config ? path20.resolve(opts.config) : void 0;
69750
70391
  const config2 = configPath ? loadConfigFromPath(configPath, throwOnConfigError) : loadConfig(resolvedPath);
69751
70392
  const mcpGlobal = opts.mcpGlobal || config2?.mcpGlobal || false;
69752
70393
  const mcpOnly = opts.mcpOnly || config2?.mcpOnly || false;