mason-context 0.3.3 → 0.3.5
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/README.md +8 -0
- package/dist/bin/mason-mcp.js +27 -1
- package/dist/bin/mason-mcp.js.map +1 -1
- package/dist/bin/mason.js +28 -2
- package/dist/bin/mason.js.map +1 -1
- package/dist/src/cli.js +28 -2
- package/dist/src/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,14 @@ mason snapshot # create/update concept map
|
|
|
114
114
|
|
|
115
115
|
Most providers work without an API key — `claude`, `gemini`, and `ollama` all use their respective CLIs directly.
|
|
116
116
|
|
|
117
|
+
## Security
|
|
118
|
+
|
|
119
|
+
**What the snapshot contains:** Feature names, relative file paths, and flow descriptions. No source code, secrets, or business logic.
|
|
120
|
+
|
|
121
|
+
**What it doesn't touch:** Mason respects `.gitignore` (via `git ls-files`) and has a deny-list that blocks `.env`, `.pem`, `.key`, credentials, and other sensitive files from being sampled. Path traversal protection ensures all file access stays within the project root.
|
|
122
|
+
|
|
123
|
+
**LLM data flow:** When generating a snapshot via CLI (`mason generate`, `mason snapshot`), Mason sends sampled file contents to your configured LLM provider. If you're using `claude`, `openai`, or `gemini`, this means source code is sent to an external API. Use `ollama` for fully local generation. The MCP server tools (`get_snapshot`, `get_impact`, etc.) do not send data to any LLM — they only read local files.
|
|
124
|
+
|
|
117
125
|
## Language support
|
|
118
126
|
|
|
119
127
|
Mason is completely language-agnostic. It uses file naming patterns and git history rather than language-specific parsing, so it works with any project that has source files and a git repository — TypeScript, Kotlin, Python, Go, Rust, Swift, Java, C#, Dart, and more.
|
package/dist/bin/mason-mcp.js
CHANGED
|
@@ -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");
|
|
@@ -1226,10 +1239,23 @@ async function fullAnalysis(dir) {
|
|
|
1226
1239
|
}
|
|
1227
1240
|
return JSON.stringify(output, null, 2);
|
|
1228
1241
|
}
|
|
1242
|
+
function sanitizePaths(rootDir, files) {
|
|
1243
|
+
return files.filter((f) => {
|
|
1244
|
+
const resolved = path6.resolve(rootDir, f);
|
|
1245
|
+
return resolved.startsWith(rootDir) && !f.startsWith("/") && !f.includes("..");
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1229
1248
|
async function saveSnapshotData(dir, features, flows) {
|
|
1230
1249
|
const rootDir = path6.resolve(dir);
|
|
1231
1250
|
const gitHash = await getCurrentGitHash(rootDir);
|
|
1232
1251
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1252
|
+
for (const feat of Object.values(features)) {
|
|
1253
|
+
feat.files = sanitizePaths(rootDir, feat.files);
|
|
1254
|
+
if (feat.tests) feat.tests = sanitizePaths(rootDir, feat.tests);
|
|
1255
|
+
}
|
|
1256
|
+
for (const flow of Object.values(flows)) {
|
|
1257
|
+
flow.chain = sanitizePaths(rootDir, flow.chain);
|
|
1258
|
+
}
|
|
1233
1259
|
const existing = await loadSnapshot(rootDir);
|
|
1234
1260
|
if (existing) {
|
|
1235
1261
|
existing.features = { ...existing.features, ...features };
|
|
@@ -1270,7 +1296,7 @@ function createMcpServer() {
|
|
|
1270
1296
|
const server = new McpServer(
|
|
1271
1297
|
{
|
|
1272
1298
|
name: "mason",
|
|
1273
|
-
version: "0.3.
|
|
1299
|
+
version: "0.3.5"
|
|
1274
1300
|
},
|
|
1275
1301
|
{
|
|
1276
1302
|
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."
|