@yawlabs/ctxlint 0.18.0 → 0.18.1

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.
@@ -4,7 +4,7 @@
4
4
  # Version-pinned so a checkout at `rev: vX.Y.Z` runs exactly that release
5
5
  # of ctxlint — matches the pinning done by `ctxlint init`. release.sh keeps
6
6
  # this in sync with package.json on each bump.
7
- entry: npx @yawlabs/ctxlint@0.18.0 --strict
7
+ entry: npx @yawlabs/ctxlint@0.18.1 --strict
8
8
  language: node
9
9
  always_run: true
10
10
  pass_filenames: false
package/dist/index.js CHANGED
@@ -13769,6 +13769,7 @@ function extractPathReferences(lines, sections) {
13769
13769
  cleanValue = cleanValue.slice(0, -1);
13770
13770
  }
13771
13771
  if (!cleanValue.includes("/")) continue;
13772
+ if (/(^|\/)\.git\//.test(cleanValue) || /\.app\//.test(cleanValue)) continue;
13772
13773
  const column = match.index + match[0].length - match[1].length + 1;
13773
13774
  paths.push({
13774
13775
  value: cleanValue,
@@ -20432,12 +20433,34 @@ async function checkPaths(file2, projectRoot) {
20432
20433
  const contextDir = path4.dirname(file2.filePath);
20433
20434
  const pending = [];
20434
20435
  for (const ref of file2.references.paths) {
20435
- const normalizedRef = ref.value.replace(/\\/g, "/");
20436
- const baseDir = /^\.\.?\//.test(normalizedRef) ? contextDir : projectRoot;
20437
- const resolvedPath = path4.resolve(baseDir, normalizedRef);
20436
+ const rawNormalized = ref.value.replace(/\\/g, "/");
20437
+ const isImport = rawNormalized.startsWith("@");
20438
+ const normalizedRef = isImport ? rawNormalized.slice(1) : rawNormalized;
20439
+ if (isImport && normalizedRef.startsWith("~/")) continue;
20440
+ if (isImport && /^[\w.-]+\/[\w.-]+$/.test(normalizedRef) && !/\.\w+$/.test(normalizedRef)) {
20441
+ continue;
20442
+ }
20443
+ const explicitRel = /^\.\.?\//.test(normalizedRef);
20444
+ const baseDirs = explicitRel || isImport ? [contextDir] : [projectRoot, contextDir];
20445
+ const primaryBase = baseDirs[0];
20438
20446
  if (normalizedRef.includes("*")) {
20439
- const iter = path4.isAbsolute(normalizedRef) ? es(normalizedRef, { absolute: true, nodir: false, ignore: GLOB_IGNORE }) : es(normalizedRef, { cwd: baseDir, nodir: false, ignore: GLOB_IGNORE });
20440
- const hasMatch = !(await iter.next()).done;
20447
+ let hasMatch = false;
20448
+ if (path4.isAbsolute(normalizedRef)) {
20449
+ const iter = es(normalizedRef, {
20450
+ absolute: true,
20451
+ nodir: false,
20452
+ ignore: GLOB_IGNORE
20453
+ });
20454
+ hasMatch = !(await iter.next()).done;
20455
+ } else {
20456
+ for (const b2 of baseDirs) {
20457
+ const iter = es(normalizedRef, { cwd: b2, nodir: false, ignore: GLOB_IGNORE });
20458
+ if (!(await iter.next()).done) {
20459
+ hasMatch = true;
20460
+ break;
20461
+ }
20462
+ }
20463
+ }
20441
20464
  if (!hasMatch) {
20442
20465
  issues.push({
20443
20466
  severity: "error",
@@ -20452,8 +20475,7 @@ async function checkPaths(file2, projectRoot) {
20452
20475
  }
20453
20476
  const isDir = normalizedRef.endsWith("/");
20454
20477
  if (isDir) {
20455
- const dirPath = path4.resolve(baseDir, normalizedRef);
20456
- if (!isDirectory(dirPath)) {
20478
+ if (!baseDirs.some((b2) => isDirectory(path4.resolve(b2, normalizedRef)))) {
20457
20479
  issues.push({
20458
20480
  severity: "error",
20459
20481
  check: "paths",
@@ -20464,18 +20486,25 @@ async function checkPaths(file2, projectRoot) {
20464
20486
  }
20465
20487
  continue;
20466
20488
  }
20467
- if (fileExists(resolvedPath) || isDirectory(resolvedPath)) {
20489
+ const resolvedCandidates = baseDirs.map((b2) => path4.resolve(b2, normalizedRef));
20490
+ if (resolvedCandidates.some((p2) => fileExists(p2) || isDirectory(p2))) {
20468
20491
  continue;
20469
20492
  }
20493
+ const insideRoot = resolvedCandidates.some((p2) => {
20494
+ const rel = path4.relative(projectRoot, p2);
20495
+ return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
20496
+ });
20497
+ if (!insideRoot) continue;
20498
+ const resolvedPath = path4.resolve(primaryBase, normalizedRef);
20470
20499
  const relTarget = path4.relative(projectRoot, resolvedPath).replace(/\\/g, "/");
20471
- pending.push({ ref, normalizedRef, baseDir, relTarget });
20500
+ pending.push({ ref, normalizedRef, baseDir: primaryBase, relTarget, isImport });
20472
20501
  }
20473
20502
  if (pending.length > 0) {
20474
20503
  const batchResult = await findRenamesBatch(
20475
20504
  projectRoot,
20476
20505
  pending.map((p2) => p2.relTarget)
20477
20506
  );
20478
- for (const { ref, normalizedRef, baseDir, relTarget } of pending) {
20507
+ for (const { ref, normalizedRef, baseDir, relTarget, isImport } of pending) {
20479
20508
  const rename = batchResult.get(relTarget) ?? null;
20480
20509
  let suggestion;
20481
20510
  let detail;
@@ -20498,6 +20527,9 @@ async function checkPaths(file2, projectRoot) {
20498
20527
  fixText = `./${fixText}`;
20499
20528
  }
20500
20529
  }
20530
+ if (fixText && isImport) {
20531
+ fixText = `@${fixText}`;
20532
+ }
20501
20533
  issues.push({
20502
20534
  severity: "error",
20503
20535
  check: "paths",
@@ -27683,7 +27715,7 @@ import { readFileSync as readFileSync7 } from "node:fs";
27683
27715
  import { resolve as resolve14, dirname as dirname6 } from "node:path";
27684
27716
  import { fileURLToPath as fileURLToPath2 } from "node:url";
27685
27717
  function loadVersion() {
27686
- if (true) return "0.18.0";
27718
+ if (true) return "0.18.1";
27687
27719
  try {
27688
27720
  const __dir = dirname6(fileURLToPath2(import.meta.url));
27689
27721
  const pkgPath = resolve14(__dir, "../package.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/ctxlint",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "mcpName": "io.github.YawLabs/ctxlint",
5
5
  "description": "Lint your AI agent context files, MCP server configs, and session data against your actual codebase",
6
6
  "bin": {