@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/.pre-commit-hooks.yaml +1 -1
- package/dist/index.js +310 -291
- package/package.json +1 -1
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:
|
|
452
|
-
const fullPath = [...
|
|
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,
|
|
732
|
+
constructor(parent, value, path13, key) {
|
|
733
733
|
this._cachedPath = [];
|
|
734
734
|
this.parent = parent;
|
|
735
735
|
this.data = value;
|
|
736
|
-
this._path =
|
|
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,
|
|
4242
|
-
if (!
|
|
4241
|
+
function getElementAtPath(obj, path13) {
|
|
4242
|
+
if (!path13)
|
|
4243
4243
|
return obj;
|
|
4244
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 = [...
|
|
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
|
|
4845
|
-
for (const seg of
|
|
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
|
|
17796
|
-
if (
|
|
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 (
|
|
17801
|
-
const key =
|
|
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(
|
|
25892
|
-
let input =
|
|
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 [
|
|
26092
|
-
wsComponent.path =
|
|
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,
|
|
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,
|
|
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(
|
|
35565
|
-
log(`checking %s`,
|
|
35564
|
+
function check2(path13, isFile, isDirectory2) {
|
|
35565
|
+
log(`checking %s`, path13);
|
|
35566
35566
|
try {
|
|
35567
|
-
const stat3 = fs_1.statSync(
|
|
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(
|
|
35588
|
-
return check2(
|
|
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(
|
|
36178
|
-
return (0, import_file_exists.exists)(
|
|
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(
|
|
36370
|
-
return /^\.(git)?$/.test(
|
|
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 [
|
|
36627
|
-
paths.add(
|
|
36628
|
-
(results[
|
|
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:
|
|
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,
|
|
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,
|
|
36931
|
+
return new InitSummary(bare, path13, false, result[1]);
|
|
36932
36932
|
}
|
|
36933
36933
|
if (result = reInitResponseRegex.exec(response)) {
|
|
36934
|
-
return new InitSummary(bare,
|
|
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,
|
|
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,
|
|
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"),
|
|
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,
|
|
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,
|
|
37242
|
+
handler(result, path13);
|
|
37243
37243
|
}
|
|
37244
37244
|
if (raw !== "##" && raw !== "!!") {
|
|
37245
|
-
result.files.push(new FileStatusSummary(
|
|
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
|
|
37433
|
-
return
|
|
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,
|
|
37573
|
-
return subModuleTask(["add", repo,
|
|
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,
|
|
38835
|
+
constructor(bare, path13, existing, gitDir) {
|
|
38836
38836
|
this.bare = bare;
|
|
38837
|
-
this.path =
|
|
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(
|
|
39371
|
-
this.path =
|
|
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(
|
|
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(
|
|
39637
|
+
hashObject(path13, write) {
|
|
39638
39638
|
return this._runTask(
|
|
39639
|
-
hashObjectTask(
|
|
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,
|
|
40277
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
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 (
|
|
40622
|
-
const
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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
|
|
42233
|
-
import * as
|
|
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 =
|
|
42281
|
+
const binPath = path4.join(projectRoot, "node_modules", ".bin", pkgName);
|
|
42284
42282
|
try {
|
|
42285
|
-
|
|
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 =
|
|
42329
|
+
const binPath = path4.join(projectRoot, "node_modules", ".bin", tool);
|
|
42332
42330
|
try {
|
|
42333
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
42511
|
-
import * as
|
|
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
|
|
42541
|
-
return ALWAYS_LOADED_BASENAMES.has(
|
|
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
|
-
|
|
42557
|
-
|
|
42558
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
43625
|
-
import * as
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
43830
|
-
const
|
|
43831
|
-
|
|
43832
|
-
|
|
43833
|
-
|
|
43834
|
-
|
|
43835
|
-
|
|
43836
|
-
|
|
43837
|
-
|
|
43838
|
-
|
|
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
|
|
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
|
|
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: `${
|
|
44356
|
-
suggestion: `Add "${
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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:
|
|
44632
|
-
{ provider: "codex-cli", dir:
|
|
44633
|
-
{ provider: "vibe-cli", dir:
|
|
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:
|
|
44627
|
+
dir: join5(home, ".aws", "amazonq")
|
|
44637
44628
|
},
|
|
44638
44629
|
{
|
|
44639
44630
|
provider: "goose",
|
|
44640
|
-
dir: process.platform === "win32" ?
|
|
44631
|
+
dir: process.platform === "win32" ? join5(process.env.APPDATA || "", "Block", "goose") : join5(home, ".config", "goose")
|
|
44641
44632
|
},
|
|
44642
|
-
{ provider: "continue", dir:
|
|
44633
|
+
{ provider: "continue", dir: join5(home, ".continue") },
|
|
44643
44634
|
{
|
|
44644
44635
|
provider: "windsurf",
|
|
44645
|
-
dir:
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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.
|
|
44728
|
-
if (linesA.
|
|
44729
|
-
let
|
|
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))
|
|
44724
|
+
if (linesB.has(line)) intersection2++;
|
|
44732
44725
|
}
|
|
44733
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
44799
|
-
if (!existsSync3(
|
|
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 =
|
|
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 =
|
|
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.
|
|
44902
|
-
let
|
|
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))
|
|
44900
|
+
if (linesB.has(line)) intersection2++;
|
|
44905
44901
|
}
|
|
44906
|
-
|
|
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("
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
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 =
|
|
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(
|
|
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-]
|
|
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
|
|
45241
|
-
import { resolve as resolve8, dirname as
|
|
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.
|
|
45245
|
-
const __dir =
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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("
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
47702
|
-
var
|
|
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 (
|
|
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 =
|
|
48715
|
-
if (
|
|
48716
|
-
if (sourceExt.includes(
|
|
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) =>
|
|
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 =
|
|
48730
|
+
resolvedScriptPath = fs10.realpathSync(this._scriptPath);
|
|
48731
48731
|
} catch {
|
|
48732
48732
|
resolvedScriptPath = this._scriptPath;
|
|
48733
48733
|
}
|
|
48734
|
-
executableDir =
|
|
48735
|
-
|
|
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 =
|
|
48742
|
+
const legacyName = path13.basename(
|
|
48743
48743
|
this._scriptPath,
|
|
48744
|
-
|
|
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(
|
|
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 =
|
|
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(
|
|
49685
|
-
if (
|
|
49686
|
-
this._executableDir =
|
|
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(
|
|
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("
|
|
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(` ${"
|
|
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(` ${"
|
|
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("
|
|
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("
|
|
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
|
|
53347
|
-
import * as
|
|
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 =
|
|
53437
|
+
const filePath = path11.join(projectRoot, filename);
|
|
53421
53438
|
let content;
|
|
53422
53439
|
try {
|
|
53423
|
-
content =
|
|
53440
|
+
content = fs8.readFileSync(filePath, "utf-8");
|
|
53424
53441
|
} catch {
|
|
53425
53442
|
continue;
|
|
53426
53443
|
}
|
|
53427
|
-
|
|
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
|
-
"
|
|
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
|
|
53470
|
-
import * as
|
|
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 =
|
|
53494
|
-
const configPath = opts.config ?
|
|
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
|
|
53504
|
-
const
|
|
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
|
|
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
|
-
|
|
53676
|
-
|
|
53677
|
-
|
|
53678
|
-
|
|
53679
|
-
|
|
53680
|
-
|
|
53681
|
-
|
|
53682
|
-
|
|
53683
|
-
|
|
53684
|
-
|
|
53685
|
-
|
|
53686
|
-
|
|
53687
|
-
|
|
53688
|
-
|
|
53689
|
-
|
|
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
|
-
|
|
53693
|
-
|
|
53694
|
-
|
|
53695
|
-
|
|
53696
|
-
|
|
53697
|
-
|
|
53698
|
-
|
|
53699
|
-
|
|
53700
|
-
|
|
53701
|
-
|
|
53702
|
-
|
|
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(
|
|
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(
|
|
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 =
|
|
53778
|
-
const gitDir =
|
|
53779
|
-
const hooksDir =
|
|
53780
|
-
if (!
|
|
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 (!
|
|
53785
|
-
|
|
53804
|
+
if (!fs9.existsSync(hooksDir)) {
|
|
53805
|
+
fs9.mkdirSync(hooksDir, { recursive: true });
|
|
53786
53806
|
}
|
|
53787
|
-
const hookPath =
|
|
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 (
|
|
53797
|
-
const existing =
|
|
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
|
-
|
|
53822
|
+
fs9.appendFileSync(hookPath, appendHookContent);
|
|
53803
53823
|
console.log("Added ctxlint to existing pre-commit hook.");
|
|
53804
53824
|
} else {
|
|
53805
|
-
|
|
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
|
-
|
|
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:
|
|
53847
|
+
console.error(`Error: ${detail}`);
|
|
53829
53848
|
process.exit(2);
|
|
53830
53849
|
}
|
|
53831
53850
|
}
|