@directive-run/knowledge 1.21.0 → 1.23.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/README.md +4 -4
- package/core/choosing-primitives.md +2 -1
- package/core/resolvers.md +26 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/sitemap.md +31 -33
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @directive-run/knowledge
|
|
2
2
|
|
|
3
|
-
The **source of truth** for all Directive coding knowledge
|
|
3
|
+
The **source of truth** for all Directive coding knowledge – used by Claude Code skills, Cursor / Copilot / Windsurf / Cline / Codex rules files, the website's `/llms.txt` route, and the programmatic API for downstream tooling.
|
|
4
4
|
|
|
5
|
-
If you want your AI assistant to write idiomatic Directive code, you do not install this package directly
|
|
5
|
+
If you want your AI assistant to write idiomatic Directive code, you do not install this package directly – you install one of its consumers below.
|
|
6
6
|
|
|
7
7
|
## Using the knowledge
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ Two commands in a Claude Code session:
|
|
|
15
15
|
/plugin install directive@directive-plugins
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Ships 12 skills bundled from this package. Skills are model-invoked
|
|
18
|
+
Ships 12 skills bundled from this package. Skills are model-invoked – Claude reads each skill's description and auto-loads the relevant one when your task matches.
|
|
19
19
|
|
|
20
20
|
### Cursor, Copilot, Windsurf, Cline, OpenAI Codex
|
|
21
21
|
|
|
@@ -63,7 +63,7 @@ const examples = getAllExamples();
|
|
|
63
63
|
clearCache();
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
If you're just trying to write code with AI help, you don't need this
|
|
66
|
+
If you're just trying to write code with AI help, you don't need this – install the Claude plugin or run `directive ai-rules` above.
|
|
67
67
|
|
|
68
68
|
## What's in the package
|
|
69
69
|
|
|
@@ -156,7 +156,8 @@ seven pieces of work, zero `useEffect` hooks.
|
|
|
156
156
|
- [`sources.md`](./sources.md) — the source primitive's full lifecycle
|
|
157
157
|
and recipes.
|
|
158
158
|
- [`constraints.md`](./constraints.md) — `when` predicates, requirement
|
|
159
|
-
shapes, and the `
|
|
159
|
+
shapes, and the `abortOn` field-scoped CAS contract (v1; `bind:` is a
|
|
160
|
+
v2 reservation – see RFC 0003 Future Work).
|
|
160
161
|
- [`resolvers.md`](./resolvers.md) — retry config, batch semantics, and
|
|
161
162
|
the `ctx.set` write contract.
|
|
162
163
|
- [`anti-patterns.md`](./anti-patterns.md) — the things to avoid that
|
package/core/resolvers.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Resolvers
|
|
2
2
|
|
|
3
|
-
> Covers `@directive-run/core` — resolver definition: retry policies, batching, cancellation, custom dedup keys, `
|
|
3
|
+
> Covers `@directive-run/core` — resolver definition: retry policies, batching, cancellation, custom dedup keys, `abortOn` binding.
|
|
4
4
|
|
|
5
5
|
Resolvers fulfill requirements emitted by constraints. They are the supply side of the constraint-resolver pattern. Resolvers handle async work and mutate state through `context.facts`.
|
|
6
6
|
|
|
@@ -205,6 +205,31 @@ resolvers: {
|
|
|
205
205
|
|
|
206
206
|
Failed items from `resolveBatchWithResults` can be individually retried if a retry policy is configured.
|
|
207
207
|
|
|
208
|
+
## `abortOn` binding (constraint-side)
|
|
209
|
+
|
|
210
|
+
Declared on the *constraint*, not the resolver. Lists facts whose values
|
|
211
|
+
must remain unchanged between dispatch and the resolver's writes; if any
|
|
212
|
+
of them changes mid-flight, the resolver's writes are dropped and its
|
|
213
|
+
signal is aborted.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
constraints: {
|
|
217
|
+
finalizeKyc: {
|
|
218
|
+
when: (f) => f.kyc.status === "pending",
|
|
219
|
+
require: { type: "FINALIZE_KYC" },
|
|
220
|
+
abortOn: ["kyc.status"], // abort if `kyc.status` changes mid-flight
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`abortOn:` does **not** lock or gate other writers. It only protects this
|
|
226
|
+
resolver from clobbering with stale data when its tail write attempts a
|
|
227
|
+
value the world has since moved past. See
|
|
228
|
+
[`/docs/resolver-binding`](https://directive.run/docs/resolver-binding)
|
|
229
|
+
for the full lifecycle, ABA caveats, and the audit event
|
|
230
|
+
(`resolver.write.rejected { reason: "clobbered" }`) that fires on a
|
|
231
|
+
dropped write.
|
|
232
|
+
|
|
208
233
|
## Timeout
|
|
209
234
|
|
|
210
235
|
```typescript
|
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 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)))),
|
|
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)))),C=path.resolve(K,".."),l=null;function L(){let t=[path.join(C,"core","anti-patterns.md"),path.join(C,"..","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
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],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
|
|
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 S(){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 S()}function B(t){return S().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)))),E=path.resolve(V,".."),b=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[path.join(E,"migration.json"),path.join(E,"..","migration.json")];for(let e of t)if(fs.existsSync(e))return e;return t[0]??""}function A(){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 b}function tt(){return A()}function et(t){return A().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)))),R=path.resolve(ct,".."),g=null;function lt(){let t=[path.join(R,"compositions.json"),path.join(R,"..","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"),Ct=f("ai"),St=f("examples"),Mt=f("api-skeleton.md"),i=null,s=null;function x(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 y(){let t=new Map;x(Pt,t),x(Ct,t);try{t.set("api-skeleton",fs.readFileSync(Mt,"utf-8"));}catch{}return t}function h(){let t=new Map;return x(St,t),t}function Et(t){return i||(i=y()),i.get(t)??""}function Gt(){return i||(i=y()),i}function Ut(t){return i||(i=y()),i.has(t)}function bt(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=>Et(e)).filter(Boolean).join(`
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
`)}function Wt(t){return t.map(e=>{let r=
|
|
9
|
+
`)}function Wt(t){return t.map(e=>{let r=bt(e);return r?`### Example: ${e}
|
|
10
10
|
|
|
11
11
|
\`\`\`typescript
|
|
12
12
|
${r}
|
|
13
13
|
\`\`\``:""}).filter(Boolean).join(`
|
|
14
14
|
|
|
15
|
-
`)}function Jt(){i=null,s=null;}exports.MIGRATION_SOURCES=
|
|
15
|
+
`)}function Jt(){i=null,s=null;}exports.MIGRATION_SOURCES=b;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=bt;exports.getExampleFiles=Wt;exports.getKnowledge=Et;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
|
package/dist/index.cjs.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","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"]}
|
|
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: readonly 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(): readonly 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(): readonly 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: readonly 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(): readonly 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(): readonly MigrationSourceId[] {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): readonly 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: readonly 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(): readonly 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(): readonly 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): readonly 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): readonly 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
|
@@ -32,7 +32,7 @@ interface AntiPattern {
|
|
|
32
32
|
goodExample?: string;
|
|
33
33
|
}
|
|
34
34
|
/** Return every parsed anti-pattern, stable order, frozen. */
|
|
35
|
-
declare function getAntiPatterns():
|
|
35
|
+
declare function getAntiPatterns(): readonly AntiPattern[];
|
|
36
36
|
/** Look up one anti-pattern by its slug id. */
|
|
37
37
|
declare function getAntiPatternById(id: string): AntiPattern | undefined;
|
|
38
38
|
/** Clear the in-memory cache. Test / watch-mode helper. */
|
|
@@ -62,9 +62,9 @@ interface MigrationPattern {
|
|
|
62
62
|
after: string;
|
|
63
63
|
}
|
|
64
64
|
/** All supported source library IDs. */
|
|
65
|
-
declare function getMigrationSources():
|
|
65
|
+
declare function getMigrationSources(): readonly MigrationSourceId[];
|
|
66
66
|
/** All migration patterns, in registry order. */
|
|
67
|
-
declare function getMigrationPatterns():
|
|
67
|
+
declare function getMigrationPatterns(): readonly MigrationPattern[];
|
|
68
68
|
/** One migration pattern by its source-library id. */
|
|
69
69
|
declare function getMigrationPattern(source: string): MigrationPattern | undefined;
|
|
70
70
|
/** Test / watch-mode helper. */
|
|
@@ -85,16 +85,16 @@ interface CompositionEdge {
|
|
|
85
85
|
reason: string;
|
|
86
86
|
}
|
|
87
87
|
/** All composition edges as a flat list. */
|
|
88
|
-
declare function getCompositions():
|
|
88
|
+
declare function getCompositions(): readonly CompositionEdge[];
|
|
89
89
|
/**
|
|
90
90
|
* All edges originating at the given package. Returns an empty array
|
|
91
91
|
* when the package is unknown or has no outgoing compositions.
|
|
92
92
|
*/
|
|
93
|
-
declare function getCompositionsFor(packageName: string):
|
|
93
|
+
declare function getCompositionsFor(packageName: string): readonly CompositionEdge[];
|
|
94
94
|
/**
|
|
95
95
|
* All edges arriving at the given package — "who composes WITH me?"
|
|
96
96
|
*/
|
|
97
|
-
declare function getReverseCompositionsFor(packageName: string):
|
|
97
|
+
declare function getReverseCompositionsFor(packageName: string): readonly CompositionEdge[];
|
|
98
98
|
/** Test / watch-mode helper. */
|
|
99
99
|
declare function clearCompositionsCache(): void;
|
|
100
100
|
|
package/dist/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ interface AntiPattern {
|
|
|
32
32
|
goodExample?: string;
|
|
33
33
|
}
|
|
34
34
|
/** Return every parsed anti-pattern, stable order, frozen. */
|
|
35
|
-
declare function getAntiPatterns():
|
|
35
|
+
declare function getAntiPatterns(): readonly AntiPattern[];
|
|
36
36
|
/** Look up one anti-pattern by its slug id. */
|
|
37
37
|
declare function getAntiPatternById(id: string): AntiPattern | undefined;
|
|
38
38
|
/** Clear the in-memory cache. Test / watch-mode helper. */
|
|
@@ -62,9 +62,9 @@ interface MigrationPattern {
|
|
|
62
62
|
after: string;
|
|
63
63
|
}
|
|
64
64
|
/** All supported source library IDs. */
|
|
65
|
-
declare function getMigrationSources():
|
|
65
|
+
declare function getMigrationSources(): readonly MigrationSourceId[];
|
|
66
66
|
/** All migration patterns, in registry order. */
|
|
67
|
-
declare function getMigrationPatterns():
|
|
67
|
+
declare function getMigrationPatterns(): readonly MigrationPattern[];
|
|
68
68
|
/** One migration pattern by its source-library id. */
|
|
69
69
|
declare function getMigrationPattern(source: string): MigrationPattern | undefined;
|
|
70
70
|
/** Test / watch-mode helper. */
|
|
@@ -85,16 +85,16 @@ interface CompositionEdge {
|
|
|
85
85
|
reason: string;
|
|
86
86
|
}
|
|
87
87
|
/** All composition edges as a flat list. */
|
|
88
|
-
declare function getCompositions():
|
|
88
|
+
declare function getCompositions(): readonly CompositionEdge[];
|
|
89
89
|
/**
|
|
90
90
|
* All edges originating at the given package. Returns an empty array
|
|
91
91
|
* when the package is unknown or has no outgoing compositions.
|
|
92
92
|
*/
|
|
93
|
-
declare function getCompositionsFor(packageName: string):
|
|
93
|
+
declare function getCompositionsFor(packageName: string): readonly CompositionEdge[];
|
|
94
94
|
/**
|
|
95
95
|
* All edges arriving at the given package — "who composes WITH me?"
|
|
96
96
|
*/
|
|
97
|
-
declare function getReverseCompositionsFor(packageName: string):
|
|
97
|
+
declare function getReverseCompositionsFor(packageName: string): readonly CompositionEdge[];
|
|
98
98
|
/** Test / watch-mode helper. */
|
|
99
99
|
declare function clearCompositionsCache(): void;
|
|
100
100
|
|
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 K=dirname(fileURLToPath(import.meta.url)),
|
|
1
|
+
import {existsSync,readFileSync,readdirSync}from'fs';import {dirname,resolve,join}from'path';import {fileURLToPath}from'url';var K=dirname(fileURLToPath(import.meta.url)),C=resolve(K,".."),l=null;function L(){let t=[join(C,"core","anti-patterns.md"),join(C,"..","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
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],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
|
|
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 S(){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 S()}function B(t){return S().find(e=>e.id===t)}function W(){l=null;}var V=dirname(fileURLToPath(import.meta.url)),E=resolve(V,".."),b=["redux","zustand","xstate","mobx","jotai","recoil"],u=null;function Y(){let t=[join(E,"migration.json"),join(E,"..","migration.json")];for(let e of t)if(existsSync(e))return e;return t[0]??""}function A(){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 b}function tt(){return A()}function et(t){return A().find(e=>e.id===t)}function nt(){u=null;}var ct=dirname(fileURLToPath(import.meta.url)),R=resolve(ct,".."),g=null;function lt(){let t=[join(R,"compositions.json"),join(R,"..","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"),Ct=f("ai"),St=f("examples"),Mt=f("api-skeleton.md"),i=null,s=null;function x(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 y(){let t=new Map;x(Pt,t),x(Ct,t);try{t.set("api-skeleton",readFileSync(Mt,"utf-8"));}catch{}return t}function h(){let t=new Map;return x(St,t),t}function Et(t){return i||(i=y()),i.get(t)??""}function Gt(){return i||(i=y()),i}function Ut(t){return i||(i=y()),i.has(t)}function bt(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=>Et(e)).filter(Boolean).join(`
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
`)}function Wt(t){return t.map(e=>{let r=
|
|
9
|
+
`)}function Wt(t){return t.map(e=>{let r=bt(e);return r?`### Example: ${e}
|
|
10
10
|
|
|
11
11
|
\`\`\`typescript
|
|
12
12
|
${r}
|
|
13
13
|
\`\`\``:""}).filter(Boolean).join(`
|
|
14
14
|
|
|
15
|
-
`)}function Jt(){i=null,s=null;}export{
|
|
15
|
+
`)}function Jt(){i=null,s=null;}export{b 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,bt as getExample,Wt as getExampleFiles,Et 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","hasKnowledge","getExample","hasExample","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\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"]}
|
|
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.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: readonly 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(): readonly 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(): readonly 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: readonly 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(): readonly 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(): readonly MigrationSourceId[] {\n return MIGRATION_SOURCES;\n}\n\n/** All migration patterns, in registry order. */\nexport function getMigrationPatterns(): readonly 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: readonly 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(): readonly 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(): readonly 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): readonly 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): readonly 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.
|
|
3
|
+
"version": "1.23.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.
|
|
57
|
-
"@directive-run/ai": "1.
|
|
56
|
+
"@directive-run/core": "1.23.0",
|
|
57
|
+
"@directive-run/ai": "1.23.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",
|
package/sitemap.md
CHANGED
|
@@ -12,16 +12,13 @@ Website: https://directive.run
|
|
|
12
12
|
- [Why Directive](https://directive.run/docs/why-directive)
|
|
13
13
|
- [Installation](https://directive.run/docs/installation)
|
|
14
14
|
- [Core Concepts](https://directive.run/docs/core-concepts)
|
|
15
|
-
- [Comparison](https://directive.run/docs/comparison)
|
|
16
15
|
- [Choosing Primitives](https://directive.run/docs/choosing-primitives)
|
|
16
|
+
- [Comparison](https://directive.run/docs/comparison)
|
|
17
17
|
|
|
18
|
-
###
|
|
18
|
+
### Editor Setup
|
|
19
19
|
- [IDE Integration](https://directive.run/docs/ide-integration)
|
|
20
|
-
- [Claude Code plugin](https://directive.run/docs/ide-integration#claude-code)
|
|
21
|
-
- [CLI ai-rules](https://directive.run/docs/ide-integration#cli-ai-rules)
|
|
22
|
-
- [Knowledge package](https://directive.run/docs/ide-integration#knowledge-package)
|
|
23
20
|
|
|
24
|
-
###
|
|
21
|
+
### Primitives
|
|
25
22
|
- [Overview](https://directive.run/docs/core-api)
|
|
26
23
|
- [Module & System](https://directive.run/docs/module-system)
|
|
27
24
|
- [Facts](https://directive.run/docs/facts)
|
|
@@ -29,8 +26,8 @@ Website: https://directive.run
|
|
|
29
26
|
- [Constraints](https://directive.run/docs/constraints)
|
|
30
27
|
- [Resolvers](https://directive.run/docs/resolvers)
|
|
31
28
|
- [Effects](https://directive.run/docs/effects)
|
|
32
|
-
- [Sources](https://directive.run/docs/sources)
|
|
33
29
|
- [Events](https://directive.run/docs/events)
|
|
30
|
+
- [Sources](https://directive.run/docs/sources)
|
|
34
31
|
- [Schema & Types](https://directive.run/docs/schema-overview)
|
|
35
32
|
- [API Reference](https://directive.run/docs/api/core)
|
|
36
33
|
- [Type Reference](https://directive.run/docs/api/types)
|
|
@@ -63,7 +60,7 @@ Website: https://directive.run
|
|
|
63
60
|
### Advanced Patterns
|
|
64
61
|
- [Overview](https://directive.run/docs/advanced/overview)
|
|
65
62
|
- [Data-form Definitions](https://directive.run/docs/data-triggers)
|
|
66
|
-
- [
|
|
63
|
+
- [Sandbox](https://directive.run/docs/sandbox)
|
|
67
64
|
- [Multi-Module](https://directive.run/docs/advanced/multi-module)
|
|
68
65
|
- [Runtime Dynamics](https://directive.run/docs/advanced/runtime)
|
|
69
66
|
- [History & Snapshots](https://directive.run/docs/advanced/history)
|
|
@@ -72,13 +69,13 @@ Website: https://directive.run
|
|
|
72
69
|
- [Definition Meta](https://directive.run/docs/advanced/meta)
|
|
73
70
|
|
|
74
71
|
### Predicate Tools
|
|
75
|
-
- [
|
|
76
|
-
- [
|
|
77
|
-
- [Predicate Codegen
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
80
|
-
- [Predicate Backtest
|
|
81
|
-
- [Parameter Sweep
|
|
72
|
+
- [Predicate from Intent](https://directive.run/docs/predicate-from-intent)
|
|
73
|
+
- [Describe Predicate](https://directive.run/docs/describe-predicate)
|
|
74
|
+
- [Predicate Codegen](https://directive.run/docs/predicate-codegen)
|
|
75
|
+
- [Predict](https://directive.run/docs/predict)
|
|
76
|
+
- [Doctor Check](https://directive.run/docs/doctor)
|
|
77
|
+
- [Predicate Backtest](https://directive.run/docs/replay-under)
|
|
78
|
+
- [Parameter Sweep](https://directive.run/docs/tune)
|
|
82
79
|
- [Rules Diff](https://directive.run/docs/rules-diff)
|
|
83
80
|
|
|
84
81
|
### Plugins
|
|
@@ -89,17 +86,16 @@ Website: https://directive.run
|
|
|
89
86
|
- [Persistence](https://directive.run/docs/plugins/persistence)
|
|
90
87
|
- [Performance](https://directive.run/docs/plugins/performance)
|
|
91
88
|
- [Circuit Breaker](https://directive.run/docs/plugins/circuit-breaker)
|
|
92
|
-
- [Audit Ledger](https://directive.run/docs/audit-ledger)
|
|
93
89
|
- [Observability](https://directive.run/docs/plugins/observability)
|
|
94
90
|
- [Custom Plugins](https://directive.run/docs/plugins/custom)
|
|
95
91
|
|
|
96
|
-
### Packages
|
|
97
|
-
- [Timeline
|
|
98
|
-
- [Mutator
|
|
99
|
-
- [Optimistic
|
|
100
|
-
- [Query
|
|
92
|
+
### Companion Packages
|
|
93
|
+
- [Timeline](https://directive.run/docs/packages/timeline)
|
|
94
|
+
- [Mutator](https://directive.run/docs/packages/mutator)
|
|
95
|
+
- [Optimistic](https://directive.run/docs/packages/optimistic)
|
|
96
|
+
- [Query](https://directive.run/docs/packages/query)
|
|
101
97
|
- [Vite Dev Proxy](https://directive.run/docs/packages/vite-dev-proxy)
|
|
102
|
-
- [Composing
|
|
98
|
+
- [Composing All Four](https://directive.run/docs/packages/composing-packages)
|
|
103
99
|
|
|
104
100
|
### Testing
|
|
105
101
|
- [Overview](https://directive.run/docs/testing/overview)
|
|
@@ -108,6 +104,10 @@ Website: https://directive.run
|
|
|
108
104
|
- [Assertions](https://directive.run/docs/testing/assertions)
|
|
109
105
|
- [Test Async Chains](https://directive.run/docs/guides/test-async-chains)
|
|
110
106
|
|
|
107
|
+
### Security & Compliance
|
|
108
|
+
- [Resolver Binding](https://directive.run/docs/resolver-binding)
|
|
109
|
+
- [Audit Ledger](https://directive.run/docs/audit-ledger)
|
|
110
|
+
|
|
111
111
|
### Examples
|
|
112
112
|
- [Number Match](https://directive.run/docs/examples/counter)
|
|
113
113
|
- [Auth Flow](https://directive.run/docs/examples/auth-flow)
|
|
@@ -134,7 +134,7 @@ Website: https://directive.run
|
|
|
134
134
|
- [Role-Based Permissions](https://directive.run/docs/guides/permissions)
|
|
135
135
|
- [Batch Mutations](https://directive.run/docs/guides/batch-mutations)
|
|
136
136
|
|
|
137
|
-
###
|
|
137
|
+
### Works With
|
|
138
138
|
- [Overview](https://directive.run/docs/works-with/overview)
|
|
139
139
|
- [Redux](https://directive.run/docs/works-with/redux)
|
|
140
140
|
- [Zustand](https://directive.run/docs/works-with/zustand)
|
|
@@ -146,17 +146,17 @@ Website: https://directive.run
|
|
|
146
146
|
|
|
147
147
|
### Foundations
|
|
148
148
|
- [Overview](https://directive.run/ai/overview)
|
|
149
|
+
- [Tutorial](https://directive.run/ai/tutorial)
|
|
149
150
|
- [Running Agents](https://directive.run/ai/running-agents)
|
|
150
|
-
- [Resilience & Routing](https://directive.run/ai/resilience-routing)
|
|
151
151
|
- [Comparison](https://directive.run/ai/comparison)
|
|
152
|
-
- [Tutorial](https://directive.run/ai/tutorial)
|
|
153
152
|
- [Troubleshooting](https://directive.run/ai/troubleshooting)
|
|
154
153
|
|
|
155
|
-
### Agent Orchestrator
|
|
154
|
+
### Single-Agent Orchestrator
|
|
156
155
|
- [Overview](https://directive.run/ai/orchestrator)
|
|
157
156
|
- [Guardrails](https://directive.run/ai/guardrails)
|
|
158
157
|
- [Streaming](https://directive.run/ai/streaming)
|
|
159
158
|
- [Memory](https://directive.run/ai/memory)
|
|
159
|
+
- [Resilience & Routing](https://directive.run/ai/resilience-routing)
|
|
160
160
|
|
|
161
161
|
### Multi-Agent Orchestrator
|
|
162
162
|
- [Overview](https://directive.run/ai/multi-agent)
|
|
@@ -168,6 +168,7 @@ Website: https://directive.run
|
|
|
168
168
|
|
|
169
169
|
### Infrastructure
|
|
170
170
|
- [MCP Integration](https://directive.run/ai/mcp)
|
|
171
|
+
- [Sources × Agents](https://directive.run/ai/sources)
|
|
171
172
|
- [RAG Enricher](https://directive.run/ai/rag)
|
|
172
173
|
- [SSE Transport](https://directive.run/ai/sse-transport)
|
|
173
174
|
- [Semantic Cache](https://directive.run/ai/semantic-cache)
|
|
@@ -176,6 +177,7 @@ Website: https://directive.run
|
|
|
176
177
|
- [Debug Timeline](https://directive.run/ai/debug-timeline)
|
|
177
178
|
- [Pattern Checkpoints](https://directive.run/ai/checkpoints)
|
|
178
179
|
- [Breakpoints & Checkpoints](https://directive.run/ai/breakpoints)
|
|
180
|
+
- [Guardrail Events](https://directive.run/ai/guardrail-events)
|
|
179
181
|
- [DevTools](https://directive.run/ai/devtools)
|
|
180
182
|
|
|
181
183
|
### Security & Compliance
|
|
@@ -195,15 +197,11 @@ Website: https://directive.run
|
|
|
195
197
|
- [Data Pipeline](https://directive.run/ai/examples/data-pipeline)
|
|
196
198
|
- [Code Review](https://directive.run/ai/examples/code-review)
|
|
197
199
|
|
|
198
|
-
###
|
|
199
|
-
- [Control AI Costs](https://directive.run/ai/guides/control-ai-costs)
|
|
200
|
-
|
|
201
|
-
### Validate Structured Output
|
|
200
|
+
### Stream Agent Responses
|
|
202
201
|
- [Handle Agent Errors](https://directive.run/ai/guides/handle-agent-errors)
|
|
202
|
+
- [Control AI Costs](https://directive.run/ai/guides/control-ai-costs)
|
|
203
203
|
|
|
204
|
-
###
|
|
204
|
+
### Pipelines & Apps
|
|
205
205
|
- [Multi-Step Pipeline](https://directive.run/ai/guides/multi-step-pipeline)
|
|
206
|
-
|
|
207
|
-
### Test Without LLM Calls
|
|
208
206
|
- [DAG Pipeline](https://directive.run/ai/guides/dag-pipeline)
|
|
209
207
|
- [Goal Pipeline](https://directive.run/ai/guides/goal-pipeline)
|