mason-context 0.3.2 → 0.3.4

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.
@@ -115,7 +115,7 @@ import fs5 from "fs/promises";
115
115
  import path5 from "path";
116
116
  import { execFile as execFile7 } from "child_process";
117
117
  import { promisify as promisify7 } from "util";
118
- import fg4 from "fast-glob";
118
+ import fg5 from "fast-glob";
119
119
  async function analyzeImpact(rootDir, targetFiles) {
120
120
  const resolvedRoot = path5.resolve(rootDir);
121
121
  const resolvedTargets = await resolveTargetFiles(resolvedRoot, targetFiles);
@@ -138,7 +138,7 @@ async function resolveTargetFiles(rootDir, targets) {
138
138
  resolved.push(target);
139
139
  continue;
140
140
  }
141
- const matches = await fg4(`**/${target}`, {
141
+ const matches = await fg5(`**/${target}`, {
142
142
  cwd: rootDir,
143
143
  ignore: IGNORE2
144
144
  });
@@ -146,7 +146,7 @@ async function resolveTargetFiles(rootDir, targets) {
146
146
  resolved.push(matches[0]);
147
147
  } else {
148
148
  const noExt = target.replace(/\.[^.]+$/, "");
149
- const extMatches = await fg4(`**/${noExt}.*`, {
149
+ const extMatches = await fg5(`**/${noExt}.*`, {
150
150
  cwd: rootDir,
151
151
  ignore: IGNORE2
152
152
  });
@@ -203,7 +203,7 @@ async function getReferences(rootDir, targetFiles) {
203
203
  const basename = path5.basename(target).replace(/\.[^.]+$/, "");
204
204
  searchNames.add(basename);
205
205
  }
206
- const allSourceFiles = await fg4(`**/${SOURCE_EXTENSIONS2}`, {
206
+ const allSourceFiles = await fg5(`**/${SOURCE_EXTENSIONS2}`, {
207
207
  cwd: rootDir,
208
208
  ignore: IGNORE2
209
209
  });
@@ -252,7 +252,7 @@ async function getRelatedTests(rootDir, targetFiles) {
252
252
  "**/*Test.swift",
253
253
  "**/*_test.rs"
254
254
  ];
255
- const testFiles = await fg4(testPatterns, { cwd: rootDir, ignore: IGNORE2 });
255
+ const testFiles = await fg5(testPatterns, { cwd: rootDir, ignore: IGNORE2 });
256
256
  const results = [];
257
257
  for (const target of targetFiles) {
258
258
  const targetBaseName = path5.basename(target).replace(/\.[^.]+$/, "");
@@ -304,7 +304,7 @@ import fs6 from "fs/promises";
304
304
  import path6 from "path";
305
305
  import { execFile as execFile8 } from "child_process";
306
306
  import { promisify as promisify8 } from "util";
307
- import fg5 from "fast-glob";
307
+ import fg6 from "fast-glob";
308
308
 
309
309
  // src/analyzers/git-history.ts
310
310
  import { execFile } from "child_process";
@@ -686,10 +686,22 @@ async function loadProjectConfig(rootDir) {
686
686
  return {};
687
687
  }
688
688
  }
689
+ async function getTrackedFiles(rootDir) {
690
+ try {
691
+ const { stdout } = await exec3("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
692
+ cwd: rootDir,
693
+ maxBuffer: 1e7
694
+ });
695
+ return new Set(stdout.trim().split("\n").filter(Boolean));
696
+ } catch {
697
+ return null;
698
+ }
699
+ }
689
700
  async function sampleFiles(rootDir, maxFiles = 25) {
690
701
  const selected = /* @__PURE__ */ new Map();
691
702
  const projectConfig = await loadProjectConfig(rootDir);
692
703
  const ignorePatterns = [...IGNORE_PATTERNS, ...projectConfig.ignore ?? []];
704
+ const trackedFiles = await getTrackedFiles(rootDir);
693
705
  for (const filePath of projectConfig.alwaysInclude ?? []) {
694
706
  if (selected.size >= maxFiles) break;
695
707
  const resolvedPath = path.resolve(rootDir, filePath);
@@ -868,6 +880,7 @@ async function sampleFiles(rootDir, maxFiles = 25) {
868
880
  const fullPath = path.resolve(rootDir, filePath);
869
881
  if (!fullPath.startsWith(path.resolve(rootDir))) continue;
870
882
  if (isSensitiveFile(filePath)) continue;
883
+ if (trackedFiles && !trackedFiles.has(filePath)) continue;
871
884
  const stat = await fs2.stat(fullPath);
872
885
  if (stat.size > 1e5) continue;
873
886
  const content = await fs2.readFile(fullPath, "utf-8");
@@ -910,6 +923,7 @@ import fs4 from "fs/promises";
910
923
  import path4 from "path";
911
924
  import { execFile as execFile6 } from "child_process";
912
925
  import { promisify as promisify6 } from "util";
926
+ import fg4 from "fast-glob";
913
927
  init_test_map();
914
928
 
915
929
  // src/llm/providers.ts
@@ -1061,7 +1075,7 @@ async function detectProjectSnapshot(rootDir) {
1061
1075
  ];
1062
1076
  const testInfo = {};
1063
1077
  for (const pattern of testDirs) {
1064
- const files = await fg5(`${pattern}/**/*`, {
1078
+ const files = await fg6(`${pattern}/**/*`, {
1065
1079
  cwd: rootDir,
1066
1080
  ignore: IGNORE3,
1067
1081
  onlyFiles: true
@@ -1081,12 +1095,12 @@ async function detectProjectSnapshot(rootDir) {
1081
1095
  { pattern: "**/*_test.rs", label: "*_test.rs" }
1082
1096
  ];
1083
1097
  for (const { pattern, label } of testFilePatterns) {
1084
- const files = await fg5(pattern, { cwd: rootDir, ignore: IGNORE3 });
1098
+ const files = await fg6(pattern, { cwd: rootDir, ignore: IGNORE3 });
1085
1099
  if (files.length > 0) {
1086
1100
  testInfo[label] = files.length;
1087
1101
  }
1088
1102
  }
1089
- const sourceFiles = await fg5("**/*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,c,dart}", {
1103
+ const sourceFiles = await fg6("**/*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,c,dart}", {
1090
1104
  cwd: rootDir,
1091
1105
  ignore: IGNORE3
1092
1106
  });
@@ -1119,7 +1133,7 @@ async function getCodeSamples(dir, count = 15) {
1119
1133
  }
1120
1134
  async function getProjectStructure(dir) {
1121
1135
  const rootDir = path6.resolve(dir);
1122
- const allFiles = await fg5("**/*", {
1136
+ const allFiles = await fg6("**/*", {
1123
1137
  cwd: rootDir,
1124
1138
  ignore: IGNORE3,
1125
1139
  onlyFiles: true
@@ -1269,7 +1283,7 @@ function createMcpServer() {
1269
1283
  const server = new McpServer(
1270
1284
  {
1271
1285
  name: "mason",
1272
- version: "0.3.2"
1286
+ version: "0.3.4"
1273
1287
  },
1274
1288
  {
1275
1289
  instructions: "Mason is a context engineering tool. Always call get_snapshot before using Explore agents, Glob, or Grep to understand the codebase. The snapshot is a concept map that maps features and flows to their implementing files \u2014 it eliminates the need to search. This applies to ANY question about architecture, features, flows, how things work, cross-feature interactions, or bug investigation. Workflow: 1) Call get_snapshot first. 2) If no snapshot, call full_analysis and then save_snapshot to create one. 3) If the snapshot is stale, tell the user and offer to update it. 4) Use your native file reading tool to read files the snapshot points to. 5) Before modifying a file, call get_impact to check what else might be affected. 6) After making significant changes (new features, refactors, architecture changes), call save_snapshot to update the concept map."