@ez-corp/ez-context 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as writeWithMarkers, i as MARKER_START, n as emit, o as extractConventions, r as MARKER_END, s as createBridge, t as FORMAT_EMITTER_MAP } from "./emitters-6MMh0yUj.js";
2
+ import { a as writeWithMarkers, i as MARKER_START, n as emit, o as extractConventions, r as MARKER_END, s as createBridge, t as FORMAT_EMITTER_MAP } from "./emitters-DOtul0uF.js";
3
3
  import { copyFile, readFile, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { existsSync } from "node:fs";
@@ -579,7 +579,7 @@ async function updateAction(pathArg, options) {
579
579
 
580
580
  //#endregion
581
581
  //#region package.json
582
- var version = "0.1.8";
582
+ var version = "0.1.9";
583
583
 
584
584
  //#endregion
585
585
  //#region src/cli.ts
@@ -1055,11 +1055,7 @@ var EzSearchBridgeImpl = class {
1055
1055
  await index(projectPath);
1056
1056
  }
1057
1057
  async refreshIndex(projectPath) {
1058
- try {
1059
- await index(projectPath);
1060
- } catch {
1061
- await index(projectPath, { clear: true });
1062
- }
1058
+ await index(projectPath);
1063
1059
  }
1064
1060
  async search(searchQuery, options = {}) {
1065
1061
  const { k = 10 } = options;
@@ -1853,4 +1849,4 @@ async function emit(registry, options) {
1853
1849
 
1854
1850
  //#endregion
1855
1851
  export { EvidenceRefSchema as _, writeWithMarkers as a, ALWAYS_SKIP as c, addConvention as d, createRegistry as f, ConventionRegistrySchema as g, ConventionEntrySchema as h, MARKER_START as i, listProjectFiles as l, ConventionCategorySchema as m, emit as n, extractConventions as o, ArchitectureInfoSchema as p, MARKER_END as r, createBridge as s, FORMAT_EMITTER_MAP as t, runExtractors as u, StackInfoSchema as v };
1856
- //# sourceMappingURL=emitters-6MMh0yUj.js.map
1852
+ //# sourceMappingURL=emitters-DOtul0uF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitters-DOtul0uF.js","names":["EVIDENCE","parseToml","yamlLoad","prepData"],"sources":["../src/core/schema.ts","../src/core/registry.ts","../src/extractors/index.ts","../src/extractors/static/package-json.ts","../src/extractors/static/lockfile.ts","../src/extractors/static/tsconfig.ts","../src/extractors/static/go-mod.ts","../src/extractors/static/cargo-toml.ts","../src/extractors/static/ci.ts","../src/utils/fs.ts","../src/extractors/static/project-structure.ts","../src/extractors/code/naming.ts","../src/extractors/code/imports.ts","../src/extractors/code/error-handling.ts","../src/core/ez-search-bridge.ts","../src/extractors/semantic/error-handling.ts","../src/extractors/semantic/architecture.ts","../src/core/pipeline.ts","../src/emitters/writer.ts","../src/emitters/render-helpers.ts","../src/emitters/claude-md.ts","../src/emitters/agents-md.ts","../src/emitters/cursor-mdc.ts","../src/emitters/copilot-md.ts","../src/emitters/skill-md.ts","../src/emitters/rulesync-md.ts","../src/emitters/ruler-md.ts","../src/emitters/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Atomic schemas\n// ---------------------------------------------------------------------------\n\nexport const ConventionCategorySchema = z.enum([\n \"stack\",\n \"naming\",\n \"architecture\",\n \"error_handling\",\n \"testing\",\n \"imports\",\n \"other\",\n]);\n\nexport const EvidenceRefSchema = z.object({\n file: z.string(),\n line: z.number().int().positive().nullable(),\n});\n\nexport const ConventionEntrySchema = z.object({\n id: z.uuid(),\n category: ConventionCategorySchema,\n pattern: z.string().min(1),\n confidence: z.number().min(0).max(1),\n evidence: z.array(EvidenceRefSchema),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const StackInfoSchema = z.object({\n language: z.string(),\n framework: z.string().optional(),\n testRunner: z.string().optional(),\n buildTool: z.string().optional(),\n packageManager: z.string().optional(),\n nodeVersion: z.string().optional(),\n});\n\nexport const ArchitectureInfoSchema = z.object({\n pattern: z.string().optional(),\n layers: z.array(z.string()),\n entryPoints: z.array(z.string()).optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Root registry schema\n// ---------------------------------------------------------------------------\n\nexport const ConventionRegistrySchema = z.object({\n version: z.literal(\"1\"),\n projectPath: z.string(),\n generatedAt: z.string().datetime(),\n stack: StackInfoSchema,\n conventions: z.array(ConventionEntrySchema),\n architecture: ArchitectureInfoSchema,\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Inferred types (no manual interfaces)\n// ---------------------------------------------------------------------------\n\nexport type ConventionCategory = z.infer<typeof ConventionCategorySchema>;\nexport type EvidenceRef = z.infer<typeof EvidenceRefSchema>;\nexport type ConventionEntry = z.infer<typeof ConventionEntrySchema>;\nexport type StackInfo = z.infer<typeof StackInfoSchema>;\nexport type ArchitectureInfo = z.infer<typeof ArchitectureInfoSchema>;\nexport type ConventionRegistry = z.infer<typeof ConventionRegistrySchema>;\n","import {\n type ConventionEntry,\n type ConventionRegistry,\n ConventionRegistrySchema,\n} from \"./schema.js\";\n\n/**\n * Create a new empty ConventionRegistry for the given project path.\n * The returned registry passes ConventionRegistrySchema validation.\n */\nexport function createRegistry(projectPath: string): ConventionRegistry {\n const registry: ConventionRegistry = {\n version: \"1\",\n projectPath,\n generatedAt: new Date().toISOString(),\n stack: {\n language: \"unknown\",\n },\n conventions: [],\n architecture: {\n layers: [],\n },\n };\n\n const result = ConventionRegistrySchema.safeParse(registry);\n if (!result.success) {\n throw new Error(\n `createRegistry produced invalid registry: ${JSON.stringify(result.error.issues)}`\n );\n }\n\n return result.data;\n}\n\n/**\n * Add a convention entry to the registry, auto-generating a UUID for the id.\n * Returns a new registry (does not mutate the input).\n */\nexport function addConvention(\n registry: ConventionRegistry,\n entry: Omit<ConventionEntry, \"id\">\n): ConventionRegistry {\n const newEntry: ConventionEntry = {\n id: crypto.randomUUID(),\n ...entry,\n };\n\n const updated: ConventionRegistry = {\n ...registry,\n conventions: [...registry.conventions, newEntry],\n };\n\n const result = ConventionRegistrySchema.safeParse(updated);\n if (!result.success) {\n throw new Error(\n `addConvention produced invalid registry: ${JSON.stringify(result.error.issues)}`\n );\n }\n\n return result.data;\n}\n","import { addConvention } from \"../core/registry.js\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"./types.js\";\n\n/**\n * Run all extractors in parallel via Promise.allSettled so that a single\n * failing extractor does not abort the others.\n *\n * Fulfilled entries are added to the registry immutably via `addConvention`.\n * Rejected extractors emit a console.warn and are skipped.\n */\nexport async function runExtractors(\n extractors: Extractor[],\n ctx: ExtractionContext,\n registry: ConventionRegistry\n): Promise<ConventionRegistry> {\n const results = await Promise.allSettled(\n extractors.map((e) => e.extract(ctx).then((entries) => ({ extractor: e, entries })))\n );\n\n let current = registry;\n\n for (const [i, result] of results.entries()) {\n if (result.status === \"fulfilled\") {\n for (const entry of result.value.entries) {\n current = addConvention(current, entry);\n }\n } else {\n console.warn(\n `[runExtractors] Extractor \"${extractors[i]!.name}\" failed:`,\n result.reason\n );\n }\n }\n\n return current;\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Detection maps\n// ---------------------------------------------------------------------------\n\nconst FRAMEWORK_MAP: Record<string, string> = {\n react: \"React\",\n vue: \"Vue\",\n \"@angular/core\": \"Angular\",\n next: \"Next.js\",\n nuxt: \"Nuxt\",\n svelte: \"Svelte\",\n hono: \"Hono\",\n express: \"Express\",\n fastify: \"Fastify\",\n koa: \"Koa\",\n};\n\nconst TEST_RUNNER_MAP: Record<string, string> = {\n vitest: \"Vitest\",\n jest: \"Jest\",\n mocha: \"Mocha\",\n jasmine: \"Jasmine\",\n ava: \"Ava\",\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ntype PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n type?: string;\n packageManager?: string;\n};\n\nfunction allDeps(pkg: PackageJson): Record<string, string> {\n return { ...pkg.dependencies, ...pkg.devDependencies };\n}\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nconst EVIDENCE = [{ file: \"package.json\", line: null }];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const packageJsonExtractor: Extractor = {\n name: \"package-json\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"package.json\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let pkg: PackageJson;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n pkg = JSON.parse(raw) as PackageJson;\n } catch {\n return [];\n }\n\n const deps = allDeps(pkg);\n const entries: Entry[] = [];\n\n // --- Language detection ---\n const isTypeScript =\n \"typescript\" in deps || \"@types/node\" in deps;\n const language = isTypeScript ? \"TypeScript\" : \"JavaScript\";\n entries.push({\n category: \"stack\",\n pattern: `Language: ${language}`,\n confidence: 0.95,\n evidence: EVIDENCE,\n metadata: { language },\n });\n\n // --- Framework detection ---\n for (const [pkg_name, label] of Object.entries(FRAMEWORK_MAP)) {\n if (pkg_name in deps) {\n const version = deps[pkg_name];\n entries.push({\n category: \"stack\",\n pattern: `Framework: ${label}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { framework: label, version },\n });\n break; // first match wins\n }\n }\n\n // --- Test runner detection ---\n for (const [pkg_name, label] of Object.entries(TEST_RUNNER_MAP)) {\n if (pkg_name in deps) {\n entries.push({\n category: \"testing\",\n pattern: `Test runner: ${label}`,\n confidence: 0.95,\n evidence: EVIDENCE,\n metadata: { testRunner: label },\n });\n break; // first match wins\n }\n }\n\n // --- Package manager detection (corepack \"packageManager\" field) ---\n if (typeof pkg.packageManager === \"string\") {\n const pmName = pkg.packageManager.split(\"@\")[0];\n if (pmName) {\n entries.push({\n category: \"stack\",\n pattern: `Package manager: ${pmName}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { packageManager: pmName },\n });\n }\n }\n\n // --- ESM module system detection ---\n if (pkg.type === \"module\") {\n entries.push({\n category: \"imports\",\n pattern: `ES modules (package.json \"type\": \"module\")`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { moduleSystem: \"esm\" },\n });\n }\n\n // --- Scripts ---\n const scripts = pkg.scripts ?? {};\n for (const [scriptName, command] of Object.entries(scripts)) {\n const isTestScript =\n scriptName === \"test\" || scriptName.startsWith(\"test:\");\n const isBuildOrLint =\n scriptName === \"build\" || scriptName === \"lint\";\n\n if (isTestScript || isBuildOrLint) {\n entries.push({\n category: isTestScript ? \"testing\" : \"stack\",\n pattern: `Script \"${scriptName}\": ${command}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { scriptName, command },\n });\n }\n }\n\n return entries;\n },\n};\n","import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Lockfile → package manager mapping (priority order)\n// ---------------------------------------------------------------------------\n\nconst LOCKFILES: Array<{ file: string; manager: string }> = [\n { file: \"bun.lock\", manager: \"bun\" },\n { file: \"bun.lockb\", manager: \"bun\" },\n { file: \"pnpm-lock.yaml\", manager: \"pnpm\" },\n { file: \"yarn.lock\", manager: \"yarn\" },\n { file: \"package-lock.json\", manager: \"npm\" },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nexport const lockfileExtractor: Extractor = {\n name: \"lockfile\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n for (const { file, manager } of LOCKFILES) {\n try {\n await access(join(ctx.projectPath, file));\n return [\n {\n category: \"stack\",\n pattern: `Package manager: ${manager}`,\n confidence: 1.0,\n evidence: [{ file, line: null }],\n metadata: { packageManager: manager },\n },\n ];\n } catch {\n // not found, try next\n }\n }\n\n return [];\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype CompilerOptions = {\n strict?: boolean;\n target?: string;\n module?: string;\n moduleResolution?: string;\n paths?: Record<string, string[]>;\n [key: string]: unknown;\n};\n\ntype TsConfig = {\n compilerOptions?: CompilerOptions;\n [key: string]: unknown;\n};\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst EVIDENCE = [{ file: \"tsconfig.json\", line: null }];\n\n/**\n * Strip single-line // comments and trailing commas so JSON.parse accepts\n * tsconfig.json files that use non-standard JSON.\n */\nfunction stripTsConfigNonStandardJson(raw: string): string {\n return raw\n // Remove single-line comments (// ...)\n .replace(/\\/\\/[^\\n]*/g, \"\")\n // Remove trailing commas before ] or }\n .replace(/,(\\s*[}\\]])/g, \"$1\");\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const tsconfigExtractor: Extractor = {\n name: \"tsconfig\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"tsconfig.json\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let config: TsConfig;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n config = JSON.parse(stripTsConfigNonStandardJson(raw)) as TsConfig;\n } catch {\n return [];\n }\n\n const co = config.compilerOptions ?? {};\n const entries: Entry[] = [];\n\n // --- Strict mode ---\n if (co.strict === true) {\n entries.push({\n category: \"stack\",\n pattern: \"TypeScript strict mode enabled\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { strict: true },\n });\n }\n\n // --- Notable compiler options ---\n const notable: Record<string, unknown> = {};\n for (const key of [\"target\", \"module\", \"moduleResolution\"] as const) {\n if (co[key] !== undefined) {\n notable[key] = co[key];\n }\n }\n if (Object.keys(notable).length > 0) {\n entries.push({\n category: \"stack\",\n pattern: \"TypeScript compiler options configured\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: notable,\n });\n }\n\n // --- Path aliases ---\n if (co.paths && Object.keys(co.paths).length > 0) {\n entries.push({\n category: \"imports\",\n pattern: \"Uses TypeScript path aliases\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { aliases: co.paths },\n });\n }\n\n return entries;\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nexport const goModExtractor: Extractor = {\n name: \"go-mod\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"go.mod\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const lines = raw.split(\"\\n\");\n\n let moduleName = \"\";\n let goVersion = \"\";\n let dependencyCount = 0;\n let inRequireBlock = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (!moduleName) {\n const moduleMatch = trimmed.match(/^module\\s+(\\S+)/);\n if (moduleMatch?.[1]) {\n moduleName = moduleMatch[1];\n continue;\n }\n }\n\n if (!goVersion) {\n const goMatch = trimmed.match(/^go\\s+(\\S+)/);\n if (goMatch?.[1]) {\n goVersion = goMatch[1];\n continue;\n }\n }\n\n // Count deps in require blocks\n if (trimmed === \"require (\") {\n inRequireBlock = true;\n continue;\n }\n if (inRequireBlock) {\n if (trimmed === \")\") {\n inRequireBlock = false;\n } else if (trimmed.length > 0 && !trimmed.startsWith(\"//\")) {\n dependencyCount++;\n }\n continue;\n }\n // Single-line require\n if (trimmed.match(/^require\\s+\\S+\\s+v\\S+/)) {\n dependencyCount++;\n }\n }\n\n if (!moduleName) {\n return [];\n }\n\n return [\n {\n category: \"stack\",\n pattern: `Go project (${moduleName})`,\n confidence: 1.0,\n evidence: [{ file: \"go.mod\", line: null }],\n metadata: {\n language: \"Go\",\n moduleName,\n goVersion: goVersion || null,\n dependencyCount,\n },\n },\n ];\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse as parseToml } from \"smol-toml\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype CargoToml = {\n package?: { name?: string; version?: string };\n dependencies?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport const cargoTomlExtractor: Extractor = {\n name: \"cargo-toml\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"Cargo.toml\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let cargo: CargoToml;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n cargo = parseToml(raw) as CargoToml;\n } catch {\n return [];\n }\n\n const packageName = cargo.package?.name;\n if (!packageName) {\n return [];\n }\n\n const dependencyCount = Object.keys(cargo.dependencies ?? {}).length;\n\n return [\n {\n category: \"stack\",\n pattern: `Rust project (${packageName})`,\n confidence: 1.0,\n evidence: [{ file: \"Cargo.toml\", line: null }],\n metadata: {\n language: \"Rust\",\n packageName,\n dependencyCount,\n },\n },\n ];\n },\n};\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { globby } from \"globby\";\nimport { load as yamlLoad } from \"js-yaml\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ntype CommandCategory = \"stack\" | \"testing\";\n\ninterface CommandMatch {\n command: string;\n category: CommandCategory;\n ciFile: string;\n}\n\nconst BUILD_KEYWORDS = [\"build\", \"compile\", \"tsc\", \"tsdown\"];\nconst TEST_KEYWORDS = [\"test\", \"vitest\", \"jest\", \"pytest\", \"cargo test\", \"go test\"];\nconst LINT_KEYWORDS = [\"lint\", \"eslint\", \"biome\", \"clippy\", \"ruff\"];\n\nfunction categorizeCommand(cmd: string): CommandCategory | null {\n const lower = cmd.toLowerCase();\n if (TEST_KEYWORDS.some((kw) => lower.includes(kw))) return \"testing\";\n if (BUILD_KEYWORDS.some((kw) => lower.includes(kw))) return \"stack\";\n if (LINT_KEYWORDS.some((kw) => lower.includes(kw))) return \"stack\";\n return null;\n}\n\n/**\n * Extract run commands from a GitHub Actions workflow YAML.\n * Traverses jobs.*.steps[].run\n */\nfunction extractGithubActionsCommands(doc: unknown, filePath: string): { matched: CommandMatch[]; raw: string[] } {\n const matched: CommandMatch[] = [];\n const raw: string[] = [];\n\n if (!doc || typeof doc !== \"object\") return { matched, raw };\n const record = doc as Record<string, unknown>;\n const jobs = record[\"jobs\"];\n if (!jobs || typeof jobs !== \"object\") return { matched, raw };\n\n for (const job of Object.values(jobs as Record<string, unknown>)) {\n if (!job || typeof job !== \"object\") continue;\n const steps = (job as Record<string, unknown>)[\"steps\"];\n if (!Array.isArray(steps)) continue;\n for (const step of steps) {\n if (!step || typeof step !== \"object\") continue;\n const run = (step as Record<string, unknown>)[\"run\"];\n if (typeof run !== \"string\") continue;\n // A single run block may contain multiple lines\n for (const line of run.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n raw.push(trimmed);\n const category = categorizeCommand(trimmed);\n if (category !== null) {\n matched.push({ command: trimmed, category, ciFile: filePath });\n }\n }\n }\n }\n\n return { matched, raw };\n}\n\n/** Keys that are not job definitions in GitLab CI top-level. */\nconst GITLAB_RESERVED = new Set([\"stages\", \"variables\", \"include\", \"default\", \"workflow\", \"image\", \"services\", \"before_script\", \"after_script\", \"cache\", \"artifacts\"]);\n\n/**\n * Extract script commands from a GitLab CI YAML.\n * Traverses top-level job keys (skipping reserved keys), looks for script arrays.\n */\nfunction extractGitlabCiCommands(doc: unknown, filePath: string): { matched: CommandMatch[]; raw: string[] } {\n const matched: CommandMatch[] = [];\n const raw: string[] = [];\n\n if (!doc || typeof doc !== \"object\") return { matched, raw };\n\n for (const [key, job] of Object.entries(doc as Record<string, unknown>)) {\n if (GITLAB_RESERVED.has(key)) continue;\n if (!job || typeof job !== \"object\") continue;\n const script = (job as Record<string, unknown>)[\"script\"];\n const scripts = Array.isArray(script) ? script : typeof script === \"string\" ? [script] : [];\n for (const cmd of scripts) {\n if (typeof cmd !== \"string\") continue;\n const trimmed = cmd.trim();\n if (!trimmed) continue;\n raw.push(trimmed);\n const category = categorizeCommand(trimmed);\n if (category !== null) {\n matched.push({ command: trimmed, category, ciFile: filePath });\n }\n }\n }\n\n return { matched, raw };\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const ciExtractor: Extractor = {\n name: \"ci\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const ciPatterns = [\n \".github/workflows/*.yml\",\n \".github/workflows/*.yaml\",\n \".gitlab-ci.yml\",\n ];\n\n const ciFiles = await globby(ciPatterns, {\n cwd: ctx.projectPath,\n gitignore: false,\n followSymbolicLinks: false,\n absolute: false,\n });\n\n if (ciFiles.length === 0) return [];\n\n const entries: Entry[] = [];\n\n for (const relPath of ciFiles) {\n const absPath = join(ctx.projectPath, relPath);\n let raw: string;\n try {\n raw = await readFile(absPath, \"utf-8\");\n } catch {\n continue;\n }\n\n let doc: unknown;\n try {\n doc = yamlLoad(raw);\n } catch {\n // Malformed YAML: skip file, no throw\n continue;\n }\n\n const isGitlab = relPath.includes(\".gitlab-ci\");\n const { matched, raw: rawCmds } = isGitlab\n ? extractGitlabCiCommands(doc, relPath)\n : extractGithubActionsCommands(doc, relPath);\n\n // Store all raw commands in a single metadata entry per file\n if (rawCmds.length > 0 || matched.length > 0) {\n for (const { command, category } of matched) {\n entries.push({\n category,\n pattern: `CI command: ${command}`,\n confidence: 0.9,\n evidence: [{ file: relative(ctx.projectPath, absPath) || relPath, line: null }],\n metadata: { command, ciFile: relPath, rawCommands: rawCmds },\n });\n }\n }\n }\n\n return entries;\n },\n};\n","import { globby } from \"globby\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Directories and paths that are always excluded from file listings. */\nexport const ALWAYS_SKIP: readonly string[] = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/generated/**\",\n \"**/.ez-search/**\",\n \"**/.ez-context/**\",\n \"**/.git/**\",\n];\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ListFilesOptions {\n /** The project root to search from. */\n cwd: string;\n /** File extensions to include (without dot). Defaults to ts, js, json, md. */\n extensions?: string[];\n /** Additional ignore patterns (glob syntax). */\n additionalIgnore?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/**\n * List project files while respecting .gitignore (INTG-04) and always\n * skipping common generated/build directories.\n *\n * @returns Relative paths sorted alphabetically.\n */\nexport async function listProjectFiles(\n options: ListFilesOptions\n): Promise<string[]> {\n const {\n cwd,\n extensions = [\"ts\", \"js\", \"json\", \"md\"],\n additionalIgnore = [],\n } = options;\n\n const extPattern =\n extensions.length === 1\n ? `**/*.${extensions[0]}`\n : `**/*.{${extensions.join(\",\")}}`;\n\n const files = await globby(extPattern, {\n cwd,\n gitignore: true,\n ignore: [...ALWAYS_SKIP, ...additionalIgnore],\n followSymbolicLinks: false,\n absolute: false,\n });\n\n return files.sort();\n}\n","import { globby } from \"globby\";\nimport { ALWAYS_SKIP } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ninterface TestPattern {\n glob: string;\n location: string;\n style: string;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Top-level test directory prefixes — files here are directory-based, not co-located. */\nconst TEST_DIR_PREFIXES = [\"test/\", \"tests/\", \"__tests__/\"];\n\nconst TEST_PATTERNS: TestPattern[] = [\n { glob: \"**/*.test.{ts,tsx,js,jsx}\", location: \"co-located\", style: \"*.test.ts style\" },\n { glob: \"**/*.spec.{ts,tsx,js,jsx}\", location: \"co-located\", style: \"*.spec.ts style\" },\n { glob: \"test/**/*.{ts,tsx,js,jsx}\", location: \"test/ directory\", style: \"test/ directory\" },\n { glob: \"tests/**/*.{ts,tsx,js,jsx}\", location: \"tests/ directory\", style: \"tests/ directory\" },\n { glob: \"__tests__/**/*.{ts,tsx,js,jsx}\", location: \"__tests__/ directory\", style: \"__tests__/ directory\" },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const projectStructureExtractor: Extractor = {\n name: \"project-structure\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const entries: Entry[] = [];\n\n for (const { glob, location, style } of TEST_PATTERNS) {\n let matches = await globby(glob, {\n cwd: ctx.projectPath,\n gitignore: true,\n ignore: [...ALWAYS_SKIP],\n followSymbolicLinks: false,\n absolute: false,\n });\n\n // For co-located patterns, exclude files that live in dedicated test directories\n if (location === \"co-located\") {\n matches = matches.filter(\n (f) => !TEST_DIR_PREFIXES.some((prefix) => f.startsWith(prefix))\n );\n }\n\n if (matches.length === 0) continue;\n\n const count = matches.length;\n const confidence = Math.min(0.95, 0.5 + count * 0.05);\n const evidenceFiles = matches.slice(0, 5);\n\n entries.push({\n category: \"testing\",\n pattern: `Test files in ${location} (${style})`,\n confidence,\n evidence: evidenceFiles.map((f) => ({ file: f, line: null })),\n metadata: {\n testFileCount: count,\n location,\n style,\n },\n });\n }\n\n return entries;\n },\n};\n","import { Project } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\ntype CaseKind = \"camelCase\" | \"PascalCase\" | \"snake_case\" | \"UPPER_SNAKE_CASE\";\n\n// ---------------------------------------------------------------------------\n// Case classification\n// ---------------------------------------------------------------------------\n\n/**\n * Classify the naming convention of a single identifier.\n * Returns null for short names (< 4 chars) or unclassifiable names.\n */\nfunction classifyCase(name: string): CaseKind | null {\n if (name.length < 4) return null;\n\n if (/^[A-Z][A-Z0-9_]{3,}$/.test(name)) return \"UPPER_SNAKE_CASE\";\n if (/^[A-Z][a-zA-Z0-9]+$/.test(name)) return \"PascalCase\";\n if (/^[a-z][a-z0-9_]+$/.test(name) && name.includes(\"_\")) return \"snake_case\";\n if (/^[a-z][a-zA-Z0-9]+$/.test(name) && /[A-Z]/.test(name)) return \"camelCase\";\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const namingExtractor: Extractor = {\n name: \"naming\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n // Absolute paths needed for ts-morph\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n // Track counts: { functions, variables, classes } -> { CaseKind -> count }\n const functions: Record<string, number> = {};\n const variables: Record<string, number> = {};\n const classes: Record<string, number> = {};\n const counts: Record<string, Record<string, number>> = { functions, variables, classes };\n\n for (const sf of project.getSourceFiles()) {\n for (const fn of sf.getFunctions()) {\n const name = fn.getName();\n if (!name) continue;\n const kind = classifyCase(name);\n if (kind) functions[kind] = (functions[kind] ?? 0) + 1;\n }\n\n for (const decl of sf.getVariableDeclarations()) {\n const name = decl.getName();\n const kind = classifyCase(name);\n if (kind) variables[kind] = (variables[kind] ?? 0) + 1;\n }\n\n for (const cls of sf.getClasses()) {\n const name = cls.getName();\n if (!name) continue;\n const kind = classifyCase(name);\n if (kind) classes[kind] = (classes[kind] ?? 0) + 1;\n }\n }\n\n const entries: Entry[] = [];\n\n for (const [entityType, caseCounts] of Object.entries(counts)) {\n const total = Object.values(caseCounts).reduce((a, b) => a + b, 0);\n if (total < 3) continue;\n\n // Find dominant case\n let dominant: CaseKind | null = null;\n let dominantCount = 0;\n for (const [kind, count] of Object.entries(caseCounts)) {\n if (count > dominantCount) {\n dominant = kind as CaseKind;\n dominantCount = count;\n }\n }\n\n if (!dominant) continue;\n\n const confidence = Math.min(0.95, dominantCount / total);\n if (confidence < 0.6) continue;\n\n entries.push({\n category: \"naming\",\n pattern: `${entityType} use ${dominant} naming`,\n confidence,\n evidence: [{ file: \"src/**/*.ts\", line: null }],\n metadata: {\n entityType,\n dominantCase: dominant,\n counts: caseCounts,\n sampleSize: total,\n },\n });\n }\n\n return entries;\n },\n};\n","import { join, dirname, resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\ntype SourceFile = ReturnType<InstanceType<typeof Project>[\"getSourceFiles\"]>[number];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Known path alias prefixes used across JS/TS ecosystems. */\nconst ALIAS_PREFIXES = [\"@/\", \"~/\", \"#/\", \"$lib/\"];\n\nfunction hasPathAlias(specifier: string): boolean {\n return ALIAS_PREFIXES.some((prefix) => specifier.startsWith(prefix));\n}\n\n/**\n * Check whether a source file looks like a barrel file:\n * - Has at least one export declaration\n * - Has no function, class, or variable declarations\n */\nfunction isBarrelFile(sourceFile: SourceFile): boolean {\n const hasExports = sourceFile.getExportDeclarations().length > 0;\n if (!hasExports) return false;\n const hasFunctions = sourceFile.getFunctions().length > 0;\n const hasClasses = sourceFile.getClasses().length > 0;\n const hasVars = sourceFile.getVariableDeclarations().length > 0;\n return !hasFunctions && !hasClasses && !hasVars;\n}\n\n/**\n * Build a set of absolute paths for barrel files (index.ts/js variants).\n * Since skipFileDependencyResolution prevents module resolution,\n * we identify barrel files upfront and match imports by path.\n */\nfunction buildBarrelFileSet(project: Project): Set<string> {\n const barrels = new Set<string>();\n for (const sf of project.getSourceFiles()) {\n const filePath = sf.getFilePath();\n const baseName = filePath.split(\"/\").pop() ?? \"\";\n // Only index files can be barrel files (index.ts, index.tsx, index.js, index.jsx)\n if (/^index\\.[tj]sx?$/.test(baseName) && isBarrelFile(sf)) {\n barrels.add(filePath);\n }\n }\n return barrels;\n}\n\n/** Resolve a relative import specifier to candidate absolute paths. */\nfunction resolveRelativeImport(importingFile: string, specifier: string): string[] {\n const dir = dirname(importingFile);\n const base = resolve(dir, specifier);\n const exts = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n const candidates: string[] = [];\n // Direct file: ./foo -> ./foo.ts etc\n for (const ext of exts) candidates.push(base + ext);\n // Directory index: ./foo -> ./foo/index.ts etc\n for (const ext of exts) candidates.push(join(base, \"index\" + ext));\n return candidates;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const importsExtractor: Extractor = {\n name: \"imports\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n // Pre-compute barrel file set for path-based matching\n const barrelFiles = buildBarrelFileSet(project);\n\n let relativeCount = 0;\n let externalCount = 0;\n let barrelCount = 0;\n let aliasCount = 0;\n\n for (const sf of project.getSourceFiles()) {\n for (const imp of sf.getImportDeclarations()) {\n const specifier = imp.getModuleSpecifierValue();\n\n if (imp.isModuleSpecifierRelative()) {\n relativeCount++;\n\n // Barrel detection via path heuristic\n const candidates = resolveRelativeImport(sf.getFilePath(), specifier);\n if (candidates.some((c) => barrelFiles.has(c))) {\n barrelCount++;\n }\n } else {\n externalCount++;\n\n if (hasPathAlias(specifier)) {\n aliasCount++;\n }\n }\n }\n }\n\n const totalImports = relativeCount + externalCount;\n if (totalImports === 0) return [];\n\n const entries: Entry[] = [];\n const evidence = [{ file: \"src/**/*.ts\", line: null }];\n\n // --- Import organization pattern ---\n const relRatio = relativeCount / totalImports;\n let orgPattern: string;\n if (relRatio >= 0.75) {\n orgPattern = \"Predominantly relative imports\";\n } else if (relRatio <= 0.25) {\n orgPattern = \"Predominantly external imports\";\n } else {\n orgPattern = \"Mix of relative and external imports\";\n }\n\n // Confidence scales with sample size (saturates at 100 imports)\n const sizeConfidence = Math.min(0.95, 0.5 + (totalImports / 100) * 0.45);\n\n entries.push({\n category: \"imports\",\n pattern: orgPattern,\n confidence: sizeConfidence,\n evidence,\n metadata: {\n relativeCount,\n externalCount,\n totalImports,\n relativeRatio: Math.round(relRatio * 100) / 100,\n },\n });\n\n // --- Barrel file usage ---\n if (barrelCount > 0) {\n const barrelRatio = barrelCount / relativeCount;\n entries.push({\n category: \"imports\",\n pattern: \"Uses barrel file (index) imports\",\n confidence: Math.min(0.95, 0.5 + barrelRatio * 0.45),\n evidence,\n metadata: { barrelCount, relativeCount },\n });\n }\n\n // --- Path alias usage ---\n if (aliasCount > 0) {\n entries.push({\n category: \"imports\",\n pattern: \"Uses path aliases (@/ prefix)\",\n confidence: 1.0,\n evidence,\n metadata: { aliasCount },\n });\n }\n\n return entries;\n },\n};\n","import { Project, SyntaxKind } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const staticErrorHandlingExtractor: Extractor = {\n name: \"static-error-handling\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n let tryCatchFileCount = 0;\n let tryCatchTotalCount = 0;\n let customErrorClassCount = 0;\n const tryCatchEvidence: string[] = [];\n const customErrorEvidence: string[] = [];\n\n for (const sf of project.getSourceFiles()) {\n const relPath = sf.getFilePath().replace(ctx.projectPath + \"/\", \"\");\n\n const tryStatements = sf.getDescendantsOfKind(SyntaxKind.TryStatement);\n if (tryStatements.length > 0) {\n tryCatchFileCount++;\n tryCatchTotalCount += tryStatements.length;\n if (tryCatchEvidence.length < 5) tryCatchEvidence.push(relPath);\n }\n\n for (const cls of sf.getClasses()) {\n const heritage = cls.getExtends();\n if (heritage && /\\bError\\b/.test(heritage.getText())) {\n customErrorClassCount++;\n if (customErrorEvidence.length < 5) customErrorEvidence.push(relPath);\n }\n }\n }\n\n const entries: Entry[] = [];\n const totalFiles = filesToAnalyse.length;\n\n // Require at least 2 try/catch occurrences (across 1+ files) for a meaningful pattern\n if (tryCatchTotalCount >= 2) {\n // Confidence based on both file spread and occurrence density\n const fileSpread = tryCatchFileCount / totalFiles;\n const densityBoost = Math.min(0.2, tryCatchTotalCount * 0.05);\n const confidence = Math.min(0.95, 0.5 + fileSpread * 0.35 + densityBoost);\n entries.push({\n category: \"error_handling\",\n pattern: \"try/catch imperative error handling\",\n confidence,\n evidence: tryCatchEvidence.map((file) => ({ file, line: null })),\n metadata: { style: \"try-catch\", fileCount: tryCatchFileCount, totalCount: tryCatchTotalCount },\n });\n }\n\n if (customErrorClassCount >= 1) {\n const confidence = Math.min(0.95, 0.5 + (customErrorClassCount / totalFiles) * 0.45);\n entries.push({\n category: \"error_handling\",\n pattern: \"custom error class hierarchy\",\n confidence,\n evidence: customErrorEvidence.map((file) => ({ file, line: null })),\n metadata: { style: \"custom-error-class\", classCount: customErrorClassCount },\n });\n }\n\n return entries;\n },\n};\n","/**\n * ez-search bridge — thin adapter over @ez-corp/ez-search.\n *\n * This is the ONLY file that imports from @ez-corp/ez-search.\n * All other modules interact with ez-search via the EzSearchBridge interface.\n */\nimport { index, query, EzSearchError } from \"@ez-corp/ez-search\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Supporting types\n// ---------------------------------------------------------------------------\n\nexport interface SearchResult {\n file: string;\n chunk: string;\n score: number;\n}\n\n// ---------------------------------------------------------------------------\n// Bridge interface\n// ---------------------------------------------------------------------------\n\nexport interface EzSearchBridge {\n /**\n * Returns true if an .ez-search/ index exists for the project directory.\n */\n hasIndex(projectPath: string): Promise<boolean>;\n\n /**\n * Ensures an index exists: indexes the project if no index is present (EXTR-10).\n */\n ensureIndex(projectPath: string): Promise<void>;\n\n /**\n * Unconditionally re-indexes the project so search results reflect current file state.\n */\n refreshIndex(projectPath: string): Promise<void>;\n\n /**\n * Semantic (and hybrid) search over the indexed project.\n */\n search(query: string, options?: { k?: number }): Promise<SearchResult[]>;\n\n /**\n * Get an embedding vector for the given text.\n * NOTE: @ez-corp/ez-search does not expose a standalone embed API.\n * This method is reserved for future use or a companion embedder.\n */\n embed(text: string): Promise<number[]>;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nclass EzSearchBridgeImpl implements EzSearchBridge {\n constructor(private readonly projectPath: string) {}\n\n async hasIndex(projectPath: string): Promise<boolean> {\n const indexDir = join(projectPath, \".ez-search\");\n return existsSync(indexDir);\n }\n\n async ensureIndex(projectPath: string): Promise<void> {\n if (await this.hasIndex(projectPath)) {\n return;\n }\n await index(projectPath);\n }\n\n async refreshIndex(projectPath: string): Promise<void> {\n // Incremental: ez-search >=1.3.3 skips unchanged files (mtime+size+hash),\n // only re-embeds modified chunks, and auto-recovers from stale Zvec locks.\n await index(projectPath);\n }\n\n async search(\n searchQuery: string,\n options: { k?: number } = {}\n ): Promise<SearchResult[]> {\n const { k = 10 } = options;\n\n let raw: Awaited<ReturnType<typeof query>>;\n try {\n raw = await query(searchQuery, {\n topK: k,\n projectDir: this.projectPath,\n autoIndex: false,\n });\n } catch (err: unknown) {\n if (err instanceof EzSearchError && err.code === \"NO_INDEX\") {\n return [];\n }\n throw err;\n }\n\n const results: SearchResult[] = [];\n\n for (const hit of raw.code) {\n results.push({ file: hit.file, chunk: hit.text, score: hit.score });\n }\n for (const hit of raw.text) {\n results.push({ file: hit.file, chunk: hit.text, score: hit.score });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, k);\n }\n\n async embed(_text: string): Promise<number[]> {\n // @ez-corp/ez-search does not expose a standalone embed endpoint.\n // This is a planned capability that will be implemented when a\n // companion embedding API becomes available.\n throw new Error(\n \"embed() is not yet supported by the ez-search bridge. \" +\n \"Use search() for semantic retrieval.\"\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create an EzSearchBridge bound to the given project directory.\n */\nexport async function createBridge(\n projectPath: string\n): Promise<EzSearchBridge> {\n return new EzSearchBridgeImpl(projectPath);\n}\n","import { createBridge } from \"../../core/ez-search-bridge.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype ErrorStyle = \"try-catch\" | \"result-type\" | \"custom-error-class\" | \"error-boundary\";\n\ninterface PatternDef {\n style: ErrorStyle;\n pattern: string;\n test: (content: string) => boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern definitions\n// ---------------------------------------------------------------------------\n\nconst PATTERNS: PatternDef[] = [\n {\n style: \"try-catch\",\n pattern: \"try/catch imperative error handling\",\n test: (content) => /\\btry\\s*\\{/.test(content) && /\\bcatch\\s*\\(/.test(content),\n },\n {\n style: \"result-type\",\n pattern: \"Result/Either functional error handling\",\n test: (content) =>\n /\\bResult<|\\bOk\\(|\\bErr\\(|\\bisOk\\b|\\bisErr\\b|\\bneverthrow\\b/.test(content),\n },\n {\n style: \"custom-error-class\",\n pattern: \"custom error class hierarchy\",\n test: (content) => /class\\s+\\w+Error\\b|\\bnew\\s+\\w+Error\\(/.test(content),\n },\n {\n style: \"error-boundary\",\n pattern: \"React error boundary components\",\n test: (content) => /\\bErrorBoundary\\b|\\bcomponentDidCatch\\b/.test(content),\n },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const errorHandlingExtractor: Extractor = {\n name: \"error-handling\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const bridge = await createBridge(ctx.projectPath);\n\n if (!(await bridge.hasIndex(ctx.projectPath))) {\n return [];\n }\n\n // Issue targeted search queries\n const [general, resultType, customErrors] = await Promise.all([\n bridge.search(\"error handling try catch throw exception\", { k: 30 }),\n bridge.search(\"Result Ok Err return error value\", { k: 20 }),\n bridge.search(\"custom error class extends Error\", { k: 20 }),\n ]);\n\n // Merge and deduplicate chunks by file (concatenate text for same file)\n const fileContentMap = new Map<string, string>();\n for (const result of [...general, ...resultType, ...customErrors]) {\n const existing = fileContentMap.get(result.file) ?? \"\";\n fileContentMap.set(result.file, existing + \"\\n\" + result.chunk);\n }\n\n const totalUniqueFiles = fileContentMap.size;\n if (totalUniqueFiles === 0) return [];\n\n const entries: Entry[] = [];\n\n for (const patternDef of PATTERNS) {\n const matchingFiles: string[] = [];\n\n for (const [file, content] of fileContentMap) {\n if (patternDef.test(content)) {\n matchingFiles.push(file);\n }\n }\n\n // Require at least 2 distinct files\n if (matchingFiles.length < 2) continue;\n\n const confidence = Math.min(0.95, 0.5 + (matchingFiles.length / totalUniqueFiles) * 0.45);\n\n entries.push({\n category: \"error_handling\",\n pattern: patternDef.pattern,\n confidence,\n evidence: matchingFiles.slice(0, 5).map((file) => ({ file, line: null })),\n metadata: {\n style: patternDef.style,\n fileCount: matchingFiles.length,\n },\n });\n }\n\n return entries;\n },\n};\n","import { createBridge } from \"../../core/ez-search-bridge.js\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype ArchPattern = \"MVC\" | \"feature-based\" | \"layer-based\";\n\n// ---------------------------------------------------------------------------\n// Directory pattern detection\n// ---------------------------------------------------------------------------\n\n/** Get directory paths under src/ (or project root if no src/). */\nfunction extractSourceDirs(files: string[]): Set<string> {\n const dirs = new Set<string>();\n for (const f of files) {\n const parts = f.split(\"/\");\n if (parts.length < 2) continue;\n\n if (parts[0] === \"src\" && parts.length >= 3) {\n // Under src/ -- use \"src/subdir\" as the dir\n dirs.add(`src/${parts[1]}`);\n } else if (parts[0] !== \"src\") {\n // Project root level\n dirs.add(parts[0]!);\n }\n }\n return dirs;\n}\n\n/** Normalise a directory name to lower case for matching. */\nfunction normalise(dir: string): string {\n return dir.split(\"/\").pop()!.toLowerCase();\n}\n\n/** Detect MVC: >= 2 of models/, views/, controllers/, routes/ */\nfunction detectMVC(sourceDirs: Set<string>): string[] {\n const mvc = [\"model\", \"models\", \"view\", \"views\", \"controller\", \"controllers\", \"route\", \"routes\"];\n const found: string[] = [];\n for (const dir of sourceDirs) {\n if (mvc.includes(normalise(dir))) found.push(dir);\n }\n // Deduplicate by canonical name (model/models both count as one)\n const canonical = new Set(found.map((d) => normalise(d).replace(/s$/, \"\")));\n return canonical.size >= 2 ? found : [];\n}\n\n/** Detect feature-based: files under features/, modules/, pages/ with >= 5 files total. */\nfunction detectFeatureBased(files: string[]): string[] {\n const featurePattern = /\\/(features?|modules?|pages?)\\//i;\n const featureDirs = new Set<string>();\n let count = 0;\n for (const f of files) {\n if (featurePattern.test(f)) {\n count++;\n // Extract the feature root dir (e.g. \"src/features\" or \"features\")\n const match = f.match(/^(.*?\\/(features?|modules?|pages?))\\//i);\n if (match) featureDirs.add(match[1]!);\n }\n }\n return count >= 5 ? Array.from(featureDirs) : [];\n}\n\n/** Detect layer-based architecture (DDD / hexagonal / clean arch). */\nfunction detectLayerBased(sourceDirs: Set<string>): string[] {\n const layerPatterns = [\n // DDD\n \"domain\", \"application\", \"infrastructure\",\n // Hexagonal\n \"service\", \"services\", \"repository\", \"repositories\", \"handler\", \"handlers\", \"usecase\", \"usecases\",\n // Clean arch\n \"core\", \"data\", \"presentation\",\n ];\n const found: string[] = [];\n for (const dir of sourceDirs) {\n if (layerPatterns.includes(normalise(dir))) found.push(dir);\n }\n // Need >= 2 distinct layer dirs\n const canonical = new Set(found.map((d) => normalise(d)));\n return canonical.size >= 2 ? found : [];\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const architectureExtractor: Extractor = {\n name: \"architecture\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n // Signal 1: Directory structure scan (deterministic)\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"js\", \"tsx\", \"jsx\", \"py\", \"rb\", \"go\", \"rs\"],\n });\n\n const sourceDirs = extractSourceDirs(files);\n\n // Try each pattern\n const mvcDirs = detectMVC(sourceDirs);\n const featureDirs = detectFeatureBased(files);\n const layerDirs = detectLayerBased(sourceDirs);\n\n let detectedPattern: ArchPattern | null = null;\n let detectedLayers: string[] = [];\n\n if (mvcDirs.length > 0) {\n detectedPattern = \"MVC\";\n detectedLayers = mvcDirs;\n } else if (featureDirs.length > 0) {\n detectedPattern = \"feature-based\";\n detectedLayers = featureDirs;\n } else if (layerDirs.length > 0) {\n detectedPattern = \"layer-based\";\n detectedLayers = layerDirs;\n }\n\n if (!detectedPattern) return [];\n\n // Signal 2: Semantic search confirmation (optional -- adds evidence and boosts confidence)\n const bridge = await createBridge(ctx.projectPath);\n const hasIdx = await bridge.hasIndex(ctx.projectPath);\n\n let confidence = 0.7; // directory-only\n const evidence: { file: string; line: null }[] = detectedLayers\n .slice(0, 3)\n .map((dir) => ({ file: dir, line: null }));\n\n if (hasIdx) {\n const searchResults = await bridge.search(\n \"model view controller route handler service repository\",\n { k: 20 }\n );\n if (searchResults.length > 0) {\n confidence = 0.85;\n for (const r of searchResults.slice(0, 2)) {\n evidence.push({ file: r.file, line: null });\n }\n }\n }\n\n // Deduplicate evidence by file\n const seen = new Set<string>();\n const deduped = evidence.filter(({ file }) => {\n if (seen.has(file)) return false;\n seen.add(file);\n return true;\n });\n\n return [\n {\n category: \"architecture\",\n pattern: patternLabel(detectedPattern),\n confidence,\n evidence: deduped.slice(0, 5),\n metadata: {\n architecturePattern: detectedPattern,\n layers: detectedLayers,\n },\n },\n ];\n },\n};\n\nfunction patternLabel(p: ArchPattern): string {\n switch (p) {\n case \"MVC\":\n return \"MVC architecture pattern\";\n case \"feature-based\":\n return \"Feature-based architecture\";\n case \"layer-based\":\n return \"Layer-based architecture\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers exposed for testing\n// ---------------------------------------------------------------------------\n\nexport { extractSourceDirs, detectMVC, detectFeatureBased, detectLayerBased };\n","import { createRegistry } from \"./registry.js\";\nimport { ConventionRegistrySchema } from \"./schema.js\";\nimport type { ConventionEntry, ConventionRegistry, EvidenceRef } from \"./schema.js\";\nimport { runExtractors } from \"../extractors/index.js\";\nimport type { ExtractorOptions } from \"../extractors/types.js\";\nimport { packageJsonExtractor } from \"../extractors/static/package-json.js\";\nimport { lockfileExtractor } from \"../extractors/static/lockfile.js\";\nimport { tsconfigExtractor } from \"../extractors/static/tsconfig.js\";\nimport { goModExtractor } from \"../extractors/static/go-mod.js\";\nimport { cargoTomlExtractor } from \"../extractors/static/cargo-toml.js\";\nimport { ciExtractor } from \"../extractors/static/ci.js\";\nimport { projectStructureExtractor } from \"../extractors/static/project-structure.js\";\nimport { namingExtractor } from \"../extractors/code/naming.js\";\nimport { importsExtractor } from \"../extractors/code/imports.js\";\nimport { staticErrorHandlingExtractor } from \"../extractors/code/error-handling.js\";\nimport { errorHandlingExtractor } from \"../extractors/semantic/error-handling.js\";\nimport { architectureExtractor } from \"../extractors/semantic/architecture.js\";\n\n// ---------------------------------------------------------------------------\n// Extractor registry (ordered by confidence priority for StackInfo population)\n// ---------------------------------------------------------------------------\n\nconst ALL_EXTRACTORS = [\n packageJsonExtractor,\n lockfileExtractor,\n tsconfigExtractor,\n goModExtractor,\n cargoTomlExtractor,\n ciExtractor,\n projectStructureExtractor,\n namingExtractor,\n importsExtractor,\n staticErrorHandlingExtractor,\n errorHandlingExtractor,\n architectureExtractor,\n];\n\n// ---------------------------------------------------------------------------\n// Deduplication helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Deduplicate evidence by file+line combination.\n */\nfunction deduplicateEvidence(evidence: EvidenceRef[]): EvidenceRef[] {\n const seen = new Set<string>();\n return evidence.filter((e) => {\n const key = `${e.file}:${e.line ?? \"null\"}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Deduplicate conventions by category+pattern.\n * For duplicates, keep the one with higher confidence.\n * Merge evidence arrays from duplicates.\n */\nfunction deduplicateConventions(\n conventions: ConventionEntry[]\n): ConventionEntry[] {\n const grouped = new Map<string, ConventionEntry>();\n\n for (const entry of conventions) {\n const key = `${entry.category}:${entry.pattern}`;\n const existing = grouped.get(key);\n\n if (!existing) {\n grouped.set(key, entry);\n } else {\n // Keep higher confidence, merge evidence\n const winner: ConventionEntry =\n entry.confidence > existing.confidence ? entry : existing;\n const mergedEvidence = deduplicateEvidence([\n ...existing.evidence,\n ...entry.evidence,\n ]);\n grouped.set(key, { ...winner, evidence: mergedEvidence });\n }\n }\n\n return Array.from(grouped.values());\n}\n\n// ---------------------------------------------------------------------------\n// StackInfo population helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Populate StackInfo from extracted conventions via a post-extraction pass.\n * Conventions are processed in array order; first match wins for each field.\n */\nfunction populateStackInfo(registry: ConventionRegistry): ConventionRegistry {\n const stack = { ...registry.stack };\n\n for (const entry of registry.conventions) {\n const meta = entry.metadata ?? {};\n\n if (entry.category === \"stack\") {\n if (!stack.language || stack.language === \"unknown\") {\n if (typeof meta.language === \"string\") {\n stack.language = meta.language;\n }\n }\n if (!stack.framework && typeof meta.framework === \"string\") {\n stack.framework = meta.framework;\n }\n if (!stack.testRunner && typeof meta.testRunner === \"string\") {\n stack.testRunner = meta.testRunner;\n }\n if (!stack.packageManager && typeof meta.packageManager === \"string\") {\n stack.packageManager = meta.packageManager;\n }\n if (!stack.buildTool) {\n // Detect buildTool from scripts metadata\n if (typeof meta.buildTool === \"string\") {\n stack.buildTool = meta.buildTool;\n } else if (\n typeof meta.scriptName === \"string\" &&\n meta.scriptName === \"build\" &&\n typeof meta.command === \"string\"\n ) {\n // Extract the build tool from the build script command (first word)\n stack.buildTool = (meta.command as string).split(\" \")[0];\n }\n }\n }\n\n if (entry.category === \"testing\") {\n if (!stack.testRunner && typeof meta.testRunner === \"string\") {\n stack.testRunner = meta.testRunner;\n }\n }\n }\n\n return { ...registry, stack };\n}\n\n// ---------------------------------------------------------------------------\n// ArchitectureInfo population helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Populate ArchitectureInfo from extracted conventions via a post-extraction pass.\n * First architecture convention with the relevant metadata wins.\n */\nfunction populateArchitectureInfo(\n registry: ConventionRegistry\n): ConventionRegistry {\n const arch = { ...registry.architecture };\n\n for (const entry of registry.conventions) {\n if (entry.category === \"architecture\") {\n if (\n !arch.pattern &&\n typeof entry.metadata?.architecturePattern === \"string\"\n ) {\n arch.pattern = entry.metadata.architecturePattern;\n }\n if (\n arch.layers.length === 0 &&\n Array.isArray(entry.metadata?.layers)\n ) {\n arch.layers = entry.metadata.layers as string[];\n }\n }\n }\n\n return { ...registry, architecture: arch };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Run the full extraction pipeline against the given project path.\n *\n * 1. Runs all extractors in parallel (Promise.allSettled)\n * 2. Deduplicates conventions by category+pattern (higher confidence wins)\n * 3. Populates StackInfo from convention metadata\n * 4. Populates ArchitectureInfo from convention metadata\n * 5. Validates and returns the final ConventionRegistry\n */\nexport async function extractConventions(\n projectPath: string,\n options?: ExtractorOptions\n): Promise<ConventionRegistry> {\n const ctx = { projectPath, options };\n const emptyRegistry = createRegistry(projectPath);\n\n // Run all extractors\n const populated = await runExtractors(ALL_EXTRACTORS, ctx, emptyRegistry);\n\n // Deduplicate conventions\n const deduplicated: ConventionRegistry = {\n ...populated,\n conventions: deduplicateConventions(populated.conventions),\n };\n\n // Populate StackInfo from convention metadata\n const withStack = populateStackInfo(deduplicated);\n\n // Populate ArchitectureInfo from convention metadata\n const withArch = populateArchitectureInfo(withStack);\n\n // Validate and return\n return ConventionRegistrySchema.parse(withArch);\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\n\nexport const MARKER_START = \"<!-- ez-context:start -->\";\nexport const MARKER_END = \"<!-- ez-context:end -->\";\n\n/**\n * Write content into the marker section of filePath.\n *\n * Three paths:\n * 1. File does not exist: creates it with markers wrapping content.\n * 2. File exists, no markers (or only one marker): appends the section at the end.\n * 3. File exists with both markers: splices new content between existing markers,\n * preserving everything outside.\n */\nexport async function writeWithMarkers(\n filePath: string,\n content: string\n): Promise<void> {\n const wrapped = `${MARKER_START}\\n${content}\\n${MARKER_END}`;\n\n if (!existsSync(filePath)) {\n await writeFile(filePath, wrapped + \"\\n\", \"utf-8\");\n return;\n }\n\n const existing = await readFile(filePath, \"utf-8\");\n const startIdx = existing.indexOf(MARKER_START);\n const endIdx = existing.indexOf(MARKER_END);\n\n // Treat missing or unpaired marker as \"no markers\" — append section\n if (startIdx === -1 || endIdx === -1) {\n const separator = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n await writeFile(filePath, existing + separator + wrapped + \"\\n\", \"utf-8\");\n return;\n }\n\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + MARKER_END.length);\n await writeFile(filePath, before + wrapped + after, \"utf-8\");\n}\n","// Shared rendering helpers for all emitter modules\nimport type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\n\n/**\n * Extract script commands from a filtered list of convention entries.\n * Shared by agents-md and renderConventionsBody.\n */\nexport function extractCommands(\n filtered: ConventionEntry[]\n): Array<{ scriptName: string; command: string }> {\n const commands: Array<{ scriptName: string; command: string }> = [];\n for (const entry of filtered) {\n const meta = entry.metadata;\n if (\n meta &&\n typeof meta[\"command\"] === \"string\" &&\n typeof meta[\"scriptName\"] === \"string\"\n ) {\n commands.push({\n scriptName: meta[\"scriptName\"] as string,\n command: meta[\"command\"] as string,\n });\n }\n }\n return commands;\n}\n\n/**\n * Check if a stack-category convention should appear in the Conventions section.\n * Stack entries that map to StackInfo fields (language, framework, etc.) are already\n * shown in the Stack section. Others (e.g. \"TypeScript strict mode\") are convention-worthy.\n */\nfunction isStackConventionWorthy(\n entry: ConventionEntry,\n stack: ConventionRegistry[\"stack\"]\n): boolean {\n if (entry.category !== \"stack\") return false;\n const meta = entry.metadata ?? {};\n // Already represented in Stack section via StackInfo fields\n if (typeof meta[\"language\"] === \"string\" && stack.language !== \"unknown\") return false;\n if (typeof meta[\"framework\"] === \"string\" && stack.framework) return false;\n if (typeof meta[\"buildTool\"] === \"string\" && stack.buildTool) return false;\n if (typeof meta[\"packageManager\"] === \"string\" && stack.packageManager) return false;\n // Script entries are shown in Commands section\n if (typeof meta[\"scriptName\"] === \"string\") return false;\n // Everything else (strict mode, compiler options, etc.) is convention-worthy\n return true;\n}\n\n/**\n * Check if a convention entry is redundant with the Stack or Commands sections.\n * - \"Test runner: X\" in testing category duplicates Stack > Test Runner\n * - Entries with metadata.scriptName duplicate the Commands section\n */\nexport function isRedundantConvention(entry: ConventionEntry): boolean {\n if (entry.category === \"testing\" && entry.pattern.startsWith(\"Test runner:\")) {\n return true;\n }\n if (entry.metadata && typeof entry.metadata[\"scriptName\"] === \"string\") {\n return true;\n }\n return false;\n}\n\n/**\n * Render conventions body as markdown lines.\n * Used by cursor-mdc, skill-md, rulesync-md, ruler-md, copilot-md.\n */\nexport function renderConventionsBody(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string[] {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n const lines: string[] = [];\n\n // Stack section\n const s = registry.stack;\n const hasStack =\n s.language !== \"unknown\" ||\n Boolean(s.framework) ||\n Boolean(s.buildTool) ||\n Boolean(s.packageManager) ||\n Boolean(s.testRunner);\n\n if (hasStack) {\n lines.push(\"## Stack\");\n if (s.language !== \"unknown\") lines.push(`- Language: ${s.language}`);\n if (s.framework) lines.push(`- Framework: ${s.framework}`);\n if (s.buildTool) lines.push(`- Build: ${s.buildTool}`);\n if (s.packageManager) lines.push(`- Package Manager: ${s.packageManager}`);\n if (s.testRunner) lines.push(`- Test Runner: ${s.testRunner}`);\n lines.push(\"\");\n }\n\n // Architecture section\n const a = registry.architecture;\n const hasArchitecture =\n Boolean(a.pattern) || (a.layers?.length ?? 0) > 0;\n\n if (hasArchitecture) {\n lines.push(\"## Architecture\");\n if (a.pattern) lines.push(`- Pattern: ${a.pattern}`);\n if (a.layers && a.layers.length > 0) {\n lines.push(`- Layers: ${a.layers.join(\", \")}`);\n }\n lines.push(\"\");\n }\n\n // Conventions section — group by category, exclude architecture and redundant entries.\n // Stack entries without scriptName are kept (e.g. \"TypeScript strict mode enabled\").\n const categoryMap = new Map<string, string[]>();\n for (const entry of filtered) {\n if (entry.category === \"architecture\") continue;\n if (entry.category === \"stack\" && !isStackConventionWorthy(entry, s)) continue;\n if (isRedundantConvention(entry)) continue;\n const list = categoryMap.get(entry.category) ?? [];\n list.push(entry.pattern);\n categoryMap.set(entry.category, list);\n }\n\n if (categoryMap.size > 0) {\n lines.push(\"## Conventions\");\n for (const [category, patterns] of categoryMap) {\n for (const pattern of patterns) {\n lines.push(`- **${category}**: ${pattern}`);\n }\n }\n lines.push(\"\");\n }\n\n // Commands section — from conventions with metadata.command + metadata.scriptName\n const commands = extractCommands(filtered);\n\n if (commands.length > 0) {\n lines.push(\"## Commands\");\n for (const cmd of commands) {\n lines.push(`- \\`${cmd.scriptName}\\`: \\`${cmd.command}\\``);\n }\n lines.push(\"\");\n }\n\n return lines;\n}\n","import type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\nimport { isRedundantConvention } from \"./render-helpers.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ConventionGroup {\n category: string;\n entries: ConventionEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// Data prep\n// ---------------------------------------------------------------------------\n\nfunction prepData(registry: ConventionRegistry, confidenceThreshold: number) {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n // Group by category, excluding architecture and entries redundant with Stack/Commands.\n // Stack entries not covered by StackInfo fields (e.g. \"TypeScript strict mode\") are kept.\n const categoryMap = new Map<string, ConventionEntry[]>();\n for (const entry of filtered) {\n if (entry.category === \"architecture\") continue;\n if (entry.category === \"stack\") {\n const meta = entry.metadata ?? {};\n // Skip entries already rendered in the Stack section\n if (typeof meta[\"language\"] === \"string\") continue;\n if (typeof meta[\"framework\"] === \"string\") continue;\n if (typeof meta[\"buildTool\"] === \"string\") continue;\n if (typeof meta[\"packageManager\"] === \"string\") continue;\n if (typeof meta[\"scriptName\"] === \"string\") continue;\n }\n if (isRedundantConvention(entry)) continue;\n const list = categoryMap.get(entry.category) ?? [];\n list.push(entry);\n categoryMap.set(entry.category, list);\n }\n\n const conventionGroups: ConventionGroup[] = [];\n for (const [category, entries] of categoryMap) {\n conventionGroups.push({ category, entries });\n }\n\n const hasStack =\n registry.stack.language !== \"unknown\" ||\n Boolean(registry.stack.framework) ||\n Boolean(registry.stack.buildTool) ||\n Boolean(registry.stack.packageManager) ||\n Boolean(registry.stack.testRunner);\n\n const hasArchitecture =\n Boolean(registry.architecture.pattern) ||\n (registry.architecture.layers?.length ?? 0) > 0;\n\n return {\n stack: registry.stack,\n architecture: registry.architecture,\n conventionGroups,\n hasStack,\n hasArchitecture,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function renderClaudeMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const data = prepData(registry, confidenceThreshold);\n const lines: string[] = [];\n\n lines.push(\"# Project Context\");\n\n // Stack section\n if (data.hasStack) {\n lines.push(\"\");\n lines.push(\"## Stack\");\n if (data.stack.language !== \"unknown\") {\n lines.push(`- Language: ${data.stack.language}`);\n }\n if (data.stack.framework) lines.push(`- Framework: ${data.stack.framework}`);\n if (data.stack.buildTool) lines.push(`- Build: ${data.stack.buildTool}`);\n if (data.stack.packageManager) lines.push(`- Package Manager: ${data.stack.packageManager}`);\n if (data.stack.testRunner) lines.push(`- Test Runner: ${data.stack.testRunner}`);\n }\n\n // Conventions section\n if (data.conventionGroups.length > 0) {\n lines.push(\"\");\n lines.push(\"## Conventions\");\n for (const group of data.conventionGroups) {\n for (const entry of group.entries) {\n lines.push(`- **${group.category}**: ${entry.pattern}`);\n }\n }\n }\n\n // Architecture section\n if (data.hasArchitecture) {\n lines.push(\"\");\n lines.push(\"## Architecture\");\n if (data.architecture.pattern) {\n lines.push(`- Pattern: ${data.architecture.pattern}`);\n }\n if (data.architecture.layers && data.architecture.layers.length > 0) {\n lines.push(`- Layers: ${data.architecture.layers.join(\", \")}`);\n }\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\nimport { extractCommands } from \"./render-helpers.js\";\n\n// ---------------------------------------------------------------------------\n// Data prep\n// ---------------------------------------------------------------------------\n\nfunction prepData(registry: ConventionRegistry, confidenceThreshold: number) {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n const commands = extractCommands(filtered);\n\n const byCategory = (cat: string): ConventionEntry[] =>\n filtered.filter((c) => c.category === cat);\n\n const testingConventions = byCategory(\"testing\");\n const namingConventions = byCategory(\"naming\");\n const importConventions = byCategory(\"imports\");\n const gitConventions = filtered.filter(\n (c) =>\n c.pattern.toLowerCase().includes(\"git\") ||\n (c.category === \"other\" && c.pattern.toLowerCase().includes(\"commit\"))\n );\n\n const hasTesting =\n Boolean(registry.stack.testRunner) || testingConventions.length > 0;\n\n const hasProjectStructure =\n Boolean(registry.architecture.pattern) ||\n (registry.architecture.layers?.length ?? 0) > 0;\n\n const hasCodeStyle =\n namingConventions.length > 0 || importConventions.length > 0;\n\n return {\n commands,\n testRunner: registry.stack.testRunner ?? null,\n testingConventions,\n namingConventions,\n importConventions,\n gitConventions,\n architecture: registry.architecture,\n hasTesting,\n hasProjectStructure,\n hasCodeStyle,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function renderAgentsMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const data = prepData(registry, confidenceThreshold);\n const lines: string[] = [];\n\n lines.push(\"# AGENTS.md\");\n\n // Commands section\n if (data.commands.length > 0) {\n lines.push(\"\");\n lines.push(\"## Commands\");\n for (const cmd of data.commands) {\n lines.push(`- \\`${cmd.scriptName}\\`: \\`${cmd.command}\\``);\n }\n }\n\n // Testing section\n if (data.hasTesting) {\n lines.push(\"\");\n lines.push(\"## Testing\");\n if (data.testRunner) lines.push(`- Test runner: ${data.testRunner}`);\n for (const entry of data.testingConventions) {\n lines.push(`- ${entry.pattern}`);\n }\n }\n\n // Project Structure section\n if (data.hasProjectStructure) {\n lines.push(\"\");\n lines.push(\"## Project Structure\");\n if (data.architecture.pattern) {\n lines.push(`- Architecture: ${data.architecture.pattern}`);\n }\n if (data.architecture.layers && data.architecture.layers.length > 0) {\n lines.push(`- Layers: ${data.architecture.layers.join(\", \")}`);\n }\n }\n\n // Code Style section\n if (data.hasCodeStyle) {\n lines.push(\"\");\n lines.push(\"## Code Style\");\n for (const entry of data.namingConventions) {\n lines.push(`- **naming**: ${entry.pattern}`);\n }\n for (const entry of data.importConventions) {\n lines.push(`- **imports**: ${entry.pattern}`);\n }\n }\n\n // Git Workflow section (optional)\n if (data.gitConventions.length > 0) {\n lines.push(\"\");\n lines.push(\"## Git Workflow\");\n for (const entry of data.gitConventions) {\n lines.push(`- ${entry.pattern}`);\n }\n }\n\n // Boundaries section (always present)\n lines.push(\"\");\n lines.push(\"## Boundaries\");\n lines.push(\"- Do not modify auto-generated sections between ez-context markers\");\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Cursor MDC rule file (.cursor/rules/ez-context.mdc).\n *\n * Format: YAML frontmatter + markdown body.\n * - description: shown in Cursor UI\n * - globs: empty string (not null/omitted) per Cursor docs\n * - alwaysApply: true ensures conventions are always in context\n */\nexport function renderCursorMdc(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const frontmatter = yaml\n .dump({\n description: \"Project conventions extracted by ez-context\",\n globs: \"\",\n alwaysApply: true,\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line added by renderConventionsBody\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a GitHub Copilot instructions file (.github/copilot-instructions.md).\n *\n * Format: Plain markdown, no YAML frontmatter.\n * GitHub Copilot reads the entire file; HTML comment markers are used\n * for idempotent updates via writeWithMarkers.\n */\nexport function renderCopilotMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const lines: string[] = [];\n\n lines.push(\"<!-- Generated by ez-context. Do not edit between markers. -->\");\n lines.push(\"\");\n lines.push(\"# Copilot Instructions\");\n lines.push(\"\");\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n lines.push(...bodyLines);\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a SKILL.md module file (.skills/ez-context/SKILL.md).\n *\n * Format: YAML frontmatter + markdown body.\n * - name: must match directory name (ez-context)\n * - description: max 1024 chars, describes what AND when to use\n * Body stays under 5000 tokens (~3750 words) as per SKILL.md spec.\n */\nexport function renderSkillMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const description =\n \"Project conventions and coding standards for this codebase. \" +\n \"Use when writing new code, reviewing patterns, or understanding project architecture.\";\n\n const frontmatter = yaml\n .dump({\n name: \"ez-context\",\n description,\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Rulesync rule file (.rulesync/rules/ez-context.md).\n *\n * Format: YAML frontmatter + markdown body.\n * - targets: specifies which AI tools receive this rule\n * ez-context writes INTO .rulesync/rules/; Rulesync distributes to tools.\n */\nexport function renderRulesyncMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const frontmatter = yaml\n .dump({\n description: \"Project conventions extracted by ez-context\",\n targets: [\"cursor\", \"copilot\", \"windsurf\"],\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Ruler rule file (.ruler/ez-context.md).\n *\n * Format: Plain markdown, no YAML frontmatter.\n * Ruler recursively discovers all .md files in .ruler/ and distributes them.\n * ez-context writes a single .ruler/ez-context.md as an additive conventions file.\n */\nexport function renderRulerMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const lines: string[] = [];\n\n lines.push(\"# Project Conventions (ez-context)\");\n lines.push(\"\");\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n lines.push(...bodyLines);\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import path from \"node:path\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport type { EmitOptions, EmitResult, OutputFormat } from \"./types.js\";\nimport { writeWithMarkers } from \"./writer.js\";\nimport { renderClaudeMd } from \"./claude-md.js\";\nimport { renderAgentsMd } from \"./agents-md.js\";\nimport { renderCursorMdc } from \"./cursor-mdc.js\";\nimport { renderCopilotMd } from \"./copilot-md.js\";\nimport { renderSkillMd } from \"./skill-md.js\";\nimport { renderRulesyncMd } from \"./rulesync-md.js\";\nimport { renderRulerMd } from \"./ruler-md.js\";\n\nexport { renderClaudeMd } from \"./claude-md.js\";\nexport { renderAgentsMd } from \"./agents-md.js\";\nexport { renderCursorMdc } from \"./cursor-mdc.js\";\nexport { renderCopilotMd } from \"./copilot-md.js\";\nexport { renderSkillMd } from \"./skill-md.js\";\nexport { renderRulesyncMd } from \"./rulesync-md.js\";\nexport { renderRulerMd } from \"./ruler-md.js\";\nexport type { OutputFormat } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Format emitter registry\n// ---------------------------------------------------------------------------\n\ntype WriteStrategy = \"markers\" | \"direct\";\n\ninterface FormatEmitterEntry {\n render: (registry: ConventionRegistry, threshold: number) => string;\n filename: string;\n strategy: WriteStrategy;\n}\n\nexport const FORMAT_EMITTER_MAP: Record<OutputFormat, FormatEmitterEntry> = {\n claude: {\n render: renderClaudeMd,\n filename: \"CLAUDE.md\",\n strategy: \"markers\",\n },\n agents: {\n render: renderAgentsMd,\n filename: \"AGENTS.md\",\n strategy: \"markers\",\n },\n cursor: {\n render: renderCursorMdc,\n filename: path.join(\".cursor\", \"rules\", \"ez-context.mdc\"),\n strategy: \"direct\",\n },\n copilot: {\n render: renderCopilotMd,\n filename: path.join(\".github\", \"copilot-instructions.md\"),\n strategy: \"markers\",\n },\n skills: {\n render: renderSkillMd,\n filename: path.join(\".skills\", \"ez-context\", \"SKILL.md\"),\n strategy: \"direct\",\n },\n rulesync: {\n render: renderRulesyncMd,\n filename: path.join(\".rulesync\", \"rules\", \"ez-context.md\"),\n strategy: \"markers\",\n },\n ruler: {\n render: renderRulerMd,\n filename: path.join(\".ruler\", \"ez-context.md\"),\n strategy: \"direct\",\n },\n};\n\n// ---------------------------------------------------------------------------\n// emit()\n// ---------------------------------------------------------------------------\n\n/**\n * Emit output files for the given ConventionRegistry.\n *\n * Defaults to [\"claude\", \"agents\"] for backward compatibility.\n * In dryRun mode, returns rendered content without writing any files.\n */\nexport async function emit(\n registry: ConventionRegistry,\n options: EmitOptions\n): Promise<EmitResult> {\n const threshold = options.confidenceThreshold ?? 0.7;\n const formats: OutputFormat[] = options.formats ?? [\"claude\", \"agents\"];\n\n // Render all requested formats\n const rendered: Record<string, string> = {};\n for (const format of formats) {\n const entry = FORMAT_EMITTER_MAP[format];\n rendered[format] = entry.render(registry, threshold);\n }\n\n // Backward compat aliases\n const claudeMd = rendered[\"claude\"] ?? \"\";\n const agentsMd = rendered[\"agents\"] ?? \"\";\n\n if (options.dryRun) {\n return { rendered, claudeMd, agentsMd, filesWritten: [] };\n }\n\n // Write files\n const filesWritten: string[] = [];\n for (const format of formats) {\n const entry = FORMAT_EMITTER_MAP[format];\n const filePath = path.join(options.outputDir, entry.filename);\n\n await mkdir(path.dirname(filePath), { recursive: true });\n if (entry.strategy === \"direct\") {\n await writeFile(filePath, rendered[format]!, \"utf-8\");\n } else {\n await writeWithMarkers(filePath, rendered[format]!);\n }\n\n filesWritten.push(filePath);\n }\n\n return { rendered, claudeMd, agentsMd, filesWritten };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/schema.ts","../src/core/registry.ts","../src/extractors/types.ts","../src/core/pipeline.ts","../src/core/ez-search-bridge.ts","../src/utils/fs.ts","../src/extractors/index.ts","../src/emitters/types.ts","../src/emitters/index.ts","../src/emitters/writer.ts"],"mappings":";;;cAMa,wBAAA,EAAwB,CAAA,CAAA,OAAA;;;;;;;;;cAUxB,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;cAKjB,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;cASrB,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;cASf,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;cAUtB,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAczB,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;AAAA,KACpC,WAAA,GAAc,CAAA,CAAE,KAAA,QAAa,iBAAA;AAAA,KAC7B,eAAA,GAAkB,CAAA,CAAE,KAAA,QAAa,qBAAA;AAAA,KACjC,SAAA,GAAY,CAAA,CAAE,KAAA,QAAa,eAAA;AAAA,KAC3B,gBAAA,GAAmB,CAAA,CAAE,KAAA,QAAa,sBAAA;AAAA,KAClC,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;;;;;AA9DhD;;iBCIgB,cAAA,CAAe,WAAA,WAAsB,kBAAA;;;;;iBA4BrC,aAAA,CACd,QAAA,EAAU,kBAAA,EACV,KAAA,EAAO,IAAA,CAAK,eAAA,UACX,kBAAA;;;UCnCc,gBAAA;;EAEf,cAAA;AAAA;AAAA,UAOe,iBAAA;EFToB;EEWnC,WAAA;EACA,OAAA,GAAU,gBAAA;AAAA;;;;;;UAYK,SAAA;;EAEf,IAAA;EACA,OAAA,CAAQ,GAAA,EAAK,iBAAA,GAAoB,OAAA,CAAQ,IAAA,CAAK,eAAA;AAAA;;;;AF3BhD;;;;;;;;iBGmLsB,kBAAA,CACpB,WAAA,UACA,OAAA,GAAU,gBAAA,GACT,OAAA,CAAQ,kBAAA;;;UC9KM,YAAA;EACf,IAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,UAOe,cAAA;EJlBoB;;;EIsBnC,QAAA,CAAS,WAAA,WAAsB,OAAA;;;;EAK/B,WAAA,CAAY,WAAA,WAAsB,OAAA;;;;EAKlC,YAAA,CAAa,WAAA,WAAsB,OAAA;EJtBxB;;;EI2BX,MAAA,CAAO,KAAA,UAAe,OAAA;IAAY,CAAA;EAAA,IAAe,OAAA,CAAQ,YAAA;;;;;;EAOzD,KAAA,CAAM,IAAA,WAAe,OAAA;AAAA;;;;iBAqFD,YAAA,CACpB,WAAA,WACC,OAAA,CAAQ,cAAA;;;;cClIE,WAAA;AAAA,UAaI,gBAAA;ELdJ;EKgBX,GAAA;;EAEA,UAAA;ELlBmC;EKoBnC,gBAAA;AAAA;;;;;;;iBAaoB,gBAAA,CACpB,OAAA,EAAS,gBAAA,GACR,OAAA;;;;ALnCH;;;;;;iBMKsB,aAAA,CACpB,UAAA,EAAY,SAAA,IACZ,GAAA,EAAK,iBAAA,EACL,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,kBAAA;;;KCbC,YAAA;AAAA,UASK,WAAA;;EAEf,SAAA;EPCA;EOCA,mBAAA;EPTmC;EOWnC,MAAA;EPXmC;EOanC,OAAA,GAAU,YAAA;AAAA;AAAA,UAGK,UAAA;;EAEf,QAAA,EAAU,MAAA;;EAEV,YAAA;;EAEA,QAAA;EPZW;EOcX,QAAA;AAAA;;;;APdF;;;;;iBQkEsB,IAAA,CACpB,QAAA,EAAU,kBAAA,EACV,OAAA,EAAS,WAAA,GACR,OAAA,CAAQ,UAAA;;;cClFE,YAAA;AAAA,cACA,UAAA;;ATEb;;;;;;;;iBSSsB,gBAAA,CACpB,QAAA,UACA,OAAA,WACC,OAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/schema.ts","../src/core/registry.ts","../src/extractors/types.ts","../src/core/pipeline.ts","../src/core/ez-search-bridge.ts","../src/utils/fs.ts","../src/extractors/index.ts","../src/emitters/types.ts","../src/emitters/index.ts","../src/emitters/writer.ts"],"mappings":";;;cAMa,wBAAA,EAAwB,CAAA,CAAA,OAAA;;;;;;;;;cAUxB,iBAAA,EAAiB,CAAA,CAAA,SAAA;;;;cAKjB,qBAAA,EAAqB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;cASrB,eAAA,EAAe,CAAA,CAAA,SAAA;;;;;;;;cASf,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;cAUtB,wBAAA,EAAwB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAczB,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;AAAA,KACpC,WAAA,GAAc,CAAA,CAAE,KAAA,QAAa,iBAAA;AAAA,KAC7B,eAAA,GAAkB,CAAA,CAAE,KAAA,QAAa,qBAAA;AAAA,KACjC,SAAA,GAAY,CAAA,CAAE,KAAA,QAAa,eAAA;AAAA,KAC3B,gBAAA,GAAmB,CAAA,CAAE,KAAA,QAAa,sBAAA;AAAA,KAClC,kBAAA,GAAqB,CAAA,CAAE,KAAA,QAAa,wBAAA;;;;;AA9DhD;;iBCIgB,cAAA,CAAe,WAAA,WAAsB,kBAAA;;;;;iBA4BrC,aAAA,CACd,QAAA,EAAU,kBAAA,EACV,KAAA,EAAO,IAAA,CAAK,eAAA,UACX,kBAAA;;;UCnCc,gBAAA;;EAEf,cAAA;AAAA;AAAA,UAOe,iBAAA;EFToB;EEWnC,WAAA;EACA,OAAA,GAAU,gBAAA;AAAA;;;;;;UAYK,SAAA;;EAEf,IAAA;EACA,OAAA,CAAQ,GAAA,EAAK,iBAAA,GAAoB,OAAA,CAAQ,IAAA,CAAK,eAAA;AAAA;;;;AF3BhD;;;;;;;;iBGmLsB,kBAAA,CACpB,WAAA,UACA,OAAA,GAAU,gBAAA,GACT,OAAA,CAAQ,kBAAA;;;UC9KM,YAAA;EACf,IAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,UAOe,cAAA;EJlBoB;;;EIsBnC,QAAA,CAAS,WAAA,WAAsB,OAAA;;;;EAK/B,WAAA,CAAY,WAAA,WAAsB,OAAA;;;;EAKlC,YAAA,CAAa,WAAA,WAAsB,OAAA;EJtBxB;;;EI2BX,MAAA,CAAO,KAAA,UAAe,OAAA;IAAY,CAAA;EAAA,IAAe,OAAA,CAAQ,YAAA;;;;;;EAOzD,KAAA,CAAM,IAAA,WAAe,OAAA;AAAA;;;;iBA+ED,YAAA,CACpB,WAAA,WACC,OAAA,CAAQ,cAAA;;;;cC5HE,WAAA;AAAA,UAaI,gBAAA;ELdJ;EKgBX,GAAA;;EAEA,UAAA;ELlBmC;EKoBnC,gBAAA;AAAA;;;;;;;iBAaoB,gBAAA,CACpB,OAAA,EAAS,gBAAA,GACR,OAAA;;;;ALnCH;;;;;;iBMKsB,aAAA,CACpB,UAAA,EAAY,SAAA,IACZ,GAAA,EAAK,iBAAA,EACL,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,kBAAA;;;KCbC,YAAA;AAAA,UASK,WAAA;;EAEf,SAAA;EPCA;EOCA,mBAAA;EPTmC;EOWnC,MAAA;EPXmC;EOanC,OAAA,GAAU,YAAA;AAAA;AAAA,UAGK,UAAA;;EAEf,QAAA,EAAU,MAAA;;EAEV,YAAA;;EAEA,QAAA;EPZW;EOcX,QAAA;AAAA;;;;APdF;;;;;iBQkEsB,IAAA,CACpB,QAAA,EAAU,kBAAA,EACV,OAAA,EAAS,WAAA,GACR,OAAA,CAAQ,UAAA;;;cClFE,YAAA;AAAA,cACA,UAAA;;ATEb;;;;;;;;iBSSsB,gBAAA,CACpB,QAAA,UACA,OAAA,WACC,OAAA"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { _ as EvidenceRefSchema, a as writeWithMarkers, c as ALWAYS_SKIP, d as addConvention, f as createRegistry, g as ConventionRegistrySchema, h as ConventionEntrySchema, i as MARKER_START, l as listProjectFiles, m as ConventionCategorySchema, n as emit, o as extractConventions, p as ArchitectureInfoSchema, r as MARKER_END, s as createBridge, u as runExtractors, v as StackInfoSchema } from "./emitters-6MMh0yUj.js";
1
+ import { _ as EvidenceRefSchema, a as writeWithMarkers, c as ALWAYS_SKIP, d as addConvention, f as createRegistry, g as ConventionRegistrySchema, h as ConventionEntrySchema, i as MARKER_START, l as listProjectFiles, m as ConventionCategorySchema, n as emit, o as extractConventions, p as ArchitectureInfoSchema, r as MARKER_END, s as createBridge, u as runExtractors, v as StackInfoSchema } from "./emitters-DOtul0uF.js";
2
2
 
3
3
  export { ALWAYS_SKIP, ArchitectureInfoSchema, ConventionCategorySchema, ConventionEntrySchema, ConventionRegistrySchema, EvidenceRefSchema, MARKER_END, MARKER_START, StackInfoSchema, addConvention, createBridge, createRegistry, emit, extractConventions, listProjectFiles, runExtractors, writeWithMarkers };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ez-corp/ez-context",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Extract coding conventions and generate AI context files (CLAUDE.md, AGENTS.md, Cursor rules, Copilot instructions) with semantic drift detection",
5
5
  "type": "module",
6
6
  "license": "ISC",
@@ -45,7 +45,7 @@
45
45
  "typecheck": "tsc --noEmit -p tsconfig.test.json"
46
46
  },
47
47
  "dependencies": {
48
- "@ez-corp/ez-search": "1.3.2",
48
+ "@ez-corp/ez-search": "1.3.3",
49
49
  "chalk": "^5.6.2",
50
50
  "commander": "^14.0.3",
51
51
  "globby": "^14.0.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"emitters-6MMh0yUj.js","names":["EVIDENCE","parseToml","yamlLoad","prepData"],"sources":["../src/core/schema.ts","../src/core/registry.ts","../src/extractors/index.ts","../src/extractors/static/package-json.ts","../src/extractors/static/lockfile.ts","../src/extractors/static/tsconfig.ts","../src/extractors/static/go-mod.ts","../src/extractors/static/cargo-toml.ts","../src/extractors/static/ci.ts","../src/utils/fs.ts","../src/extractors/static/project-structure.ts","../src/extractors/code/naming.ts","../src/extractors/code/imports.ts","../src/extractors/code/error-handling.ts","../src/core/ez-search-bridge.ts","../src/extractors/semantic/error-handling.ts","../src/extractors/semantic/architecture.ts","../src/core/pipeline.ts","../src/emitters/writer.ts","../src/emitters/render-helpers.ts","../src/emitters/claude-md.ts","../src/emitters/agents-md.ts","../src/emitters/cursor-mdc.ts","../src/emitters/copilot-md.ts","../src/emitters/skill-md.ts","../src/emitters/rulesync-md.ts","../src/emitters/ruler-md.ts","../src/emitters/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Atomic schemas\n// ---------------------------------------------------------------------------\n\nexport const ConventionCategorySchema = z.enum([\n \"stack\",\n \"naming\",\n \"architecture\",\n \"error_handling\",\n \"testing\",\n \"imports\",\n \"other\",\n]);\n\nexport const EvidenceRefSchema = z.object({\n file: z.string(),\n line: z.number().int().positive().nullable(),\n});\n\nexport const ConventionEntrySchema = z.object({\n id: z.uuid(),\n category: ConventionCategorySchema,\n pattern: z.string().min(1),\n confidence: z.number().min(0).max(1),\n evidence: z.array(EvidenceRefSchema),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport const StackInfoSchema = z.object({\n language: z.string(),\n framework: z.string().optional(),\n testRunner: z.string().optional(),\n buildTool: z.string().optional(),\n packageManager: z.string().optional(),\n nodeVersion: z.string().optional(),\n});\n\nexport const ArchitectureInfoSchema = z.object({\n pattern: z.string().optional(),\n layers: z.array(z.string()),\n entryPoints: z.array(z.string()).optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Root registry schema\n// ---------------------------------------------------------------------------\n\nexport const ConventionRegistrySchema = z.object({\n version: z.literal(\"1\"),\n projectPath: z.string(),\n generatedAt: z.string().datetime(),\n stack: StackInfoSchema,\n conventions: z.array(ConventionEntrySchema),\n architecture: ArchitectureInfoSchema,\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Inferred types (no manual interfaces)\n// ---------------------------------------------------------------------------\n\nexport type ConventionCategory = z.infer<typeof ConventionCategorySchema>;\nexport type EvidenceRef = z.infer<typeof EvidenceRefSchema>;\nexport type ConventionEntry = z.infer<typeof ConventionEntrySchema>;\nexport type StackInfo = z.infer<typeof StackInfoSchema>;\nexport type ArchitectureInfo = z.infer<typeof ArchitectureInfoSchema>;\nexport type ConventionRegistry = z.infer<typeof ConventionRegistrySchema>;\n","import {\n type ConventionEntry,\n type ConventionRegistry,\n ConventionRegistrySchema,\n} from \"./schema.js\";\n\n/**\n * Create a new empty ConventionRegistry for the given project path.\n * The returned registry passes ConventionRegistrySchema validation.\n */\nexport function createRegistry(projectPath: string): ConventionRegistry {\n const registry: ConventionRegistry = {\n version: \"1\",\n projectPath,\n generatedAt: new Date().toISOString(),\n stack: {\n language: \"unknown\",\n },\n conventions: [],\n architecture: {\n layers: [],\n },\n };\n\n const result = ConventionRegistrySchema.safeParse(registry);\n if (!result.success) {\n throw new Error(\n `createRegistry produced invalid registry: ${JSON.stringify(result.error.issues)}`\n );\n }\n\n return result.data;\n}\n\n/**\n * Add a convention entry to the registry, auto-generating a UUID for the id.\n * Returns a new registry (does not mutate the input).\n */\nexport function addConvention(\n registry: ConventionRegistry,\n entry: Omit<ConventionEntry, \"id\">\n): ConventionRegistry {\n const newEntry: ConventionEntry = {\n id: crypto.randomUUID(),\n ...entry,\n };\n\n const updated: ConventionRegistry = {\n ...registry,\n conventions: [...registry.conventions, newEntry],\n };\n\n const result = ConventionRegistrySchema.safeParse(updated);\n if (!result.success) {\n throw new Error(\n `addConvention produced invalid registry: ${JSON.stringify(result.error.issues)}`\n );\n }\n\n return result.data;\n}\n","import { addConvention } from \"../core/registry.js\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"./types.js\";\n\n/**\n * Run all extractors in parallel via Promise.allSettled so that a single\n * failing extractor does not abort the others.\n *\n * Fulfilled entries are added to the registry immutably via `addConvention`.\n * Rejected extractors emit a console.warn and are skipped.\n */\nexport async function runExtractors(\n extractors: Extractor[],\n ctx: ExtractionContext,\n registry: ConventionRegistry\n): Promise<ConventionRegistry> {\n const results = await Promise.allSettled(\n extractors.map((e) => e.extract(ctx).then((entries) => ({ extractor: e, entries })))\n );\n\n let current = registry;\n\n for (const [i, result] of results.entries()) {\n if (result.status === \"fulfilled\") {\n for (const entry of result.value.entries) {\n current = addConvention(current, entry);\n }\n } else {\n console.warn(\n `[runExtractors] Extractor \"${extractors[i]!.name}\" failed:`,\n result.reason\n );\n }\n }\n\n return current;\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Detection maps\n// ---------------------------------------------------------------------------\n\nconst FRAMEWORK_MAP: Record<string, string> = {\n react: \"React\",\n vue: \"Vue\",\n \"@angular/core\": \"Angular\",\n next: \"Next.js\",\n nuxt: \"Nuxt\",\n svelte: \"Svelte\",\n hono: \"Hono\",\n express: \"Express\",\n fastify: \"Fastify\",\n koa: \"Koa\",\n};\n\nconst TEST_RUNNER_MAP: Record<string, string> = {\n vitest: \"Vitest\",\n jest: \"Jest\",\n mocha: \"Mocha\",\n jasmine: \"Jasmine\",\n ava: \"Ava\",\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ntype PackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n type?: string;\n packageManager?: string;\n};\n\nfunction allDeps(pkg: PackageJson): Record<string, string> {\n return { ...pkg.dependencies, ...pkg.devDependencies };\n}\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nconst EVIDENCE = [{ file: \"package.json\", line: null }];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const packageJsonExtractor: Extractor = {\n name: \"package-json\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"package.json\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let pkg: PackageJson;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n pkg = JSON.parse(raw) as PackageJson;\n } catch {\n return [];\n }\n\n const deps = allDeps(pkg);\n const entries: Entry[] = [];\n\n // --- Language detection ---\n const isTypeScript =\n \"typescript\" in deps || \"@types/node\" in deps;\n const language = isTypeScript ? \"TypeScript\" : \"JavaScript\";\n entries.push({\n category: \"stack\",\n pattern: `Language: ${language}`,\n confidence: 0.95,\n evidence: EVIDENCE,\n metadata: { language },\n });\n\n // --- Framework detection ---\n for (const [pkg_name, label] of Object.entries(FRAMEWORK_MAP)) {\n if (pkg_name in deps) {\n const version = deps[pkg_name];\n entries.push({\n category: \"stack\",\n pattern: `Framework: ${label}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { framework: label, version },\n });\n break; // first match wins\n }\n }\n\n // --- Test runner detection ---\n for (const [pkg_name, label] of Object.entries(TEST_RUNNER_MAP)) {\n if (pkg_name in deps) {\n entries.push({\n category: \"testing\",\n pattern: `Test runner: ${label}`,\n confidence: 0.95,\n evidence: EVIDENCE,\n metadata: { testRunner: label },\n });\n break; // first match wins\n }\n }\n\n // --- Package manager detection (corepack \"packageManager\" field) ---\n if (typeof pkg.packageManager === \"string\") {\n const pmName = pkg.packageManager.split(\"@\")[0];\n if (pmName) {\n entries.push({\n category: \"stack\",\n pattern: `Package manager: ${pmName}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { packageManager: pmName },\n });\n }\n }\n\n // --- ESM module system detection ---\n if (pkg.type === \"module\") {\n entries.push({\n category: \"imports\",\n pattern: `ES modules (package.json \"type\": \"module\")`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { moduleSystem: \"esm\" },\n });\n }\n\n // --- Scripts ---\n const scripts = pkg.scripts ?? {};\n for (const [scriptName, command] of Object.entries(scripts)) {\n const isTestScript =\n scriptName === \"test\" || scriptName.startsWith(\"test:\");\n const isBuildOrLint =\n scriptName === \"build\" || scriptName === \"lint\";\n\n if (isTestScript || isBuildOrLint) {\n entries.push({\n category: isTestScript ? \"testing\" : \"stack\",\n pattern: `Script \"${scriptName}\": ${command}`,\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { scriptName, command },\n });\n }\n }\n\n return entries;\n },\n};\n","import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Lockfile → package manager mapping (priority order)\n// ---------------------------------------------------------------------------\n\nconst LOCKFILES: Array<{ file: string; manager: string }> = [\n { file: \"bun.lock\", manager: \"bun\" },\n { file: \"bun.lockb\", manager: \"bun\" },\n { file: \"pnpm-lock.yaml\", manager: \"pnpm\" },\n { file: \"yarn.lock\", manager: \"yarn\" },\n { file: \"package-lock.json\", manager: \"npm\" },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nexport const lockfileExtractor: Extractor = {\n name: \"lockfile\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n for (const { file, manager } of LOCKFILES) {\n try {\n await access(join(ctx.projectPath, file));\n return [\n {\n category: \"stack\",\n pattern: `Package manager: ${manager}`,\n confidence: 1.0,\n evidence: [{ file, line: null }],\n metadata: { packageManager: manager },\n },\n ];\n } catch {\n // not found, try next\n }\n }\n\n return [];\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype CompilerOptions = {\n strict?: boolean;\n target?: string;\n module?: string;\n moduleResolution?: string;\n paths?: Record<string, string[]>;\n [key: string]: unknown;\n};\n\ntype TsConfig = {\n compilerOptions?: CompilerOptions;\n [key: string]: unknown;\n};\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst EVIDENCE = [{ file: \"tsconfig.json\", line: null }];\n\n/**\n * Strip single-line // comments and trailing commas so JSON.parse accepts\n * tsconfig.json files that use non-standard JSON.\n */\nfunction stripTsConfigNonStandardJson(raw: string): string {\n return raw\n // Remove single-line comments (// ...)\n .replace(/\\/\\/[^\\n]*/g, \"\")\n // Remove trailing commas before ] or }\n .replace(/,(\\s*[}\\]])/g, \"$1\");\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const tsconfigExtractor: Extractor = {\n name: \"tsconfig\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"tsconfig.json\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let config: TsConfig;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n config = JSON.parse(stripTsConfigNonStandardJson(raw)) as TsConfig;\n } catch {\n return [];\n }\n\n const co = config.compilerOptions ?? {};\n const entries: Entry[] = [];\n\n // --- Strict mode ---\n if (co.strict === true) {\n entries.push({\n category: \"stack\",\n pattern: \"TypeScript strict mode enabled\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { strict: true },\n });\n }\n\n // --- Notable compiler options ---\n const notable: Record<string, unknown> = {};\n for (const key of [\"target\", \"module\", \"moduleResolution\"] as const) {\n if (co[key] !== undefined) {\n notable[key] = co[key];\n }\n }\n if (Object.keys(notable).length > 0) {\n entries.push({\n category: \"stack\",\n pattern: \"TypeScript compiler options configured\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: notable,\n });\n }\n\n // --- Path aliases ---\n if (co.paths && Object.keys(co.paths).length > 0) {\n entries.push({\n category: \"imports\",\n pattern: \"Uses TypeScript path aliases\",\n confidence: 1.0,\n evidence: EVIDENCE,\n metadata: { aliases: co.paths },\n });\n }\n\n return entries;\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\nexport const goModExtractor: Extractor = {\n name: \"go-mod\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"go.mod\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const lines = raw.split(\"\\n\");\n\n let moduleName = \"\";\n let goVersion = \"\";\n let dependencyCount = 0;\n let inRequireBlock = false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (!moduleName) {\n const moduleMatch = trimmed.match(/^module\\s+(\\S+)/);\n if (moduleMatch?.[1]) {\n moduleName = moduleMatch[1];\n continue;\n }\n }\n\n if (!goVersion) {\n const goMatch = trimmed.match(/^go\\s+(\\S+)/);\n if (goMatch?.[1]) {\n goVersion = goMatch[1];\n continue;\n }\n }\n\n // Count deps in require blocks\n if (trimmed === \"require (\") {\n inRequireBlock = true;\n continue;\n }\n if (inRequireBlock) {\n if (trimmed === \")\") {\n inRequireBlock = false;\n } else if (trimmed.length > 0 && !trimmed.startsWith(\"//\")) {\n dependencyCount++;\n }\n continue;\n }\n // Single-line require\n if (trimmed.match(/^require\\s+\\S+\\s+v\\S+/)) {\n dependencyCount++;\n }\n }\n\n if (!moduleName) {\n return [];\n }\n\n return [\n {\n category: \"stack\",\n pattern: `Go project (${moduleName})`,\n confidence: 1.0,\n evidence: [{ file: \"go.mod\", line: null }],\n metadata: {\n language: \"Go\",\n moduleName,\n goVersion: goVersion || null,\n dependencyCount,\n },\n },\n ];\n },\n};\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parse as parseToml } from \"smol-toml\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype CargoToml = {\n package?: { name?: string; version?: string };\n dependencies?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport const cargoTomlExtractor: Extractor = {\n name: \"cargo-toml\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const filePath = join(ctx.projectPath, \"Cargo.toml\");\n\n try {\n await access(filePath);\n } catch {\n return [];\n }\n\n let cargo: CargoToml;\n try {\n const raw = await readFile(filePath, \"utf-8\");\n cargo = parseToml(raw) as CargoToml;\n } catch {\n return [];\n }\n\n const packageName = cargo.package?.name;\n if (!packageName) {\n return [];\n }\n\n const dependencyCount = Object.keys(cargo.dependencies ?? {}).length;\n\n return [\n {\n category: \"stack\",\n pattern: `Rust project (${packageName})`,\n confidence: 1.0,\n evidence: [{ file: \"Cargo.toml\", line: null }],\n metadata: {\n language: \"Rust\",\n packageName,\n dependencyCount,\n },\n },\n ];\n },\n};\n","import { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { globby } from \"globby\";\nimport { load as yamlLoad } from \"js-yaml\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ntype CommandCategory = \"stack\" | \"testing\";\n\ninterface CommandMatch {\n command: string;\n category: CommandCategory;\n ciFile: string;\n}\n\nconst BUILD_KEYWORDS = [\"build\", \"compile\", \"tsc\", \"tsdown\"];\nconst TEST_KEYWORDS = [\"test\", \"vitest\", \"jest\", \"pytest\", \"cargo test\", \"go test\"];\nconst LINT_KEYWORDS = [\"lint\", \"eslint\", \"biome\", \"clippy\", \"ruff\"];\n\nfunction categorizeCommand(cmd: string): CommandCategory | null {\n const lower = cmd.toLowerCase();\n if (TEST_KEYWORDS.some((kw) => lower.includes(kw))) return \"testing\";\n if (BUILD_KEYWORDS.some((kw) => lower.includes(kw))) return \"stack\";\n if (LINT_KEYWORDS.some((kw) => lower.includes(kw))) return \"stack\";\n return null;\n}\n\n/**\n * Extract run commands from a GitHub Actions workflow YAML.\n * Traverses jobs.*.steps[].run\n */\nfunction extractGithubActionsCommands(doc: unknown, filePath: string): { matched: CommandMatch[]; raw: string[] } {\n const matched: CommandMatch[] = [];\n const raw: string[] = [];\n\n if (!doc || typeof doc !== \"object\") return { matched, raw };\n const record = doc as Record<string, unknown>;\n const jobs = record[\"jobs\"];\n if (!jobs || typeof jobs !== \"object\") return { matched, raw };\n\n for (const job of Object.values(jobs as Record<string, unknown>)) {\n if (!job || typeof job !== \"object\") continue;\n const steps = (job as Record<string, unknown>)[\"steps\"];\n if (!Array.isArray(steps)) continue;\n for (const step of steps) {\n if (!step || typeof step !== \"object\") continue;\n const run = (step as Record<string, unknown>)[\"run\"];\n if (typeof run !== \"string\") continue;\n // A single run block may contain multiple lines\n for (const line of run.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n raw.push(trimmed);\n const category = categorizeCommand(trimmed);\n if (category !== null) {\n matched.push({ command: trimmed, category, ciFile: filePath });\n }\n }\n }\n }\n\n return { matched, raw };\n}\n\n/** Keys that are not job definitions in GitLab CI top-level. */\nconst GITLAB_RESERVED = new Set([\"stages\", \"variables\", \"include\", \"default\", \"workflow\", \"image\", \"services\", \"before_script\", \"after_script\", \"cache\", \"artifacts\"]);\n\n/**\n * Extract script commands from a GitLab CI YAML.\n * Traverses top-level job keys (skipping reserved keys), looks for script arrays.\n */\nfunction extractGitlabCiCommands(doc: unknown, filePath: string): { matched: CommandMatch[]; raw: string[] } {\n const matched: CommandMatch[] = [];\n const raw: string[] = [];\n\n if (!doc || typeof doc !== \"object\") return { matched, raw };\n\n for (const [key, job] of Object.entries(doc as Record<string, unknown>)) {\n if (GITLAB_RESERVED.has(key)) continue;\n if (!job || typeof job !== \"object\") continue;\n const script = (job as Record<string, unknown>)[\"script\"];\n const scripts = Array.isArray(script) ? script : typeof script === \"string\" ? [script] : [];\n for (const cmd of scripts) {\n if (typeof cmd !== \"string\") continue;\n const trimmed = cmd.trim();\n if (!trimmed) continue;\n raw.push(trimmed);\n const category = categorizeCommand(trimmed);\n if (category !== null) {\n matched.push({ command: trimmed, category, ciFile: filePath });\n }\n }\n }\n\n return { matched, raw };\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const ciExtractor: Extractor = {\n name: \"ci\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const ciPatterns = [\n \".github/workflows/*.yml\",\n \".github/workflows/*.yaml\",\n \".gitlab-ci.yml\",\n ];\n\n const ciFiles = await globby(ciPatterns, {\n cwd: ctx.projectPath,\n gitignore: false,\n followSymbolicLinks: false,\n absolute: false,\n });\n\n if (ciFiles.length === 0) return [];\n\n const entries: Entry[] = [];\n\n for (const relPath of ciFiles) {\n const absPath = join(ctx.projectPath, relPath);\n let raw: string;\n try {\n raw = await readFile(absPath, \"utf-8\");\n } catch {\n continue;\n }\n\n let doc: unknown;\n try {\n doc = yamlLoad(raw);\n } catch {\n // Malformed YAML: skip file, no throw\n continue;\n }\n\n const isGitlab = relPath.includes(\".gitlab-ci\");\n const { matched, raw: rawCmds } = isGitlab\n ? extractGitlabCiCommands(doc, relPath)\n : extractGithubActionsCommands(doc, relPath);\n\n // Store all raw commands in a single metadata entry per file\n if (rawCmds.length > 0 || matched.length > 0) {\n for (const { command, category } of matched) {\n entries.push({\n category,\n pattern: `CI command: ${command}`,\n confidence: 0.9,\n evidence: [{ file: relative(ctx.projectPath, absPath) || relPath, line: null }],\n metadata: { command, ciFile: relPath, rawCommands: rawCmds },\n });\n }\n }\n }\n\n return entries;\n },\n};\n","import { globby } from \"globby\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Directories and paths that are always excluded from file listings. */\nexport const ALWAYS_SKIP: readonly string[] = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/generated/**\",\n \"**/.ez-search/**\",\n \"**/.ez-context/**\",\n \"**/.git/**\",\n];\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ListFilesOptions {\n /** The project root to search from. */\n cwd: string;\n /** File extensions to include (without dot). Defaults to ts, js, json, md. */\n extensions?: string[];\n /** Additional ignore patterns (glob syntax). */\n additionalIgnore?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/**\n * List project files while respecting .gitignore (INTG-04) and always\n * skipping common generated/build directories.\n *\n * @returns Relative paths sorted alphabetically.\n */\nexport async function listProjectFiles(\n options: ListFilesOptions\n): Promise<string[]> {\n const {\n cwd,\n extensions = [\"ts\", \"js\", \"json\", \"md\"],\n additionalIgnore = [],\n } = options;\n\n const extPattern =\n extensions.length === 1\n ? `**/*.${extensions[0]}`\n : `**/*.{${extensions.join(\",\")}}`;\n\n const files = await globby(extPattern, {\n cwd,\n gitignore: true,\n ignore: [...ALWAYS_SKIP, ...additionalIgnore],\n followSymbolicLinks: false,\n absolute: false,\n });\n\n return files.sort();\n}\n","import { globby } from \"globby\";\nimport { ALWAYS_SKIP } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ninterface TestPattern {\n glob: string;\n location: string;\n style: string;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Top-level test directory prefixes — files here are directory-based, not co-located. */\nconst TEST_DIR_PREFIXES = [\"test/\", \"tests/\", \"__tests__/\"];\n\nconst TEST_PATTERNS: TestPattern[] = [\n { glob: \"**/*.test.{ts,tsx,js,jsx}\", location: \"co-located\", style: \"*.test.ts style\" },\n { glob: \"**/*.spec.{ts,tsx,js,jsx}\", location: \"co-located\", style: \"*.spec.ts style\" },\n { glob: \"test/**/*.{ts,tsx,js,jsx}\", location: \"test/ directory\", style: \"test/ directory\" },\n { glob: \"tests/**/*.{ts,tsx,js,jsx}\", location: \"tests/ directory\", style: \"tests/ directory\" },\n { glob: \"__tests__/**/*.{ts,tsx,js,jsx}\", location: \"__tests__/ directory\", style: \"__tests__/ directory\" },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const projectStructureExtractor: Extractor = {\n name: \"project-structure\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const entries: Entry[] = [];\n\n for (const { glob, location, style } of TEST_PATTERNS) {\n let matches = await globby(glob, {\n cwd: ctx.projectPath,\n gitignore: true,\n ignore: [...ALWAYS_SKIP],\n followSymbolicLinks: false,\n absolute: false,\n });\n\n // For co-located patterns, exclude files that live in dedicated test directories\n if (location === \"co-located\") {\n matches = matches.filter(\n (f) => !TEST_DIR_PREFIXES.some((prefix) => f.startsWith(prefix))\n );\n }\n\n if (matches.length === 0) continue;\n\n const count = matches.length;\n const confidence = Math.min(0.95, 0.5 + count * 0.05);\n const evidenceFiles = matches.slice(0, 5);\n\n entries.push({\n category: \"testing\",\n pattern: `Test files in ${location} (${style})`,\n confidence,\n evidence: evidenceFiles.map((f) => ({ file: f, line: null })),\n metadata: {\n testFileCount: count,\n location,\n style,\n },\n });\n }\n\n return entries;\n },\n};\n","import { Project } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\ntype CaseKind = \"camelCase\" | \"PascalCase\" | \"snake_case\" | \"UPPER_SNAKE_CASE\";\n\n// ---------------------------------------------------------------------------\n// Case classification\n// ---------------------------------------------------------------------------\n\n/**\n * Classify the naming convention of a single identifier.\n * Returns null for short names (< 4 chars) or unclassifiable names.\n */\nfunction classifyCase(name: string): CaseKind | null {\n if (name.length < 4) return null;\n\n if (/^[A-Z][A-Z0-9_]{3,}$/.test(name)) return \"UPPER_SNAKE_CASE\";\n if (/^[A-Z][a-zA-Z0-9]+$/.test(name)) return \"PascalCase\";\n if (/^[a-z][a-z0-9_]+$/.test(name) && name.includes(\"_\")) return \"snake_case\";\n if (/^[a-z][a-zA-Z0-9]+$/.test(name) && /[A-Z]/.test(name)) return \"camelCase\";\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const namingExtractor: Extractor = {\n name: \"naming\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n // Absolute paths needed for ts-morph\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n // Track counts: { functions, variables, classes } -> { CaseKind -> count }\n const functions: Record<string, number> = {};\n const variables: Record<string, number> = {};\n const classes: Record<string, number> = {};\n const counts: Record<string, Record<string, number>> = { functions, variables, classes };\n\n for (const sf of project.getSourceFiles()) {\n for (const fn of sf.getFunctions()) {\n const name = fn.getName();\n if (!name) continue;\n const kind = classifyCase(name);\n if (kind) functions[kind] = (functions[kind] ?? 0) + 1;\n }\n\n for (const decl of sf.getVariableDeclarations()) {\n const name = decl.getName();\n const kind = classifyCase(name);\n if (kind) variables[kind] = (variables[kind] ?? 0) + 1;\n }\n\n for (const cls of sf.getClasses()) {\n const name = cls.getName();\n if (!name) continue;\n const kind = classifyCase(name);\n if (kind) classes[kind] = (classes[kind] ?? 0) + 1;\n }\n }\n\n const entries: Entry[] = [];\n\n for (const [entityType, caseCounts] of Object.entries(counts)) {\n const total = Object.values(caseCounts).reduce((a, b) => a + b, 0);\n if (total < 3) continue;\n\n // Find dominant case\n let dominant: CaseKind | null = null;\n let dominantCount = 0;\n for (const [kind, count] of Object.entries(caseCounts)) {\n if (count > dominantCount) {\n dominant = kind as CaseKind;\n dominantCount = count;\n }\n }\n\n if (!dominant) continue;\n\n const confidence = Math.min(0.95, dominantCount / total);\n if (confidence < 0.6) continue;\n\n entries.push({\n category: \"naming\",\n pattern: `${entityType} use ${dominant} naming`,\n confidence,\n evidence: [{ file: \"src/**/*.ts\", line: null }],\n metadata: {\n entityType,\n dominantCase: dominant,\n counts: caseCounts,\n sampleSize: total,\n },\n });\n }\n\n return entries;\n },\n};\n","import { join, dirname, resolve } from \"node:path\";\nimport { Project } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\ntype SourceFile = ReturnType<InstanceType<typeof Project>[\"getSourceFiles\"]>[number];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Known path alias prefixes used across JS/TS ecosystems. */\nconst ALIAS_PREFIXES = [\"@/\", \"~/\", \"#/\", \"$lib/\"];\n\nfunction hasPathAlias(specifier: string): boolean {\n return ALIAS_PREFIXES.some((prefix) => specifier.startsWith(prefix));\n}\n\n/**\n * Check whether a source file looks like a barrel file:\n * - Has at least one export declaration\n * - Has no function, class, or variable declarations\n */\nfunction isBarrelFile(sourceFile: SourceFile): boolean {\n const hasExports = sourceFile.getExportDeclarations().length > 0;\n if (!hasExports) return false;\n const hasFunctions = sourceFile.getFunctions().length > 0;\n const hasClasses = sourceFile.getClasses().length > 0;\n const hasVars = sourceFile.getVariableDeclarations().length > 0;\n return !hasFunctions && !hasClasses && !hasVars;\n}\n\n/**\n * Build a set of absolute paths for barrel files (index.ts/js variants).\n * Since skipFileDependencyResolution prevents module resolution,\n * we identify barrel files upfront and match imports by path.\n */\nfunction buildBarrelFileSet(project: Project): Set<string> {\n const barrels = new Set<string>();\n for (const sf of project.getSourceFiles()) {\n const filePath = sf.getFilePath();\n const baseName = filePath.split(\"/\").pop() ?? \"\";\n // Only index files can be barrel files (index.ts, index.tsx, index.js, index.jsx)\n if (/^index\\.[tj]sx?$/.test(baseName) && isBarrelFile(sf)) {\n barrels.add(filePath);\n }\n }\n return barrels;\n}\n\n/** Resolve a relative import specifier to candidate absolute paths. */\nfunction resolveRelativeImport(importingFile: string, specifier: string): string[] {\n const dir = dirname(importingFile);\n const base = resolve(dir, specifier);\n const exts = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n const candidates: string[] = [];\n // Direct file: ./foo -> ./foo.ts etc\n for (const ext of exts) candidates.push(base + ext);\n // Directory index: ./foo -> ./foo/index.ts etc\n for (const ext of exts) candidates.push(join(base, \"index\" + ext));\n return candidates;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const importsExtractor: Extractor = {\n name: \"imports\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n // Pre-compute barrel file set for path-based matching\n const barrelFiles = buildBarrelFileSet(project);\n\n let relativeCount = 0;\n let externalCount = 0;\n let barrelCount = 0;\n let aliasCount = 0;\n\n for (const sf of project.getSourceFiles()) {\n for (const imp of sf.getImportDeclarations()) {\n const specifier = imp.getModuleSpecifierValue();\n\n if (imp.isModuleSpecifierRelative()) {\n relativeCount++;\n\n // Barrel detection via path heuristic\n const candidates = resolveRelativeImport(sf.getFilePath(), specifier);\n if (candidates.some((c) => barrelFiles.has(c))) {\n barrelCount++;\n }\n } else {\n externalCount++;\n\n if (hasPathAlias(specifier)) {\n aliasCount++;\n }\n }\n }\n }\n\n const totalImports = relativeCount + externalCount;\n if (totalImports === 0) return [];\n\n const entries: Entry[] = [];\n const evidence = [{ file: \"src/**/*.ts\", line: null }];\n\n // --- Import organization pattern ---\n const relRatio = relativeCount / totalImports;\n let orgPattern: string;\n if (relRatio >= 0.75) {\n orgPattern = \"Predominantly relative imports\";\n } else if (relRatio <= 0.25) {\n orgPattern = \"Predominantly external imports\";\n } else {\n orgPattern = \"Mix of relative and external imports\";\n }\n\n // Confidence scales with sample size (saturates at 100 imports)\n const sizeConfidence = Math.min(0.95, 0.5 + (totalImports / 100) * 0.45);\n\n entries.push({\n category: \"imports\",\n pattern: orgPattern,\n confidence: sizeConfidence,\n evidence,\n metadata: {\n relativeCount,\n externalCount,\n totalImports,\n relativeRatio: Math.round(relRatio * 100) / 100,\n },\n });\n\n // --- Barrel file usage ---\n if (barrelCount > 0) {\n const barrelRatio = barrelCount / relativeCount;\n entries.push({\n category: \"imports\",\n pattern: \"Uses barrel file (index) imports\",\n confidence: Math.min(0.95, 0.5 + barrelRatio * 0.45),\n evidence,\n metadata: { barrelCount, relativeCount },\n });\n }\n\n // --- Path alias usage ---\n if (aliasCount > 0) {\n entries.push({\n category: \"imports\",\n pattern: \"Uses path aliases (@/ prefix)\",\n confidence: 1.0,\n evidence,\n metadata: { aliasCount },\n });\n }\n\n return entries;\n },\n};\n","import { Project, SyntaxKind } from \"ts-morph\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const staticErrorHandlingExtractor: Extractor = {\n name: \"static-error-handling\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n });\n\n if (files.length === 0) return [];\n\n const maxFiles = ctx.options?.maxFilesForAst ?? 200;\n const filesToAnalyse = files.slice(0, maxFiles);\n\n const project = new Project({\n compilerOptions: { allowJs: true, noEmit: true },\n skipFileDependencyResolution: true,\n });\n\n const absPaths = filesToAnalyse.map((f) => `${ctx.projectPath}/${f}`);\n project.addSourceFilesAtPaths(absPaths);\n\n let tryCatchFileCount = 0;\n let tryCatchTotalCount = 0;\n let customErrorClassCount = 0;\n const tryCatchEvidence: string[] = [];\n const customErrorEvidence: string[] = [];\n\n for (const sf of project.getSourceFiles()) {\n const relPath = sf.getFilePath().replace(ctx.projectPath + \"/\", \"\");\n\n const tryStatements = sf.getDescendantsOfKind(SyntaxKind.TryStatement);\n if (tryStatements.length > 0) {\n tryCatchFileCount++;\n tryCatchTotalCount += tryStatements.length;\n if (tryCatchEvidence.length < 5) tryCatchEvidence.push(relPath);\n }\n\n for (const cls of sf.getClasses()) {\n const heritage = cls.getExtends();\n if (heritage && /\\bError\\b/.test(heritage.getText())) {\n customErrorClassCount++;\n if (customErrorEvidence.length < 5) customErrorEvidence.push(relPath);\n }\n }\n }\n\n const entries: Entry[] = [];\n const totalFiles = filesToAnalyse.length;\n\n // Require at least 2 try/catch occurrences (across 1+ files) for a meaningful pattern\n if (tryCatchTotalCount >= 2) {\n // Confidence based on both file spread and occurrence density\n const fileSpread = tryCatchFileCount / totalFiles;\n const densityBoost = Math.min(0.2, tryCatchTotalCount * 0.05);\n const confidence = Math.min(0.95, 0.5 + fileSpread * 0.35 + densityBoost);\n entries.push({\n category: \"error_handling\",\n pattern: \"try/catch imperative error handling\",\n confidence,\n evidence: tryCatchEvidence.map((file) => ({ file, line: null })),\n metadata: { style: \"try-catch\", fileCount: tryCatchFileCount, totalCount: tryCatchTotalCount },\n });\n }\n\n if (customErrorClassCount >= 1) {\n const confidence = Math.min(0.95, 0.5 + (customErrorClassCount / totalFiles) * 0.45);\n entries.push({\n category: \"error_handling\",\n pattern: \"custom error class hierarchy\",\n confidence,\n evidence: customErrorEvidence.map((file) => ({ file, line: null })),\n metadata: { style: \"custom-error-class\", classCount: customErrorClassCount },\n });\n }\n\n return entries;\n },\n};\n","/**\n * ez-search bridge — thin adapter over @ez-corp/ez-search.\n *\n * This is the ONLY file that imports from @ez-corp/ez-search.\n * All other modules interact with ez-search via the EzSearchBridge interface.\n */\nimport { index, query, EzSearchError } from \"@ez-corp/ez-search\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Supporting types\n// ---------------------------------------------------------------------------\n\nexport interface SearchResult {\n file: string;\n chunk: string;\n score: number;\n}\n\n// ---------------------------------------------------------------------------\n// Bridge interface\n// ---------------------------------------------------------------------------\n\nexport interface EzSearchBridge {\n /**\n * Returns true if an .ez-search/ index exists for the project directory.\n */\n hasIndex(projectPath: string): Promise<boolean>;\n\n /**\n * Ensures an index exists: indexes the project if no index is present (EXTR-10).\n */\n ensureIndex(projectPath: string): Promise<void>;\n\n /**\n * Unconditionally re-indexes the project so search results reflect current file state.\n */\n refreshIndex(projectPath: string): Promise<void>;\n\n /**\n * Semantic (and hybrid) search over the indexed project.\n */\n search(query: string, options?: { k?: number }): Promise<SearchResult[]>;\n\n /**\n * Get an embedding vector for the given text.\n * NOTE: @ez-corp/ez-search does not expose a standalone embed API.\n * This method is reserved for future use or a companion embedder.\n */\n embed(text: string): Promise<number[]>;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nclass EzSearchBridgeImpl implements EzSearchBridge {\n constructor(private readonly projectPath: string) {}\n\n async hasIndex(projectPath: string): Promise<boolean> {\n const indexDir = join(projectPath, \".ez-search\");\n return existsSync(indexDir);\n }\n\n async ensureIndex(projectPath: string): Promise<void> {\n if (await this.hasIndex(projectPath)) {\n return;\n }\n await index(projectPath);\n }\n\n async refreshIndex(projectPath: string): Promise<void> {\n // Incremental: ez-search skips unchanged files (mtime+size+hash)\n // and only re-embeds modified chunks. Falls back to full clear\n // if stale Zvec locks block the open (ez-search >=1.3.2 handles\n // this internally with --clear, but we add a safety net here).\n try {\n await index(projectPath);\n } catch {\n await index(projectPath, { clear: true });\n }\n }\n\n async search(\n searchQuery: string,\n options: { k?: number } = {}\n ): Promise<SearchResult[]> {\n const { k = 10 } = options;\n\n let raw: Awaited<ReturnType<typeof query>>;\n try {\n raw = await query(searchQuery, {\n topK: k,\n projectDir: this.projectPath,\n autoIndex: false,\n });\n } catch (err: unknown) {\n if (err instanceof EzSearchError && err.code === \"NO_INDEX\") {\n return [];\n }\n throw err;\n }\n\n const results: SearchResult[] = [];\n\n for (const hit of raw.code) {\n results.push({ file: hit.file, chunk: hit.text, score: hit.score });\n }\n for (const hit of raw.text) {\n results.push({ file: hit.file, chunk: hit.text, score: hit.score });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, k);\n }\n\n async embed(_text: string): Promise<number[]> {\n // @ez-corp/ez-search does not expose a standalone embed endpoint.\n // This is a planned capability that will be implemented when a\n // companion embedding API becomes available.\n throw new Error(\n \"embed() is not yet supported by the ez-search bridge. \" +\n \"Use search() for semantic retrieval.\"\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create an EzSearchBridge bound to the given project directory.\n */\nexport async function createBridge(\n projectPath: string\n): Promise<EzSearchBridge> {\n return new EzSearchBridgeImpl(projectPath);\n}\n","import { createBridge } from \"../../core/ez-search-bridge.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype ErrorStyle = \"try-catch\" | \"result-type\" | \"custom-error-class\" | \"error-boundary\";\n\ninterface PatternDef {\n style: ErrorStyle;\n pattern: string;\n test: (content: string) => boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern definitions\n// ---------------------------------------------------------------------------\n\nconst PATTERNS: PatternDef[] = [\n {\n style: \"try-catch\",\n pattern: \"try/catch imperative error handling\",\n test: (content) => /\\btry\\s*\\{/.test(content) && /\\bcatch\\s*\\(/.test(content),\n },\n {\n style: \"result-type\",\n pattern: \"Result/Either functional error handling\",\n test: (content) =>\n /\\bResult<|\\bOk\\(|\\bErr\\(|\\bisOk\\b|\\bisErr\\b|\\bneverthrow\\b/.test(content),\n },\n {\n style: \"custom-error-class\",\n pattern: \"custom error class hierarchy\",\n test: (content) => /class\\s+\\w+Error\\b|\\bnew\\s+\\w+Error\\(/.test(content),\n },\n {\n style: \"error-boundary\",\n pattern: \"React error boundary components\",\n test: (content) => /\\bErrorBoundary\\b|\\bcomponentDidCatch\\b/.test(content),\n },\n];\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const errorHandlingExtractor: Extractor = {\n name: \"error-handling\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n const bridge = await createBridge(ctx.projectPath);\n\n if (!(await bridge.hasIndex(ctx.projectPath))) {\n return [];\n }\n\n // Issue targeted search queries\n const [general, resultType, customErrors] = await Promise.all([\n bridge.search(\"error handling try catch throw exception\", { k: 30 }),\n bridge.search(\"Result Ok Err return error value\", { k: 20 }),\n bridge.search(\"custom error class extends Error\", { k: 20 }),\n ]);\n\n // Merge and deduplicate chunks by file (concatenate text for same file)\n const fileContentMap = new Map<string, string>();\n for (const result of [...general, ...resultType, ...customErrors]) {\n const existing = fileContentMap.get(result.file) ?? \"\";\n fileContentMap.set(result.file, existing + \"\\n\" + result.chunk);\n }\n\n const totalUniqueFiles = fileContentMap.size;\n if (totalUniqueFiles === 0) return [];\n\n const entries: Entry[] = [];\n\n for (const patternDef of PATTERNS) {\n const matchingFiles: string[] = [];\n\n for (const [file, content] of fileContentMap) {\n if (patternDef.test(content)) {\n matchingFiles.push(file);\n }\n }\n\n // Require at least 2 distinct files\n if (matchingFiles.length < 2) continue;\n\n const confidence = Math.min(0.95, 0.5 + (matchingFiles.length / totalUniqueFiles) * 0.45);\n\n entries.push({\n category: \"error_handling\",\n pattern: patternDef.pattern,\n confidence,\n evidence: matchingFiles.slice(0, 5).map((file) => ({ file, line: null })),\n metadata: {\n style: patternDef.style,\n fileCount: matchingFiles.length,\n },\n });\n }\n\n return entries;\n },\n};\n","import { createBridge } from \"../../core/ez-search-bridge.js\";\nimport { listProjectFiles } from \"../../utils/fs.js\";\nimport type { ConventionEntry } from \"../../core/schema.js\";\nimport type { Extractor, ExtractionContext } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype Entry = Omit<ConventionEntry, \"id\">;\n\ntype ArchPattern = \"MVC\" | \"feature-based\" | \"layer-based\";\n\n// ---------------------------------------------------------------------------\n// Directory pattern detection\n// ---------------------------------------------------------------------------\n\n/** Get directory paths under src/ (or project root if no src/). */\nfunction extractSourceDirs(files: string[]): Set<string> {\n const dirs = new Set<string>();\n for (const f of files) {\n const parts = f.split(\"/\");\n if (parts.length < 2) continue;\n\n if (parts[0] === \"src\" && parts.length >= 3) {\n // Under src/ -- use \"src/subdir\" as the dir\n dirs.add(`src/${parts[1]}`);\n } else if (parts[0] !== \"src\") {\n // Project root level\n dirs.add(parts[0]!);\n }\n }\n return dirs;\n}\n\n/** Normalise a directory name to lower case for matching. */\nfunction normalise(dir: string): string {\n return dir.split(\"/\").pop()!.toLowerCase();\n}\n\n/** Detect MVC: >= 2 of models/, views/, controllers/, routes/ */\nfunction detectMVC(sourceDirs: Set<string>): string[] {\n const mvc = [\"model\", \"models\", \"view\", \"views\", \"controller\", \"controllers\", \"route\", \"routes\"];\n const found: string[] = [];\n for (const dir of sourceDirs) {\n if (mvc.includes(normalise(dir))) found.push(dir);\n }\n // Deduplicate by canonical name (model/models both count as one)\n const canonical = new Set(found.map((d) => normalise(d).replace(/s$/, \"\")));\n return canonical.size >= 2 ? found : [];\n}\n\n/** Detect feature-based: files under features/, modules/, pages/ with >= 5 files total. */\nfunction detectFeatureBased(files: string[]): string[] {\n const featurePattern = /\\/(features?|modules?|pages?)\\//i;\n const featureDirs = new Set<string>();\n let count = 0;\n for (const f of files) {\n if (featurePattern.test(f)) {\n count++;\n // Extract the feature root dir (e.g. \"src/features\" or \"features\")\n const match = f.match(/^(.*?\\/(features?|modules?|pages?))\\//i);\n if (match) featureDirs.add(match[1]!);\n }\n }\n return count >= 5 ? Array.from(featureDirs) : [];\n}\n\n/** Detect layer-based architecture (DDD / hexagonal / clean arch). */\nfunction detectLayerBased(sourceDirs: Set<string>): string[] {\n const layerPatterns = [\n // DDD\n \"domain\", \"application\", \"infrastructure\",\n // Hexagonal\n \"service\", \"services\", \"repository\", \"repositories\", \"handler\", \"handlers\", \"usecase\", \"usecases\",\n // Clean arch\n \"core\", \"data\", \"presentation\",\n ];\n const found: string[] = [];\n for (const dir of sourceDirs) {\n if (layerPatterns.includes(normalise(dir))) found.push(dir);\n }\n // Need >= 2 distinct layer dirs\n const canonical = new Set(found.map((d) => normalise(d)));\n return canonical.size >= 2 ? found : [];\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const architectureExtractor: Extractor = {\n name: \"architecture\",\n\n async extract(ctx: ExtractionContext): Promise<Entry[]> {\n // Signal 1: Directory structure scan (deterministic)\n const files = await listProjectFiles({\n cwd: ctx.projectPath,\n extensions: [\"ts\", \"js\", \"tsx\", \"jsx\", \"py\", \"rb\", \"go\", \"rs\"],\n });\n\n const sourceDirs = extractSourceDirs(files);\n\n // Try each pattern\n const mvcDirs = detectMVC(sourceDirs);\n const featureDirs = detectFeatureBased(files);\n const layerDirs = detectLayerBased(sourceDirs);\n\n let detectedPattern: ArchPattern | null = null;\n let detectedLayers: string[] = [];\n\n if (mvcDirs.length > 0) {\n detectedPattern = \"MVC\";\n detectedLayers = mvcDirs;\n } else if (featureDirs.length > 0) {\n detectedPattern = \"feature-based\";\n detectedLayers = featureDirs;\n } else if (layerDirs.length > 0) {\n detectedPattern = \"layer-based\";\n detectedLayers = layerDirs;\n }\n\n if (!detectedPattern) return [];\n\n // Signal 2: Semantic search confirmation (optional -- adds evidence and boosts confidence)\n const bridge = await createBridge(ctx.projectPath);\n const hasIdx = await bridge.hasIndex(ctx.projectPath);\n\n let confidence = 0.7; // directory-only\n const evidence: { file: string; line: null }[] = detectedLayers\n .slice(0, 3)\n .map((dir) => ({ file: dir, line: null }));\n\n if (hasIdx) {\n const searchResults = await bridge.search(\n \"model view controller route handler service repository\",\n { k: 20 }\n );\n if (searchResults.length > 0) {\n confidence = 0.85;\n for (const r of searchResults.slice(0, 2)) {\n evidence.push({ file: r.file, line: null });\n }\n }\n }\n\n // Deduplicate evidence by file\n const seen = new Set<string>();\n const deduped = evidence.filter(({ file }) => {\n if (seen.has(file)) return false;\n seen.add(file);\n return true;\n });\n\n return [\n {\n category: \"architecture\",\n pattern: patternLabel(detectedPattern),\n confidence,\n evidence: deduped.slice(0, 5),\n metadata: {\n architecturePattern: detectedPattern,\n layers: detectedLayers,\n },\n },\n ];\n },\n};\n\nfunction patternLabel(p: ArchPattern): string {\n switch (p) {\n case \"MVC\":\n return \"MVC architecture pattern\";\n case \"feature-based\":\n return \"Feature-based architecture\";\n case \"layer-based\":\n return \"Layer-based architecture\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers exposed for testing\n// ---------------------------------------------------------------------------\n\nexport { extractSourceDirs, detectMVC, detectFeatureBased, detectLayerBased };\n","import { createRegistry } from \"./registry.js\";\nimport { ConventionRegistrySchema } from \"./schema.js\";\nimport type { ConventionEntry, ConventionRegistry, EvidenceRef } from \"./schema.js\";\nimport { runExtractors } from \"../extractors/index.js\";\nimport type { ExtractorOptions } from \"../extractors/types.js\";\nimport { packageJsonExtractor } from \"../extractors/static/package-json.js\";\nimport { lockfileExtractor } from \"../extractors/static/lockfile.js\";\nimport { tsconfigExtractor } from \"../extractors/static/tsconfig.js\";\nimport { goModExtractor } from \"../extractors/static/go-mod.js\";\nimport { cargoTomlExtractor } from \"../extractors/static/cargo-toml.js\";\nimport { ciExtractor } from \"../extractors/static/ci.js\";\nimport { projectStructureExtractor } from \"../extractors/static/project-structure.js\";\nimport { namingExtractor } from \"../extractors/code/naming.js\";\nimport { importsExtractor } from \"../extractors/code/imports.js\";\nimport { staticErrorHandlingExtractor } from \"../extractors/code/error-handling.js\";\nimport { errorHandlingExtractor } from \"../extractors/semantic/error-handling.js\";\nimport { architectureExtractor } from \"../extractors/semantic/architecture.js\";\n\n// ---------------------------------------------------------------------------\n// Extractor registry (ordered by confidence priority for StackInfo population)\n// ---------------------------------------------------------------------------\n\nconst ALL_EXTRACTORS = [\n packageJsonExtractor,\n lockfileExtractor,\n tsconfigExtractor,\n goModExtractor,\n cargoTomlExtractor,\n ciExtractor,\n projectStructureExtractor,\n namingExtractor,\n importsExtractor,\n staticErrorHandlingExtractor,\n errorHandlingExtractor,\n architectureExtractor,\n];\n\n// ---------------------------------------------------------------------------\n// Deduplication helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Deduplicate evidence by file+line combination.\n */\nfunction deduplicateEvidence(evidence: EvidenceRef[]): EvidenceRef[] {\n const seen = new Set<string>();\n return evidence.filter((e) => {\n const key = `${e.file}:${e.line ?? \"null\"}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Deduplicate conventions by category+pattern.\n * For duplicates, keep the one with higher confidence.\n * Merge evidence arrays from duplicates.\n */\nfunction deduplicateConventions(\n conventions: ConventionEntry[]\n): ConventionEntry[] {\n const grouped = new Map<string, ConventionEntry>();\n\n for (const entry of conventions) {\n const key = `${entry.category}:${entry.pattern}`;\n const existing = grouped.get(key);\n\n if (!existing) {\n grouped.set(key, entry);\n } else {\n // Keep higher confidence, merge evidence\n const winner: ConventionEntry =\n entry.confidence > existing.confidence ? entry : existing;\n const mergedEvidence = deduplicateEvidence([\n ...existing.evidence,\n ...entry.evidence,\n ]);\n grouped.set(key, { ...winner, evidence: mergedEvidence });\n }\n }\n\n return Array.from(grouped.values());\n}\n\n// ---------------------------------------------------------------------------\n// StackInfo population helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Populate StackInfo from extracted conventions via a post-extraction pass.\n * Conventions are processed in array order; first match wins for each field.\n */\nfunction populateStackInfo(registry: ConventionRegistry): ConventionRegistry {\n const stack = { ...registry.stack };\n\n for (const entry of registry.conventions) {\n const meta = entry.metadata ?? {};\n\n if (entry.category === \"stack\") {\n if (!stack.language || stack.language === \"unknown\") {\n if (typeof meta.language === \"string\") {\n stack.language = meta.language;\n }\n }\n if (!stack.framework && typeof meta.framework === \"string\") {\n stack.framework = meta.framework;\n }\n if (!stack.testRunner && typeof meta.testRunner === \"string\") {\n stack.testRunner = meta.testRunner;\n }\n if (!stack.packageManager && typeof meta.packageManager === \"string\") {\n stack.packageManager = meta.packageManager;\n }\n if (!stack.buildTool) {\n // Detect buildTool from scripts metadata\n if (typeof meta.buildTool === \"string\") {\n stack.buildTool = meta.buildTool;\n } else if (\n typeof meta.scriptName === \"string\" &&\n meta.scriptName === \"build\" &&\n typeof meta.command === \"string\"\n ) {\n // Extract the build tool from the build script command (first word)\n stack.buildTool = (meta.command as string).split(\" \")[0];\n }\n }\n }\n\n if (entry.category === \"testing\") {\n if (!stack.testRunner && typeof meta.testRunner === \"string\") {\n stack.testRunner = meta.testRunner;\n }\n }\n }\n\n return { ...registry, stack };\n}\n\n// ---------------------------------------------------------------------------\n// ArchitectureInfo population helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Populate ArchitectureInfo from extracted conventions via a post-extraction pass.\n * First architecture convention with the relevant metadata wins.\n */\nfunction populateArchitectureInfo(\n registry: ConventionRegistry\n): ConventionRegistry {\n const arch = { ...registry.architecture };\n\n for (const entry of registry.conventions) {\n if (entry.category === \"architecture\") {\n if (\n !arch.pattern &&\n typeof entry.metadata?.architecturePattern === \"string\"\n ) {\n arch.pattern = entry.metadata.architecturePattern;\n }\n if (\n arch.layers.length === 0 &&\n Array.isArray(entry.metadata?.layers)\n ) {\n arch.layers = entry.metadata.layers as string[];\n }\n }\n }\n\n return { ...registry, architecture: arch };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Run the full extraction pipeline against the given project path.\n *\n * 1. Runs all extractors in parallel (Promise.allSettled)\n * 2. Deduplicates conventions by category+pattern (higher confidence wins)\n * 3. Populates StackInfo from convention metadata\n * 4. Populates ArchitectureInfo from convention metadata\n * 5. Validates and returns the final ConventionRegistry\n */\nexport async function extractConventions(\n projectPath: string,\n options?: ExtractorOptions\n): Promise<ConventionRegistry> {\n const ctx = { projectPath, options };\n const emptyRegistry = createRegistry(projectPath);\n\n // Run all extractors\n const populated = await runExtractors(ALL_EXTRACTORS, ctx, emptyRegistry);\n\n // Deduplicate conventions\n const deduplicated: ConventionRegistry = {\n ...populated,\n conventions: deduplicateConventions(populated.conventions),\n };\n\n // Populate StackInfo from convention metadata\n const withStack = populateStackInfo(deduplicated);\n\n // Populate ArchitectureInfo from convention metadata\n const withArch = populateArchitectureInfo(withStack);\n\n // Validate and return\n return ConventionRegistrySchema.parse(withArch);\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\n\nexport const MARKER_START = \"<!-- ez-context:start -->\";\nexport const MARKER_END = \"<!-- ez-context:end -->\";\n\n/**\n * Write content into the marker section of filePath.\n *\n * Three paths:\n * 1. File does not exist: creates it with markers wrapping content.\n * 2. File exists, no markers (or only one marker): appends the section at the end.\n * 3. File exists with both markers: splices new content between existing markers,\n * preserving everything outside.\n */\nexport async function writeWithMarkers(\n filePath: string,\n content: string\n): Promise<void> {\n const wrapped = `${MARKER_START}\\n${content}\\n${MARKER_END}`;\n\n if (!existsSync(filePath)) {\n await writeFile(filePath, wrapped + \"\\n\", \"utf-8\");\n return;\n }\n\n const existing = await readFile(filePath, \"utf-8\");\n const startIdx = existing.indexOf(MARKER_START);\n const endIdx = existing.indexOf(MARKER_END);\n\n // Treat missing or unpaired marker as \"no markers\" — append section\n if (startIdx === -1 || endIdx === -1) {\n const separator = existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n await writeFile(filePath, existing + separator + wrapped + \"\\n\", \"utf-8\");\n return;\n }\n\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + MARKER_END.length);\n await writeFile(filePath, before + wrapped + after, \"utf-8\");\n}\n","// Shared rendering helpers for all emitter modules\nimport type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\n\n/**\n * Extract script commands from a filtered list of convention entries.\n * Shared by agents-md and renderConventionsBody.\n */\nexport function extractCommands(\n filtered: ConventionEntry[]\n): Array<{ scriptName: string; command: string }> {\n const commands: Array<{ scriptName: string; command: string }> = [];\n for (const entry of filtered) {\n const meta = entry.metadata;\n if (\n meta &&\n typeof meta[\"command\"] === \"string\" &&\n typeof meta[\"scriptName\"] === \"string\"\n ) {\n commands.push({\n scriptName: meta[\"scriptName\"] as string,\n command: meta[\"command\"] as string,\n });\n }\n }\n return commands;\n}\n\n/**\n * Check if a stack-category convention should appear in the Conventions section.\n * Stack entries that map to StackInfo fields (language, framework, etc.) are already\n * shown in the Stack section. Others (e.g. \"TypeScript strict mode\") are convention-worthy.\n */\nfunction isStackConventionWorthy(\n entry: ConventionEntry,\n stack: ConventionRegistry[\"stack\"]\n): boolean {\n if (entry.category !== \"stack\") return false;\n const meta = entry.metadata ?? {};\n // Already represented in Stack section via StackInfo fields\n if (typeof meta[\"language\"] === \"string\" && stack.language !== \"unknown\") return false;\n if (typeof meta[\"framework\"] === \"string\" && stack.framework) return false;\n if (typeof meta[\"buildTool\"] === \"string\" && stack.buildTool) return false;\n if (typeof meta[\"packageManager\"] === \"string\" && stack.packageManager) return false;\n // Script entries are shown in Commands section\n if (typeof meta[\"scriptName\"] === \"string\") return false;\n // Everything else (strict mode, compiler options, etc.) is convention-worthy\n return true;\n}\n\n/**\n * Check if a convention entry is redundant with the Stack or Commands sections.\n * - \"Test runner: X\" in testing category duplicates Stack > Test Runner\n * - Entries with metadata.scriptName duplicate the Commands section\n */\nexport function isRedundantConvention(entry: ConventionEntry): boolean {\n if (entry.category === \"testing\" && entry.pattern.startsWith(\"Test runner:\")) {\n return true;\n }\n if (entry.metadata && typeof entry.metadata[\"scriptName\"] === \"string\") {\n return true;\n }\n return false;\n}\n\n/**\n * Render conventions body as markdown lines.\n * Used by cursor-mdc, skill-md, rulesync-md, ruler-md, copilot-md.\n */\nexport function renderConventionsBody(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string[] {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n const lines: string[] = [];\n\n // Stack section\n const s = registry.stack;\n const hasStack =\n s.language !== \"unknown\" ||\n Boolean(s.framework) ||\n Boolean(s.buildTool) ||\n Boolean(s.packageManager) ||\n Boolean(s.testRunner);\n\n if (hasStack) {\n lines.push(\"## Stack\");\n if (s.language !== \"unknown\") lines.push(`- Language: ${s.language}`);\n if (s.framework) lines.push(`- Framework: ${s.framework}`);\n if (s.buildTool) lines.push(`- Build: ${s.buildTool}`);\n if (s.packageManager) lines.push(`- Package Manager: ${s.packageManager}`);\n if (s.testRunner) lines.push(`- Test Runner: ${s.testRunner}`);\n lines.push(\"\");\n }\n\n // Architecture section\n const a = registry.architecture;\n const hasArchitecture =\n Boolean(a.pattern) || (a.layers?.length ?? 0) > 0;\n\n if (hasArchitecture) {\n lines.push(\"## Architecture\");\n if (a.pattern) lines.push(`- Pattern: ${a.pattern}`);\n if (a.layers && a.layers.length > 0) {\n lines.push(`- Layers: ${a.layers.join(\", \")}`);\n }\n lines.push(\"\");\n }\n\n // Conventions section — group by category, exclude architecture and redundant entries.\n // Stack entries without scriptName are kept (e.g. \"TypeScript strict mode enabled\").\n const categoryMap = new Map<string, string[]>();\n for (const entry of filtered) {\n if (entry.category === \"architecture\") continue;\n if (entry.category === \"stack\" && !isStackConventionWorthy(entry, s)) continue;\n if (isRedundantConvention(entry)) continue;\n const list = categoryMap.get(entry.category) ?? [];\n list.push(entry.pattern);\n categoryMap.set(entry.category, list);\n }\n\n if (categoryMap.size > 0) {\n lines.push(\"## Conventions\");\n for (const [category, patterns] of categoryMap) {\n for (const pattern of patterns) {\n lines.push(`- **${category}**: ${pattern}`);\n }\n }\n lines.push(\"\");\n }\n\n // Commands section — from conventions with metadata.command + metadata.scriptName\n const commands = extractCommands(filtered);\n\n if (commands.length > 0) {\n lines.push(\"## Commands\");\n for (const cmd of commands) {\n lines.push(`- \\`${cmd.scriptName}\\`: \\`${cmd.command}\\``);\n }\n lines.push(\"\");\n }\n\n return lines;\n}\n","import type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\nimport { isRedundantConvention } from \"./render-helpers.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ConventionGroup {\n category: string;\n entries: ConventionEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// Data prep\n// ---------------------------------------------------------------------------\n\nfunction prepData(registry: ConventionRegistry, confidenceThreshold: number) {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n // Group by category, excluding architecture and entries redundant with Stack/Commands.\n // Stack entries not covered by StackInfo fields (e.g. \"TypeScript strict mode\") are kept.\n const categoryMap = new Map<string, ConventionEntry[]>();\n for (const entry of filtered) {\n if (entry.category === \"architecture\") continue;\n if (entry.category === \"stack\") {\n const meta = entry.metadata ?? {};\n // Skip entries already rendered in the Stack section\n if (typeof meta[\"language\"] === \"string\") continue;\n if (typeof meta[\"framework\"] === \"string\") continue;\n if (typeof meta[\"buildTool\"] === \"string\") continue;\n if (typeof meta[\"packageManager\"] === \"string\") continue;\n if (typeof meta[\"scriptName\"] === \"string\") continue;\n }\n if (isRedundantConvention(entry)) continue;\n const list = categoryMap.get(entry.category) ?? [];\n list.push(entry);\n categoryMap.set(entry.category, list);\n }\n\n const conventionGroups: ConventionGroup[] = [];\n for (const [category, entries] of categoryMap) {\n conventionGroups.push({ category, entries });\n }\n\n const hasStack =\n registry.stack.language !== \"unknown\" ||\n Boolean(registry.stack.framework) ||\n Boolean(registry.stack.buildTool) ||\n Boolean(registry.stack.packageManager) ||\n Boolean(registry.stack.testRunner);\n\n const hasArchitecture =\n Boolean(registry.architecture.pattern) ||\n (registry.architecture.layers?.length ?? 0) > 0;\n\n return {\n stack: registry.stack,\n architecture: registry.architecture,\n conventionGroups,\n hasStack,\n hasArchitecture,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function renderClaudeMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const data = prepData(registry, confidenceThreshold);\n const lines: string[] = [];\n\n lines.push(\"# Project Context\");\n\n // Stack section\n if (data.hasStack) {\n lines.push(\"\");\n lines.push(\"## Stack\");\n if (data.stack.language !== \"unknown\") {\n lines.push(`- Language: ${data.stack.language}`);\n }\n if (data.stack.framework) lines.push(`- Framework: ${data.stack.framework}`);\n if (data.stack.buildTool) lines.push(`- Build: ${data.stack.buildTool}`);\n if (data.stack.packageManager) lines.push(`- Package Manager: ${data.stack.packageManager}`);\n if (data.stack.testRunner) lines.push(`- Test Runner: ${data.stack.testRunner}`);\n }\n\n // Conventions section\n if (data.conventionGroups.length > 0) {\n lines.push(\"\");\n lines.push(\"## Conventions\");\n for (const group of data.conventionGroups) {\n for (const entry of group.entries) {\n lines.push(`- **${group.category}**: ${entry.pattern}`);\n }\n }\n }\n\n // Architecture section\n if (data.hasArchitecture) {\n lines.push(\"\");\n lines.push(\"## Architecture\");\n if (data.architecture.pattern) {\n lines.push(`- Pattern: ${data.architecture.pattern}`);\n }\n if (data.architecture.layers && data.architecture.layers.length > 0) {\n lines.push(`- Layers: ${data.architecture.layers.join(\", \")}`);\n }\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import type { ConventionRegistry, ConventionEntry } from \"../core/schema.js\";\nimport { extractCommands } from \"./render-helpers.js\";\n\n// ---------------------------------------------------------------------------\n// Data prep\n// ---------------------------------------------------------------------------\n\nfunction prepData(registry: ConventionRegistry, confidenceThreshold: number) {\n const filtered = registry.conventions.filter(\n (c) => c.confidence >= confidenceThreshold\n );\n\n const commands = extractCommands(filtered);\n\n const byCategory = (cat: string): ConventionEntry[] =>\n filtered.filter((c) => c.category === cat);\n\n const testingConventions = byCategory(\"testing\");\n const namingConventions = byCategory(\"naming\");\n const importConventions = byCategory(\"imports\");\n const gitConventions = filtered.filter(\n (c) =>\n c.pattern.toLowerCase().includes(\"git\") ||\n (c.category === \"other\" && c.pattern.toLowerCase().includes(\"commit\"))\n );\n\n const hasTesting =\n Boolean(registry.stack.testRunner) || testingConventions.length > 0;\n\n const hasProjectStructure =\n Boolean(registry.architecture.pattern) ||\n (registry.architecture.layers?.length ?? 0) > 0;\n\n const hasCodeStyle =\n namingConventions.length > 0 || importConventions.length > 0;\n\n return {\n commands,\n testRunner: registry.stack.testRunner ?? null,\n testingConventions,\n namingConventions,\n importConventions,\n gitConventions,\n architecture: registry.architecture,\n hasTesting,\n hasProjectStructure,\n hasCodeStyle,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Renderer\n// ---------------------------------------------------------------------------\n\nexport function renderAgentsMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const data = prepData(registry, confidenceThreshold);\n const lines: string[] = [];\n\n lines.push(\"# AGENTS.md\");\n\n // Commands section\n if (data.commands.length > 0) {\n lines.push(\"\");\n lines.push(\"## Commands\");\n for (const cmd of data.commands) {\n lines.push(`- \\`${cmd.scriptName}\\`: \\`${cmd.command}\\``);\n }\n }\n\n // Testing section\n if (data.hasTesting) {\n lines.push(\"\");\n lines.push(\"## Testing\");\n if (data.testRunner) lines.push(`- Test runner: ${data.testRunner}`);\n for (const entry of data.testingConventions) {\n lines.push(`- ${entry.pattern}`);\n }\n }\n\n // Project Structure section\n if (data.hasProjectStructure) {\n lines.push(\"\");\n lines.push(\"## Project Structure\");\n if (data.architecture.pattern) {\n lines.push(`- Architecture: ${data.architecture.pattern}`);\n }\n if (data.architecture.layers && data.architecture.layers.length > 0) {\n lines.push(`- Layers: ${data.architecture.layers.join(\", \")}`);\n }\n }\n\n // Code Style section\n if (data.hasCodeStyle) {\n lines.push(\"\");\n lines.push(\"## Code Style\");\n for (const entry of data.namingConventions) {\n lines.push(`- **naming**: ${entry.pattern}`);\n }\n for (const entry of data.importConventions) {\n lines.push(`- **imports**: ${entry.pattern}`);\n }\n }\n\n // Git Workflow section (optional)\n if (data.gitConventions.length > 0) {\n lines.push(\"\");\n lines.push(\"## Git Workflow\");\n for (const entry of data.gitConventions) {\n lines.push(`- ${entry.pattern}`);\n }\n }\n\n // Boundaries section (always present)\n lines.push(\"\");\n lines.push(\"## Boundaries\");\n lines.push(\"- Do not modify auto-generated sections between ez-context markers\");\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Cursor MDC rule file (.cursor/rules/ez-context.mdc).\n *\n * Format: YAML frontmatter + markdown body.\n * - description: shown in Cursor UI\n * - globs: empty string (not null/omitted) per Cursor docs\n * - alwaysApply: true ensures conventions are always in context\n */\nexport function renderCursorMdc(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const frontmatter = yaml\n .dump({\n description: \"Project conventions extracted by ez-context\",\n globs: \"\",\n alwaysApply: true,\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line added by renderConventionsBody\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a GitHub Copilot instructions file (.github/copilot-instructions.md).\n *\n * Format: Plain markdown, no YAML frontmatter.\n * GitHub Copilot reads the entire file; HTML comment markers are used\n * for idempotent updates via writeWithMarkers.\n */\nexport function renderCopilotMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const lines: string[] = [];\n\n lines.push(\"<!-- Generated by ez-context. Do not edit between markers. -->\");\n lines.push(\"\");\n lines.push(\"# Copilot Instructions\");\n lines.push(\"\");\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n lines.push(...bodyLines);\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a SKILL.md module file (.skills/ez-context/SKILL.md).\n *\n * Format: YAML frontmatter + markdown body.\n * - name: must match directory name (ez-context)\n * - description: max 1024 chars, describes what AND when to use\n * Body stays under 5000 tokens (~3750 words) as per SKILL.md spec.\n */\nexport function renderSkillMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const description =\n \"Project conventions and coding standards for this codebase. \" +\n \"Use when writing new code, reviewing patterns, or understanding project architecture.\";\n\n const frontmatter = yaml\n .dump({\n name: \"ez-context\",\n description,\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import yaml from \"js-yaml\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Rulesync rule file (.rulesync/rules/ez-context.md).\n *\n * Format: YAML frontmatter + markdown body.\n * - targets: specifies which AI tools receive this rule\n * ez-context writes INTO .rulesync/rules/; Rulesync distributes to tools.\n */\nexport function renderRulesyncMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const frontmatter = yaml\n .dump({\n description: \"Project conventions extracted by ez-context\",\n targets: [\"cursor\", \"copilot\", \"windsurf\"],\n })\n .trimEnd();\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n const body = bodyLines.join(\"\\n\");\n\n return `---\\n${frontmatter}\\n---\\n\\n${body}\\n`;\n}\n","import type { ConventionRegistry } from \"../core/schema.js\";\nimport { renderConventionsBody } from \"./render-helpers.js\";\n\n/**\n * Render a Ruler rule file (.ruler/ez-context.md).\n *\n * Format: Plain markdown, no YAML frontmatter.\n * Ruler recursively discovers all .md files in .ruler/ and distributes them.\n * ez-context writes a single .ruler/ez-context.md as an additive conventions file.\n */\nexport function renderRulerMd(\n registry: ConventionRegistry,\n confidenceThreshold: number\n): string {\n const lines: string[] = [];\n\n lines.push(\"# Project Conventions (ez-context)\");\n lines.push(\"\");\n\n const bodyLines = renderConventionsBody(registry, confidenceThreshold);\n // Remove trailing empty line\n while (bodyLines.length > 0 && bodyLines[bodyLines.length - 1] === \"\") {\n bodyLines.pop();\n }\n lines.push(...bodyLines);\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","import path from \"node:path\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport type { ConventionRegistry } from \"../core/schema.js\";\nimport type { EmitOptions, EmitResult, OutputFormat } from \"./types.js\";\nimport { writeWithMarkers } from \"./writer.js\";\nimport { renderClaudeMd } from \"./claude-md.js\";\nimport { renderAgentsMd } from \"./agents-md.js\";\nimport { renderCursorMdc } from \"./cursor-mdc.js\";\nimport { renderCopilotMd } from \"./copilot-md.js\";\nimport { renderSkillMd } from \"./skill-md.js\";\nimport { renderRulesyncMd } from \"./rulesync-md.js\";\nimport { renderRulerMd } from \"./ruler-md.js\";\n\nexport { renderClaudeMd } from \"./claude-md.js\";\nexport { renderAgentsMd } from \"./agents-md.js\";\nexport { renderCursorMdc } from \"./cursor-mdc.js\";\nexport { renderCopilotMd } from \"./copilot-md.js\";\nexport { renderSkillMd } from \"./skill-md.js\";\nexport { renderRulesyncMd } from \"./rulesync-md.js\";\nexport { renderRulerMd } from \"./ruler-md.js\";\nexport type { OutputFormat } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Format emitter registry\n// ---------------------------------------------------------------------------\n\ntype WriteStrategy = \"markers\" | \"direct\";\n\ninterface FormatEmitterEntry {\n render: (registry: ConventionRegistry, threshold: number) => string;\n filename: string;\n strategy: WriteStrategy;\n}\n\nexport const FORMAT_EMITTER_MAP: Record<OutputFormat, FormatEmitterEntry> = {\n claude: {\n render: renderClaudeMd,\n filename: \"CLAUDE.md\",\n strategy: \"markers\",\n },\n agents: {\n render: renderAgentsMd,\n filename: \"AGENTS.md\",\n strategy: \"markers\",\n },\n cursor: {\n render: renderCursorMdc,\n filename: path.join(\".cursor\", \"rules\", \"ez-context.mdc\"),\n strategy: \"direct\",\n },\n copilot: {\n render: renderCopilotMd,\n filename: path.join(\".github\", \"copilot-instructions.md\"),\n strategy: \"markers\",\n },\n skills: {\n render: renderSkillMd,\n filename: path.join(\".skills\", \"ez-context\", \"SKILL.md\"),\n strategy: \"direct\",\n },\n rulesync: {\n render: renderRulesyncMd,\n filename: path.join(\".rulesync\", \"rules\", \"ez-context.md\"),\n strategy: \"markers\",\n },\n ruler: {\n render: renderRulerMd,\n filename: path.join(\".ruler\", \"ez-context.md\"),\n strategy: \"direct\",\n },\n};\n\n// ---------------------------------------------------------------------------\n// emit()\n// ---------------------------------------------------------------------------\n\n/**\n * Emit output files for the given ConventionRegistry.\n *\n * Defaults to [\"claude\", \"agents\"] for backward compatibility.\n * In dryRun mode, returns rendered content without writing any files.\n */\nexport async function emit(\n registry: ConventionRegistry,\n options: EmitOptions\n): Promise<EmitResult> {\n const threshold = options.confidenceThreshold ?? 0.7;\n const formats: OutputFormat[] = options.formats ?? [\"claude\", \"agents\"];\n\n // Render all requested formats\n const rendered: Record<string, string> = {};\n for (const format of formats) {\n const entry = FORMAT_EMITTER_MAP[format];\n rendered[format] = entry.render(registry, threshold);\n }\n\n // Backward compat aliases\n const claudeMd = rendered[\"claude\"] ?? \"\";\n const agentsMd = rendered[\"agents\"] ?? \"\";\n\n if (options.dryRun) {\n return { rendered, claudeMd, agentsMd, filesWritten: [] };\n }\n\n // Write files\n const filesWritten: string[] = [];\n for (const format of formats) {\n const entry = FORMAT_EMITTER_MAP[format];\n const filePath = path.join(options.outputDir, entry.filename);\n\n await mkdir(path.dirname(filePath), { recursive: true });\n if (entry.strategy === \"direct\") {\n await writeFile(filePath, rendered[format]!, \"utf-8\");\n } else {\n await writeWithMarkers(filePath, rendered[format]!);\n }\n\n filesWritten.push(filePath);\n }\n\n return { rendered, claudeMd, agentsMd, filesWritten };\n}\n"],"mappings":"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"}