@directive-run/knowledge 1.20.2 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,16 +1,16 @@
1
- 'use strict';var fs=require('fs'),path=require('path'),url=require('url');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var L=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),P=path.resolve(L,".."),a=null;function k(){let t=[path.join(P,"core","anti-patterns.md"),path.join(P,"..","core","anti-patterns.md")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function z(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}function K(t){let e=t.toLowerCase();return /schema|builder/.test(e)?"schema":/constraint|cross-?module|require/.test(e)?"constraint":/resolver|settle|start/.test(e)?"resolver":/deriv|passthrough/.test(e)?"derivation":/effect/.test(e)?"effect":/usedirective|react|hook/.test(e)?"react":/import|bracket|deep import|name|context|abbreviat/.test(e)?"naming":("module")}function G(t){let e=t.toLowerCase();return /nonexistent|missing|no error|deep import|async logic/.test(e)?"error":"warning"}function U(t){let e=t.split(`
2
- `),r=[],n=null,o=/^##\s+(\d+)\.\s+(.+?)\s*$/;for(let s of e){let i=o.exec(s);if(i?.[1]&&i?.[2]){n&&r.push(n),n={number:Number(i[1]),title:i[2],body:""};continue}if(n){if(/^##\s+\D/.test(s)){r.push(n),n=null;break}n.body+=`${s}
1
+ 'use strict';var fs=require('fs'),path=require('path'),url=require('url');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var K=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),A=path.resolve(K,".."),l=null;function L(){let t=[path.join(A,"core","anti-patterns.md"),path.join(A,"..","core","anti-patterns.md")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function k(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}function z(t){let e=t.toLowerCase();return /schema|builder/.test(e)?"schema":/constraint|cross-?module|require/.test(e)?"constraint":/resolver|settle|start/.test(e)?"resolver":/deriv|passthrough/.test(e)?"derivation":/effect/.test(e)?"effect":/usedirective|react|hook/.test(e)?"react":/import|bracket|deep import|name|context|abbreviat/.test(e)?"naming":("module")}function G(t){let e=t.toLowerCase();return /nonexistent|missing|no error|deep import|async logic/.test(e)?"error":"warning"}function U(t){let e=t.split(`
2
+ `),r=[],n=null,o=/^##\s+(\d+)\.\s+(.+?)\s*$/;for(let c of e){let a=o.exec(c);if(a?.[1]&&a?.[2]){n&&r.push(n),n={number:Number(a[1]),title:a[2],body:""};continue}if(n){if(/^##\s+\D/.test(c)){r.push(n),n=null;break}n.body+=`${c}
3
3
  `;}}return n&&r.push(n),r}function $(t){let e=t.match(/```typescript\n([\s\S]*?)```/),r=[];for(let p of t.split(`
4
4
  `)){if(p.startsWith("```"))break;r.push(p);}let n=r.join(`
5
- `).trim();if(!e?.[1])return {explanation:n};let o=e[1],s=o.match(/\/\/\s*WRONG[^\n]*\n([\s\S]*?)(?:\/\/\s*CORRECT|$)/),i=o.match(/\/\/\s*CORRECT[^\n]*\n([\s\S]*)/);return {explanation:n,badExample:s?.[1]?.trim()??void 0,goodExample:i?.[1]?.trim()??void 0}}function h(){if(a)return a;let t=k(),e;try{e=fs.readFileSync(t,"utf-8");}catch{return a=Object.freeze([]),a}let n=U(e).map(o=>{let{explanation:s,badExample:i,goodExample:p}=$(o.body);return {id:z(o.title),number:o.number,title:o.title,severity:G(o.title),category:K(o.title),explanation:s,badExample:i,goodExample:p}});return a=Object.freeze(n),a}function D(){return h()}function B(t){return h().find(e=>e.id===t)}function W(){a=null;}var V=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),C=path.resolve(V,".."),R=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[path.join(C,"migration.json"),path.join(C,"..","migration.json")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function S(){if(u)return u;try{let t=fs.readFileSync(Y(),"utf-8"),e=JSON.parse(t);u=Object.freeze(e.sources??[]);}catch{u=Object.freeze([]);}return u}function Z(){return R}function tt(){return S()}function et(t){return S().find(e=>e.id===t)}function nt(){u=null;}var ct=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),E=path.resolve(ct,".."),g=null;function lt(){let t=[path.join(E,"compositions.json"),path.join(E,"..","compositions.json")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function m(){if(g)return g;try{let t=fs.readFileSync(lt(),"utf-8"),e=JSON.parse(t);g=Object.freeze(e.edges??[]);}catch{g=Object.freeze([]);}return g}function ut(){return m()}function gt(t){return m().filter(e=>e.from===t)}function pt(t){return m().filter(e=>e.to===t)}function ft(){g=null;}var Pt=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),v=path.resolve(Pt,"..");function f(t){let e=path.join(v,t);if(fs.existsSync(e))return e;let r=path.join(v,"..",t);return fs.existsSync(r)?r:e}var ht=f("core"),At=f("ai"),Ct=f("examples"),Rt=f("api-skeleton.md"),c=null,l=null;function y(t,e){try{let r=fs.readdirSync(t).filter(n=>n.endsWith(".md")||n.endsWith(".ts"));for(let n of r){let o=n.replace(/\.(md|ts)$/,"");e.set(o,fs.readFileSync(path.join(t,n),"utf-8"));}}catch(r){if(r.code!=="ENOENT")throw r}}function w(){let t=new Map;y(ht,t),y(At,t);try{t.set("api-skeleton",fs.readFileSync(Rt,"utf-8"));}catch{}return t}function _(){let t=new Map;return y(Ct,t),t}function St(t){return c||(c=w()),c.get(t)??""}function Gt(){return c||(c=w()),c}function Mt(t){return l||(l=_()),l.get(t)??""}function Ut(){return l||(l=_()),l}function $t(t){return t.map(e=>St(e)).filter(Boolean).join(`
5
+ `).trim();if(!e?.[1])return {explanation:n};let o=e[1],c=o.match(/\/\/\s*WRONG[^\n]*\n([\s\S]*?)(?:\/\/\s*CORRECT|$)/),a=o.match(/\/\/\s*CORRECT[^\n]*\n([\s\S]*)/);return {explanation:n,badExample:c?.[1]?.trim()??void 0,goodExample:a?.[1]?.trim()??void 0}}function C(){if(l)return l;let t=L(),e;try{e=fs.readFileSync(t,"utf-8");}catch{return l=Object.freeze([]),l}let n=U(e).map(o=>{let{explanation:c,badExample:a,goodExample:p}=$(o.body);return {id:k(o.title),number:o.number,title:o.title,severity:G(o.title),category:z(o.title),explanation:c,badExample:a,goodExample:p}});return l=Object.freeze(n),l}function D(){return C()}function B(t){return C().find(e=>e.id===t)}function W(){l=null;}var V=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),S=path.resolve(V,".."),M=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[path.join(S,"migration.json"),path.join(S,"..","migration.json")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function E(){if(u)return u;try{let t=fs.readFileSync(Y(),"utf-8"),e=JSON.parse(t);u=Object.freeze(e.sources??[]);}catch{u=Object.freeze([]);}return u}function Z(){return M}function tt(){return E()}function et(t){return E().find(e=>e.id===t)}function nt(){u=null;}var ct=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),v=path.resolve(ct,".."),g=null;function lt(){let t=[path.join(v,"compositions.json"),path.join(v,"..","compositions.json")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function m(){if(g)return g;try{let t=fs.readFileSync(lt(),"utf-8"),e=JSON.parse(t);g=Object.freeze(e.edges??[]);}catch{g=Object.freeze([]);}return g}function ut(){return m()}function gt(t){return m().filter(e=>e.from===t)}function pt(t){return m().filter(e=>e.to===t)}function ft(){g=null;}var ht=path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))),w=path.resolve(ht,"..");function f(t){let e=path.join(w,t);if(fs.existsSync(e))return e;let r=path.join(w,"..",t);return fs.existsSync(r)?r:e}var Pt=f("core"),At=f("ai"),Ct=f("examples"),Rt=f("api-skeleton.md"),i=null,s=null;function y(t,e){try{let r=fs.readdirSync(t).filter(n=>n.endsWith(".md")||n.endsWith(".ts"));for(let n of r){let o=n.replace(/\.(md|ts)$/,"");e.set(o,fs.readFileSync(path.join(t,n),"utf-8"));}}catch(r){if(r.code!=="ENOENT")throw r}}function x(){let t=new Map;y(Pt,t),y(At,t);try{t.set("api-skeleton",fs.readFileSync(Rt,"utf-8"));}catch{}return t}function h(){let t=new Map;return y(Ct,t),t}function St(t){return i||(i=x()),i.get(t)??""}function Gt(){return i||(i=x()),i}function Ut(t){return i||(i=x()),i.has(t)}function Mt(t){return s||(s=h()),s.get(t)??""}function $t(t){return s||(s=h()),s.has(t)}function Dt(){return s||(s=h()),s}function Bt(t){return t.map(e=>St(e)).filter(Boolean).join(`
6
6
 
7
7
  ---
8
8
 
9
- `)}function Dt(t){return t.map(e=>{let r=Mt(e);return r?`### Example: ${e}
9
+ `)}function Wt(t){return t.map(e=>{let r=Mt(e);return r?`### Example: ${e}
10
10
 
11
11
  \`\`\`typescript
12
12
  ${r}
13
13
  \`\`\``:""}).filter(Boolean).join(`
14
14
 
15
- `)}function Bt(){c=null,l=null;}exports.MIGRATION_SOURCES=R;exports.clearAntiPatternCache=W;exports.clearCache=Bt;exports.clearCompositionsCache=ft;exports.clearMigrationCache=nt;exports.getAllExamples=Ut;exports.getAllKnowledge=Gt;exports.getAntiPatternById=B;exports.getAntiPatterns=D;exports.getCompositions=ut;exports.getCompositionsFor=gt;exports.getExample=Mt;exports.getExampleFiles=Dt;exports.getKnowledge=St;exports.getKnowledgeFiles=$t;exports.getMigrationPattern=et;exports.getMigrationPatterns=tt;exports.getMigrationSources=Z;exports.getReverseCompositionsFor=pt;//# sourceMappingURL=index.cjs.map
15
+ `)}function Jt(){i=null,s=null;}exports.MIGRATION_SOURCES=M;exports.clearAntiPatternCache=W;exports.clearCache=Jt;exports.clearCompositionsCache=ft;exports.clearMigrationCache=nt;exports.getAllExamples=Dt;exports.getAllKnowledge=Gt;exports.getAntiPatternById=B;exports.getAntiPatterns=D;exports.getCompositions=ut;exports.getCompositionsFor=gt;exports.getExample=Mt;exports.getExampleFiles=Wt;exports.getKnowledge=St;exports.getKnowledgeFiles=Bt;exports.getMigrationPattern=et;exports.getMigrationPatterns=tt;exports.getMigrationSources=Z;exports.getReverseCompositionsFor=pt;exports.hasExample=$t;exports.hasKnowledge=Ut;//# sourceMappingURL=index.cjs.map
16
16
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parsers/anti-patterns.ts","../src/parsers/migration.ts","../src/parsers/compositions.ts","../src/index.ts"],"names":["__dirname","dirname","fileURLToPath","PKG_ROOT","resolve","cache","resolveSourcePath","candidates","join","c","existsSync","slugify","title","categorize","lower","severityFor","splitSections","md","lines","sections","current","heading","line","match","extractExamples","body","codeBlock","explanationLines","explanation","code","wrongMatch","correctMatch","loadAntiPatterns","sourcePath","readFileSync","out","section","badExample","goodExample","getAntiPatterns","getAntiPatternById","id","ap","clearAntiPatternCache","MIGRATION_SOURCES","load","raw","parsed","getMigrationSources","getMigrationPatterns","getMigrationPattern","source","p","clearMigrationCache","getCompositions","getCompositionsFor","packageName","getReverseCompositionsFor","clearCompositionsCache","resolveAsset","name","fromDist","fromSrc","CORE_DIR","AI_DIR","EXAMPLES_DIR","API_SKELETON_PATH","knowledgeCache","exampleCache","loadDir","dir","map","files","readdirSync","f","file","err","loadAllKnowledge","loadAllExamples","getKnowledge","getAllKnowledge","getExample","getAllExamples","getKnowledgeFiles","names","getExampleFiles","content","clearCache"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Parser for `packages/knowledge/core/anti-patterns.md` → structured\n * `AntiPattern[]` data. Lazy + cached so the cost is paid once per\n * process at first call.\n *\n * The source markdown is organized as numbered sections (`## N. Title`)\n * each containing a TypeScript code block with `// WRONG` and\n * `// CORRECT` examples. Some sections include prose between the\n * heading and the code block — captured as `explanation`.\n *\n * IDs are kebab-cased slugs derived from the heading text; stable\n * across releases as long as the heading isn't renamed.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport type AntiPatternSeverity = \"error\" | \"warning\" | \"info\";\nexport type AntiPatternCategory =\n | \"module\"\n | \"schema\"\n | \"constraint\"\n | \"resolver\"\n | \"derivation\"\n | \"effect\"\n | \"naming\"\n | \"react\"\n | \"composition\";\n\nexport interface AntiPattern {\n /** Stable slug, derived from the heading text. */\n id: string;\n /** Section number in the source markdown (1..N). */\n number: number;\n /** Human-readable title (the heading text minus the number prefix). */\n title: string;\n /** Default severity. Heuristic; tunable per-rule later. */\n severity: AntiPatternSeverity;\n /** Heuristic category from title keywords. */\n category: AntiPatternCategory;\n /** Body prose between heading and the first code block (often empty). */\n explanation: string;\n /** The `// WRONG` example, if present. */\n badExample?: string;\n /** The `// CORRECT` example, if present. */\n goodExample?: string;\n}\n\nlet cache: ReadonlyArray<AntiPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"core\", \"anti-patterns.md\"),\n join(PKG_ROOT, \"..\", \"core\", \"anti-patterns.md\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n}\n\nfunction categorize(title: string): AntiPatternCategory {\n const lower = title.toLowerCase();\n if (/schema|builder/.test(lower)) {\n return \"schema\";\n }\n if (/constraint|cross-?module|require/.test(lower)) {\n return \"constraint\";\n }\n if (/resolver|settle|start/.test(lower)) {\n return \"resolver\";\n }\n if (/deriv|passthrough/.test(lower)) {\n return \"derivation\";\n }\n if (/effect/.test(lower)) {\n return \"effect\";\n }\n if (/usedirective|react|hook/.test(lower)) {\n return \"react\";\n }\n if (/import|bracket|deep import|name|context|abbreviat/.test(lower)) {\n return \"naming\";\n }\n if (/init|module|config/.test(lower)) {\n return \"module\";\n }\n return \"module\";\n}\n\nfunction severityFor(title: string): AntiPatternSeverity {\n const lower = title.toLowerCase();\n if (/nonexistent|missing|no error|deep import|async logic/.test(lower)) {\n return \"error\";\n }\n return \"warning\";\n}\n\ninterface Section {\n number: number;\n title: string;\n body: string;\n}\n\nfunction splitSections(md: string): Section[] {\n const lines = md.split(\"\\n\");\n const sections: Section[] = [];\n let current: Section | null = null;\n const heading = /^##\\s+(\\d+)\\.\\s+(.+?)\\s*$/;\n for (const line of lines) {\n const match = heading.exec(line);\n if (match?.[1] && match?.[2]) {\n if (current) {\n sections.push(current);\n }\n current = {\n number: Number(match[1]),\n title: match[2],\n body: \"\",\n };\n continue;\n }\n if (current) {\n // Stop at the first non-numbered ## section (e.g. \"Quick Reference Checklist\")\n if (/^##\\s+\\D/.test(line)) {\n sections.push(current);\n current = null;\n break;\n }\n current.body += `${line}\\n`;\n }\n }\n if (current) {\n sections.push(current);\n }\n return sections;\n}\n\nfunction extractExamples(body: string): {\n explanation: string;\n badExample?: string;\n goodExample?: string;\n} {\n const codeBlock = body.match(/```typescript\\n([\\s\\S]*?)```/);\n const explanationLines: string[] = [];\n for (const line of body.split(\"\\n\")) {\n if (line.startsWith(\"```\")) {\n break;\n }\n explanationLines.push(line);\n }\n const explanation = explanationLines.join(\"\\n\").trim();\n\n if (!codeBlock?.[1]) {\n return { explanation };\n }\n\n const code = codeBlock[1];\n // Split on the WRONG/CORRECT comment markers.\n const wrongMatch = code.match(\n /\\/\\/\\s*WRONG[^\\n]*\\n([\\s\\S]*?)(?:\\/\\/\\s*CORRECT|$)/,\n );\n const correctMatch = code.match(/\\/\\/\\s*CORRECT[^\\n]*\\n([\\s\\S]*)/);\n\n return {\n explanation,\n badExample: wrongMatch?.[1]?.trim() ?? undefined,\n goodExample: correctMatch?.[1]?.trim() ?? undefined,\n };\n}\n\nfunction loadAntiPatterns(): ReadonlyArray<AntiPattern> {\n if (cache) {\n return cache;\n }\n\n const sourcePath = resolveSourcePath();\n let md: string;\n try {\n md = readFileSync(sourcePath, \"utf-8\");\n } catch {\n cache = Object.freeze([]);\n return cache;\n }\n\n const sections = splitSections(md);\n const out: AntiPattern[] = sections.map((section) => {\n const { explanation, badExample, goodExample } = extractExamples(\n section.body,\n );\n return {\n id: slugify(section.title),\n number: section.number,\n title: section.title,\n severity: severityFor(section.title),\n category: categorize(section.title),\n explanation,\n badExample,\n goodExample,\n };\n });\n\n cache = Object.freeze(out);\n return cache;\n}\n\n/** Return every parsed anti-pattern, stable order, frozen. */\nexport function getAntiPatterns(): ReadonlyArray<AntiPattern> {\n return loadAntiPatterns();\n}\n\n/** Look up one anti-pattern by its slug id. */\nexport function getAntiPatternById(id: string): AntiPattern | undefined {\n return loadAntiPatterns().find((ap) => ap.id === id);\n}\n\n/** Clear the in-memory cache. Test / watch-mode helper. */\nexport function clearAntiPatternCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/migration.json` → structured\n * migration patterns. Lazy + cached.\n *\n * The JSON ships in the published tarball; consumers don't need to\n * parse markdown at runtime.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/** Supported source-library identifiers. */\nexport const MIGRATION_SOURCES = [\n \"redux\",\n \"zustand\",\n \"xstate\",\n \"mobx\",\n \"jotai\",\n \"recoil\",\n] as const;\nexport type MigrationSourceId = (typeof MIGRATION_SOURCES)[number];\n\nexport interface MigrationConceptRow {\n from: string;\n to: string;\n note: string;\n}\n\nexport interface MigrationPattern {\n id: MigrationSourceId;\n name: string;\n conceptMap: MigrationConceptRow[];\n steps: string[];\n before: string;\n after: string;\n}\n\ninterface MigrationFile {\n version: number;\n sources: MigrationPattern[];\n}\n\nlet cache: ReadonlyArray<MigrationPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"migration.json\"),\n join(PKG_ROOT, \"..\", \"migration.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<MigrationPattern> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as MigrationFile;\n cache = Object.freeze(parsed.sources ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All supported source library IDs. */\nexport function getMigrationSources(): ReadonlyArray<MigrationSourceId> {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): ReadonlyArray<MigrationPattern> {\n return load();\n}\n\n/** One migration pattern by its source-library id. */\nexport function getMigrationPattern(\n source: string,\n): MigrationPattern | undefined {\n return load().find((p) => p.id === source);\n}\n\n/** Test / watch-mode helper. */\nexport function clearMigrationCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/compositions.json` → typed\n * composition graph. Lazy + cached.\n *\n * The JSON ships in the published tarball. Adjacency list rather\n * than per-package projections so consumers can answer both\n * \"what does X compose with?\" and \"what composes with X?\" without\n * duplicate data.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// After bundling, all parsers live in dist/index.js — one level up\n// from dist reaches the package root. In src/ during dev, the file is\n// two levels up; the fallback in `resolveSourcePath` handles that.\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport interface CompositionEdge {\n from: string;\n to: string;\n reason: string;\n}\n\ninterface CompositionsFile {\n version: number;\n edges: CompositionEdge[];\n}\n\nlet cache: ReadonlyArray<CompositionEdge> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"compositions.json\"),\n join(PKG_ROOT, \"..\", \"compositions.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<CompositionEdge> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as CompositionsFile;\n cache = Object.freeze(parsed.edges ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All composition edges as a flat list. */\nexport function getCompositions(): ReadonlyArray<CompositionEdge> {\n return load();\n}\n\n/**\n * All edges originating at the given package. Returns an empty array\n * when the package is unknown or has no outgoing compositions.\n */\nexport function getCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.from === packageName);\n}\n\n/**\n * All edges arriving at the given package — \"who composes WITH me?\"\n */\nexport function getReverseCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.to === packageName);\n}\n\n/** Test / watch-mode helper. */\nexport function clearCompositionsCache(): void {\n cache = null;\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n\n// ---------------------------------------------------------------------------\n// Structured data APIs (v1.16.0 — back the MCP `list_review_rules`,\n// `get_review_rule`, `list_migration_sources`, `get_migration_pattern`,\n// `get_composable_packages` tools).\n// ---------------------------------------------------------------------------\n\nexport {\n type AntiPattern,\n type AntiPatternCategory,\n type AntiPatternSeverity,\n clearAntiPatternCache,\n getAntiPatternById,\n getAntiPatterns,\n} from \"./parsers/anti-patterns.js\";\n\nexport {\n type MigrationConceptRow,\n type MigrationPattern,\n type MigrationSourceId,\n MIGRATION_SOURCES,\n clearMigrationCache,\n getMigrationPattern,\n getMigrationPatterns,\n getMigrationSources,\n} from \"./parsers/migration.js\";\n\nexport {\n type CompositionEdge,\n clearCompositionsCache,\n getCompositions,\n getCompositionsFor,\n getReverseCompositionsFor,\n} from \"./parsers/compositions.js\";\n"]}
1
+ {"version":3,"sources":["../src/parsers/anti-patterns.ts","../src/parsers/migration.ts","../src/parsers/compositions.ts","../src/index.ts"],"names":["__dirname","dirname","fileURLToPath","PKG_ROOT","resolve","cache","resolveSourcePath","candidates","join","c","existsSync","slugify","title","categorize","lower","severityFor","splitSections","md","lines","sections","current","heading","line","match","extractExamples","body","codeBlock","explanationLines","explanation","code","wrongMatch","correctMatch","loadAntiPatterns","sourcePath","readFileSync","out","section","badExample","goodExample","getAntiPatterns","getAntiPatternById","id","ap","clearAntiPatternCache","MIGRATION_SOURCES","load","raw","parsed","getMigrationSources","getMigrationPatterns","getMigrationPattern","source","p","clearMigrationCache","getCompositions","getCompositionsFor","packageName","getReverseCompositionsFor","clearCompositionsCache","resolveAsset","name","fromDist","fromSrc","CORE_DIR","AI_DIR","EXAMPLES_DIR","API_SKELETON_PATH","knowledgeCache","exampleCache","loadDir","dir","map","files","readdirSync","f","file","err","loadAllKnowledge","loadAllExamples","getKnowledge","getAllKnowledge","hasKnowledge","getExample","hasExample","getAllExamples","getKnowledgeFiles","names","getExampleFiles","content","clearCache"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Parser for `packages/knowledge/core/anti-patterns.md` → structured\n * `AntiPattern[]` data. Lazy + cached so the cost is paid once per\n * process at first call.\n *\n * The source markdown is organized as numbered sections (`## N. Title`)\n * each containing a TypeScript code block with `// WRONG` and\n * `// CORRECT` examples. Some sections include prose between the\n * heading and the code block — captured as `explanation`.\n *\n * IDs are kebab-cased slugs derived from the heading text; stable\n * across releases as long as the heading isn't renamed.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport type AntiPatternSeverity = \"error\" | \"warning\" | \"info\";\nexport type AntiPatternCategory =\n | \"module\"\n | \"schema\"\n | \"constraint\"\n | \"resolver\"\n | \"derivation\"\n | \"effect\"\n | \"naming\"\n | \"react\"\n | \"composition\";\n\nexport interface AntiPattern {\n /** Stable slug, derived from the heading text. */\n id: string;\n /** Section number in the source markdown (1..N). */\n number: number;\n /** Human-readable title (the heading text minus the number prefix). */\n title: string;\n /** Default severity. Heuristic; tunable per-rule later. */\n severity: AntiPatternSeverity;\n /** Heuristic category from title keywords. */\n category: AntiPatternCategory;\n /** Body prose between heading and the first code block (often empty). */\n explanation: string;\n /** The `// WRONG` example, if present. */\n badExample?: string;\n /** The `// CORRECT` example, if present. */\n goodExample?: string;\n}\n\nlet cache: ReadonlyArray<AntiPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"core\", \"anti-patterns.md\"),\n join(PKG_ROOT, \"..\", \"core\", \"anti-patterns.md\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n}\n\nfunction categorize(title: string): AntiPatternCategory {\n const lower = title.toLowerCase();\n if (/schema|builder/.test(lower)) {\n return \"schema\";\n }\n if (/constraint|cross-?module|require/.test(lower)) {\n return \"constraint\";\n }\n if (/resolver|settle|start/.test(lower)) {\n return \"resolver\";\n }\n if (/deriv|passthrough/.test(lower)) {\n return \"derivation\";\n }\n if (/effect/.test(lower)) {\n return \"effect\";\n }\n if (/usedirective|react|hook/.test(lower)) {\n return \"react\";\n }\n if (/import|bracket|deep import|name|context|abbreviat/.test(lower)) {\n return \"naming\";\n }\n if (/init|module|config/.test(lower)) {\n return \"module\";\n }\n return \"module\";\n}\n\nfunction severityFor(title: string): AntiPatternSeverity {\n const lower = title.toLowerCase();\n if (/nonexistent|missing|no error|deep import|async logic/.test(lower)) {\n return \"error\";\n }\n return \"warning\";\n}\n\ninterface Section {\n number: number;\n title: string;\n body: string;\n}\n\nfunction splitSections(md: string): Section[] {\n const lines = md.split(\"\\n\");\n const sections: Section[] = [];\n let current: Section | null = null;\n const heading = /^##\\s+(\\d+)\\.\\s+(.+?)\\s*$/;\n for (const line of lines) {\n const match = heading.exec(line);\n if (match?.[1] && match?.[2]) {\n if (current) {\n sections.push(current);\n }\n current = {\n number: Number(match[1]),\n title: match[2],\n body: \"\",\n };\n continue;\n }\n if (current) {\n // Stop at the first non-numbered ## section (e.g. \"Quick Reference Checklist\")\n if (/^##\\s+\\D/.test(line)) {\n sections.push(current);\n current = null;\n break;\n }\n current.body += `${line}\\n`;\n }\n }\n if (current) {\n sections.push(current);\n }\n return sections;\n}\n\nfunction extractExamples(body: string): {\n explanation: string;\n badExample?: string;\n goodExample?: string;\n} {\n const codeBlock = body.match(/```typescript\\n([\\s\\S]*?)```/);\n const explanationLines: string[] = [];\n for (const line of body.split(\"\\n\")) {\n if (line.startsWith(\"```\")) {\n break;\n }\n explanationLines.push(line);\n }\n const explanation = explanationLines.join(\"\\n\").trim();\n\n if (!codeBlock?.[1]) {\n return { explanation };\n }\n\n const code = codeBlock[1];\n // Split on the WRONG/CORRECT comment markers.\n const wrongMatch = code.match(\n /\\/\\/\\s*WRONG[^\\n]*\\n([\\s\\S]*?)(?:\\/\\/\\s*CORRECT|$)/,\n );\n const correctMatch = code.match(/\\/\\/\\s*CORRECT[^\\n]*\\n([\\s\\S]*)/);\n\n return {\n explanation,\n badExample: wrongMatch?.[1]?.trim() ?? undefined,\n goodExample: correctMatch?.[1]?.trim() ?? undefined,\n };\n}\n\nfunction loadAntiPatterns(): ReadonlyArray<AntiPattern> {\n if (cache) {\n return cache;\n }\n\n const sourcePath = resolveSourcePath();\n let md: string;\n try {\n md = readFileSync(sourcePath, \"utf-8\");\n } catch {\n cache = Object.freeze([]);\n return cache;\n }\n\n const sections = splitSections(md);\n const out: AntiPattern[] = sections.map((section) => {\n const { explanation, badExample, goodExample } = extractExamples(\n section.body,\n );\n return {\n id: slugify(section.title),\n number: section.number,\n title: section.title,\n severity: severityFor(section.title),\n category: categorize(section.title),\n explanation,\n badExample,\n goodExample,\n };\n });\n\n cache = Object.freeze(out);\n return cache;\n}\n\n/** Return every parsed anti-pattern, stable order, frozen. */\nexport function getAntiPatterns(): ReadonlyArray<AntiPattern> {\n return loadAntiPatterns();\n}\n\n/** Look up one anti-pattern by its slug id. */\nexport function getAntiPatternById(id: string): AntiPattern | undefined {\n return loadAntiPatterns().find((ap) => ap.id === id);\n}\n\n/** Clear the in-memory cache. Test / watch-mode helper. */\nexport function clearAntiPatternCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/migration.json` → structured\n * migration patterns. Lazy + cached.\n *\n * The JSON ships in the published tarball; consumers don't need to\n * parse markdown at runtime.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/** Supported source-library identifiers. */\nexport const MIGRATION_SOURCES = [\n \"redux\",\n \"zustand\",\n \"xstate\",\n \"mobx\",\n \"jotai\",\n \"recoil\",\n] as const;\nexport type MigrationSourceId = (typeof MIGRATION_SOURCES)[number];\n\nexport interface MigrationConceptRow {\n from: string;\n to: string;\n note: string;\n}\n\nexport interface MigrationPattern {\n id: MigrationSourceId;\n name: string;\n conceptMap: MigrationConceptRow[];\n steps: string[];\n before: string;\n after: string;\n}\n\ninterface MigrationFile {\n version: number;\n sources: MigrationPattern[];\n}\n\nlet cache: ReadonlyArray<MigrationPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"migration.json\"),\n join(PKG_ROOT, \"..\", \"migration.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<MigrationPattern> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as MigrationFile;\n cache = Object.freeze(parsed.sources ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All supported source library IDs. */\nexport function getMigrationSources(): ReadonlyArray<MigrationSourceId> {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): ReadonlyArray<MigrationPattern> {\n return load();\n}\n\n/** One migration pattern by its source-library id. */\nexport function getMigrationPattern(\n source: string,\n): MigrationPattern | undefined {\n return load().find((p) => p.id === source);\n}\n\n/** Test / watch-mode helper. */\nexport function clearMigrationCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/compositions.json` → typed\n * composition graph. Lazy + cached.\n *\n * The JSON ships in the published tarball. Adjacency list rather\n * than per-package projections so consumers can answer both\n * \"what does X compose with?\" and \"what composes with X?\" without\n * duplicate data.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// After bundling, all parsers live in dist/index.js — one level up\n// from dist reaches the package root. In src/ during dev, the file is\n// two levels up; the fallback in `resolveSourcePath` handles that.\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport interface CompositionEdge {\n from: string;\n to: string;\n reason: string;\n}\n\ninterface CompositionsFile {\n version: number;\n edges: CompositionEdge[];\n}\n\nlet cache: ReadonlyArray<CompositionEdge> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"compositions.json\"),\n join(PKG_ROOT, \"..\", \"compositions.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<CompositionEdge> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as CompositionsFile;\n cache = Object.freeze(parsed.edges ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All composition edges as a flat list. */\nexport function getCompositions(): ReadonlyArray<CompositionEdge> {\n return load();\n}\n\n/**\n * All edges originating at the given package. Returns an empty array\n * when the package is unknown or has no outgoing compositions.\n */\nexport function getCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.from === packageName);\n}\n\n/**\n * All edges arriving at the given package — \"who composes WITH me?\"\n */\nexport function getReverseCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.to === packageName);\n}\n\n/** Test / watch-mode helper. */\nexport function clearCompositionsCache(): void {\n cache = null;\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\n/**\n * Look up a bundled knowledge file by name. Returns the raw markdown\n * string. Returns `\"\"` when the name isn't known — callers driving an\n * LLM should pair this with {@link hasKnowledge} so a typo turns\n * into an actionable error instead of a silently empty prompt.\n *\n * @example\n * ```ts\n * import { getKnowledge, hasKnowledge } from \"@directive-run/knowledge\";\n *\n * if (!hasKnowledge(\"guardrails\")) throw new Error(\"typo\");\n * const md = getKnowledge(\"guardrails\");\n * ```\n */\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\n/**\n * Return every loaded knowledge file as `name → markdown`. Consumers\n * iterating the corpus (full-text search, embedding builder, RAG\n * index) read this once and key off the returned map.\n */\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\n/**\n * `true` when a knowledge file with this exact name is bundled.\n * Use this BEFORE {@link getKnowledge} when the name is user / agent\n * input — `getKnowledge` returns `\"\"` on miss, which is\n * indistinguishable from an intentionally empty file.\n *\n * @example\n * ```ts\n * if (!hasKnowledge(userTyped)) {\n * console.error(`unknown knowledge file: ${userTyped}`);\n * console.error(`available: ${[...getAllKnowledge().keys()].join(\", \")}`);\n * return;\n * }\n * ```\n */\nexport function hasKnowledge(name: string): boolean {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n return knowledgeCache.has(name);\n}\n\n/**\n * Look up a bundled example file by name. Returns the raw source.\n * Returns `\"\"` when the name isn't known — pair with {@link hasExample}\n * when the input is user-controlled.\n */\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\n/**\n * `true` when an example file with this exact name is bundled.\n * The miss-vs-empty disambiguator for {@link getExample}.\n */\nexport function hasExample(name: string): boolean {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n return exampleCache.has(name);\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n\n// ---------------------------------------------------------------------------\n// Structured data APIs (v1.16.0 — back the MCP `list_review_rules`,\n// `get_review_rule`, `list_migration_sources`, `get_migration_pattern`,\n// `get_composable_packages` tools).\n// ---------------------------------------------------------------------------\n\nexport {\n type AntiPattern,\n type AntiPatternCategory,\n type AntiPatternSeverity,\n clearAntiPatternCache,\n getAntiPatternById,\n getAntiPatterns,\n} from \"./parsers/anti-patterns.js\";\n\nexport {\n type MigrationConceptRow,\n type MigrationPattern,\n type MigrationSourceId,\n MIGRATION_SOURCES,\n clearMigrationCache,\n getMigrationPattern,\n getMigrationPatterns,\n getMigrationSources,\n} from \"./parsers/migration.js\";\n\nexport {\n type CompositionEdge,\n clearCompositionsCache,\n getCompositions,\n getCompositionsFor,\n getReverseCompositionsFor,\n} from \"./parsers/compositions.js\";\n"]}
package/dist/index.d.cts CHANGED
@@ -98,13 +98,58 @@ declare function getReverseCompositionsFor(packageName: string): ReadonlyArray<C
98
98
  /** Test / watch-mode helper. */
99
99
  declare function clearCompositionsCache(): void;
100
100
 
101
+ /**
102
+ * Look up a bundled knowledge file by name. Returns the raw markdown
103
+ * string. Returns `""` when the name isn't known — callers driving an
104
+ * LLM should pair this with {@link hasKnowledge} so a typo turns
105
+ * into an actionable error instead of a silently empty prompt.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * import { getKnowledge, hasKnowledge } from "@directive-run/knowledge";
110
+ *
111
+ * if (!hasKnowledge("guardrails")) throw new Error("typo");
112
+ * const md = getKnowledge("guardrails");
113
+ * ```
114
+ */
101
115
  declare function getKnowledge(name: string): string;
116
+ /**
117
+ * Return every loaded knowledge file as `name → markdown`. Consumers
118
+ * iterating the corpus (full-text search, embedding builder, RAG
119
+ * index) read this once and key off the returned map.
120
+ */
102
121
  declare function getAllKnowledge(): ReadonlyMap<string, string>;
122
+ /**
123
+ * `true` when a knowledge file with this exact name is bundled.
124
+ * Use this BEFORE {@link getKnowledge} when the name is user / agent
125
+ * input — `getKnowledge` returns `""` on miss, which is
126
+ * indistinguishable from an intentionally empty file.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * if (!hasKnowledge(userTyped)) {
131
+ * console.error(`unknown knowledge file: ${userTyped}`);
132
+ * console.error(`available: ${[...getAllKnowledge().keys()].join(", ")}`);
133
+ * return;
134
+ * }
135
+ * ```
136
+ */
137
+ declare function hasKnowledge(name: string): boolean;
138
+ /**
139
+ * Look up a bundled example file by name. Returns the raw source.
140
+ * Returns `""` when the name isn't known — pair with {@link hasExample}
141
+ * when the input is user-controlled.
142
+ */
103
143
  declare function getExample(name: string): string;
144
+ /**
145
+ * `true` when an example file with this exact name is bundled.
146
+ * The miss-vs-empty disambiguator for {@link getExample}.
147
+ */
148
+ declare function hasExample(name: string): boolean;
104
149
  declare function getAllExamples(): ReadonlyMap<string, string>;
105
150
  declare function getKnowledgeFiles(names: string[]): string;
106
151
  declare function getExampleFiles(names: string[]): string;
107
152
  /** Clear cached knowledge and examples. Useful for dev/watch mode. */
108
153
  declare function clearCache(): void;
109
154
 
110
- export { type AntiPattern, type AntiPatternCategory, type AntiPatternSeverity, type CompositionEdge, MIGRATION_SOURCES, type MigrationConceptRow, type MigrationPattern, type MigrationSourceId, clearAntiPatternCache, clearCache, clearCompositionsCache, clearMigrationCache, getAllExamples, getAllKnowledge, getAntiPatternById, getAntiPatterns, getCompositions, getCompositionsFor, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles, getMigrationPattern, getMigrationPatterns, getMigrationSources, getReverseCompositionsFor };
155
+ export { type AntiPattern, type AntiPatternCategory, type AntiPatternSeverity, type CompositionEdge, MIGRATION_SOURCES, type MigrationConceptRow, type MigrationPattern, type MigrationSourceId, clearAntiPatternCache, clearCache, clearCompositionsCache, clearMigrationCache, getAllExamples, getAllKnowledge, getAntiPatternById, getAntiPatterns, getCompositions, getCompositionsFor, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles, getMigrationPattern, getMigrationPatterns, getMigrationSources, getReverseCompositionsFor, hasExample, hasKnowledge };
package/dist/index.d.ts CHANGED
@@ -98,13 +98,58 @@ declare function getReverseCompositionsFor(packageName: string): ReadonlyArray<C
98
98
  /** Test / watch-mode helper. */
99
99
  declare function clearCompositionsCache(): void;
100
100
 
101
+ /**
102
+ * Look up a bundled knowledge file by name. Returns the raw markdown
103
+ * string. Returns `""` when the name isn't known — callers driving an
104
+ * LLM should pair this with {@link hasKnowledge} so a typo turns
105
+ * into an actionable error instead of a silently empty prompt.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * import { getKnowledge, hasKnowledge } from "@directive-run/knowledge";
110
+ *
111
+ * if (!hasKnowledge("guardrails")) throw new Error("typo");
112
+ * const md = getKnowledge("guardrails");
113
+ * ```
114
+ */
101
115
  declare function getKnowledge(name: string): string;
116
+ /**
117
+ * Return every loaded knowledge file as `name → markdown`. Consumers
118
+ * iterating the corpus (full-text search, embedding builder, RAG
119
+ * index) read this once and key off the returned map.
120
+ */
102
121
  declare function getAllKnowledge(): ReadonlyMap<string, string>;
122
+ /**
123
+ * `true` when a knowledge file with this exact name is bundled.
124
+ * Use this BEFORE {@link getKnowledge} when the name is user / agent
125
+ * input — `getKnowledge` returns `""` on miss, which is
126
+ * indistinguishable from an intentionally empty file.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * if (!hasKnowledge(userTyped)) {
131
+ * console.error(`unknown knowledge file: ${userTyped}`);
132
+ * console.error(`available: ${[...getAllKnowledge().keys()].join(", ")}`);
133
+ * return;
134
+ * }
135
+ * ```
136
+ */
137
+ declare function hasKnowledge(name: string): boolean;
138
+ /**
139
+ * Look up a bundled example file by name. Returns the raw source.
140
+ * Returns `""` when the name isn't known — pair with {@link hasExample}
141
+ * when the input is user-controlled.
142
+ */
103
143
  declare function getExample(name: string): string;
144
+ /**
145
+ * `true` when an example file with this exact name is bundled.
146
+ * The miss-vs-empty disambiguator for {@link getExample}.
147
+ */
148
+ declare function hasExample(name: string): boolean;
104
149
  declare function getAllExamples(): ReadonlyMap<string, string>;
105
150
  declare function getKnowledgeFiles(names: string[]): string;
106
151
  declare function getExampleFiles(names: string[]): string;
107
152
  /** Clear cached knowledge and examples. Useful for dev/watch mode. */
108
153
  declare function clearCache(): void;
109
154
 
110
- export { type AntiPattern, type AntiPatternCategory, type AntiPatternSeverity, type CompositionEdge, MIGRATION_SOURCES, type MigrationConceptRow, type MigrationPattern, type MigrationSourceId, clearAntiPatternCache, clearCache, clearCompositionsCache, clearMigrationCache, getAllExamples, getAllKnowledge, getAntiPatternById, getAntiPatterns, getCompositions, getCompositionsFor, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles, getMigrationPattern, getMigrationPatterns, getMigrationSources, getReverseCompositionsFor };
155
+ export { type AntiPattern, type AntiPatternCategory, type AntiPatternSeverity, type CompositionEdge, MIGRATION_SOURCES, type MigrationConceptRow, type MigrationPattern, type MigrationSourceId, clearAntiPatternCache, clearCache, clearCompositionsCache, clearMigrationCache, getAllExamples, getAllKnowledge, getAntiPatternById, getAntiPatterns, getCompositions, getCompositionsFor, getExample, getExampleFiles, getKnowledge, getKnowledgeFiles, getMigrationPattern, getMigrationPatterns, getMigrationSources, getReverseCompositionsFor, hasExample, hasKnowledge };
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import {existsSync,readFileSync,readdirSync}from'fs';import {dirname,resolve,join}from'path';import {fileURLToPath}from'url';var L=dirname(fileURLToPath(import.meta.url)),P=resolve(L,".."),a=null;function k(){let t=[join(P,"core","anti-patterns.md"),join(P,"..","core","anti-patterns.md")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function z(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}function K(t){let e=t.toLowerCase();return /schema|builder/.test(e)?"schema":/constraint|cross-?module|require/.test(e)?"constraint":/resolver|settle|start/.test(e)?"resolver":/deriv|passthrough/.test(e)?"derivation":/effect/.test(e)?"effect":/usedirective|react|hook/.test(e)?"react":/import|bracket|deep import|name|context|abbreviat/.test(e)?"naming":("module")}function G(t){let e=t.toLowerCase();return /nonexistent|missing|no error|deep import|async logic/.test(e)?"error":"warning"}function U(t){let e=t.split(`
2
- `),r=[],n=null,o=/^##\s+(\d+)\.\s+(.+?)\s*$/;for(let s of e){let i=o.exec(s);if(i?.[1]&&i?.[2]){n&&r.push(n),n={number:Number(i[1]),title:i[2],body:""};continue}if(n){if(/^##\s+\D/.test(s)){r.push(n),n=null;break}n.body+=`${s}
1
+ import {existsSync,readFileSync,readdirSync}from'fs';import {dirname,resolve,join}from'path';import {fileURLToPath}from'url';var K=dirname(fileURLToPath(import.meta.url)),A=resolve(K,".."),l=null;function L(){let t=[join(A,"core","anti-patterns.md"),join(A,"..","core","anti-patterns.md")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function k(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").replace(/-{2,}/g,"-")}function z(t){let e=t.toLowerCase();return /schema|builder/.test(e)?"schema":/constraint|cross-?module|require/.test(e)?"constraint":/resolver|settle|start/.test(e)?"resolver":/deriv|passthrough/.test(e)?"derivation":/effect/.test(e)?"effect":/usedirective|react|hook/.test(e)?"react":/import|bracket|deep import|name|context|abbreviat/.test(e)?"naming":("module")}function G(t){let e=t.toLowerCase();return /nonexistent|missing|no error|deep import|async logic/.test(e)?"error":"warning"}function U(t){let e=t.split(`
2
+ `),r=[],n=null,o=/^##\s+(\d+)\.\s+(.+?)\s*$/;for(let c of e){let a=o.exec(c);if(a?.[1]&&a?.[2]){n&&r.push(n),n={number:Number(a[1]),title:a[2],body:""};continue}if(n){if(/^##\s+\D/.test(c)){r.push(n),n=null;break}n.body+=`${c}
3
3
  `;}}return n&&r.push(n),r}function $(t){let e=t.match(/```typescript\n([\s\S]*?)```/),r=[];for(let p of t.split(`
4
4
  `)){if(p.startsWith("```"))break;r.push(p);}let n=r.join(`
5
- `).trim();if(!e?.[1])return {explanation:n};let o=e[1],s=o.match(/\/\/\s*WRONG[^\n]*\n([\s\S]*?)(?:\/\/\s*CORRECT|$)/),i=o.match(/\/\/\s*CORRECT[^\n]*\n([\s\S]*)/);return {explanation:n,badExample:s?.[1]?.trim()??void 0,goodExample:i?.[1]?.trim()??void 0}}function h(){if(a)return a;let t=k(),e;try{e=readFileSync(t,"utf-8");}catch{return a=Object.freeze([]),a}let n=U(e).map(o=>{let{explanation:s,badExample:i,goodExample:p}=$(o.body);return {id:z(o.title),number:o.number,title:o.title,severity:G(o.title),category:K(o.title),explanation:s,badExample:i,goodExample:p}});return a=Object.freeze(n),a}function D(){return h()}function B(t){return h().find(e=>e.id===t)}function W(){a=null;}var V=dirname(fileURLToPath(import.meta.url)),C=resolve(V,".."),R=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[join(C,"migration.json"),join(C,"..","migration.json")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function S(){if(u)return u;try{let t=readFileSync(Y(),"utf-8"),e=JSON.parse(t);u=Object.freeze(e.sources??[]);}catch{u=Object.freeze([]);}return u}function Z(){return R}function tt(){return S()}function et(t){return S().find(e=>e.id===t)}function nt(){u=null;}var ct=dirname(fileURLToPath(import.meta.url)),E=resolve(ct,".."),g=null;function lt(){let t=[join(E,"compositions.json"),join(E,"..","compositions.json")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function m(){if(g)return g;try{let t=readFileSync(lt(),"utf-8"),e=JSON.parse(t);g=Object.freeze(e.edges??[]);}catch{g=Object.freeze([]);}return g}function ut(){return m()}function gt(t){return m().filter(e=>e.from===t)}function pt(t){return m().filter(e=>e.to===t)}function ft(){g=null;}var Pt=dirname(fileURLToPath(import.meta.url)),v=resolve(Pt,"..");function f(t){let e=join(v,t);if(existsSync(e))return e;let r=join(v,"..",t);return existsSync(r)?r:e}var ht=f("core"),At=f("ai"),Ct=f("examples"),Rt=f("api-skeleton.md"),c=null,l=null;function y(t,e){try{let r=readdirSync(t).filter(n=>n.endsWith(".md")||n.endsWith(".ts"));for(let n of r){let o=n.replace(/\.(md|ts)$/,"");e.set(o,readFileSync(join(t,n),"utf-8"));}}catch(r){if(r.code!=="ENOENT")throw r}}function w(){let t=new Map;y(ht,t),y(At,t);try{t.set("api-skeleton",readFileSync(Rt,"utf-8"));}catch{}return t}function _(){let t=new Map;return y(Ct,t),t}function St(t){return c||(c=w()),c.get(t)??""}function Gt(){return c||(c=w()),c}function Mt(t){return l||(l=_()),l.get(t)??""}function Ut(){return l||(l=_()),l}function $t(t){return t.map(e=>St(e)).filter(Boolean).join(`
5
+ `).trim();if(!e?.[1])return {explanation:n};let o=e[1],c=o.match(/\/\/\s*WRONG[^\n]*\n([\s\S]*?)(?:\/\/\s*CORRECT|$)/),a=o.match(/\/\/\s*CORRECT[^\n]*\n([\s\S]*)/);return {explanation:n,badExample:c?.[1]?.trim()??void 0,goodExample:a?.[1]?.trim()??void 0}}function C(){if(l)return l;let t=L(),e;try{e=readFileSync(t,"utf-8");}catch{return l=Object.freeze([]),l}let n=U(e).map(o=>{let{explanation:c,badExample:a,goodExample:p}=$(o.body);return {id:k(o.title),number:o.number,title:o.title,severity:G(o.title),category:z(o.title),explanation:c,badExample:a,goodExample:p}});return l=Object.freeze(n),l}function D(){return C()}function B(t){return C().find(e=>e.id===t)}function W(){l=null;}var V=dirname(fileURLToPath(import.meta.url)),S=resolve(V,".."),M=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[join(S,"migration.json"),join(S,"..","migration.json")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function E(){if(u)return u;try{let t=readFileSync(Y(),"utf-8"),e=JSON.parse(t);u=Object.freeze(e.sources??[]);}catch{u=Object.freeze([]);}return u}function Z(){return M}function tt(){return E()}function et(t){return E().find(e=>e.id===t)}function nt(){u=null;}var ct=dirname(fileURLToPath(import.meta.url)),v=resolve(ct,".."),g=null;function lt(){let t=[join(v,"compositions.json"),join(v,"..","compositions.json")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function m(){if(g)return g;try{let t=readFileSync(lt(),"utf-8"),e=JSON.parse(t);g=Object.freeze(e.edges??[]);}catch{g=Object.freeze([]);}return g}function ut(){return m()}function gt(t){return m().filter(e=>e.from===t)}function pt(t){return m().filter(e=>e.to===t)}function ft(){g=null;}var ht=dirname(fileURLToPath(import.meta.url)),w=resolve(ht,"..");function f(t){let e=join(w,t);if(existsSync(e))return e;let r=join(w,"..",t);return existsSync(r)?r:e}var Pt=f("core"),At=f("ai"),Ct=f("examples"),Rt=f("api-skeleton.md"),i=null,s=null;function y(t,e){try{let r=readdirSync(t).filter(n=>n.endsWith(".md")||n.endsWith(".ts"));for(let n of r){let o=n.replace(/\.(md|ts)$/,"");e.set(o,readFileSync(join(t,n),"utf-8"));}}catch(r){if(r.code!=="ENOENT")throw r}}function x(){let t=new Map;y(Pt,t),y(At,t);try{t.set("api-skeleton",readFileSync(Rt,"utf-8"));}catch{}return t}function h(){let t=new Map;return y(Ct,t),t}function St(t){return i||(i=x()),i.get(t)??""}function Gt(){return i||(i=x()),i}function Ut(t){return i||(i=x()),i.has(t)}function Mt(t){return s||(s=h()),s.get(t)??""}function $t(t){return s||(s=h()),s.has(t)}function Dt(){return s||(s=h()),s}function Bt(t){return t.map(e=>St(e)).filter(Boolean).join(`
6
6
 
7
7
  ---
8
8
 
9
- `)}function Dt(t){return t.map(e=>{let r=Mt(e);return r?`### Example: ${e}
9
+ `)}function Wt(t){return t.map(e=>{let r=Mt(e);return r?`### Example: ${e}
10
10
 
11
11
  \`\`\`typescript
12
12
  ${r}
13
13
  \`\`\``:""}).filter(Boolean).join(`
14
14
 
15
- `)}function Bt(){c=null,l=null;}export{R as MIGRATION_SOURCES,W as clearAntiPatternCache,Bt as clearCache,ft as clearCompositionsCache,nt as clearMigrationCache,Ut as getAllExamples,Gt as getAllKnowledge,B as getAntiPatternById,D as getAntiPatterns,ut as getCompositions,gt as getCompositionsFor,Mt as getExample,Dt as getExampleFiles,St as getKnowledge,$t as getKnowledgeFiles,et as getMigrationPattern,tt as getMigrationPatterns,Z as getMigrationSources,pt as getReverseCompositionsFor};//# sourceMappingURL=index.js.map
15
+ `)}function Jt(){i=null,s=null;}export{M as MIGRATION_SOURCES,W as clearAntiPatternCache,Jt as clearCache,ft as clearCompositionsCache,nt as clearMigrationCache,Dt as getAllExamples,Gt as getAllKnowledge,B as getAntiPatternById,D as getAntiPatterns,ut as getCompositions,gt as getCompositionsFor,Mt as getExample,Wt as getExampleFiles,St as getKnowledge,Bt as getKnowledgeFiles,et as getMigrationPattern,tt as getMigrationPatterns,Z as getMigrationSources,pt as getReverseCompositionsFor,$t as hasExample,Ut as hasKnowledge};//# sourceMappingURL=index.js.map
16
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parsers/anti-patterns.ts","../src/parsers/migration.ts","../src/parsers/compositions.ts","../src/index.ts"],"names":["__dirname","dirname","fileURLToPath","PKG_ROOT","resolve","cache","resolveSourcePath","candidates","join","c","existsSync","slugify","title","categorize","lower","severityFor","splitSections","md","lines","sections","current","heading","line","match","extractExamples","body","codeBlock","explanationLines","explanation","code","wrongMatch","correctMatch","loadAntiPatterns","sourcePath","readFileSync","out","section","badExample","goodExample","getAntiPatterns","getAntiPatternById","id","ap","clearAntiPatternCache","MIGRATION_SOURCES","load","raw","parsed","getMigrationSources","getMigrationPatterns","getMigrationPattern","source","p","clearMigrationCache","getCompositions","getCompositionsFor","packageName","getReverseCompositionsFor","clearCompositionsCache","resolveAsset","name","fromDist","fromSrc","CORE_DIR","AI_DIR","EXAMPLES_DIR","API_SKELETON_PATH","knowledgeCache","exampleCache","loadDir","dir","map","files","readdirSync","f","file","err","loadAllKnowledge","loadAllExamples","getKnowledge","getAllKnowledge","getExample","getAllExamples","getKnowledgeFiles","names","getExampleFiles","content","clearCache"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Parser for `packages/knowledge/core/anti-patterns.md` → structured\n * `AntiPattern[]` data. Lazy + cached so the cost is paid once per\n * process at first call.\n *\n * The source markdown is organized as numbered sections (`## N. Title`)\n * each containing a TypeScript code block with `// WRONG` and\n * `// CORRECT` examples. Some sections include prose between the\n * heading and the code block — captured as `explanation`.\n *\n * IDs are kebab-cased slugs derived from the heading text; stable\n * across releases as long as the heading isn't renamed.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport type AntiPatternSeverity = \"error\" | \"warning\" | \"info\";\nexport type AntiPatternCategory =\n | \"module\"\n | \"schema\"\n | \"constraint\"\n | \"resolver\"\n | \"derivation\"\n | \"effect\"\n | \"naming\"\n | \"react\"\n | \"composition\";\n\nexport interface AntiPattern {\n /** Stable slug, derived from the heading text. */\n id: string;\n /** Section number in the source markdown (1..N). */\n number: number;\n /** Human-readable title (the heading text minus the number prefix). */\n title: string;\n /** Default severity. Heuristic; tunable per-rule later. */\n severity: AntiPatternSeverity;\n /** Heuristic category from title keywords. */\n category: AntiPatternCategory;\n /** Body prose between heading and the first code block (often empty). */\n explanation: string;\n /** The `// WRONG` example, if present. */\n badExample?: string;\n /** The `// CORRECT` example, if present. */\n goodExample?: string;\n}\n\nlet cache: ReadonlyArray<AntiPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"core\", \"anti-patterns.md\"),\n join(PKG_ROOT, \"..\", \"core\", \"anti-patterns.md\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n}\n\nfunction categorize(title: string): AntiPatternCategory {\n const lower = title.toLowerCase();\n if (/schema|builder/.test(lower)) {\n return \"schema\";\n }\n if (/constraint|cross-?module|require/.test(lower)) {\n return \"constraint\";\n }\n if (/resolver|settle|start/.test(lower)) {\n return \"resolver\";\n }\n if (/deriv|passthrough/.test(lower)) {\n return \"derivation\";\n }\n if (/effect/.test(lower)) {\n return \"effect\";\n }\n if (/usedirective|react|hook/.test(lower)) {\n return \"react\";\n }\n if (/import|bracket|deep import|name|context|abbreviat/.test(lower)) {\n return \"naming\";\n }\n if (/init|module|config/.test(lower)) {\n return \"module\";\n }\n return \"module\";\n}\n\nfunction severityFor(title: string): AntiPatternSeverity {\n const lower = title.toLowerCase();\n if (/nonexistent|missing|no error|deep import|async logic/.test(lower)) {\n return \"error\";\n }\n return \"warning\";\n}\n\ninterface Section {\n number: number;\n title: string;\n body: string;\n}\n\nfunction splitSections(md: string): Section[] {\n const lines = md.split(\"\\n\");\n const sections: Section[] = [];\n let current: Section | null = null;\n const heading = /^##\\s+(\\d+)\\.\\s+(.+?)\\s*$/;\n for (const line of lines) {\n const match = heading.exec(line);\n if (match?.[1] && match?.[2]) {\n if (current) {\n sections.push(current);\n }\n current = {\n number: Number(match[1]),\n title: match[2],\n body: \"\",\n };\n continue;\n }\n if (current) {\n // Stop at the first non-numbered ## section (e.g. \"Quick Reference Checklist\")\n if (/^##\\s+\\D/.test(line)) {\n sections.push(current);\n current = null;\n break;\n }\n current.body += `${line}\\n`;\n }\n }\n if (current) {\n sections.push(current);\n }\n return sections;\n}\n\nfunction extractExamples(body: string): {\n explanation: string;\n badExample?: string;\n goodExample?: string;\n} {\n const codeBlock = body.match(/```typescript\\n([\\s\\S]*?)```/);\n const explanationLines: string[] = [];\n for (const line of body.split(\"\\n\")) {\n if (line.startsWith(\"```\")) {\n break;\n }\n explanationLines.push(line);\n }\n const explanation = explanationLines.join(\"\\n\").trim();\n\n if (!codeBlock?.[1]) {\n return { explanation };\n }\n\n const code = codeBlock[1];\n // Split on the WRONG/CORRECT comment markers.\n const wrongMatch = code.match(\n /\\/\\/\\s*WRONG[^\\n]*\\n([\\s\\S]*?)(?:\\/\\/\\s*CORRECT|$)/,\n );\n const correctMatch = code.match(/\\/\\/\\s*CORRECT[^\\n]*\\n([\\s\\S]*)/);\n\n return {\n explanation,\n badExample: wrongMatch?.[1]?.trim() ?? undefined,\n goodExample: correctMatch?.[1]?.trim() ?? undefined,\n };\n}\n\nfunction loadAntiPatterns(): ReadonlyArray<AntiPattern> {\n if (cache) {\n return cache;\n }\n\n const sourcePath = resolveSourcePath();\n let md: string;\n try {\n md = readFileSync(sourcePath, \"utf-8\");\n } catch {\n cache = Object.freeze([]);\n return cache;\n }\n\n const sections = splitSections(md);\n const out: AntiPattern[] = sections.map((section) => {\n const { explanation, badExample, goodExample } = extractExamples(\n section.body,\n );\n return {\n id: slugify(section.title),\n number: section.number,\n title: section.title,\n severity: severityFor(section.title),\n category: categorize(section.title),\n explanation,\n badExample,\n goodExample,\n };\n });\n\n cache = Object.freeze(out);\n return cache;\n}\n\n/** Return every parsed anti-pattern, stable order, frozen. */\nexport function getAntiPatterns(): ReadonlyArray<AntiPattern> {\n return loadAntiPatterns();\n}\n\n/** Look up one anti-pattern by its slug id. */\nexport function getAntiPatternById(id: string): AntiPattern | undefined {\n return loadAntiPatterns().find((ap) => ap.id === id);\n}\n\n/** Clear the in-memory cache. Test / watch-mode helper. */\nexport function clearAntiPatternCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/migration.json` → structured\n * migration patterns. Lazy + cached.\n *\n * The JSON ships in the published tarball; consumers don't need to\n * parse markdown at runtime.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/** Supported source-library identifiers. */\nexport const MIGRATION_SOURCES = [\n \"redux\",\n \"zustand\",\n \"xstate\",\n \"mobx\",\n \"jotai\",\n \"recoil\",\n] as const;\nexport type MigrationSourceId = (typeof MIGRATION_SOURCES)[number];\n\nexport interface MigrationConceptRow {\n from: string;\n to: string;\n note: string;\n}\n\nexport interface MigrationPattern {\n id: MigrationSourceId;\n name: string;\n conceptMap: MigrationConceptRow[];\n steps: string[];\n before: string;\n after: string;\n}\n\ninterface MigrationFile {\n version: number;\n sources: MigrationPattern[];\n}\n\nlet cache: ReadonlyArray<MigrationPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"migration.json\"),\n join(PKG_ROOT, \"..\", \"migration.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<MigrationPattern> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as MigrationFile;\n cache = Object.freeze(parsed.sources ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All supported source library IDs. */\nexport function getMigrationSources(): ReadonlyArray<MigrationSourceId> {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): ReadonlyArray<MigrationPattern> {\n return load();\n}\n\n/** One migration pattern by its source-library id. */\nexport function getMigrationPattern(\n source: string,\n): MigrationPattern | undefined {\n return load().find((p) => p.id === source);\n}\n\n/** Test / watch-mode helper. */\nexport function clearMigrationCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/compositions.json` → typed\n * composition graph. Lazy + cached.\n *\n * The JSON ships in the published tarball. Adjacency list rather\n * than per-package projections so consumers can answer both\n * \"what does X compose with?\" and \"what composes with X?\" without\n * duplicate data.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// After bundling, all parsers live in dist/index.js — one level up\n// from dist reaches the package root. In src/ during dev, the file is\n// two levels up; the fallback in `resolveSourcePath` handles that.\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport interface CompositionEdge {\n from: string;\n to: string;\n reason: string;\n}\n\ninterface CompositionsFile {\n version: number;\n edges: CompositionEdge[];\n}\n\nlet cache: ReadonlyArray<CompositionEdge> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"compositions.json\"),\n join(PKG_ROOT, \"..\", \"compositions.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<CompositionEdge> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as CompositionsFile;\n cache = Object.freeze(parsed.edges ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All composition edges as a flat list. */\nexport function getCompositions(): ReadonlyArray<CompositionEdge> {\n return load();\n}\n\n/**\n * All edges originating at the given package. Returns an empty array\n * when the package is unknown or has no outgoing compositions.\n */\nexport function getCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.from === packageName);\n}\n\n/**\n * All edges arriving at the given package — \"who composes WITH me?\"\n */\nexport function getReverseCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.to === packageName);\n}\n\n/** Test / watch-mode helper. */\nexport function clearCompositionsCache(): void {\n cache = null;\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n\n// ---------------------------------------------------------------------------\n// Structured data APIs (v1.16.0 — back the MCP `list_review_rules`,\n// `get_review_rule`, `list_migration_sources`, `get_migration_pattern`,\n// `get_composable_packages` tools).\n// ---------------------------------------------------------------------------\n\nexport {\n type AntiPattern,\n type AntiPatternCategory,\n type AntiPatternSeverity,\n clearAntiPatternCache,\n getAntiPatternById,\n getAntiPatterns,\n} from \"./parsers/anti-patterns.js\";\n\nexport {\n type MigrationConceptRow,\n type MigrationPattern,\n type MigrationSourceId,\n MIGRATION_SOURCES,\n clearMigrationCache,\n getMigrationPattern,\n getMigrationPatterns,\n getMigrationSources,\n} from \"./parsers/migration.js\";\n\nexport {\n type CompositionEdge,\n clearCompositionsCache,\n getCompositions,\n getCompositionsFor,\n getReverseCompositionsFor,\n} from \"./parsers/compositions.js\";\n"]}
1
+ {"version":3,"sources":["../src/parsers/anti-patterns.ts","../src/parsers/migration.ts","../src/parsers/compositions.ts","../src/index.ts"],"names":["__dirname","dirname","fileURLToPath","PKG_ROOT","resolve","cache","resolveSourcePath","candidates","join","c","existsSync","slugify","title","categorize","lower","severityFor","splitSections","md","lines","sections","current","heading","line","match","extractExamples","body","codeBlock","explanationLines","explanation","code","wrongMatch","correctMatch","loadAntiPatterns","sourcePath","readFileSync","out","section","badExample","goodExample","getAntiPatterns","getAntiPatternById","id","ap","clearAntiPatternCache","MIGRATION_SOURCES","load","raw","parsed","getMigrationSources","getMigrationPatterns","getMigrationPattern","source","p","clearMigrationCache","getCompositions","getCompositionsFor","packageName","getReverseCompositionsFor","clearCompositionsCache","resolveAsset","name","fromDist","fromSrc","CORE_DIR","AI_DIR","EXAMPLES_DIR","API_SKELETON_PATH","knowledgeCache","exampleCache","loadDir","dir","map","files","readdirSync","f","file","err","loadAllKnowledge","loadAllExamples","getKnowledge","getAllKnowledge","hasKnowledge","getExample","hasExample","getAllExamples","getKnowledgeFiles","names","getExampleFiles","content","clearCache"],"mappings":"6HAkBA,IAAMA,EAAYC,OAAAA,CAAQC,aAAAA,CAAc,YAAY,GAAG,CAAC,CAAA,CAClDC,CAAAA,CAAWC,QAAQJ,CAAAA,CAAW,IAAI,EAiCpCK,CAAAA,CAA2C,IAAA,CAE/C,SAASC,CAAAA,EAA4B,CACnC,IAAMC,CAAAA,CAAa,CACjBC,KAAKL,CAAAA,CAAU,MAAA,CAAQ,kBAAkB,CAAA,CACzCK,IAAAA,CAAKL,EAAU,IAAA,CAAM,MAAA,CAAQ,kBAAkB,CACjD,EACA,IAAA,IAAWM,CAAAA,IAAKF,EACd,GAAIG,UAAAA,CAAWD,CAAC,CAAA,CACd,OAAOA,EAGX,OAAOF,CAAAA,CAAW,CAAC,CAAA,EAAK,EAC1B,CAEA,SAASI,CAAAA,CAAQC,EAAuB,CACtC,OAAOA,CAAAA,CACJ,WAAA,GACA,OAAA,CAAQ,aAAA,CAAe,GAAG,CAAA,CAC1B,OAAA,CAAQ,WAAY,EAAE,CAAA,CACtB,QAAQ,QAAA,CAAU,GAAG,CAC1B,CAEA,SAASC,EAAWD,CAAAA,CAAoC,CACtD,IAAME,CAAAA,CAAQF,CAAAA,CAAM,WAAA,EAAY,CAChC,OAAI,gBAAA,CAAiB,IAAA,CAAKE,CAAK,CAAA,CACtB,QAAA,CAEL,mCAAmC,IAAA,CAAKA,CAAK,EACxC,YAAA,CAEL,uBAAA,CAAwB,KAAKA,CAAK,CAAA,CAC7B,WAEL,mBAAA,CAAoB,IAAA,CAAKA,CAAK,CAAA,CACzB,YAAA,CAEL,QAAA,CAAS,IAAA,CAAKA,CAAK,CAAA,CACd,QAAA,CAEL,0BAA0B,IAAA,CAAKA,CAAK,EAC/B,OAAA,CAEL,mDAAA,CAAoD,KAAKA,CAAK,CAAA,CACzD,UAGA,QAAA,CAGX,CAEA,SAASC,CAAAA,CAAYH,EAAoC,CACvD,IAAME,EAAQF,CAAAA,CAAM,WAAA,GACpB,OAAI,sDAAA,CAAuD,KAAKE,CAAK,CAAA,CAC5D,QAEF,SACT,CAQA,SAASE,CAAAA,CAAcC,CAAAA,CAAuB,CAC5C,IAAMC,CAAAA,CAAQD,EAAG,KAAA,CAAM;AAAA,CAAI,CAAA,CACrBE,CAAAA,CAAsB,EAAC,CACzBC,EAA0B,IAAA,CACxBC,CAAAA,CAAU,2BAAA,CAChB,IAAA,IAAWC,CAAAA,IAAQJ,CAAAA,CAAO,CACxB,IAAMK,EAAQF,CAAAA,CAAQ,IAAA,CAAKC,CAAI,CAAA,CAC/B,GAAIC,CAAAA,GAAQ,CAAC,CAAA,EAAKA,IAAQ,CAAC,CAAA,CAAG,CACxBH,CAAAA,EACFD,CAAAA,CAAS,IAAA,CAAKC,CAAO,CAAA,CAEvBA,EAAU,CACR,MAAA,CAAQ,MAAA,CAAOG,CAAAA,CAAM,CAAC,CAAC,CAAA,CACvB,KAAA,CAAOA,EAAM,CAAC,CAAA,CACd,IAAA,CAAM,EACR,CAAA,CACA,QACF,CACA,GAAIH,EAAS,CAEX,GAAI,UAAA,CAAW,IAAA,CAAKE,CAAI,CAAA,CAAG,CACzBH,CAAAA,CAAS,KAAKC,CAAO,CAAA,CACrBA,CAAAA,CAAU,IAAA,CACV,KACF,CACAA,CAAAA,CAAQ,IAAA,EAAQ,GAAGE,CAAI;AAAA,EACzB,CACF,CACA,OAAIF,CAAAA,EACFD,CAAAA,CAAS,IAAA,CAAKC,CAAO,CAAA,CAEhBD,CACT,CAEA,SAASK,CAAAA,CAAgBC,CAAAA,CAIvB,CACA,IAAMC,CAAAA,CAAYD,CAAAA,CAAK,KAAA,CAAM,8BAA8B,CAAA,CACrDE,CAAAA,CAA6B,EAAC,CACpC,IAAA,IAAWL,CAAAA,IAAQG,CAAAA,CAAK,KAAA,CAAM;AAAA,CAAI,EAAG,CACnC,GAAIH,CAAAA,CAAK,UAAA,CAAW,KAAK,CAAA,CACvB,MAEFK,CAAAA,CAAiB,IAAA,CAAKL,CAAI,EAC5B,CACA,IAAMM,CAAAA,CAAcD,EAAiB,IAAA,CAAK;AAAA,CAAI,EAAE,IAAA,EAAK,CAErD,GAAI,CAACD,CAAAA,GAAY,CAAC,CAAA,CAChB,OAAO,CAAE,WAAA,CAAAE,CAAY,CAAA,CAGvB,IAAMC,EAAOH,CAAAA,CAAU,CAAC,EAElBI,CAAAA,CAAaD,CAAAA,CAAK,KAAA,CACtB,oDACF,EACME,CAAAA,CAAeF,CAAAA,CAAK,MAAM,iCAAiC,CAAA,CAEjE,OAAO,CACL,WAAA,CAAAD,EACA,UAAA,CAAYE,CAAAA,GAAa,CAAC,CAAA,EAAG,IAAA,IAAU,MAAA,CACvC,WAAA,CAAaC,IAAe,CAAC,CAAA,EAAG,IAAA,EAAK,EAAK,MAC5C,CACF,CAEA,SAASC,CAAAA,EAA+C,CACtD,GAAI3B,CAAAA,CACF,OAAOA,CAAAA,CAGT,IAAM4B,EAAa3B,CAAAA,EAAkB,CACjCW,EACJ,GAAI,CACFA,EAAKiB,YAAAA,CAAaD,CAAAA,CAAY,OAAO,EACvC,MAAQ,CACN,OAAA5B,EAAQ,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA,CACjBA,CACT,CAGA,IAAM8B,EADWnB,CAAAA,CAAcC,CAAE,EACG,GAAA,CAAKmB,CAAAA,EAAY,CACnD,GAAM,CAAE,WAAA,CAAAR,CAAAA,CAAa,WAAAS,CAAAA,CAAY,WAAA,CAAAC,CAAY,CAAA,CAAId,CAAAA,CAC/CY,EAAQ,IACV,CAAA,CACA,OAAO,CACL,GAAIzB,CAAAA,CAAQyB,CAAAA,CAAQ,KAAK,CAAA,CACzB,MAAA,CAAQA,EAAQ,MAAA,CAChB,KAAA,CAAOA,CAAAA,CAAQ,KAAA,CACf,SAAUrB,CAAAA,CAAYqB,CAAAA,CAAQ,KAAK,CAAA,CACnC,QAAA,CAAUvB,EAAWuB,CAAAA,CAAQ,KAAK,EAClC,WAAA,CAAAR,CAAAA,CACA,WAAAS,CAAAA,CACA,WAAA,CAAAC,CACF,CACF,CAAC,EAED,OAAAjC,CAAAA,CAAQ,MAAA,CAAO,MAAA,CAAO8B,CAAG,CAAA,CAClB9B,CACT,CAGO,SAASkC,CAAAA,EAA8C,CAC5D,OAAOP,CAAAA,EACT,CAGO,SAASQ,CAAAA,CAAmBC,CAAAA,CAAqC,CACtE,OAAOT,CAAAA,GAAmB,IAAA,CAAMU,CAAAA,EAAOA,CAAAA,CAAG,EAAA,GAAOD,CAAE,CACrD,CAGO,SAASE,CAAAA,EAA8B,CAC5CtC,EAAQ,KACV,CC7NA,IAAML,CAAAA,CAAYC,QAAQC,aAAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,EAClDC,CAAAA,CAAWC,OAAAA,CAAQJ,EAAW,IAAI,CAAA,CAG3B4C,EAAoB,CAC/B,OAAA,CACA,SAAA,CACA,QAAA,CACA,OACA,OAAA,CACA,QACF,EAuBIvC,CAAAA,CAAgD,KAEpD,SAASC,CAAAA,EAA4B,CACnC,IAAMC,CAAAA,CAAa,CACjBC,KAAKL,CAAAA,CAAU,gBAAgB,EAC/BK,IAAAA,CAAKL,CAAAA,CAAU,KAAM,gBAAgB,CACvC,CAAA,CACA,IAAA,IAAWM,KAAKF,CAAAA,CACd,GAAIG,WAAWD,CAAC,CAAA,CACd,OAAOA,CAAAA,CAGX,OAAOF,CAAAA,CAAW,CAAC,GAAK,EAC1B,CAEA,SAASsC,CAAAA,EAAwC,CAC/C,GAAIxC,CAAAA,CACF,OAAOA,CAAAA,CAET,GAAI,CACF,IAAMyC,CAAAA,CAAMZ,aAAa5B,CAAAA,EAAkB,CAAG,OAAO,CAAA,CAC/CyC,CAAAA,CAAS,KAAK,KAAA,CAAMD,CAAG,EAC7BzC,CAAAA,CAAQ,MAAA,CAAO,OAAO0C,CAAAA,CAAO,OAAA,EAAW,EAAE,EAC5C,CAAA,KAAQ,CACN1C,EAAQ,MAAA,CAAO,MAAA,CAAO,EAAE,EAC1B,CACA,OAAOA,CACT,CAGO,SAAS2C,GAAwD,CACtE,OAAOJ,CACT,CAGO,SAASK,IAAwD,CACtE,OAAOJ,CAAAA,EACT,CAGO,SAASK,EAAAA,CACdC,EAC8B,CAC9B,OAAON,GAAK,CAAE,IAAA,CAAMO,GAAMA,CAAAA,CAAE,EAAA,GAAOD,CAAM,CAC3C,CAGO,SAASE,EAAAA,EAA4B,CAC1ChD,EAAQ,KACV,CCjFA,IAAML,EAAAA,CAAYC,QAAQC,aAAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,EAIlDC,CAAAA,CAAWC,OAAAA,CAAQJ,GAAW,IAAI,CAAA,CAapCK,EAA+C,IAAA,CAEnD,SAASC,IAA4B,CACnC,IAAMC,EAAa,CACjBC,IAAAA,CAAKL,EAAU,mBAAmB,CAAA,CAClCK,KAAKL,CAAAA,CAAU,IAAA,CAAM,mBAAmB,CAC1C,EACA,IAAA,IAAWM,CAAAA,IAAKF,EACd,GAAIG,UAAAA,CAAWD,CAAC,CAAA,CACd,OAAOA,CAAAA,CAGX,OAAOF,EAAW,CAAC,CAAA,EAAK,EAC1B,CAEA,SAASsC,GAAuC,CAC9C,GAAIxC,CAAAA,CACF,OAAOA,EAET,GAAI,CACF,IAAMyC,CAAAA,CAAMZ,YAAAA,CAAa5B,IAAkB,CAAG,OAAO,EAC/CyC,CAAAA,CAAS,IAAA,CAAK,MAAMD,CAAG,CAAA,CAC7BzC,EAAQ,MAAA,CAAO,MAAA,CAAO0C,EAAO,KAAA,EAAS,EAAE,EAC1C,MAAQ,CACN1C,CAAAA,CAAQ,OAAO,MAAA,CAAO,EAAE,EAC1B,CACA,OAAOA,CACT,CAGO,SAASiD,EAAAA,EAAkD,CAChE,OAAOT,CAAAA,EACT,CAMO,SAASU,EAAAA,CACdC,CAAAA,CACgC,CAChC,OAAOX,CAAAA,GAAO,MAAA,CAAQ,CAAA,EAAM,EAAE,IAAA,GAASW,CAAW,CACpD,CAKO,SAASC,GACdD,CAAAA,CACgC,CAChC,OAAOX,CAAAA,EAAK,CAAE,OAAQ,CAAA,EAAM,CAAA,CAAE,EAAA,GAAOW,CAAW,CAClD,CAGO,SAASE,IAA+B,CAC7CrD,CAAAA,CAAQ,KACV,CClFA,IAAML,EAAAA,CAAYC,OAAAA,CAAQC,cAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA,CAClDC,CAAAA,CAAWC,QAAQJ,EAAAA,CAAW,IAAI,CAAA,CAMxC,SAAS2D,EAAaC,CAAAA,CAAsB,CAC1C,IAAMC,CAAAA,CAAWrD,IAAAA,CAAKL,EAAUyD,CAAI,CAAA,CACpC,GAAIlD,UAAAA,CAAWmD,CAAQ,EACrB,OAAOA,CAAAA,CAGT,IAAMC,CAAAA,CAAUtD,IAAAA,CAAKL,EAAU,IAAA,CAAMyD,CAAI,CAAA,CACzC,OAAIlD,WAAWoD,CAAO,CAAA,CACbA,EAGFD,CACT,CAEA,IAAME,EAAAA,CAAWJ,CAAAA,CAAa,MAAM,CAAA,CAC9BK,GAASL,CAAAA,CAAa,IAAI,EAC1BM,EAAAA,CAAeN,CAAAA,CAAa,UAAU,CAAA,CACtCO,EAAAA,CAAoBP,CAAAA,CAAa,iBAAiB,EAEpDQ,CAAAA,CAA6C,IAAA,CAC7CC,EAA2C,IAAA,CAE/C,SAASC,EAAQC,CAAAA,CAAaC,CAAAA,CAAgC,CAC5D,GAAI,CACF,IAAMC,CAAAA,CAAQC,WAAAA,CAAYH,CAAG,CAAA,CAAE,MAAA,CAC5BI,GAAMA,CAAAA,CAAE,QAAA,CAAS,KAAK,CAAA,EAAKA,EAAE,QAAA,CAAS,KAAK,CAC9C,CAAA,CACA,IAAA,IAAWC,KAAQH,CAAAA,CAAO,CACxB,IAAMZ,CAAAA,CAAOe,EAAK,OAAA,CAAQ,YAAA,CAAc,EAAE,CAAA,CAC1CJ,CAAAA,CAAI,IAAIX,CAAAA,CAAM1B,YAAAA,CAAa1B,IAAAA,CAAK8D,CAAAA,CAAKK,CAAI,CAAA,CAAG,OAAO,CAAC,EACtD,CACF,OAASC,CAAAA,CAAc,CACrB,GAAKA,CAAAA,CAA8B,IAAA,GAAS,SAC1C,MAAMA,CAGV,CACF,CAEA,SAASC,GAAwC,CAC/C,IAAMN,CAAAA,CAAM,IAAI,IAChBF,CAAAA,CAAQN,EAAAA,CAAUQ,CAAG,CAAA,CACrBF,CAAAA,CAAQL,GAAQO,CAAG,CAAA,CAGnB,GAAI,CACFA,EAAI,GAAA,CAAI,cAAA,CAAgBrC,aAAagC,EAAAA,CAAmB,OAAO,CAAC,EAClE,CAAA,KAAQ,CAER,CAEA,OAAOK,CACT,CAEA,SAASO,CAAAA,EAAuC,CAC9C,IAAMP,CAAAA,CAAM,IAAI,IAChB,OAAAF,CAAAA,CAAQJ,GAAcM,CAAG,CAAA,CAElBA,CACT,CAgBO,SAASQ,GAAanB,CAAAA,CAAsB,CACjD,OAAKO,CAAAA,GACHA,EAAiBU,CAAAA,EAAiB,CAAA,CAG7BV,EAAe,GAAA,CAAIP,CAAI,GAAK,EACrC,CAOO,SAASoB,EAAAA,EAA+C,CAC7D,OAAKb,CAAAA,GACHA,EAAiBU,CAAAA,EAAiB,CAAA,CAG7BV,CACT,CAiBO,SAASc,EAAAA,CAAarB,CAAAA,CAAuB,CAClD,OAAKO,CAAAA,GACHA,EAAiBU,CAAAA,EAAiB,CAAA,CAE7BV,EAAe,GAAA,CAAIP,CAAI,CAChC,CAOO,SAASsB,GAAWtB,CAAAA,CAAsB,CAC/C,OAAKQ,CAAAA,GACHA,CAAAA,CAAeU,GAAgB,CAAA,CAG1BV,CAAAA,CAAa,GAAA,CAAIR,CAAI,GAAK,EACnC,CAMO,SAASuB,EAAAA,CAAWvB,CAAAA,CAAuB,CAChD,OAAKQ,CAAAA,GACHA,EAAeU,CAAAA,EAAgB,CAAA,CAE1BV,EAAa,GAAA,CAAIR,CAAI,CAC9B,CAEO,SAASwB,IAA8C,CAC5D,OAAKhB,CAAAA,GACHA,CAAAA,CAAeU,GAAgB,CAAA,CAG1BV,CACT,CAEO,SAASiB,EAAAA,CAAkBC,EAAyB,CACzD,OAAOA,EACJ,GAAA,CAAK1B,CAAAA,EAASmB,GAAanB,CAAI,CAAC,EAChC,MAAA,CAAO,OAAO,EACd,IAAA,CAAK;;AAAA;;AAAA,CAAa,CACvB,CAEO,SAAS2B,GAAgBD,CAAAA,CAAyB,CACvD,OAAOA,CAAAA,CACJ,GAAA,CAAK1B,GAAS,CACb,IAAM4B,EAAUN,EAAAA,CAAWtB,CAAI,EAC/B,OAAK4B,CAAAA,CAIE,gBAAgB5B,CAAI;;AAAA;AAAA,EAAyB4B,CAAO;AAAA,MAAA,CAAA,CAHlD,EAIX,CAAC,CAAA,CACA,MAAA,CAAO,OAAO,EACd,IAAA,CAAK;;AAAA,CAAM,CAChB,CAGO,SAASC,EAAAA,EAAmB,CACjCtB,CAAAA,CAAiB,IAAA,CACjBC,EAAe,KACjB","file":"index.js","sourcesContent":["/**\n * Parser for `packages/knowledge/core/anti-patterns.md` → structured\n * `AntiPattern[]` data. Lazy + cached so the cost is paid once per\n * process at first call.\n *\n * The source markdown is organized as numbered sections (`## N. Title`)\n * each containing a TypeScript code block with `// WRONG` and\n * `// CORRECT` examples. Some sections include prose between the\n * heading and the code block — captured as `explanation`.\n *\n * IDs are kebab-cased slugs derived from the heading text; stable\n * across releases as long as the heading isn't renamed.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport type AntiPatternSeverity = \"error\" | \"warning\" | \"info\";\nexport type AntiPatternCategory =\n | \"module\"\n | \"schema\"\n | \"constraint\"\n | \"resolver\"\n | \"derivation\"\n | \"effect\"\n | \"naming\"\n | \"react\"\n | \"composition\";\n\nexport interface AntiPattern {\n /** Stable slug, derived from the heading text. */\n id: string;\n /** Section number in the source markdown (1..N). */\n number: number;\n /** Human-readable title (the heading text minus the number prefix). */\n title: string;\n /** Default severity. Heuristic; tunable per-rule later. */\n severity: AntiPatternSeverity;\n /** Heuristic category from title keywords. */\n category: AntiPatternCategory;\n /** Body prose between heading and the first code block (often empty). */\n explanation: string;\n /** The `// WRONG` example, if present. */\n badExample?: string;\n /** The `// CORRECT` example, if present. */\n goodExample?: string;\n}\n\nlet cache: ReadonlyArray<AntiPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"core\", \"anti-patterns.md\"),\n join(PKG_ROOT, \"..\", \"core\", \"anti-patterns.md\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\");\n}\n\nfunction categorize(title: string): AntiPatternCategory {\n const lower = title.toLowerCase();\n if (/schema|builder/.test(lower)) {\n return \"schema\";\n }\n if (/constraint|cross-?module|require/.test(lower)) {\n return \"constraint\";\n }\n if (/resolver|settle|start/.test(lower)) {\n return \"resolver\";\n }\n if (/deriv|passthrough/.test(lower)) {\n return \"derivation\";\n }\n if (/effect/.test(lower)) {\n return \"effect\";\n }\n if (/usedirective|react|hook/.test(lower)) {\n return \"react\";\n }\n if (/import|bracket|deep import|name|context|abbreviat/.test(lower)) {\n return \"naming\";\n }\n if (/init|module|config/.test(lower)) {\n return \"module\";\n }\n return \"module\";\n}\n\nfunction severityFor(title: string): AntiPatternSeverity {\n const lower = title.toLowerCase();\n if (/nonexistent|missing|no error|deep import|async logic/.test(lower)) {\n return \"error\";\n }\n return \"warning\";\n}\n\ninterface Section {\n number: number;\n title: string;\n body: string;\n}\n\nfunction splitSections(md: string): Section[] {\n const lines = md.split(\"\\n\");\n const sections: Section[] = [];\n let current: Section | null = null;\n const heading = /^##\\s+(\\d+)\\.\\s+(.+?)\\s*$/;\n for (const line of lines) {\n const match = heading.exec(line);\n if (match?.[1] && match?.[2]) {\n if (current) {\n sections.push(current);\n }\n current = {\n number: Number(match[1]),\n title: match[2],\n body: \"\",\n };\n continue;\n }\n if (current) {\n // Stop at the first non-numbered ## section (e.g. \"Quick Reference Checklist\")\n if (/^##\\s+\\D/.test(line)) {\n sections.push(current);\n current = null;\n break;\n }\n current.body += `${line}\\n`;\n }\n }\n if (current) {\n sections.push(current);\n }\n return sections;\n}\n\nfunction extractExamples(body: string): {\n explanation: string;\n badExample?: string;\n goodExample?: string;\n} {\n const codeBlock = body.match(/```typescript\\n([\\s\\S]*?)```/);\n const explanationLines: string[] = [];\n for (const line of body.split(\"\\n\")) {\n if (line.startsWith(\"```\")) {\n break;\n }\n explanationLines.push(line);\n }\n const explanation = explanationLines.join(\"\\n\").trim();\n\n if (!codeBlock?.[1]) {\n return { explanation };\n }\n\n const code = codeBlock[1];\n // Split on the WRONG/CORRECT comment markers.\n const wrongMatch = code.match(\n /\\/\\/\\s*WRONG[^\\n]*\\n([\\s\\S]*?)(?:\\/\\/\\s*CORRECT|$)/,\n );\n const correctMatch = code.match(/\\/\\/\\s*CORRECT[^\\n]*\\n([\\s\\S]*)/);\n\n return {\n explanation,\n badExample: wrongMatch?.[1]?.trim() ?? undefined,\n goodExample: correctMatch?.[1]?.trim() ?? undefined,\n };\n}\n\nfunction loadAntiPatterns(): ReadonlyArray<AntiPattern> {\n if (cache) {\n return cache;\n }\n\n const sourcePath = resolveSourcePath();\n let md: string;\n try {\n md = readFileSync(sourcePath, \"utf-8\");\n } catch {\n cache = Object.freeze([]);\n return cache;\n }\n\n const sections = splitSections(md);\n const out: AntiPattern[] = sections.map((section) => {\n const { explanation, badExample, goodExample } = extractExamples(\n section.body,\n );\n return {\n id: slugify(section.title),\n number: section.number,\n title: section.title,\n severity: severityFor(section.title),\n category: categorize(section.title),\n explanation,\n badExample,\n goodExample,\n };\n });\n\n cache = Object.freeze(out);\n return cache;\n}\n\n/** Return every parsed anti-pattern, stable order, frozen. */\nexport function getAntiPatterns(): ReadonlyArray<AntiPattern> {\n return loadAntiPatterns();\n}\n\n/** Look up one anti-pattern by its slug id. */\nexport function getAntiPatternById(id: string): AntiPattern | undefined {\n return loadAntiPatterns().find((ap) => ap.id === id);\n}\n\n/** Clear the in-memory cache. Test / watch-mode helper. */\nexport function clearAntiPatternCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/migration.json` → structured\n * migration patterns. Lazy + cached.\n *\n * The JSON ships in the published tarball; consumers don't need to\n * parse markdown at runtime.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/** Supported source-library identifiers. */\nexport const MIGRATION_SOURCES = [\n \"redux\",\n \"zustand\",\n \"xstate\",\n \"mobx\",\n \"jotai\",\n \"recoil\",\n] as const;\nexport type MigrationSourceId = (typeof MIGRATION_SOURCES)[number];\n\nexport interface MigrationConceptRow {\n from: string;\n to: string;\n note: string;\n}\n\nexport interface MigrationPattern {\n id: MigrationSourceId;\n name: string;\n conceptMap: MigrationConceptRow[];\n steps: string[];\n before: string;\n after: string;\n}\n\ninterface MigrationFile {\n version: number;\n sources: MigrationPattern[];\n}\n\nlet cache: ReadonlyArray<MigrationPattern> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"migration.json\"),\n join(PKG_ROOT, \"..\", \"migration.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<MigrationPattern> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as MigrationFile;\n cache = Object.freeze(parsed.sources ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All supported source library IDs. */\nexport function getMigrationSources(): ReadonlyArray<MigrationSourceId> {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): ReadonlyArray<MigrationPattern> {\n return load();\n}\n\n/** One migration pattern by its source-library id. */\nexport function getMigrationPattern(\n source: string,\n): MigrationPattern | undefined {\n return load().find((p) => p.id === source);\n}\n\n/** Test / watch-mode helper. */\nexport function clearMigrationCache(): void {\n cache = null;\n}\n","/**\n * Loader for `packages/knowledge/compositions.json` → typed\n * composition graph. Lazy + cached.\n *\n * The JSON ships in the published tarball. Adjacency list rather\n * than per-package projections so consumers can answer both\n * \"what does X compose with?\" and \"what composes with X?\" without\n * duplicate data.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// After bundling, all parsers live in dist/index.js — one level up\n// from dist reaches the package root. In src/ during dev, the file is\n// two levels up; the fallback in `resolveSourcePath` handles that.\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\nexport interface CompositionEdge {\n from: string;\n to: string;\n reason: string;\n}\n\ninterface CompositionsFile {\n version: number;\n edges: CompositionEdge[];\n}\n\nlet cache: ReadonlyArray<CompositionEdge> | null = null;\n\nfunction resolveSourcePath(): string {\n const candidates = [\n join(PKG_ROOT, \"compositions.json\"),\n join(PKG_ROOT, \"..\", \"compositions.json\"),\n ];\n for (const c of candidates) {\n if (existsSync(c)) {\n return c;\n }\n }\n return candidates[0] ?? \"\";\n}\n\nfunction load(): ReadonlyArray<CompositionEdge> {\n if (cache) {\n return cache;\n }\n try {\n const raw = readFileSync(resolveSourcePath(), \"utf-8\");\n const parsed = JSON.parse(raw) as CompositionsFile;\n cache = Object.freeze(parsed.edges ?? []);\n } catch {\n cache = Object.freeze([]);\n }\n return cache;\n}\n\n/** All composition edges as a flat list. */\nexport function getCompositions(): ReadonlyArray<CompositionEdge> {\n return load();\n}\n\n/**\n * All edges originating at the given package. Returns an empty array\n * when the package is unknown or has no outgoing compositions.\n */\nexport function getCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.from === packageName);\n}\n\n/**\n * All edges arriving at the given package — \"who composes WITH me?\"\n */\nexport function getReverseCompositionsFor(\n packageName: string,\n): ReadonlyArray<CompositionEdge> {\n return load().filter((e) => e.to === packageName);\n}\n\n/** Test / watch-mode helper. */\nexport function clearCompositionsCache(): void {\n cache = null;\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n// Resolve package root: works both in src/ (dev) and dist/ (bundled)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst PKG_ROOT = resolve(__dirname, \"..\");\n\n/**\n * Resolve a path relative to the package root.\n * Tries dist-relative first (bundled), then src-relative (dev).\n */\nfunction resolveAsset(name: string): string {\n const fromDist = join(PKG_ROOT, name);\n if (existsSync(fromDist)) {\n return fromDist;\n }\n\n const fromSrc = join(PKG_ROOT, \"..\", name);\n if (existsSync(fromSrc)) {\n return fromSrc;\n }\n\n return fromDist; // default, will just return empty maps\n}\n\nconst CORE_DIR = resolveAsset(\"core\");\nconst AI_DIR = resolveAsset(\"ai\");\nconst EXAMPLES_DIR = resolveAsset(\"examples\");\nconst API_SKELETON_PATH = resolveAsset(\"api-skeleton.md\");\n\nlet knowledgeCache: Map<string, string> | null = null;\nlet exampleCache: Map<string, string> | null = null;\n\nfunction loadDir(dir: string, map: Map<string, string>): void {\n try {\n const files = readdirSync(dir).filter(\n (f) => f.endsWith(\".md\") || f.endsWith(\".ts\"),\n );\n for (const file of files) {\n const name = file.replace(/\\.(md|ts)$/, \"\");\n map.set(name, readFileSync(join(dir, file), \"utf-8\"));\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n // directory does not exist — expected during tests or incomplete installs\n }\n}\n\nfunction loadAllKnowledge(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(CORE_DIR, map);\n loadDir(AI_DIR, map);\n\n // Include api-skeleton\n try {\n map.set(\"api-skeleton\", readFileSync(API_SKELETON_PATH, \"utf-8\"));\n } catch {\n // may not exist yet\n }\n\n return map;\n}\n\nfunction loadAllExamples(): Map<string, string> {\n const map = new Map<string, string>();\n loadDir(EXAMPLES_DIR, map);\n\n return map;\n}\n\n/**\n * Look up a bundled knowledge file by name. Returns the raw markdown\n * string. Returns `\"\"` when the name isn't known — callers driving an\n * LLM should pair this with {@link hasKnowledge} so a typo turns\n * into an actionable error instead of a silently empty prompt.\n *\n * @example\n * ```ts\n * import { getKnowledge, hasKnowledge } from \"@directive-run/knowledge\";\n *\n * if (!hasKnowledge(\"guardrails\")) throw new Error(\"typo\");\n * const md = getKnowledge(\"guardrails\");\n * ```\n */\nexport function getKnowledge(name: string): string {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache.get(name) ?? \"\";\n}\n\n/**\n * Return every loaded knowledge file as `name → markdown`. Consumers\n * iterating the corpus (full-text search, embedding builder, RAG\n * index) read this once and key off the returned map.\n */\nexport function getAllKnowledge(): ReadonlyMap<string, string> {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n\n return knowledgeCache;\n}\n\n/**\n * `true` when a knowledge file with this exact name is bundled.\n * Use this BEFORE {@link getKnowledge} when the name is user / agent\n * input — `getKnowledge` returns `\"\"` on miss, which is\n * indistinguishable from an intentionally empty file.\n *\n * @example\n * ```ts\n * if (!hasKnowledge(userTyped)) {\n * console.error(`unknown knowledge file: ${userTyped}`);\n * console.error(`available: ${[...getAllKnowledge().keys()].join(\", \")}`);\n * return;\n * }\n * ```\n */\nexport function hasKnowledge(name: string): boolean {\n if (!knowledgeCache) {\n knowledgeCache = loadAllKnowledge();\n }\n return knowledgeCache.has(name);\n}\n\n/**\n * Look up a bundled example file by name. Returns the raw source.\n * Returns `\"\"` when the name isn't known — pair with {@link hasExample}\n * when the input is user-controlled.\n */\nexport function getExample(name: string): string {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache.get(name) ?? \"\";\n}\n\n/**\n * `true` when an example file with this exact name is bundled.\n * The miss-vs-empty disambiguator for {@link getExample}.\n */\nexport function hasExample(name: string): boolean {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n return exampleCache.has(name);\n}\n\nexport function getAllExamples(): ReadonlyMap<string, string> {\n if (!exampleCache) {\n exampleCache = loadAllExamples();\n }\n\n return exampleCache;\n}\n\nexport function getKnowledgeFiles(names: string[]): string {\n return names\n .map((name) => getKnowledge(name))\n .filter(Boolean)\n .join(\"\\n\\n---\\n\\n\");\n}\n\nexport function getExampleFiles(names: string[]): string {\n return names\n .map((name) => {\n const content = getExample(name);\n if (!content) {\n return \"\";\n }\n\n return `### Example: ${name}\\n\\n\\`\\`\\`typescript\\n${content}\\n\\`\\`\\``;\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n}\n\n/** Clear cached knowledge and examples. Useful for dev/watch mode. */\nexport function clearCache(): void {\n knowledgeCache = null;\n exampleCache = null;\n}\n\n// ---------------------------------------------------------------------------\n// Structured data APIs (v1.16.0 — back the MCP `list_review_rules`,\n// `get_review_rule`, `list_migration_sources`, `get_migration_pattern`,\n// `get_composable_packages` tools).\n// ---------------------------------------------------------------------------\n\nexport {\n type AntiPattern,\n type AntiPatternCategory,\n type AntiPatternSeverity,\n clearAntiPatternCache,\n getAntiPatternById,\n getAntiPatterns,\n} from \"./parsers/anti-patterns.js\";\n\nexport {\n type MigrationConceptRow,\n type MigrationPattern,\n type MigrationSourceId,\n MIGRATION_SOURCES,\n clearMigrationCache,\n getMigrationPattern,\n getMigrationPatterns,\n getMigrationSources,\n} from \"./parsers/migration.js\";\n\nexport {\n type CompositionEdge,\n clearCompositionsCache,\n getCompositions,\n getCompositionsFor,\n getReverseCompositionsFor,\n} from \"./parsers/compositions.js\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@directive-run/knowledge",
3
- "version": "1.20.2",
3
+ "version": "1.21.0",
4
4
  "description": "Knowledge files, examples, and validation for Directive — the constraint-driven TypeScript runtime.",
5
5
  "license": "(MIT OR Apache-2.0)",
6
6
  "author": "Jason Comes",
@@ -53,8 +53,8 @@
53
53
  "tsx": "^4.19.2",
54
54
  "typescript": "^5.7.2",
55
55
  "vitest": "^3.0.0",
56
- "@directive-run/core": "1.20.2",
57
- "@directive-run/ai": "1.20.2"
56
+ "@directive-run/core": "1.21.0",
57
+ "@directive-run/ai": "1.21.0"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "tsx scripts/generate-api-skeleton.ts && tsx scripts/generate-sitemap.ts && tsx scripts/extract-examples.ts && tsup",