mason-context 0.3.7 → 0.7.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/sampler.ts","../src/test-map.ts","../src/snapshot/snapshot.ts","../src/drift/drift.ts","../src/context/lexical.ts","../src/decisions/decisions.ts","../src/impact/impact.ts","../src/decisions/drift.ts","../src/context/assemble.ts","../src/confluence/client.ts","../src/llm/config.ts","../src/confluence/url.ts","../src/confluence/renderer.ts","../src/confluence/diff.ts","../src/llm/providers.ts","../src/confluence/rewrite.ts","../src/confluence/sync.ts","../src/mcp/server.ts","../src/mcp/tools.ts","../src/analyzers/git-history.ts","../src/analyzers/base.ts","../src/analyzers/index.ts","../src/utils/git.ts","../src/snapshot/prompt.ts","../src/snapshot/partials.ts","../src/mcp/init.ts","../bin/mason-mcp.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fg from \"fast-glob\";\n\nconst exec = promisify(execFile);\n\nconst SOURCE_EXTENSIONS = [\n \"ts\", \"tsx\", \"js\", \"jsx\", \"mts\", \"mjs\",\n \"kt\", \"kts\", \"java\",\n \"py\",\n \"go\",\n \"rs\",\n \"swift\",\n \"rb\",\n \"cs\", \"cpp\", \"c\", \"h\",\n \"dart\",\n];\n\nconst CONFIG_FILES = [\n // Build & project config\n \"package.json\",\n \"tsconfig.json\",\n \"build.gradle.kts\",\n \"build.gradle\",\n \"settings.gradle.kts\",\n \"settings.gradle\",\n \"Cargo.toml\",\n \"go.mod\",\n \"pyproject.toml\",\n \"Gemfile\",\n \"*.csproj\",\n // Version catalogs & dependency locks\n \"gradle/libs.versions.toml\",\n // Code quality & formatting\n \".editorconfig\",\n \".eslintrc.*\",\n \"eslint.config.*\",\n \".prettierrc\",\n \"rustfmt.toml\",\n \".swiftlint.yml\",\n // CI/CD\n \".github/workflows/*.yml\",\n \".gitlab-ci.yml\",\n \"Jenkinsfile\",\n // Containerization\n \"Dockerfile\",\n \"docker-compose.yml\",\n \"docker-compose.yaml\",\n];\n\nconst ENTRY_POINT_PATTERNS = [\n \"src/main.*\",\n \"src/index.*\",\n \"src/app.*\",\n \"main.*\",\n \"index.*\",\n \"app.*\",\n \"App.*\",\n \"**/Main.kt\",\n \"**/Application.kt\",\n \"**/main.py\",\n \"**/main.go\",\n \"**/main.rs\",\n \"**/lib.rs\",\n \"**/Program.cs\",\n];\n\n// Filename patterns that reveal architectural patterns and conventions.\n// These are language-agnostic — the suffixes appear across ecosystems.\n// Ordered by architectural importance — most distinctive patterns first.\nconst ARCHITECTURAL_PATTERNS = [\n // State/data flow\n { glob: \"**/*ViewModel.*\", category: \"state\", reason: \"viewmodel (state management)\" },\n { glob: \"**/*Store.*\", category: \"state\", reason: \"store (state management)\" },\n { glob: \"**/*Reducer.*\", category: \"state\", reason: \"reducer (state management)\" },\n // Data layer — interface\n { glob: \"**/*Repository.*\", category: \"data-interface\", reason: \"repository interface (data layer contract)\" },\n { glob: \"**/*Dao.*\", category: \"data-interface\", reason: \"DAO (data access)\" },\n { glob: \"**/*DataSource.*\", category: \"data-interface\", reason: \"data source\" },\n // Data layer — implementation (where actual patterns live: mappers, retry, IO dispatchers)\n { glob: \"**/*RepositoryImpl.*\", category: \"data-impl\", reason: \"repository implementation (data layer patterns)\" },\n { glob: \"**/*ServiceImpl.*\", category: \"data-impl\", reason: \"service implementation\" },\n { glob: \"**/*Impl.*\", category: \"data-impl\", reason: \"implementation (concrete patterns)\" },\n // Data transformation\n { glob: \"**/*Mapper.*\", category: \"transform\", reason: \"mapper (data transformation)\" },\n { glob: \"**/*Converter.*\", category: \"transform\", reason: \"converter (data transformation)\" },\n { glob: \"**/*Adapter.*\", category: \"transform\", reason: \"adapter (interface adaptation)\" },\n // Dependency injection / wiring\n { glob: \"**/*Module.*\", category: \"di\", reason: \"module (DI/wiring)\" },\n { glob: \"**/*Provider.*\", category: \"di\", reason: \"provider (DI/wiring)\" },\n { glob: \"**/*Container.*\", category: \"di\", reason: \"container (DI/wiring)\" },\n { glob: \"**/*Factory.*\", category: \"di\", reason: \"factory (object creation)\" },\n // API / network\n { glob: \"**/*Service.*\", category: \"api\", reason: \"service (business/API layer)\" },\n { glob: \"**/*Client.*\", category: \"api\", reason: \"client (API/network layer)\" },\n { glob: \"**/*Api.*\", category: \"api\", reason: \"API interface definition\" },\n // Interface contracts / protocols\n { glob: \"**/*Interface.*\", category: \"contract\", reason: \"interface definition\" },\n { glob: \"**/*Protocol.*\", category: \"contract\", reason: \"protocol definition\" },\n { glob: \"**/*Trait.*\", category: \"contract\", reason: \"trait definition\" },\n // Routing / navigation\n { glob: \"**/*Router.*\", category: \"routing\", reason: \"router (navigation/routing)\" },\n { glob: \"**/*Route.*\", category: \"routing\", reason: \"route definition\" },\n { glob: \"**/*NavHost.*\", category: \"routing\", reason: \"navigation host\" },\n { glob: \"**/*Controller.*\", category: \"routing\", reason: \"controller (request handling)\" },\n { glob: \"**/*Handler.*\", category: \"routing\", reason: \"handler (request handling)\" },\n // Middleware / interceptors\n { glob: \"**/*Middleware.*\", category: \"middleware\", reason: \"middleware (request pipeline)\" },\n { glob: \"**/*Interceptor.*\", category: \"middleware\", reason: \"interceptor (cross-cutting)\" },\n { glob: \"**/*Plugin.*\", category: \"middleware\", reason: \"plugin (extensibility)\" },\n // Models / types\n { glob: \"**/*Model.*\", category: \"model\", reason: \"model (domain types)\" },\n { glob: \"**/*Entity.*\", category: \"model\", reason: \"entity (persistence types)\" },\n { glob: \"**/*Dto.*\", category: \"model\", reason: \"DTO (data transfer types)\" },\n { glob: \"**/*Schema.*\", category: \"model\", reason: \"schema (data validation)\" },\n // Use cases / commands\n { glob: \"**/*UseCase.*\", category: \"usecase\", reason: \"use case (business logic)\" },\n { glob: \"**/*Interactor.*\", category: \"usecase\", reason: \"interactor (business logic)\" },\n { glob: \"**/*Command.*\", category: \"usecase\", reason: \"command (CQRS pattern)\" },\n];\n\nconst IGNORE_PATTERNS = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.gradle/**\",\n \"**/target/**\",\n \"**/.git/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/*.min.*\",\n \"**/*.map\",\n \"**/package-lock.json\",\n \"**/yarn.lock\",\n \"**/pnpm-lock.yaml\",\n \"**/*.lock\",\n \"**/*.generated.*\",\n \"**/generated/**\",\n \"**/R.java\",\n \"**/BuildConfig.java\",\n];\n\nconst PREVIEW_LINES = 60;\n\nexport interface ProjectConfig {\n patterns?: string[];\n alwaysInclude?: string[];\n ignore?: string[];\n}\n\nexport interface SampledFile {\n path: string;\n preview: string;\n totalLines: number;\n sizeBytes: number;\n reason: string;\n}\n\nasync function loadProjectConfig(\n rootDir: string\n): Promise<ProjectConfig> {\n try {\n const raw = await fs.readFile(\n path.join(rootDir, \".mason\", \"config.json\"),\n \"utf-8\"\n );\n return JSON.parse(raw);\n } catch {\n return {};\n }\n}\n\nasync function getTrackedFiles(rootDir: string): Promise<Set<string> | null> {\n try {\n const { stdout } = await exec(\"git\", [\"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\"], {\n cwd: rootDir,\n maxBuffer: 10_000_000,\n });\n return new Set(stdout.trim().split(\"\\n\").filter(Boolean));\n } catch {\n return null; // Not a git repo — skip filtering\n }\n}\n\nexport async function sampleFiles(\n rootDir: string,\n maxFiles: number = 25\n): Promise<SampledFile[]> {\n const selected = new Map<string, string>(); // path -> reason\n const projectConfig = await loadProjectConfig(rootDir);\n const ignorePatterns = [...IGNORE_PATTERNS, ...(projectConfig.ignore ?? [])];\n const trackedFiles = await getTrackedFiles(rootDir);\n\n // 0. Always-include files from project config (highest priority)\n for (const filePath of projectConfig.alwaysInclude ?? []) {\n if (selected.size >= maxFiles) break;\n // Validate path stays within project root\n const resolvedPath = path.resolve(rootDir, filePath);\n if (!resolvedPath.startsWith(path.resolve(rootDir))) continue;\n selected.set(filePath, \"always-include (project config)\");\n }\n\n // 1. Config files (cap at 5)\n let configCount = 0;\n for (const pattern of CONFIG_FILES) {\n if (configCount >= 5) break;\n const matches = await fg(pattern, {\n cwd: rootDir,\n ignore: ignorePatterns,\n deep: 3,\n });\n for (const match of matches) {\n if (configCount >= 5 || selected.size >= maxFiles) break;\n selected.set(match, \"config file\");\n configCount++;\n }\n }\n\n // 2. Module build/config files — build files from subdirectories reveal dependency graph\n const moduleBuildPatterns = [\n // Gradle\n \"**/build.gradle.kts\",\n \"**/build.gradle\",\n // Cargo workspace members\n \"**/Cargo.toml\",\n // Node workspaces\n \"**/package.json\",\n // Go sub-modules\n \"**/go.mod\",\n ];\n let moduleBuildCount = 0;\n for (const pattern of moduleBuildPatterns) {\n const matches = await fg(pattern, {\n cwd: rootDir,\n ignore: ignorePatterns,\n deep: 4,\n });\n // Skip root-level files (already captured as config)\n const subMatches = matches.filter((m) => m.includes(\"/\"));\n for (const match of subMatches) {\n if (moduleBuildCount >= 4 || selected.size >= maxFiles) break;\n if (!selected.has(match)) {\n selected.set(match, \"module build file (reveals dependency graph)\");\n moduleBuildCount++;\n }\n }\n if (moduleBuildCount >= 4) break;\n }\n\n // 3. Entry points (cap at 2)\n let entryCount = 0;\n for (const pattern of ENTRY_POINT_PATTERNS) {\n if (entryCount >= 2) break;\n const matches = await fg(pattern, {\n cwd: rootDir,\n ignore: ignorePatterns,\n deep: 5,\n });\n for (const match of matches) {\n if (entryCount >= 2 || selected.size >= maxFiles) break;\n if (!selected.has(match)) {\n selected.set(match, \"entry point\");\n entryCount++;\n }\n }\n }\n\n // 4. Hot files from git (up to 5)\n try {\n const { stdout } = await exec(\n \"git\",\n [\"log\", \"--since=3 months ago\", \"--format=\", \"--name-only\"],\n { cwd: rootDir, maxBuffer: 5_000_000 }\n );\n\n const fileCounts = new Map<string, number>();\n for (const line of stdout.split(\"\\n\")) {\n if (!line) continue;\n if (\n line.includes(\"node_modules\") ||\n line.includes(\"/build/\") ||\n line.includes(\".gradle\") ||\n line.includes(\"/generated/\")\n )\n continue;\n const ext = path.extname(line).slice(1);\n if (!SOURCE_EXTENSIONS.includes(ext)) continue;\n fileCounts.set(line, (fileCounts.get(line) ?? 0) + 1);\n }\n\n const hotFiles = [...fileCounts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n for (const [file, count] of hotFiles) {\n if (selected.size >= maxFiles) break;\n if (!selected.has(file)) {\n selected.set(file, `frequently changed (${count} commits in 3 months)`);\n }\n }\n } catch {\n // No git\n }\n\n // 5. Architectural pattern files — one per category (cap at 8)\n const seenCategories = new Set<string>();\n let patternCount = 0;\n for (const pattern of ARCHITECTURAL_PATTERNS) {\n if (patternCount >= 8 || selected.size >= maxFiles) break;\n if (seenCategories.has(pattern.category)) continue;\n\n const matches = await fg(pattern.glob, {\n cwd: rootDir,\n ignore: ignorePatterns,\n });\n\n if (matches.length > 0) {\n for (const match of matches) {\n if (!selected.has(match)) {\n selected.set(match, pattern.reason);\n seenCategories.add(pattern.category);\n patternCount++;\n break;\n }\n }\n }\n }\n\n // 5b. Custom patterns from project config\n for (const customGlob of projectConfig.patterns ?? []) {\n if (selected.size >= maxFiles) break;\n const matches = await fg(customGlob, {\n cwd: rootDir,\n ignore: ignorePatterns,\n });\n for (const match of matches) {\n if (selected.size >= maxFiles) break;\n if (!selected.has(match)) {\n selected.set(match, \"custom pattern (project config)\");\n break; // one per pattern\n }\n }\n }\n\n // 6. Test examples — diverse across file types (cap at 3)\n const testPatternGroups = [\n // JS/TS tests\n { patterns: [\"**/*.test.*\", \"**/*.spec.*\"], label: \"JS/TS test\" },\n // JVM tests\n { patterns: [\"**/*Test.kt\", \"**/*Test.java\"], label: \"JVM test\" },\n // Python tests\n { patterns: [\"**/test_*.py\", \"**/*_test.py\"], label: \"Python test\" },\n // Go tests\n { patterns: [\"**/*_test.go\"], label: \"Go test\" },\n // Swift tests\n { patterns: [\"**/*Tests.swift\", \"**/*Test.swift\"], label: \"Swift test\" },\n // Rust tests\n { patterns: [\"**/*_test.rs\"], label: \"Rust test\" },\n ];\n let testCount = 0;\n for (const group of testPatternGroups) {\n if (testCount >= 3 || selected.size >= maxFiles) break;\n const testFiles = await fg(group.patterns, {\n cwd: rootDir,\n ignore: ignorePatterns,\n });\n if (testFiles.length > 0) {\n for (const file of testFiles) {\n if (!selected.has(file)) {\n selected.set(file, `test example (${group.label})`);\n testCount++;\n break;\n }\n }\n }\n }\n\n // 7. Directory breadth — fill remaining slots with one file per top-level dir\n const sourceGlobs = SOURCE_EXTENSIONS.map((ext) => `**/*.${ext}`);\n const allSourceFiles = await fg(sourceGlobs, {\n cwd: rootDir,\n ignore: ignorePatterns,\n });\n\n const dirRepresentatives = new Map<string, string>();\n const boringFiles = /\\.(gradle|gradle\\.kts|json|toml|yaml|yml|xml|properties)$/;\n for (const file of allSourceFiles) {\n const topDir = file.split(\"/\")[0];\n if (!dirRepresentatives.has(topDir) && !boringFiles.test(file)) {\n dirRepresentatives.set(topDir, file);\n }\n }\n\n for (const [, file] of dirRepresentatives) {\n if (selected.size >= maxFiles) break;\n if (!selected.has(file)) {\n selected.set(file, \"directory representative\");\n }\n }\n\n // Read file previews\n const results: SampledFile[] = [];\n for (const [filePath, reason] of selected) {\n try {\n const fullPath = path.resolve(rootDir, filePath);\n if (!fullPath.startsWith(path.resolve(rootDir))) continue;\n if (isSensitiveFile(filePath)) continue;\n if (trackedFiles && !trackedFiles.has(filePath)) continue; // respect .gitignore\n const stat = await fs.stat(fullPath);\n if (stat.size > 100_000) continue;\n\n const content = await fs.readFile(fullPath, \"utf-8\");\n const lines = content.split(\"\\n\");\n const preview = lines.slice(0, PREVIEW_LINES).join(\"\\n\");\n\n results.push({\n path: filePath,\n preview,\n totalLines: lines.length,\n sizeBytes: stat.size,\n reason,\n });\n } catch {\n // Skip\n }\n }\n\n return results;\n}\n\nconst SENSITIVE_PATTERNS = [\n /^\\.env$/,\n /^\\.env\\./,\n /\\.pem$/,\n /\\.key$/,\n /\\.p12$/,\n /\\.pfx$/,\n /\\.jks$/,\n /id_rsa/,\n /id_ed25519/,\n /credentials\\./,\n /secret/i,\n /\\.keystore$/,\n /local\\.properties$/,\n];\n\nfunction isSensitiveFile(filePath: string): boolean {\n const basename = path.basename(filePath);\n return SENSITIVE_PATTERNS.some((p) => p.test(basename));\n}\n\nexport async function readFullFile(\n rootDir: string,\n filePath: string\n): Promise<{ path: string; content: string; totalLines: number } | null> {\n try {\n const fullPath = path.join(path.resolve(rootDir), filePath);\n if (!fullPath.startsWith(path.resolve(rootDir))) return null;\n if (isSensitiveFile(filePath)) return null;\n\n const content = await fs.readFile(fullPath, \"utf-8\");\n return {\n path: filePath,\n content,\n totalLines: content.split(\"\\n\").length,\n };\n } catch {\n return null;\n }\n}\n","import path from \"node:path\";\nimport fg from \"fast-glob\";\n\nconst IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.gradle/**\",\n \"**/target/**\",\n \"**/.git/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/*.min.*\",\n \"**/*.map\",\n];\n\nexport interface TestPair {\n test: string;\n source: string;\n confidence: string;\n}\n\nexport interface TestMapResult {\n totalTestFiles: number;\n paired: TestPair[];\n unmatched: string[];\n}\n\nexport async function buildTestMap(dir: string): Promise<TestMapResult> {\n const rootDir = path.resolve(dir);\n\n // Find all test files\n const testPatterns = [\n \"**/*.test.*\", \"**/*.spec.*\",\n \"**/*Test.kt\", \"**/*Test.java\", \"**/*Tests.kt\", \"**/*Tests.java\",\n \"**/test_*.py\", \"**/*_test.py\",\n \"**/*_test.go\",\n \"**/*Tests.swift\", \"**/*Test.swift\",\n \"**/*_test.rs\",\n ];\n const testFiles = await fg(testPatterns, { cwd: rootDir, ignore: IGNORE });\n\n // Find all source files\n const sourceFiles = await fg(\n \"**/*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,dart}\",\n { cwd: rootDir, ignore: IGNORE }\n );\n\n // Build source file index by base name (without extension)\n const sourceByBaseName = new Map<string, string[]>();\n for (const file of sourceFiles) {\n if (testFiles.includes(file)) continue; // Skip test files\n const baseName = path.basename(file).replace(/\\.[^.]+$/, \"\");\n const existing = sourceByBaseName.get(baseName) ?? [];\n existing.push(file);\n sourceByBaseName.set(baseName, existing);\n }\n\n // Match test files to source files by name\n const paired: TestPair[] = [];\n const unmatched: string[] = [];\n\n for (const testFile of testFiles) {\n const testBaseName = path.basename(testFile).replace(/\\.[^.]+$/, \"\");\n\n // Strip test suffixes/prefixes to get the source name\n const sourceName = testBaseName\n .replace(/Test$|Tests$|Spec$|\\.test$|\\.spec$/, \"\")\n .replace(/^test_|_test$/, \"\");\n\n if (!sourceName) {\n unmatched.push(testFile);\n continue;\n }\n\n const candidates = sourceByBaseName.get(sourceName);\n if (candidates && candidates.length > 0) {\n // If multiple candidates, prefer one in a similar directory path\n const testDir = path.dirname(testFile);\n const bestMatch = candidates.reduce((best, candidate) => {\n const candidateDir = path.dirname(candidate);\n const bestDir = path.dirname(best);\n const candidateOverlap = commonSegments(testDir, candidateDir);\n const bestOverlap = commonSegments(testDir, bestDir);\n return candidateOverlap > bestOverlap ? candidate : best;\n });\n\n paired.push({\n test: testFile,\n source: bestMatch,\n confidence: candidates.length === 1 ? \"exact\" : \"best-guess\",\n });\n } else {\n unmatched.push(testFile);\n }\n }\n\n return { totalTestFiles: testFiles.length, paired, unmatched };\n}\n\nfunction commonSegments(pathA: string, pathB: string): number {\n const segsA = pathA.split(\"/\");\n const segsB = pathB.split(\"/\");\n let count = 0;\n for (let i = 0; i < Math.min(segsA.length, segsB.length); i++) {\n if (segsA[i] === segsB[i]) count++;\n else break;\n }\n return count;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fg from \"fast-glob\";\nimport { readFullFile } from \"../mcp/sampler.js\";\nimport { buildTestMap } from \"../test-map.js\";\n\nconst exec = promisify(execFile);\n\nexport interface FeatureEntry {\n description: string;\n files: string[];\n tests?: string[];\n /**\n * Commit this entry was last verified against. Entries updated by an\n * incremental save carry HEAD here; untouched entries keep the hash the\n * map had before the save, so drift stays visible per entry. Absent means\n * \"as of the snapshot's top-level gitHash\".\n */\n refreshedHash?: string;\n /**\n * Whether this is a user-facing capability or internal infrastructure\n * (DI wiring, config loading, logging, provider/transport plumbing).\n * Capabilities are published to product-facing docs (Confluence);\n * infrastructure stays in the AI concept map only. Defaults to \"capability\"\n * when absent (older snapshots) or unrecognized — see normalizeFeatureType.\n */\n type?: \"capability\" | \"infrastructure\";\n /**\n * When an assistant last confirmed this entry's files actually implement\n * the claimed feature (verify_snapshot flow). Absent on older snapshots\n * and never-verified entries. Drift checks freshness against git; this\n * checks the map was CORRECT in the first place.\n */\n verifiedAt?: string;\n /** Set when verification judged the entry wrong — re-map it. */\n verificationFailed?: boolean;\n verificationNote?: string;\n}\n\nexport type FeatureType = \"capability\" | \"infrastructure\";\n\n/**\n * Coerce an arbitrary type value to a known classification. Anything that\n * isn't explicitly \"infrastructure\" defaults to \"capability\" — so older\n * snapshots and unclassified entries are treated as user-facing (published),\n * never silently hidden.\n */\nexport function normalizeFeatureType(value: unknown): FeatureType {\n return value === \"infrastructure\" ? \"infrastructure\" : \"capability\";\n}\n\nexport interface FlowEntry {\n description: string;\n chain: string[];\n /** See FeatureEntry.refreshedHash. */\n refreshedHash?: string;\n /** See FeatureEntry.verifiedAt / verificationFailed. */\n verifiedAt?: string;\n verificationFailed?: boolean;\n verificationNote?: string;\n}\n\nexport interface Snapshot {\n version: 2;\n createdAt: string;\n updatedAt: string;\n gitHash: string;\n features: Record<string, FeatureEntry>;\n flows: Record<string, FlowEntry>;\n}\n\nfunction snapshotDir(rootDir: string): string {\n return path.join(rootDir, \".mason\");\n}\n\nfunction snapshotPath(rootDir: string): string {\n return path.join(snapshotDir(rootDir), \"snapshot.json\");\n}\n\nexport async function loadSnapshot(rootDir: string): Promise<Snapshot | null> {\n try {\n const raw = await fs.readFile(snapshotPath(rootDir), \"utf-8\");\n const parsed = JSON.parse(raw);\n // Skip v1 snapshots — they're the old per-file format\n if (parsed.version !== 2) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport async function saveSnapshot(\n rootDir: string,\n snapshot: Snapshot\n): Promise<void> {\n await fs.mkdir(snapshotDir(rootDir), { recursive: true });\n await fs.writeFile(\n snapshotPath(rootDir),\n JSON.stringify(snapshot, null, 2),\n \"utf-8\"\n );\n}\n\nexport async function getCurrentGitHash(rootDir: string): Promise<string> {\n try {\n const { stdout } = await exec(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: rootDir,\n });\n return stdout.trim();\n } catch {\n return \"unknown\";\n }\n}\n\nexport const SOURCE_GLOB =\n \"**/*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,c,dart}\";\nexport const SOURCE_IGNORE = [\n \"**/node_modules/**\", \"**/dist/**\", \"**/build/**\", \"**/.gradle/**\",\n \"**/target/**\", \"**/.git/**\", \"**/vendor/**\", \"**/__pycache__/**\",\n \"**/venv/**\", \"**/.venv/**\", \"**/*.min.*\", \"**/*.map\",\n \"**/generated/**\", \"**/R.java\", \"**/BuildConfig.java\",\n];\n\nexport const DEFAULT_BATCH_SIZE = 50;\nconst SKELETON_CHARS = 500;\nconst DEEP_SAMPLE_CHARS = 1500;\nconst DEEP_SAMPLES_PER_BATCH = 3;\n\nexport interface SnapshotBatch {\n offset: number;\n batchSize: number;\n nextOffset: number | null;\n totalFiles: number;\n skeletons: Array<{ path: string; content: string }>;\n samples: Array<{ path: string; content: string }>;\n testPairs: Array<{ test: string; source: string; confidence: string }>;\n}\n\nexport async function listSourceFiles(resolvedRoot: string): Promise<string[]> {\n const all = await fg(SOURCE_GLOB, {\n cwd: resolvedRoot,\n ignore: SOURCE_IGNORE,\n });\n // Deterministic order so the same offset always returns the same batch.\n return [...all].sort();\n}\n\nexport async function prepareSnapshotBatch(\n rootDir: string,\n offset: number,\n batchSize: number = DEFAULT_BATCH_SIZE,\n scopeFiles?: string[]\n): Promise<SnapshotBatch> {\n const resolvedRoot = path.resolve(rootDir);\n let allFiles = await listSourceFiles(resolvedRoot);\n if (scopeFiles) {\n // Intersect with the real source list: keeps ignore rules and path safety,\n // and silently drops scope entries that no longer exist on disk. An empty\n // scope stays empty — it must not fall back to walking the whole project.\n const scopeSet = new Set(scopeFiles);\n allFiles = allFiles.filter((f) => scopeSet.has(f));\n }\n const totalFiles = allFiles.length;\n const safeOffset = Math.max(0, Math.min(offset, totalFiles));\n const batchPaths = allFiles.slice(safeOffset, safeOffset + batchSize);\n\n const skeletons: Array<{ path: string; content: string }> = [];\n for (const filePath of batchPaths) {\n const full = await readFullFile(resolvedRoot, filePath);\n if (full) {\n skeletons.push({\n path: full.path,\n content: full.content.slice(0, SKELETON_CHARS),\n });\n }\n }\n\n // Pick a few files from this batch to read deeply for grounding. Spread\n // evenly across the batch so the deep samples represent the batch's range.\n const samples: Array<{ path: string; content: string }> = [];\n if (skeletons.length > 0) {\n const step = Math.max(1, Math.floor(skeletons.length / DEEP_SAMPLES_PER_BATCH));\n for (let i = 0; i < skeletons.length && samples.length < DEEP_SAMPLES_PER_BATCH; i += step) {\n const full = await readFullFile(resolvedRoot, skeletons[i].path);\n if (full) {\n samples.push({\n path: full.path,\n content: full.content.slice(0, DEEP_SAMPLE_CHARS),\n });\n }\n }\n }\n\n // Only include test pairs that involve files in this batch — keeps the\n // appendix relevant and small.\n const batchPathSet = new Set(batchPaths);\n const allTestPairs = (await buildTestMap(resolvedRoot)).paired;\n const testPairs = allTestPairs.filter(\n (p) => batchPathSet.has(p.test) || batchPathSet.has(p.source)\n );\n\n const nextOffset =\n safeOffset + batchSize >= totalFiles ? null : safeOffset + batchSize;\n\n return {\n offset: safeOffset,\n batchSize,\n nextOffset,\n totalFiles,\n skeletons,\n samples,\n testPairs,\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport {\n loadSnapshot,\n getCurrentGitHash,\n listSourceFiles,\n} from \"../snapshot/snapshot.js\";\nimport type { Snapshot } from \"../snapshot/snapshot.js\";\n\nconst exec = promisify(execFile);\n\n// Incremental refresh stops paying off once a large share of the map is\n// touched — but small absolute counts are always cheap to refresh in place,\n// so both thresholds must be exceeded before recommending a full rebuild.\nconst FULL_REBUILD_FRACTION = 0.4;\nconst FULL_REBUILD_MIN_CHANGED_MAPPED_FILES = 10;\n\nexport type ChangeStatus = \"added\" | \"modified\" | \"deleted\" | \"renamed\";\n\nexport interface FileChange {\n status: ChangeStatus;\n /** Current path (the new path for renames). */\n path: string;\n /** Pre-rename path, only present for renames. */\n previousPath?: string;\n}\n\nexport type DriftRecommendation = \"up-to-date\" | \"incremental\" | \"full-rebuild\";\n\nexport interface DriftReport {\n stale: boolean;\n snapshotHash: string;\n headHash: string;\n /** Commits between the snapshot and HEAD; null when history is unavailable. */\n commitsBehind: number | null;\n /**\n * False when the snapshot commit is unreachable (shallow clone, rewritten\n * history) — staleFeatures/unmappedFiles/renames cannot be computed then.\n */\n historyAvailable: boolean;\n /** Current paths of every file changed since the snapshot. */\n changedFiles: string[];\n /** Stale feature name → the mapped files that changed under it. */\n staleFeatures: Record<string, string[]>;\n /** Stale flow name → the chain files that changed under it. */\n staleFlows: Record<string, string[]>;\n totalFeatures: number;\n totalFlows: number;\n /** New source files not referenced by any feature or flow. */\n unmappedFiles: string[];\n /** Files referenced by the map that no longer exist on disk. */\n ghostFiles: string[];\n renames: Array<{ from: string; to: string }>;\n recommendation: DriftRecommendation;\n}\n\nexport async function getChangesWithStatus(\n resolvedRoot: string,\n fromHash: string\n): Promise<FileChange[] | null> {\n if (!fromHash || fromHash === \"unknown\") return null;\n try {\n const { stdout } = await exec(\n \"git\",\n [\"diff\", \"--name-status\", \"-M\", fromHash, \"HEAD\"],\n { cwd: resolvedRoot, maxBuffer: 10 * 1024 * 1024 }\n );\n\n const changes: FileChange[] = [];\n for (const line of stdout.split(\"\\n\")) {\n if (!line.trim()) continue;\n const parts = line.split(\"\\t\");\n // Mason's own metadata changes on every save — never count it as drift.\n if (parts.some((p) => p.startsWith(\".mason/\"))) continue;\n const code = parts[0];\n if (code.startsWith(\"R\") && parts.length >= 3) {\n changes.push({\n status: \"renamed\",\n path: parts[2],\n previousPath: parts[1],\n });\n } else if (code.startsWith(\"C\") && parts.length >= 3) {\n // A copy leaves the original in place — only the new path is a change.\n changes.push({ status: \"added\", path: parts[2] });\n } else if (code === \"A\" && parts.length >= 2) {\n changes.push({ status: \"added\", path: parts[1] });\n } else if (code === \"D\" && parts.length >= 2) {\n changes.push({ status: \"deleted\", path: parts[1] });\n } else if (parts.length >= 2) {\n // M, T (typechange), and anything unrecognized count as modified.\n changes.push({ status: \"modified\", path: parts[1] });\n }\n }\n return changes;\n } catch {\n return null;\n }\n}\n\nasync function countCommitsBehind(\n resolvedRoot: string,\n fromHash: string\n): Promise<number | null> {\n try {\n const { stdout } = await exec(\n \"git\",\n [\"rev-list\", \"--count\", `${fromHash}..HEAD`],\n { cwd: resolvedRoot }\n );\n const count = Number.parseInt(stdout.trim(), 10);\n return Number.isNaN(count) ? null : count;\n } catch {\n return null;\n }\n}\n\nfunction collectMappedFiles(snapshot: Snapshot): Set<string> {\n const mappedFiles = new Set<string>();\n for (const feature of Object.values(snapshot.features)) {\n for (const f of feature.files) mappedFiles.add(f);\n for (const t of feature.tests ?? []) mappedFiles.add(t);\n }\n for (const flow of Object.values(snapshot.flows)) {\n for (const f of flow.chain) mappedFiles.add(f);\n }\n return mappedFiles;\n}\n\nasync function findGhostFiles(\n resolvedRoot: string,\n mappedFiles: Set<string>\n): Promise<string[]> {\n const ghosts: string[] = [];\n for (const file of mappedFiles) {\n try {\n await fs.access(path.join(resolvedRoot, file));\n } catch {\n ghosts.push(file);\n }\n }\n return ghosts.sort();\n}\n\n/**\n * Compare the concept map against HEAD and report feature-level drift.\n * Fully deterministic — git + filesystem only, no LLM involved.\n * Returns null when no snapshot exists.\n */\nexport async function computeDrift(\n rootDir: string\n): Promise<DriftReport | null> {\n const resolvedRoot = path.resolve(rootDir);\n const snapshot = await loadSnapshot(resolvedRoot);\n if (!snapshot) return null;\n\n const headHash = await getCurrentGitHash(resolvedRoot);\n const totalFeatures = Object.keys(snapshot.features).length;\n const totalFlows = Object.keys(snapshot.flows).length;\n\n // Each entry is only verified as of its refreshedHash (falling back to the\n // top-level gitHash), so drift is evaluated per distinct hash — a partially\n // refreshed map can be fresh at the top level and still hold stale entries.\n const hashFor = (entry: { refreshedHash?: string }): string =>\n entry.refreshedHash ?? snapshot.gitHash;\n\n const distinctHashes = new Set<string>([snapshot.gitHash]);\n for (const feature of Object.values(snapshot.features)) {\n distinctHashes.add(hashFor(feature));\n }\n for (const flow of Object.values(snapshot.flows)) {\n distinctHashes.add(hashFor(flow));\n }\n distinctHashes.delete(\"unknown\");\n\n const staleHashes =\n headHash === \"unknown\"\n ? []\n : [...distinctHashes].filter((h) => h !== headHash);\n const stale = staleHashes.length > 0;\n\n const report: DriftReport = {\n stale,\n snapshotHash: snapshot.gitHash,\n headHash,\n commitsBehind: stale ? null : 0,\n historyAvailable: true,\n changedFiles: [],\n staleFeatures: {},\n staleFlows: {},\n totalFeatures,\n totalFlows,\n unmappedFiles: [],\n ghostFiles: [],\n renames: [],\n recommendation: \"up-to-date\",\n };\n\n if (!stale) return report;\n\n const mappedFiles = collectMappedFiles(snapshot);\n report.ghostFiles = await findGhostFiles(resolvedRoot, mappedFiles);\n\n const changesByHash = new Map<string, FileChange[]>();\n const touchedByHash = new Map<string, Set<string>>();\n for (const hash of staleHashes) {\n const changes = await getChangesWithStatus(resolvedRoot, hash);\n if (changes === null) {\n // One unreachable base commit is enough to make per-entry drift\n // uncomputable — we know the map is stale but not how.\n report.historyAvailable = false;\n report.recommendation = \"full-rebuild\";\n return report;\n }\n changesByHash.set(hash, changes);\n // Every path a change touches, old and new — an entry referencing either\n // side of a rename is stale.\n const touched = new Set<string>();\n for (const change of changes) {\n touched.add(change.path);\n if (change.previousPath) touched.add(change.previousPath);\n }\n touchedByHash.set(hash, touched);\n }\n\n // The oldest verification state in the map is the honest answer to \"how\n // far behind is this snapshot\".\n const commitCounts = await Promise.all(\n staleHashes.map((hash) => countCommitsBehind(resolvedRoot, hash))\n );\n const validCounts = commitCounts.filter((c): c is number => c !== null);\n report.commitsBehind =\n validCounts.length > 0 ? Math.max(...validCounts) : null;\n\n const emptySet = new Set<string>();\n const touchedFor = (entry: { refreshedHash?: string }): Set<string> =>\n touchedByHash.get(hashFor(entry)) ?? emptySet;\n\n for (const [name, feature] of Object.entries(snapshot.features)) {\n const touched = touchedFor(feature);\n const hits = [...feature.files, ...(feature.tests ?? [])].filter((f) =>\n touched.has(f)\n );\n if (hits.length > 0) report.staleFeatures[name] = [...new Set(hits)];\n }\n for (const [name, flow] of Object.entries(snapshot.flows)) {\n const touched = touchedFor(flow);\n const hits = flow.chain.filter((f) => touched.has(f));\n if (hits.length > 0) report.staleFlows[name] = [...new Set(hits)];\n }\n\n const allChanges = [...changesByHash.values()].flat();\n report.changedFiles = [...new Set(allChanges.map((c) => c.path))].sort();\n\n // New source files (added, or the new side of a rename) missing from the map.\n const sourceFileSet = new Set(await listSourceFiles(resolvedRoot));\n const newPaths = allChanges\n .filter((c) => c.status === \"added\" || c.status === \"renamed\")\n .map((c) => c.path);\n report.unmappedFiles = [...new Set(newPaths)]\n .filter((p) => sourceFileSet.has(p) && !mappedFiles.has(p))\n .sort();\n\n const renameKeys = new Set<string>();\n for (const change of allChanges) {\n if (change.status !== \"renamed\" || !change.previousPath) continue;\n const key = `${change.previousPath}\u0000${change.path}`;\n if (renameKeys.has(key)) continue;\n renameKeys.add(key);\n report.renames.push({ from: change.previousPath, to: change.path });\n }\n\n const changedMapped = new Set<string>([\n ...Object.values(report.staleFeatures).flat(),\n ...Object.values(report.staleFlows).flat(),\n ]);\n const changedFraction =\n mappedFiles.size > 0 ? changedMapped.size / mappedFiles.size : 0;\n report.recommendation =\n changedMapped.size >= FULL_REBUILD_MIN_CHANGED_MAPPED_FILES &&\n changedFraction > FULL_REBUILD_FRACTION\n ? \"full-rebuild\"\n : \"incremental\";\n\n return report;\n}\n","import path from \"node:path\";\n\n// Question/filler words that carry no signal about which entry a task\n// touches. Domain words (\"auth\", \"drift\") are never in this list.\nconst STOPWORDS = new Set([\n \"the\", \"a\", \"an\", \"and\", \"or\", \"of\", \"to\", \"in\", \"on\", \"for\", \"with\",\n \"how\", \"does\", \"do\", \"is\", \"are\", \"was\", \"what\", \"where\", \"which\", \"why\",\n \"when\", \"who\", \"i\", \"we\", \"my\", \"our\", \"you\", \"your\", \"it\", \"its\", \"this\",\n \"that\", \"these\", \"those\", \"can\", \"could\", \"should\", \"would\", \"will\",\n \"want\", \"need\", \"please\", \"about\", \"into\", \"from\", \"when\", \"there\", \"any\",\n \"all\", \"some\", \"not\", \"but\", \"also\", \"just\", \"like\", \"get\", \"make\", \"use\",\n \"new\", \"work\", \"works\", \"working\", \"implement\", \"implemented\", \"change\",\n \"changed\", \"file\", \"files\", \"code\",\n]);\n\n/** Split camelCase/PascalCase/kebab/snake/path into lowercase word tokens. */\nexport function tokenize(text: string): string[] {\n return text\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 2 && !STOPWORDS.has(t));\n}\n\n/** Crude singular/plural folding so \"flows\" matches \"flow\" etc. */\nexport function stem(token: string): string {\n return token.length > 3 && token.endsWith(\"s\") ? token.slice(0, -1) : token;\n}\n\nexport function tokenSet(text: string): Set<string> {\n return new Set(tokenize(text).map(stem));\n}\n\nexport interface Scorable {\n name: string;\n description: string;\n files: string[];\n}\n\n/**\n * Lexical relevance of one entry to the task. Name hits are the strongest\n * signal, then description, then file-path words. Each distinct task token\n * counts once at its best weight, so a token appearing everywhere doesn't\n * triple-count.\n */\nexport function scoreEntry(taskTokens: Set<string>, entry: Scorable): number {\n const nameTokens = tokenSet(entry.name);\n const descTokens = tokenSet(entry.description);\n const fileTokens = tokenSet(entry.files.map((f) => path.basename(f)).join(\" \"));\n\n let score = 0;\n for (const token of taskTokens) {\n if (nameTokens.has(token)) score += 3;\n else if (descTokens.has(token)) score += 1;\n else if (fileTokens.has(token)) score += 1;\n }\n return score;\n}\n\n/** Jaccard similarity of two token sets: |∩| / |∪|, 0 when both empty. */\nexport function jaccard(a: Set<string>, b: Set<string>): number {\n if (a.size === 0 && b.size === 0) return 0;\n let intersection = 0;\n for (const token of a) if (b.has(token)) intersection++;\n return intersection / (a.size + b.size - intersection);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { getCurrentGitHash } from \"../snapshot/snapshot.js\";\nimport { jaccard, tokenSet } from \"../context/lexical.js\";\n\nexport type DecisionCategory =\n | \"decision\"\n | \"gotcha\"\n | \"deprecation\"\n | \"convention\";\nexport type DecisionStatus = \"active\" | \"superseded\";\n\n/**\n * One unit of team knowledge the code alone can't express: a failed\n * approach, a deprecation, a workaround's reason, a review-settled\n * convention. Stored one file per record under .mason/decisions/ so\n * concurrent additions on different branches merge without conflict,\n * while concurrent edits to the SAME record conflict — contested\n * knowledge should reach a human.\n */\nexport interface DecisionRecord {\n version: 1;\n id: string;\n title: string;\n body: string;\n category: DecisionCategory;\n /** Repo-relative anchor files. Empty means pure prose — never goes stale. */\n files: string[];\n createdAt: string;\n updatedAt: string;\n /** Commit this record was last verified against. */\n refreshedHash: string;\n status: DecisionStatus;\n supersededBy?: string;\n}\n\nexport const TITLE_MAX_CHARS = 80;\nexport const BODY_MAX_CHARS = 1500;\nexport const MAX_ACTIVE_DECISIONS = 150;\n\nconst DUPLICATE_JACCARD = 0.5;\nconst DUPLICATE_JACCARD_WITH_SHARED_FILE = 0.35;\n\nfunction decisionsDir(rootDir: string): string {\n return path.join(rootDir, \".mason\", \"decisions\");\n}\n\nexport async function loadDecisions(\n rootDir: string\n): Promise<DecisionRecord[]> {\n let entries: string[];\n try {\n entries = await fs.readdir(decisionsDir(rootDir));\n } catch {\n return [];\n }\n const records: DecisionRecord[] = [];\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) continue;\n try {\n const raw = await fs.readFile(\n path.join(decisionsDir(rootDir), entry),\n \"utf-8\"\n );\n const parsed = JSON.parse(raw);\n // Skip unknown versions and malformed records individually — one bad\n // merge artifact must not take down the store.\n if (parsed.version !== 1 || !parsed.id || !parsed.title || !parsed.body) {\n continue;\n }\n records.push(parsed);\n } catch {\n continue;\n }\n }\n return records.sort((a, b) => a.id.localeCompare(b.id));\n}\n\nexport async function saveDecisionRecord(\n rootDir: string,\n record: DecisionRecord\n): Promise<void> {\n await fs.mkdir(decisionsDir(rootDir), { recursive: true });\n await fs.writeFile(\n path.join(decisionsDir(rootDir), `${record.id}.json`),\n JSON.stringify(record, null, 2) + \"\\n\",\n \"utf-8\"\n );\n}\n\n/**\n * Deterministic, human-readable id: kebab slug of the title, ≤60 chars.\n * A slug collision with a DIFFERENT record appends a 6-hex content suffix.\n */\nexport function decisionIdFor(\n title: string,\n body: string,\n existingIds: Set<string>\n): string {\n const slug = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60)\n .replace(/-+$/, \"\");\n if (!existingIds.has(slug)) return slug || \"decision\";\n const suffix = createHash(\"sha1\")\n .update(title + body)\n .digest(\"hex\")\n .slice(0, 6);\n return `${slug}-${suffix}`;\n}\n\nexport function findNearDuplicate(\n candidate: { title: string; body: string; files: string[] },\n existing: DecisionRecord[]\n): { record: DecisionRecord; similarity: number } | null {\n const candidateTokens = tokenSet(`${candidate.title} ${candidate.body}`);\n const candidateFiles = new Set(candidate.files);\n let best: { record: DecisionRecord; similarity: number } | null = null;\n\n for (const record of existing) {\n if (record.status !== \"active\") continue;\n const similarity = jaccard(\n candidateTokens,\n tokenSet(`${record.title} ${record.body}`)\n );\n const sharesFile = record.files.some((f) => candidateFiles.has(f));\n const threshold = sharesFile\n ? DUPLICATE_JACCARD_WITH_SHARED_FILE\n : DUPLICATE_JACCARD;\n if (similarity >= threshold && (!best || similarity > best.similarity)) {\n best = { record, similarity };\n }\n }\n return best;\n}\n\nfunction sanitizeAnchorFiles(rootDir: string, files: string[]): string[] {\n const resolvedRoot = path.resolve(rootDir);\n return files.filter((f) => {\n const resolved = path.resolve(resolvedRoot, f);\n return (\n resolved.startsWith(resolvedRoot) &&\n !f.startsWith(\"/\") &&\n !f.includes(\"..\")\n );\n });\n}\n\nexport interface UpsertDecisionInput {\n title: string;\n body: string;\n category: DecisionCategory;\n files?: string[];\n /** Existing id to update. Same id + unchanged content = re-verify (re-pin to HEAD). */\n id?: string;\n /** Id of a decision this one replaces; the old record is kept, marked superseded. */\n supersedes?: string;\n /** Save even when a near-duplicate was detected. */\n force?: boolean;\n}\n\nexport type UpsertDecisionResult =\n | {\n status: \"created\" | \"updated\" | \"reverified\" | \"superseded_and_created\";\n id: string;\n totalActive: number;\n warnings: string[];\n pruneCandidates?: string[];\n }\n | { status: \"duplicate_suspected\"; existing: DecisionRecord; hint: string }\n | { status: \"error\"; error: string };\n\nexport async function upsertDecision(\n rootDir: string,\n input: UpsertDecisionInput\n): Promise<UpsertDecisionResult> {\n const title = input.title.trim();\n const body = input.body.trim();\n if (title.length === 0 || body.length === 0) {\n return { status: \"error\", error: \"title and body must be non-empty\" };\n }\n if (title.length > TITLE_MAX_CHARS) {\n return {\n status: \"error\",\n error: `title exceeds ${TITLE_MAX_CHARS} chars — tighten it to a specific headline`,\n };\n }\n if (body.length > BODY_MAX_CHARS) {\n return {\n status: \"error\",\n error: `body exceeds ${BODY_MAX_CHARS} chars — record the decision, not the transcript`,\n };\n }\n\n const existing = await loadDecisions(rootDir);\n const byId = new Map(existing.map((r) => [r.id, r]));\n const now = new Date().toISOString();\n const head = await getCurrentGitHash(rootDir);\n const warnings: string[] = [];\n\n const files = sanitizeAnchorFiles(rootDir, input.files ?? []);\n if (input.files && files.length < input.files.length) {\n warnings.push(\"some anchor paths were outside the repo and were dropped\");\n }\n // Nonexistent anchors warn but save — a deprecation note may outlive its file.\n for (const f of files) {\n try {\n await fs.access(path.join(rootDir, f));\n } catch {\n warnings.push(`anchor file does not exist on disk: ${f}`);\n }\n }\n\n // Update / re-verify path\n if (input.id) {\n const record = byId.get(input.id);\n if (!record) {\n return { status: \"error\", error: `no decision with id \"${input.id}\"` };\n }\n const unchanged =\n record.title === title &&\n record.body === body &&\n record.category === input.category &&\n JSON.stringify(record.files) === JSON.stringify(files.length > 0 ? files : record.files);\n const updated: DecisionRecord = {\n ...record,\n title,\n body,\n category: input.category,\n files: input.files !== undefined ? files : record.files,\n updatedAt: now,\n refreshedHash: head,\n };\n await saveDecisionRecord(rootDir, updated);\n return {\n status: unchanged ? \"reverified\" : \"updated\",\n id: record.id,\n totalActive: existing.filter((r) => r.status === \"active\").length,\n warnings,\n };\n }\n\n // Create path — dedupe first\n if (!input.force) {\n const duplicate = findNearDuplicate({ title, body, files }, existing);\n if (duplicate) {\n return {\n status: \"duplicate_suspected\",\n existing: duplicate.record,\n hint: `A similar decision exists (\"${duplicate.record.title}\"). Call save_decision with id=\"${duplicate.record.id}\" to update/merge into it, or force:true if genuinely distinct.`,\n };\n }\n }\n\n // Supersede\n if (input.supersedes) {\n const old = byId.get(input.supersedes);\n if (!old) {\n return {\n status: \"error\",\n error: `no decision with id \"${input.supersedes}\" to supersede`,\n };\n }\n const id = decisionIdFor(title, body, new Set(byId.keys()));\n await saveDecisionRecord(rootDir, {\n ...old,\n status: \"superseded\",\n supersededBy: id,\n updatedAt: now,\n });\n const record: DecisionRecord = {\n version: 1,\n id,\n title,\n body,\n category: input.category,\n files,\n createdAt: now,\n updatedAt: now,\n refreshedHash: head,\n status: \"active\",\n };\n await saveDecisionRecord(rootDir, record);\n return {\n status: \"superseded_and_created\",\n id,\n totalActive: existing.filter((r) => r.status === \"active\").length,\n warnings,\n };\n }\n\n const id = decisionIdFor(title, body, new Set(byId.keys()));\n const record: DecisionRecord = {\n version: 1,\n id,\n title,\n body,\n category: input.category,\n files,\n createdAt: now,\n updatedAt: now,\n refreshedHash: head,\n status: \"active\",\n };\n await saveDecisionRecord(rootDir, record);\n\n const totalActive =\n existing.filter((r) => r.status === \"active\").length + 1;\n const result: UpsertDecisionResult = {\n status: \"created\",\n id,\n totalActive,\n warnings,\n };\n if (totalActive > MAX_ACTIVE_DECISIONS) {\n // Never auto-evict git-committed team knowledge — surface candidates\n // for a human cleanup PR instead.\n result.pruneCandidates = existing\n .filter((r) => r.status === \"superseded\")\n .map((r) => r.id)\n .slice(0, 10);\n warnings.push(\n `${totalActive} active decisions exceeds the soft cap of ${MAX_ACTIVE_DECISIONS} — consider a cleanup PR (superseded records first)`\n );\n }\n return result;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fg from \"fast-glob\";\n\nconst exec = promisify(execFile);\n\nconst IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.gradle/**\",\n \"**/target/**\",\n \"**/.git/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/generated/**\",\n];\n\nconst SOURCE_EXTENSIONS =\n \"*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,c,h,dart,gradle.kts,gradle}\";\n\nexport interface CochangeEntry {\n file: string;\n cochangeRate: number;\n sharedCommits: number;\n}\n\nexport interface ReferenceEntry {\n file: string;\n matches: string[];\n /**\n * \"import\" when the name appears on an import/include/use line — a\n * structural dependency; \"mention\" for any other textual hit (comments,\n * strings, same-name-different-concept collisions). Imports sort first:\n * a mention of \"context\" in a doc comment is not the same signal as\n * `import { Context }`.\n */\n kind: \"import\" | \"mention\";\n}\n\nexport interface TestEntry {\n file: string;\n confidence: \"exact\" | \"best-guess\";\n}\n\nexport interface ImpactResult {\n targetFiles: string[];\n cochange: CochangeEntry[];\n references: ReferenceEntry[];\n tests: TestEntry[];\n}\n\nexport async function analyzeImpact(\n rootDir: string,\n targetFiles: string[]\n): Promise<ImpactResult> {\n const resolvedRoot = path.resolve(rootDir);\n\n // Resolve target files to full relative paths if only basename given\n const resolvedTargets = await resolveTargetFiles(resolvedRoot, targetFiles);\n\n const [cochange, references, tests] = await Promise.all([\n getCochangeFiles(resolvedRoot, resolvedTargets),\n getReferences(resolvedRoot, resolvedTargets),\n getRelatedTests(resolvedRoot, resolvedTargets),\n ]);\n\n return {\n targetFiles: resolvedTargets,\n cochange,\n references,\n tests,\n };\n}\n\nasync function resolveTargetFiles(\n rootDir: string,\n targets: string[]\n): Promise<string[]> {\n const resolved: string[] = [];\n\n for (const target of targets) {\n // If it contains a path separator, use as-is\n if (target.includes(\"/\")) {\n resolved.push(target);\n continue;\n }\n\n // Otherwise, search for the filename\n const matches = await fg(`**/${target}`, {\n cwd: rootDir,\n ignore: IGNORE,\n });\n\n if (matches.length > 0) {\n resolved.push(matches[0]);\n } else {\n // Try without extension\n const noExt = target.replace(/\\.[^.]+$/, \"\");\n const extMatches = await fg(`**/${noExt}.*`, {\n cwd: rootDir,\n ignore: IGNORE,\n });\n if (extMatches.length > 0) {\n resolved.push(extMatches[0]);\n } else {\n resolved.push(target); // Keep as-is, might still work for grep\n }\n }\n }\n\n return resolved;\n}\n\nasync function getCochangeFiles(\n rootDir: string,\n targetFiles: string[]\n): Promise<CochangeEntry[]> {\n const cochangeCounts = new Map<string, number>();\n let totalTargetCommits = 0;\n\n for (const targetFile of targetFiles) {\n try {\n // Get commits that touched this file (cap at 500)\n const { stdout: commitLog } = await exec(\n \"git\",\n [\"log\", \"--format=%H\", \"-n\", \"500\", \"--\", targetFile],\n { cwd: rootDir, maxBuffer: 5_000_000 }\n );\n\n const commits = commitLog.trim().split(\"\\n\").filter(Boolean);\n totalTargetCommits += commits.length;\n\n if (commits.length === 0) continue;\n\n // For each commit, get the other files that changed\n for (const commit of commits) {\n try {\n const { stdout: filesInCommit } = await exec(\n \"git\",\n [\"diff-tree\", \"--no-commit-id\", \"--name-only\", \"-r\", commit],\n { cwd: rootDir }\n );\n\n const files = filesInCommit.trim().split(\"\\n\").filter(Boolean);\n for (const file of files) {\n if (targetFiles.includes(file)) continue; // Skip the target itself\n cochangeCounts.set(file, (cochangeCounts.get(file) ?? 0) + 1);\n }\n } catch {\n // Skip this commit\n }\n }\n } catch {\n // No git or file not tracked\n }\n }\n\n if (totalTargetCommits === 0) return [];\n\n // Filter to files that co-change >30% of the time, sort by rate\n return [...cochangeCounts.entries()]\n .map(([file, count]) => ({\n file,\n cochangeRate: Math.round((count / totalTargetCommits) * 100) / 100,\n sharedCommits: count,\n }))\n .filter((e) => e.cochangeRate >= 0.3 || e.sharedCommits >= 3)\n .sort((a, b) => b.cochangeRate - a.cochangeRate)\n .slice(0, 20);\n}\n\nasync function getReferences(\n rootDir: string,\n targetFiles: string[]\n): Promise<ReferenceEntry[]> {\n // Extract searchable names from target files\n const searchNames = new Set<string>();\n for (const target of targetFiles) {\n const basename = path.basename(target).replace(/\\.[^.]+$/, \"\");\n searchNames.add(basename);\n }\n\n const allSourceFiles = await fg(`**/${SOURCE_EXTENSIONS}`, {\n cwd: rootDir,\n ignore: IGNORE,\n });\n\n // Exclude target files from search\n const targetSet = new Set(targetFiles);\n const filesToSearch = allSourceFiles.filter((f) => !targetSet.has(f));\n\n const results = new Map<string, { matches: Set<string>; isImport: boolean }>();\n\n // Language-agnostic import-line heuristic: covers JS/TS import/require,\n // Python import/from, Go/Rust/Swift/Kotlin/Java import/use, C include.\n const importLine = /^\\s*(import\\b|from\\b.*\\bimport\\b|const\\b.*=\\s*require\\(|use\\b|#include\\b|require\\s*\\()/;\n\n // Read files in batches to avoid too many open handles\n const batchSize = 50;\n for (let i = 0; i < filesToSearch.length; i += batchSize) {\n const batch = filesToSearch.slice(i, i + batchSize);\n\n await Promise.all(\n batch.map(async (file) => {\n try {\n const content = await fs.readFile(\n path.join(rootDir, file),\n \"utf-8\"\n );\n const lines = content.split(\"\\n\");\n\n for (const name of searchNames) {\n // Match the name as a word boundary (not part of another word)\n const regex = new RegExp(`\\\\b${escapeRegex(name)}\\\\b`);\n if (!regex.test(content)) continue;\n if (!results.has(file)) {\n results.set(file, { matches: new Set(), isImport: false });\n }\n const entry = results.get(file)!;\n entry.matches.add(name);\n if (\n !entry.isImport &&\n lines.some((l) => regex.test(l) && importLine.test(l))\n ) {\n entry.isImport = true;\n }\n }\n } catch {\n // Skip unreadable files\n }\n })\n );\n }\n\n return [...results.entries()]\n .map(([file, { matches, isImport }]) => ({\n file,\n matches: [...matches],\n kind: (isImport ? \"import\" : \"mention\") as \"import\" | \"mention\",\n }))\n .sort((a, b) => {\n if (a.kind !== b.kind) return a.kind === \"import\" ? -1 : 1;\n return b.matches.length - a.matches.length;\n });\n}\n\nasync function getRelatedTests(\n rootDir: string,\n targetFiles: string[]\n): Promise<TestEntry[]> {\n const testPatterns = [\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/*Test.kt\",\n \"**/*Test.java\",\n \"**/*Tests.kt\",\n \"**/*Tests.java\",\n \"**/test_*.py\",\n \"**/*_test.py\",\n \"**/*_test.go\",\n \"**/*Tests.swift\",\n \"**/*Test.swift\",\n \"**/*_test.rs\",\n ];\n\n const testFiles = await fg(testPatterns, { cwd: rootDir, ignore: IGNORE });\n const results: TestEntry[] = [];\n\n for (const target of targetFiles) {\n const targetBaseName = path\n .basename(target)\n .replace(/\\.[^.]+$/, \"\");\n\n for (const testFile of testFiles) {\n const testBaseName = path\n .basename(testFile)\n .replace(/\\.[^.]+$/, \"\");\n\n // Strip test suffixes to get the source name\n const sourceName = testBaseName\n .replace(/Test$|Tests$|Spec$|\\.test$|\\.spec$/, \"\")\n .replace(/^test_|_test$/, \"\");\n\n if (sourceName === targetBaseName) {\n results.push({\n file: testFile,\n confidence: \"exact\",\n });\n }\n }\n }\n\n return results;\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import path from \"node:path\";\nimport { getChangesWithStatus } from \"../drift/drift.js\";\nimport { getCurrentGitHash } from \"../snapshot/snapshot.js\";\nimport { loadDecisions } from \"./decisions.js\";\nimport type { DecisionRecord } from \"./decisions.js\";\n\n/**\n * Deliberately separate from DriftReport: mason-drift's exit codes and\n * --json shape are a CI contract, and `stale` there means MAP staleness.\n * Decision staleness is additive on top.\n */\nexport interface DecisionDriftReport {\n historyAvailable: boolean;\n totalDecisions: number;\n /** Decision id → anchor files changed since the record's refreshedHash. */\n staleDecisions: Record<string, string[]>;\n}\n\n/**\n * Flag active decisions whose anchor files changed since the record was\n * last verified. Anchorless decisions are pure prose and never go stale.\n * Deterministic — git only, no LLM.\n */\nexport async function computeDecisionDrift(\n rootDir: string,\n decisions?: DecisionRecord[]\n): Promise<DecisionDriftReport> {\n const resolvedRoot = path.resolve(rootDir);\n const records = decisions ?? (await loadDecisions(resolvedRoot));\n const report: DecisionDriftReport = {\n historyAvailable: true,\n totalDecisions: records.length,\n staleDecisions: {},\n };\n\n const head = await getCurrentGitHash(resolvedRoot);\n const changesByHash = new Map<string, Set<string> | null>();\n\n for (const record of records) {\n if (record.status !== \"active\" || record.files.length === 0) continue;\n if (record.refreshedHash === head) continue;\n\n let touched = changesByHash.get(record.refreshedHash);\n if (touched === undefined) {\n const changes = await getChangesWithStatus(\n resolvedRoot,\n record.refreshedHash\n );\n if (changes === null) {\n touched = null;\n } else {\n touched = new Set<string>();\n for (const change of changes) {\n touched.add(change.path);\n if (change.previousPath) touched.add(change.previousPath);\n }\n }\n changesByHash.set(record.refreshedHash, touched);\n }\n\n if (touched === null) {\n // Unreachable base commit — we know nothing per-file; surface that\n // rather than silently reporting the record fresh.\n report.historyAvailable = false;\n continue;\n }\n\n const hits = record.files.filter((f) => touched.has(f));\n if (hits.length > 0) {\n report.staleDecisions[record.id] = hits;\n }\n }\n\n return report;\n}\n","import path from \"node:path\";\nimport { loadSnapshot, normalizeFeatureType } from \"../snapshot/snapshot.js\";\nimport type { FeatureType, Snapshot } from \"../snapshot/snapshot.js\";\nimport { computeDrift } from \"../drift/drift.js\";\nimport { analyzeImpact } from \"../impact/impact.js\";\nimport type { CochangeEntry, ReferenceEntry } from \"../impact/impact.js\";\nimport { scoreEntry, tokenSet } from \"./lexical.js\";\nimport { loadDecisions } from \"../decisions/decisions.js\";\nimport type { DecisionCategory, DecisionRecord } from \"../decisions/decisions.js\";\nimport { computeDecisionDrift } from \"../decisions/drift.js\";\n\nconst MAX_FEATURES = 5;\nconst MAX_FLOWS = 3;\nconst MAX_IMPACT_TARGETS = 3;\nconst MAX_DECISIONS = 5;\nconst DECISION_FEATURE_OVERLAP_BOOST = 2;\n\nexport interface MatchedFeature {\n description: string;\n files: string[];\n tests?: string[];\n type: FeatureType;\n score: number;\n stale: boolean;\n}\n\nexport interface MatchedFlow {\n description: string;\n chain: string[];\n score: number;\n stale: boolean;\n}\n\nexport interface MatchedDecision {\n title: string;\n /** Full body — the payload the decisions store exists for. */\n body: string;\n category: DecisionCategory;\n files: string[];\n score: number;\n /** Anchor files changed since this record was last verified. */\n stale: boolean;\n}\n\nexport interface ContextBundle {\n exists: true;\n task: string;\n features: Record<string, MatchedFeature>;\n flows: Record<string, MatchedFlow>;\n /** Recorded team knowledge matching this task — treat as constraints. */\n decisions: Record<string, MatchedDecision>;\n /** All tests paired with the matched files, deduped. */\n relatedTests: string[];\n impact: {\n targets: string[];\n cochange: CochangeEntry[];\n references: ReferenceEntry[];\n } | null;\n freshness: {\n stale: boolean;\n recommendation: string;\n /** Matched entries whose files changed since they were last verified. */\n staleMatches: string[];\n };\n hint: string;\n}\n\nexport interface NoMatchBundle {\n exists: true;\n task: string;\n features: Record<string, never>;\n flows: Record<string, never>;\n /** Decisions can match even when no feature does. */\n decisions: Record<string, MatchedDecision>;\n /** The full feature catalog, so the caller can still act without a second guess. */\n availableFeatures: Record<string, string>;\n availableFlows: Record<string, string>;\n hint: string;\n}\n\n/**\n * Assemble everything needed to start a task in one call: matching map\n * entries, their files and tests, blast radius for the top files, and\n * per-entry freshness. Deterministic and LLM-free.\n *\n * `files` optionally anchors matching to an explicit file list (e.g. a diff):\n * entries containing those files are boosted above pure lexical matches.\n */\nexport async function assembleContext(\n rootDir: string,\n task: string,\n files?: string[]\n): Promise<ContextBundle | NoMatchBundle | null> {\n const resolvedRoot = path.resolve(rootDir);\n const snapshot = await loadSnapshot(resolvedRoot);\n if (!snapshot) return null;\n\n const drift = await computeDrift(resolvedRoot);\n const allDecisions = await loadDecisions(resolvedRoot);\n const decisionDrift = await computeDecisionDrift(resolvedRoot, allDecisions);\n const taskTokens = tokenSet(task);\n const anchorFiles = new Set(files ?? []);\n\n const anchorBoost = (entryFiles: string[]): number => {\n let boost = 0;\n for (const f of entryFiles) if (anchorFiles.has(f)) boost += 5;\n return boost;\n };\n\n const featureScores = Object.entries(snapshot.features)\n .map(([name, feat]) => ({\n name,\n feat,\n score:\n scoreEntry(taskTokens, { name, description: feat.description, files: feat.files }) +\n anchorBoost([...feat.files, ...(feat.tests ?? [])]),\n }))\n .filter((e) => e.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, MAX_FEATURES);\n\n const flowScores = Object.entries(snapshot.flows)\n .map(([name, flow]) => ({\n name,\n flow,\n score:\n scoreEntry(taskTokens, { name, description: flow.description, files: flow.chain }) +\n anchorBoost(flow.chain),\n }))\n .filter((e) => e.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, MAX_FLOWS);\n\n const matchedEntryFiles = new Set<string>([\n ...featureScores.flatMap((e) => e.feat.files),\n ...flowScores.flatMap((e) => e.flow.chain),\n ]);\n const decisions = matchDecisions(\n allDecisions,\n taskTokens,\n anchorBoost,\n matchedEntryFiles,\n decisionDrift.staleDecisions\n );\n\n if (featureScores.length === 0 && flowScores.length === 0) {\n return noMatchBundle(snapshot, task, decisions);\n }\n\n const features: Record<string, MatchedFeature> = {};\n const staleMatches: string[] = [];\n for (const { name, feat, score } of featureScores) {\n const stale = drift?.staleFeatures[name] !== undefined;\n if (stale) staleMatches.push(name);\n features[name] = {\n description: feat.description,\n files: feat.files,\n ...(feat.tests && feat.tests.length > 0 ? { tests: feat.tests } : {}),\n type: normalizeFeatureType(feat.type),\n score,\n stale,\n };\n }\n\n const flows: Record<string, MatchedFlow> = {};\n for (const { name, flow, score } of flowScores) {\n const stale = drift?.staleFlows[name] !== undefined;\n if (stale) staleMatches.push(name);\n flows[name] = {\n description: flow.description,\n chain: flow.chain,\n score,\n stale,\n };\n }\n\n // Blast radius for the most relevant files: anchor files first, then the\n // top-scoring feature's files.\n const impactTargets = [\n ...anchorFiles,\n ...featureScores.flatMap((e) => e.feat.files),\n ].slice(0, MAX_IMPACT_TARGETS);\n\n let impact: ContextBundle[\"impact\"] = null;\n let impactTests: string[] = [];\n if (impactTargets.length > 0) {\n const result = await analyzeImpact(resolvedRoot, impactTargets);\n impact = {\n targets: result.targetFiles,\n cochange: result.cochange,\n references: result.references.slice(0, 10),\n };\n impactTests = result.tests.map((t) => t.file);\n }\n\n const relatedTests = [\n ...new Set([\n ...featureScores.flatMap((e) => e.feat.tests ?? []),\n ...impactTests,\n ]),\n ];\n\n const stale = drift?.stale ?? false;\n const staleDecisionIds = Object.keys(decisions).filter(\n (id) => decisions[id].stale\n );\n return {\n exists: true,\n task,\n features,\n flows,\n decisions,\n relatedTests,\n impact,\n freshness: {\n stale,\n recommendation: drift?.recommendation ?? \"up-to-date\",\n staleMatches,\n },\n hint: bundleHint(stale, staleMatches, staleDecisionIds),\n };\n}\n\n/**\n * Score active decisions against the task with the same lexical machinery\n * as map entries, plus a feature-overlap boost: a decision anchored to a\n * file of an already-matched feature is relevant even with zero lexical\n * overlap (\"auth is weird\" should surface on any auth task).\n */\nfunction matchDecisions(\n allDecisions: DecisionRecord[],\n taskTokens: Set<string>,\n anchorBoost: (files: string[]) => number,\n matchedEntryFiles: Set<string>,\n staleDecisions: Record<string, string[]>\n): Record<string, MatchedDecision> {\n const scored = allDecisions\n .filter((d) => d.status === \"active\")\n .map((d) => {\n let score =\n scoreEntry(taskTokens, {\n name: d.title,\n description: d.body,\n files: d.files,\n }) + anchorBoost(d.files);\n if (d.files.some((f) => matchedEntryFiles.has(f))) {\n score += DECISION_FEATURE_OVERLAP_BOOST;\n }\n return { d, score };\n })\n .filter((e) => e.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, MAX_DECISIONS);\n\n const result: Record<string, MatchedDecision> = {};\n for (const { d, score } of scored) {\n result[d.id] = {\n title: d.title,\n body: d.body,\n category: d.category,\n files: d.files,\n score,\n stale: staleDecisions[d.id] !== undefined,\n };\n }\n return result;\n}\n\nfunction bundleHint(\n stale: boolean,\n staleMatches: string[],\n staleDecisionIds: string[] = []\n): string {\n const parts: string[] = [];\n if (staleMatches.length > 0) {\n parts.push(\n `Entries [${staleMatches.join(\", \")}] changed since they were last verified — read their files rather than trusting the descriptions, and consider mason_check_drift for a refresh plan.`\n );\n } else if (stale) {\n parts.push(\n \"The matched entries are current, but other parts of the map have drifted — mason_check_drift shows what needs refreshing.\"\n );\n } else {\n parts.push(\n \"Map is current. Start from the listed files; cochange/references show what else an edit would touch.\"\n );\n }\n if (staleDecisionIds.length > 0) {\n parts.push(\n `Decisions [${staleDecisionIds.join(\", \")}] have anchor files that changed since they were recorded — verify each still holds; if it does, re-save it with its id to re-pin, otherwise update or supersede it via save_decision.`\n );\n }\n return parts.join(\" \");\n}\n\nfunction noMatchBundle(\n snapshot: Snapshot,\n task: string,\n decisions: Record<string, MatchedDecision>\n): NoMatchBundle {\n const availableFeatures: Record<string, string> = {};\n for (const [name, feat] of Object.entries(snapshot.features)) {\n availableFeatures[name] = feat.description;\n }\n const availableFlows: Record<string, string> = {};\n for (const [name, flow] of Object.entries(snapshot.flows)) {\n availableFlows[name] = flow.description;\n }\n return {\n exists: true,\n task,\n features: {},\n flows: {},\n decisions,\n availableFeatures,\n availableFlows,\n hint: \"No map entry matched the task wording. The full catalog is listed — pick the relevant entries and call get_context again with their names in the task, or read their files directly via get_snapshot.\",\n };\n}\n","import type { ConfluenceConfig } from \"../llm/config.js\";\n\nexport interface ConfluencePage {\n id: string;\n title: string;\n version: number;\n body: string;\n parentId?: string;\n}\n\nexport interface CreatePageInput {\n spaceId: string;\n title: string;\n body: string;\n parentId?: string;\n}\n\nexport interface UpdatePageInput {\n id: string;\n title: string;\n body: string;\n version: number;\n parentId?: string;\n}\n\nexport interface ConfluenceSpace {\n id: string;\n key: string;\n name: string;\n}\n\nexport interface ConfluenceRootPage {\n id: string;\n title: string;\n}\n\nexport interface ConfluenceClient {\n resolveSpaceId(spaceKey: string): Promise<string>;\n listSpaces(): Promise<ConfluenceSpace[]>;\n listRootPages(spaceId: string): Promise<ConfluenceRootPage[]>;\n findPageByTitle(spaceId: string, title: string): Promise<ConfluencePage | null>;\n createPage(input: CreatePageInput): Promise<ConfluencePage>;\n updatePage(input: UpdatePageInput): Promise<ConfluencePage>;\n}\n\ninterface PageApiResponse {\n id: string;\n title: string;\n parentId?: string;\n version?: { number: number };\n body?: { storage?: { value?: string } };\n}\n\nexport function createConfluenceClient(\n config: ConfluenceConfig,\n fetchFn: typeof fetch = fetch\n): ConfluenceClient {\n const baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n const auth =\n \"Basic \" +\n Buffer.from(`${config.email}:${config.apiToken}`).toString(\"base64\");\n\n async function call(\n method: string,\n path: string,\n body?: unknown\n ): Promise<unknown> {\n const res = await fetchFn(`${baseUrl}${path}`, {\n method,\n headers: {\n Authorization: auth,\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(\n `Confluence ${method} ${path} failed: ${res.status} ${res.statusText} — ${text}`\n );\n }\n\n if (res.status === 204) return null;\n return res.json();\n }\n\n function toPage(raw: PageApiResponse): ConfluencePage {\n return {\n id: raw.id,\n title: raw.title,\n version: raw.version?.number ?? 1,\n body: raw.body?.storage?.value ?? \"\",\n parentId: raw.parentId,\n };\n }\n\n return {\n async resolveSpaceId(spaceKey: string): Promise<string> {\n const res = (await call(\n \"GET\",\n `/wiki/api/v2/spaces?keys=${encodeURIComponent(spaceKey)}`\n )) as { results?: Array<{ id: string; key: string }> };\n const space = res.results?.find((s) => s.key === spaceKey);\n if (!space) {\n throw new Error(`Confluence space not found: ${spaceKey}`);\n }\n return space.id;\n },\n\n async listSpaces(): Promise<ConfluenceSpace[]> {\n const all: ConfluenceSpace[] = [];\n let cursor = \"/wiki/api/v2/spaces?limit=100\";\n while (cursor) {\n const res = (await call(\"GET\", cursor)) as {\n results?: Array<{ id: string; key: string; name?: string }>;\n _links?: { next?: string };\n };\n for (const s of res.results ?? []) {\n all.push({ id: s.id, key: s.key, name: s.name ?? s.key });\n }\n const next = res._links?.next;\n if (!next) break;\n // v2 returns relative paths beginning with \"/wiki/...\"\n cursor = next.startsWith(\"/\") ? next : `/${next}`;\n }\n return all;\n },\n\n async listRootPages(spaceId: string): Promise<ConfluenceRootPage[]> {\n const url =\n `/wiki/api/v2/spaces/${encodeURIComponent(spaceId)}/pages` +\n `?depth=root&limit=50`;\n const res = (await call(\"GET\", url)) as {\n results?: Array<{ id: string; title: string }>;\n };\n return (res.results ?? []).map((p) => ({ id: p.id, title: p.title }));\n },\n\n async findPageByTitle(\n spaceId: string,\n title: string\n ): Promise<ConfluencePage | null> {\n const url =\n `/wiki/api/v2/spaces/${encodeURIComponent(spaceId)}/pages` +\n `?title=${encodeURIComponent(title)}&body-format=storage&limit=1`;\n const res = (await call(\"GET\", url)) as {\n results?: PageApiResponse[];\n };\n const match = res.results?.find((p) => p.title === title);\n return match ? toPage(match) : null;\n },\n\n async createPage(input: CreatePageInput): Promise<ConfluencePage> {\n const res = (await call(\"POST\", \"/wiki/api/v2/pages\", {\n spaceId: input.spaceId,\n status: \"current\",\n title: input.title,\n parentId: input.parentId,\n body: {\n representation: \"storage\",\n value: input.body,\n },\n })) as PageApiResponse;\n return toPage(res);\n },\n\n async updatePage(input: UpdatePageInput): Promise<ConfluencePage> {\n const res = (await call(\"PUT\", `/wiki/api/v2/pages/${input.id}`, {\n id: input.id,\n status: \"current\",\n title: input.title,\n parentId: input.parentId,\n body: {\n representation: \"storage\",\n value: input.body,\n },\n version: {\n number: input.version + 1,\n },\n })) as PageApiResponse;\n return toPage(res);\n },\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst exec = promisify(execFile);\n\nexport type Provider = \"claude\" | \"gemini\" | \"openai\" | \"ollama\";\n\nexport interface ConfluenceConfig {\n baseUrl: string;\n email: string;\n apiToken: string;\n spaceKey: string;\n parentPageId?: string;\n}\n\nexport interface MasonConfig {\n provider: Provider;\n apiKey?: string;\n model?: string;\n ollamaHost?: string;\n confluence?: ConfluenceConfig;\n}\n\nfunction configDir(): string {\n return path.join(os.homedir(), \".mason\");\n}\n\nfunction configFile(): string {\n return path.join(configDir(), \"config.json\");\n}\n\nconst DEFAULT_MODELS: Record<Provider, string> = {\n claude: \"claude-sonnet-4-20250514\",\n gemini: \"gemini-2.5-flash\",\n openai: \"gpt-4o\",\n ollama: \"llama3\",\n};\n\nexport async function loadConfig(): Promise<MasonConfig | null> {\n try {\n const raw = await fs.readFile(configFile(), \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nexport async function saveConfig(config: MasonConfig): Promise<void> {\n await fs.mkdir(configDir(), { recursive: true });\n await fs.writeFile(configFile(), JSON.stringify(config, null, 2), \"utf-8\");\n}\n\nexport function getDefaultModel(provider: Provider): string {\n return DEFAULT_MODELS[provider];\n}\n\nexport function validateProvider(value: string): Provider {\n const valid: Provider[] = [\"claude\", \"gemini\", \"openai\", \"ollama\"];\n if (!valid.includes(value as Provider)) {\n throw new Error(\n `Invalid provider \"${value}\". Must be one of: ${valid.join(\", \")}`\n );\n }\n return value as Provider;\n}\n\nexport async function detectCLI(\n provider: Provider\n): Promise<{ available: boolean; version?: string }> {\n const cliName = provider === \"claude\" ? \"claude\"\n : provider === \"gemini\" ? \"gemini\"\n : provider === \"ollama\" ? \"ollama\"\n : null;\n\n if (!cliName) return { available: false };\n\n try {\n const { stdout } = await exec(cliName, [\"--version\"]);\n return { available: true, version: stdout.trim() };\n } catch {\n return { available: false };\n }\n}\n\nexport function needsApiKey(provider: Provider): boolean {\n return provider === \"openai\";\n}\n\nexport async function saveConfluenceConfig(\n confluence: ConfluenceConfig\n): Promise<void> {\n const existing = (await loadConfig()) ?? { provider: \"claude\" as Provider };\n await saveConfig({ ...existing, confluence });\n}\n\nexport async function loadConfluenceConfig(): Promise<ConfluenceConfig | null> {\n const config = await loadConfig();\n return config?.confluence ?? null;\n}\n","export function normalizeAtlassianBaseUrl(input: string): string {\n const trimmed = input.trim().replace(/\\/+$/, \"\");\n if (!trimmed) throw new Error(\"Confluence baseUrl is required.\");\n if (/^https?:\\/\\//i.test(trimmed)) return trimmed;\n if (trimmed.includes(\".\")) return `https://${trimmed}`;\n // Bare subdomain — assume Atlassian Cloud\n return `https://${trimmed}.atlassian.net`;\n}\n","import type { FeatureEntry, FlowEntry } from \"../snapshot/snapshot.js\";\n\n// Mason fully owns each page body and overwrites it on every sync. Confluence\n// strips HTML comments and re-serializes storage XHTML, so in-page region\n// markers can't survive a round-trip — no-op detection happens via a content\n// hash in the local sync state instead (see sync.ts / diff.ts).\n\nfunction escape(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\nfunction infoPanel(text: string): string {\n return (\n `<ac:structured-macro ac:name=\"info\"><ac:rich-text-body>` +\n `<p>${escape(text)}</p>` +\n `</ac:rich-text-body></ac:structured-macro>`\n );\n}\n\nexport function featurePageTitle(prefix: string, name: string): string {\n return `${prefix}${name}`;\n}\n\nexport interface RenderedFeaturePage {\n body: string;\n title: string;\n}\n\nexport interface RenderFeaturePageOptions {\n name: string;\n productDescription: string;\n flowDescriptions: Array<{ name: string; description: string }>;\n indexPageTitle: string;\n}\n\nexport function renderFeaturePage(\n options: RenderFeaturePageOptions\n): RenderedFeaturePage {\n const overviewBody =\n `<h2>What it does</h2>` + `<p>${escape(options.productDescription)}</p>`;\n\n // Only render \"How it fits in\" when there are flows — an empty section with a\n // \"nothing here\" placeholder reads as unfinished.\n const flowsBody = options.flowDescriptions.length\n ? `<h2>How it fits in</h2><ul>` +\n options.flowDescriptions\n .map(\n (f) =>\n `<li><strong>${escape(f.name)}</strong> — ${escape(f.description)}</li>`\n )\n .join(\"\") +\n `</ul>`\n : \"\";\n\n // Native Confluence page link, resolved by title.\n const navBody =\n `<p><ac:link><ri:page ri:content-title=\"${escape(options.indexPageTitle)}\"/>` +\n `<ac:plain-text-link-body><![CDATA[Back to ${options.indexPageTitle}]]></ac:plain-text-link-body>` +\n `</ac:link></p>`;\n\n // Provenance note as a footer, not wedged between the content sections.\n const footer = infoPanel(\n `Generated from code by Mason. This page is overwritten on each sync — ` +\n `edit the code, not the page.`\n );\n\n const body = overviewBody + flowsBody + navBody + footer;\n\n return {\n title: options.name,\n body,\n };\n}\n\nexport interface RenderIndexPageOptions {\n featureTitles: string[];\n featurePrefix: string;\n}\n\nexport function renderIndexPage(options: RenderIndexPageOptions): string {\n if (options.featureTitles.length === 0) {\n return infoPanel(\"No features in the snapshot yet.\");\n }\n\n const list =\n `<h2>Features</h2><ul>` +\n options.featureTitles\n .map((name) => {\n const pageTitle = featurePageTitle(options.featurePrefix, name);\n return (\n `<li><ac:link><ri:page ri:content-title=\"${escape(pageTitle)}\"/>` +\n `<ac:plain-text-link-body><![CDATA[${name}]]></ac:plain-text-link-body>` +\n `</ac:link></li>`\n );\n })\n .join(\"\") +\n `</ul>`;\n\n const banner = infoPanel(\n `Generated from code by Mason. Maintained automatically — edit the code, not this page.`\n );\n\n return banner + list;\n}\n\nexport interface DiffSection {\n syncedAt: string;\n addedFeatures: string[];\n removedFeatures: string[];\n changedFeatures: string[];\n addedFlows: string[];\n removedFlows: string[];\n}\n\nexport function renderChangelogSection(section: DiffSection): string {\n const segments: string[] = [];\n if (section.addedFeatures.length) {\n segments.push(\n `<p><strong>Added features:</strong> ${section.addedFeatures.map(escape).join(\", \")}</p>`\n );\n }\n if (section.removedFeatures.length) {\n segments.push(\n `<p><strong>Removed features:</strong> ${section.removedFeatures.map(escape).join(\", \")}</p>`\n );\n }\n if (section.changedFeatures.length) {\n segments.push(\n `<p><strong>Updated features:</strong> ${section.changedFeatures.map(escape).join(\", \")}</p>`\n );\n }\n if (section.addedFlows.length) {\n segments.push(\n `<p><strong>Added flows:</strong> ${section.addedFlows.map(escape).join(\", \")}</p>`\n );\n }\n if (section.removedFlows.length) {\n segments.push(\n `<p><strong>Removed flows:</strong> ${section.removedFlows.map(escape).join(\", \")}</p>`\n );\n }\n if (segments.length === 0) {\n segments.push(`<p><em>No meaningful changes detected.</em></p>`);\n }\n\n return (\n `<h3>${escape(section.syncedAt)}</h3>` + segments.join(\"\")\n );\n}\n\nexport function renderChangelogPage(sections: string[]): string {\n if (sections.length === 0) {\n return `<p><em>No sync has run yet.</em></p>`;\n }\n // Newest first\n return sections.join(\"\\n<hr/>\\n\");\n}\n\nexport type FeatureMap = Record<string, FeatureEntry>;\nexport type FlowMap = Record<string, FlowEntry>;\n\nexport function flowsForFeature(\n featureFiles: string[],\n flows: FlowMap\n): Array<{ name: string; description: string }> {\n const fileSet = new Set(featureFiles);\n const result: Array<{ name: string; description: string }> = [];\n for (const [name, flow] of Object.entries(flows)) {\n if (flow.chain.some((file) => fileSet.has(file))) {\n result.push({ name, description: flow.description });\n }\n }\n return result;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport type { Snapshot } from \"../snapshot/snapshot.js\";\nimport type { DiffSection } from \"./renderer.js\";\n\nexport interface RewriteCacheEntry {\n /** sha256 of the engineering (source) description this prose was derived from */\n sourceHash: string;\n /** the cached product-language prose */\n product: string;\n /** true when produced by the no-LLM fallback, not the model — re-attempted next run */\n fallback?: boolean;\n}\n\nexport interface RewriteCache {\n features: Record<string, RewriteCacheEntry>;\n flows: Record<string, RewriteCacheEntry>;\n}\n\nexport interface SyncState {\n version: 2;\n syncedAt: string;\n pageIds: {\n index?: string;\n changelog?: string;\n features: Record<string, string>;\n };\n lastSnapshot: {\n features: Record<string, { description: string }>;\n flows: Record<string, { description: string }>;\n };\n changelogSections: string[];\n /** product-language prose cache, keyed by feature/flow name */\n rewriteCache: RewriteCache;\n /**\n * Hash of the body Mason last rendered for each page, keyed by page title.\n * Used to skip re-publishing unchanged pages — we compare our render hash to\n * this, never to Confluence's re-serialized body. Optional for forward\n * compatibility with state written before this field existed.\n */\n pageHashes?: Record<string, string>;\n}\n\n/** Stable content hash of a source description, for cache invalidation. */\nexport function hashDescription(description: string): string {\n return createHash(\"sha256\").update(description, \"utf8\").digest(\"hex\");\n}\n\nfunction syncStateDir(rootDir: string): string {\n return path.join(rootDir, \".mason\");\n}\n\nfunction syncStatePath(rootDir: string): string {\n return path.join(syncStateDir(rootDir), \"confluence-sync.json\");\n}\n\nexport async function loadSyncState(rootDir: string): Promise<SyncState | null> {\n try {\n const raw = await fs.readFile(syncStatePath(rootDir), \"utf-8\");\n const parsed = JSON.parse(raw);\n // Only v2 state is usable. Older state (v1) is treated as absent: the next\n // export re-finds pages by title and rebuilds the rewrite cache from scratch.\n if (parsed.version !== 2) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport async function saveSyncState(\n rootDir: string,\n state: SyncState\n): Promise<void> {\n await fs.mkdir(syncStateDir(rootDir), { recursive: true });\n await fs.writeFile(\n syncStatePath(rootDir),\n JSON.stringify(state, null, 2),\n \"utf-8\"\n );\n}\n\nexport function computeDiff(\n previous: SyncState | null,\n current: Snapshot,\n syncedAt: string\n): DiffSection {\n const prevFeatures = previous?.lastSnapshot.features ?? {};\n const prevFlows = previous?.lastSnapshot.flows ?? {};\n\n const currentFeatureNames = Object.keys(current.features);\n const prevFeatureNames = Object.keys(prevFeatures);\n\n const addedFeatures = currentFeatureNames.filter(\n (n) => !(n in prevFeatures)\n );\n const removedFeatures = prevFeatureNames.filter(\n (n) => !(n in current.features)\n );\n const changedFeatures = currentFeatureNames.filter(\n (n) =>\n n in prevFeatures &&\n prevFeatures[n].description !== current.features[n].description\n );\n\n const currentFlowNames = Object.keys(current.flows);\n const prevFlowNames = Object.keys(prevFlows);\n const addedFlows = currentFlowNames.filter((n) => !(n in prevFlows));\n const removedFlows = prevFlowNames.filter((n) => !(n in current.flows));\n\n return {\n syncedAt,\n addedFeatures,\n removedFeatures,\n changedFeatures,\n addedFlows,\n removedFlows,\n };\n}\n\nexport function isMeaningfulDiff(diff: DiffSection): boolean {\n return (\n diff.addedFeatures.length > 0 ||\n diff.removedFeatures.length > 0 ||\n diff.changedFeatures.length > 0 ||\n diff.addedFlows.length > 0 ||\n diff.removedFlows.length > 0\n );\n}\n\nexport function snapshotMinimal(snapshot: Snapshot): SyncState[\"lastSnapshot\"] {\n const features: Record<string, { description: string }> = {};\n for (const [k, v] of Object.entries(snapshot.features)) {\n features[k] = { description: v.description };\n }\n const flows: Record<string, { description: string }> = {};\n for (const [k, v] of Object.entries(snapshot.flows)) {\n flows[k] = { description: v.description };\n }\n return { features, flows };\n}\n","import { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { MasonConfig } from \"./config.js\";\nimport { getDefaultModel } from \"./config.js\";\n\nconst exec = promisify(execFile);\n\nconst CLAUDE_MD_SYSTEM_PROMPT = `You are Mason, a context engineering tool. You've been given a comprehensive analysis of a codebase including:\n- Git history stats (commit patterns, frequently changed files, stale directories)\n- Project structure (directory layout, file counts by type)\n- Curated code samples (key architectural files with previews)\n- Test-to-source file mapping\n\nYour job: write a COMPLETE CLAUDE.md file from scratch based ONLY on the analysis data provided below. Do NOT read any existing files in the project. Do NOT reference or preserve any existing CLAUDE.md. Generate the entire document fresh.\n\nCRITICAL: Output ONLY the raw markdown content. No preamble, no summary, no \"Here's the CLAUDE.md:\", no explanation, no questions, no commentary. Start directly with \"# CLAUDE.md\" and end with the last line of content. Your entire response will be written directly to a file.\n\nThe CLAUDE.md should include:\n- Project overview (what it is, tech stack, architecture)\n- Module/package structure and boundaries\n- Code conventions and patterns you observe in the samples\n- Testing conventions and coverage\n- Build and development commands\n- Important files and hot spots\n- Any warnings or gotchas\n\nBe specific and actionable. Reference actual file paths. Don't be generic — every rule should be grounded in what you see in the data.`;\n\nexport type CallResult =\n | { type: \"response\"; text: string }\n | { type: \"prompt\"; text: string };\n\nexport async function callLLM(\n config: MasonConfig,\n userMessage: string,\n systemPrompt?: string\n): Promise<CallResult> {\n const model = config.model ?? getDefaultModel(config.provider);\n const system = systemPrompt ?? CLAUDE_MD_SYSTEM_PROMPT;\n\n switch (config.provider) {\n case \"claude\":\n if (config.apiKey) {\n return {\n type: \"response\",\n text: await callClaudeAPI(config.apiKey, model, system, userMessage),\n };\n }\n return {\n type: \"response\",\n text: await callClaudeCLI(system, userMessage),\n };\n\n case \"ollama\":\n return {\n type: \"response\",\n text: await callOllamaCLI(\n config.ollamaHost ?? \"http://localhost:11434\",\n model,\n system,\n userMessage,\n ),\n };\n\n case \"gemini\":\n if (config.apiKey) {\n return {\n type: \"response\",\n text: await callGeminiAPI(config.apiKey, model, system, userMessage),\n };\n }\n return {\n type: \"response\",\n text: await callGeminiCLI(system, userMessage),\n };\n\n case \"openai\":\n if (config.apiKey) {\n return {\n type: \"response\",\n text: await callOpenAIAPI(config.apiKey, model, system, userMessage),\n };\n }\n return {\n type: \"prompt\",\n text: formatPromptForCopy(system, userMessage),\n };\n }\n}\n\nfunction formatPromptForCopy(system: string, userMessage: string): string {\n return `${system}\\n\\n---\\n\\n${userMessage}`;\n}\n\n// === CLI-based providers (no API key) ===\n\nasync function callViaTempFile(\n command: string,\n args: (promptPath: string) => string[],\n system: string,\n userMessage: string\n): Promise<string> {\n const fs = await import(\"node:fs/promises\");\n const os = await import(\"node:os\");\n const path = await import(\"node:path\");\n\n const prompt = `${system}\\n\\n${userMessage}`;\n const tmpFile = path.join(os.tmpdir(), `mason-prompt-${Date.now()}.txt`);\n\n try {\n await fs.writeFile(tmpFile, prompt, \"utf-8\");\n const { stdout } = await exec(command, args(tmpFile), {\n maxBuffer: 10_000_000,\n timeout: 300_000,\n });\n return stdout.trim();\n } finally {\n await fs.unlink(tmpFile).catch(() => {});\n }\n}\n\nfunction spawnWithStdin(\n command: string,\n args: string[],\n input: string\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n timeout: 300_000,\n });\n\n // ora puts stdin into raw mode, which means Ctrl+C is emitted as\n // process.emit(\"SIGINT\") rather than a real signal to the process\n // group. Forward it to the child so it can terminate.\n const onSigint = () => proc.kill(\"SIGINT\");\n process.on(\"SIGINT\", onSigint);\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n proc.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n\n proc.on(\"close\", (code: number | null) => {\n process.off(\"SIGINT\", onSigint);\n if (code === 0) {\n resolve(stdout.trim());\n } else {\n reject(new Error(`${command} exited with code ${code}: ${stderr}`));\n }\n });\n\n proc.on(\"error\", (err) => {\n process.off(\"SIGINT\", onSigint);\n reject(err);\n });\n\n proc.stdin.write(input);\n proc.stdin.end();\n });\n}\n\nasync function callClaudeCLI(\n system: string,\n userMessage: string\n): Promise<string> {\n return spawnWithStdin(\"claude\", [\"-p\", \"--system-prompt\", system], userMessage);\n}\n\nasync function callGeminiCLI(\n system: string,\n userMessage: string\n): Promise<string> {\n const prompt = `<system>\\n${system}\\n</system>\\n\\n${userMessage}`;\n return spawnWithStdin(\"gemini\", [\"-p\", \"\"], prompt);\n}\n\nasync function callOllamaCLI(\n host: string,\n model: string,\n system: string,\n userMessage: string\n): Promise<string> {\n const response = await fetch(`${host}/api/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n model,\n stream: false,\n messages: [\n { role: \"system\", content: system },\n { role: \"user\", content: userMessage },\n ],\n }),\n });\n\n const result = (await response.json()) as {\n message?: { content?: string };\n };\n return result.message?.content ?? \"\";\n}\n\n// === API-based providers ===\n\nasync function callClaudeAPI(\n apiKey: string,\n model: string,\n system: string,\n userMessage: string\n): Promise<string> {\n const { default: Anthropic } = await import(\"@anthropic-ai/sdk\");\n const client = new Anthropic({ apiKey });\n\n const response = await client.messages.create({\n model,\n max_tokens: 8192,\n system,\n messages: [{ role: \"user\", content: userMessage }],\n });\n\n const textBlock = response.content.find((b) => b.type === \"text\");\n return textBlock?.text ?? \"\";\n}\n\nasync function callGeminiAPI(\n apiKey: string,\n model: string,\n system: string,\n userMessage: string\n): Promise<string> {\n const { default: OpenAI } = await import(\"openai\");\n const client = new OpenAI({\n apiKey,\n baseURL: \"https://generativelanguage.googleapis.com/v1beta/openai/\",\n });\n\n const response = await client.chat.completions.create({\n model,\n max_tokens: 8192,\n messages: [\n { role: \"system\", content: system },\n { role: \"user\", content: userMessage },\n ],\n });\n\n return response.choices[0]?.message?.content ?? \"\";\n}\n\nasync function callOpenAIAPI(\n apiKey: string,\n model: string,\n system: string,\n userMessage: string\n): Promise<string> {\n const { default: OpenAI } = await import(\"openai\");\n const client = new OpenAI({ apiKey });\n\n const response = await client.chat.completions.create({\n model,\n max_tokens: 8192,\n messages: [\n { role: \"system\", content: system },\n { role: \"user\", content: userMessage },\n ],\n });\n\n return response.choices[0]?.message?.content ?? \"\";\n}\n","import { callLLM } from \"../llm/providers.js\";\nimport type { MasonConfig } from \"../llm/config.js\";\nimport type {\n FeatureEntry,\n FlowEntry,\n Snapshot,\n} from \"../snapshot/snapshot.js\";\nimport {\n hashDescription,\n type RewriteCache,\n type RewriteCacheEntry,\n} from \"./diff.js\";\n\nconst PM_REWRITE_SYSTEM_PROMPT = `You are Mason, rewriting an engineering-flavoured concept map into product-readable language for a company wiki.\n\nYou will receive a JSON object with two maps:\n- \"features\": each entry has a description and a list of source file paths.\n- \"flows\": each entry has a description and an ordered chain of file paths.\n\nYour job: rewrite EACH description so a Product Manager, designer, or non-engineering stakeholder can understand what the system does — without seeing any code. Treat the file paths as hints, not content. Do NOT include them in your output.\n\nHard rules:\n- NEVER mention file names, directory names, file extensions, class names, function names, repository names, framework names, or libraries.\n- NEVER use words like \"module\", \"service\", \"handler\", \"controller\", \"ViewModel\", \"repository\", \"endpoint\", \"API\", \"schema\", \"interface\", \"class\".\n- Use plain English. Focus on what users or the business can do, what data moves, what decisions get made, and why it matters.\n- 1–3 sentences per description. Concrete. No filler.\n- Preserve the original keys exactly; only the description values change.\n\nOutput ONLY raw JSON with the same shape as the input — same keys, rewritten descriptions. No markdown, no code fences, no preamble.`;\n\ntype Rewritten = {\n features: Record<string, string>;\n flows: Record<string, string>;\n};\n\ninterface RewriteInput {\n features: Record<string, FeatureEntry>;\n flows: Record<string, FlowEntry>;\n}\n\nfunction buildPrompt(input: RewriteInput): string {\n return `Rewrite the descriptions below for a product audience. Return ONLY a JSON object of the form {\"features\": {\"name\": \"rewritten description\", ...}, \"flows\": {...}}.\\n\\n${JSON.stringify(input, null, 2)}`;\n}\n\nfunction parseRewriteResponse(raw: string): Rewritten {\n let cleaned = raw.trim();\n if (cleaned.startsWith(\"```\")) {\n cleaned = cleaned.replace(/^```(?:json)?\\n?/, \"\").replace(/\\n?```$/, \"\");\n }\n try {\n const parsed = JSON.parse(cleaned);\n return {\n features: parsed.features ?? {},\n flows: parsed.flows ?? {},\n };\n } catch {\n const match = raw.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n try {\n const parsed = JSON.parse(match[0]);\n return {\n features: parsed.features ?? {},\n flows: parsed.flows ?? {},\n };\n } catch {\n return { features: {}, flows: {} };\n }\n }\n return { features: {}, flows: {} };\n }\n}\n\nexport interface RewriteResult {\n features: Record<string, string>;\n flows: Record<string, string>;\n /** Updated prose cache to persist into the sync state. */\n cache: RewriteCache;\n}\n\nexport interface RewriteContext {\n /** Prose cache from the previous sync; used to skip unchanged entries. */\n previousCache?: RewriteCache;\n /** LLM caller; injectable for tests. Defaults to the configured provider. */\n llm?: typeof callLLM;\n}\n\n/** Pick a subset of a record by key. */\nfunction pick<T>(source: Record<string, T>, keys: string[]): Record<string, T> {\n const out: Record<string, T> = {};\n for (const k of keys) out[k] = source[k];\n return out;\n}\n\n/**\n * Rewrite engineering descriptions into product-readable prose, incrementally.\n *\n * Entries whose source description is unchanged since the last sync (matched by\n * content hash) reuse their cached prose verbatim — no LLM call. Only new or\n * changed entries are sent to the model, batched into a single request. When\n * nothing changed, the LLM is not invoked at all.\n */\nexport async function rewriteForProduct(\n snapshot: Snapshot,\n config: MasonConfig,\n ctx: RewriteContext = {}\n): Promise<RewriteResult> {\n const featureHashes = hashEntries(snapshot.features);\n const flowHashes = hashEntries(snapshot.flows);\n\n const missFeatures = missingNames(\n snapshot.features,\n featureHashes,\n ctx.previousCache?.features\n );\n const missFlows = missingNames(\n snapshot.flows,\n flowHashes,\n ctx.previousCache?.flows\n );\n\n let parsed: Rewritten = { features: {}, flows: {} };\n if (missFeatures.length > 0 || missFlows.length > 0) {\n const input: RewriteInput = {\n features: pick(snapshot.features, missFeatures),\n flows: pick(snapshot.flows, missFlows),\n };\n const prompt = buildPrompt(input);\n const llm = ctx.llm ?? callLLM;\n const result = await llm(config, prompt, PM_REWRITE_SYSTEM_PROMPT);\n const text =\n typeof result === \"string\"\n ? result\n : result.type === \"response\"\n ? result.text\n : \"\";\n // Empty text means no API/CLI is available — leave `parsed` empty so every\n // miss falls back to its engineering description (cached as fallback).\n if (text) parsed = parseRewriteResponse(text);\n }\n\n const features = resolve(\n snapshot.features,\n featureHashes,\n parsed.features,\n ctx.previousCache?.features\n );\n const flows = resolve(\n snapshot.flows,\n flowHashes,\n parsed.flows,\n ctx.previousCache?.flows\n );\n\n return {\n features: features.descriptions,\n flows: flows.descriptions,\n cache: { features: features.cache, flows: flows.cache },\n };\n}\n\nfunction hashEntries(\n entries: Record<string, { description: string }>\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, entry] of Object.entries(entries)) {\n out[name] = hashDescription(entry.description);\n }\n return out;\n}\n\n/** A cache entry is a hit only if the source hash matches and it isn't a fallback. */\nfunction isHit(\n prev: RewriteCacheEntry | undefined,\n hash: string\n): prev is RewriteCacheEntry {\n return !!prev && prev.sourceHash === hash && !prev.fallback;\n}\n\nfunction missingNames(\n entries: Record<string, { description: string }>,\n hashes: Record<string, string>,\n prevCache: Record<string, RewriteCacheEntry> | undefined\n): string[] {\n return Object.keys(entries).filter(\n (name) => !isHit(prevCache?.[name], hashes[name])\n );\n}\n\n/**\n * Build the final prose map + next cache for one collection (features or flows):\n * reuse cached prose on a hit, take fresh model prose on a miss, or fall back to\n * the engineering description (marked `fallback`) when the model omitted it.\n */\nfunction resolve(\n entries: Record<string, { description: string }>,\n hashes: Record<string, string>,\n rewritten: Record<string, string>,\n prevCache: Record<string, RewriteCacheEntry> | undefined\n): { descriptions: Record<string, string>; cache: Record<string, RewriteCacheEntry> } {\n const descriptions: Record<string, string> = {};\n const cache: Record<string, RewriteCacheEntry> = {};\n\n for (const [name, entry] of Object.entries(entries)) {\n const hash = hashes[name];\n const prev = prevCache?.[name];\n\n if (isHit(prev, hash)) {\n descriptions[name] = prev.product;\n cache[name] = { sourceHash: hash, product: prev.product };\n continue;\n }\n\n const fresh = rewritten[name];\n if (typeof fresh === \"string\" && fresh.trim().length > 0) {\n descriptions[name] = fresh;\n cache[name] = { sourceHash: hash, product: fresh };\n } else {\n // No usable model output — keep the engineering description and mark it a\n // fallback so a later successful run re-attempts it.\n descriptions[name] = entry.description;\n cache[name] = { sourceHash: hash, product: entry.description, fallback: true };\n }\n }\n\n return { descriptions, cache };\n}\n","import { loadSnapshot } from \"../snapshot/snapshot.js\";\nimport type { MasonConfig, ConfluenceConfig } from \"../llm/config.js\";\nimport { createConfluenceClient, type ConfluenceClient } from \"./client.js\";\nimport {\n renderFeaturePage,\n renderIndexPage,\n renderChangelogPage,\n renderChangelogSection,\n flowsForFeature,\n featurePageTitle,\n} from \"./renderer.js\";\nimport {\n computeDiff,\n isMeaningfulDiff,\n loadSyncState,\n saveSyncState,\n snapshotMinimal,\n hashDescription,\n type SyncState,\n} from \"./diff.js\";\nimport {\n rewriteForProduct,\n type RewriteResult,\n type RewriteContext,\n} from \"./rewrite.js\";\nimport type { FeatureEntry, Snapshot } from \"../snapshot/snapshot.js\";\n\nexport interface SyncOptions {\n indexPageTitle?: string;\n changelogPageTitle?: string;\n featurePagePrefix?: string;\n}\n\nexport interface SyncSummary {\n created: string[];\n updated: string[];\n unchanged: string[];\n indexPageId: string;\n changelogPageId: string;\n hadChanges: boolean;\n}\n\nexport interface SyncDeps {\n client: ConfluenceClient;\n rewrite: (\n snapshot: Snapshot,\n config: MasonConfig,\n ctx: RewriteContext\n ) => Promise<RewriteResult>;\n}\n\nconst DEFAULT_INDEX_TITLE = \"Mason — System Map\";\nconst DEFAULT_CHANGELOG_TITLE = \"Mason — Changelog\";\nconst DEFAULT_FEATURE_PREFIX = \"Feature: \";\n\nexport async function exportToConfluence(\n rootDir: string,\n config: MasonConfig,\n options: SyncOptions = {},\n deps?: Partial<SyncDeps>\n): Promise<SyncSummary> {\n const confluence = config.confluence;\n if (!confluence) {\n throw new Error(\n \"No Confluence credentials configured. Ask your assistant to call mason_set_confluence first.\"\n );\n }\n\n const snapshot = await loadSnapshot(rootDir);\n if (!snapshot) {\n throw new Error(\n \"No snapshot found. Build the concept map first (ask your assistant to run mason_init and follow the playbook).\"\n );\n }\n\n const client = deps?.client ?? createConfluenceClient(confluence);\n const rewrite = deps?.rewrite ?? rewriteForProduct;\n\n // Only user-facing capabilities are published to the wiki. Infrastructure\n // features (DI wiring, config, logging, provider plumbing) stay in the AI\n // concept map but never become PM-facing pages. Filter once here; everything\n // downstream — rewrite, index, feature pages, changelog diff, persisted\n // state — operates on this published subset. Missing type defaults to\n // \"capability\" (see normalizeFeatureType), so older snapshots publish as before.\n const publishedFeatures: Record<string, FeatureEntry> = {};\n for (const [name, entry] of Object.entries(snapshot.features)) {\n if (entry.type !== \"infrastructure\") publishedFeatures[name] = entry;\n }\n const publishSnapshot: Snapshot = { ...snapshot, features: publishedFeatures };\n\n const indexTitle = options.indexPageTitle ?? DEFAULT_INDEX_TITLE;\n const changelogTitle = options.changelogPageTitle ?? DEFAULT_CHANGELOG_TITLE;\n const featurePrefix = options.featurePagePrefix ?? DEFAULT_FEATURE_PREFIX;\n\n const spaceId = await client.resolveSpaceId(confluence.spaceKey);\n // Wall-clock time is used ONLY for the append-only changelog heading. Page\n // bodies carry no timestamp/hash, so a page is re-published only when its own\n // content (description/flows) changes — not on every unrelated commit.\n const syncedAt = new Date().toISOString();\n const previousState = await loadSyncState(rootDir);\n const previousHashes = previousState?.pageHashes ?? {};\n const nextHashes: Record<string, string> = {};\n\n const productLanguage = await rewrite(publishSnapshot, config, {\n previousCache: previousState?.rewriteCache,\n });\n\n // 1. Upsert index page (so feature pages can hang under it)\n const indexBody = renderIndexPage({\n featureTitles: Object.keys(publishSnapshot.features),\n featurePrefix,\n });\n\n const indexPage = await upsertPage({\n client,\n spaceId,\n title: indexTitle,\n parentId: confluence.parentPageId,\n renderedBody: indexBody,\n previousHash: previousHashes[indexTitle],\n });\n nextHashes[indexTitle] = indexPage.hash;\n\n // 2. Upsert each feature page under the index\n const created: string[] = [];\n const updated: string[] = [];\n const unchanged: string[] = [];\n const featurePageIds: Record<string, string> = {};\n\n for (const [name, entry] of Object.entries(publishSnapshot.features)) {\n const title = featurePageTitle(featurePrefix, name);\n const productDescription =\n productLanguage.features[name] ?? entry.description;\n const relatedFlows = flowsForFeature(entry.files, publishSnapshot.flows).map(\n (f) => ({\n name: f.name,\n description: productLanguage.flows[f.name] ?? f.description,\n })\n );\n\n const rendered = renderFeaturePage({\n name,\n productDescription,\n flowDescriptions: relatedFlows,\n indexPageTitle: indexTitle,\n });\n\n const result = await upsertPage({\n client,\n spaceId,\n title,\n parentId: indexPage.id,\n renderedBody: rendered.body,\n previousHash: previousHashes[title],\n });\n nextHashes[title] = result.hash;\n\n featurePageIds[name] = result.id;\n if (result.outcome === \"created\") created.push(title);\n else if (result.outcome === \"updated\") updated.push(title);\n else unchanged.push(title);\n }\n\n // 3. Diff + changelog page\n const diff = computeDiff(previousState, publishSnapshot, syncedAt);\n const hadChanges = previousState === null || isMeaningfulDiff(diff);\n\n const previousSections = previousState?.changelogSections ?? [];\n let newSections = previousSections;\n if (hadChanges) {\n const section = renderChangelogSection(diff);\n newSections = [section, ...previousSections].slice(0, 50);\n }\n\n const changelogBody = renderChangelogPage(newSections);\n const changelogPage = await upsertPage({\n client,\n spaceId,\n title: changelogTitle,\n parentId: indexPage.id,\n renderedBody: changelogBody,\n previousHash: previousHashes[changelogTitle],\n });\n nextHashes[changelogTitle] = changelogPage.hash;\n\n // 4. Persist sync state\n const nextState: SyncState = {\n version: 2,\n syncedAt,\n pageIds: {\n index: indexPage.id,\n changelog: changelogPage.id,\n features: featurePageIds,\n },\n lastSnapshot: snapshotMinimal(publishSnapshot),\n changelogSections: newSections,\n rewriteCache: productLanguage.cache,\n pageHashes: nextHashes,\n };\n await saveSyncState(rootDir, nextState);\n\n return {\n created,\n updated,\n unchanged,\n indexPageId: indexPage.id,\n changelogPageId: changelogPage.id,\n hadChanges,\n };\n}\n\ninterface UpsertArgs {\n client: ConfluenceClient;\n spaceId: string;\n title: string;\n parentId?: string;\n renderedBody: string;\n /** Hash of the body we published for this page last sync, if any. */\n previousHash?: string;\n}\n\ninterface UpsertResult {\n id: string;\n outcome: \"created\" | \"updated\" | \"unchanged\";\n /** Hash of the body published this sync — persist for next-run comparison. */\n hash: string;\n}\n\nasync function upsertPage(args: UpsertArgs): Promise<UpsertResult> {\n const hash = hashDescription(args.renderedBody);\n const existing = await args.client.findPageByTitle(args.spaceId, args.title);\n\n if (!existing) {\n const page = await args.client.createPage({\n spaceId: args.spaceId,\n title: args.title,\n parentId: args.parentId,\n body: args.renderedBody,\n });\n return { id: page.id, outcome: \"created\", hash };\n }\n\n // Confluence re-serializes stored bodies (strips comments, re-encodes\n // entities, injects macro ids), so we can't compare against existing.body.\n // Compare our render hash to the hash we stored last sync instead. When it\n // matches, the page is already current — skip the write entirely.\n if (args.previousHash === hash) {\n return { id: existing.id, outcome: \"unchanged\", hash };\n }\n\n // Mason owns the whole page body: overwrite it wholesale.\n const updated = await args.client.updatePage({\n id: existing.id,\n title: args.title,\n parentId: args.parentId,\n body: args.renderedBody,\n version: existing.version,\n });\n return { id: updated.id, outcome: \"updated\", hash };\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport {\n analyzeProject,\n checkDrift,\n exportToConfluenceTool,\n fullAnalysis,\n generateSnapshotBatch,\n getCodeSamples,\n getContext,\n getImpact,\n getSnapshot,\n saveDecision,\n saveVerification,\n verifySnapshot,\n masonCompleteInit,\n masonInit,\n masonSetConfluence,\n reduceSnapshot,\n saveSnapshotData,\n saveSnapshotPartial,\n} from \"./tools.js\";\n\ndeclare const PKG_VERSION: string;\n\nexport function createMcpServer(): McpServer {\n const server = new McpServer(\n {\n name: \"mason\",\n version: PKG_VERSION,\n },\n {\n instructions:\n \"Mason maintains a persistent feature-to-file concept map of this codebase so you can skip manual exploration. RULE: when given a task, bug, or change request, call `get_context` with the task text first — one call returns the relevant features, files, tests, blast radius, and freshness. Before answering ANY question about features, architecture, data flows, or where something lives — and before any grep/glob/file-read exploration for such a question — call `get_snapshot` first. One call returns the whole map and replaces 5-10 search round-trips; if it has drifted it says so and self-corrects. Likewise call `get_impact` BEFORE editing or refactoring a file (git co-change history + references + related tests — signals you cannot get from reading the file itself), and `mason_check_drift` to verify the map is fresh in long sessions. When you learn something the code alone can't tell you — a failed approach, a deprecation, a workaround's reason, a review-settled convention — record it with `save_decision` so the whole team's assistants inherit it; `get_context` returns matching decisions as constraints. If `get_snapshot` reports no snapshot exists, offer to set Mason up: `mason_init` returns a setup playbook (a Map-Reduce loop of `generate_snapshot_batch` + `save_partial_snapshot`, then `reduce_snapshot` + `save_snapshot`, optionally `mason_set_confluence`, then `mason_complete_init`). `full_analysis`, `analyze_project`, and `get_code_samples` are read-only diagnostics for unmapped projects and never need init. Mason has no CLI; everything happens through these tools.\",\n }\n );\n\n server.tool(\n \"mason_init\",\n \"Start here. Checks if Mason is set up for this project. If not, returns a `playbook` of questions the assistant must walk the user through (concept map + optional Confluence sync). Once the walkthrough is done, call `mason_complete_init`. Idempotent: re-running on an already-initialized project just returns the current state.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await masonInit(dir);\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"mason_complete_init\",\n \"Mark the project as initialized. Call this after walking the user through the playbook returned by `mason_init`. Writes `.mason/project.json` so future tool calls don't re-run the wizard. Pass `confluenceConfigured: true` if Phase 3 of the playbook ended with Confluence credentials saved.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n confluenceConfigured: z\n .boolean()\n .optional()\n .default(false)\n .describe(\"True if Confluence was successfully configured during init\"),\n },\n async ({ dir, confluenceConfigured }) => {\n const result = await masonCompleteInit(dir, { confluenceConfigured });\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"mason_set_confluence\",\n \"Configure Confluence credentials. Two-step flow: (1) call without `spaceKey` to validate the credentials and receive a list of available spaces — relay them to the user. (2) call again with the same `baseUrl`/`email`/`apiToken` plus the chosen `spaceKey` to persist. Credentials are stored in `~/.mason/config.json`. Warn the user that the API token will be visible in chat history before they paste it.\",\n {\n baseUrl: z\n .string()\n .describe(\"Confluence base URL. Accepts `acme`, `acme.atlassian.net`, or `https://acme.atlassian.net` (normalized automatically).\"),\n email: z.string().describe(\"User's Atlassian account email\"),\n apiToken: z\n .string()\n .describe(\"API token from id.atlassian.com/manage-profile/security/api-tokens\"),\n spaceKey: z\n .string()\n .optional()\n .describe(\"Confluence space key. Omit on the first call to list available spaces.\"),\n parentPageId: z\n .string()\n .optional()\n .describe(\"Optional parent page ID under which Mason's index page is created\"),\n },\n async ({ baseUrl, email, apiToken, spaceKey, parentPageId }) => {\n const result = await masonSetConfluence({\n baseUrl,\n email,\n apiToken,\n spaceKey,\n parentPageId,\n });\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"full_analysis\",\n \"One-shot orientation for a project WITHOUT a concept map (get_snapshot returned exists:false). Returns git history stats, project structure with file counts, curated code sample previews (~60 lines each), and test-to-source mapping. On a mapped project, prefer get_snapshot — it is cheaper and answers feature/architecture questions directly.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await fullAnalysis(dir);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"analyze_project\",\n \"Run git history analysis on a codebase. Returns commit convention patterns, stale directories, and frequently changed files. These are aggregate stats across hundreds of commits that would be expensive to compute manually.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await analyzeProject(dir);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"get_code_samples\",\n \"Get previews (first ~60 lines) of representative source files from the codebase. Includes entry points, config files, hot files (frequently changed), test examples, and one file per directory for breadth. Read files natively for full content.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n count: z\n .number()\n .optional()\n .default(15)\n .describe(\"Maximum number of files to sample (default: 15)\"),\n },\n async ({ dir, count }) => {\n const result = await getCodeSamples(dir, count);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"get_snapshot\",\n \"CALL THIS FIRST — before grep, glob, or reading files — for any question about what this codebase does, its features, architecture, data flows, or where something is implemented ('where is X handled?', 'how does Y work?', 'what implements Z?'). Returns the persistent feature-to-file concept map in one cheap, instant, LLM-free call, replacing 5-10 exploration round-trips. Example: 'home screen' → [HomeScreen.kt, HomeViewModel.kt, HomeModule.kt]. Then read only the mapped files. If the map has drifted it says so (with a diff) — trust the freshness signal. If exists:false, the project isn't set up; offer mason_init.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await getSnapshot(dir);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"get_context\",\n \"CALL THIS FIRST when given a task to implement, a bug to fix, a ticket, or a change request ('add X', 'fix Y', 'refactor Z'). One call returns everything needed to start: the matching features/flows with their files, related tests, blast radius for the key files (git co-change + references), and per-entry freshness — replacing a get_snapshot + get_impact + test-hunting sequence. Cheap, instant, LLM-free. Pass the task in natural language; optionally pass `files` (e.g. from a diff) to anchor the match. For open-ended architecture questions with no task, use get_snapshot instead.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n task: z\n .string()\n .describe(\"The task, bug, or change request in natural language — e.g. 'add rate limiting to the API client' or a ticket description\"),\n files: z\n .array(z.string())\n .optional()\n .describe(\"Optional file paths already known to be involved (e.g. from a diff or stack trace). Entries containing them are boosted above pure text matches.\"),\n },\n async ({ dir, task, files }) => {\n const result = await getContext(dir, task, files);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"generate_snapshot_batch\",\n \"Map step of the concept-map build. Returns one batch of source files (skeletons of every file in the batch plus a few deeper-read bodies for grounding), along with a system prompt instructing you to derive features and flows for ONLY this batch. Call repeatedly with the returned `nextOffset` until it is null, calling `save_partial_snapshot` between each call. Use product-natural feature names so partials merge cleanly in the reduce step.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n offset: z\n .number()\n .int()\n .optional()\n .describe(\"0-indexed file offset to start the batch at. Omit on the first call; pass the `nextOffset` from the previous response for subsequent calls.\"),\n batchSize: z\n .number()\n .int()\n .optional()\n .describe(\"Files per batch. Defaults to 50.\"),\n files: z\n .array(z.string())\n .optional()\n .describe(\"Scope the batch walk to this explicit file list — e.g. the drift set from mason_check_drift (changedFiles + unmappedFiles). Pass the SAME list on every batch call of one refresh run. Triggers refresh mode: reduce_snapshot will merge the partials into the existing map instead of rebuilding it.\"),\n },\n async ({ dir, offset, batchSize, files }) => {\n const result = await generateSnapshotBatch(dir, offset, batchSize, files);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"save_partial_snapshot\",\n \"Persist the partial concept map you derived for one batch. Call this once per batch, with the `batchId` from the `generate_snapshot_batch` response. Partials accumulate in `.mason/partial-snapshots/` and are merged in the reduce step.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n batchId: z\n .string()\n .describe(\"The `batchId` returned by `generate_snapshot_batch`.\"),\n offset: z\n .number()\n .int()\n .describe(\"The `offset` returned by `generate_snapshot_batch`. Used to order partials in the reduce step.\"),\n features: z\n .record(\n z.object({\n description: z.string(),\n files: z.array(z.string()),\n tests: z.array(z.string()).optional(),\n type: z\n .enum([\"capability\", \"infrastructure\"])\n .optional()\n .describe(\n '\"capability\" (user-facing functionality) or \"infrastructure\" (internal plumbing with no end user — DI/service wiring, config, logging, adapters). Defaults to \"capability\".'\n ),\n })\n )\n .describe(\"Partial features for this batch only — files outside the batch will be added by other partials.\"),\n flows: z\n .record(\n z.object({\n description: z.string(),\n chain: z.array(z.string()),\n })\n )\n .describe(\"Partial flows whose entire chain is in this batch. Cross-batch flows are reconstructed in reduce.\"),\n },\n async ({ dir, batchId, offset, features, flows }) => {\n const result = await saveSnapshotPartial(dir, batchId, offset, features, flows);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"reduce_snapshot\",\n \"Reduce step of the concept-map build. Returns every partial snapshot plus a system prompt asking you to merge them into one coherent project-wide map. Resolve platform variants into single product features, dedupe near-duplicates, and ensure no file is dropped. After producing the unified map, call `save_snapshot` to persist it (this also clears the partials).\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await reduceSnapshot(dir);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"save_snapshot\",\n \"Save a concept-to-files map as a persistent project snapshot. Maps feature names and data flows to the files that implement them. Persists across conversations — future sessions can call get_snapshot to instantly find relevant files. No API key needed — you are the LLM generating the map.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n features: z\n .record(\n z.object({\n description: z.string().describe(\"One-line description of the feature\"),\n files: z.array(z.string()).describe(\"File paths that implement this feature\"),\n tests: z.array(z.string()).optional().describe(\"Test file paths for this feature\"),\n type: z\n .enum([\"capability\", \"infrastructure\"])\n .optional()\n .describe(\n 'Classification: \"capability\" for user-facing functionality, \"infrastructure\" for internal plumbing with no end user (DI/service wiring, config, logging, adapters). Capabilities are published to Confluence; infrastructure stays in the AI concept map only. Defaults to \"capability\".'\n ),\n })\n )\n .describe(\"Map of feature names to their implementing files\"),\n flows: z\n .record(\n z.object({\n description: z.string().describe(\"One-line description of the flow\"),\n chain: z.array(z.string()).describe(\"Ordered list of file paths showing data/call flow\"),\n })\n )\n .describe(\"Map of flow names to ordered file chains\"),\n removeFeatures: z\n .array(z.string())\n .optional()\n .describe(\"Feature names to delete from the existing map — for features that were renamed or no longer exist. Applied before merging; only meaningful on incremental saves.\"),\n removeFlows: z\n .array(z.string())\n .optional()\n .describe(\"Flow names to delete from the existing map. Applied before merging; only meaningful on incremental saves.\"),\n },\n async ({ dir, features, flows, removeFeatures, removeFlows }) => {\n const result = await saveSnapshotData(\n dir,\n features,\n flows,\n removeFeatures ?? [],\n removeFlows ?? []\n );\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"save_decision\",\n \"CALL THIS when you learn something about this codebase that the code alone can't tell you: a failed approach ('we tried X, it broke Y'), a deprecation ('don't extend Z'), a workaround and its reason, or a convention settled in review. Best moments: the end of a debugging session, right after a design choice. Records are git-committed to .mason/decisions/ and PR-reviewed like code; get_context surfaces them on matching tasks. Do NOT record anything derivable by reading the code, session trivia, or secrets. Also handles updates (pass id), re-verification (same id + content re-pins to HEAD), and supersession (pass supersedes).\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n title: z\n .string()\n .max(80)\n .describe(\"Short, specific headline — becomes the stable record id\"),\n body: z\n .string()\n .max(1500)\n .describe(\"The knowledge itself: what was tried/decided, why, and what to avoid. Must contain information NOT derivable by reading the code.\"),\n category: z.enum([\"decision\", \"gotcha\", \"deprecation\", \"convention\"]),\n files: z\n .array(z.string())\n .optional()\n .describe(\"Repo-relative files this applies to. Anchors drift-checking: if these change, the decision is flagged for re-verification.\"),\n id: z\n .string()\n .optional()\n .describe(\"Existing decision id to update. Passing id with unchanged content re-verifies it (re-pins refreshedHash to HEAD).\"),\n supersedes: z\n .string()\n .optional()\n .describe(\"Id of a decision this one replaces — the old record is kept but marked superseded\"),\n force: z\n .boolean()\n .optional()\n .describe(\"Save even when a near-duplicate was detected\"),\n },\n async ({ dir, title, body, category, files, id, supersedes, force }) => {\n const result = await saveDecision(dir, {\n title,\n body,\n category,\n files,\n id,\n supersedes,\n force,\n });\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"mason_check_drift\",\n \"Check how far the concept map has drifted from HEAD. Deterministic (git + filesystem, no LLM). Returns which features/flows are stale and the changed files behind them, new source files not yet mapped, ghost files (mapped but deleted), renames, and a `recommendation`: `up-to-date` (nothing to do), `incremental` (update just the stale entries via save_snapshot), or `full-rebuild` (re-run the Map-Reduce build). Call this before trusting the map in a long session, or periodically to keep the map and any synced wikis fresh.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n },\n async ({ dir }) => {\n const result = await checkDrift(dir);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"verify_snapshot\",\n \"Spot-check the concept map's CORRECTNESS (drift checks freshness; this checks entries were right to begin with). Returns a sample of entries — always the never-verified and least-recently-verified first — with skeletons of their claimed files, for you to judge whether the files actually implement what the entry claims. Report verdicts back via save_verification. Run periodically, or after an automated refresh wrote entries no human reviewed.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n sample: z\n .number()\n .int()\n .optional()\n .describe(\"Entries to sample (default 5)\"),\n },\n async ({ dir, sample }) => {\n const result = await verifySnapshot(dir, sample);\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"save_verification\",\n \"Record verify_snapshot verdicts. Entries judged ok are stamped verifiedAt; failures are flagged verificationFailed with your note and surface in mason_check_drift until re-mapped. Verdict notes are required for failures.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n verdicts: z\n .record(\n z.object({\n ok: z.boolean(),\n note: z\n .string()\n .optional()\n .describe(\"One line on what's wrong — required when ok is false\"),\n })\n )\n .describe(\"Entry name → verdict, exactly as returned by verify_snapshot\"),\n },\n async ({ dir, verdicts }) => {\n const result = await saveVerification(dir, verdicts);\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n server.tool(\n \"get_impact\",\n \"CALL THIS BEFORE editing, refactoring, or assessing the blast radius of any file. Returns three signals you cannot get by reading the file itself: git co-change history (files that historically change in the same commits), references (files that mention the target by name), and related tests. One call replaces a manual sweep of grep + git log. Also the right tool for 'what would break if I changed X?' questions.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n files: z\n .array(z.string())\n .describe(\"File paths or names to analyze (e.g., ['WeatherRepository.kt'] or ['src/services/auth.ts'])\"),\n },\n async ({ dir, files }) => {\n const result = await getImpact(dir, files);\n return {\n content: [{ type: \"text\", text: result }],\n };\n }\n );\n\n server.tool(\n \"export_to_confluence\",\n \"Sync the project's concept map to Confluence as product-readable wiki pages: an index page, one page per feature (PM-language descriptions, no file paths), and a changelog page. Hand-edits outside `<!-- mason:start/end:* -->` markers are preserved across syncs. Requires `mason_set_confluence` to have been called first.\",\n {\n dir: z\n .string()\n .describe(\"Absolute path to the project root directory\"),\n spaceKey: z\n .string()\n .optional()\n .describe(\"Override the configured space key\"),\n parentPageId: z\n .string()\n .optional()\n .describe(\"Override the configured parent page ID\"),\n indexPageTitle: z\n .string()\n .optional()\n .describe(\"Title of the index page (default: 'Mason — System Map')\"),\n changelogPageTitle: z\n .string()\n .optional()\n .describe(\"Title of the changelog page (default: 'Mason — Changelog')\"),\n featurePagePrefix: z\n .string()\n .optional()\n .describe(\"Prefix for each feature page title (default: 'Feature: ')\"),\n },\n async ({ dir, spaceKey, parentPageId, indexPageTitle, changelogPageTitle, featurePagePrefix }) => {\n const result = await exportToConfluenceTool(dir, {\n spaceKey,\n parentPageId,\n indexPageTitle,\n changelogPageTitle,\n featurePagePrefix,\n });\n return { content: [{ type: \"text\", text: result }] };\n }\n );\n\n return server;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport fg from \"fast-glob\";\n\nconst exec = promisify(execFile);\nimport { runAll } from \"../analyzers/index.js\";\nimport { isGitRepo } from \"../utils/git.js\";\nimport { sampleFiles, readFullFile } from \"./sampler.js\";\nimport {\n loadSnapshot,\n saveSnapshot,\n getCurrentGitHash,\n prepareSnapshotBatch,\n normalizeFeatureType,\n DEFAULT_BATCH_SIZE,\n type FeatureType,\n} from \"../snapshot/snapshot.js\";\nimport { computeDrift } from \"../drift/drift.js\";\nimport type { DriftReport } from \"../drift/drift.js\";\nimport {\n BATCH_SYSTEM_PROMPT,\n REDUCE_SYSTEM_PROMPT,\n REFRESH_REDUCE_SYSTEM_PROMPT,\n buildBatchPrompt,\n buildReducePrompt,\n buildRefreshReducePrompt,\n} from \"../snapshot/prompt.js\";\nimport {\n batchIdFor,\n clearAllPartials,\n clearScope,\n loadAllPartials,\n loadScope,\n savePartial,\n saveScope,\n} from \"../snapshot/partials.js\";\nimport type { Snapshot } from \"../snapshot/snapshot.js\";\nimport type { AnalyzerContext } from \"../types.js\";\nimport {\n isInitialized,\n loadProjectMarker,\n saveProjectMarker,\n setupPlaybook,\n uninitializedResponse,\n type ProjectMarker,\n} from \"./init.js\";\n\nconst IGNORE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.gradle/**\",\n \"**/target/**\",\n \"**/.git/**\",\n \"**/vendor/**\",\n \"**/__pycache__/**\",\n \"**/venv/**\",\n \"**/.venv/**\",\n \"**/*.min.*\",\n \"**/*.map\",\n];\n\nasync function buildContext(dir: string): Promise<AnalyzerContext> {\n return {\n rootDir: dir,\n gitAvailable: await isGitRepo(dir),\n };\n}\n\nexport async function analyzeProject(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n const context = await buildContext(rootDir);\n const results = await runAll(context);\n\n // Lightweight project snapshot — pure file existence checks, no parsing\n const projectSnapshot = await detectProjectSnapshot(rootDir);\n\n const output = {\n project: projectSnapshot,\n analyzers: results.map((r) => ({\n name: r.analyzer,\n durationMs: r.durationMs,\n findings: r.findings.map((f) => ({\n category: f.category,\n confidence: f.confidence,\n summary: f.summary,\n evidence: f.evidence,\n suggestedRule: f.ruleCandidate,\n })),\n gaps: r.gaps.map((g) => ({\n question: g.question,\n context: g.context,\n })),\n })),\n };\n\n return JSON.stringify(output, null, 2);\n}\n\nasync function detectProjectSnapshot(rootDir: string): Promise<Record<string, unknown>> {\n // Build config files present (what exists, not what's in them)\n const buildFiles = [\n \"package.json\", \"tsconfig.json\",\n \"build.gradle.kts\", \"build.gradle\", \"settings.gradle.kts\", \"settings.gradle\",\n \"gradle/libs.versions.toml\",\n \"Cargo.toml\", \"go.mod\", \"go.sum\",\n \"pyproject.toml\", \"setup.py\", \"requirements.txt\", \"Pipfile\",\n \"Gemfile\", \"Package.swift\",\n \"Makefile\", \"CMakeLists.txt\",\n \"Dockerfile\", \"docker-compose.yml\", \"docker-compose.yaml\",\n \".github/workflows\", \".gitlab-ci.yml\", \"Jenkinsfile\",\n ];\n\n const present: string[] = [];\n for (const file of buildFiles) {\n try {\n await fs.access(path.join(rootDir, file));\n present.push(file);\n } catch {\n // Not found\n }\n }\n\n // Test directories and file counts\n const testDirs = [\n \"test\", \"tests\", \"__tests__\", \"spec\",\n \"src/test\", \"src/tests\",\n \"**/src/test\", \"**/src/androidTest\", \"**/src/iosTest\",\n ];\n const testInfo: Record<string, number> = {};\n for (const pattern of testDirs) {\n const files = await fg(`${pattern}/**/*`, {\n cwd: rootDir,\n ignore: IGNORE,\n onlyFiles: true,\n });\n if (files.length > 0) {\n testInfo[pattern] = files.length;\n }\n }\n\n // Also count test files by naming convention\n const testFilePatterns = [\n { pattern: \"**/*.test.*\", label: \"*.test.*\" },\n { pattern: \"**/*.spec.*\", label: \"*.spec.*\" },\n { pattern: \"**/*Test.kt\", label: \"*Test.kt\" },\n { pattern: \"**/*Test.java\", label: \"*Test.java\" },\n { pattern: \"**/test_*.py\", label: \"test_*.py\" },\n { pattern: \"**/*_test.go\", label: \"*_test.go\" },\n { pattern: \"**/*Tests.swift\", label: \"*Tests.swift\" },\n { pattern: \"**/*_test.rs\", label: \"*_test.rs\" },\n ];\n for (const { pattern, label } of testFilePatterns) {\n const files = await fg(pattern, { cwd: rootDir, ignore: IGNORE });\n if (files.length > 0) {\n testInfo[label] = files.length;\n }\n }\n\n // Source file counts by extension\n const sourceFiles = await fg(\"**/*.{ts,tsx,js,jsx,kt,kts,java,py,go,rs,swift,rb,cs,cpp,c,dart}\", {\n cwd: rootDir,\n ignore: IGNORE,\n });\n const fileCounts: Record<string, number> = {};\n for (const file of sourceFiles) {\n const ext = path.extname(file).slice(1);\n fileCounts[ext] = (fileCounts[ext] ?? 0) + 1;\n }\n\n return {\n configFilesPresent: present,\n sourceFileCounts: fileCounts,\n totalSourceFiles: sourceFiles.length,\n testInfo: Object.keys(testInfo).length > 0 ? testInfo : undefined,\n };\n}\n\nexport async function getCodeSamples(\n dir: string,\n count: number = 15\n): Promise<string> {\n const rootDir = path.resolve(dir);\n const samples = await sampleFiles(rootDir, count);\n\n const output = {\n note: \"These are previews (first ~60 lines). Read the file directly with your own tools to see it in full.\",\n files: samples.map((s) => ({\n path: s.path,\n reason: s.reason,\n totalLines: s.totalLines,\n sizeBytes: s.sizeBytes,\n preview: s.preview,\n })),\n };\n\n return JSON.stringify(output, null, 2);\n}\n\nconst UNINIT_MAX_DIRECTORIES = 40;\nconst UNINIT_MAX_TEST_PAIRS = 30;\n\n/**\n * Uninitialized response for READ-path tools. A bare \"not initialized\" wastes\n * the call — the most common first contact anyone has with Mason. Return the\n * cheap deterministic context inline (structure, git signals, test pairing)\n * so the assistant can act immediately and offer setup afterwards. Write-path\n * tools keep the bare gate (uninitializedResponse).\n */\nasync function uninitializedContextResponse(\n rootDir: string,\n action: string\n): Promise<string> {\n const [structureRaw, analyzerResults, testMap] = await Promise.all([\n getProjectStructure(rootDir),\n runAll(await buildContext(rootDir)).catch(() => []),\n import(\"../test-map.js\")\n .then((m) => m.buildTestMap(rootDir))\n .catch(() => null),\n ]);\n\n const structure = JSON.parse(structureRaw);\n structure.directories = (structure.directories ?? [])\n .sort(\n (a: { fileCount: number }, b: { fileCount: number }) =>\n b.fileCount - a.fileCount\n )\n .slice(0, UNINIT_MAX_DIRECTORIES);\n\n const gitSignals = analyzerResults.flatMap((r) =>\n r.findings.map((f) => ({\n category: f.category,\n summary: f.summary,\n evidence: f.evidence.slice(0, 5),\n }))\n );\n\n return JSON.stringify({\n initialized: false,\n hint:\n `No Mason concept map exists here yet. Use the context below plus your own reads to answer now — ` +\n `then offer to set Mason up (\\`mason_init\\` walks the user through ${action}); don't start setup unprompted.`,\n structure,\n gitSignals,\n testPairs: testMap?.paired?.slice(0, UNINIT_MAX_TEST_PAIRS) ?? [],\n });\n}\n\nexport async function getProjectStructure(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n\n // Get all files\n const allFiles = await fg(\"**/*\", {\n cwd: rootDir,\n ignore: IGNORE,\n onlyFiles: true,\n });\n\n // Build directory summary with file counts and extension breakdown\n const dirInfo = new Map<\n string,\n { fileCount: number; extensions: Map<string, number> }\n >();\n\n for (const file of allFiles) {\n const parts = file.split(\"/\");\n // Track up to 2 levels deep\n for (let depth = 1; depth <= Math.min(parts.length, 2); depth++) {\n const dirPath = parts.slice(0, depth).join(\"/\");\n if (!dirInfo.has(dirPath)) {\n dirInfo.set(dirPath, { fileCount: 0, extensions: new Map() });\n }\n const info = dirInfo.get(dirPath)!;\n info.fileCount++;\n const ext = path.extname(file).slice(1);\n if (ext) {\n info.extensions.set(ext, (info.extensions.get(ext) ?? 0) + 1);\n }\n }\n }\n\n // Format directories sorted by path\n const directories = [...dirInfo.entries()]\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(([dirPath, info]) => {\n const extensions: Record<string, number> = {};\n for (const [ext, count] of info.extensions) {\n extensions[ext] = count;\n }\n return { path: dirPath, fileCount: info.fileCount, extensions };\n });\n\n // Top-level files\n const topLevelFiles = allFiles.filter((f) => !f.includes(\"/\"));\n\n const output = {\n totalFiles: allFiles.length,\n topLevelFiles,\n directories,\n };\n\n return JSON.stringify(output, null, 2);\n}\n\nexport async function getTestMap(dir: string): Promise<string> {\n const { buildTestMap } = await import(\"../test-map.js\");\n const result = await buildTestMap(dir);\n return JSON.stringify(result, null, 2);\n}\n\nconst STALE_DIFF_PREVIEW_LINES = 60;\nconst STALE_DIFF_MAX_FILES = 25;\n\nasync function buildChangedFilePreviews(\n rootDir: string,\n changedFiles: string[]\n): Promise<Array<{ path: string; totalLines: number; preview: string }>> {\n const capped = changedFiles.slice(0, STALE_DIFF_MAX_FILES);\n const previews: Array<{ path: string; totalLines: number; preview: string }> = [];\n for (const filePath of capped) {\n const full = await readFullFile(rootDir, filePath);\n if (!full) continue;\n const lines = full.content.split(\"\\n\");\n previews.push({\n path: full.path,\n totalLines: full.totalLines,\n preview: lines.slice(0, STALE_DIFF_PREVIEW_LINES).join(\"\\n\"),\n });\n }\n return previews;\n}\n\nexport async function getSnapshot(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n\n if (!(await isInitialized(rootDir))) {\n return uninitializedContextResponse(rootDir, \"building the concept map\");\n }\n\n const snapshot = await loadSnapshot(rootDir);\n\n if (!snapshot) {\n return JSON.stringify({\n exists: false,\n hint: \"Project is initialized but no concept map exists yet. Run mason_init for the setup playbook (generate_snapshot_batch → save_partial_snapshot per batch, then reduce_snapshot and save_snapshot).\",\n });\n }\n\n // Staleness is per entry, not just top-level — a partially refreshed map\n // can be pinned to HEAD while individual entries lag behind.\n const drift = await computeDrift(rootDir);\n const isStale = drift?.stale ?? false;\n\n // Return compact format: feature/flow names -> file lists only.\n // Descriptions and metadata stay in the full snapshot on disk.\n // Deduplicate files that appear in multiple features.\n const seenFiles = new Set<string>();\n const compactFeatures: Record<\n string,\n { files: string[]; tests?: string[]; type: FeatureType }\n > = {};\n for (const [name, feat] of Object.entries(snapshot.features)) {\n const unique = feat.files.filter((f) => !seenFiles.has(f));\n if (unique.length === 0) continue; // Skip fully duplicate features\n for (const f of unique) seenFiles.add(f);\n const entry: { files: string[]; tests?: string[]; type: FeatureType } = {\n files: unique,\n type: normalizeFeatureType(feat.type),\n };\n if (feat.tests && feat.tests.length > 0) {\n entry.tests = feat.tests;\n }\n compactFeatures[name] = entry;\n }\n\n const compactFlows: Record<string, string[]> = {};\n for (const [name, flow] of Object.entries(snapshot.flows)) {\n compactFlows[name] = flow.chain; // Flows keep all files (order matters)\n }\n\n const output: Record<string, unknown> = {\n exists: true,\n updatedAt: snapshot.updatedAt,\n features: compactFeatures,\n flows: compactFlows,\n stale: isStale,\n };\n\n // Compact decision index — titles only, no bodies (up to 150 × 1.5KB is\n // too heavy for the orientation call). Full text via get_context or the\n // record file itself.\n const { loadDecisions } = await import(\"../decisions/decisions.js\");\n const decisionRecords = await loadDecisions(rootDir);\n if (decisionRecords.length > 0) {\n const compactDecisions: Record<\n string,\n { title: string; category: string; files: string[] }\n > = {};\n for (const d of decisionRecords) {\n if (d.status !== \"active\") continue;\n compactDecisions[d.id] = {\n title: d.title,\n category: d.category,\n files: d.files,\n };\n }\n output.decisions = compactDecisions;\n output.decisionsHint =\n \"Recorded team knowledge — get_context returns matching full bodies; records live at .mason/decisions/<id>.json.\";\n }\n\n if (isStale && drift) {\n output.hint = driftHint(drift);\n if (drift.historyAvailable && drift.changedFiles.length > 0) {\n const samples = await buildChangedFilePreviews(\n rootDir,\n drift.changedFiles\n );\n output.diff = {\n changedFiles: drift.changedFiles,\n samples,\n truncated: drift.changedFiles.length > STALE_DIFF_MAX_FILES,\n };\n output.drift = {\n staleFeatures: drift.staleFeatures,\n staleFlows: drift.staleFlows,\n unmappedFiles: drift.unmappedFiles,\n ghostFiles: drift.ghostFiles,\n renames: drift.renames,\n recommendation: drift.recommendation,\n };\n }\n }\n\n return JSON.stringify(output);\n}\n\nfunction driftHint(report: DriftReport): string {\n if (!report.stale) {\n return \"Snapshot matches HEAD. No action needed.\";\n }\n if (!report.historyAvailable) {\n return \"Snapshot is stale but its commit is unreachable (shallow clone or rewritten history), so per-feature drift cannot be computed. Re-run the Map-Reduce build: generate_snapshot_batch → save_partial_snapshot → reduce_snapshot → save_snapshot.\";\n }\n if (report.recommendation === \"full-rebuild\") {\n return \"Drift is too large for an incremental update. Re-run the Map-Reduce build: generate_snapshot_batch → save_partial_snapshot → reduce_snapshot → save_snapshot.\";\n }\n if (report.changedFiles.length + report.unmappedFiles.length > STALE_DIFF_MAX_FILES) {\n return \"Many files drifted — use a scoped refresh instead of reading them all inline: call generate_snapshot_batch(dir, files=[...changedFiles, ...unmappedFiles]) repeatedly (same list every call) with save_partial_snapshot per batch, then reduce_snapshot and save_snapshot. Entries untouched by the drift are preserved in the reduce step.\";\n }\n const nothingToRemap =\n Object.keys(report.staleFeatures).length === 0 &&\n Object.keys(report.staleFlows).length === 0 &&\n report.unmappedFiles.length === 0 &&\n report.ghostFiles.length === 0;\n if (nothingToRemap) {\n return \"Changes since the snapshot don't touch any mapped files. Call save_snapshot with empty features/flows to re-pin the snapshot to HEAD.\";\n }\n return \"Read the changed files under staleFeatures/staleFlows, update those entries (fold unmappedFiles into the right features), and call save_snapshot with only the affected entries — unchanged entries are preserved. Drop ghostFiles from any entries that reference them, and delete features/flows that no longer exist via save_snapshot's removeFeatures/removeFlows.\";\n}\n\nexport async function checkDrift(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n\n if (!(await isInitialized(rootDir))) {\n return uninitializedResponse(\"checking concept-map drift\");\n }\n\n const report = await computeDrift(rootDir);\n if (!report) {\n return JSON.stringify({\n exists: false,\n hint: \"No concept map exists yet. Build one first: generate_snapshot_batch → save_partial_snapshot → reduce_snapshot → save_snapshot.\",\n });\n }\n\n // Additive: correctness state alongside freshness state. Drift proves the\n // map is current; verification proves it was right to begin with.\n const snapshot = await loadSnapshot(rootDir);\n let verification: Record<string, unknown> | undefined;\n let hint = driftHint(report);\n if (snapshot) {\n const all = [\n ...Object.values(snapshot.features),\n ...Object.values(snapshot.flows),\n ];\n const failedNames = [\n ...Object.entries(snapshot.features)\n .filter(([, e]) => e.verificationFailed)\n .map(([n]) => n),\n ...Object.entries(snapshot.flows)\n .filter(([, e]) => e.verificationFailed)\n .map(([n]) => n),\n ];\n verification = {\n neverVerified: all.filter((e) => !e.verifiedAt).length,\n failed: failedNames,\n };\n if (failedNames.length > 0) {\n hint += ` Verification previously FAILED for [${failedNames.join(\", \")}] — re-map those entries before trusting them.`;\n }\n }\n\n return JSON.stringify({ exists: true, ...report, verification, hint });\n}\n\nexport async function generateSnapshotBatch(\n dir: string,\n offset: number = 0,\n batchSize: number = DEFAULT_BATCH_SIZE,\n files?: string[]\n): Promise<string> {\n const rootDir = path.resolve(dir);\n const scoped = files !== undefined && files.length > 0;\n const scopeFiles = scoped ? sanitizePaths(rootDir, files) : undefined;\n const batch = await prepareSnapshotBatch(dir, offset, batchSize, scopeFiles);\n\n if (scoped && batch.totalFiles > 0) {\n // Mark this partial run as a scoped refresh so reduce_snapshot merges\n // into the existing map instead of rebuilding it from partials alone.\n await saveScope(rootDir, scopeFiles!);\n } else if (!scoped) {\n // A full build must never inherit a scope marker left behind by an\n // abandoned refresh run — its reduce step would wrongly merge instead\n // of rebuilding.\n await clearScope(rootDir);\n }\n\n const task = scoped\n ? \"Refresh the concept map for a scoped set of drifted files (batch step).\"\n : \"Build a concept-to-files map for this project (batch step).\";\n\n if (batch.totalFiles === 0) {\n return JSON.stringify(\n {\n task,\n offset: 0,\n nextOffset: null,\n totalFiles: 0,\n batchId: batchIdFor(0),\n instructions: BATCH_SYSTEM_PROMPT,\n prompt: scoped\n ? \"(None of the requested files exist as source files in this project.)\"\n : \"(No source files found to map.)\",\n next: scoped\n ? \"None of the requested files matched project source files. Check the paths passed in `files` — they must be repo-relative.\"\n : \"No source files were found. Skip the rest of the playbook and call mason_complete_init.\",\n },\n null,\n 2\n );\n }\n\n const batchId = batchIdFor(batch.offset);\n const continueCall = scoped\n ? `generate_snapshot_batch(dir, offset=${batch.nextOffset}, files=<the same list>)`\n : `generate_snapshot_batch(dir, offset=${batch.nextOffset})`;\n\n return JSON.stringify(\n {\n task,\n offset: batch.offset,\n nextOffset: batch.nextOffset,\n totalFiles: batch.totalFiles,\n batchId,\n batchSize: batch.batchSize,\n filesInBatch: batch.skeletons.length,\n scoped,\n instructions: BATCH_SYSTEM_PROMPT,\n prompt: buildBatchPrompt(batch),\n next:\n batch.nextOffset === null\n ? `Derive partial features/flows for this batch and call save_partial_snapshot(dir, batchId=\"${batchId}\", features, flows). This is the last batch — after saving, proceed to reduce_snapshot.`\n : `Derive partial features/flows for this batch and call save_partial_snapshot(dir, batchId=\"${batchId}\", features, flows). Then call ${continueCall} to continue.`,\n },\n null,\n 2\n );\n}\n\nexport async function saveSnapshotPartial(\n dir: string,\n batchId: string,\n offset: number,\n features: Record<\n string,\n { description: string; files: string[]; tests?: string[]; type?: FeatureType }\n >,\n flows: Record<string, { description: string; chain: string[] }>\n): Promise<string> {\n const rootDir = path.resolve(dir);\n\n // Sanitize all file paths to prevent path traversal in stored partials, and\n // normalize the capability/infrastructure classification so it survives reduce.\n for (const feat of Object.values(features)) {\n feat.files = sanitizePaths(rootDir, feat.files);\n if (feat.tests) feat.tests = sanitizePaths(rootDir, feat.tests);\n feat.type = normalizeFeatureType(feat.type);\n }\n for (const flow of Object.values(flows)) {\n flow.chain = sanitizePaths(rootDir, flow.chain);\n }\n\n await savePartial(rootDir, {\n batchId,\n offset,\n features,\n flows,\n savedAt: new Date().toISOString(),\n });\n\n const all = await loadAllPartials(rootDir);\n return JSON.stringify(\n {\n status: \"stored\",\n batchId,\n partialsStored: all.length,\n hint:\n \"Partial saved. Continue with the next generate_snapshot_batch call, or proceed to reduce_snapshot when nextOffset is null.\",\n },\n null,\n 2\n );\n}\n\nexport async function reduceSnapshot(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n const partials = await loadAllPartials(rootDir);\n\n if (partials.length === 0) {\n return JSON.stringify(\n {\n status: \"error\",\n error:\n \"No partial snapshots found. Run generate_snapshot_batch and save_partial_snapshot at least once before calling reduce_snapshot.\",\n },\n null,\n 2\n );\n }\n\n // A scope marker means these partials re-analyzed only a drifted subset —\n // merge them into the existing map instead of rebuilding from scratch.\n const scope = await loadScope(rootDir);\n const existing =\n scope && scope.length > 0 ? await loadSnapshot(rootDir) : null;\n\n if (scope && existing) {\n // Strip bookkeeping fields — the assistant shouldn't echo them back.\n const cleanFeatures = Object.fromEntries(\n Object.entries(existing.features).map(([name, feat]) => [\n name,\n {\n description: feat.description,\n files: feat.files,\n ...(feat.tests && feat.tests.length > 0 ? { tests: feat.tests } : {}),\n },\n ])\n );\n const cleanFlows = Object.fromEntries(\n Object.entries(existing.flows).map(([name, flow]) => [\n name,\n { description: flow.description, chain: flow.chain },\n ])\n );\n\n return JSON.stringify(\n {\n task: \"Merge a scoped refresh into the existing concept map.\",\n partialsCount: partials.length,\n refreshedFiles: scope.length,\n instructions: REFRESH_REDUCE_SYSTEM_PROMPT,\n prompt: buildRefreshReducePrompt(\n { features: cleanFeatures, flows: cleanFlows },\n scope,\n partials\n ),\n next: \"Follow `instructions` to produce the COMPLETE updated features/flows (entries untouched by the refresh copied through unchanged), then call save_snapshot(dir, features, flows). Partials and the scope marker are cleaned up automatically after save_snapshot succeeds.\",\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(\n {\n task: \"Merge partial concept maps into one unified map.\",\n partialsCount: partials.length,\n instructions: REDUCE_SYSTEM_PROMPT,\n prompt: buildReducePrompt(partials),\n next: \"Follow `instructions` to produce the unified features/flows, then call save_snapshot(dir, features, flows). Partial files will be cleaned up automatically after save_snapshot succeeds. Finish with mason_complete_init(dir).\",\n },\n null,\n 2\n );\n}\n\nexport async function fullAnalysis(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n\n const [analysis, structure, samples, testMap, snapshot] = await Promise.all([\n analyzeProject(dir),\n getProjectStructure(dir),\n getCodeSamples(dir, 25),\n getTestMap(dir),\n loadSnapshot(rootDir),\n ]);\n\n const output: Record<string, unknown> = {\n note: \"Full project analysis. Code samples are previews (~60 lines). Read files directly with your own tools to see them in full.\",\n analysis: JSON.parse(analysis),\n structure: JSON.parse(structure),\n codeSamples: JSON.parse(samples),\n testMap: JSON.parse(testMap),\n };\n\n if (snapshot) {\n output.conceptMap = {\n updatedAt: snapshot.updatedAt,\n features: snapshot.features,\n flows: snapshot.flows,\n };\n output.note =\n \"Full project analysis with concept map. The concept map shows which files implement each feature and how data flows through them. Use it to jump straight to relevant files instead of exploring, then read them directly with your own tools.\";\n }\n\n return JSON.stringify(output, null, 2);\n}\n\nfunction sanitizePaths(\n rootDir: string,\n files: string[]\n): string[] {\n return files.filter((f) => {\n const resolved = path.resolve(rootDir, f);\n return resolved.startsWith(rootDir) && !f.startsWith(\"/\") && !f.includes(\"..\");\n });\n}\n\nexport async function saveSnapshotData(\n dir: string,\n features: Record<\n string,\n {\n description: string;\n files: string[];\n tests?: string[];\n refreshedHash?: string;\n type?: FeatureType;\n }\n >,\n flows: Record<\n string,\n { description: string; chain: string[]; refreshedHash?: string }\n >,\n removeFeatures: string[] = [],\n removeFlows: string[] = []\n): Promise<string> {\n const rootDir = path.resolve(dir);\n const gitHash = await getCurrentGitHash(rootDir);\n const now = new Date().toISOString();\n\n // Sanitize all file paths to prevent path traversal, and normalize the\n // capability/infrastructure classification (defaults to \"capability\").\n for (const feat of Object.values(features)) {\n feat.files = sanitizePaths(rootDir, feat.files);\n if (feat.tests) feat.tests = sanitizePaths(rootDir, feat.tests);\n feat.type = normalizeFeatureType(feat.type);\n }\n for (const flow of Object.values(flows)) {\n flow.chain = sanitizePaths(rootDir, flow.chain);\n }\n\n // If partials exist we're consolidating a Map-Reduce run: replace the\n // snapshot wholesale. Merging here would pollute the unified map with any\n // earlier (possibly hallucinated) call to save_snapshot. Outside of\n // Map-Reduce — incremental refresh of one feature — fall back to merge.\n const partials = await loadAllPartials(rootDir);\n const replaceMode = partials.length > 0;\n const existing = replaceMode ? null : await loadSnapshot(rootDir);\n\n if (existing) {\n // Entries not re-sent in this call are only verified as of the previous\n // hash — record that before the top-level gitHash moves to HEAD, so\n // drift detection can still see which entries were skipped.\n if (existing.gitHash !== \"unknown\") {\n for (const feat of Object.values(existing.features)) {\n feat.refreshedHash ??= existing.gitHash;\n }\n for (const flow of Object.values(existing.flows)) {\n flow.refreshedHash ??= existing.gitHash;\n }\n }\n\n const removedFeatures = removeFeatures.filter(\n (name) => name in existing.features\n );\n const removedFlows = removeFlows.filter((name) => name in existing.flows);\n for (const name of removedFeatures) delete existing.features[name];\n for (const name of removedFlows) delete existing.flows[name];\n\n if (gitHash !== \"unknown\") {\n for (const feat of Object.values(features)) feat.refreshedHash = gitHash;\n for (const flow of Object.values(flows)) flow.refreshedHash = gitHash;\n }\n\n existing.features = { ...existing.features, ...features };\n existing.flows = { ...existing.flows, ...flows };\n existing.updatedAt = now;\n existing.gitHash = gitHash;\n await saveSnapshot(rootDir, existing);\n await clearAllPartials(rootDir);\n return JSON.stringify({\n status: \"updated\",\n mode: \"merged\",\n features: Object.keys(existing.features).length,\n flows: Object.keys(existing.flows).length,\n removedFeatures: removedFeatures.length,\n removedFlows: removedFlows.length,\n });\n }\n\n const snapshot: Snapshot = {\n version: 2,\n createdAt: now,\n updatedAt: now,\n gitHash,\n features,\n flows,\n };\n\n await saveSnapshot(rootDir, snapshot);\n await clearAllPartials(rootDir);\n return JSON.stringify({\n status: replaceMode ? \"replaced\" : \"created\",\n mode: replaceMode ? \"replaced-from-partials\" : \"fresh\",\n features: Object.keys(features).length,\n flows: Object.keys(flows).length,\n });\n}\n\nexport async function configureProject(\n dir: string,\n config: {\n patterns?: string[];\n alwaysInclude?: string[];\n ignore?: string[];\n }\n): Promise<string> {\n const rootDir = path.resolve(dir);\n const configDir = path.join(rootDir, \".mason\");\n const configPath = path.join(configDir, \"config.json\");\n\n // Load existing config and merge\n let existing: Record<string, unknown> = {};\n try {\n const raw = await fs.readFile(configPath, \"utf-8\");\n existing = JSON.parse(raw);\n } catch {\n // No existing config\n }\n\n if (config.patterns) existing.patterns = config.patterns;\n if (config.alwaysInclude) existing.alwaysInclude = config.alwaysInclude;\n if (config.ignore) existing.ignore = config.ignore;\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(existing, null, 2), \"utf-8\");\n\n return JSON.stringify({\n status: \"saved\",\n path: configPath,\n config: existing,\n });\n}\n\nexport async function getImpact(\n dir: string,\n files: string[]\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedContextResponse(rootDir, \"analyzing change impact\");\n }\n const { analyzeImpact } = await import(\"../impact/impact.js\");\n const result = await analyzeImpact(rootDir, files);\n return JSON.stringify(result, null, 2);\n}\n\nconst VERIFY_DEFAULT_SAMPLE = 5;\nconst VERIFY_MAX_FILES_PER_ENTRY = 8;\nconst VERIFY_SKELETON_CHARS = 500;\n\n/**\n * Verification closes the day-one hole drift can't: drift proves the map is\n * current against git, but nothing proves an entry was CORRECT when written.\n * Sample entries weighted toward never-verified, then oldest-verified.\n */\nexport async function verifySnapshot(\n dir: string,\n sample: number = VERIFY_DEFAULT_SAMPLE\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedResponse(\"verifying the concept map\");\n }\n const snapshot = await loadSnapshot(rootDir);\n if (!snapshot) {\n return JSON.stringify({\n exists: false,\n hint: \"No concept map exists yet — nothing to verify.\",\n });\n }\n\n const entries = [\n ...Object.entries(snapshot.features).map(([name, e]) => ({\n name,\n kind: \"feature\" as const,\n description: e.description,\n files: e.files,\n verifiedAt: e.verifiedAt,\n })),\n ...Object.entries(snapshot.flows).map(([name, e]) => ({\n name,\n kind: \"flow\" as const,\n description: e.description,\n files: e.chain,\n verifiedAt: e.verifiedAt,\n })),\n ];\n\n entries.sort((a, b) => {\n if (!a.verifiedAt && !b.verifiedAt) return a.name.localeCompare(b.name);\n if (!a.verifiedAt) return -1;\n if (!b.verifiedAt) return 1;\n return a.verifiedAt.localeCompare(b.verifiedAt);\n });\n\n const picked = entries.slice(0, Math.max(1, sample));\n const toVerify = [];\n for (const entry of picked) {\n const skeletons: Array<{ path: string; content: string } | { path: string; missing: true }> = [];\n for (const filePath of entry.files.slice(0, VERIFY_MAX_FILES_PER_ENTRY)) {\n const full = await readFullFile(rootDir, filePath);\n if (full) {\n skeletons.push({\n path: full.path,\n content: full.content.slice(0, VERIFY_SKELETON_CHARS),\n });\n } else {\n skeletons.push({ path: filePath, missing: true });\n }\n }\n toVerify.push({\n name: entry.name,\n kind: entry.kind,\n description: entry.description,\n lastVerified: entry.verifiedAt ?? \"never\",\n skeletons,\n truncated: entry.files.length > VERIFY_MAX_FILES_PER_ENTRY,\n });\n }\n\n const neverVerified = entries.filter((e) => !e.verifiedAt).length;\n\n return JSON.stringify({\n exists: true,\n totalEntries: entries.length,\n neverVerified,\n entries: toVerify,\n instructions:\n \"For each entry, judge from the skeletons whether the listed files actually implement the claimed feature/flow (missing files count against it). Then call save_verification with verdicts: {\\\"<entry name>\\\": {\\\"ok\\\": true|false, \\\"note\\\": \\\"<one line, required when ok is false>\\\"}}. Be skeptical — a plausible description is not evidence; the files must show it.\",\n });\n}\n\nexport async function saveVerification(\n dir: string,\n verdicts: Record<string, { ok: boolean; note?: string }>\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedResponse(\"saving verification verdicts\");\n }\n const snapshot = await loadSnapshot(rootDir);\n if (!snapshot) {\n return JSON.stringify({ exists: false, hint: \"No concept map exists.\" });\n }\n\n const now = new Date().toISOString();\n const stamped: string[] = [];\n const unknown: string[] = [];\n const failed: string[] = [];\n\n for (const [name, verdict] of Object.entries(verdicts)) {\n const entry = snapshot.features[name] ?? snapshot.flows[name];\n if (!entry) {\n unknown.push(name);\n continue;\n }\n entry.verifiedAt = now;\n if (verdict.ok) {\n delete entry.verificationFailed;\n delete entry.verificationNote;\n } else {\n entry.verificationFailed = true;\n entry.verificationNote = verdict.note ?? \"verification failed\";\n failed.push(name);\n }\n stamped.push(name);\n }\n\n snapshot.updatedAt = now;\n await saveSnapshot(rootDir, snapshot);\n\n return JSON.stringify({\n stamped,\n unknown,\n failed,\n hint:\n failed.length > 0\n ? `Entries [${failed.join(\", \")}] are mis-mapped. Re-map them: read their actual files, correct the entries, and call save_snapshot with only those entries (plus removeFeatures/removeFlows if a concept no longer exists).`\n : \"All sampled entries verified. Re-run verify_snapshot periodically — it always picks the least-recently-verified entries next.\",\n });\n}\n\nexport async function saveDecision(\n dir: string,\n input: {\n title: string;\n body: string;\n category: \"decision\" | \"gotcha\" | \"deprecation\" | \"convention\";\n files?: string[];\n id?: string;\n supersedes?: string;\n force?: boolean;\n }\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedResponse(\"recording team decisions\");\n }\n const { upsertDecision } = await import(\"../decisions/decisions.js\");\n const result = await upsertDecision(rootDir, input);\n return JSON.stringify(result);\n}\n\nexport async function getContext(\n dir: string,\n task: string,\n files?: string[]\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedContextResponse(rootDir, \"assembling task context\");\n }\n const { assembleContext } = await import(\"../context/assemble.js\");\n const bundle = await assembleContext(rootDir, task, files);\n if (!bundle) {\n return JSON.stringify({\n exists: false,\n hint: \"No concept map exists yet. Build one first: generate_snapshot_batch → save_partial_snapshot → reduce_snapshot → save_snapshot.\",\n });\n }\n return JSON.stringify(bundle);\n}\n\n// ===== Init MCP tools =====\n\nexport async function masonInit(dir: string): Promise<string> {\n const rootDir = path.resolve(dir);\n const marker = await loadProjectMarker(rootDir);\n\n if (marker) {\n return JSON.stringify(\n {\n initialized: true,\n initializedAt: marker.initializedAt,\n confluenceConfigured: marker.features?.confluence === true,\n hint:\n \"This project is already set up for Mason. To refresh the concept map, call generate_snapshot_batch. To (re)configure Confluence, call mason_set_confluence directly.\",\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(\n {\n initialized: false,\n playbook: setupPlaybook(),\n },\n null,\n 2\n );\n}\n\nexport async function masonCompleteInit(\n dir: string,\n options: { confluenceConfigured?: boolean } = {}\n): Promise<string> {\n const rootDir = path.resolve(dir);\n const marker: ProjectMarker = {\n version: 1,\n initializedAt: new Date().toISOString(),\n features: {\n confluence: options.confluenceConfigured ?? false,\n },\n };\n await saveProjectMarker(rootDir, marker);\n return JSON.stringify(\n {\n status: \"initialized\",\n marker,\n hint: \"Setup complete. Future calls to other Mason tools will work normally.\",\n },\n null,\n 2\n );\n}\n\n// ===== Confluence MCP tools =====\n\nexport async function masonSetConfluence(input: {\n baseUrl: string;\n email: string;\n apiToken: string;\n spaceKey?: string;\n parentPageId?: string;\n}): Promise<string> {\n const { createConfluenceClient } = await import(\"../confluence/client.js\");\n const { saveConfluenceConfig } = await import(\"../llm/config.js\");\n const { normalizeAtlassianBaseUrl } = await import(\"../confluence/url.js\");\n\n let baseUrl: string;\n try {\n baseUrl = normalizeAtlassianBaseUrl(input.baseUrl);\n } catch (err) {\n return JSON.stringify({\n status: \"error\",\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n if (!input.email.includes(\"@\")) {\n return JSON.stringify({\n status: \"error\",\n error: `Email looks invalid: \"${input.email}\".`,\n });\n }\n if (!input.apiToken.trim()) {\n return JSON.stringify({\n status: \"error\",\n error: \"API token is required.\",\n });\n }\n\n const probeConfig = {\n baseUrl,\n email: input.email,\n apiToken: input.apiToken,\n spaceKey: input.spaceKey ?? \"\",\n parentPageId: input.parentPageId,\n };\n const client = createConfluenceClient(probeConfig);\n\n let spaces;\n try {\n spaces = await client.listSpaces();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes(\"401\") || msg.includes(\"403\")) {\n return JSON.stringify({\n status: \"error\",\n error:\n \"Credentials rejected by Confluence. Re-check the email and that the API token hasn't expired or been revoked.\",\n });\n }\n return JSON.stringify({\n status: \"error\",\n error: `Confluence validation failed: ${msg}`,\n });\n }\n\n if (!input.spaceKey) {\n // Step 1 — return spaces for the assistant to relay to the user.\n return JSON.stringify(\n {\n status: \"spaces_listed\",\n baseUrl,\n spaces: spaces.map((s) => ({ key: s.key, name: s.name })),\n hint:\n spaces.length === 0\n ? \"Authenticated, but no spaces are visible to this account. Create one in Confluence first, then re-run mason_set_confluence.\"\n : \"Ask the user which space to use, then call mason_set_confluence again with the same baseUrl/email/apiToken plus the chosen spaceKey.\",\n },\n null,\n 2\n );\n }\n\n const match = spaces.find((s) => s.key === input.spaceKey);\n if (!match) {\n return JSON.stringify({\n status: \"error\",\n error: `Space key \"${input.spaceKey}\" was not found among the spaces visible to this account. Available keys: ${spaces.map((s) => s.key).join(\", \") || \"(none)\"}.`,\n });\n }\n\n await saveConfluenceConfig({\n baseUrl,\n email: input.email,\n apiToken: input.apiToken,\n spaceKey: input.spaceKey,\n parentPageId: input.parentPageId,\n });\n\n return JSON.stringify(\n {\n status: \"saved\",\n spaceKey: input.spaceKey,\n spaceName: match.name,\n hint:\n \"Confluence is configured. The credentials are stored in ~/.mason/config.json. Call export_to_confluence to sync the concept map.\",\n },\n null,\n 2\n );\n}\n\nexport async function exportToConfluenceTool(\n dir: string,\n overrides?: {\n spaceKey?: string;\n parentPageId?: string;\n indexPageTitle?: string;\n changelogPageTitle?: string;\n featurePagePrefix?: string;\n }\n): Promise<string> {\n const rootDir = path.resolve(dir);\n if (!(await isInitialized(rootDir))) {\n return uninitializedResponse(\"syncing to Confluence\");\n }\n\n const { loadConfig } = await import(\"../llm/config.js\");\n const { exportToConfluence } = await import(\"../confluence/sync.js\");\n\n const config = await loadConfig();\n if (!config?.confluence) {\n return JSON.stringify({\n status: \"error\",\n error:\n 'No Confluence credentials configured. Call mason_set_confluence first (or re-run mason_init and walk through the Confluence section).',\n });\n }\n\n const merged = {\n ...config,\n confluence: {\n ...config.confluence,\n spaceKey: overrides?.spaceKey ?? config.confluence.spaceKey,\n parentPageId: overrides?.parentPageId ?? config.confluence.parentPageId,\n },\n };\n\n try {\n const summary = await exportToConfluence(rootDir, merged, {\n indexPageTitle: overrides?.indexPageTitle,\n changelogPageTitle: overrides?.changelogPageTitle,\n featurePagePrefix: overrides?.featurePagePrefix,\n });\n return JSON.stringify({ status: \"ok\", ...summary }, null, 2);\n } catch (err) {\n return JSON.stringify({\n status: \"error\",\n error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { BaseAnalyzer } from \"./base.js\";\nimport type { AnalyzerContext, AnalyzerResult, Finding, Gap } from \"../types.js\";\n\nconst exec = promisify(execFile);\n\nexport class GitHistoryAnalyzer extends BaseAnalyzer {\n name = \"git-history\";\n\n async analyze(context: AnalyzerContext): Promise<AnalyzerResult> {\n const startTime = Date.now();\n const findings: Finding[] = [];\n const gaps: Gap[] = [];\n\n if (!context.gitAvailable) {\n return this.createResult([], [], startTime);\n }\n\n const [staleFindings, staleGaps] = await this.findStaleDirectories(context);\n findings.push(...staleFindings);\n gaps.push(...staleGaps);\n\n const hotFindings = await this.findHotFiles(context);\n findings.push(...hotFindings);\n\n const commitFindings = await this.analyzeCommitPatterns(context);\n findings.push(...commitFindings);\n\n return this.createResult(findings, gaps, startTime);\n }\n\n private async git(\n args: string[],\n cwd: string\n ): Promise<string> {\n try {\n const { stdout } = await exec(\"git\", args, { cwd, maxBuffer: 10_000_000 });\n return stdout.trim();\n } catch {\n return \"\";\n }\n }\n\n private async findStaleDirectories(\n context: AnalyzerContext\n ): Promise<[Finding[], Gap[]]> {\n const findings: Finding[] = [];\n const gaps: Gap[] = [];\n\n // Get top-level directories with their last commit date\n const output = await this.git(\n [\"log\", \"--all\", \"--format=%ci\", \"--name-only\", \"--diff-filter=AMCR\", \"-n\", \"500\"],\n context.rootDir\n );\n\n if (!output) return [findings, gaps];\n\n const dirLastTouch = new Map<string, Date>();\n let currentDate: Date | null = null;\n\n for (const line of output.split(\"\\n\")) {\n if (!line) continue;\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(line)) {\n currentDate = new Date(line);\n } else if (currentDate) {\n const topDir = line.split(\"/\")[0];\n if (\n topDir &&\n !topDir.startsWith(\".\") &&\n !topDir.includes(\"node_modules\")\n ) {\n const existing = dirLastTouch.get(topDir);\n if (!existing || currentDate > existing) {\n dirLastTouch.set(topDir, currentDate);\n }\n }\n }\n }\n\n const sixMonthsAgo = new Date();\n sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);\n\n for (const [dir, lastTouch] of dirLastTouch) {\n if (lastTouch < sixMonthsAgo) {\n const monthsStale = Math.floor(\n (Date.now() - lastTouch.getTime()) / (1000 * 60 * 60 * 24 * 30)\n );\n findings.push(\n this.createFinding({\n category: \"risk\",\n confidence: 0.7,\n summary: `Directory \"${dir}\" hasn't been modified in ${monthsStale} months`,\n evidence: [\n { filePath: dir, detail: `Last commit: ${lastTouch.toISOString().split(\"T\")[0]}` },\n ],\n ruleCandidate: `Do not refactor or modify files in \"${dir}/\" unless explicitly asked — this area has been stable for ${monthsStale} months and may be legacy code.`,\n })\n );\n gaps.push({\n analyzer: this.name,\n question: `Directory \"${dir}\" hasn't been touched in ${monthsStale} months. Is it deprecated, stable, or legacy?`,\n context: `Last modified: ${lastTouch.toISOString().split(\"T\")[0]}`,\n answerKey: `stale-dir-${dir}`,\n });\n }\n }\n\n return [findings, gaps];\n }\n\n private async findHotFiles(context: AnalyzerContext): Promise<Finding[]> {\n const findings: Finding[] = [];\n\n // Most frequently changed files in the last 3 months\n const output = await this.git(\n [\"log\", \"--since=3 months ago\", \"--format=\", \"--name-only\"],\n context.rootDir\n );\n\n if (!output) return findings;\n\n const fileCounts = new Map<string, number>();\n for (const line of output.split(\"\\n\")) {\n if (!line || line.startsWith(\".\") || line.includes(\"node_modules\")) continue;\n fileCounts.set(line, (fileCounts.get(line) ?? 0) + 1);\n }\n\n const sorted = [...fileCounts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10);\n\n if (sorted.length > 0 && sorted[0][1] >= 5) {\n const hotFiles = sorted.filter(([, count]) => count >= 5);\n if (hotFiles.length > 0) {\n findings.push(\n this.createFinding({\n category: \"risk\",\n confidence: 0.8,\n summary: `${hotFiles.length} files changed frequently in the last 3 months`,\n evidence: hotFiles.map(([file, count]) => ({\n filePath: file,\n detail: `${count} commits`,\n })),\n ruleCandidate: `These files change frequently and are high-risk for conflicts: ${hotFiles.map(([f]) => f).join(\", \")}. Take extra care when modifying them.`,\n })\n );\n }\n }\n\n return findings;\n }\n\n private async analyzeCommitPatterns(\n context: AnalyzerContext\n ): Promise<Finding[]> {\n const findings: Finding[] = [];\n\n const output = await this.git(\n [\"log\", \"--format=%s\", \"-n\", \"100\"],\n context.rootDir\n );\n\n if (!output) return findings;\n\n const messages = output.split(\"\\n\").filter(Boolean);\n\n // Check for conventional commits\n const conventionalPattern = /^(feat|fix|chore|docs|style|refactor|test|perf|ci|build|revert)(\\(.+\\))?:/;\n const conventionalCount = messages.filter((m) =>\n conventionalPattern.test(m)\n ).length;\n const conventionalRatio = conventionalCount / messages.length;\n\n if (conventionalRatio > 0.5) {\n findings.push(\n this.createFinding({\n category: \"convention\",\n confidence: Math.min(conventionalRatio + 0.1, 1),\n summary: `${Math.round(conventionalRatio * 100)}% of recent commits use conventional commit format`,\n evidence: [\n {\n filePath: \".git\",\n detail: `${conventionalCount} of ${messages.length} commits match`,\n },\n ],\n ruleCandidate:\n \"Use conventional commit format: type(scope): description (e.g., feat(auth): add login endpoint)\",\n })\n );\n }\n\n // Check for ticket/issue references\n const ticketPattern = /[A-Z]+-\\d+|#\\d+/;\n const ticketCount = messages.filter((m) => ticketPattern.test(m)).length;\n const ticketRatio = ticketCount / messages.length;\n\n if (ticketRatio > 0.3) {\n findings.push(\n this.createFinding({\n category: \"convention\",\n confidence: ticketRatio,\n summary: `${Math.round(ticketRatio * 100)}% of commits reference issue/ticket IDs`,\n evidence: [\n {\n filePath: \".git\",\n detail: `${ticketCount} of ${messages.length} commits have ticket refs`,\n },\n ],\n ruleCandidate:\n \"Include issue/ticket references in commit messages when applicable.\",\n })\n );\n }\n\n return findings;\n }\n}\n","import fs from \"node:fs/promises\";\nimport fg from \"fast-glob\";\nimport type {\n AnalyzerContext,\n AnalyzerResult,\n Finding,\n FindingCategory,\n} from \"../types.js\";\n\nexport abstract class BaseAnalyzer {\n abstract name: string;\n abstract analyze(context: AnalyzerContext): Promise<AnalyzerResult>;\n\n protected async findFiles(\n patterns: string[],\n root: string\n ): Promise<string[]> {\n return fg(patterns, {\n cwd: root,\n ignore: [\"**/node_modules/**\", \"**/dist/**\", \"**/.git/**\"],\n absolute: true,\n });\n }\n\n protected async readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, \"utf-8\");\n }\n\n protected createFinding(partial: {\n category: FindingCategory;\n confidence: number;\n summary: string;\n evidence?: Finding[\"evidence\"];\n ruleCandidate?: string | null;\n }): Finding {\n return {\n analyzer: this.name,\n category: partial.category,\n confidence: partial.confidence,\n summary: partial.summary,\n evidence: partial.evidence ?? [],\n ruleCandidate: partial.ruleCandidate ?? null,\n };\n }\n\n protected createResult(\n findings: Finding[],\n gaps: AnalyzerResult[\"gaps\"],\n startTime: number\n ): AnalyzerResult {\n return {\n analyzer: this.name,\n findings,\n gaps,\n durationMs: Date.now() - startTime,\n };\n }\n}\n","import type { AnalyzerContext, AnalyzerResult } from \"../types.js\";\nimport type { BaseAnalyzer } from \"./base.js\";\nimport { GitHistoryAnalyzer } from \"./git-history.js\";\n\nconst analyzers: BaseAnalyzer[] = [new GitHistoryAnalyzer()];\n\nexport async function runAll(\n context: AnalyzerContext\n): Promise<AnalyzerResult[]> {\n return Promise.all(analyzers.map((a) => a.analyze(context)));\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst exec = promisify(execFile);\n\nexport async function isGitRepo(dir: string): Promise<boolean> {\n try {\n await exec(\"git\", [\"rev-parse\", \"--git-dir\"], { cwd: dir });\n return true;\n } catch {\n return false;\n }\n}\n","export const BATCH_SYSTEM_PROMPT = `You are Mason, building one piece of a larger concept-to-files map via a Map-Reduce pattern.\n\nYou are seeing ONE batch of files from this project — not the whole codebase. Other batches will be processed separately and merged with yours in a final reduce step.\n\nYour job for this batch: identify the features and flows that involve the files in this batch, and return a partial concept map.\n\nRespond with ONLY a JSON object. No markdown, no explanation, no code fences. Just the raw JSON. Same shape as the full map (\\`{\"features\": {...}, \"flows\": {...}}\\`).\n\nCRITICAL: name features in PRODUCT-NATURAL language (e.g., \"home screen\", \"authentication\", \"checkout\"). Do NOT add platform or layer suffixes — call both the Android and iOS home-screen files part of a feature named \"home screen\". This is what lets the reduce step merge platform variants from other batches into a single product feature.\n\nOther rules:\n- Only include files that you see in this batch. Don't predict files in other batches.\n- Use the FULL relative file paths exactly as given.\n- Classify each feature with a \"type\": \"capability\" (user-facing functionality) or \"infrastructure\" (internal plumbing with no end user — DI/service wiring, configuration, logging, adapters, build tooling). When unsure, use \"capability\".\n- Each feature should have 1–8 files from this batch — partials can be narrow.\n- Flows in a partial only make sense if all their chain steps are in this batch. Skip flows that span batches; the reduce step will assemble them.\n- Include test files in \"tests\" when present in this batch.\n- Two views of the batch: FILE HEADERS (every file in the batch, skeleton-level) and REPRESENTATIVE BODIES (deeper read of a few for grounding). Use the bodies to learn the codebase's domain vocabulary; use the headers to know which files exist.`;\n\nexport const REDUCE_SYSTEM_PROMPT = `You are Mason, merging partial concept maps from a Map-Reduce pass into a single unified map.\n\nYou will receive an array of \\`partials\\`, each produced from one batch of files. Your job: merge them into one coherent concept-to-files map for the whole project.\n\nRespond with ONLY a JSON object: \\`{\"features\": {...}, \"flows\": {...}}\\`. No markdown, no preamble.\n\nMerge rules:\n- If two partials use the same feature name (e.g., both have \"home screen\"), MERGE them — combine their \\`files\\` and \\`tests\\` arrays (dedupe), and reconcile descriptions by picking the more product-natural wording or merging the two.\n- If two partials use *near-duplicate* feature names that clearly refer to the same product concept (\"home screen\" vs \"home view\", \"auth\" vs \"authentication\"), merge them under the more product-natural name.\n- If a partial split what should be one feature by platform (\"home Android\" + \"home iOS\"), merge into a single platform-agnostic feature (\"home screen\").\n- Preserve each feature's \"type\" (\"capability\" or \"infrastructure\"). When merged partials disagree on a feature's type, prefer \"capability\". If a partial omitted the type, infer it: user-facing functionality is \"capability\"; internal plumbing with no end user (DI/service wiring, config, logging, adapters) is \"infrastructure\".\n- For flows that were skipped by partials because they span batches, reconstruct them when you can see the full chain across multiple partials.\n- Every file that appears in any partial MUST end up in some feature in the unified map. Don't silently drop files.\n- Feature descriptions in the final map should be 1–2 sentences, written for a product/PM audience — concrete and specific, but free of code-level detail.\n- Each feature should have 2–8 files. If merging produces a feature with 20+ files, consider whether it should be split into sub-features.`;\n\nexport function buildBatchPrompt(\n batch: {\n offset: number;\n batchSize: number;\n nextOffset: number | null;\n totalFiles: number;\n skeletons: Array<{ path: string; content: string }>;\n samples: Array<{ path: string; content: string }>;\n testPairs?: Array<{ test: string; source: string; confidence: string }>;\n }\n): string {\n const skeletonBlocks = batch.skeletons\n .map(\n (f) =>\n `--- ${f.path} ---\\n${f.content}${f.content.length >= 500 ? \"\\n... (truncated)\" : \"\"}`\n )\n .join(\"\\n\\n\");\n\n const sampleBlocks = batch.samples\n .map(\n (f) =>\n `=== ${f.path} (deeper read) ===\\n${f.content}${f.content.length >= 1500 ? \"\\n... (truncated)\" : \"\"}`\n )\n .join(\"\\n\\n\");\n\n const batchInfo = `Batch ${Math.floor(batch.offset / batch.batchSize) + 1}: files ${batch.offset + 1}–${batch.offset + batch.skeletons.length} of ${batch.totalFiles}.`;\n\n let prompt = `${batchInfo}\n\n=== FILE HEADERS (every file in this batch) ===\n\n${skeletonBlocks}\n\n=== REPRESENTATIVE BODIES (for grounding) ===\n\n${sampleBlocks}`;\n\n if (batch.testPairs && batch.testPairs.length > 0) {\n const testBlock = batch.testPairs\n .map((p) => `${p.test} → ${p.source}`)\n .join(\"\\n\");\n prompt += `\\n\\n=== TEST → SOURCE MAPPINGS (for this batch) ===\\n\\n${testBlock}`;\n }\n\n return prompt;\n}\n\nexport function buildReducePrompt(\n partials: Array<{\n batchId: string;\n offset: number;\n features: Record<string, { description: string; files: string[]; tests?: string[] }>;\n flows: Record<string, { description: string; chain: string[] }>;\n }>\n): string {\n return `Merge the following ${partials.length} partial concept maps into a single unified map.\n\n${JSON.stringify({ partials }, null, 2)}`;\n}\n\nexport const REFRESH_REDUCE_SYSTEM_PROMPT = `You are Mason, merging a scoped refresh into an existing concept-to-files map.\n\nOnly a subset of the project's files was re-analyzed (they changed since the map was built). You receive the existing full map, the list of re-analyzed file paths, and partial concept maps derived from ONLY those files.\n\nRespond with ONLY a JSON object: \\`{\"features\": {...}, \"flows\": {...}}\\` — the COMPLETE updated map. No markdown, no preamble.\n\nMerge rules:\n- Entries in the existing map that reference none of the re-analyzed files: copy them through UNCHANGED.\n- Entries that reference re-analyzed files: update them using the partials — adjust descriptions, add new files, drop files that moved elsewhere.\n- Merge partial features into existing features when they're the same product concept, even if named slightly differently (\"auth\" vs \"authentication\") — keep the existing name unless the new one is clearly more product-natural.\n- Features whose files were all deleted or renamed away: remove them by omitting them from your output.\n- Every file that appears in any partial MUST end up in some feature. Don't silently drop files.\n- Do not invent or alter entries for files you haven't seen.`;\n\nexport function buildRefreshReducePrompt(\n existingMap: {\n features: Record<string, { description: string; files: string[]; tests?: string[] }>;\n flows: Record<string, { description: string; chain: string[] }>;\n },\n refreshedFiles: string[],\n partials: Array<{\n batchId: string;\n offset: number;\n features: Record<string, { description: string; files: string[]; tests?: string[] }>;\n flows: Record<string, { description: string; chain: string[] }>;\n }>\n): string {\n return `Merge this scoped refresh into the existing concept map.\n\n=== EXISTING MAP ===\n${JSON.stringify(existingMap, null, 2)}\n\n=== RE-ANALYZED FILES ===\n${refreshedFiles.join(\"\\n\")}\n\n=== PARTIALS (derived from the re-analyzed files only) ===\n${JSON.stringify({ partials }, null, 2)}`;\n}\n\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { FeatureEntry, FlowEntry } from \"./snapshot.js\";\n\nexport interface Partial {\n batchId: string;\n offset: number;\n features: Record<string, FeatureEntry>;\n flows: Record<string, FlowEntry>;\n savedAt: string;\n}\n\nfunction partialsDir(rootDir: string): string {\n return path.join(rootDir, \".mason\", \"partial-snapshots\");\n}\n\nfunction partialPath(rootDir: string, batchId: string): string {\n return path.join(partialsDir(rootDir), `${batchId}.json`);\n}\n\nfunction isSafeBatchId(batchId: string): boolean {\n // batchIds are server-issued; defensively reject anything that could escape\n return /^[a-zA-Z0-9_-]+$/.test(batchId);\n}\n\nexport async function savePartial(\n rootDir: string,\n partial: Partial\n): Promise<void> {\n if (!isSafeBatchId(partial.batchId)) {\n throw new Error(`Invalid batchId: ${partial.batchId}`);\n }\n await fs.mkdir(partialsDir(rootDir), { recursive: true });\n await fs.writeFile(\n partialPath(rootDir, partial.batchId),\n JSON.stringify(partial, null, 2),\n \"utf-8\"\n );\n}\n\nexport async function loadAllPartials(rootDir: string): Promise<Partial[]> {\n let entries: string[];\n try {\n entries = await fs.readdir(partialsDir(rootDir));\n } catch {\n return [];\n }\n\n const partials: Partial[] = [];\n for (const entry of entries) {\n if (!entry.endsWith(\".json\")) continue;\n try {\n const raw = await fs.readFile(\n path.join(partialsDir(rootDir), entry),\n \"utf-8\"\n );\n const parsed = JSON.parse(raw) as Partial;\n if (parsed && parsed.batchId && parsed.features && parsed.flows) {\n partials.push(parsed);\n }\n } catch {\n // Skip unreadable / malformed partials\n }\n }\n\n partials.sort((a, b) => a.offset - b.offset);\n return partials;\n}\n\n// A scope marker records that the current partials come from a scoped\n// refresh (drift repair) rather than a full Map-Reduce build. It lives in the\n// partials directory so clearAllPartials removes it with the partials;\n// loadAllPartials skips it because it has no batchId/features/flows.\nfunction scopePath(rootDir: string): string {\n return path.join(partialsDir(rootDir), \"scope.json\");\n}\n\nexport async function saveScope(\n rootDir: string,\n files: string[]\n): Promise<void> {\n await fs.mkdir(partialsDir(rootDir), { recursive: true });\n await fs.writeFile(\n scopePath(rootDir),\n JSON.stringify({ files, savedAt: new Date().toISOString() }, null, 2),\n \"utf-8\"\n );\n}\n\nexport async function loadScope(rootDir: string): Promise<string[] | null> {\n try {\n const raw = await fs.readFile(scopePath(rootDir), \"utf-8\");\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed?.files)) return parsed.files;\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function clearScope(rootDir: string): Promise<void> {\n await fs.rm(scopePath(rootDir), { force: true });\n}\n\nexport async function clearAllPartials(rootDir: string): Promise<void> {\n try {\n await fs.rm(partialsDir(rootDir), { recursive: true, force: true });\n } catch {\n // No partials to clear — fine\n }\n}\n\nexport function batchIdFor(offset: number): string {\n return `batch-${String(offset).padStart(6, \"0\")}`;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport interface ProjectMarker {\n version: 1;\n initializedAt: string;\n features?: {\n confluence?: boolean;\n };\n}\n\nfunction masonDir(rootDir: string): string {\n return path.join(rootDir, \".mason\");\n}\n\nfunction markerPath(rootDir: string): string {\n return path.join(masonDir(rootDir), \"project.json\");\n}\n\nexport async function loadProjectMarker(\n rootDir: string\n): Promise<ProjectMarker | null> {\n try {\n const raw = await fs.readFile(markerPath(rootDir), \"utf-8\");\n const parsed = JSON.parse(raw);\n if (parsed.version !== 1) return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nexport async function saveProjectMarker(\n rootDir: string,\n marker: ProjectMarker\n): Promise<void> {\n await fs.mkdir(masonDir(rootDir), { recursive: true });\n await fs.writeFile(\n markerPath(rootDir),\n JSON.stringify(marker, null, 2),\n \"utf-8\"\n );\n}\n\nexport async function isInitialized(rootDir: string): Promise<boolean> {\n const marker = await loadProjectMarker(rootDir);\n return marker !== null;\n}\n\nexport function uninitializedResponse(action: string): string {\n return JSON.stringify(\n {\n initialized: false,\n hint: `This project hasn't been set up for Mason yet. Call \\`mason_init\\` first; it will walk the user through ${action}.`,\n },\n null,\n 2\n );\n}\n\n/**\n * The section the setup playbook offers to add to the project's CLAUDE.md.\n * This is Mason's salience channel: benchmark runs showed assistants ignore\n * MCP tool descriptions in favor of grep muscle memory, but reliably follow\n * project instructions. Marker-delimited so a future init can update it.\n */\nexport const CLAUDE_MD_SECTION = `<!-- mason:start -->\n## Mason concept map\n\nThis project has a Mason concept map (\\`.mason/snapshot.json\\`) and decision store (\\`.mason/decisions/\\`) served over MCP. Use them BEFORE grep, glob, or file reads:\n\n- Task, bug, or change request → \\`get_context\\` with the task text: relevant features, files, tests, blast radius, freshness, and decisions in one call.\n- \"How does X work / where is Y\" → \\`get_snapshot\\` first.\n- Before editing any file → \\`get_impact\\`.\n- Learned something the code can't tell you (a failed approach, a deprecation, a workaround's reason, a review-settled convention) → record it with \\`save_decision\\`. Never record code-derivable facts, session trivia, or secrets.\n- Decisions returned by \\`get_context\\` are constraints — follow them; verify any marked stale before relying on it.\n\nFall back to manual exploration only for what the map doesn't answer.\n<!-- mason:end -->`;\n\nconst SETUP_PLAYBOOK = `You are walking the user through one-time Mason setup for this project. \\\nMason persists a concept map of this codebase so future questions don't re-explore from scratch. \\\nThe map is built via a Map-Reduce pattern so it covers the WHOLE codebase, not just a sample. \\\nSurface each question to the user in plain language and wait for their answer before proceeding.\n\nCONSENT\nTell the user: \"Mason will read your codebase in batches and build a concept map at .mason/snapshot.json. This can take a while — Mason makes several tool calls in sequence. Proceed?\"\nOn no: stop. Mason setup is opt-in.\nOn yes: continue with the phases below.\n\nPHASE 1 — Map (loop until done)\nGoal: process every file in the codebase, batch by batch, producing a partial concept map per batch.\n\n 1. Call \\`generate_snapshot_batch(dir)\\` (omit offset on the first call).\n The response includes:\n - \\`batchId\\`: identifier for this batch\n - \\`offset\\`, \\`nextOffset\\`, \\`totalFiles\\`: progress markers\n - \\`instructions\\`: the system prompt for the batch step\n - \\`prompt\\`: the files in this batch (skeletons + a few deeper bodies)\n 2. Following the \\`instructions\\`, derive features and flows that involve ONLY the files in this batch. Use product-natural feature names (\"home screen\", not \"HomeScreenAndroid\") so the reduce step can merge platform variants.\n 3. Call \\`save_partial_snapshot(dir, batchId, offset, features, flows)\\` to persist the partial.\n 4. If \\`nextOffset\\` is null, the Map phase is done. Otherwise call \\`generate_snapshot_batch(dir, offset=nextOffset)\\` and repeat from step 2.\n\n Briefly tell the user \"Batch N of M done\" each iteration so they see progress.\n\n CRITICAL RULES FOR PHASE 1:\n - Derive features and file paths ONLY from what appears verbatim in the \\`prompt\\` field of each batch response. NEVER invent paths from memory, prior projects, or what you assume a project of this kind would contain. If you have not seen a path in a batch \\`prompt\\`, do not put it in \\`features.files\\` or \\`flows.chain\\`.\n - Process batches SEQUENTIALLY: one \\`generate_snapshot_batch\\` → derive → one \\`save_partial_snapshot\\` → next \\`generate_snapshot_batch\\`. Do not parallelise. Do not call \\`save_snapshot\\` during this phase — that is a Phase 2 step.\n - You must walk every batch until \\`nextOffset\\` is null. Do not stop early. Do not skip ahead to reduce until every batch has been saved as a partial.\n\nPHASE 2 — Reduce (once)\nGoal: merge all partial maps into one coherent product-shaped catalog.\n\n 1. Call \\`reduce_snapshot(dir)\\`. It returns every partial map plus reconciliation instructions.\n 2. Follow the instructions to produce a unified \\`features\\` and \\`flows\\` map. Specifically: merge platform variants (\"home Android\" + \"home iOS\" → \"home screen\"), dedupe near-duplicates, reconcile descriptions, and ensure every file from every partial appears somewhere in the final map.\n 3. Call \\`save_snapshot(dir, features, flows)\\` ONCE with the unified map. Mason detects that partials exist and replaces the snapshot wholesale (rather than merging with any earlier state) and then clears the partials. Do not call \\`save_snapshot\\` more than once per Map-Reduce run.\n\nPHASE 3 — Confluence sync (optional)\nGoal: optionally configure Confluence so the concept map can be exported as a product-readable wiki later.\n\nTell the user: \"Mason can keep a Confluence wiki in sync with the concept map, rewriting it into product-readable language for PMs and designers. Want to set that up now? You can also skip and configure it later by asking your assistant to 'set up Confluence for this project'.\"\nOn no: skip to Phase 4.\nOn yes:\n 1. Ask the user for the Atlassian site URL (e.g. \\`acme.atlassian.net\\` or \\`https://acme.atlassian.net\\`).\n 2. Ask for the user's Atlassian account email.\n 3. Tell the user: \"Generate an API token at https://id.atlassian.com/manage-profile/security/api-tokens (label it 'Mason') and paste it here. WARNING: the token will be visible in this chat history; if that's not acceptable, skip Confluence and configure it elsewhere.\"\n 4. Call \\`mason_set_confluence({ baseUrl, email, apiToken })\\` — no spaceKey on the first call. The tool validates credentials and returns a list of spaces.\n 5. Show the spaces to the user (key + name) and ask which one to use.\n 6. Call \\`mason_set_confluence({ baseUrl, email, apiToken, spaceKey })\\` with the chosen spaceKey to persist.\n 7. Confirm Confluence is configured. Mention they can run \\`export_to_confluence\\` whenever they want to sync.\n\nIf the credentials are rejected with a 401/403 the tool returns a friendly error — re-ask the user for a fresh token or correct email.\n\nPHASE 4 — Assistant instructions (recommended)\nGoal: make sure future assistant sessions actually use the map instead of re-exploring.\n\nTell the user: \"Assistants reliably follow project instruction files but often ignore available tools. Mason works best if I add a short section to this project's instruction file telling assistants to consult the concept map first. Add it?\"\nOn no: skip to Phase 5.\nOn yes, pick the target file by what the project already uses:\n - \\`AGENTS.md\\` exists → put the section there (it's the tool-agnostic standard). If a \\`CLAUDE.md\\` also exists and doesn't reference AGENTS.md, add a one-line pointer to it.\n - only \\`CLAUDE.md\\` (or \\`.claude/CLAUDE.md\\`) exists → put the section there.\n - neither exists → create \\`CLAUDE.md\\` with just the section.\nAppend the following section verbatim; if the \\`<!-- mason:start -->\\` marker is already present in the target file, replace the marked block instead of appending:\n\n${CLAUDE_MD_SECTION}\n\nPHASE 5 — Finalize\n 1. Call \\`mason_complete_init(dir, { confluenceConfigured: true | false })\\` — true if Phase 3 ended with status \"saved\", false otherwise.\n 2. Confirm to the user that setup is complete and they can now ask architectural questions, request impact analysis, or sync to Confluence (if configured).\n\nNotes:\n- Read tools (\\`get_snapshot\\`, \\`get_impact\\`) refuse to run until \\`mason_complete_init\\` has been called. Do not skip Phase 5.\n- If the user aborts mid-flow, the partials persist in \\`.mason/partial-snapshots/\\`; the next \\`mason_init\\` run can pick up where it left off.\n- \\`mason_init\\` is idempotent — already-initialized projects return \\`{ initialized: true, confluenceConfigured: ... }\\`.\n- The user can reconfigure Confluence later by asking their assistant to call \\`mason_set_confluence\\` directly.`;\n\nexport function setupPlaybook(): string {\n return SETUP_PLAYBOOK;\n}\n","import { startMcpServer } from \"../src/mcp/server.js\";\n\nstartMcpServer().catch((err) => {\n process.stderr.write(`Mason MCP server error: ${err}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","execFile","promisify","fg","exec","path","fg","fs","path","execFile","promisify","fg","exec","fs","path","execFile","promisify","exec","path","fs","path","record","id","fs","path","execFile","promisify","fg","IGNORE","exec","SOURCE_EXTENSIONS","path","init_drift","path","stale","init_drift","path","fs","path","execFile","promisify","exec","fs","path","createHash","execFile","promisify","resolve","exec","fs","path","execFile","promisify","fg","execFile","promisify","exec","fs","path","fs","path","exec","promisify","execFile","IGNORE","path","fs","fg","buildTestMap","loadDecisions","path","analyzeImpact","upsertDecision","assembleContext","createConfluenceClient","saveConfluenceConfig","normalizeAtlassianBaseUrl","loadConfig","exportToConfluence"]}