@teamix-evo/mcp 0.4.0 → 0.4.3

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.
Files changed (30) hide show
  1. package/dist/cli.js +64 -16
  2. package/dist/cli.js.map +1 -1
  3. package/dist/data/adr/0001-three-layer-alignment.md +11 -11
  4. package/dist/data/adr/0005-ui-no-variant.md +4 -4
  5. package/dist/data/adr/0006-ui-upgrade-no-baseline.md +6 -6
  6. package/dist/data/adr/0010-design-default-and-variants.md +1 -1
  7. package/dist/data/adr/0019-project-upgrade-flow.md +13 -13
  8. package/dist/data/adr/0021-semantic-color-api-unification.md +127 -0
  9. package/dist/data/adr/0022-preferences-css-boundary.md +75 -0
  10. package/dist/data/adr/0023-cursor-pointer-explicit-in-component-source.md +70 -0
  11. package/dist/data/adr/0024-scoped-css-radix-state-conflict.md +99 -0
  12. package/dist/data/adr/0025-component-props-explicit-declaration.md +145 -0
  13. package/dist/data/adr/0026-component-level-token-alias.md +107 -0
  14. package/dist/data/adr/0027-component-visual-token-alignment.md +127 -0
  15. package/dist/data/adr/0028-ui-component-categorization.md +112 -0
  16. package/dist/data/adr/0029-input-split-and-prefix-suffix-removal.md +68 -0
  17. package/dist/data/adr/0030-skill-uni-manager-uplift.md +56 -0
  18. package/dist/data/adr/0031-skill-templates-decoupling.md +77 -0
  19. package/dist/data/adr/0032-opentrek-v4.1-brand-token-alignment.md +129 -0
  20. package/dist/data/adr/0033-entry-skill-global-only-scope.md +64 -0
  21. package/dist/data/adr/0034-skills-cli-verb-alignment.md +61 -0
  22. package/dist/data/adr/0035-skills-update-scope-and-lock-gates.md +69 -0
  23. package/dist/data/adr/0036-ui-v2-shadcn-baseline-rebuild.md +146 -0
  24. package/dist/data/adr/0037-filter-bar-composable-architecture.md +426 -0
  25. package/dist/data/adr/0038-create-agents-md-skill-trigger-fallback.md +99 -0
  26. package/dist/data/adr/0040-component-source-layer-upgrade-flow.md +104 -0
  27. package/dist/data/adr/README.md +41 -28
  28. package/dist/index.js +64 -16
  29. package/dist/index.js.map +1 -1
  30. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -91,33 +91,46 @@ function parseFrontmatter(text) {
91
91
 
92
92
  // src/groups/registry.ts
93
93
  var ListComponentsInput = z.object({
94
- status: z.enum(["stable", "experimental", "deprecated"]).optional()
94
+ status: z.enum(["stable", "experimental", "deprecated"]).optional(),
95
+ /**
96
+ * Include archived entries from `manifest.deprecatedEntries` (ADR 0028).
97
+ * Equivalent to `status: "deprecated"` when set alone, but composes with
98
+ * other filters: e.g. unset status + `includeDeprecated: true` returns
99
+ * active + deprecated together.
100
+ */
101
+ includeDeprecated: z.boolean().optional()
95
102
  });
96
103
  var GetComponentMetaInput = z.object({
97
104
  id: z.string().min(1)
98
105
  });
99
106
  var FindComponentsInput = z.object({
100
107
  query: z.string().min(1),
101
- limit: z.number().int().positive().max(100).optional()
108
+ limit: z.number().int().positive().max(100).optional(),
109
+ /** Include archived deprecated entries in matches (ADR 0028). */
110
+ includeDeprecated: z.boolean().optional()
102
111
  });
103
112
  var TOOLS = [
104
113
  {
105
114
  name: "list_components",
106
- description: "List all UI components in the @teamix-evo/ui registry. Optionally filter by status (stable / experimental / deprecated). Returns id, name, description, status, registryDependencies \u2014 small enough for the model to scan whole.",
115
+ description: 'List UI components in the @teamix-evo/ui registry. By default excludes archived `deprecatedEntries` (ADR 0028) \u2014 pass `includeDeprecated: true` (or `status: "deprecated"`) to inspect them, e.g. for upgrade audits. Returns id, name, description, status, registryDependencies \u2014 small enough for the model to scan whole.',
107
116
  inputSchema: {
108
117
  type: "object",
109
118
  properties: {
110
119
  status: {
111
120
  type: "string",
112
121
  enum: ["stable", "experimental", "deprecated"],
113
- description: "Filter by maturity status."
122
+ description: "Filter active entries by maturity status. `deprecated` returns the archived `deprecatedEntries` list."
123
+ },
124
+ includeDeprecated: {
125
+ type: "boolean",
126
+ description: "When true, merge archived `deprecatedEntries` into the result (ADR 0028)."
114
127
  }
115
128
  }
116
129
  }
117
130
  },
118
131
  {
119
132
  name: "get_component_meta",
120
- description: "Fetch the full registry entry + parsed meta.md for a single component by id. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.",
133
+ description: "Fetch the full registry entry + parsed meta.md for a single component by id. Searches both active `entries` and archived `deprecatedEntries`; deprecated hits are flagged via `archived: true` in the payload. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.",
121
134
  inputSchema: {
122
135
  type: "object",
123
136
  properties: {
@@ -131,7 +144,7 @@ var TOOLS = [
131
144
  },
132
145
  {
133
146
  name: "find_components",
134
- description: 'Substring match over component id / name / description. Use when you need a component but don\'t know its exact id (e.g. "find a component supporting async search and pagination"). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',
147
+ description: 'Substring match over component id / name / description. Use when you need a component but don\'t know its exact id (e.g. "find a component supporting async search and pagination"). Excludes archived `deprecatedEntries` by default \u2014 pass `includeDeprecated: true` to widen the search (ADR 0028). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',
135
148
  inputSchema: {
136
149
  type: "object",
137
150
  properties: {
@@ -144,6 +157,10 @@ var TOOLS = [
144
157
  minimum: 1,
145
158
  maximum: 100,
146
159
  description: "Max matches to return (default 10)."
160
+ },
161
+ includeDeprecated: {
162
+ type: "boolean",
163
+ description: "When true, also search archived `deprecatedEntries` (ADR 0028)."
147
164
  }
148
165
  },
149
166
  required: ["query"]
@@ -163,6 +180,9 @@ function pickListEntry(entry) {
163
180
  registryDependencies: entry.registryDependencies ?? []
164
181
  };
165
182
  }
183
+ function pickArchivedEntry(entry) {
184
+ return { ...pickListEntry(entry), archived: true };
185
+ }
166
186
  function createRegistryGroup(opts = {}) {
167
187
  let cache = opts.loaded ?? null;
168
188
  function getManifest() {
@@ -177,30 +197,44 @@ function createRegistryGroup(opts = {}) {
177
197
  if (name === "list_components") {
178
198
  const input = ListComponentsInput.parse(args ?? {});
179
199
  const { manifest } = getManifest();
180
- const entries = manifest.entries.filter((e) => e.type === "component").filter((e) => input.status ? e.status === input.status : true).map(pickListEntry);
200
+ const archived = manifest.deprecatedEntries ?? [];
201
+ if (input.status === "deprecated") {
202
+ const entries = archived.filter((e) => e.type === "component").map(pickArchivedEntry);
203
+ return {
204
+ content: [{ type: "text", text: JSON.stringify(entries, null, 2) }]
205
+ };
206
+ }
207
+ const active = manifest.entries.filter((e) => e.type === "component").filter((e) => input.status ? e.status === input.status : true).map(pickListEntry);
208
+ const merged = input.includeDeprecated ? [
209
+ ...active,
210
+ ...archived.filter((e) => e.type === "component").map(pickArchivedEntry)
211
+ ] : active;
181
212
  return {
182
- content: [{ type: "text", text: JSON.stringify(entries, null, 2) }]
213
+ content: [{ type: "text", text: JSON.stringify(merged, null, 2) }]
183
214
  };
184
215
  }
185
216
  if (name === "get_component_meta") {
186
217
  const input = GetComponentMetaInput.parse(args);
187
218
  const { manifest, rootDir } = getManifest();
188
219
  const entry = manifest.entries.find((e) => e.id === input.id);
189
- if (!entry) {
220
+ const archived = entry ? null : (manifest.deprecatedEntries ?? []).find((e) => e.id === input.id) ?? null;
221
+ const found = entry ?? archived;
222
+ if (!found) {
190
223
  return {
191
224
  content: [
192
225
  {
193
226
  type: "text",
194
- text: `Component not found: ${input.id}. Use list_components to discover ids.`
227
+ text: `Component not found: ${input.id}. Use list_components to discover ids (pass includeDeprecated: true to widen the search).`
195
228
  }
196
229
  ],
197
230
  isError: true
198
231
  };
199
232
  }
200
- const meta = loadMeta(entry, rootDir);
233
+ const meta = loadMeta(found, rootDir);
201
234
  const payload = {
202
- entry,
203
- meta: meta ?? null
235
+ entry: found,
236
+ meta: meta ?? null,
237
+ archived: archived !== null
204
238
  };
205
239
  return {
206
240
  content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
@@ -211,9 +245,23 @@ function createRegistryGroup(opts = {}) {
211
245
  const limit = input.limit ?? 10;
212
246
  const q = input.query.toLowerCase();
213
247
  const { manifest } = getManifest();
214
- const matches = manifest.entries.filter((e) => e.type === "component").filter((e) => {
215
- return e.id.toLowerCase().includes(q) || e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q);
216
- }).slice(0, limit).map(pickListEntry);
248
+ const pool = input.includeDeprecated ? [
249
+ ...manifest.entries.map((e) => ({ entry: e, archived: false })),
250
+ ...(manifest.deprecatedEntries ?? []).map((e) => ({
251
+ entry: e,
252
+ archived: true
253
+ }))
254
+ ] : manifest.entries.map((e) => ({ entry: e, archived: false }));
255
+ const matches = pool.filter(({ entry }) => entry.type === "component").filter(({ entry, archived: a }) => {
256
+ if (!input.includeDeprecated && !a && entry.status === "deprecated") {
257
+ return false;
258
+ }
259
+ return true;
260
+ }).filter(({ entry }) => {
261
+ return entry.id.toLowerCase().includes(q) || entry.name.toLowerCase().includes(q) || entry.description.toLowerCase().includes(q);
262
+ }).slice(0, limit).map(
263
+ ({ entry, archived: a }) => a ? pickArchivedEntry(entry) : pickListEntry(entry)
264
+ );
217
265
  return {
218
266
  content: [
219
267
  {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/groups/registry.ts","../src/manifest-loader.ts","../src/groups/adr.ts","../src/adr-loader.ts","../src/groups/skills.ts","../src/skills-loader.ts","../src/groups/tokens.ts","../src/tokens-loader.ts"],"sourcesContent":["/**\n * Bin entry — speaks stdio MCP.\n *\n * Invoked by AI editors (Cursor / Claude Code / Cline / Aider) via:\n * npx @teamix-evo/mcp\n * or directly:\n * node ./packages/mcp/dist/cli.js\n *\n * See README.md for the per-IDE config snippets.\n */\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createServer } from './server.js';\n\nasync function main(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // Stdio transport keeps the process alive while client is connected.\n}\n\nmain().catch((err) => {\n // Write to stderr so MCP client logs surface the failure.\n // eslint-disable-next-line no-console -- stderr logging at process boundary\n console.error('[teamix-evo-mcp] fatal:', err);\n process.exit(1);\n});\n","/**\n * Main MCP server — composes multiple tool groups into one stdio process.\n *\n * Architecture per [ADR 0011](../../../docs/adr/0011-mcp-single-package-multi-group.md):\n * single package / single bin / multiple tool groups. Groups added in later\n * milestones (tokens v0.6, adr v0.7, scenario v0.8) plug in here without\n * touching the transport or ListTools/CallTool handler logic.\n *\n * Tool dispatch:\n * - `tools/list` returns the union of all groups' tools.\n * - `tools/call` walks the group list in registration order; the first group\n * whose `handle` returns a non-`undefined` result wins. Tool-name uniqueness\n * across groups is the responsibility of group authors (see ADR 0011 §5\n * for the `<group>_<verb>_<noun>` naming convention; `registry` is the\n * historical exception).\n */\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { createRegistryGroup, type RegistryGroupOptions } from './groups/registry.js';\nimport { createAdrGroup, type AdrGroupOptions } from './groups/adr.js';\nimport { createSkillsGroup, type SkillsGroupOptions } from './groups/skills.js';\nimport { createTokensGroup, type TokensGroupOptions } from './groups/tokens.js';\nimport type { ToolGroup } from './types.js';\n\nexport interface ServerOptions {\n /** Options forwarded to the registry group. Pass `loaded` in tests. */\n registry?: RegistryGroupOptions;\n /** Options forwarded to the adr group. Pass `loaded` in tests. */\n adr?: AdrGroupOptions;\n /** Options forwarded to the skills group. Pass `loaded` in tests. */\n skills?: SkillsGroupOptions;\n /** Options forwarded to the tokens group. Pass `loaded` in tests. */\n tokens?: TokensGroupOptions;\n}\n\nexport function createServer(opts: ServerOptions = {}): Server {\n const groups: ToolGroup[] = [\n createRegistryGroup(opts.registry),\n createAdrGroup(opts.adr),\n createSkillsGroup(opts.skills),\n createTokensGroup(opts.tokens),\n // Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8\n ];\n\n // Sanity check: tool names must be unique across groups.\n const seen = new Set<string>();\n for (const group of groups) {\n for (const tool of group.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Duplicate MCP tool name across groups: ${tool.name}. ` +\n `Each group must use unique tool names — see ADR 0011 §5.`,\n );\n }\n seen.add(tool.name);\n }\n }\n\n const allTools = groups.flatMap((g) => g.tools);\n\n const server = new Server(\n {\n name: '@teamix-evo/mcp',\n version: '0.2.0',\n },\n {\n capabilities: { tools: {} },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: allTools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const { name, arguments: args } = req.params;\n for (const group of groups) {\n const result = await group.handle(name, args);\n if (result !== undefined) return result;\n }\n return {\n content: [\n {\n type: 'text',\n text: `Unknown tool: ${name}. Use tools/list to discover available tools.`,\n },\n ],\n isError: true,\n };\n });\n\n return server;\n}\n","/**\n * Registry tool group — exposes the @teamix-evo/ui component registry to AI\n * editors.\n *\n * Originally `src/server.ts` of `@teamix-evo/registry-mcp`. Moved here as part\n * of [ADR 0011](../../../../docs/adr/0011-mcp-single-package-multi-group.md)\n * single-package / multi-group restructure.\n *\n * Tool naming is the **historical exception**: `list_components` /\n * `get_component_meta` / `find_components` keep their unprefixed names because\n * they're already in production AI client memory (see ADR 0011 §5). All\n * future groups (`design_*`, `adr_*`, `scenario_*`) MUST use the\n * `<group>_<verb>_<noun>` prefix convention.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadManifest,\n loadMeta,\n type LoadedManifest,\n} from '../manifest-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { UiEntry } from '@teamix-evo/registry';\n\nconst ListComponentsInput = z.object({\n status: z.enum(['stable', 'experimental', 'deprecated']).optional(),\n});\n\nconst GetComponentMetaInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindComponentsInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'list_components',\n description:\n 'List all UI components in the @teamix-evo/ui registry. Optionally filter by status (stable / experimental / deprecated). Returns id, name, description, status, registryDependencies — small enough for the model to scan whole.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['stable', 'experimental', 'deprecated'],\n description: 'Filter by maturity status.',\n },\n },\n },\n },\n {\n name: 'get_component_meta',\n description:\n 'Fetch the full registry entry + parsed meta.md for a single component by id. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Component id (e.g. \"button\", \"data-table\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'find_components',\n description:\n 'Substring match over component id / name / description. Use when you need a component but don\\'t know its exact id (e.g. \"find a component supporting async search and pagination\"). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Free-text query.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 10).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickListEntry(entry: UiEntry) {\n return {\n id: entry.id,\n name: entry.name,\n type: entry.type,\n description: entry.description,\n status: entry.status,\n deprecatedReason: entry.deprecatedReason,\n replacedBy: entry.replacedBy,\n registryDependencies: entry.registryDependencies ?? [],\n };\n}\n\nexport interface RegistryGroupOptions {\n /** Pre-loaded manifest (used in tests to avoid filesystem). */\n loaded?: LoadedManifest;\n}\n\nexport function createRegistryGroup(opts: RegistryGroupOptions = {}): ToolGroup {\n // Lazy-load the manifest so failures yield a tool-call error rather than\n // blocking server startup (which would prevent the MCP client from even\n // discovering the tools and seeing a usable error message).\n let cache: LoadedManifest | null = opts.loaded ?? null;\n function getManifest(): LoadedManifest {\n if (!cache) cache = loadManifest();\n return cache;\n }\n\n return {\n name: 'registry',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'list_components') {\n const input = ListComponentsInput.parse(args ?? {});\n const { manifest } = getManifest();\n const entries = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => (input.status ? e.status === input.status : true))\n .map(pickListEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'get_component_meta') {\n const input = GetComponentMetaInput.parse(args);\n const { manifest, rootDir } = getManifest();\n const entry = manifest.entries.find((e) => e.id === input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Component not found: ${input.id}. Use list_components to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const meta = loadMeta(entry, rootDir);\n const payload = {\n entry,\n meta: meta ?? null,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n }\n\n if (name === 'find_components') {\n const input = FindComponentsInput.parse(args);\n const limit = input.limit ?? 10;\n const q = input.query.toLowerCase();\n const { manifest } = getManifest();\n const matches = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => {\n return (\n e.id.toLowerCase().includes(q) ||\n e.name.toLowerCase().includes(q) ||\n e.description.toLowerCase().includes(q)\n );\n })\n .slice(0, limit)\n .map(pickListEntry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: matches.length,\n results: matches,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n // Unreachable — TOOL_NAMES guard above ensures we only enter known names.\n return undefined;\n },\n };\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { UiPackageManifestSchema } from '@teamix-evo/registry';\nimport type { UiEntry, UiPackageManifest } from '@teamix-evo/registry';\n\n/**\n * Resolves the `@teamix-evo/ui/manifest.json` path using a layered strategy:\n *\n * 1. `TEAMIX_EVO_UI_MANIFEST` env var (absolute path)\n * 2. `<cwd>/node_modules/@teamix-evo/ui/manifest.json`\n * 3. Walking up parent directories until a matching `node_modules/...` is found\n * 4. Throws with a clear error message\n */\nexport function resolveManifestPath(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_UI_MANIFEST;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n // Limit walk to prevent runaway in pathological filesystems.\n for (let i = 0; i < 16; i++) {\n const candidate = join(\n dir,\n 'node_modules',\n '@teamix-evo',\n 'ui',\n 'manifest.json',\n );\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/ui/manifest.json — the UI registry is not installed in this project.',\n '',\n 'Fix one of:',\n ` 1. Install the package: pnpm add @teamix-evo/ui (or npm/yarn equivalent)`,\n ` 2. Point env at an existing manifest: export TEAMIX_EVO_UI_MANIFEST=/abs/path/to/manifest.json`,\n '',\n `Searched: $TEAMIX_EVO_UI_MANIFEST, then walked up from ${startDir} looking for node_modules/@teamix-evo/ui/manifest.json (16 levels).`,\n 'Note: MCP currently has no online fallback — it does not fetch from the npm registry / unpkg.',\n ].join('\\n'),\n );\n}\n\nexport interface LoadedManifest {\n manifest: UiPackageManifest;\n /** Directory of the manifest.json itself; used to resolve `meta.md` paths. */\n rootDir: string;\n}\n\n/**\n * Loads and Zod-validates the UI package manifest.\n * Throws on invalid manifest with the underlying Zod error attached.\n */\nexport function loadManifest(path?: string): LoadedManifest {\n const manifestPath = path ?? resolveManifestPath();\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const result = UiPackageManifestSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(\n `Invalid manifest at ${manifestPath}: ${result.error.message}`,\n );\n }\n return {\n manifest: result.data,\n rootDir: dirname(manifestPath),\n };\n}\n\n/**\n * Frontmatter + body extracted from a `<id>.meta.md` file.\n * Frontmatter is parsed as a flat key/value map (no YAML library dep —\n * meta.md frontmatters are intentionally simple).\n */\nexport interface ParsedMeta {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Reads and minimally parses a `<id>.meta.md` file. Returns `null` if the\n * meta file is missing or the entry didn't declare one.\n *\n * Frontmatter parser is minimal (single-line `key: value` pairs only). It\n * does NOT support nested or array YAML — sufficient for the meta.md format\n * documented in packages/ui/AGENTS.md §三.E.\n */\nexport function loadMeta(\n entry: UiEntry,\n rootDir: string,\n): ParsedMeta | null {\n if (!entry.meta) return null;\n const path = join(rootDir, entry.meta);\n if (!existsSync(path)) return null;\n const text = readFileSync(path, 'utf-8');\n return parseFrontmatter(text);\n}\n\nfunction parseFrontmatter(text: string): ParsedMeta {\n const FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n const match = text.match(FM_RE);\n if (!match) {\n return { frontmatter: {}, body: text };\n }\n const fm: Record<string, string> = {};\n // Capture group [1] is guaranteed when match succeeds.\n for (const line of match[1]!.split('\\n')) {\n const m = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (m) fm[m[1]!] = m[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return {\n frontmatter: fm,\n body: text.slice(match[0].length),\n };\n}\n","/**\n * ADR tool group — exposes Architecture Decision Records to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md),\n * new groups use the `<group>_<verb>` prefix convention:\n *\n * - `adr_list` — index of all ADRs (id, title, status, date)\n * - `adr_get` — full markdown body for one ADR\n * - `adr_find` — substring search across title + body\n *\n * Use this group to let AI agents:\n *\n * - Cite ADRs in PR reviews (\"this change violates ADR 0008 §2.B\")\n * - Resolve \"why was this done?\" questions before recommending refactors\n * - Discover related ADRs when proposing a new decision\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadAdrIndex,\n loadAdrContent,\n findAdr,\n type LoadedAdrs,\n} from '../adr-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst ListInput = z.object({\n /** Match `Status` line by substring (case-insensitive). */\n status: z.string().min(1).optional(),\n});\n\nconst GetInput = z.object({\n /** ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\"). */\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * When true, returns a snippet (~200 chars) around each match so the model\n * can decide whether to fetch the full ADR. Defaults to true.\n */\n withSnippets: z.boolean().optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'adr_list',\n description:\n 'List all Architecture Decision Records (ADRs) in docs/adr/. Returns id (4-digit), slug, title, status, date, region for each. Use this as the first call to discover which decisions exist before drilling into one with adr_get. Filter by status substring (e.g. \"Accepted\" / \"Proposed\" / \"Superseded\") to narrow down.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n description:\n 'Optional case-insensitive substring filter against the ADR Status line. Examples: \"Accepted\", \"Proposed\", \"Superseded\".',\n },\n },\n },\n },\n {\n name: 'adr_get',\n description:\n 'Fetch the full markdown body of one ADR by id (\"0011\") or slug (\"0011-mcp-single-package-multi-group\"). Returns the entry metadata + raw markdown so the model can cite specific sections (Context / Decision / Consequences / Source). Use after adr_list / adr_find to read a specific decision in full.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description:\n 'ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'adr_find',\n description:\n 'Substring search across ADR titles and bodies (case-insensitive). Use when you remember a phrase (\"source-mirror\", \"lint-core\", \"no baseline\") but not which ADR it lives in. Returns up to `limit` matches (default 10) with optional snippets (~200 chars around each match). Combine with adr_get for the full text.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n withSnippets: {\n type: 'boolean',\n description: 'Include ~200-char snippet around each match (default true).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(e: {\n id: string;\n slug: string;\n title: string;\n status: string;\n date: string;\n region: string;\n}) {\n return {\n id: e.id,\n slug: e.slug,\n title: e.title,\n status: e.status,\n date: e.date,\n region: e.region,\n };\n}\n\nconst SNIPPET_RADIUS = 100;\n\nfunction snippet(text: string, index: number): string {\n const start = Math.max(0, index - SNIPPET_RADIUS);\n const end = Math.min(text.length, index + SNIPPET_RADIUS);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return prefix + text.slice(start, end).replace(/\\s+/g, ' ').trim() + suffix;\n}\n\nexport interface AdrGroupOptions {\n /** Pre-loaded index (used in tests to avoid filesystem). */\n loaded?: LoadedAdrs;\n}\n\nexport function createAdrGroup(opts: AdrGroupOptions = {}): ToolGroup {\n let cache: LoadedAdrs | null = opts.loaded ?? null;\n function getIndex(): LoadedAdrs {\n if (!cache) cache = loadAdrIndex();\n return cache;\n }\n\n return {\n name: 'adr',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'adr_list') {\n const input = ListInput.parse(args ?? {});\n const idx = getIndex();\n const needle = input.status?.toLowerCase();\n const entries = idx.entries\n .filter((e) =>\n needle ? e.status.toLowerCase().includes(needle) : true,\n )\n .map(pickEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'adr_get') {\n const input = GetInput.parse(args);\n const idx = getIndex();\n const entry = findAdr(idx, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `ADR not found: ${input.id}. Use adr_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const text = loadAdrContent(entry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { entry: pickEntry(entry), content: text },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'adr_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const withSnippets = input.withSnippets ?? true;\n const needle = input.query.toLowerCase();\n const idx = getIndex();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n snippets?: string[];\n hitCount: number;\n }> = [];\n for (const entry of idx.entries) {\n const body = loadAdrContent(entry).toLowerCase();\n const titleHit = entry.title.toLowerCase().includes(needle);\n if (!titleHit && !body.includes(needle)) continue;\n\n const snippets: string[] = [];\n if (withSnippets) {\n const rawBody = loadAdrContent(entry);\n let from = 0;\n // Up to 3 snippets per ADR to keep response compact.\n for (let i = 0; i < 3; i++) {\n const at = rawBody.toLowerCase().indexOf(needle, from);\n if (at < 0) break;\n snippets.push(snippet(rawBody, at));\n from = at + needle.length;\n }\n }\n // Count total hits in body for ranking.\n let hits = titleHit ? 1 : 0;\n let from = 0;\n for (;;) {\n const at = body.indexOf(needle, from);\n if (at < 0) break;\n hits++;\n from = at + needle.length;\n }\n matches.push({\n entry: pickEntry(entry),\n ...(withSnippets ? { snippets } : {}),\n hitCount: hits,\n });\n }\n matches.sort((a, b) => b.hitCount - a.hitCount);\n const sliced = matches.slice(0, limit);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: sliced.length,\n totalMatchingAdrs: matches.length,\n results: sliced,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for ADR (Architecture Decision Record) markdown files.\n *\n * ADRs live in `docs/adr/<NNNN>-<slug>.md` per [ADR 0007](../../../docs/adr/0007-governance-docs-at-root.md).\n * Each file has the shape:\n *\n * ```md\n * # 0011. <title>\n *\n * - **Status**: Proposed | Accepted | Superseded by NNNN | Deprecated\n * - **Date**: YYYY-MM-DD\n * - **Region**: 0100–0999 协议与工具\n * - **Related ADR**: [0007 ...](...)\n *\n * ## Context\n * ...\n * ```\n *\n * This loader parses just enough metadata to power the `adr_list` /\n * `adr_get` / `adr_find` MCP tools (see [`groups/adr.ts`](./groups/adr.ts)).\n * `README.md` and `_template.md` are skipped — they are not ADRs.\n */\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport interface AdrEntry {\n /** Numeric id, e.g. \"0011\". Derived from the filename prefix. */\n id: string;\n /** Filename without `.md`, e.g. \"0011-mcp-single-package-multi-group\". */\n slug: string;\n /** Title after \"NNNN. \" in the H1 line. */\n title: string;\n /** Raw status string from the `- **Status**:` line. Empty if missing. */\n status: string;\n /** Date from the `- **Date**:` line (YYYY-MM-DD). Empty if missing. */\n date: string;\n /** Optional region label (`0100–0999 协议与工具`). Empty if missing. */\n region: string;\n /** Absolute path to the source file (for `adr_get`). */\n filePath: string;\n}\n\nexport interface LoadedAdrs {\n /** Directory containing the ADR `.md` files. */\n rootDir: string;\n entries: AdrEntry[];\n}\n\n/**\n * Resolves the ADR directory using a layered strategy:\n *\n * 1. `TEAMIX_EVO_ADR_ROOT` env var (absolute path)\n * 2. Bundled snapshot at `<mcp-pkg>/dist/data/adr/` (works in consumer projects\n * after `pnpm add @teamix-evo/mcp` — see tsup.config.ts onSuccess copy)\n * 3. Walk up from cwd looking for `docs/adr/` (monorepo layout)\n * 4. Walk up from cwd looking for `.teamix-evo/adr/` (consumer override)\n * 5. Throws with a clear error\n */\nexport function resolveAdrRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_ADR_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n // Bundled snapshot inside the mcp package itself. import.meta.url at\n // runtime resolves to dist/cli.js or dist/index.js inside the published\n // package; its sibling `data/adr/` is populated by tsup onSuccess.\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n const bundled = join(here, 'data', 'adr');\n if (existsSync(bundled)) return bundled;\n } catch {\n // import.meta.url may be unavailable in some test environments.\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'docs', 'adr'),\n join(dir, '.teamix-evo', 'adr'),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate ADR directory.',\n `Tried env TEAMIX_EVO_ADR_ROOT, mcp-bundled snapshot, and walked up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,\n 'Either install @teamix-evo/mcp (carries ADR snapshot) or set TEAMIX_EVO_ADR_ROOT to an absolute path.',\n ].join(' '),\n );\n}\n\nconst SKIP_FILES = new Set(['README.md', '_template.md']);\nconst ID_RE = /^(\\d{4})-/;\nconst H1_RE = /^#\\s+\\d{4}\\.\\s+(.+?)\\s*$/m;\nconst STATUS_RE = /^-\\s+\\*\\*Status\\*\\*:\\s*(.+?)\\s*$/m;\nconst DATE_RE = /^-\\s+\\*\\*Date\\*\\*:\\s*(.+?)\\s*$/m;\nconst REGION_RE = /^-\\s+\\*\\*Region\\*\\*:\\s*(.+?)\\s*$/m;\n\nfunction parseAdr(slug: string, filePath: string): AdrEntry | null {\n const idMatch = slug.match(ID_RE);\n if (!idMatch) return null;\n const id = idMatch[1]!;\n\n const text = readFileSync(filePath, 'utf-8');\n const titleMatch = text.match(H1_RE);\n const statusMatch = text.match(STATUS_RE);\n const dateMatch = text.match(DATE_RE);\n const regionMatch = text.match(REGION_RE);\n\n return {\n id,\n slug,\n title: titleMatch?.[1] ?? slug,\n status: statusMatch?.[1] ?? '',\n date: dateMatch?.[1] ?? '',\n region: regionMatch?.[1] ?? '',\n filePath,\n };\n}\n\nexport function loadAdrIndex(rootDir?: string): LoadedAdrs {\n const root = rootDir ?? resolveAdrRoot();\n const files = readdirSync(root).filter(\n (f) => f.endsWith('.md') && !SKIP_FILES.has(f),\n );\n const entries: AdrEntry[] = [];\n for (const f of files) {\n const slug = f.replace(/\\.md$/, '');\n const entry = parseAdr(slug, join(root, f));\n if (entry) entries.push(entry);\n }\n entries.sort((a, b) => a.id.localeCompare(b.id));\n return { rootDir: root, entries };\n}\n\n/**\n * Look up one ADR by id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").\n * Returns `null` if no match.\n */\nexport function findAdr(\n loaded: LoadedAdrs,\n idOrSlug: string,\n): AdrEntry | null {\n const needle = idOrSlug.trim();\n if (/^\\d{4}$/.test(needle)) {\n return loaded.entries.find((e) => e.id === needle) ?? null;\n }\n return (\n loaded.entries.find((e) => e.slug === needle) ??\n loaded.entries.find((e) => e.id === needle) ??\n null\n );\n}\n\nexport function loadAdrContent(entry: AdrEntry): string {\n return readFileSync(entry.filePath, 'utf-8');\n}\n","/**\n * Skills tool group — exposes `@teamix-evo/skills` SKILL.md content to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md):\n *\n * - `skills_list` — index of all shipped skills (id, name, description, version)\n * - `skills_get` — full SKILL.md content + attachment names for one skill\n * - `skills_find` — substring search across `description` (the AI trigger) + body\n *\n * `description` in SKILL.md frontmatter is the AI trigger contract per\n * [ADR 0013](../../../../docs/adr/0013-skills-source-mirror.md). Searching it\n * is the primary use of `skills_find`.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadSkillsManifest,\n loadSkillContent,\n findSkill,\n type LoadedSkills,\n} from '../skills-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { SkillEntry } from '@teamix-evo/registry';\n\nconst ListInput = z.object({});\n\nconst GetInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * Scope: 'description' (default — fast, only matches the AI trigger contract)\n * or 'body' (slower — matches across SKILL.md prose, useful for \"where do we\n * mention X\" questions).\n */\n scope: z.enum(['description', 'body', 'all']).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'skills_list',\n description:\n 'List all SKILL.md entries shipped by @teamix-evo/skills. Returns id, name, description (the AI trigger contract), version, source path, ides, updateStrategy. Use this to discover which skills exist before invoking one via the IDE\\'s skill mechanism.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'skills_get',\n description:\n 'Fetch the full SKILL.md content (frontmatter + body) for one skill by id or name. Also lists attachment files (sibling .md docs the skill references). Use after skills_list / skills_find to read the actual rules / decision tree / checklist that the skill encodes.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Skill id or name (matches manifest.skills[].id or .name).',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'skills_find',\n description:\n 'Substring search across skill descriptions and bodies. Default scope is `description` (matches the AI trigger contract — fast). Set `scope: \"body\"` to search SKILL.md prose, or `scope: \"all\"` for both. Use when you remember a phrase (\"token refresh\", \"design review\", \"drift scan\") but not the skill id.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n scope: {\n type: 'string',\n enum: ['description', 'body', 'all'],\n description:\n 'Where to search: \"description\" (frontmatter, default), \"body\" (SKILL.md prose), or \"all\".',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(s: SkillEntry) {\n return {\n id: s.id,\n name: s.name,\n description: s.description,\n version: s.version,\n source: s.source,\n ides: s.ides ?? [],\n updateStrategy: s.updateStrategy ?? 'managed',\n template: s.template ?? false,\n };\n}\n\nexport interface SkillsGroupOptions {\n loaded?: LoadedSkills;\n}\n\nexport function createSkillsGroup(opts: SkillsGroupOptions = {}): ToolGroup {\n let cache: LoadedSkills | null = opts.loaded ?? null;\n function getManifest(): LoadedSkills {\n if (!cache) cache = loadSkillsManifest();\n return cache;\n }\n\n return {\n name: 'skills',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'skills_list') {\n ListInput.parse(args ?? {});\n const { manifest } = getManifest();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(manifest.skills.map(pickEntry), null, 2),\n },\n ],\n };\n }\n\n if (name === 'skills_get') {\n const input = GetInput.parse(args);\n const loaded = getManifest();\n const entry = findSkill(loaded, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill not found: ${input.id}. Use skills_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const content = loadSkillContent(entry, loaded.rootDir);\n if (!content) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill source missing on disk for \"${entry.id}\" (expected at ${entry.source}). Check packages/skills installation.`,\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n entry: pickEntry(entry),\n attachments: content.attachments,\n content: content.text,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'skills_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const scope = input.scope ?? 'description';\n const needle = input.query.toLowerCase();\n const loaded = getManifest();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n hitIn: 'description' | 'body' | 'both';\n }> = [];\n\n for (const entry of loaded.manifest.skills) {\n const descHit =\n scope !== 'body' &&\n entry.description.toLowerCase().includes(needle);\n let bodyHit = false;\n if (scope === 'body' || scope === 'all') {\n const content = loadSkillContent(entry, loaded.rootDir);\n if (content) {\n bodyHit = content.text.toLowerCase().includes(needle);\n }\n }\n if (!descHit && !bodyHit) continue;\n matches.push({\n entry: pickEntry(entry),\n hitIn:\n descHit && bodyHit\n ? 'both'\n : descHit\n ? 'description'\n : 'body',\n });\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n scope,\n limit,\n count: Math.min(matches.length, limit),\n totalMatches: matches.length,\n results: matches.slice(0, limit),\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for `@teamix-evo/skills` (the skills source-of-truth package).\n *\n * Reads `packages/skills/manifest.json` + each `skills/<id>/SKILL.md`. The\n * frontmatter `description` is the AI trigger contract (see ADR 0013) and is\n * what `skills_find` searches over.\n *\n * In a consumer project, the same shape lives under `node_modules/@teamix-evo/skills/`.\n * Resolution order mirrors the registry/adr loaders:\n *\n * 1. `TEAMIX_EVO_SKILLS_ROOT` env var (absolute path to the package dir)\n * 2. Walk up from cwd looking for `packages/skills/` (monorepo)\n * 3. Walk up from cwd looking for `node_modules/@teamix-evo/skills/` (consumer)\n * 4. Throws with a clear error\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport {\n SkillsPackageManifestSchema,\n type SkillsPackageManifest,\n type SkillEntry,\n} from '@teamix-evo/registry';\n\nexport interface LoadedSkills {\n /** Absolute path to the package root containing manifest.json. */\n rootDir: string;\n manifest: SkillsPackageManifest;\n}\n\nexport function resolveSkillsRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_SKILLS_ROOT;\n if (envPath && existsSync(join(envPath, 'manifest.json'))) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'packages', 'skills'),\n join(dir, 'node_modules', '@teamix-evo', 'skills'),\n ];\n for (const c of candidates) {\n if (existsSync(join(c, 'manifest.json'))) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/skills root.',\n `Tried env TEAMIX_EVO_SKILLS_ROOT and walked up from ${startDir} for packages/skills/ or node_modules/@teamix-evo/skills/.`,\n 'Install @teamix-evo/skills as a devDependency in your project (the scaffold adds it automatically).',\n ].join(' '),\n );\n}\n\nexport function loadSkillsManifest(rootDir?: string): LoadedSkills {\n const root = rootDir ?? resolveSkillsRoot();\n const manifestPath = join(root, 'manifest.json');\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const parsed = SkillsPackageManifestSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(\n `Invalid skills manifest at ${manifestPath}: ${parsed.error.message}`,\n );\n }\n return { rootDir: root, manifest: parsed.data };\n}\n\nexport interface SkillContent {\n entry: SkillEntry;\n /** Full SKILL.md text (frontmatter + body). */\n text: string;\n /** Just the body, frontmatter stripped. Null if SKILL.md missing. */\n body: string | null;\n /** Parsed frontmatter as flat string map. */\n frontmatter: Record<string, string>;\n /** Absolute path to SKILL.md. */\n filePath: string;\n /**\n * Other markdown files attached to the skill (siblings of SKILL.md), e.g.\n * generation-flow.md / boundaries.md / checklist.md. Just the relative names —\n * the model can fetch them by name via a follow-up tool call.\n */\n attachments: string[];\n}\n\nconst FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n\nfunction parseFrontmatter(text: string): {\n frontmatter: Record<string, string>;\n body: string;\n} {\n const m = text.match(FM_RE);\n if (!m) return { frontmatter: {}, body: text };\n const fm: Record<string, string> = {};\n for (const line of m[1]!.split('\\n')) {\n const kv = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (kv) fm[kv[1]!] = kv[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return { frontmatter: fm, body: text.slice(m[0].length) };\n}\n\nexport function loadSkillContent(\n entry: SkillEntry,\n rootDir: string,\n): SkillContent | null {\n const sourcePath = join(rootDir, entry.source);\n if (!existsSync(sourcePath)) return null;\n\n // Skills are typically directories with SKILL.md inside.\n let skillMdPath: string;\n let attachments: string[] = [];\n const dirCandidate = join(sourcePath, 'SKILL.md');\n if (existsSync(dirCandidate)) {\n skillMdPath = dirCandidate;\n // Light attachment scan: top-level .md siblings of SKILL.md.\n try {\n attachments = readdirSync(sourcePath)\n .filter((f) => f.endsWith('.md') && f !== 'SKILL.md')\n .filter((f) => {\n try {\n return statSync(join(sourcePath, f)).isFile();\n } catch {\n return false;\n }\n });\n } catch {\n attachments = [];\n }\n } else {\n // Single-file skill (entry.source points directly at a .md).\n skillMdPath = sourcePath;\n }\n\n const text = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, body } = parseFrontmatter(text);\n return {\n entry,\n text,\n body,\n frontmatter,\n filePath: skillMdPath,\n attachments,\n };\n}\n\nexport function findSkill(\n loaded: LoadedSkills,\n idOrName: string,\n): SkillEntry | null {\n const needle = idOrName.trim();\n return (\n loaded.manifest.skills.find((s) => s.id === needle) ??\n loaded.manifest.skills.find((s) => s.name === needle) ??\n null\n );\n}\n","/**\n * Tokens tool group — exposes the consumer project's design tokens\n * to AI editors via MCP.\n *\n * Per [ADR 0020](../../../../docs/adr/0020-design-to-tokens-skill-fusion.md),\n * design knowledge now lives in @teamix-evo/skills (AI reads skill files\n * directly). MCP only provides token value lookup — the one thing AI\n * can't get from a static skill file.\n *\n * - `tokens_get` — full snapshot (base JSON + theme/overrides CSS) for copy-paste\n * - `tokens_list` — flat list of token entries for introspection (category/name/values)\n * - `tokens_search` — substring search across category / name / description / values\n *\n * When `tokens/` directory is absent (project hasn't run `tokens init`),\n * the tools return empty results with a `note` field.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadTokens,\n readTokens,\n listTokens,\n searchTokens,\n type LoadedTokens,\n} from '../tokens-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst EmptyInput = z.object({});\nconst SearchInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().min(1).max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'tokens_get',\n description:\n \"Fetch the consumer project's design tokens — parsed JSON from `tokens/base.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each result lists `sources` so you can cite paths.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_list',\n description:\n 'List ALL design tokens as a flat array of entries `{ category, name, type, values, description }`. Categories come from top-level keys of base.tokens.json (e.g. `color`, `radius`, `spacing`). Each entry exposes resolved values keyed by mode (e.g. `light` / `dark` / `default`). Use this BEFORE writing styles to discover what semantic names are available — much cheaper than parsing the whole CSS file. Use `tokens_search` instead when you have a keyword.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_search',\n description:\n 'Substring match across token category / name / description / values (case-insensitive). Use when you remember a phrase (\"primary\" / \"destructive\" / \"card-gap\") but not the exact path. Returns up to `limit` matches (default 20). Combine with `tokens_get` if you need raw CSS text after locating an entry.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 20).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nexport interface TokensGroupOptions {\n /** Pre-loaded tokens snapshot (used by tests). When omitted, the loader walks cwd. */\n loaded?: LoadedTokens | null;\n /** Override the start directory for cwd-relative resolution (used by tests). */\n rootDir?: string;\n}\n\nconst NO_TOKENS_NOTE =\n 'tokens/ directory not found in this project. Run `npx teamix-evo tokens init <variant>` to install design tokens.';\n\nexport function createTokensGroup(opts: TokensGroupOptions = {}): ToolGroup {\n let cache: LoadedTokens | null | undefined =\n opts.loaded === undefined ? undefined : opts.loaded;\n function getLoaded(): LoadedTokens | null {\n if (cache === undefined) cache = loadTokens(opts.rootDir);\n return cache;\n }\n\n return {\n name: 'tokens',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n const loaded = getLoaded();\n\n if (name === 'tokens_get') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ sources: [], note: NO_TOKENS_NOTE });\n }\n return jsonResult(readTokens(loaded));\n }\n\n if (name === 'tokens_list') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n tokens: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(listTokens(loaded));\n }\n\n if (name === 'tokens_search') {\n const parsed = SearchInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n query: parsed.query,\n matches: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(searchTokens(loaded, parsed.query, parsed.limit));\n }\n\n return undefined;\n },\n };\n}\n\nfunction jsonResult(payload: unknown): ToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n}\n","/**\n * Loader for the consumer project's `.teamix-evo/` state.\n *\n * Per [ADR 0020](../../../docs/adr/0020-design-to-tokens-skill-fusion.md) the\n * MCP `tokens` group reads the **installed** tokens of a teamix-evo project.\n * The loader walks up from the cwd looking for `.teamix-evo/` and, if a\n * `tokens-lock.json` is present, records the variant for downstream tools.\n *\n * Resolution order:\n *\n * 1. `TEAMIX_EVO_TOKENS_ROOT` env var (absolute path to the `.teamix-evo/` dir)\n * 2. Walk up from cwd looking for `.teamix-evo/`\n * 3. Returns `null` (not an error — projects without teamix-evo init should\n * get empty tool results with a `note`, not a thrown exception)\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface LoadedTokens {\n /** Absolute path to `.teamix-evo/` in the consumer project. */\n rootDir: string;\n /** Variant name read from `tokens-lock.json`, or null if missing. */\n variant: string | null;\n}\n\nexport function resolveTokensRoot(\n startDir: string = process.cwd(),\n): string | null {\n const envPath = process.env.TEAMIX_EVO_TOKENS_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidate = join(dir, '.teamix-evo');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function loadTokens(rootDir?: string): LoadedTokens | null {\n const root = rootDir ?? resolveTokensRoot();\n if (!root) return null;\n\n let variant: string | null = null;\n const lockPath = join(root, 'tokens-lock.json');\n if (existsSync(lockPath)) {\n try {\n const raw = JSON.parse(readFileSync(lockPath, 'utf-8')) as {\n variant?: string;\n };\n variant = typeof raw.variant === 'string' ? raw.variant : null;\n } catch {\n variant = null;\n }\n }\n return { rootDir: root, variant };\n}\n\nexport interface TokenSnapshot {\n /** Parsed contents of `base.tokens.json` if present. */\n base?: unknown;\n /** Raw text of `tokens.theme.css` if present. */\n themeCss?: string;\n /** Raw text of `tokens.overrides.css` if present (user-owned overrides). */\n overridesCss?: string;\n /** Source paths discovered, in load order. */\n sources: string[];\n note?: string;\n}\n\n/**\n * Locate the tokens directory. Tokens live at `<projectRoot>/tokens/`\n * (root-level, per ADR 0020).\n */\nfunction resolveTokensDir(loaded: LoadedTokens): string | null {\n const projectRoot = dirname(loaded.rootDir);\n const rootTokens = join(projectRoot, 'tokens');\n if (existsSync(rootTokens)) return rootTokens;\n return null;\n}\n\nexport function readTokens(loaded: LoadedTokens): TokenSnapshot {\n const tokensDir = resolveTokensDir(loaded);\n const out: TokenSnapshot = { sources: [] };\n if (!tokensDir) {\n out.note = 'tokens/ not found at project root.';\n return out;\n }\n const tryJson = (rel: string): unknown | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n try {\n return JSON.parse(readFileSync(fp, 'utf-8'));\n } catch {\n return undefined;\n }\n };\n const tryText = (rel: string): string | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n return readFileSync(fp, 'utf-8');\n };\n out.base = tryJson('base.tokens.json');\n out.themeCss = tryText('tokens.theme.css');\n out.overridesCss = tryText('tokens.overrides.css');\n return out;\n}\n\nexport interface TokenEntry {\n /** Top-level group from base.tokens.json, e.g. \"color\" / \"radius\" / \"spacing\". */\n category: string;\n /** Token leaf name within the category, e.g. \"primary\" / \"card-foreground\". */\n name: string;\n /** W3C `$type` declared on the token, when present. */\n type?: string;\n /**\n * Resolved values keyed by mode. For W3C tokens with `light` / `dark`\n * sub-objects we emit both; for flat tokens (single `$value`) we emit\n * `default`.\n */\n values: Record<string, string>;\n /** First non-empty `$description` found on the token or its modes. */\n description?: string;\n}\n\nconst W3C_KEYS = new Set(['$value', '$type', '$description', '$extensions']);\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Flatten a W3C-format design-token JSON tree into a list of token entries.\n *\n * The format we ingest is the one shipped by `@teamix-evo/tokens`:\n *\n * { color: { primary: { $type, light: { $value, $description }, dark: { ... } } } }\n *\n * For tokens with `$value` directly under the leaf (no light/dark split) we\n * emit `values = { default: <value> }`.\n *\n * Top-level keys starting with `$` (e.g. `$schema`, `$version`) are skipped.\n */\nexport function flattenTokens(base: unknown): TokenEntry[] {\n if (!isPlainObject(base)) return [];\n const out: TokenEntry[] = [];\n\n for (const [category, group] of Object.entries(base)) {\n if (category.startsWith('$')) continue;\n if (!isPlainObject(group)) continue;\n\n for (const [name, leaf] of Object.entries(group)) {\n if (name.startsWith('$')) continue;\n if (!isPlainObject(leaf)) continue;\n\n const type =\n typeof leaf.$type === 'string' ? (leaf.$type as string) : undefined;\n const values: Record<string, string> = {};\n let description =\n typeof leaf.$description === 'string'\n ? (leaf.$description as string)\n : undefined;\n\n if (typeof leaf.$value === 'string') {\n values.default = leaf.$value as string;\n }\n\n for (const [modeKey, modeVal] of Object.entries(leaf)) {\n if (W3C_KEYS.has(modeKey)) continue;\n if (!isPlainObject(modeVal)) continue;\n if (typeof modeVal.$value === 'string') {\n values[modeKey] = modeVal.$value as string;\n }\n if (\n !description &&\n typeof modeVal.$description === 'string'\n ) {\n description = modeVal.$description as string;\n }\n }\n\n if (Object.keys(values).length === 0) continue;\n\n out.push({\n category,\n name,\n ...(type ? { type } : {}),\n values,\n ...(description ? { description } : {}),\n });\n }\n }\n\n return out;\n}\n\nexport interface TokenListResult {\n variant: string | null;\n tokens: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\nexport function listTokens(loaded: LoadedTokens): TokenListResult {\n const snapshot = readTokens(loaded);\n if (!snapshot.base) {\n return {\n variant: loaded.variant,\n tokens: [],\n sources: snapshot.sources,\n note: snapshot.note ?? 'base.tokens.json not found.',\n };\n }\n return {\n variant: loaded.variant,\n tokens: flattenTokens(snapshot.base),\n sources: snapshot.sources,\n };\n}\n\nexport interface TokenSearchResult {\n variant: string | null;\n query: string;\n matches: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\n/**\n * Substring match across category / name / description / values. Case-insensitive.\n * Returns up to `limit` (default 20) matches ordered by category > name.\n */\nexport function searchTokens(\n loaded: LoadedTokens,\n query: string,\n limit = 20,\n): TokenSearchResult {\n const list = listTokens(loaded);\n const q = query.trim().toLowerCase();\n if (!q) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: 'query is empty.',\n };\n }\n if (list.note && list.tokens.length === 0) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: list.note,\n };\n }\n const hits = list.tokens.filter((t) => {\n if (t.category.toLowerCase().includes(q)) return true;\n if (t.name.toLowerCase().includes(q)) return true;\n if (t.description?.toLowerCase().includes(q)) return true;\n return Object.values(t.values).some((v) => v.toLowerCase().includes(q));\n });\n hits.sort((a, b) => {\n const c = a.category.localeCompare(b.category);\n return c !== 0 ? c : a.name.localeCompare(b.name);\n });\n return {\n variant: list.variant,\n query,\n matches: hits.slice(0, limit),\n sources: list.sources,\n };\n}\n"],"mappings":";;;AAUA,SAAS,4BAA4B;;;ACMrC,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACNP,SAAS,SAAS;;;ACdlB,SAAS,cAAc,kBAAkB;AACzC,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,+BAA+B;AAWjC,SAAS,oBAAoB,WAAmB,QAAQ,IAAI,GAAW;AAC5E,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAW,WAAW,OAAO,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,QAAQ;AAE1B,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,0DAA0D,QAAQ;AAAA,MAClE;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAYO,SAAS,aAAa,MAA+B;AAC1D,QAAM,eAAe,QAAQ,oBAAoB;AACjD,QAAM,MAAM,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAC1D,QAAM,SAAS,wBAAwB,UAAU,GAAG;AACpD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR,uBAAuB,YAAY,KAAK,OAAO,MAAM,OAAO;AAAA,IAC9D;AAAA,EACF;AACA,SAAO;AAAA,IACL,UAAU,OAAO;AAAA,IACjB,SAAS,QAAQ,YAAY;AAAA,EAC/B;AACF;AAoBO,SAAS,SACd,OACA,SACmB;AACnB,MAAI,CAAC,MAAM,KAAM,QAAO;AACxB,QAAM,OAAO,KAAK,SAAS,MAAM,IAAI;AACrC,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,OAAO,aAAa,MAAM,OAAO;AACvC,SAAO,iBAAiB,IAAI;AAC9B;AAEA,SAAS,iBAAiB,MAA0B;AAClD,QAAMA,SAAQ;AACd,QAAM,QAAQ,KAAK,MAAMA,MAAK;AAC9B,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,aAAa,CAAC,GAAG,MAAM,KAAK;AAAA,EACvC;AACA,QAAM,KAA6B,CAAC;AAEpC,aAAW,QAAQ,MAAM,CAAC,EAAG,MAAM,IAAI,GAAG;AACxC,UAAM,IAAI,KAAK,MAAM,oCAAoC;AACzD,QAAI,EAAG,IAAG,EAAE,CAAC,CAAE,IAAI,EAAE,CAAC,EAAG,QAAQ,gBAAgB,EAAE;AAAA,EACrD;AACA,SAAO;AAAA,IACL,aAAa;AAAA,IACb,MAAM,KAAK,MAAM,MAAM,CAAC,EAAE,MAAM;AAAA,EAClC;AACF;;;ADjGA,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,QAAQ,EAAE,KAAK,CAAC,UAAU,gBAAgB,YAAY,CAAC,EAAE,SAAS;AACpE,CAAC;AAED,IAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;AACtB,CAAC;AAED,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,SAAS;AACvD,CAAC;AAED,IAAM,QAAgB;AAAA,EACpB;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM,CAAC,UAAU,gBAAgB,YAAY;AAAA,UAC7C,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI;AAAA,UACF,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO;AAAA,UACL,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAEA,IAAM,aAAa,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEnD,SAAS,cAAc,OAAgB;AACrC,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM;AAAA,IACZ,aAAa,MAAM;AAAA,IACnB,QAAQ,MAAM;AAAA,IACd,kBAAkB,MAAM;AAAA,IACxB,YAAY,MAAM;AAAA,IAClB,sBAAsB,MAAM,wBAAwB,CAAC;AAAA,EACvD;AACF;AAOO,SAAS,oBAAoB,OAA6B,CAAC,GAAc;AAI9E,MAAI,QAA+B,KAAK,UAAU;AAClD,WAAS,cAA8B;AACrC,QAAI,CAAC,MAAO,SAAQ,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM,OAAO,MAAM,MAAuC;AACxD,UAAI,CAAC,WAAW,IAAI,IAAI,EAAG,QAAO;AAElC,UAAI,SAAS,mBAAmB;AAC9B,cAAM,QAAQ,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAClD,cAAM,EAAE,SAAS,IAAI,YAAY;AACjC,cAAM,UAAU,SAAS,QACtB,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EACpC,OAAO,CAAC,MAAO,MAAM,SAAS,EAAE,WAAW,MAAM,SAAS,IAAK,EAC/D,IAAI,aAAa;AACpB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,UAAI,SAAS,sBAAsB;AACjC,cAAM,QAAQ,sBAAsB,MAAM,IAAI;AAC9C,cAAM,EAAE,UAAU,QAAQ,IAAI,YAAY;AAC1C,cAAM,QAAQ,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE;AAC5D,YAAI,CAAC,OAAO;AACV,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,wBAAwB,MAAM,EAAE;AAAA,cACxC;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,OAAO,SAAS,OAAO,OAAO;AACpC,cAAM,UAAU;AAAA,UACd;AAAA,UACA,MAAM,QAAQ;AAAA,QAChB;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,UAAI,SAAS,mBAAmB;AAC9B,cAAM,QAAQ,oBAAoB,MAAM,IAAI;AAC5C,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,IAAI,MAAM,MAAM,YAAY;AAClC,cAAM,EAAE,SAAS,IAAI,YAAY;AACjC,cAAM,UAAU,SAAS,QACtB,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EACpC,OAAO,CAAC,MAAM;AACb,iBACE,EAAE,GAAG,YAAY,EAAE,SAAS,CAAC,KAC7B,EAAE,KAAK,YAAY,EAAE,SAAS,CAAC,KAC/B,EAAE,YAAY,YAAY,EAAE,SAAS,CAAC;AAAA,QAE1C,CAAC,EACA,MAAM,GAAG,KAAK,EACd,IAAI,aAAa;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT;AAAA,kBACE,OAAO,MAAM;AAAA,kBACb;AAAA,kBACA,OAAO,QAAQ;AAAA,kBACf,SAAS;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AE3LA,SAAS,KAAAC,UAAS;;;ACMlB,SAAS,cAAAC,aAAY,gBAAAC,eAAc,mBAAmB;AACtD,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AACvC,SAAS,qBAAqB;AAmCvB,SAAS,eAAe,WAAmB,QAAQ,IAAI,GAAW;AACvE,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAWJ,YAAW,OAAO,GAAG;AAClC,WAAO;AAAA,EACT;AAKA,MAAI;AACF,UAAM,OAAOE,SAAQ,cAAc,YAAY,GAAG,CAAC;AACnD,UAAM,UAAUC,MAAK,MAAM,QAAQ,KAAK;AACxC,QAAIH,YAAW,OAAO,EAAG,QAAO;AAAA,EAClC,QAAQ;AAAA,EAER;AAEA,MAAI,MAAMI,SAAQ,QAAQ;AAC1B,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,aAAa;AAAA,MACjBD,MAAK,KAAK,QAAQ,KAAK;AAAA,MACvBA,MAAK,KAAK,eAAe,KAAK;AAAA,IAChC;AACA,eAAW,KAAK,YAAY;AAC1B,UAAIH,YAAW,CAAC,EAAG,QAAO;AAAA,IAC5B;AACA,UAAM,SAASE,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,MACE;AAAA,MACA,2EAA2E,QAAQ;AAAA,MACnF;AAAA,IACF,EAAE,KAAK,GAAG;AAAA,EACZ;AACF;AAEA,IAAM,aAAa,oBAAI,IAAI,CAAC,aAAa,cAAc,CAAC;AACxD,IAAM,QAAQ;AACd,IAAM,QAAQ;AACd,IAAM,YAAY;AAClB,IAAM,UAAU;AAChB,IAAM,YAAY;AAElB,SAAS,SAAS,MAAc,UAAmC;AACjE,QAAM,UAAU,KAAK,MAAM,KAAK;AAChC,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,KAAK,QAAQ,CAAC;AAEpB,QAAM,OAAOD,cAAa,UAAU,OAAO;AAC3C,QAAM,aAAa,KAAK,MAAM,KAAK;AACnC,QAAM,cAAc,KAAK,MAAM,SAAS;AACxC,QAAM,YAAY,KAAK,MAAM,OAAO;AACpC,QAAM,cAAc,KAAK,MAAM,SAAS;AAExC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,aAAa,CAAC,KAAK;AAAA,IAC1B,QAAQ,cAAc,CAAC,KAAK;AAAA,IAC5B,MAAM,YAAY,CAAC,KAAK;AAAA,IACxB,QAAQ,cAAc,CAAC,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;AAEO,SAAS,aAAa,SAA8B;AACzD,QAAM,OAAO,WAAW,eAAe;AACvC,QAAM,QAAQ,YAAY,IAAI,EAAE;AAAA,IAC9B,CAAC,MAAM,EAAE,SAAS,KAAK,KAAK,CAAC,WAAW,IAAI,CAAC;AAAA,EAC/C;AACA,QAAM,UAAsB,CAAC;AAC7B,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,EAAE,QAAQ,SAAS,EAAE;AAClC,UAAM,QAAQ,SAAS,MAAME,MAAK,MAAM,CAAC,CAAC;AAC1C,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,EAC/B;AACA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAC/C,SAAO,EAAE,SAAS,MAAM,QAAQ;AAClC;AAMO,SAAS,QACd,QACA,UACiB;AACjB,QAAM,SAAS,SAAS,KAAK;AAC7B,MAAI,UAAU,KAAK,MAAM,GAAG;AAC1B,WAAO,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,KAAK;AAAA,EACxD;AACA,SACE,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KAC5C,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,KAC1C;AAEJ;AAEO,SAAS,eAAe,OAAyB;AACtD,SAAOF,cAAa,MAAM,UAAU,OAAO;AAC7C;;;AD1IA,IAAM,YAAYI,GAAE,OAAO;AAAA;AAAA,EAEzB,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC;AAED,IAAM,WAAWA,GAAE,OAAO;AAAA;AAAA,EAExB,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AACtB,CAAC;AAED,IAAM,YAAYA,GAAE,OAAO;AAAA,EACzB,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpD,cAAcA,GAAE,QAAQ,EAAE,SAAS;AACrC,CAAC;AAED,IAAMC,SAAgB;AAAA,EACpB;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI;AAAA,UACF,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,mBAAmB;AAAA,QACzD,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,QACA,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAEA,IAAMC,cAAa,IAAI,IAAID,OAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEnD,SAAS,UAAU,GAOhB;AACD,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,MAAM,EAAE;AAAA,IACR,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,MAAM,EAAE;AAAA,IACR,QAAQ,EAAE;AAAA,EACZ;AACF;AAEA,IAAM,iBAAiB;AAEvB,SAAS,QAAQ,MAAc,OAAuB;AACpD,QAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,cAAc;AAChD,QAAM,MAAM,KAAK,IAAI,KAAK,QAAQ,QAAQ,cAAc;AACxD,QAAM,SAAS,QAAQ,IAAI,WAAM;AACjC,QAAM,SAAS,MAAM,KAAK,SAAS,WAAM;AACzC,SAAO,SAAS,KAAK,MAAM,OAAO,GAAG,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK,IAAI;AACvE;AAOO,SAAS,eAAe,OAAwB,CAAC,GAAc;AACpE,MAAI,QAA2B,KAAK,UAAU;AAC9C,WAAS,WAAuB;AAC9B,QAAI,CAAC,MAAO,SAAQ,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAOA;AAAA,IACP,MAAM,OAAO,MAAM,MAAuC;AACxD,UAAI,CAACC,YAAW,IAAI,IAAI,EAAG,QAAO;AAElC,UAAI,SAAS,YAAY;AACvB,cAAM,QAAQ,UAAU,MAAM,QAAQ,CAAC,CAAC;AACxC,cAAM,MAAM,SAAS;AACrB,cAAM,SAAS,MAAM,QAAQ,YAAY;AACzC,cAAM,UAAU,IAAI,QACjB;AAAA,UAAO,CAAC,MACP,SAAS,EAAE,OAAO,YAAY,EAAE,SAAS,MAAM,IAAI;AAAA,QACrD,EACC,IAAI,SAAS;AAChB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,UAAI,SAAS,WAAW;AACtB,cAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,cAAM,MAAM,SAAS;AACrB,cAAM,QAAQ,QAAQ,KAAK,MAAM,EAAE;AACnC,YAAI,CAAC,OAAO;AACV,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,kBAAkB,MAAM,EAAE;AAAA,cAClC;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,OAAO,eAAe,KAAK;AACjC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT,EAAE,OAAO,UAAU,KAAK,GAAG,SAAS,KAAK;AAAA,gBACzC;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,YAAY;AACvB,cAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,eAAe,MAAM,gBAAgB;AAC3C,cAAM,SAAS,MAAM,MAAM,YAAY;AACvC,cAAM,MAAM,SAAS;AAErB,cAAM,UAID,CAAC;AACN,mBAAW,SAAS,IAAI,SAAS;AAC/B,gBAAM,OAAO,eAAe,KAAK,EAAE,YAAY;AAC/C,gBAAM,WAAW,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM;AAC1D,cAAI,CAAC,YAAY,CAAC,KAAK,SAAS,MAAM,EAAG;AAEzC,gBAAM,WAAqB,CAAC;AAC5B,cAAI,cAAc;AAChB,kBAAM,UAAU,eAAe,KAAK;AACpC,gBAAIC,QAAO;AAEX,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,oBAAM,KAAK,QAAQ,YAAY,EAAE,QAAQ,QAAQA,KAAI;AACrD,kBAAI,KAAK,EAAG;AACZ,uBAAS,KAAK,QAAQ,SAAS,EAAE,CAAC;AAClC,cAAAA,QAAO,KAAK,OAAO;AAAA,YACrB;AAAA,UACF;AAEA,cAAI,OAAO,WAAW,IAAI;AAC1B,cAAI,OAAO;AACX,qBAAS;AACP,kBAAM,KAAK,KAAK,QAAQ,QAAQ,IAAI;AACpC,gBAAI,KAAK,EAAG;AACZ;AACA,mBAAO,KAAK,OAAO;AAAA,UACrB;AACA,kBAAQ,KAAK;AAAA,YACX,OAAO,UAAU,KAAK;AAAA,YACtB,GAAI,eAAe,EAAE,SAAS,IAAI,CAAC;AAAA,YACnC,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AACA,gBAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC9C,cAAM,SAAS,QAAQ,MAAM,GAAG,KAAK;AACrC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT;AAAA,kBACE,OAAO,MAAM;AAAA,kBACb;AAAA,kBACA,OAAO,OAAO;AAAA,kBACd,mBAAmB,QAAQ;AAAA,kBAC3B,SAAS;AAAA,gBACX;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AE1PA,SAAS,KAAAC,UAAS;;;ACElB,SAAS,cAAAC,aAAY,gBAAAC,eAAc,eAAAC,cAAa,gBAAgB;AAChE,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AACvC;AAAA,EACE;AAAA,OAGK;AAQA,SAAS,kBAAkB,WAAmB,QAAQ,IAAI,GAAW;AAC1E,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAWL,YAAWI,MAAK,SAAS,eAAe,CAAC,GAAG;AACzD,WAAO;AAAA,EACT;AAEA,MAAI,MAAMC,SAAQ,QAAQ;AAC1B,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,aAAa;AAAA,MACjBD,MAAK,KAAK,YAAY,QAAQ;AAAA,MAC9BA,MAAK,KAAK,gBAAgB,eAAe,QAAQ;AAAA,IACnD;AACA,eAAW,KAAK,YAAY;AAC1B,UAAIJ,YAAWI,MAAK,GAAG,eAAe,CAAC,EAAG,QAAO;AAAA,IACnD;AACA,UAAM,SAASD,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,MACE;AAAA,MACA,uDAAuD,QAAQ;AAAA,MAC/D;AAAA,IACF,EAAE,KAAK,GAAG;AAAA,EACZ;AACF;AAEO,SAAS,mBAAmB,SAAgC;AACjE,QAAM,OAAO,WAAW,kBAAkB;AAC1C,QAAM,eAAeC,MAAK,MAAM,eAAe;AAC/C,QAAM,MAAM,KAAK,MAAMH,cAAa,cAAc,OAAO,CAAC;AAC1D,QAAM,SAAS,4BAA4B,UAAU,GAAG;AACxD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR,8BAA8B,YAAY,KAAK,OAAO,MAAM,OAAO;AAAA,IACrE;AAAA,EACF;AACA,SAAO,EAAE,SAAS,MAAM,UAAU,OAAO,KAAK;AAChD;AAoBA,IAAM,QAAQ;AAEd,SAASK,kBAAiB,MAGxB;AACA,QAAM,IAAI,KAAK,MAAM,KAAK;AAC1B,MAAI,CAAC,EAAG,QAAO,EAAE,aAAa,CAAC,GAAG,MAAM,KAAK;AAC7C,QAAM,KAA6B,CAAC;AACpC,aAAW,QAAQ,EAAE,CAAC,EAAG,MAAM,IAAI,GAAG;AACpC,UAAM,KAAK,KAAK,MAAM,oCAAoC;AAC1D,QAAI,GAAI,IAAG,GAAG,CAAC,CAAE,IAAI,GAAG,CAAC,EAAG,QAAQ,gBAAgB,EAAE;AAAA,EACxD;AACA,SAAO,EAAE,aAAa,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE;AAC1D;AAEO,SAAS,iBACd,OACA,SACqB;AACrB,QAAM,aAAaF,MAAK,SAAS,MAAM,MAAM;AAC7C,MAAI,CAACJ,YAAW,UAAU,EAAG,QAAO;AAGpC,MAAI;AACJ,MAAI,cAAwB,CAAC;AAC7B,QAAM,eAAeI,MAAK,YAAY,UAAU;AAChD,MAAIJ,YAAW,YAAY,GAAG;AAC5B,kBAAc;AAEd,QAAI;AACF,oBAAcE,aAAY,UAAU,EACjC,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,KAAK,MAAM,UAAU,EACnD,OAAO,CAAC,MAAM;AACb,YAAI;AACF,iBAAO,SAASE,MAAK,YAAY,CAAC,CAAC,EAAE,OAAO;AAAA,QAC9C,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACL,QAAQ;AACN,oBAAc,CAAC;AAAA,IACjB;AAAA,EACF,OAAO;AAEL,kBAAc;AAAA,EAChB;AAEA,QAAM,OAAOH,cAAa,aAAa,OAAO;AAC9C,QAAM,EAAE,aAAa,KAAK,IAAIK,kBAAiB,IAAI;AACnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACF;AAEO,SAAS,UACd,QACA,UACmB;AACnB,QAAM,SAAS,SAAS,KAAK;AAC7B,SACE,OAAO,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,KAClD,OAAO,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,KACpD;AAEJ;;;ADvIA,IAAMC,aAAYC,GAAE,OAAO,CAAC,CAAC;AAE7B,IAAMC,YAAWD,GAAE,OAAO;AAAA,EACxB,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AACtB,CAAC;AAED,IAAME,aAAYF,GAAE,OAAO;AAAA,EACzB,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpD,OAAOA,GAAE,KAAK,CAAC,eAAe,QAAQ,KAAK,CAAC,EAAE,SAAS;AACzD,CAAC;AAED,IAAMG,SAAgB;AAAA,EACpB;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,EAChD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI;AAAA,UACF,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,mBAAmB;AAAA,QACzD,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,QACA,OAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,CAAC,eAAe,QAAQ,KAAK;AAAA,UACnC,aACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAEA,IAAMC,cAAa,IAAI,IAAID,OAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEnD,SAASE,WAAU,GAAe;AAChC,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,MAAM,EAAE,QAAQ,CAAC;AAAA,IACjB,gBAAgB,EAAE,kBAAkB;AAAA,IACpC,UAAU,EAAE,YAAY;AAAA,EAC1B;AACF;AAMO,SAAS,kBAAkB,OAA2B,CAAC,GAAc;AAC1E,MAAI,QAA6B,KAAK,UAAU;AAChD,WAAS,cAA4B;AACnC,QAAI,CAAC,MAAO,SAAQ,mBAAmB;AACvC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAOF;AAAA,IACP,MAAM,OAAO,MAAM,MAAuC;AACxD,UAAI,CAACC,YAAW,IAAI,IAAI,EAAG,QAAO;AAElC,UAAI,SAAS,eAAe;AAC1B,QAAAL,WAAU,MAAM,QAAQ,CAAC,CAAC;AAC1B,cAAM,EAAE,SAAS,IAAI,YAAY;AACjC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK,UAAU,SAAS,OAAO,IAAIM,UAAS,GAAG,MAAM,CAAC;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,cAAc;AACzB,cAAM,QAAQJ,UAAS,MAAM,IAAI;AACjC,cAAM,SAAS,YAAY;AAC3B,cAAM,QAAQ,UAAU,QAAQ,MAAM,EAAE;AACxC,YAAI,CAAC,OAAO;AACV,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,oBAAoB,MAAM,EAAE;AAAA,cACpC;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,UAAU,iBAAiB,OAAO,OAAO,OAAO;AACtD,YAAI,CAAC,SAAS;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,qCAAqC,MAAM,EAAE,kBAAkB,MAAM,MAAM;AAAA,cACnF;AAAA,YACF;AAAA,YACA,SAAS;AAAA,UACX;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT;AAAA,kBACE,OAAOI,WAAU,KAAK;AAAA,kBACtB,aAAa,QAAQ;AAAA,kBACrB,SAAS,QAAQ;AAAA,gBACnB;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,eAAe;AAC1B,cAAM,QAAQH,WAAU,MAAM,IAAI;AAClC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,SAAS,MAAM,MAAM,YAAY;AACvC,cAAM,SAAS,YAAY;AAE3B,cAAM,UAGD,CAAC;AAEN,mBAAW,SAAS,OAAO,SAAS,QAAQ;AAC1C,gBAAM,UACJ,UAAU,UACV,MAAM,YAAY,YAAY,EAAE,SAAS,MAAM;AACjD,cAAI,UAAU;AACd,cAAI,UAAU,UAAU,UAAU,OAAO;AACvC,kBAAM,UAAU,iBAAiB,OAAO,OAAO,OAAO;AACtD,gBAAI,SAAS;AACX,wBAAU,QAAQ,KAAK,YAAY,EAAE,SAAS,MAAM;AAAA,YACtD;AAAA,UACF;AACA,cAAI,CAAC,WAAW,CAAC,QAAS;AAC1B,kBAAQ,KAAK;AAAA,YACX,OAAOG,WAAU,KAAK;AAAA,YACtB,OACE,WAAW,UACP,SACA,UACE,gBACA;AAAA,UACV,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT;AAAA,kBACE,OAAO,MAAM;AAAA,kBACb;AAAA,kBACA;AAAA,kBACA,OAAO,KAAK,IAAI,QAAQ,QAAQ,KAAK;AAAA,kBACrC,cAAc,QAAQ;AAAA,kBACtB,SAAS,QAAQ,MAAM,GAAG,KAAK;AAAA,gBACjC;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AE9NA,SAAS,KAAAC,UAAS;;;ACDlB,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,UAAS,QAAAC,OAAM,WAAAC,gBAAe;AAShC,SAAS,kBACd,WAAmB,QAAQ,IAAI,GAChB;AACf,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAWJ,YAAW,OAAO,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,MAAI,MAAMI,SAAQ,QAAQ;AAC1B,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,YAAYD,MAAK,KAAK,aAAa;AACzC,QAAIH,YAAW,SAAS,EAAG,QAAO;AAClC,UAAM,SAASE,SAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAEO,SAAS,WAAW,SAAuC;AAChE,QAAM,OAAO,WAAW,kBAAkB;AAC1C,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI,UAAyB;AAC7B,QAAM,WAAWC,MAAK,MAAM,kBAAkB;AAC9C,MAAIH,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,YAAM,MAAM,KAAK,MAAMC,cAAa,UAAU,OAAO,CAAC;AAGtD,gBAAU,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAAA,IAC5D,QAAQ;AACN,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,SAAO,EAAE,SAAS,MAAM,QAAQ;AAClC;AAkBA,SAAS,iBAAiB,QAAqC;AAC7D,QAAM,cAAcC,SAAQ,OAAO,OAAO;AAC1C,QAAM,aAAaC,MAAK,aAAa,QAAQ;AAC7C,MAAIH,YAAW,UAAU,EAAG,QAAO;AACnC,SAAO;AACT;AAEO,SAAS,WAAW,QAAqC;AAC9D,QAAM,YAAY,iBAAiB,MAAM;AACzC,QAAM,MAAqB,EAAE,SAAS,CAAC,EAAE;AACzC,MAAI,CAAC,WAAW;AACd,QAAI,OAAO;AACX,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,QAAqC;AACpD,UAAM,KAAKG,MAAK,WAAW,GAAG;AAC9B,QAAI,CAACH,YAAW,EAAE,EAAG,QAAO;AAC5B,QAAI,QAAQ,KAAK,EAAE;AACnB,QAAI;AACF,aAAO,KAAK,MAAMC,cAAa,IAAI,OAAO,CAAC;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,UAAU,CAAC,QAAoC;AACnD,UAAM,KAAKE,MAAK,WAAW,GAAG;AAC9B,QAAI,CAACH,YAAW,EAAE,EAAG,QAAO;AAC5B,QAAI,QAAQ,KAAK,EAAE;AACnB,WAAOC,cAAa,IAAI,OAAO;AAAA,EACjC;AACA,MAAI,OAAO,QAAQ,kBAAkB;AACrC,MAAI,WAAW,QAAQ,kBAAkB;AACzC,MAAI,eAAe,QAAQ,sBAAsB;AACjD,SAAO;AACT;AAmBA,IAAM,WAAW,oBAAI,IAAI,CAAC,UAAU,SAAS,gBAAgB,aAAa,CAAC;AAE3E,SAAS,cAAc,GAA0C;AAC/D,SAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAChE;AAcO,SAAS,cAAc,MAA6B;AACzD,MAAI,CAAC,cAAc,IAAI,EAAG,QAAO,CAAC;AAClC,QAAM,MAAoB,CAAC;AAE3B,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AACpD,QAAI,SAAS,WAAW,GAAG,EAAG;AAC9B,QAAI,CAAC,cAAc,KAAK,EAAG;AAE3B,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAI,KAAK,WAAW,GAAG,EAAG;AAC1B,UAAI,CAAC,cAAc,IAAI,EAAG;AAE1B,YAAM,OACJ,OAAO,KAAK,UAAU,WAAY,KAAK,QAAmB;AAC5D,YAAM,SAAiC,CAAC;AACxC,UAAI,cACF,OAAO,KAAK,iBAAiB,WACxB,KAAK,eACN;AAEN,UAAI,OAAO,KAAK,WAAW,UAAU;AACnC,eAAO,UAAU,KAAK;AAAA,MACxB;AAEA,iBAAW,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,IAAI,GAAG;AACrD,YAAI,SAAS,IAAI,OAAO,EAAG;AAC3B,YAAI,CAAC,cAAc,OAAO,EAAG;AAC7B,YAAI,OAAO,QAAQ,WAAW,UAAU;AACtC,iBAAO,OAAO,IAAI,QAAQ;AAAA,QAC5B;AACA,YACE,CAAC,eACD,OAAO,QAAQ,iBAAiB,UAChC;AACA,wBAAc,QAAQ;AAAA,QACxB;AAAA,MACF;AAEA,UAAI,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG;AAEtC,UAAI,KAAK;AAAA,QACP;AAAA,QACA;AAAA,QACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,QACvB;AAAA,QACA,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AASO,SAAS,WAAW,QAAuC;AAChE,QAAM,WAAW,WAAW,MAAM;AAClC,MAAI,CAAC,SAAS,MAAM;AAClB,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,QAAQ,CAAC;AAAA,MACT,SAAS,SAAS;AAAA,MAClB,MAAM,SAAS,QAAQ;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AAAA,IACL,SAAS,OAAO;AAAA,IAChB,QAAQ,cAAc,SAAS,IAAI;AAAA,IACnC,SAAS,SAAS;AAAA,EACpB;AACF;AAcO,SAAS,aACd,QACA,OACA,QAAQ,IACW;AACnB,QAAM,OAAO,WAAW,MAAM;AAC9B,QAAM,IAAI,MAAM,KAAK,EAAE,YAAY;AACnC,MAAI,CAAC,GAAG;AACN,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd;AAAA,MACA,SAAS,CAAC;AAAA,MACV,SAAS,KAAK;AAAA,MACd,MAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,KAAK,QAAQ,KAAK,OAAO,WAAW,GAAG;AACzC,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd;AAAA,MACA,SAAS,CAAC;AAAA,MACV,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AACA,QAAM,OAAO,KAAK,OAAO,OAAO,CAAC,MAAM;AACrC,QAAI,EAAE,SAAS,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AACjD,QAAI,EAAE,KAAK,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AAC7C,QAAI,EAAE,aAAa,YAAY,EAAE,SAAS,CAAC,EAAG,QAAO;AACrD,WAAO,OAAO,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,EACxE,CAAC;AACD,OAAK,KAAK,CAAC,GAAG,MAAM;AAClB,UAAM,IAAI,EAAE,SAAS,cAAc,EAAE,QAAQ;AAC7C,WAAO,MAAM,IAAI,IAAI,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EAClD,CAAC;AACD,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd;AAAA,IACA,SAAS,KAAK,MAAM,GAAG,KAAK;AAAA,IAC5B,SAAS,KAAK;AAAA,EAChB;AACF;;;AD7PA,IAAM,aAAaI,GAAE,OAAO,CAAC,CAAC;AAC9B,IAAM,cAAcA,GAAE,OAAO;AAAA,EAC3B,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AACnD,CAAC;AAED,IAAMC,SAAgB;AAAA,EACpB;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,EAChD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,EAChD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,mBAAmB;AAAA,QACzD,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAEA,IAAMC,cAAa,IAAI,IAAID,OAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AASnD,IAAM,iBACJ;AAEK,SAAS,kBAAkB,OAA2B,CAAC,GAAc;AAC1E,MAAI,QACF,KAAK,WAAW,SAAY,SAAY,KAAK;AAC/C,WAAS,YAAiC;AACxC,QAAI,UAAU,OAAW,SAAQ,WAAW,KAAK,OAAO;AACxD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAOA;AAAA,IACP,MAAM,OAAO,MAAM,MAAuC;AACxD,UAAI,CAACC,YAAW,IAAI,IAAI,EAAG,QAAO;AAElC,YAAM,SAAS,UAAU;AAEzB,UAAI,SAAS,cAAc;AACzB,mBAAW,MAAM,QAAQ,CAAC,CAAC;AAC3B,YAAI,CAAC,QAAQ;AACX,iBAAO,WAAW,EAAE,SAAS,CAAC,GAAG,MAAM,eAAe,CAAC;AAAA,QACzD;AACA,eAAO,WAAW,WAAW,MAAM,CAAC;AAAA,MACtC;AAEA,UAAI,SAAS,eAAe;AAC1B,mBAAW,MAAM,QAAQ,CAAC,CAAC;AAC3B,YAAI,CAAC,QAAQ;AACX,iBAAO,WAAW;AAAA,YAChB,SAAS;AAAA,YACT,QAAQ,CAAC;AAAA,YACT,SAAS,CAAC;AAAA,YACV,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AACA,eAAO,WAAW,WAAW,MAAM,CAAC;AAAA,MACtC;AAEA,UAAI,SAAS,iBAAiB;AAC5B,cAAM,SAAS,YAAY,MAAM,QAAQ,CAAC,CAAC;AAC3C,YAAI,CAAC,QAAQ;AACX,iBAAO,WAAW;AAAA,YAChB,SAAS;AAAA,YACT,OAAO,OAAO;AAAA,YACd,SAAS,CAAC;AAAA,YACV,SAAS,CAAC;AAAA,YACV,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AACA,eAAO,WAAW,aAAa,QAAQ,OAAO,OAAO,OAAO,KAAK,CAAC;AAAA,MACpE;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,WAAW,SAA8B;AAChD,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,CAAC;AAAA,EACpE;AACF;;;APpGO,SAAS,aAAa,OAAsB,CAAC,GAAW;AAC7D,QAAM,SAAsB;AAAA,IAC1B,oBAAoB,KAAK,QAAQ;AAAA,IACjC,eAAe,KAAK,GAAG;AAAA,IACvB,kBAAkB,KAAK,MAAM;AAAA,IAC7B,kBAAkB,KAAK,MAAM;AAAA;AAAA,EAE/B;AAGA,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,QAAQ;AAC1B,eAAW,QAAQ,MAAM,OAAO;AAC9B,UAAI,KAAK,IAAI,KAAK,IAAI,GAAG;AACvB,cAAM,IAAI;AAAA,UACR,0CAA0C,KAAK,IAAI;AAAA,QAErD;AAAA,MACF;AACA,WAAK,IAAI,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK;AAE9C,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,cAAc,EAAE,OAAO,CAAC,EAAE;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO,kBAAkB,wBAAwB,aAAa;AAAA,IAC5D,OAAO;AAAA,EACT,EAAE;AAEF,SAAO,kBAAkB,uBAAuB,OAAO,QAAQ;AAC7D,UAAM,EAAE,MAAM,WAAW,KAAK,IAAI,IAAI;AACtC,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI;AAC5C,UAAI,WAAW,OAAW,QAAO;AAAA,IACnC;AACA,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,iBAAiB,IAAI;AAAA,QAC7B;AAAA,MACF;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ADlFA,eAAe,OAAsB;AACnC,QAAM,SAAS,aAAa;AAC5B,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAEhC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AAGpB,UAAQ,MAAM,2BAA2B,GAAG;AAC5C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["FM_RE","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES","from","z","existsSync","readFileSync","readdirSync","dirname","join","resolve","parseFrontmatter","ListInput","z","GetInput","FindInput","TOOLS","TOOL_NAMES","pickEntry","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/server.ts","../src/groups/registry.ts","../src/manifest-loader.ts","../src/groups/adr.ts","../src/adr-loader.ts","../src/groups/skills.ts","../src/skills-loader.ts","../src/groups/tokens.ts","../src/tokens-loader.ts"],"sourcesContent":["/**\n * Bin entry — speaks stdio MCP.\n *\n * Invoked by AI editors (Cursor / Claude Code / Cline / Aider) via:\n * npx @teamix-evo/mcp\n * or directly:\n * node ./packages/mcp/dist/cli.js\n *\n * See README.md for the per-IDE config snippets.\n */\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createServer } from './server.js';\n\nasync function main(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // Stdio transport keeps the process alive while client is connected.\n}\n\nmain().catch((err) => {\n // Write to stderr so MCP client logs surface the failure.\n // eslint-disable-next-line no-console -- stderr logging at process boundary\n console.error('[teamix-evo-mcp] fatal:', err);\n process.exit(1);\n});\n","/**\n * Main MCP server — composes multiple tool groups into one stdio process.\n *\n * Architecture per [ADR 0011](../../../docs/adr/0011-mcp-single-package-multi-group.md):\n * single package / single bin / multiple tool groups. Groups added in later\n * milestones (tokens v0.6, adr v0.7, scenario v0.8) plug in here without\n * touching the transport or ListTools/CallTool handler logic.\n *\n * Tool dispatch:\n * - `tools/list` returns the union of all groups' tools.\n * - `tools/call` walks the group list in registration order; the first group\n * whose `handle` returns a non-`undefined` result wins. Tool-name uniqueness\n * across groups is the responsibility of group authors (see ADR 0011 §5\n * for the `<group>_<verb>_<noun>` naming convention; `registry` is the\n * historical exception).\n */\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { createRegistryGroup, type RegistryGroupOptions } from './groups/registry.js';\nimport { createAdrGroup, type AdrGroupOptions } from './groups/adr.js';\nimport { createSkillsGroup, type SkillsGroupOptions } from './groups/skills.js';\nimport { createTokensGroup, type TokensGroupOptions } from './groups/tokens.js';\nimport type { ToolGroup } from './types.js';\n\nexport interface ServerOptions {\n /** Options forwarded to the registry group. Pass `loaded` in tests. */\n registry?: RegistryGroupOptions;\n /** Options forwarded to the adr group. Pass `loaded` in tests. */\n adr?: AdrGroupOptions;\n /** Options forwarded to the skills group. Pass `loaded` in tests. */\n skills?: SkillsGroupOptions;\n /** Options forwarded to the tokens group. Pass `loaded` in tests. */\n tokens?: TokensGroupOptions;\n}\n\nexport function createServer(opts: ServerOptions = {}): Server {\n const groups: ToolGroup[] = [\n createRegistryGroup(opts.registry),\n createAdrGroup(opts.adr),\n createSkillsGroup(opts.skills),\n createTokensGroup(opts.tokens),\n // Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8\n ];\n\n // Sanity check: tool names must be unique across groups.\n const seen = new Set<string>();\n for (const group of groups) {\n for (const tool of group.tools) {\n if (seen.has(tool.name)) {\n throw new Error(\n `Duplicate MCP tool name across groups: ${tool.name}. ` +\n `Each group must use unique tool names — see ADR 0011 §5.`,\n );\n }\n seen.add(tool.name);\n }\n }\n\n const allTools = groups.flatMap((g) => g.tools);\n\n const server = new Server(\n {\n name: '@teamix-evo/mcp',\n version: '0.2.0',\n },\n {\n capabilities: { tools: {} },\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: allTools,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const { name, arguments: args } = req.params;\n for (const group of groups) {\n const result = await group.handle(name, args);\n if (result !== undefined) return result;\n }\n return {\n content: [\n {\n type: 'text',\n text: `Unknown tool: ${name}. Use tools/list to discover available tools.`,\n },\n ],\n isError: true,\n };\n });\n\n return server;\n}\n","/**\n * Registry tool group — exposes the @teamix-evo/ui component registry to AI\n * editors.\n *\n * Originally `src/server.ts` of `@teamix-evo/registry-mcp`. Moved here as part\n * of [ADR 0011](../../../../docs/adr/0011-mcp-single-package-multi-group.md)\n * single-package / multi-group restructure.\n *\n * Tool naming is the **historical exception**: `list_components` /\n * `get_component_meta` / `find_components` keep their unprefixed names because\n * they're already in production AI client memory (see ADR 0011 §5). All\n * future groups (`design_*`, `adr_*`, `scenario_*`) MUST use the\n * `<group>_<verb>_<noun>` prefix convention.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadManifest,\n loadMeta,\n type LoadedManifest,\n} from '../manifest-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { UiEntry } from '@teamix-evo/registry';\n\nconst ListComponentsInput = z.object({\n status: z.enum(['stable', 'experimental', 'deprecated']).optional(),\n /**\n * Include archived entries from `manifest.deprecatedEntries` (ADR 0028).\n * Equivalent to `status: \"deprecated\"` when set alone, but composes with\n * other filters: e.g. unset status + `includeDeprecated: true` returns\n * active + deprecated together.\n */\n includeDeprecated: z.boolean().optional(),\n});\n\nconst GetComponentMetaInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindComponentsInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(100).optional(),\n /** Include archived deprecated entries in matches (ADR 0028). */\n includeDeprecated: z.boolean().optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'list_components',\n description:\n 'List UI components in the @teamix-evo/ui registry. By default excludes archived `deprecatedEntries` (ADR 0028) — pass `includeDeprecated: true` (or `status: \"deprecated\"`) to inspect them, e.g. for upgrade audits. Returns id, name, description, status, registryDependencies — small enough for the model to scan whole.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n enum: ['stable', 'experimental', 'deprecated'],\n description:\n 'Filter active entries by maturity status. `deprecated` returns the archived `deprecatedEntries` list.',\n },\n includeDeprecated: {\n type: 'boolean',\n description:\n 'When true, merge archived `deprecatedEntries` into the result (ADR 0028).',\n },\n },\n },\n },\n {\n name: 'get_component_meta',\n description:\n 'Fetch the full registry entry + parsed meta.md for a single component by id. Searches both active `entries` and archived `deprecatedEntries`; deprecated hits are flagged via `archived: true` in the payload. Returns props schema reference, registryDependencies, npm dependencies, AI generation rules, and the component description.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Component id (e.g. \"button\", \"data-table\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'find_components',\n description:\n 'Substring match over component id / name / description. Use when you need a component but don\\'t know its exact id (e.g. \"find a component supporting async search and pagination\"). Excludes archived `deprecatedEntries` by default — pass `includeDeprecated: true` to widen the search (ADR 0028). Returns up to `limit` matches (default 10). Note: substring match is a v0.1 implementation; semantic search is planned for v0.7 (see ADR 0009).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Free-text query.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 10).',\n },\n includeDeprecated: {\n type: 'boolean',\n description:\n 'When true, also search archived `deprecatedEntries` (ADR 0028).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickListEntry(entry: UiEntry) {\n return {\n id: entry.id,\n name: entry.name,\n type: entry.type,\n description: entry.description,\n status: entry.status,\n deprecatedReason: entry.deprecatedReason,\n replacedBy: entry.replacedBy,\n registryDependencies: entry.registryDependencies ?? [],\n };\n}\n\n/**\n * Mark an entry that came from `manifest.deprecatedEntries` so callers can\n * tell archived hits apart from active `status: 'deprecated'` ones.\n */\nfunction pickArchivedEntry(entry: UiEntry) {\n return { ...pickListEntry(entry), archived: true as const };\n}\n\nexport interface RegistryGroupOptions {\n /** Pre-loaded manifest (used in tests to avoid filesystem). */\n loaded?: LoadedManifest;\n}\n\nexport function createRegistryGroup(\n opts: RegistryGroupOptions = {},\n): ToolGroup {\n // Lazy-load the manifest so failures yield a tool-call error rather than\n // blocking server startup (which would prevent the MCP client from even\n // discovering the tools and seeing a usable error message).\n let cache: LoadedManifest | null = opts.loaded ?? null;\n function getManifest(): LoadedManifest {\n if (!cache) cache = loadManifest();\n return cache;\n }\n\n return {\n name: 'registry',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'list_components') {\n const input = ListComponentsInput.parse(args ?? {});\n const { manifest } = getManifest();\n const archived = manifest.deprecatedEntries ?? [];\n\n // status:'deprecated' is treated as an explicit \"only archived\" filter\n // for backwards compat with the v0.1 API; archived entries live in\n // `deprecatedEntries` per ADR 0028 (no longer in `entries`).\n if (input.status === 'deprecated') {\n const entries = archived\n .filter((e) => e.type === 'component')\n .map(pickArchivedEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n const active = manifest.entries\n .filter((e) => e.type === 'component')\n .filter((e) => (input.status ? e.status === input.status : true))\n .map(pickListEntry);\n\n const merged = input.includeDeprecated\n ? [\n ...active,\n ...archived\n .filter((e) => e.type === 'component')\n .map(pickArchivedEntry),\n ]\n : active;\n\n return {\n content: [{ type: 'text', text: JSON.stringify(merged, null, 2) }],\n };\n }\n\n if (name === 'get_component_meta') {\n const input = GetComponentMetaInput.parse(args);\n const { manifest, rootDir } = getManifest();\n const entry = manifest.entries.find((e) => e.id === input.id);\n const archived = entry\n ? null\n : (manifest.deprecatedEntries ?? []).find((e) => e.id === input.id) ??\n null;\n const found = entry ?? archived;\n if (!found) {\n return {\n content: [\n {\n type: 'text',\n text: `Component not found: ${input.id}. Use list_components to discover ids (pass includeDeprecated: true to widen the search).`,\n },\n ],\n isError: true,\n };\n }\n const meta = loadMeta(found, rootDir);\n const payload = {\n entry: found,\n meta: meta ?? null,\n archived: archived !== null,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n }\n\n if (name === 'find_components') {\n const input = FindComponentsInput.parse(args);\n const limit = input.limit ?? 10;\n const q = input.query.toLowerCase();\n const { manifest } = getManifest();\n const pool = input.includeDeprecated\n ? [\n ...manifest.entries.map((e) => ({ entry: e, archived: false })),\n ...(manifest.deprecatedEntries ?? []).map((e) => ({\n entry: e,\n archived: true,\n })),\n ]\n : manifest.entries.map((e) => ({ entry: e, archived: false }));\n const matches = pool\n .filter(({ entry }) => entry.type === 'component')\n .filter(({ entry, archived: a }) => {\n // Active entries with status:'deprecated' are still hidden by\n // default (legacy data shape — archived flag wins for new shape).\n if (\n !input.includeDeprecated &&\n !a &&\n entry.status === 'deprecated'\n ) {\n return false;\n }\n return true;\n })\n .filter(({ entry }) => {\n return (\n entry.id.toLowerCase().includes(q) ||\n entry.name.toLowerCase().includes(q) ||\n entry.description.toLowerCase().includes(q)\n );\n })\n .slice(0, limit)\n .map(({ entry, archived: a }) =>\n a ? pickArchivedEntry(entry) : pickListEntry(entry),\n );\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: matches.length,\n results: matches,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n // Unreachable — TOOL_NAMES guard above ensures we only enter known names.\n return undefined;\n },\n };\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { UiPackageManifestSchema } from '@teamix-evo/registry';\nimport type { UiEntry, UiPackageManifest } from '@teamix-evo/registry';\n\n/**\n * Resolves the `@teamix-evo/ui/manifest.json` path using a layered strategy:\n *\n * 1. `TEAMIX_EVO_UI_MANIFEST` env var (absolute path)\n * 2. `<cwd>/node_modules/@teamix-evo/ui/manifest.json`\n * 3. Walking up parent directories until a matching `node_modules/...` is found\n * 4. Throws with a clear error message\n */\nexport function resolveManifestPath(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_UI_MANIFEST;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n // Limit walk to prevent runaway in pathological filesystems.\n for (let i = 0; i < 16; i++) {\n const candidate = join(\n dir,\n 'node_modules',\n '@teamix-evo',\n 'ui',\n 'manifest.json',\n );\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/ui/manifest.json — the UI registry is not installed in this project.',\n '',\n 'Fix one of:',\n ` 1. Install the package: pnpm add @teamix-evo/ui (or npm/yarn equivalent)`,\n ` 2. Point env at an existing manifest: export TEAMIX_EVO_UI_MANIFEST=/abs/path/to/manifest.json`,\n '',\n `Searched: $TEAMIX_EVO_UI_MANIFEST, then walked up from ${startDir} looking for node_modules/@teamix-evo/ui/manifest.json (16 levels).`,\n 'Note: MCP currently has no online fallback — it does not fetch from the npm registry / unpkg.',\n ].join('\\n'),\n );\n}\n\nexport interface LoadedManifest {\n manifest: UiPackageManifest;\n /** Directory of the manifest.json itself; used to resolve `meta.md` paths. */\n rootDir: string;\n}\n\n/**\n * Loads and Zod-validates the UI package manifest.\n * Throws on invalid manifest with the underlying Zod error attached.\n */\nexport function loadManifest(path?: string): LoadedManifest {\n const manifestPath = path ?? resolveManifestPath();\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const result = UiPackageManifestSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(\n `Invalid manifest at ${manifestPath}: ${result.error.message}`,\n );\n }\n return {\n manifest: result.data,\n rootDir: dirname(manifestPath),\n };\n}\n\n/**\n * Frontmatter + body extracted from a `<id>.meta.md` file.\n * Frontmatter is parsed as a flat key/value map (no YAML library dep —\n * meta.md frontmatters are intentionally simple).\n */\nexport interface ParsedMeta {\n frontmatter: Record<string, string>;\n body: string;\n}\n\n/**\n * Reads and minimally parses a `<id>.meta.md` file. Returns `null` if the\n * meta file is missing or the entry didn't declare one.\n *\n * Frontmatter parser is minimal (single-line `key: value` pairs only). It\n * does NOT support nested or array YAML — sufficient for the meta.md format\n * documented in packages/ui/AGENTS.md §三.E.\n */\nexport function loadMeta(\n entry: UiEntry,\n rootDir: string,\n): ParsedMeta | null {\n if (!entry.meta) return null;\n const path = join(rootDir, entry.meta);\n if (!existsSync(path)) return null;\n const text = readFileSync(path, 'utf-8');\n return parseFrontmatter(text);\n}\n\nfunction parseFrontmatter(text: string): ParsedMeta {\n const FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n const match = text.match(FM_RE);\n if (!match) {\n return { frontmatter: {}, body: text };\n }\n const fm: Record<string, string> = {};\n // Capture group [1] is guaranteed when match succeeds.\n for (const line of match[1]!.split('\\n')) {\n const m = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (m) fm[m[1]!] = m[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return {\n frontmatter: fm,\n body: text.slice(match[0].length),\n };\n}\n","/**\n * ADR tool group — exposes Architecture Decision Records to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md),\n * new groups use the `<group>_<verb>` prefix convention:\n *\n * - `adr_list` — index of all ADRs (id, title, status, date)\n * - `adr_get` — full markdown body for one ADR\n * - `adr_find` — substring search across title + body\n *\n * Use this group to let AI agents:\n *\n * - Cite ADRs in PR reviews (\"this change violates ADR 0008 §2.B\")\n * - Resolve \"why was this done?\" questions before recommending refactors\n * - Discover related ADRs when proposing a new decision\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadAdrIndex,\n loadAdrContent,\n findAdr,\n type LoadedAdrs,\n} from '../adr-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst ListInput = z.object({\n /** Match `Status` line by substring (case-insensitive). */\n status: z.string().min(1).optional(),\n});\n\nconst GetInput = z.object({\n /** ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\"). */\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * When true, returns a snippet (~200 chars) around each match so the model\n * can decide whether to fetch the full ADR. Defaults to true.\n */\n withSnippets: z.boolean().optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'adr_list',\n description:\n 'List all Architecture Decision Records (ADRs) in docs/adr/. Returns id (4-digit), slug, title, status, date, region for each. Use this as the first call to discover which decisions exist before drilling into one with adr_get. Filter by status substring (e.g. \"Accepted\" / \"Proposed\" / \"Superseded\") to narrow down.',\n inputSchema: {\n type: 'object',\n properties: {\n status: {\n type: 'string',\n description:\n 'Optional case-insensitive substring filter against the ADR Status line. Examples: \"Accepted\", \"Proposed\", \"Superseded\".',\n },\n },\n },\n },\n {\n name: 'adr_get',\n description:\n 'Fetch the full markdown body of one ADR by id (\"0011\") or slug (\"0011-mcp-single-package-multi-group\"). Returns the entry metadata + raw markdown so the model can cite specific sections (Context / Decision / Consequences / Source). Use after adr_list / adr_find to read a specific decision in full.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description:\n 'ADR id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'adr_find',\n description:\n 'Substring search across ADR titles and bodies (case-insensitive). Use when you remember a phrase (\"source-mirror\", \"lint-core\", \"no baseline\") but not which ADR it lives in. Returns up to `limit` matches (default 10) with optional snippets (~200 chars around each match). Combine with adr_get for the full text.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n withSnippets: {\n type: 'boolean',\n description: 'Include ~200-char snippet around each match (default true).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(e: {\n id: string;\n slug: string;\n title: string;\n status: string;\n date: string;\n region: string;\n}) {\n return {\n id: e.id,\n slug: e.slug,\n title: e.title,\n status: e.status,\n date: e.date,\n region: e.region,\n };\n}\n\nconst SNIPPET_RADIUS = 100;\n\nfunction snippet(text: string, index: number): string {\n const start = Math.max(0, index - SNIPPET_RADIUS);\n const end = Math.min(text.length, index + SNIPPET_RADIUS);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return prefix + text.slice(start, end).replace(/\\s+/g, ' ').trim() + suffix;\n}\n\nexport interface AdrGroupOptions {\n /** Pre-loaded index (used in tests to avoid filesystem). */\n loaded?: LoadedAdrs;\n}\n\nexport function createAdrGroup(opts: AdrGroupOptions = {}): ToolGroup {\n let cache: LoadedAdrs | null = opts.loaded ?? null;\n function getIndex(): LoadedAdrs {\n if (!cache) cache = loadAdrIndex();\n return cache;\n }\n\n return {\n name: 'adr',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'adr_list') {\n const input = ListInput.parse(args ?? {});\n const idx = getIndex();\n const needle = input.status?.toLowerCase();\n const entries = idx.entries\n .filter((e) =>\n needle ? e.status.toLowerCase().includes(needle) : true,\n )\n .map(pickEntry);\n return {\n content: [{ type: 'text', text: JSON.stringify(entries, null, 2) }],\n };\n }\n\n if (name === 'adr_get') {\n const input = GetInput.parse(args);\n const idx = getIndex();\n const entry = findAdr(idx, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `ADR not found: ${input.id}. Use adr_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const text = loadAdrContent(entry);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { entry: pickEntry(entry), content: text },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'adr_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const withSnippets = input.withSnippets ?? true;\n const needle = input.query.toLowerCase();\n const idx = getIndex();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n snippets?: string[];\n hitCount: number;\n }> = [];\n for (const entry of idx.entries) {\n const body = loadAdrContent(entry).toLowerCase();\n const titleHit = entry.title.toLowerCase().includes(needle);\n if (!titleHit && !body.includes(needle)) continue;\n\n const snippets: string[] = [];\n if (withSnippets) {\n const rawBody = loadAdrContent(entry);\n let from = 0;\n // Up to 3 snippets per ADR to keep response compact.\n for (let i = 0; i < 3; i++) {\n const at = rawBody.toLowerCase().indexOf(needle, from);\n if (at < 0) break;\n snippets.push(snippet(rawBody, at));\n from = at + needle.length;\n }\n }\n // Count total hits in body for ranking.\n let hits = titleHit ? 1 : 0;\n let from = 0;\n for (;;) {\n const at = body.indexOf(needle, from);\n if (at < 0) break;\n hits++;\n from = at + needle.length;\n }\n matches.push({\n entry: pickEntry(entry),\n ...(withSnippets ? { snippets } : {}),\n hitCount: hits,\n });\n }\n matches.sort((a, b) => b.hitCount - a.hitCount);\n const sliced = matches.slice(0, limit);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n limit,\n count: sliced.length,\n totalMatchingAdrs: matches.length,\n results: sliced,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for ADR (Architecture Decision Record) markdown files.\n *\n * ADRs live in `docs/adr/<NNNN>-<slug>.md` per [ADR 0007](../../../docs/adr/0007-governance-docs-at-root.md).\n * Each file has the shape:\n *\n * ```md\n * # 0011. <title>\n *\n * - **Status**: Proposed | Accepted | Superseded by NNNN | Deprecated\n * - **Date**: YYYY-MM-DD\n * - **Region**: 0100–0999 协议与工具\n * - **Related ADR**: [0007 ...](...)\n *\n * ## Context\n * ...\n * ```\n *\n * This loader parses just enough metadata to power the `adr_list` /\n * `adr_get` / `adr_find` MCP tools (see [`groups/adr.ts`](./groups/adr.ts)).\n * `README.md` and `_template.md` are skipped — they are not ADRs.\n */\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport interface AdrEntry {\n /** Numeric id, e.g. \"0011\". Derived from the filename prefix. */\n id: string;\n /** Filename without `.md`, e.g. \"0011-mcp-single-package-multi-group\". */\n slug: string;\n /** Title after \"NNNN. \" in the H1 line. */\n title: string;\n /** Raw status string from the `- **Status**:` line. Empty if missing. */\n status: string;\n /** Date from the `- **Date**:` line (YYYY-MM-DD). Empty if missing. */\n date: string;\n /** Optional region label (`0100–0999 协议与工具`). Empty if missing. */\n region: string;\n /** Absolute path to the source file (for `adr_get`). */\n filePath: string;\n}\n\nexport interface LoadedAdrs {\n /** Directory containing the ADR `.md` files. */\n rootDir: string;\n entries: AdrEntry[];\n}\n\n/**\n * Resolves the ADR directory using a layered strategy:\n *\n * 1. `TEAMIX_EVO_ADR_ROOT` env var (absolute path)\n * 2. Bundled snapshot at `<mcp-pkg>/dist/data/adr/` (works in consumer projects\n * after `pnpm add @teamix-evo/mcp` — see tsup.config.ts onSuccess copy)\n * 3. Walk up from cwd looking for `docs/adr/` (monorepo layout)\n * 4. Walk up from cwd looking for `.teamix-evo/adr/` (consumer override)\n * 5. Throws with a clear error\n */\nexport function resolveAdrRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_ADR_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n // Bundled snapshot inside the mcp package itself. import.meta.url at\n // runtime resolves to dist/cli.js or dist/index.js inside the published\n // package; its sibling `data/adr/` is populated by tsup onSuccess.\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n const bundled = join(here, 'data', 'adr');\n if (existsSync(bundled)) return bundled;\n } catch {\n // import.meta.url may be unavailable in some test environments.\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'docs', 'adr'),\n join(dir, '.teamix-evo', 'adr'),\n ];\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate ADR directory.',\n `Tried env TEAMIX_EVO_ADR_ROOT, mcp-bundled snapshot, and walked up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,\n 'Either install @teamix-evo/mcp (carries ADR snapshot) or set TEAMIX_EVO_ADR_ROOT to an absolute path.',\n ].join(' '),\n );\n}\n\nconst SKIP_FILES = new Set(['README.md', '_template.md']);\nconst ID_RE = /^(\\d{4})-/;\nconst H1_RE = /^#\\s+\\d{4}\\.\\s+(.+?)\\s*$/m;\nconst STATUS_RE = /^-\\s+\\*\\*Status\\*\\*:\\s*(.+?)\\s*$/m;\nconst DATE_RE = /^-\\s+\\*\\*Date\\*\\*:\\s*(.+?)\\s*$/m;\nconst REGION_RE = /^-\\s+\\*\\*Region\\*\\*:\\s*(.+?)\\s*$/m;\n\nfunction parseAdr(slug: string, filePath: string): AdrEntry | null {\n const idMatch = slug.match(ID_RE);\n if (!idMatch) return null;\n const id = idMatch[1]!;\n\n const text = readFileSync(filePath, 'utf-8');\n const titleMatch = text.match(H1_RE);\n const statusMatch = text.match(STATUS_RE);\n const dateMatch = text.match(DATE_RE);\n const regionMatch = text.match(REGION_RE);\n\n return {\n id,\n slug,\n title: titleMatch?.[1] ?? slug,\n status: statusMatch?.[1] ?? '',\n date: dateMatch?.[1] ?? '',\n region: regionMatch?.[1] ?? '',\n filePath,\n };\n}\n\nexport function loadAdrIndex(rootDir?: string): LoadedAdrs {\n const root = rootDir ?? resolveAdrRoot();\n const files = readdirSync(root).filter(\n (f) => f.endsWith('.md') && !SKIP_FILES.has(f),\n );\n const entries: AdrEntry[] = [];\n for (const f of files) {\n const slug = f.replace(/\\.md$/, '');\n const entry = parseAdr(slug, join(root, f));\n if (entry) entries.push(entry);\n }\n entries.sort((a, b) => a.id.localeCompare(b.id));\n return { rootDir: root, entries };\n}\n\n/**\n * Look up one ADR by id (\"0011\") or full slug (\"0011-mcp-single-package-multi-group\").\n * Returns `null` if no match.\n */\nexport function findAdr(\n loaded: LoadedAdrs,\n idOrSlug: string,\n): AdrEntry | null {\n const needle = idOrSlug.trim();\n if (/^\\d{4}$/.test(needle)) {\n return loaded.entries.find((e) => e.id === needle) ?? null;\n }\n return (\n loaded.entries.find((e) => e.slug === needle) ??\n loaded.entries.find((e) => e.id === needle) ??\n null\n );\n}\n\nexport function loadAdrContent(entry: AdrEntry): string {\n return readFileSync(entry.filePath, 'utf-8');\n}\n","/**\n * Skills tool group — exposes `@teamix-evo/skills` SKILL.md content to AI editors.\n *\n * Per [ADR 0011 §5](../../../../docs/adr/0011-mcp-single-package-multi-group.md):\n *\n * - `skills_list` — index of all shipped skills (id, name, description, version)\n * - `skills_get` — full SKILL.md content + attachment names for one skill\n * - `skills_find` — substring search across `description` (the AI trigger) + body\n *\n * `description` in SKILL.md frontmatter is the AI trigger contract per\n * [ADR 0013](../../../../docs/adr/0013-skills-source-mirror.md). Searching it\n * is the primary use of `skills_find`.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadSkillsManifest,\n loadSkillContent,\n findSkill,\n type LoadedSkills,\n} from '../skills-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\nimport type { SkillEntry } from '@teamix-evo/registry';\n\nconst ListInput = z.object({});\n\nconst GetInput = z.object({\n id: z.string().min(1),\n});\n\nconst FindInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().max(50).optional(),\n /**\n * Scope: 'description' (default — fast, only matches the AI trigger contract)\n * or 'body' (slower — matches across SKILL.md prose, useful for \"where do we\n * mention X\" questions).\n */\n scope: z.enum(['description', 'body', 'all']).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'skills_list',\n description:\n 'List all SKILL.md entries shipped by @teamix-evo/skills. Returns id, name, description (the AI trigger contract), version, source path, ides, updateStrategy. Use this to discover which skills exist before invoking one via the IDE\\'s skill mechanism.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'skills_get',\n description:\n 'Fetch the full SKILL.md content (frontmatter + body) for one skill by id or name. Also lists attachment files (sibling .md docs the skill references). Use after skills_list / skills_find to read the actual rules / decision tree / checklist that the skill encodes.',\n inputSchema: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Skill id or name (matches manifest.skills[].id or .name).',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'skills_find',\n description:\n 'Substring search across skill descriptions and bodies. Default scope is `description` (matches the AI trigger contract — fast). Set `scope: \"body\"` to search SKILL.md prose, or `scope: \"all\"` for both. Use when you remember a phrase (\"token refresh\", \"design review\", \"drift scan\") but not the skill id.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 50,\n description: 'Max matches to return (default 10).',\n },\n scope: {\n type: 'string',\n enum: ['description', 'body', 'all'],\n description:\n 'Where to search: \"description\" (frontmatter, default), \"body\" (SKILL.md prose), or \"all\".',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nfunction pickEntry(s: SkillEntry) {\n return {\n id: s.id,\n name: s.name,\n description: s.description,\n version: s.version,\n source: s.source,\n ides: s.ides ?? [],\n updateStrategy: s.updateStrategy ?? 'managed',\n template: s.template ?? false,\n };\n}\n\nexport interface SkillsGroupOptions {\n loaded?: LoadedSkills;\n}\n\nexport function createSkillsGroup(opts: SkillsGroupOptions = {}): ToolGroup {\n let cache: LoadedSkills | null = opts.loaded ?? null;\n function getManifest(): LoadedSkills {\n if (!cache) cache = loadSkillsManifest();\n return cache;\n }\n\n return {\n name: 'skills',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n if (name === 'skills_list') {\n ListInput.parse(args ?? {});\n const { manifest } = getManifest();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(manifest.skills.map(pickEntry), null, 2),\n },\n ],\n };\n }\n\n if (name === 'skills_get') {\n const input = GetInput.parse(args);\n const loaded = getManifest();\n const entry = findSkill(loaded, input.id);\n if (!entry) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill not found: ${input.id}. Use skills_list to discover ids.`,\n },\n ],\n isError: true,\n };\n }\n const content = loadSkillContent(entry, loaded.rootDir);\n if (!content) {\n return {\n content: [\n {\n type: 'text',\n text: `Skill source missing on disk for \"${entry.id}\" (expected at ${entry.source}). Check packages/skills installation.`,\n },\n ],\n isError: true,\n };\n }\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n entry: pickEntry(entry),\n attachments: content.attachments,\n content: content.text,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n if (name === 'skills_find') {\n const input = FindInput.parse(args);\n const limit = input.limit ?? 10;\n const scope = input.scope ?? 'description';\n const needle = input.query.toLowerCase();\n const loaded = getManifest();\n\n const matches: Array<{\n entry: ReturnType<typeof pickEntry>;\n hitIn: 'description' | 'body' | 'both';\n }> = [];\n\n for (const entry of loaded.manifest.skills) {\n const descHit =\n scope !== 'body' &&\n entry.description.toLowerCase().includes(needle);\n let bodyHit = false;\n if (scope === 'body' || scope === 'all') {\n const content = loadSkillContent(entry, loaded.rootDir);\n if (content) {\n bodyHit = content.text.toLowerCase().includes(needle);\n }\n }\n if (!descHit && !bodyHit) continue;\n matches.push({\n entry: pickEntry(entry),\n hitIn:\n descHit && bodyHit\n ? 'both'\n : descHit\n ? 'description'\n : 'body',\n });\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n query: input.query,\n scope,\n limit,\n count: Math.min(matches.length, limit),\n totalMatches: matches.length,\n results: matches.slice(0, limit),\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n return undefined;\n },\n };\n}\n","/**\n * Loader for `@teamix-evo/skills` (the skills source-of-truth package).\n *\n * Reads `packages/skills/manifest.json` + each `skills/<id>/SKILL.md`. The\n * frontmatter `description` is the AI trigger contract (see ADR 0013) and is\n * what `skills_find` searches over.\n *\n * In a consumer project, the same shape lives under `node_modules/@teamix-evo/skills/`.\n * Resolution order mirrors the registry/adr loaders:\n *\n * 1. `TEAMIX_EVO_SKILLS_ROOT` env var (absolute path to the package dir)\n * 2. Walk up from cwd looking for `packages/skills/` (monorepo)\n * 3. Walk up from cwd looking for `node_modules/@teamix-evo/skills/` (consumer)\n * 4. Throws with a clear error\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport {\n SkillsPackageManifestSchema,\n type SkillsPackageManifest,\n type SkillEntry,\n} from '@teamix-evo/registry';\n\nexport interface LoadedSkills {\n /** Absolute path to the package root containing manifest.json. */\n rootDir: string;\n manifest: SkillsPackageManifest;\n}\n\nexport function resolveSkillsRoot(startDir: string = process.cwd()): string {\n const envPath = process.env.TEAMIX_EVO_SKILLS_ROOT;\n if (envPath && existsSync(join(envPath, 'manifest.json'))) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidates = [\n join(dir, 'packages', 'skills'),\n join(dir, 'node_modules', '@teamix-evo', 'skills'),\n ];\n for (const c of candidates) {\n if (existsSync(join(c, 'manifest.json'))) return c;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n throw new Error(\n [\n 'Could not locate @teamix-evo/skills root.',\n `Tried env TEAMIX_EVO_SKILLS_ROOT and walked up from ${startDir} for packages/skills/ or node_modules/@teamix-evo/skills/.`,\n 'Install @teamix-evo/skills as a devDependency in your project (the scaffold adds it automatically).',\n ].join(' '),\n );\n}\n\nexport function loadSkillsManifest(rootDir?: string): LoadedSkills {\n const root = rootDir ?? resolveSkillsRoot();\n const manifestPath = join(root, 'manifest.json');\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as unknown;\n const parsed = SkillsPackageManifestSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(\n `Invalid skills manifest at ${manifestPath}: ${parsed.error.message}`,\n );\n }\n return { rootDir: root, manifest: parsed.data };\n}\n\nexport interface SkillContent {\n entry: SkillEntry;\n /** Full SKILL.md text (frontmatter + body). */\n text: string;\n /** Just the body, frontmatter stripped. Null if SKILL.md missing. */\n body: string | null;\n /** Parsed frontmatter as flat string map. */\n frontmatter: Record<string, string>;\n /** Absolute path to SKILL.md. */\n filePath: string;\n /**\n * Other markdown files attached to the skill (siblings of SKILL.md), e.g.\n * generation-flow.md / boundaries.md / checklist.md. Just the relative names —\n * the model can fetch them by name via a follow-up tool call.\n */\n attachments: string[];\n}\n\nconst FM_RE = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/;\n\nfunction parseFrontmatter(text: string): {\n frontmatter: Record<string, string>;\n body: string;\n} {\n const m = text.match(FM_RE);\n if (!m) return { frontmatter: {}, body: text };\n const fm: Record<string, string> = {};\n for (const line of m[1]!.split('\\n')) {\n const kv = line.match(/^([A-Za-z_][\\w-]*)\\s*:\\s*(.+?)\\s*$/);\n if (kv) fm[kv[1]!] = kv[2]!.replace(/^['\"]|['\"]$/g, '');\n }\n return { frontmatter: fm, body: text.slice(m[0].length) };\n}\n\nexport function loadSkillContent(\n entry: SkillEntry,\n rootDir: string,\n): SkillContent | null {\n const sourcePath = join(rootDir, entry.source);\n if (!existsSync(sourcePath)) return null;\n\n // Skills are typically directories with SKILL.md inside.\n let skillMdPath: string;\n let attachments: string[] = [];\n const dirCandidate = join(sourcePath, 'SKILL.md');\n if (existsSync(dirCandidate)) {\n skillMdPath = dirCandidate;\n // Light attachment scan: top-level .md siblings of SKILL.md.\n try {\n attachments = readdirSync(sourcePath)\n .filter((f) => f.endsWith('.md') && f !== 'SKILL.md')\n .filter((f) => {\n try {\n return statSync(join(sourcePath, f)).isFile();\n } catch {\n return false;\n }\n });\n } catch {\n attachments = [];\n }\n } else {\n // Single-file skill (entry.source points directly at a .md).\n skillMdPath = sourcePath;\n }\n\n const text = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, body } = parseFrontmatter(text);\n return {\n entry,\n text,\n body,\n frontmatter,\n filePath: skillMdPath,\n attachments,\n };\n}\n\nexport function findSkill(\n loaded: LoadedSkills,\n idOrName: string,\n): SkillEntry | null {\n const needle = idOrName.trim();\n return (\n loaded.manifest.skills.find((s) => s.id === needle) ??\n loaded.manifest.skills.find((s) => s.name === needle) ??\n null\n );\n}\n","/**\n * Tokens tool group — exposes the consumer project's design tokens\n * to AI editors via MCP.\n *\n * Per [ADR 0020](../../../../docs/adr/0020-design-to-tokens-skill-fusion.md),\n * design knowledge now lives in @teamix-evo/skills (AI reads skill files\n * directly). MCP only provides token value lookup — the one thing AI\n * can't get from a static skill file.\n *\n * - `tokens_get` — full snapshot (base JSON + theme/overrides CSS) for copy-paste\n * - `tokens_list` — flat list of token entries for introspection (category/name/values)\n * - `tokens_search` — substring search across category / name / description / values\n *\n * When `tokens/` directory is absent (project hasn't run `tokens init`),\n * the tools return empty results with a `note` field.\n */\nimport { z } from 'zod';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n loadTokens,\n readTokens,\n listTokens,\n searchTokens,\n type LoadedTokens,\n} from '../tokens-loader.js';\nimport type { ToolGroup, ToolResult } from '../types.js';\n\nconst EmptyInput = z.object({});\nconst SearchInput = z.object({\n query: z.string().min(1),\n limit: z.number().int().min(1).max(100).optional(),\n});\n\nconst TOOLS: Tool[] = [\n {\n name: 'tokens_get',\n description:\n \"Fetch the consumer project's design tokens — parsed JSON from `tokens/base.tokens.json`, plus raw text of `tokens.theme.css` (variant theme) and `tokens.overrides.css` (user-owned overrides) when present. Use when AI needs to know what semantic colors / spacing / radii are available before writing component styles. JSON is for introspection; CSS is for copy-paste. Each result lists `sources` so you can cite paths.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_list',\n description:\n 'List ALL design tokens as a flat array of entries `{ category, name, type, values, description }`. Categories come from top-level keys of base.tokens.json (e.g. `color`, `radius`, `spacing`). Each entry exposes resolved values keyed by mode (e.g. `light` / `dark` / `default`). Use this BEFORE writing styles to discover what semantic names are available — much cheaper than parsing the whole CSS file. Use `tokens_search` instead when you have a keyword.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'tokens_search',\n description:\n 'Substring match across token category / name / description / values (case-insensitive). Use when you remember a phrase (\"primary\" / \"destructive\" / \"card-gap\") but not the exact path. Returns up to `limit` matches (default 20). Combine with `tokens_get` if you need raw CSS text after locating an entry.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Free-text query.' },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: 100,\n description: 'Max matches to return (default 20).',\n },\n },\n required: ['query'],\n },\n },\n];\n\nconst TOOL_NAMES = new Set(TOOLS.map((t) => t.name));\n\nexport interface TokensGroupOptions {\n /** Pre-loaded tokens snapshot (used by tests). When omitted, the loader walks cwd. */\n loaded?: LoadedTokens | null;\n /** Override the start directory for cwd-relative resolution (used by tests). */\n rootDir?: string;\n}\n\nconst NO_TOKENS_NOTE =\n 'tokens/ directory not found in this project. Run `npx teamix-evo tokens init <variant>` to install design tokens.';\n\nexport function createTokensGroup(opts: TokensGroupOptions = {}): ToolGroup {\n let cache: LoadedTokens | null | undefined =\n opts.loaded === undefined ? undefined : opts.loaded;\n function getLoaded(): LoadedTokens | null {\n if (cache === undefined) cache = loadTokens(opts.rootDir);\n return cache;\n }\n\n return {\n name: 'tokens',\n tools: TOOLS,\n async handle(name, args): Promise<ToolResult | undefined> {\n if (!TOOL_NAMES.has(name)) return undefined;\n\n const loaded = getLoaded();\n\n if (name === 'tokens_get') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({ sources: [], note: NO_TOKENS_NOTE });\n }\n return jsonResult(readTokens(loaded));\n }\n\n if (name === 'tokens_list') {\n EmptyInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n tokens: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(listTokens(loaded));\n }\n\n if (name === 'tokens_search') {\n const parsed = SearchInput.parse(args ?? {});\n if (!loaded) {\n return jsonResult({\n variant: null,\n query: parsed.query,\n matches: [],\n sources: [],\n note: NO_TOKENS_NOTE,\n });\n }\n return jsonResult(searchTokens(loaded, parsed.query, parsed.limit));\n }\n\n return undefined;\n },\n };\n}\n\nfunction jsonResult(payload: unknown): ToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],\n };\n}\n","/**\n * Loader for the consumer project's `.teamix-evo/` state.\n *\n * Per [ADR 0020](../../../docs/adr/0020-design-to-tokens-skill-fusion.md) the\n * MCP `tokens` group reads the **installed** tokens of a teamix-evo project.\n * The loader walks up from the cwd looking for `.teamix-evo/` and, if a\n * `tokens-lock.json` is present, records the variant for downstream tools.\n *\n * Resolution order:\n *\n * 1. `TEAMIX_EVO_TOKENS_ROOT` env var (absolute path to the `.teamix-evo/` dir)\n * 2. Walk up from cwd looking for `.teamix-evo/`\n * 3. Returns `null` (not an error — projects without teamix-evo init should\n * get empty tool results with a `note`, not a thrown exception)\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface LoadedTokens {\n /** Absolute path to `.teamix-evo/` in the consumer project. */\n rootDir: string;\n /** Variant name read from `tokens-lock.json`, or null if missing. */\n variant: string | null;\n}\n\nexport function resolveTokensRoot(\n startDir: string = process.cwd(),\n): string | null {\n const envPath = process.env.TEAMIX_EVO_TOKENS_ROOT;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n let dir = resolve(startDir);\n for (let i = 0; i < 16; i++) {\n const candidate = join(dir, '.teamix-evo');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nexport function loadTokens(rootDir?: string): LoadedTokens | null {\n const root = rootDir ?? resolveTokensRoot();\n if (!root) return null;\n\n let variant: string | null = null;\n const lockPath = join(root, 'tokens-lock.json');\n if (existsSync(lockPath)) {\n try {\n const raw = JSON.parse(readFileSync(lockPath, 'utf-8')) as {\n variant?: string;\n };\n variant = typeof raw.variant === 'string' ? raw.variant : null;\n } catch {\n variant = null;\n }\n }\n return { rootDir: root, variant };\n}\n\nexport interface TokenSnapshot {\n /** Parsed contents of `base.tokens.json` if present. */\n base?: unknown;\n /** Raw text of `tokens.theme.css` if present. */\n themeCss?: string;\n /** Raw text of `tokens.overrides.css` if present (user-owned overrides). */\n overridesCss?: string;\n /** Source paths discovered, in load order. */\n sources: string[];\n note?: string;\n}\n\n/**\n * Locate the tokens directory. Tokens live at `<projectRoot>/tokens/`\n * (root-level, per ADR 0020).\n */\nfunction resolveTokensDir(loaded: LoadedTokens): string | null {\n const projectRoot = dirname(loaded.rootDir);\n const rootTokens = join(projectRoot, 'tokens');\n if (existsSync(rootTokens)) return rootTokens;\n return null;\n}\n\nexport function readTokens(loaded: LoadedTokens): TokenSnapshot {\n const tokensDir = resolveTokensDir(loaded);\n const out: TokenSnapshot = { sources: [] };\n if (!tokensDir) {\n out.note = 'tokens/ not found at project root.';\n return out;\n }\n const tryJson = (rel: string): unknown | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n try {\n return JSON.parse(readFileSync(fp, 'utf-8'));\n } catch {\n return undefined;\n }\n };\n const tryText = (rel: string): string | undefined => {\n const fp = join(tokensDir, rel);\n if (!existsSync(fp)) return undefined;\n out.sources.push(fp);\n return readFileSync(fp, 'utf-8');\n };\n out.base = tryJson('base.tokens.json');\n out.themeCss = tryText('tokens.theme.css');\n out.overridesCss = tryText('tokens.overrides.css');\n return out;\n}\n\nexport interface TokenEntry {\n /** Top-level group from base.tokens.json, e.g. \"color\" / \"radius\" / \"spacing\". */\n category: string;\n /** Token leaf name within the category, e.g. \"primary\" / \"card-foreground\". */\n name: string;\n /** W3C `$type` declared on the token, when present. */\n type?: string;\n /**\n * Resolved values keyed by mode. For W3C tokens with `light` / `dark`\n * sub-objects we emit both; for flat tokens (single `$value`) we emit\n * `default`.\n */\n values: Record<string, string>;\n /** First non-empty `$description` found on the token or its modes. */\n description?: string;\n}\n\nconst W3C_KEYS = new Set(['$value', '$type', '$description', '$extensions']);\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Flatten a W3C-format design-token JSON tree into a list of token entries.\n *\n * The format we ingest is the one shipped by `@teamix-evo/tokens`:\n *\n * { color: { primary: { $type, light: { $value, $description }, dark: { ... } } } }\n *\n * For tokens with `$value` directly under the leaf (no light/dark split) we\n * emit `values = { default: <value> }`.\n *\n * Top-level keys starting with `$` (e.g. `$schema`, `$version`) are skipped.\n */\nexport function flattenTokens(base: unknown): TokenEntry[] {\n if (!isPlainObject(base)) return [];\n const out: TokenEntry[] = [];\n\n for (const [category, group] of Object.entries(base)) {\n if (category.startsWith('$')) continue;\n if (!isPlainObject(group)) continue;\n\n for (const [name, leaf] of Object.entries(group)) {\n if (name.startsWith('$')) continue;\n if (!isPlainObject(leaf)) continue;\n\n const type =\n typeof leaf.$type === 'string' ? (leaf.$type as string) : undefined;\n const values: Record<string, string> = {};\n let description =\n typeof leaf.$description === 'string'\n ? (leaf.$description as string)\n : undefined;\n\n if (typeof leaf.$value === 'string') {\n values.default = leaf.$value as string;\n }\n\n for (const [modeKey, modeVal] of Object.entries(leaf)) {\n if (W3C_KEYS.has(modeKey)) continue;\n if (!isPlainObject(modeVal)) continue;\n if (typeof modeVal.$value === 'string') {\n values[modeKey] = modeVal.$value as string;\n }\n if (\n !description &&\n typeof modeVal.$description === 'string'\n ) {\n description = modeVal.$description as string;\n }\n }\n\n if (Object.keys(values).length === 0) continue;\n\n out.push({\n category,\n name,\n ...(type ? { type } : {}),\n values,\n ...(description ? { description } : {}),\n });\n }\n }\n\n return out;\n}\n\nexport interface TokenListResult {\n variant: string | null;\n tokens: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\nexport function listTokens(loaded: LoadedTokens): TokenListResult {\n const snapshot = readTokens(loaded);\n if (!snapshot.base) {\n return {\n variant: loaded.variant,\n tokens: [],\n sources: snapshot.sources,\n note: snapshot.note ?? 'base.tokens.json not found.',\n };\n }\n return {\n variant: loaded.variant,\n tokens: flattenTokens(snapshot.base),\n sources: snapshot.sources,\n };\n}\n\nexport interface TokenSearchResult {\n variant: string | null;\n query: string;\n matches: TokenEntry[];\n sources: string[];\n note?: string;\n}\n\n/**\n * Substring match across category / name / description / values. Case-insensitive.\n * Returns up to `limit` (default 20) matches ordered by category > name.\n */\nexport function searchTokens(\n loaded: LoadedTokens,\n query: string,\n limit = 20,\n): TokenSearchResult {\n const list = listTokens(loaded);\n const q = query.trim().toLowerCase();\n if (!q) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: 'query is empty.',\n };\n }\n if (list.note && list.tokens.length === 0) {\n return {\n variant: list.variant,\n query,\n matches: [],\n sources: list.sources,\n note: list.note,\n };\n }\n const hits = list.tokens.filter((t) => {\n if (t.category.toLowerCase().includes(q)) return true;\n if (t.name.toLowerCase().includes(q)) return true;\n if (t.description?.toLowerCase().includes(q)) return true;\n return Object.values(t.values).some((v) => v.toLowerCase().includes(q));\n });\n hits.sort((a, b) => {\n const c = a.category.localeCompare(b.category);\n return c !== 0 ? c : a.name.localeCompare(b.name);\n });\n return {\n variant: list.variant,\n query,\n matches: hits.slice(0, limit),\n sources: list.sources,\n };\n}\n"],"mappings":"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","names":["FM_RE","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES","from","z","existsSync","readFileSync","readdirSync","dirname","join","resolve","parseFrontmatter","ListInput","z","GetInput","FindInput","TOOLS","TOOL_NAMES","pickEntry","z","existsSync","readFileSync","dirname","join","resolve","z","TOOLS","TOOL_NAMES"]}