@yawlabs/ctxlint 0.9.17 → 0.9.18

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
@@ -448,8 +448,8 @@ var init_parseUtil = __esm({
448
448
  init_errors();
449
449
  init_en();
450
450
  makeIssue = (params) => {
451
- const { data, path: path14, errorMaps, issueData } = params;
452
- const fullPath = [...path14, ...issueData.path || []];
451
+ const { data, path: path13, errorMaps, issueData } = params;
452
+ const fullPath = [...path13, ...issueData.path || []];
453
453
  const fullIssue = {
454
454
  ...issueData,
455
455
  path: fullPath
@@ -729,11 +729,11 @@ var init_types = __esm({
729
729
  init_parseUtil();
730
730
  init_util();
731
731
  ParseInputLazyPath = class {
732
- constructor(parent, value, path14, key) {
732
+ constructor(parent, value, path13, key) {
733
733
  this._cachedPath = [];
734
734
  this.parent = parent;
735
735
  this.data = value;
736
- this._path = path14;
736
+ this._path = path13;
737
737
  this._key = key;
738
738
  }
739
739
  get path() {
@@ -4238,10 +4238,10 @@ function mergeDefs(...defs) {
4238
4238
  function cloneDef(schema) {
4239
4239
  return mergeDefs(schema._zod.def);
4240
4240
  }
4241
- function getElementAtPath(obj, path14) {
4242
- if (!path14)
4241
+ function getElementAtPath(obj, path13) {
4242
+ if (!path13)
4243
4243
  return obj;
4244
- return path14.reduce((acc, key) => acc?.[key], obj);
4244
+ return path13.reduce((acc, key) => acc?.[key], obj);
4245
4245
  }
4246
4246
  function promiseAllObject(promisesObj) {
4247
4247
  const keys = Object.keys(promisesObj);
@@ -4553,11 +4553,11 @@ function aborted(x3, startIndex = 0) {
4553
4553
  }
4554
4554
  return false;
4555
4555
  }
4556
- function prefixIssues(path14, issues) {
4556
+ function prefixIssues(path13, issues) {
4557
4557
  return issues.map((iss) => {
4558
4558
  var _a3;
4559
4559
  (_a3 = iss).path ?? (_a3.path = []);
4560
- iss.path.unshift(path14);
4560
+ iss.path.unshift(path13);
4561
4561
  return iss;
4562
4562
  });
4563
4563
  }
@@ -4799,7 +4799,7 @@ function formatError(error49, mapper = (issue2) => issue2.message) {
4799
4799
  }
4800
4800
  function treeifyError(error49, mapper = (issue2) => issue2.message) {
4801
4801
  const result = { errors: [] };
4802
- const processError = (error50, path14 = []) => {
4802
+ const processError = (error50, path13 = []) => {
4803
4803
  var _a3, _b;
4804
4804
  for (const issue2 of error50.issues) {
4805
4805
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -4809,7 +4809,7 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
4809
4809
  } else if (issue2.code === "invalid_element") {
4810
4810
  processError({ issues: issue2.issues }, issue2.path);
4811
4811
  } else {
4812
- const fullpath = [...path14, ...issue2.path];
4812
+ const fullpath = [...path13, ...issue2.path];
4813
4813
  if (fullpath.length === 0) {
4814
4814
  result.errors.push(mapper(issue2));
4815
4815
  continue;
@@ -4841,8 +4841,8 @@ function treeifyError(error49, mapper = (issue2) => issue2.message) {
4841
4841
  }
4842
4842
  function toDotPath(_path) {
4843
4843
  const segs = [];
4844
- const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
4845
- for (const seg of path14) {
4844
+ const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
4845
+ for (const seg of path13) {
4846
4846
  if (typeof seg === "number")
4847
4847
  segs.push(`[${seg}]`);
4848
4848
  else if (typeof seg === "symbol")
@@ -17792,13 +17792,13 @@ function resolveRef(ref, ctx) {
17792
17792
  if (!ref.startsWith("#")) {
17793
17793
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
17794
17794
  }
17795
- const path14 = ref.slice(1).split("/").filter(Boolean);
17796
- if (path14.length === 0) {
17795
+ const path13 = ref.slice(1).split("/").filter(Boolean);
17796
+ if (path13.length === 0) {
17797
17797
  return ctx.rootSchema;
17798
17798
  }
17799
17799
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
17800
- if (path14[0] === defsKey) {
17801
- const key = path14[1];
17800
+ if (path13[0] === defsKey) {
17801
+ const key = path13[1];
17802
17802
  if (!key || !ctx.defs[key]) {
17803
17803
  throw new Error(`Reference not found: ${ref}`);
17804
17804
  }
@@ -25888,8 +25888,8 @@ var require_utils = __commonJS({
25888
25888
  }
25889
25889
  return ind;
25890
25890
  }
25891
- function removeDotSegments(path14) {
25892
- let input = path14;
25891
+ function removeDotSegments(path13) {
25892
+ let input = path13;
25893
25893
  const output = [];
25894
25894
  let nextSlash = -1;
25895
25895
  let len = 0;
@@ -26088,8 +26088,8 @@ var require_schemes = __commonJS({
26088
26088
  wsComponent.secure = void 0;
26089
26089
  }
26090
26090
  if (wsComponent.resourceName) {
26091
- const [path14, query] = wsComponent.resourceName.split("?");
26092
- wsComponent.path = path14 && path14 !== "/" ? path14 : void 0;
26091
+ const [path13, query] = wsComponent.resourceName.split("?");
26092
+ wsComponent.path = path13 && path13 !== "/" ? path13 : void 0;
26093
26093
  wsComponent.query = query;
26094
26094
  wsComponent.resourceName = void 0;
26095
26095
  }
@@ -29451,12 +29451,12 @@ var require_dist = __commonJS({
29451
29451
  throw new Error(`Unknown format "${name}"`);
29452
29452
  return f;
29453
29453
  };
29454
- function addFormats(ajv, list, fs11, exportName) {
29454
+ function addFormats(ajv, list, fs10, exportName) {
29455
29455
  var _a3;
29456
29456
  var _b;
29457
29457
  (_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
29458
29458
  for (const f of list)
29459
- ajv.addFormat(f, fs11[f]);
29459
+ ajv.addFormat(f, fs10[f]);
29460
29460
  }
29461
29461
  module.exports = exports = formatsPlugin;
29462
29462
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -35561,10 +35561,10 @@ var require_src2 = __commonJS({
35561
35561
  var fs_1 = __require("fs");
35562
35562
  var debug_1 = __importDefault(require_src());
35563
35563
  var log = debug_1.default("@kwsites/file-exists");
35564
- function check2(path14, isFile, isDirectory2) {
35565
- log(`checking %s`, path14);
35564
+ function check2(path13, isFile, isDirectory2) {
35565
+ log(`checking %s`, path13);
35566
35566
  try {
35567
- const stat3 = fs_1.statSync(path14);
35567
+ const stat3 = fs_1.statSync(path13);
35568
35568
  if (stat3.isFile() && isFile) {
35569
35569
  log(`[OK] path represents a file`);
35570
35570
  return true;
@@ -35584,8 +35584,8 @@ var require_src2 = __commonJS({
35584
35584
  throw e;
35585
35585
  }
35586
35586
  }
35587
- function exists2(path14, type = exports.READABLE) {
35588
- return check2(path14, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
35587
+ function exists2(path13, type = exports.READABLE) {
35588
+ return check2(path13, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
35589
35589
  }
35590
35590
  exports.exists = exists2;
35591
35591
  exports.FILE = 1;
@@ -36174,8 +36174,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
36174
36174
  function forEachLineWithContent(input, callback) {
36175
36175
  return toLinesWithContent(input, true).map((line) => callback(line));
36176
36176
  }
36177
- function folderExists(path14) {
36178
- return (0, import_file_exists.exists)(path14, import_file_exists.FOLDER);
36177
+ function folderExists(path13) {
36178
+ return (0, import_file_exists.exists)(path13, import_file_exists.FOLDER);
36179
36179
  }
36180
36180
  function append(target, item) {
36181
36181
  if (Array.isArray(target)) {
@@ -36366,8 +36366,8 @@ function checkIsRepoRootTask() {
36366
36366
  commands,
36367
36367
  format: "utf-8",
36368
36368
  onError,
36369
- parser(path14) {
36370
- return /^\.(git)?$/.test(path14.trim());
36369
+ parser(path13) {
36370
+ return /^\.(git)?$/.test(path13.trim());
36371
36371
  }
36372
36372
  };
36373
36373
  }
@@ -36623,11 +36623,11 @@ function parseGrep(grep) {
36623
36623
  const paths = /* @__PURE__ */ new Set();
36624
36624
  const results = {};
36625
36625
  forEachLineWithContent(grep, (input) => {
36626
- const [path14, line, preview] = input.split(NULL);
36627
- paths.add(path14);
36628
- (results[path14] = results[path14] || []).push({
36626
+ const [path13, line, preview] = input.split(NULL);
36627
+ paths.add(path13);
36628
+ (results[path13] = results[path13] || []).push({
36629
36629
  line: asNumber(line),
36630
- path: path14,
36630
+ path: path13,
36631
36631
  preview
36632
36632
  });
36633
36633
  });
@@ -36924,14 +36924,14 @@ function hashObjectTask(filePath, write) {
36924
36924
  }
36925
36925
  return straightThroughStringTask(commands, true);
36926
36926
  }
36927
- function parseInit(bare, path14, text) {
36927
+ function parseInit(bare, path13, text) {
36928
36928
  const response = String(text).trim();
36929
36929
  let result;
36930
36930
  if (result = initResponseRegex.exec(response)) {
36931
- return new InitSummary(bare, path14, false, result[1]);
36931
+ return new InitSummary(bare, path13, false, result[1]);
36932
36932
  }
36933
36933
  if (result = reInitResponseRegex.exec(response)) {
36934
- return new InitSummary(bare, path14, true, result[1]);
36934
+ return new InitSummary(bare, path13, true, result[1]);
36935
36935
  }
36936
36936
  let gitDir = "";
36937
36937
  const tokens = response.split(" ");
@@ -36942,12 +36942,12 @@ function parseInit(bare, path14, text) {
36942
36942
  break;
36943
36943
  }
36944
36944
  }
36945
- return new InitSummary(bare, path14, /^re/i.test(response), gitDir);
36945
+ return new InitSummary(bare, path13, /^re/i.test(response), gitDir);
36946
36946
  }
36947
36947
  function hasBareCommand(command) {
36948
36948
  return command.includes(bareCommand);
36949
36949
  }
36950
- function initTask(bare = false, path14, customArgs) {
36950
+ function initTask(bare = false, path13, customArgs) {
36951
36951
  const commands = ["init", ...customArgs];
36952
36952
  if (bare && !hasBareCommand(commands)) {
36953
36953
  commands.splice(1, 0, bareCommand);
@@ -36956,7 +36956,7 @@ function initTask(bare = false, path14, customArgs) {
36956
36956
  commands,
36957
36957
  format: "utf-8",
36958
36958
  parser(text) {
36959
- return parseInit(commands.includes("--bare"), path14, text);
36959
+ return parseInit(commands.includes("--bare"), path13, text);
36960
36960
  }
36961
36961
  };
36962
36962
  }
@@ -37235,14 +37235,14 @@ function splitLine(result, lineStr) {
37235
37235
  default:
37236
37236
  return;
37237
37237
  }
37238
- function data(index, workingDir, path14) {
37238
+ function data(index, workingDir, path13) {
37239
37239
  const raw = `${index}${workingDir}`;
37240
37240
  const handler = parsers6.get(raw);
37241
37241
  if (handler) {
37242
- handler(result, path14);
37242
+ handler(result, path13);
37243
37243
  }
37244
37244
  if (raw !== "##" && raw !== "!!") {
37245
- result.files.push(new FileStatusSummary(path14, index, workingDir));
37245
+ result.files.push(new FileStatusSummary(path13, index, workingDir));
37246
37246
  }
37247
37247
  }
37248
37248
  }
@@ -37429,8 +37429,8 @@ function deleteBranchTask(branch, forceDelete = false) {
37429
37429
  return task;
37430
37430
  }
37431
37431
  function toPath(input) {
37432
- const path14 = input.trim().replace(/^["']|["']$/g, "");
37433
- return path14 && normalize2(path14);
37432
+ const path13 = input.trim().replace(/^["']|["']$/g, "");
37433
+ return path13 && normalize2(path13);
37434
37434
  }
37435
37435
  function checkIgnoreTask(paths) {
37436
37436
  return {
@@ -37569,8 +37569,8 @@ function stashListTask(opt = {}, customArgs) {
37569
37569
  parser: parser4
37570
37570
  };
37571
37571
  }
37572
- function addSubModuleTask(repo, path14) {
37573
- return subModuleTask(["add", repo, path14]);
37572
+ function addSubModuleTask(repo, path13) {
37573
+ return subModuleTask(["add", repo, path13]);
37574
37574
  }
37575
37575
  function initSubModuleTask(customArgs) {
37576
37576
  return subModuleTask(["init", ...customArgs]);
@@ -38832,9 +38832,9 @@ var init_esm2 = __esm({
38832
38832
  "src/lib/responses/InitSummary.ts"() {
38833
38833
  "use strict";
38834
38834
  InitSummary = class {
38835
- constructor(bare, path14, existing, gitDir) {
38835
+ constructor(bare, path13, existing, gitDir) {
38836
38836
  this.bare = bare;
38837
- this.path = path14;
38837
+ this.path = path13;
38838
38838
  this.existing = existing;
38839
38839
  this.gitDir = gitDir;
38840
38840
  }
@@ -39367,12 +39367,12 @@ var init_esm2 = __esm({
39367
39367
  "use strict";
39368
39368
  fromPathRegex = /^(.+)\0(.+)$/;
39369
39369
  FileStatusSummary = class {
39370
- constructor(path14, index, working_dir) {
39371
- this.path = path14;
39370
+ constructor(path13, index, working_dir) {
39371
+ this.path = path13;
39372
39372
  this.index = index;
39373
39373
  this.working_dir = working_dir;
39374
39374
  if (index === "R" || working_dir === "R") {
39375
- const detail = fromPathRegex.exec(path14) || [null, path14, path14];
39375
+ const detail = fromPathRegex.exec(path13) || [null, path13, path13];
39376
39376
  this.from = detail[2] || "";
39377
39377
  this.path = detail[1] || "";
39378
39378
  }
@@ -39634,9 +39634,9 @@ var init_esm2 = __esm({
39634
39634
  next
39635
39635
  );
39636
39636
  }
39637
- hashObject(path14, write) {
39637
+ hashObject(path13, write) {
39638
39638
  return this._runTask(
39639
- hashObjectTask(path14, write === true),
39639
+ hashObjectTask(path13, write === true),
39640
39640
  trailingFunctionArgument(arguments)
39641
39641
  );
39642
39642
  }
@@ -40273,8 +40273,8 @@ var init_esm2 = __esm({
40273
40273
  }
40274
40274
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
40275
40275
  };
40276
- Git2.prototype.submoduleAdd = function(repo, path14, then) {
40277
- return this._runTask(addSubModuleTask2(repo, path14), trailingFunctionArgument2(arguments));
40276
+ Git2.prototype.submoduleAdd = function(repo, path13, then) {
40277
+ return this._runTask(addSubModuleTask2(repo, path13), trailingFunctionArgument2(arguments));
40278
40278
  };
40279
40279
  Git2.prototype.submoduleUpdate = function(args2, then) {
40280
40280
  return this._runTask(
@@ -40617,21 +40617,24 @@ async function findRenames(projectRoot, filePath) {
40617
40617
  filePath
40618
40618
  ]);
40619
40619
  if (!result.trim()) return null;
40620
+ let currentHash = "unknown";
40621
+ let currentDateStr;
40620
40622
  const lines = result.trim().split("\n");
40621
- for (let i2 = 0; i2 < lines.length; i2++) {
40622
- const line = lines[i2];
40623
+ for (const line of lines) {
40624
+ const headerMatch = line.match(/^([a-f0-9]{7,40})\s+(.+)$/);
40625
+ if (headerMatch) {
40626
+ currentHash = headerMatch[1].substring(0, 7);
40627
+ currentDateStr = headerMatch[2];
40628
+ continue;
40629
+ }
40623
40630
  if (line.startsWith("R")) {
40624
40631
  const parts = line.split(" ");
40625
40632
  if (parts.length >= 3) {
40626
- const hashLine = lines[i2 - 1] || "";
40627
- const hashMatch = hashLine.match(/^([a-f0-9]+)\s+(.+)/);
40628
- const commitHash = hashMatch?.[1]?.substring(0, 7) || "unknown";
40629
- const dateStr = hashMatch?.[2];
40630
- const daysAgo = dateStr ? Math.floor((Date.now() - new Date(dateStr).getTime()) / (1e3 * 60 * 60 * 24)) : 0;
40633
+ const daysAgo = currentDateStr ? Math.floor((Date.now() - new Date(currentDateStr).getTime()) / (1e3 * 60 * 60 * 24)) : 0;
40631
40634
  return {
40632
40635
  oldPath: parts[1],
40633
40636
  newPath: parts[2],
40634
- commitHash,
40637
+ commitHash: currentHash,
40635
40638
  daysAgo
40636
40639
  };
40637
40640
  }
@@ -41720,13 +41723,11 @@ var init_main = __esm({
41720
41723
  });
41721
41724
 
41722
41725
  // src/core/mcph-parser.ts
41723
- import * as fs4 from "node:fs";
41724
- import * as path3 from "node:path";
41725
41726
  async function parseMchpConfig(file2, projectRoot, scopeOverride) {
41726
41727
  const content = readFileContent(file2.absolutePath);
41727
41728
  const scope = scopeOverride ?? detectScope2(file2.relativePath);
41728
41729
  const isGitTracked = await checkGitTracked2(file2.absolutePath, projectRoot);
41729
- const isGitignored = checkGitignored(file2.absolutePath, projectRoot);
41730
+ const isGitignored = await checkGitignored(file2.absolutePath, projectRoot);
41730
41731
  const result = {
41731
41732
  filePath: file2.absolutePath,
41732
41733
  relativePath: file2.relativePath,
@@ -41864,17 +41865,14 @@ async function checkGitTracked2(filePath, projectRoot) {
41864
41865
  return false;
41865
41866
  }
41866
41867
  }
41867
- function checkGitignored(filePath, projectRoot) {
41868
- const gitignorePath = path3.join(projectRoot, ".gitignore");
41869
- let content;
41868
+ async function checkGitignored(filePath, projectRoot) {
41870
41869
  try {
41871
- content = fs4.readFileSync(gitignorePath, "utf-8");
41870
+ const git = getGit(projectRoot);
41871
+ const result = await git.raw(["check-ignore", "--", filePath]);
41872
+ return result.trim().length > 0;
41872
41873
  } catch {
41873
41874
  return false;
41874
41875
  }
41875
- const basename5 = path3.basename(filePath);
41876
- const patterns = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
41877
- return patterns.some((p2) => p2 === basename5 || p2 === `/${basename5}` || p2 === `./${basename5}`);
41878
41876
  }
41879
41877
  var KNOWN_FIELDS;
41880
41878
  var init_mcph_parser = __esm({
@@ -42111,7 +42109,7 @@ var require_levenshtein = __commonJS({
42111
42109
  });
42112
42110
 
42113
42111
  // src/core/checks/paths.ts
42114
- import * as path4 from "node:path";
42112
+ import * as path3 from "node:path";
42115
42113
  function getProjectFiles(projectRoot) {
42116
42114
  if (cachedProjectFiles?.root === projectRoot) return cachedProjectFiles.files;
42117
42115
  const files = getAllProjectFiles(projectRoot);
@@ -42124,10 +42122,10 @@ function resetPathsCache() {
42124
42122
  async function checkPaths(file2, projectRoot) {
42125
42123
  const issues = [];
42126
42124
  const projectFiles = getProjectFiles(projectRoot);
42127
- const contextDir = path4.dirname(file2.filePath);
42125
+ const contextDir = path3.dirname(file2.filePath);
42128
42126
  for (const ref of file2.references.paths) {
42129
42127
  const baseDir = ref.value.startsWith("./") || ref.value.startsWith("../") ? contextDir : projectRoot;
42130
- const resolvedPath = path4.resolve(baseDir, ref.value);
42128
+ const resolvedPath = path3.resolve(baseDir, ref.value);
42131
42129
  const normalizedRef = ref.value.replace(/\\/g, "/");
42132
42130
  if (normalizedRef.includes("*")) {
42133
42131
  const matches = await Ze(normalizedRef, { cwd: baseDir, nodir: false });
@@ -42145,7 +42143,7 @@ async function checkPaths(file2, projectRoot) {
42145
42143
  }
42146
42144
  const isDir = normalizedRef.endsWith("/");
42147
42145
  if (isDir) {
42148
- const dirPath = path4.resolve(baseDir, normalizedRef);
42146
+ const dirPath = path3.resolve(baseDir, normalizedRef);
42149
42147
  if (!isDirectory(dirPath)) {
42150
42148
  issues.push({
42151
42149
  severity: "error",
@@ -42190,12 +42188,12 @@ async function checkPaths(file2, projectRoot) {
42190
42188
  }
42191
42189
  function findClosestMatch(target, files) {
42192
42190
  const targetNorm = target.replace(/\\/g, "/");
42193
- const targetBase = path4.basename(targetNorm);
42191
+ const targetBase = path3.basename(targetNorm);
42194
42192
  let bestMatch = null;
42195
42193
  let bestDistance = Infinity;
42196
42194
  for (const file2 of files) {
42197
42195
  const fileNorm = file2.replace(/\\/g, "/");
42198
- if (path4.basename(fileNorm) === targetBase && fileNorm !== targetNorm) {
42196
+ if (path3.basename(fileNorm) === targetBase && fileNorm !== targetNorm) {
42199
42197
  const dist = levenshtein(targetNorm, fileNorm);
42200
42198
  if (dist < bestDistance) {
42201
42199
  bestDistance = dist;
@@ -42229,8 +42227,8 @@ var init_paths = __esm({
42229
42227
  });
42230
42228
 
42231
42229
  // src/core/checks/commands.ts
42232
- import * as fs5 from "node:fs";
42233
- import * as path5 from "node:path";
42230
+ import * as fs4 from "node:fs";
42231
+ import * as path4 from "node:path";
42234
42232
  async function checkCommands(file2, projectRoot) {
42235
42233
  const issues = [];
42236
42234
  const pkgJson = loadPackageJson(projectRoot);
@@ -42280,9 +42278,9 @@ async function checkCommands(file2, projectRoot) {
42280
42278
  ...pkgJson.optionalDependencies
42281
42279
  };
42282
42280
  if (!(pkgName in allDeps)) {
42283
- const binPath = path5.join(projectRoot, "node_modules", ".bin", pkgName);
42281
+ const binPath = path4.join(projectRoot, "node_modules", ".bin", pkgName);
42284
42282
  try {
42285
- fs5.accessSync(binPath);
42283
+ fs4.accessSync(binPath);
42286
42284
  } catch {
42287
42285
  issues.push({
42288
42286
  severity: "warning",
@@ -42328,9 +42326,9 @@ async function checkCommands(file2, projectRoot) {
42328
42326
  ...pkgJson.optionalDependencies
42329
42327
  };
42330
42328
  if (!(tool in allDeps)) {
42331
- const binPath = path5.join(projectRoot, "node_modules", ".bin", tool);
42329
+ const binPath = path4.join(projectRoot, "node_modules", ".bin", tool);
42332
42330
  try {
42333
- fs5.accessSync(binPath);
42331
+ fs4.accessSync(binPath);
42334
42332
  } catch {
42335
42333
  issues.push({
42336
42334
  severity: "warning",
@@ -42347,7 +42345,7 @@ async function checkCommands(file2, projectRoot) {
42347
42345
  }
42348
42346
  function loadMakefile(projectRoot) {
42349
42347
  try {
42350
- return fs5.readFileSync(path5.join(projectRoot, "Makefile"), "utf-8");
42348
+ return fs4.readFileSync(path4.join(projectRoot, "Makefile"), "utf-8");
42351
42349
  } catch {
42352
42350
  return null;
42353
42351
  }
@@ -42368,13 +42366,13 @@ var init_commands = __esm({
42368
42366
  });
42369
42367
 
42370
42368
  // src/core/checks/staleness.ts
42371
- import * as path6 from "node:path";
42369
+ import * as path5 from "node:path";
42372
42370
  async function checkStaleness(file2, projectRoot) {
42373
42371
  const issues = [];
42374
42372
  if (!await isGitRepo(projectRoot)) {
42375
42373
  return issues;
42376
42374
  }
42377
- const relativePath = path6.relative(projectRoot, file2.filePath).replace(/\\/g, "/");
42375
+ const relativePath = path5.relative(projectRoot, file2.filePath).replace(/\\/g, "/");
42378
42376
  const lastModified = await getFileLastModified(projectRoot, relativePath);
42379
42377
  if (!lastModified || isNaN(lastModified.getTime())) {
42380
42378
  return issues;
@@ -42507,8 +42505,8 @@ var init_tokens2 = __esm({
42507
42505
  });
42508
42506
 
42509
42507
  // src/core/checks/tier-tokens.ts
42510
- import * as fs6 from "node:fs";
42511
- import * as path7 from "node:path";
42508
+ import * as fs5 from "node:fs";
42509
+ import * as path6 from "node:path";
42512
42510
  function hasPathsFrontmatter(content) {
42513
42511
  const lines = content.split("\n");
42514
42512
  if (lines[0]?.trim() !== "---") return false;
@@ -42537,8 +42535,8 @@ function isAlwaysLoaded(file2) {
42537
42535
  if (rel.includes("/rules/")) {
42538
42536
  return !hasPathsFrontmatter(file2.content);
42539
42537
  }
42540
- const basename5 = rel.split("/").pop() ?? "";
42541
- return ALWAYS_LOADED_BASENAMES.has(basename5);
42538
+ const basename4 = rel.split("/").pop() ?? "";
42539
+ return ALWAYS_LOADED_BASENAMES.has(basename4);
42542
42540
  }
42543
42541
  function computeSectionCosts(file2) {
42544
42542
  if (file2.sections.length === 0) return [];
@@ -42553,14 +42551,14 @@ function computeSectionCosts(file2) {
42553
42551
  function loadSettingsSources(projectRoot) {
42554
42552
  const sources = [];
42555
42553
  const candidates = [
42556
- path7.join(projectRoot, ".claude", "settings.json"),
42557
- path7.join(projectRoot, ".claude", "settings.local.json"),
42558
- path7.join(process.env.HOME || process.env.USERPROFILE || "", ".claude", "settings.json")
42554
+ path6.join(projectRoot, ".claude", "settings.json"),
42555
+ path6.join(projectRoot, ".claude", "settings.local.json"),
42556
+ path6.join(process.env.HOME || process.env.USERPROFILE || "", ".claude", "settings.json")
42559
42557
  ];
42560
42558
  for (const p2 of candidates) {
42561
42559
  let content;
42562
42560
  try {
42563
- content = fs6.readFileSync(p2, "utf-8");
42561
+ content = fs5.readFileSync(p2, "utf-8");
42564
42562
  } catch {
42565
42563
  continue;
42566
42564
  }
@@ -42687,7 +42685,7 @@ var init_tier_tokens = __esm({
42687
42685
  });
42688
42686
 
42689
42687
  // src/core/checks/redundancy.ts
42690
- import * as path8 from "node:path";
42688
+ import * as path7 from "node:path";
42691
42689
  function compilePatterns(allDeps) {
42692
42690
  const compiled = [];
42693
42691
  for (const [pkg, mentions] of Object.entries(PACKAGE_TECH_MAP)) {
@@ -42752,7 +42750,7 @@ async function checkRedundancy(file2, projectRoot) {
42752
42750
  );
42753
42751
  if (dirMatch) {
42754
42752
  const dir = dirMatch[1].replace(/[`"]/g, "");
42755
- const fullPath = path8.resolve(projectRoot, dir);
42753
+ const fullPath = path7.resolve(projectRoot, dir);
42756
42754
  if (isDirectory(fullPath)) {
42757
42755
  issues.push({
42758
42756
  severity: "info",
@@ -43621,8 +43619,8 @@ var init_security = __esm({
43621
43619
  });
43622
43620
 
43623
43621
  // src/core/checks/mcp/commands.ts
43624
- import * as fs7 from "node:fs";
43625
- import * as path9 from "node:path";
43622
+ import * as fs6 from "node:fs";
43623
+ import * as path8 from "node:path";
43626
43624
  async function checkMcpCommands(config2, projectRoot) {
43627
43625
  const issues = [];
43628
43626
  if (config2.parseErrors.length > 0) return issues;
@@ -43639,7 +43637,7 @@ async function checkMcpCommands(config2, projectRoot) {
43639
43637
  });
43640
43638
  }
43641
43639
  if (LOCAL_PATH_PATTERN.test(server2.command)) {
43642
- const resolved = path9.resolve(projectRoot, server2.command);
43640
+ const resolved = path8.resolve(projectRoot, server2.command);
43643
43641
  if (!fileExistsSafe(resolved)) {
43644
43642
  issues.push({
43645
43643
  severity: "warning",
@@ -43654,7 +43652,7 @@ async function checkMcpCommands(config2, projectRoot) {
43654
43652
  for (const arg of server2.args) {
43655
43653
  if (URL_PREFIX.test(arg)) continue;
43656
43654
  if (LOCAL_PATH_PATTERN.test(arg) || FILE_PATH_PATTERN.test(arg)) {
43657
- const resolved = path9.resolve(projectRoot, arg);
43655
+ const resolved = path8.resolve(projectRoot, arg);
43658
43656
  if (!fileExistsSafe(resolved)) {
43659
43657
  issues.push({
43660
43658
  severity: "warning",
@@ -43672,7 +43670,7 @@ async function checkMcpCommands(config2, projectRoot) {
43672
43670
  }
43673
43671
  function fileExistsSafe(filePath) {
43674
43672
  try {
43675
- fs7.accessSync(filePath);
43673
+ fs6.accessSync(filePath);
43676
43674
  return true;
43677
43675
  } catch {
43678
43676
  return false;
@@ -43826,17 +43824,19 @@ async function checkMcpEnv(config2, _projectRoot) {
43826
43824
  }
43827
43825
  }
43828
43826
  }
43829
- for (const value of allValues) {
43830
- const refs = extractEnvVarRefs(value);
43831
- for (const ref of refs) {
43832
- if (!(ref.varName in process.env)) {
43833
- issues.push({
43834
- severity: "info",
43835
- check: "mcp-env",
43836
- ruleId: "unset-variable",
43837
- line: server2.line,
43838
- message: `Server "${server2.name}": environment variable "${ref.varName}" is not set`
43839
- });
43827
+ if (config2.client !== "continue") {
43828
+ for (const value of allValues) {
43829
+ const refs = extractEnvVarRefs(value);
43830
+ for (const ref of refs) {
43831
+ if (!(ref.varName in process.env)) {
43832
+ issues.push({
43833
+ severity: "info",
43834
+ check: "mcp-env",
43835
+ ruleId: "unset-variable",
43836
+ line: server2.line,
43837
+ message: `Server "${server2.name}": environment variable "${ref.varName}" is not set`
43838
+ });
43839
+ }
43840
43840
  }
43841
43841
  }
43842
43842
  }
@@ -44342,27 +44342,18 @@ var init_lists = __esm({
44342
44342
  });
44343
44343
 
44344
44344
  // src/core/checks/mcph/gitignore.ts
44345
- import * as path10 from "node:path";
44345
+ import * as path9 from "node:path";
44346
44346
  async function checkMcphGitignore(config2, _projectRoot) {
44347
44347
  const issues = [];
44348
44348
  if (config2.scope === "project-local" && !config2.isGitignored) {
44349
- const basename5 = path10.basename(config2.filePath);
44349
+ const basename4 = path9.basename(config2.filePath);
44350
44350
  issues.push({
44351
44351
  severity: "error",
44352
44352
  check: "mcph-gitignore",
44353
44353
  ruleId: "mcph-config/local-file-not-gitignored",
44354
44354
  line: 1,
44355
- message: `${basename5} is not covered by .gitignore \u2014 machine-local overrides can leak via git`,
44356
- suggestion: `Add "${basename5}" to .gitignore in your project root.`,
44357
- fix: {
44358
- file: path10.join(path10.dirname(config2.filePath), ".gitignore"),
44359
- line: 0,
44360
- oldText: "",
44361
- newText: `
44362
- # mcph CLI local overrides (machine-specific, never commit)
44363
- ${basename5}
44364
- `
44365
- }
44355
+ message: `${basename4} is not covered by .gitignore \u2014 machine-local overrides can leak via git`,
44356
+ suggestion: `Add "${basename4}" to .gitignore in your project root.`
44366
44357
  });
44367
44358
  }
44368
44359
  return issues;
@@ -44444,7 +44435,7 @@ var init_session_parser = __esm({
44444
44435
  import { readdir, stat } from "node:fs/promises";
44445
44436
  import { createReadStream } from "node:fs";
44446
44437
  import { createInterface } from "node:readline";
44447
- import { dirname as dirname3, join as join7, resolve as resolve4 } from "node:path";
44438
+ import { dirname as dirname2, join as join5, resolve as resolve4 } from "node:path";
44448
44439
  import { existsSync } from "node:fs";
44449
44440
  function detectProviders() {
44450
44441
  if (!home) return [];
@@ -44469,7 +44460,7 @@ async function parseJsonlFiltered(filePath, filter) {
44469
44460
  return results;
44470
44461
  }
44471
44462
  async function readClaudeHistory() {
44472
- const historyPath = join7(home, ".claude", "history.jsonl");
44463
+ const historyPath = join5(home, ".claude", "history.jsonl");
44473
44464
  return parseJsonlFiltered(historyPath, (entry) => {
44474
44465
  if (!entry.display || !entry.project) return null;
44475
44466
  return {
@@ -44482,7 +44473,7 @@ async function readClaudeHistory() {
44482
44473
  });
44483
44474
  }
44484
44475
  async function readCodexHistory() {
44485
- const historyPath = join7(home, ".codex", "history.jsonl");
44476
+ const historyPath = join5(home, ".codex", "history.jsonl");
44486
44477
  return parseJsonlFiltered(historyPath, (entry) => {
44487
44478
  if (!entry.display && !entry.command) return null;
44488
44479
  return {
@@ -44495,18 +44486,18 @@ async function readCodexHistory() {
44495
44486
  });
44496
44487
  }
44497
44488
  async function readClaudeMemories() {
44498
- const projectsDir = join7(home, ".claude", "projects");
44489
+ const projectsDir = join5(home, ".claude", "projects");
44499
44490
  if (!existsSync(projectsDir)) return [];
44500
44491
  const memories = [];
44501
44492
  const projectDirs = await readdir(projectsDir).catch(() => []);
44502
44493
  for (const projDir of projectDirs) {
44503
- const memoryDir = join7(projectsDir, projDir, "memory");
44494
+ const memoryDir = join5(projectsDir, projDir, "memory");
44504
44495
  if (!existsSync(memoryDir)) continue;
44505
44496
  const files = await readdir(memoryDir).catch(() => []);
44506
44497
  for (const file2 of files) {
44507
44498
  if (!file2.endsWith(".md") || file2 === "MEMORY.md") continue;
44508
44499
  try {
44509
- const entry = await parseMemoryFile(join7(memoryDir, file2), projDir);
44500
+ const entry = await parseMemoryFile(join5(memoryDir, file2), projDir);
44510
44501
  memories.push(entry);
44511
44502
  } catch {
44512
44503
  }
@@ -44516,14 +44507,14 @@ async function readClaudeMemories() {
44516
44507
  }
44517
44508
  function detectAiderInSiblings(siblings) {
44518
44509
  for (const sib of siblings) {
44519
- if (existsSync(join7(sib.path, ".aider.chat.history.md"))) {
44510
+ if (existsSync(join5(sib.path, ".aider.chat.history.md"))) {
44520
44511
  return "aider";
44521
44512
  }
44522
44513
  }
44523
44514
  return null;
44524
44515
  }
44525
44516
  async function detectSiblings(projectRoot) {
44526
- const parentDir = dirname3(resolve4(projectRoot));
44517
+ const parentDir = dirname2(resolve4(projectRoot));
44527
44518
  let entries;
44528
44519
  try {
44529
44520
  entries = await readdir(parentDir);
@@ -44533,7 +44524,7 @@ async function detectSiblings(projectRoot) {
44533
44524
  const candidates = [];
44534
44525
  for (const entry of entries) {
44535
44526
  if (entry.startsWith(".") || entry === "node_modules") continue;
44536
- const fullPath = join7(parentDir, entry);
44527
+ const fullPath = join5(parentDir, entry);
44537
44528
  const entryPath = resolve4(fullPath);
44538
44529
  if (entryPath === resolve4(projectRoot)) continue;
44539
44530
  try {
@@ -44542,7 +44533,7 @@ async function detectSiblings(projectRoot) {
44542
44533
  } catch {
44543
44534
  continue;
44544
44535
  }
44545
- const isProject = existsSync(join7(fullPath, ".git")) || existsSync(join7(fullPath, "package.json")) || existsSync(join7(fullPath, "Cargo.toml")) || existsSync(join7(fullPath, "go.mod")) || existsSync(join7(fullPath, "pyproject.toml"));
44536
+ const isProject = existsSync(join5(fullPath, ".git")) || existsSync(join5(fullPath, "package.json")) || existsSync(join5(fullPath, "Cargo.toml")) || existsSync(join5(fullPath, "go.mod")) || existsSync(join5(fullPath, "pyproject.toml"));
44546
44537
  if (!isProject) continue;
44547
44538
  candidates.push({ fullPath, entryPath, name: entry });
44548
44539
  }
@@ -44556,7 +44547,7 @@ async function detectSiblings(projectRoot) {
44556
44547
  if (orgMatch) currentOrg = orgMatch[1];
44557
44548
  } catch {
44558
44549
  }
44559
- const gitCandidates = candidates.filter((c3) => existsSync(join7(c3.fullPath, ".git")));
44550
+ const gitCandidates = candidates.filter((c3) => existsSync(join5(c3.fullPath, ".git")));
44560
44551
  const results = await Promise.all(
44561
44552
  gitCandidates.map(async (c3) => {
44562
44553
  const sibling = { path: c3.entryPath.replace(/\\/g, "/"), name: c3.name };
@@ -44628,28 +44619,28 @@ var init_session_scanner = __esm({
44628
44619
  init_session_parser();
44629
44620
  home = process.env.HOME || process.env.USERPROFILE || "";
44630
44621
  AGENT_DIRS = [
44631
- { provider: "claude-code", dir: join7(home, ".claude"), historyFile: "history.jsonl" },
44632
- { provider: "codex-cli", dir: join7(home, ".codex"), historyFile: "history.jsonl" },
44633
- { provider: "vibe-cli", dir: join7(home, ".vibe") },
44622
+ { provider: "claude-code", dir: join5(home, ".claude"), historyFile: "history.jsonl" },
44623
+ { provider: "codex-cli", dir: join5(home, ".codex"), historyFile: "history.jsonl" },
44624
+ { provider: "vibe-cli", dir: join5(home, ".vibe") },
44634
44625
  {
44635
44626
  provider: "amazon-q",
44636
- dir: join7(home, ".aws", "amazonq")
44627
+ dir: join5(home, ".aws", "amazonq")
44637
44628
  },
44638
44629
  {
44639
44630
  provider: "goose",
44640
- dir: process.platform === "win32" ? join7(process.env.APPDATA || "", "Block", "goose") : join7(home, ".config", "goose")
44631
+ dir: process.platform === "win32" ? join5(process.env.APPDATA || "", "Block", "goose") : join5(home, ".config", "goose")
44641
44632
  },
44642
- { provider: "continue", dir: join7(home, ".continue") },
44633
+ { provider: "continue", dir: join5(home, ".continue") },
44643
44634
  {
44644
44635
  provider: "windsurf",
44645
- dir: join7(home, ".windsurf")
44636
+ dir: join5(home, ".windsurf")
44646
44637
  }
44647
44638
  ];
44648
44639
  }
44649
44640
  });
44650
44641
 
44651
44642
  // src/core/checks/session/missing-secret.ts
44652
- import { resolve as resolve5, basename as basename4 } from "node:path";
44643
+ import { resolve as resolve5, basename as basename3 } from "node:path";
44653
44644
  function normalizePath(p2) {
44654
44645
  return resolve5(p2).replace(/\\/g, "/").toLowerCase();
44655
44646
  }
@@ -44673,7 +44664,7 @@ async function checkMissingSecret(ctx) {
44673
44664
  if (s.repo) byName.get(s.name).add(s.repo);
44674
44665
  }
44675
44666
  const currentNorm = normalizePath(ctx.currentProject);
44676
- const currentBase = basename4(currentNorm);
44667
+ const currentBase = basename3(currentNorm);
44677
44668
  for (const [secretName, projects] of byName) {
44678
44669
  const normalizedProjects = [...projects].map(normalizePath);
44679
44670
  const currentHas = normalizedProjects.some((p2) => {
@@ -44684,7 +44675,7 @@ async function checkMissingSecret(ctx) {
44684
44675
  if (currentHas) continue;
44685
44676
  const siblingMatches = ctx.siblings.filter((sib) => {
44686
44677
  const sibNorm = normalizePath(sib.path);
44687
- const sibBase = basename4(sibNorm);
44678
+ const sibBase = basename3(sibNorm);
44688
44679
  return normalizedProjects.some((p2) => {
44689
44680
  if (p2 === sibNorm) return true;
44690
44681
  const lastSegment = p2.split("/").pop() || "";
@@ -44717,25 +44708,28 @@ var init_missing_secret = __esm({
44717
44708
 
44718
44709
  // src/core/checks/session/diverged-file.ts
44719
44710
  import { readFile as readFile2 } from "node:fs/promises";
44720
- import { join as join8 } from "node:path";
44711
+ import { join as join6 } from "node:path";
44721
44712
  import { existsSync as existsSync2 } from "node:fs";
44722
44713
  function calculateOverlap(a, b2) {
44723
- const linesA = a.split("\n").map((l) => l.trim()).filter((l) => l.length > 3);
44714
+ const linesA = new Set(
44715
+ a.split("\n").map((l) => l.trim()).filter((l) => l.length > 3)
44716
+ );
44724
44717
  const linesB = new Set(
44725
44718
  b2.split("\n").map((l) => l.trim()).filter((l) => l.length > 3)
44726
44719
  );
44727
- if (linesA.length === 0 && linesB.size === 0) return 1;
44728
- if (linesA.length === 0 || linesB.size === 0) return 0;
44729
- let matches = 0;
44720
+ if (linesA.size === 0 && linesB.size === 0) return 1;
44721
+ if (linesA.size === 0 || linesB.size === 0) return 0;
44722
+ let intersection2 = 0;
44730
44723
  for (const line of linesA) {
44731
- if (linesB.has(line)) matches++;
44724
+ if (linesB.has(line)) intersection2++;
44732
44725
  }
44733
- return matches / Math.max(linesA.length, linesB.size);
44726
+ const unionSize = linesA.size + linesB.size - intersection2;
44727
+ return intersection2 / unionSize;
44734
44728
  }
44735
44729
  async function checkDivergedFile(ctx) {
44736
44730
  const issues = [];
44737
44731
  for (const fileName of CANONICAL_FILES) {
44738
- const currentPath = join8(ctx.currentProject, fileName);
44732
+ const currentPath = join6(ctx.currentProject, fileName);
44739
44733
  if (!existsSync2(currentPath)) continue;
44740
44734
  let currentContent;
44741
44735
  try {
@@ -44745,7 +44739,7 @@ async function checkDivergedFile(ctx) {
44745
44739
  }
44746
44740
  const diverged = [];
44747
44741
  for (const sib of ctx.siblings) {
44748
- const sibPath = join8(sib.path, fileName);
44742
+ const sibPath = join6(sib.path, fileName);
44749
44743
  if (!existsSync2(sibPath)) continue;
44750
44744
  try {
44751
44745
  const sibContent = await readFile2(sibPath, "utf-8");
@@ -44791,12 +44785,12 @@ var init_diverged_file = __esm({
44791
44785
 
44792
44786
  // src/core/checks/session/missing-workflow.ts
44793
44787
  import { readdir as readdir2 } from "node:fs/promises";
44794
- import { join as join9 } from "node:path";
44788
+ import { join as join7 } from "node:path";
44795
44789
  import { existsSync as existsSync3 } from "node:fs";
44796
44790
  async function checkMissingWorkflow(ctx) {
44797
44791
  const issues = [];
44798
- const currentWorkflowDir = join9(ctx.currentProject, ".github", "workflows");
44799
- if (!existsSync3(join9(ctx.currentProject, ".github"))) return issues;
44792
+ const currentWorkflowDir = join7(ctx.currentProject, ".github", "workflows");
44793
+ if (!existsSync3(join7(ctx.currentProject, ".github"))) return issues;
44800
44794
  const currentWorkflows = /* @__PURE__ */ new Set();
44801
44795
  if (existsSync3(currentWorkflowDir)) {
44802
44796
  try {
@@ -44809,7 +44803,7 @@ async function checkMissingWorkflow(ctx) {
44809
44803
  }
44810
44804
  const workflowMap = /* @__PURE__ */ new Map();
44811
44805
  for (const sib of ctx.siblings) {
44812
- const sibWorkflowDir = join9(sib.path, ".github", "workflows");
44806
+ const sibWorkflowDir = join7(sib.path, ".github", "workflows");
44813
44807
  if (!existsSync3(sibWorkflowDir)) continue;
44814
44808
  try {
44815
44809
  const files = await readdir2(sibWorkflowDir);
@@ -44894,16 +44888,19 @@ var init_stale_memory = __esm({
44894
44888
 
44895
44889
  // src/core/checks/session/duplicate-memory.ts
44896
44890
  function calculateLineOverlap2(a, b2) {
44897
- const linesA = a.split("\n").map((l) => l.trim()).filter((l) => l.length > 5);
44891
+ const linesA = new Set(
44892
+ a.split("\n").map((l) => l.trim()).filter((l) => l.length > 5)
44893
+ );
44898
44894
  const linesB = new Set(
44899
44895
  b2.split("\n").map((l) => l.trim()).filter((l) => l.length > 5)
44900
44896
  );
44901
- if (linesA.length === 0 || linesB.size === 0) return 0;
44902
- let matches = 0;
44897
+ if (linesA.size === 0 || linesB.size === 0) return 0;
44898
+ let intersection2 = 0;
44903
44899
  for (const line of linesA) {
44904
- if (linesB.has(line)) matches++;
44900
+ if (linesB.has(line)) intersection2++;
44905
44901
  }
44906
- return matches / Math.max(linesA.length, linesB.size);
44902
+ const unionSize = linesA.size + linesB.size - intersection2;
44903
+ return intersection2 / unionSize;
44907
44904
  }
44908
44905
  async function checkDuplicateMemory(ctx) {
44909
44906
  const issues = [];
@@ -44913,6 +44910,9 @@ async function checkDuplicateMemory(ctx) {
44913
44910
  const a = ctx.memories[i2];
44914
44911
  const b2 = ctx.memories[j3];
44915
44912
  if (a.projectDir === b2.projectDir) continue;
44913
+ const aIsCurrent = projectDirMatchesPath(a.projectDir, ctx.currentProject);
44914
+ const bIsCurrent = projectDirMatchesPath(b2.projectDir, ctx.currentProject);
44915
+ if (!aIsCurrent && !bIsCurrent) continue;
44916
44916
  if (a.content.length < 50 || b2.content.length < 50) continue;
44917
44917
  const overlap = calculateLineOverlap2(a.content, b2.content);
44918
44918
  if (overlap < 0.6) continue;
@@ -44939,6 +44939,7 @@ async function checkDuplicateMemory(ctx) {
44939
44939
  var init_duplicate_memory = __esm({
44940
44940
  "src/core/checks/session/duplicate-memory.ts"() {
44941
44941
  "use strict";
44942
+ init_session_parser();
44942
44943
  }
44943
44944
  });
44944
44945
 
@@ -45010,7 +45011,7 @@ async function checkLoopDetection(ctx) {
45010
45011
  }
45011
45012
  const cycles = findCyclicPatterns(displays);
45012
45013
  for (const { cycle, repeats: reps } of cycles) {
45013
- const cycleStr = cycle.map((c3) => c3.length > 40 ? c3.slice(0, 37) + "..." : c3).join(" \u2192 ");
45014
+ const cycleStr = cycle.map((c3) => c3.length > 40 ? c3.slice(0, 37) + "..." : c3).join(" -> ");
45014
45015
  issues.push({
45015
45016
  severity: "warning",
45016
45017
  check: "session-loop-detection",
@@ -45034,12 +45035,12 @@ var init_loop_detection = __esm({
45034
45035
 
45035
45036
  // src/core/checks/session/memory-index-overflow.ts
45036
45037
  import { readFile as readFile3, stat as stat2 } from "node:fs/promises";
45037
- import { join as join10 } from "node:path";
45038
+ import { join as join8 } from "node:path";
45038
45039
  async function checkMemoryIndexOverflow(ctx) {
45039
45040
  const home2 = process.env.HOME || process.env.USERPROFILE || "";
45040
45041
  if (!home2) return [];
45041
45042
  const encoded = encodeProjectDir(ctx.currentProject);
45042
- const memoryFile = join10(home2, ".claude", "projects", encoded, "memory", "MEMORY.md");
45043
+ const memoryFile = join8(home2, ".claude", "projects", encoded, "memory", "MEMORY.md");
45043
45044
  let stats;
45044
45045
  try {
45045
45046
  stats = await stat2(memoryFile);
@@ -45090,10 +45091,10 @@ var init_memory_index_overflow = __esm({
45090
45091
 
45091
45092
  // src/core/checks/ci-coverage.ts
45092
45093
  import { readdir as readdir3, readFile as readFile4 } from "node:fs/promises";
45093
- import { join as join11 } from "node:path";
45094
+ import { join as join9 } from "node:path";
45094
45095
  import { existsSync as existsSync5 } from "node:fs";
45095
45096
  async function findReleaseWorkflows(projectRoot) {
45096
- const workflowDir = join11(projectRoot, ".github", "workflows");
45097
+ const workflowDir = join9(projectRoot, ".github", "workflows");
45097
45098
  if (!existsSync5(workflowDir)) return [];
45098
45099
  let files;
45099
45100
  try {
@@ -45109,7 +45110,7 @@ async function findReleaseWorkflows(projectRoot) {
45109
45110
  continue;
45110
45111
  }
45111
45112
  try {
45112
- const content = await readFile4(join11(workflowDir, f), "utf-8");
45113
+ const content = await readFile4(join9(workflowDir, f), "utf-8");
45113
45114
  const nameMatch = content.match(/^name:\s*(.+)$/m);
45114
45115
  if (nameMatch && RELEASE_FILENAME_PATTERNS.some((p2) => p2.test(nameMatch[1]))) {
45115
45116
  releaseWorkflows.push(f);
@@ -45164,10 +45165,10 @@ var init_ci_coverage = __esm({
45164
45165
 
45165
45166
  // src/core/checks/ci-secrets.ts
45166
45167
  import { readdir as readdir4, readFile as readFile5 } from "node:fs/promises";
45167
- import { join as join12 } from "node:path";
45168
+ import { join as join10 } from "node:path";
45168
45169
  import { existsSync as existsSync6 } from "node:fs";
45169
45170
  async function findSecretUsages(projectRoot) {
45170
- const workflowDir = join12(projectRoot, ".github", "workflows");
45171
+ const workflowDir = join10(projectRoot, ".github", "workflows");
45171
45172
  if (!existsSync6(workflowDir)) return [];
45172
45173
  let files;
45173
45174
  try {
@@ -45180,7 +45181,7 @@ async function findSecretUsages(projectRoot) {
45180
45181
  if (!(f.endsWith(".yml") || f.endsWith(".yaml"))) continue;
45181
45182
  let content;
45182
45183
  try {
45183
- content = await readFile5(join12(workflowDir, f), "utf-8");
45184
+ content = await readFile5(join10(workflowDir, f), "utf-8");
45184
45185
  } catch {
45185
45186
  continue;
45186
45187
  }
@@ -45197,7 +45198,7 @@ async function findSecretUsages(projectRoot) {
45197
45198
  }
45198
45199
  function contextMentionsSecret(files, secretName) {
45199
45200
  const escaped = secretName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
45200
- const pattern = new RegExp(escaped.replace(/_/g, "[_\\s-]?"), "i");
45201
+ const pattern = new RegExp(`\\b${escaped.replace(/_/g, "[_\\s-]")}\\b`, "i");
45201
45202
  return files.some((f) => pattern.test(f.content));
45202
45203
  }
45203
45204
  async function checkCiSecrets(files, projectRoot) {
@@ -45237,14 +45238,14 @@ var init_ci_secrets = __esm({
45237
45238
  });
45238
45239
 
45239
45240
  // src/version.ts
45240
- import { readFileSync as readFileSync5 } from "node:fs";
45241
- import { resolve as resolve8, dirname as dirname4 } from "node:path";
45241
+ import { readFileSync as readFileSync4 } from "node:fs";
45242
+ import { resolve as resolve8, dirname as dirname3 } from "node:path";
45242
45243
  import { fileURLToPath } from "node:url";
45243
45244
  function loadVersion() {
45244
- if (true) return "0.9.17";
45245
- const __dir = dirname4(fileURLToPath(import.meta.url));
45245
+ if (true) return "0.9.18";
45246
+ const __dir = dirname3(fileURLToPath(import.meta.url));
45246
45247
  const pkgPath = resolve8(__dir, "../package.json");
45247
- const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
45248
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
45248
45249
  return pkg.version;
45249
45250
  }
45250
45251
  var VERSION;
@@ -46138,7 +46139,7 @@ var init_source = __esm({
46138
46139
  });
46139
46140
 
46140
46141
  // src/core/fixer.ts
46141
- import * as fs8 from "node:fs";
46142
+ import * as fs7 from "node:fs";
46142
46143
  function applyFixes(result, options = {}) {
46143
46144
  const log = options.quiet ? () => {
46144
46145
  } : console.log.bind(console);
@@ -46180,12 +46181,11 @@ function applyFixes(result, options = {}) {
46180
46181
  let totalFixes = 0;
46181
46182
  const filesModified = [];
46182
46183
  for (const [filePath, fixes] of fixesByFile) {
46183
- const content = fs8.readFileSync(filePath, "utf-8");
46184
+ const content = fs7.readFileSync(filePath, "utf-8");
46184
46185
  const lines = content.split("\n");
46185
46186
  let modified = false;
46186
- const sortedFixes = [...fixes].sort((a, b2) => b2.line - a.line);
46187
46187
  const fixesByLine = /* @__PURE__ */ new Map();
46188
- for (const fix of sortedFixes) {
46188
+ for (const fix of fixes) {
46189
46189
  const existing = fixesByLine.get(fix.line) || [];
46190
46190
  existing.push(fix);
46191
46191
  fixesByLine.set(fix.line, existing);
@@ -46200,7 +46200,7 @@ function applyFixes(result, options = {}) {
46200
46200
  totalFixes++;
46201
46201
  const prefix = dryRun ? source_default.cyan(" Would fix") : source_default.green(" Fixed");
46202
46202
  log(
46203
- prefix + ` Line ${fix.line}: ${source_default.dim(fix.oldText)} ${source_default.dim("\u2192")} ${fix.newText}`
46203
+ prefix + ` Line ${fix.line}: ${source_default.dim(fix.oldText)} ${source_default.dim("->")} ${fix.newText}`
46204
46204
  );
46205
46205
  }
46206
46206
  }
@@ -46220,7 +46220,7 @@ function applyFixes(result, options = {}) {
46220
46220
  }
46221
46221
  }
46222
46222
  if (!dryRun) {
46223
- fs8.writeFileSync(filePath, newContent, "utf-8");
46223
+ fs7.writeFileSync(filePath, newContent, "utf-8");
46224
46224
  }
46225
46225
  filesModified.push(filePath);
46226
46226
  }
@@ -46236,13 +46236,13 @@ var init_fixer = __esm({
46236
46236
 
46237
46237
  // src/mcp/server.ts
46238
46238
  var server_exports = {};
46239
- import * as path11 from "node:path";
46239
+ import * as path10 from "node:path";
46240
46240
  function validateProjectPath(rawPath) {
46241
46241
  if (!rawPath) return process.cwd();
46242
46242
  if (PATH_DISALLOWED.test(rawPath)) {
46243
46243
  throw new Error("projectPath contains disallowed characters");
46244
46244
  }
46245
- const resolved = path11.resolve(rawPath);
46245
+ const resolved = path10.resolve(rawPath);
46246
46246
  if (!isDirectory(resolved)) {
46247
46247
  throw new Error("projectPath is not an existing directory");
46248
46248
  }
@@ -46328,7 +46328,7 @@ var init_server3 = __esm({
46328
46328
  try {
46329
46329
  validateFilePathInput(filePath);
46330
46330
  const root = validateProjectPath(projectPath);
46331
- const resolved = path11.resolve(root, filePath);
46331
+ const resolved = path10.resolve(root, filePath);
46332
46332
  const result = {
46333
46333
  path: filePath,
46334
46334
  exists: fileExists(resolved) || isDirectory(resolved)
@@ -47698,8 +47698,8 @@ var require_command = __commonJS({
47698
47698
  "node_modules/.pnpm/commander@14.0.3/node_modules/commander/lib/command.js"(exports) {
47699
47699
  var EventEmitter2 = __require("node:events").EventEmitter;
47700
47700
  var childProcess = __require("node:child_process");
47701
- var path14 = __require("node:path");
47702
- var fs11 = __require("node:fs");
47701
+ var path13 = __require("node:path");
47702
+ var fs10 = __require("node:fs");
47703
47703
  var process11 = __require("node:process");
47704
47704
  var { Argument: Argument2, humanReadableArgName } = require_argument();
47705
47705
  var { CommanderError: CommanderError2 } = require_error();
@@ -48693,7 +48693,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
48693
48693
  * @param {string} subcommandName
48694
48694
  */
48695
48695
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
48696
- if (fs11.existsSync(executableFile)) return;
48696
+ if (fs10.existsSync(executableFile)) return;
48697
48697
  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";
48698
48698
  const executableMissing = `'${executableFile}' does not exist
48699
48699
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -48711,11 +48711,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
48711
48711
  let launchWithNode = false;
48712
48712
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
48713
48713
  function findFile(baseDir, baseName) {
48714
- const localBin = path14.resolve(baseDir, baseName);
48715
- if (fs11.existsSync(localBin)) return localBin;
48716
- if (sourceExt.includes(path14.extname(baseName))) return void 0;
48714
+ const localBin = path13.resolve(baseDir, baseName);
48715
+ if (fs10.existsSync(localBin)) return localBin;
48716
+ if (sourceExt.includes(path13.extname(baseName))) return void 0;
48717
48717
  const foundExt = sourceExt.find(
48718
- (ext) => fs11.existsSync(`${localBin}${ext}`)
48718
+ (ext) => fs10.existsSync(`${localBin}${ext}`)
48719
48719
  );
48720
48720
  if (foundExt) return `${localBin}${foundExt}`;
48721
48721
  return void 0;
@@ -48727,21 +48727,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
48727
48727
  if (this._scriptPath) {
48728
48728
  let resolvedScriptPath;
48729
48729
  try {
48730
- resolvedScriptPath = fs11.realpathSync(this._scriptPath);
48730
+ resolvedScriptPath = fs10.realpathSync(this._scriptPath);
48731
48731
  } catch {
48732
48732
  resolvedScriptPath = this._scriptPath;
48733
48733
  }
48734
- executableDir = path14.resolve(
48735
- path14.dirname(resolvedScriptPath),
48734
+ executableDir = path13.resolve(
48735
+ path13.dirname(resolvedScriptPath),
48736
48736
  executableDir
48737
48737
  );
48738
48738
  }
48739
48739
  if (executableDir) {
48740
48740
  let localFile = findFile(executableDir, executableFile);
48741
48741
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
48742
- const legacyName = path14.basename(
48742
+ const legacyName = path13.basename(
48743
48743
  this._scriptPath,
48744
- path14.extname(this._scriptPath)
48744
+ path13.extname(this._scriptPath)
48745
48745
  );
48746
48746
  if (legacyName !== this._name) {
48747
48747
  localFile = findFile(
@@ -48752,7 +48752,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
48752
48752
  }
48753
48753
  executableFile = localFile || executableFile;
48754
48754
  }
48755
- launchWithNode = sourceExt.includes(path14.extname(executableFile));
48755
+ launchWithNode = sourceExt.includes(path13.extname(executableFile));
48756
48756
  let proc;
48757
48757
  if (process11.platform !== "win32") {
48758
48758
  if (launchWithNode) {
@@ -49667,7 +49667,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
49667
49667
  * @return {Command}
49668
49668
  */
49669
49669
  nameFromFilename(filename) {
49670
- this._name = path14.basename(filename, path14.extname(filename));
49670
+ this._name = path13.basename(filename, path13.extname(filename));
49671
49671
  return this;
49672
49672
  }
49673
49673
  /**
@@ -49681,9 +49681,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
49681
49681
  * @param {string} [path]
49682
49682
  * @return {(string|null|Command)}
49683
49683
  */
49684
- executableDir(path15) {
49685
- if (path15 === void 0) return this._executableDir;
49686
- this._executableDir = path15;
49684
+ executableDir(path14) {
49685
+ if (path14 === void 0) return this._executableDir;
49686
+ this._executableDir = path14;
49687
49687
  return this;
49688
49688
  }
49689
49689
  /**
@@ -53026,7 +53026,7 @@ function formatText(result, verbose = false) {
53026
53026
  for (const file2 of contextFiles) {
53027
53027
  let desc = ` ${file2.path} (${file2.tokens.toLocaleString()} tokens, ${file2.lines} lines)`;
53028
53028
  if (file2.isSymlink && file2.symlinkTarget) {
53029
- desc = ` ${file2.path} ${source_default.dim(`\u2192 ${file2.symlinkTarget} (symlink)`)}`;
53029
+ desc = ` ${file2.path} ${source_default.dim(`-> ${file2.symlinkTarget} (symlink)`)}`;
53030
53030
  }
53031
53031
  lines.push(desc);
53032
53032
  }
@@ -53048,7 +53048,7 @@ function formatText(result, verbose = false) {
53048
53048
  if (fileIssues.length === 0 && !verbose) continue;
53049
53049
  lines.push(source_default.underline(file2.path));
53050
53050
  if (fileIssues.length === 0) {
53051
- lines.push(source_default.green(" \u2713 All checks passed"));
53051
+ lines.push(source_default.green(" [ok] All checks passed"));
53052
53052
  } else {
53053
53053
  for (const issue2 of fileIssues) {
53054
53054
  lines.push(formatIssue(issue2));
@@ -53103,13 +53103,13 @@ function formatTokenReport(result) {
53103
53103
  lines.push(
53104
53104
  ` ${source_default.dim("File".padEnd(maxPathLen))} ${source_default.dim("Tokens".padStart(8))} ${source_default.dim("Lines".padStart(6))}`
53105
53105
  );
53106
- lines.push(` ${"\u2500".repeat(maxPathLen)} ${"\u2500".repeat(8)} ${"\u2500".repeat(6)}`);
53106
+ lines.push(` ${"-".repeat(maxPathLen)} ${"-".repeat(8)} ${"-".repeat(6)}`);
53107
53107
  for (const file2 of result.files) {
53108
53108
  const tokenStr = file2.tokens.toLocaleString().padStart(8);
53109
53109
  const lineStr = file2.lines.toString().padStart(6);
53110
53110
  lines.push(` ${file2.path.padEnd(maxPathLen)} ${tokenStr} ${lineStr}`);
53111
53111
  }
53112
- lines.push(` ${"\u2500".repeat(maxPathLen)} ${"\u2500".repeat(8)} ${"\u2500".repeat(6)}`);
53112
+ lines.push(` ${"-".repeat(maxPathLen)} ${"-".repeat(8)} ${"-".repeat(6)}`);
53113
53113
  lines.push(
53114
53114
  ` ${"Total".padEnd(maxPathLen)} ${result.summary.totalTokens.toLocaleString().padStart(8)}`
53115
53115
  );
@@ -53322,12 +53322,12 @@ function buildRuleDescriptors() {
53322
53322
  ];
53323
53323
  }
53324
53324
  function formatIssue(issue2) {
53325
- const icon = issue2.severity === "error" ? source_default.red("\u2717") : issue2.severity === "warning" ? source_default.yellow("\u26A0") : source_default.blue("\u2139");
53325
+ const icon = issue2.severity === "error" ? source_default.red("x") : issue2.severity === "warning" ? source_default.yellow("!") : source_default.blue("i");
53326
53326
  const lineRef = issue2.line > 0 ? `Line ${issue2.line}: ` : "";
53327
53327
  let line = ` ${icon} ${lineRef}${issue2.message}`;
53328
53328
  if (issue2.suggestion) {
53329
53329
  line += `
53330
- ${source_default.dim("\u2192")} ${source_default.dim(issue2.suggestion)}`;
53330
+ ${source_default.dim("->")} ${source_default.dim(issue2.suggestion)}`;
53331
53331
  }
53332
53332
  if (issue2.detail) {
53333
53333
  line += `
@@ -53343,8 +53343,8 @@ var init_reporter = __esm({
53343
53343
  });
53344
53344
 
53345
53345
  // src/core/config.ts
53346
- import * as fs9 from "node:fs";
53347
- import * as path12 from "node:path";
53346
+ import * as fs8 from "node:fs";
53347
+ import * as path11 from "node:path";
53348
53348
  function formatJsonError(content, err) {
53349
53349
  const msg = err instanceof Error ? err.message : String(err);
53350
53350
  const posMatch = msg.match(/position (\d+)/);
@@ -53415,33 +53415,46 @@ function warnUnknownKeys(config2, source) {
53415
53415
  console.error(`Warning: unknown config key "${k3}" in ${source}${suggestion}`);
53416
53416
  }
53417
53417
  }
53418
+ function parseConfigContent(content, source) {
53419
+ let parsed;
53420
+ try {
53421
+ parsed = JSON.parse(content);
53422
+ } catch (err) {
53423
+ throw new Error(`Invalid JSON in ${source}: ${formatJsonError(content, err)}`, {
53424
+ cause: err
53425
+ });
53426
+ }
53427
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
53428
+ throw new Error(
53429
+ `Invalid config in ${source}: expected a JSON object at the root, got ${Array.isArray(parsed) ? "an array" : typeof parsed}`
53430
+ );
53431
+ }
53432
+ warnUnknownKeys(parsed, source);
53433
+ return parsed;
53434
+ }
53418
53435
  function loadConfig(projectRoot) {
53419
53436
  for (const filename of CONFIG_FILENAMES) {
53420
- const filePath = path12.join(projectRoot, filename);
53437
+ const filePath = path11.join(projectRoot, filename);
53421
53438
  let content;
53422
53439
  try {
53423
- content = fs9.readFileSync(filePath, "utf-8");
53440
+ content = fs8.readFileSync(filePath, "utf-8");
53424
53441
  } catch {
53425
53442
  continue;
53426
53443
  }
53427
- let parsed;
53428
- try {
53429
- parsed = JSON.parse(content);
53430
- } catch (err) {
53431
- throw new Error(`Invalid JSON in ${filePath}: ${formatJsonError(content, err)}`, {
53432
- cause: err
53433
- });
53434
- }
53435
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
53436
- throw new Error(
53437
- `Invalid config in ${filePath}: expected a JSON object at the root, got ${Array.isArray(parsed) ? "an array" : typeof parsed}`
53438
- );
53439
- }
53440
- warnUnknownKeys(parsed, filePath);
53441
- return parsed;
53444
+ return parseConfigContent(content, filePath);
53442
53445
  }
53443
53446
  return null;
53444
53447
  }
53448
+ function loadConfigFromExplicitPath(configPath) {
53449
+ let content;
53450
+ try {
53451
+ content = fs8.readFileSync(configPath, "utf-8");
53452
+ } catch (err) {
53453
+ const detail = err instanceof Error ? err.message : String(err);
53454
+ throw new Error(`could not load config from ${configPath}: ${detail}`, { cause: err });
53455
+ }
53456
+ return parseConfigContent(content, configPath);
53457
+ }
53445
53458
  var import_fast_levenshtein2, levenshtein2, KNOWN_CONFIG_KEYS, CONFIG_FILENAMES;
53446
53459
  var init_config2 = __esm({
53447
53460
  "src/core/config.ts"() {
@@ -53455,7 +53468,14 @@ var init_config2 = __esm({
53455
53468
  "tokenThresholds",
53456
53469
  "contextFiles",
53457
53470
  "mcp",
53458
- "mcpGlobal"
53471
+ "mcpOnly",
53472
+ "mcpGlobal",
53473
+ "mcph",
53474
+ "mcphOnly",
53475
+ "mcphGlobal",
53476
+ "mcphStrictEnvToken",
53477
+ "session",
53478
+ "sessionOnly"
53459
53479
  ];
53460
53480
  CONFIG_FILENAMES = [".ctxlintrc", ".ctxlintrc.json"];
53461
53481
  }
@@ -53466,8 +53486,8 @@ var cli_exports = {};
53466
53486
  __export(cli_exports, {
53467
53487
  runCli: () => runCli
53468
53488
  });
53469
- import * as fs10 from "node:fs";
53470
- import * as path13 from "node:path";
53489
+ import * as fs9 from "node:fs";
53490
+ import * as path12 from "node:path";
53471
53491
  function validateCheckNames(names, source) {
53472
53492
  const invalid = names.filter((n7) => n7 && !VALID_CHECKS.has(n7));
53473
53493
  if (invalid.length > 0) {
@@ -53490,18 +53510,18 @@ async function runCli() {
53490
53510
  "Upgrade mcph-config/prefer-env-token from warning to error (strict env-var-only posture)",
53491
53511
  false
53492
53512
  ).option("--session", "Run session audit checks (cross-project consistency)", false).option("--session-only", "Run only session checks, skip context and MCP checks", false).option("--watch", "Re-lint on context file changes", false).action(async (projectPath, opts) => {
53493
- const resolvedPath = path13.resolve(projectPath);
53494
- const configPath = opts.config ? path13.resolve(opts.config) : void 0;
53513
+ const resolvedPath = path12.resolve(projectPath);
53514
+ const configPath = opts.config ? path12.resolve(opts.config) : void 0;
53495
53515
  const config2 = configPath ? loadConfigFromPath(configPath) : loadConfig(resolvedPath);
53496
- const mcpGlobal = opts.mcpGlobal || false;
53497
- const mcpOnly = opts.mcpOnly || false;
53516
+ const mcpGlobal = opts.mcpGlobal || config2?.mcpGlobal || false;
53517
+ const mcpOnly = opts.mcpOnly || config2?.mcpOnly || false;
53498
53518
  const mcpFlag = opts.mcp || mcpGlobal || mcpOnly || config2?.mcp || false;
53499
- const mcphGlobal = opts.mcphGlobal || false;
53500
- const mcphOnly = opts.mcphOnly || false;
53501
- const mcphFlag = opts.mcph || mcphGlobal || mcphOnly || false;
53502
- const mcphStrictEnvToken = opts.mcphStrictEnvToken || false;
53503
- const sessionFlag = opts.session || false;
53504
- const sessionOnly = opts.sessionOnly || false;
53519
+ const mcphGlobal = opts.mcphGlobal || config2?.mcphGlobal || false;
53520
+ const mcphOnly = opts.mcphOnly || config2?.mcphOnly || false;
53521
+ const mcphFlag = opts.mcph || mcphGlobal || mcphOnly || config2?.mcph || false;
53522
+ const mcphStrictEnvToken = opts.mcphStrictEnvToken || config2?.mcphStrictEnvToken || false;
53523
+ const sessionOnly = opts.sessionOnly || config2?.sessionOnly || false;
53524
+ const sessionFlag = opts.session || sessionOnly || config2?.session || false;
53505
53525
  let explicitChecks = opts.checks ? validateCheckNames(
53506
53526
  opts.checks.split(",").map((c3) => c3.trim()),
53507
53527
  "--checks"
@@ -53547,7 +53567,7 @@ async function runCli() {
53547
53567
  depth: Math.max(0, Math.min(parseInt(opts.depth, 10) || 2, 10)),
53548
53568
  mcp: effectiveMcp,
53549
53569
  mcpOnly,
53550
- mcpGlobal: mcpGlobal || config2?.mcpGlobal || false,
53570
+ mcpGlobal,
53551
53571
  mcph: effectiveMcph,
53552
53572
  mcphOnly,
53553
53573
  mcphGlobal,
@@ -53672,34 +53692,34 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
53672
53692
  const chalk2 = (await Promise.resolve().then(() => (init_source(), source_exports))).default;
53673
53693
  console.log(chalk2.dim("\nWatching for changes... (Ctrl+C to stop)\n"));
53674
53694
  const watchPaths = [
53675
- path13.join(resolvedPath, "CLAUDE.md"),
53676
- path13.join(resolvedPath, "CLAUDE.local.md"),
53677
- path13.join(resolvedPath, "AGENTS.md"),
53678
- path13.join(resolvedPath, "AGENT.md"),
53679
- path13.join(resolvedPath, ".cursorrules"),
53680
- path13.join(resolvedPath, ".windsurfrules"),
53681
- path13.join(resolvedPath, ".clinerules"),
53682
- path13.join(resolvedPath, ".aiderules"),
53683
- path13.join(resolvedPath, ".continuerules"),
53684
- path13.join(resolvedPath, ".rules"),
53685
- path13.join(resolvedPath, ".goosehints"),
53686
- path13.join(resolvedPath, "GEMINI.md"),
53687
- path13.join(resolvedPath, "replit.md"),
53688
- path13.join(resolvedPath, "package.json"),
53689
- path13.join(resolvedPath, ".mcp.json")
53695
+ path12.join(resolvedPath, "CLAUDE.md"),
53696
+ path12.join(resolvedPath, "CLAUDE.local.md"),
53697
+ path12.join(resolvedPath, "AGENTS.md"),
53698
+ path12.join(resolvedPath, "AGENT.md"),
53699
+ path12.join(resolvedPath, ".cursorrules"),
53700
+ path12.join(resolvedPath, ".windsurfrules"),
53701
+ path12.join(resolvedPath, ".clinerules"),
53702
+ path12.join(resolvedPath, ".aiderules"),
53703
+ path12.join(resolvedPath, ".continuerules"),
53704
+ path12.join(resolvedPath, ".rules"),
53705
+ path12.join(resolvedPath, ".goosehints"),
53706
+ path12.join(resolvedPath, "GEMINI.md"),
53707
+ path12.join(resolvedPath, "replit.md"),
53708
+ path12.join(resolvedPath, "package.json"),
53709
+ path12.join(resolvedPath, ".mcp.json")
53690
53710
  ];
53691
53711
  const watchDirs = [
53692
- path13.join(resolvedPath, ".claude"),
53693
- path13.join(resolvedPath, ".cursor"),
53694
- path13.join(resolvedPath, ".github"),
53695
- path13.join(resolvedPath, ".windsurf"),
53696
- path13.join(resolvedPath, ".aide"),
53697
- path13.join(resolvedPath, ".amazonq"),
53698
- path13.join(resolvedPath, ".goose"),
53699
- path13.join(resolvedPath, ".junie"),
53700
- path13.join(resolvedPath, ".aiassistant"),
53701
- path13.join(resolvedPath, ".continue"),
53702
- path13.join(resolvedPath, ".vscode")
53712
+ path12.join(resolvedPath, ".claude"),
53713
+ path12.join(resolvedPath, ".cursor"),
53714
+ path12.join(resolvedPath, ".github"),
53715
+ path12.join(resolvedPath, ".windsurf"),
53716
+ path12.join(resolvedPath, ".aide"),
53717
+ path12.join(resolvedPath, ".amazonq"),
53718
+ path12.join(resolvedPath, ".goose"),
53719
+ path12.join(resolvedPath, ".junie"),
53720
+ path12.join(resolvedPath, ".aiassistant"),
53721
+ path12.join(resolvedPath, ".continue"),
53722
+ path12.join(resolvedPath, ".vscode")
53703
53723
  ];
53704
53724
  const watchers = [];
53705
53725
  let debounceTimer = null;
@@ -53747,13 +53767,13 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
53747
53767
  };
53748
53768
  for (const filePath of watchPaths) {
53749
53769
  try {
53750
- watchers.push(fs10.watch(filePath, rerun));
53770
+ watchers.push(fs9.watch(filePath, rerun));
53751
53771
  } catch {
53752
53772
  }
53753
53773
  }
53754
53774
  for (const dir of watchDirs) {
53755
53775
  try {
53756
- watchers.push(fs10.watch(dir, { recursive: true }, rerun));
53776
+ watchers.push(fs9.watch(dir, { recursive: true }, rerun));
53757
53777
  } catch {
53758
53778
  }
53759
53779
  }
@@ -53774,17 +53794,17 @@ Fixed ${applied.totalFixes} issue${applied.totalFixes !== 1 ? "s" : ""} in ${app
53774
53794
  }
53775
53795
  });
53776
53796
  program2.command("init").description("Set up a git pre-commit hook that runs ctxlint --strict").argument("[path]", "Project directory", ".").action(async (projectPath) => {
53777
- const resolvedRoot = path13.resolve(projectPath);
53778
- const gitDir = path13.join(resolvedRoot, ".git");
53779
- const hooksDir = path13.join(gitDir, "hooks");
53780
- if (!fs10.existsSync(gitDir)) {
53797
+ const resolvedRoot = path12.resolve(projectPath);
53798
+ const gitDir = path12.join(resolvedRoot, ".git");
53799
+ const hooksDir = path12.join(gitDir, "hooks");
53800
+ if (!fs9.existsSync(gitDir)) {
53781
53801
  console.error('Error: not a git repository. Run "git init" first.');
53782
53802
  process.exit(1);
53783
53803
  }
53784
- if (!fs10.existsSync(hooksDir)) {
53785
- fs10.mkdirSync(hooksDir, { recursive: true });
53804
+ if (!fs9.existsSync(hooksDir)) {
53805
+ fs9.mkdirSync(hooksDir, { recursive: true });
53786
53806
  }
53787
- const hookPath = path13.join(hooksDir, "pre-commit");
53807
+ const hookPath = path12.join(hooksDir, "pre-commit");
53788
53808
  const fullHookContent = `#!/bin/sh
53789
53809
  # ctxlint pre-commit hook
53790
53810
  npx @yawlabs/ctxlint@${VERSION} --strict
@@ -53793,16 +53813,16 @@ npx @yawlabs/ctxlint@${VERSION} --strict
53793
53813
  # ctxlint pre-commit hook
53794
53814
  npx @yawlabs/ctxlint@${VERSION} --strict
53795
53815
  `;
53796
- if (fs10.existsSync(hookPath)) {
53797
- const existing = fs10.readFileSync(hookPath, "utf-8");
53816
+ if (fs9.existsSync(hookPath)) {
53817
+ const existing = fs9.readFileSync(hookPath, "utf-8");
53798
53818
  if (existing.includes("ctxlint")) {
53799
53819
  console.log("Pre-commit hook already includes ctxlint.");
53800
53820
  return;
53801
53821
  }
53802
- fs10.appendFileSync(hookPath, appendHookContent);
53822
+ fs9.appendFileSync(hookPath, appendHookContent);
53803
53823
  console.log("Added ctxlint to existing pre-commit hook.");
53804
53824
  } else {
53805
- fs10.writeFileSync(hookPath, fullHookContent, { mode: 493 });
53825
+ fs9.writeFileSync(hookPath, fullHookContent, { mode: 493 });
53806
53826
  console.log("Created pre-commit hook at .git/hooks/pre-commit");
53807
53827
  }
53808
53828
  console.log("ctxlint will now run automatically before each commit.");
@@ -53821,11 +53841,10 @@ async function promptYesNo(question) {
53821
53841
  }
53822
53842
  function loadConfigFromPath(configPath) {
53823
53843
  try {
53824
- const content = fs10.readFileSync(configPath, "utf-8");
53825
- return JSON.parse(content);
53844
+ return loadConfigFromExplicitPath(configPath);
53826
53845
  } catch (err) {
53827
53846
  const detail = err instanceof Error ? err.message : String(err);
53828
- console.error(`Error: could not load config from ${configPath}: ${detail}`);
53847
+ console.error(`Error: ${detail}`);
53829
53848
  process.exit(2);
53830
53849
  }
53831
53850
  }