@teamix-evo/mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +161 -162
  3. package/dist/cli.js.map +1 -1
  4. package/dist/data/adr/0001-three-layer-alignment.md +54 -0
  5. package/dist/data/adr/0002-package-naming.md +50 -0
  6. package/dist/data/adr/0003-update-strategy-tri-state.md +62 -0
  7. package/dist/data/adr/0004-cli-command-structure.md +61 -0
  8. package/dist/data/adr/0005-ui-no-variant.md +67 -0
  9. package/dist/data/adr/0006-ui-upgrade-no-baseline.md +67 -0
  10. package/dist/data/adr/0007-governance-docs-at-root.md +62 -0
  11. package/dist/data/adr/0008-eslint-visual-rules-warn-baseline.md +110 -0
  12. package/dist/data/adr/0009-registry-mcp-protocol-layer.md +87 -0
  13. package/dist/data/adr/0010-design-default-and-variants.md +319 -0
  14. package/dist/data/adr/0011-mcp-single-package-multi-group.md +169 -0
  15. package/dist/data/adr/0012-lint-shared-core.md +215 -0
  16. package/dist/data/adr/0013-skills-source-mirror.md +154 -0
  17. package/dist/data/adr/0014-ui-biz-ui-templates-tier.md +274 -0
  18. package/dist/data/adr/0015-skill-description-trigger-contract.md +122 -0
  19. package/dist/data/adr/0016-design-md-brand-charter.md +93 -0
  20. package/dist/data/adr/0017-mcp-design-group.md +107 -0
  21. package/dist/data/adr/0018-ai-context-routing.md +112 -0
  22. package/dist/data/adr/0019-project-upgrade-flow.md +156 -0
  23. package/dist/data/adr/0020-design-to-tokens-skill-fusion.md +139 -0
  24. package/dist/data/adr/README.md +70 -0
  25. package/dist/data/adr/_template.md +36 -0
  26. package/dist/index.d.ts +64 -59
  27. package/dist/index.js +168 -170
  28. package/dist/index.js.map +1 -1
  29. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -37,10 +37,15 @@ function resolveManifestPath(startDir = process.cwd()) {
37
37
  }
38
38
  throw new Error(
39
39
  [
40
- "Could not locate @teamix-evo/ui/manifest.json.",
41
- `Tried env TEAMIX_EVO_UI_MANIFEST + walking up from ${startDir}.`,
42
- "Either install @teamix-evo/ui in the consumer project, or set TEAMIX_EVO_UI_MANIFEST to an absolute path."
43
- ].join(" ")
40
+ "Could not locate @teamix-evo/ui/manifest.json \u2014 the UI registry is not installed in this project.",
41
+ "",
42
+ "Fix one of:",
43
+ ` 1. Install the package: pnpm add @teamix-evo/ui (or npm/yarn equivalent)`,
44
+ ` 2. Point env at an existing manifest: export TEAMIX_EVO_UI_MANIFEST=/abs/path/to/manifest.json`,
45
+ "",
46
+ `Searched: $TEAMIX_EVO_UI_MANIFEST, then walked up from ${startDir} looking for node_modules/@teamix-evo/ui/manifest.json (16 levels).`,
47
+ "Note: MCP currently has no online fallback \u2014 it does not fetch from the npm registry / unpkg."
48
+ ].join("\n")
44
49
  );
45
50
  }
46
51
  function loadManifest(path) {
@@ -235,11 +240,18 @@ import { z as z2 } from "zod";
235
240
  // src/adr-loader.ts
236
241
  import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync } from "fs";
237
242
  import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
243
+ import { fileURLToPath } from "url";
238
244
  function resolveAdrRoot(startDir = process.cwd()) {
239
245
  const envPath = process.env.TEAMIX_EVO_ADR_ROOT;
240
246
  if (envPath && existsSync2(envPath)) {
241
247
  return envPath;
242
248
  }
249
+ try {
250
+ const here = dirname2(fileURLToPath(import.meta.url));
251
+ const bundled = join2(here, "data", "adr");
252
+ if (existsSync2(bundled)) return bundled;
253
+ } catch {
254
+ }
243
255
  let dir = resolve2(startDir);
244
256
  for (let i = 0; i < 16; i++) {
245
257
  const candidates = [
@@ -256,8 +268,8 @@ function resolveAdrRoot(startDir = process.cwd()) {
256
268
  throw new Error(
257
269
  [
258
270
  "Could not locate ADR directory.",
259
- `Tried env TEAMIX_EVO_ADR_ROOT + walking up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,
260
- "Either run from a teamix-evo monorepo, or set TEAMIX_EVO_ADR_ROOT to an absolute path."
271
+ `Tried env TEAMIX_EVO_ADR_ROOT, mcp-bundled snapshot, and walked up from ${startDir} for docs/adr/ or .teamix-evo/adr/.`,
272
+ "Either install @teamix-evo/mcp (carries ADR snapshot) or set TEAMIX_EVO_ADR_ROOT to an absolute path."
261
273
  ].join(" ")
262
274
  );
263
275
  }
@@ -541,8 +553,8 @@ function resolveSkillsRoot(startDir = process.cwd()) {
541
553
  throw new Error(
542
554
  [
543
555
  "Could not locate @teamix-evo/skills root.",
544
- `Tried env TEAMIX_EVO_SKILLS_ROOT + walking up from ${startDir}.`,
545
- "Either install @teamix-evo/skills or run from a monorepo, or set TEAMIX_EVO_SKILLS_ROOT to an absolute path."
556
+ `Tried env TEAMIX_EVO_SKILLS_ROOT and walked up from ${startDir} for packages/skills/ or node_modules/@teamix-evo/skills/.`,
557
+ "Install @teamix-evo/skills as a devDependency in your project (the scaffold adds it automatically)."
546
558
  ].join(" ")
547
559
  );
548
560
  }
@@ -792,20 +804,20 @@ function createSkillsGroup(opts = {}) {
792
804
  };
793
805
  }
794
806
 
795
- // src/groups/design.ts
807
+ // src/groups/tokens.ts
796
808
  import { z as z4 } from "zod";
797
809
 
798
- // src/design-loader.ts
799
- import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
810
+ // src/tokens-loader.ts
811
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
800
812
  import { dirname as dirname4, join as join4, resolve as resolve4 } from "path";
801
- function resolveDesignRoot(startDir = process.cwd()) {
802
- const envPath = process.env.TEAMIX_EVO_DESIGN_ROOT;
813
+ function resolveTokensRoot(startDir = process.cwd()) {
814
+ const envPath = process.env.TEAMIX_EVO_TOKENS_ROOT;
803
815
  if (envPath && existsSync4(envPath)) {
804
816
  return envPath;
805
817
  }
806
818
  let dir = resolve4(startDir);
807
819
  for (let i = 0; i < 16; i++) {
808
- const candidate = join4(dir, ".teamix-evo", "design");
820
+ const candidate = join4(dir, ".teamix-evo");
809
821
  if (existsSync4(candidate)) return candidate;
810
822
  const parent = dirname4(dir);
811
823
  if (parent === dir) break;
@@ -813,11 +825,11 @@ function resolveDesignRoot(startDir = process.cwd()) {
813
825
  }
814
826
  return null;
815
827
  }
816
- function loadDesign(rootDir) {
817
- const root = rootDir ?? resolveDesignRoot();
828
+ function loadTokens(rootDir) {
829
+ const root = rootDir ?? resolveTokensRoot();
818
830
  if (!root) return null;
819
831
  let variant = null;
820
- const lockPath = join4(root, "pack.lock.json");
832
+ const lockPath = join4(root, "tokens-lock.json");
821
833
  if (existsSync4(lockPath)) {
822
834
  try {
823
835
  const raw = JSON.parse(readFileSync4(lockPath, "utf-8"));
@@ -828,47 +840,17 @@ function loadDesign(rootDir) {
828
840
  }
829
841
  return { rootDir: root, variant };
830
842
  }
831
- var PRINCIPLE_HEADING_RE = /^#{2,3}\s+(P\d+)\s*[·:]\s*(.+?)\s*$/;
832
- function readPrinciples(loaded) {
833
- const filePath = join4(loaded.rootDir, "philosophy", "principles.md");
834
- if (!existsSync4(filePath)) {
835
- return {
836
- principles: [],
837
- sourcePath: null,
838
- note: "philosophy/principles.md not found in this project. Run `teamix-evo design init <variant>` to install it."
839
- };
840
- }
841
- const text = readFileSync4(filePath, "utf-8");
842
- const lines = text.split(/\r?\n/);
843
- const out = [];
844
- for (let i = 0; i < lines.length; i++) {
845
- const m = lines[i].match(PRINCIPLE_HEADING_RE);
846
- if (!m) continue;
847
- let def = "";
848
- for (let j = i + 1; j < lines.length && j < i + 8; j++) {
849
- const candidate = lines[j].trim();
850
- if (!candidate) continue;
851
- if (/^#{1,6}\s/.test(candidate)) break;
852
- def = candidate.replace(/^[*_>\s-]+/, "").trim();
853
- break;
854
- }
855
- out.push({ id: m[1], name: m[2].trim(), oneLineDef: def });
856
- }
857
- return { principles: out, sourcePath: filePath };
858
- }
859
843
  function resolveTokensDir(loaded) {
860
844
  const projectRoot = dirname4(loaded.rootDir);
861
- const lifted = join4(projectRoot, "tokens");
862
- if (existsSync4(lifted)) return lifted;
863
- const legacy = join4(loaded.rootDir, "foundations", "tokens");
864
- if (existsSync4(legacy)) return legacy;
845
+ const rootTokens = join4(projectRoot, "tokens");
846
+ if (existsSync4(rootTokens)) return rootTokens;
865
847
  return null;
866
848
  }
867
849
  function readTokens(loaded) {
868
850
  const tokensDir = resolveTokensDir(loaded);
869
851
  const out = { sources: [] };
870
852
  if (!tokensDir) {
871
- out.note = ".teamix-evo/tokens/ not found in this project (and no legacy foundations/tokens/).";
853
+ out.note = "tokens/ not found at project root.";
872
854
  return out;
873
855
  }
874
856
  const tryJson = (rel) => {
@@ -888,169 +870,186 @@ function readTokens(loaded) {
888
870
  return readFileSync4(fp, "utf-8");
889
871
  };
890
872
  out.base = tryJson("base.tokens.json");
891
- out.semantic = tryJson("semantic.tokens.json");
892
873
  out.themeCss = tryText("tokens.theme.css");
893
874
  out.overridesCss = tryText("tokens.overrides.css");
894
875
  return out;
895
876
  }
896
- var VARIANT_PREFIX_RE = /^(cloud|opentrek|uni-manager|enterprise)-/i;
897
- function readPatternIndex(loaded) {
898
- const patternsDir = join4(loaded.rootDir, "patterns");
899
- if (!existsSync4(patternsDir)) return [];
877
+ var W3C_KEYS = /* @__PURE__ */ new Set(["$value", "$type", "$description", "$extensions"]);
878
+ function isPlainObject(v) {
879
+ return typeof v === "object" && v !== null && !Array.isArray(v);
880
+ }
881
+ function flattenTokens(base) {
882
+ if (!isPlainObject(base)) return [];
900
883
  const out = [];
901
- for (const name of readdirSync3(patternsDir)) {
902
- if (!name.endsWith(".md")) continue;
903
- const fp = join4(patternsDir, name);
904
- try {
905
- if (!statSync2(fp).isFile()) continue;
906
- } catch {
907
- continue;
884
+ for (const [category, group] of Object.entries(base)) {
885
+ if (category.startsWith("$")) continue;
886
+ if (!isPlainObject(group)) continue;
887
+ for (const [name, leaf] of Object.entries(group)) {
888
+ if (name.startsWith("$")) continue;
889
+ if (!isPlainObject(leaf)) continue;
890
+ const type = typeof leaf.$type === "string" ? leaf.$type : void 0;
891
+ const values = {};
892
+ let description = typeof leaf.$description === "string" ? leaf.$description : void 0;
893
+ if (typeof leaf.$value === "string") {
894
+ values.default = leaf.$value;
895
+ }
896
+ for (const [modeKey, modeVal] of Object.entries(leaf)) {
897
+ if (W3C_KEYS.has(modeKey)) continue;
898
+ if (!isPlainObject(modeVal)) continue;
899
+ if (typeof modeVal.$value === "string") {
900
+ values[modeKey] = modeVal.$value;
901
+ }
902
+ if (!description && typeof modeVal.$description === "string") {
903
+ description = modeVal.$description;
904
+ }
905
+ }
906
+ if (Object.keys(values).length === 0) continue;
907
+ out.push({
908
+ category,
909
+ name,
910
+ ...type ? { type } : {},
911
+ values,
912
+ ...description ? { description } : {}
913
+ });
908
914
  }
909
- const stem = name.replace(/\.md$/, "");
910
- const text = readFileSync4(fp, "utf-8");
911
- const titleMatch = text.match(/^#\s+(.+?)\s*$/m);
912
- out.push({
913
- id: stem,
914
- title: titleMatch ? titleMatch[1] : stem,
915
- sourcePath: fp,
916
- variantSpecific: VARIANT_PREFIX_RE.test(stem)
917
- });
918
915
  }
919
- return out.sort((a, b) => a.id.localeCompare(b.id));
916
+ return out;
920
917
  }
921
- function readPatternContent(loaded, id) {
922
- const stem = id.replace(/\.md$/, "");
923
- const fp = join4(loaded.rootDir, "patterns", `${stem}.md`);
924
- if (!existsSync4(fp)) return null;
918
+ function listTokens(loaded) {
919
+ const snapshot = readTokens(loaded);
920
+ if (!snapshot.base) {
921
+ return {
922
+ variant: loaded.variant,
923
+ tokens: [],
924
+ sources: snapshot.sources,
925
+ note: snapshot.note ?? "base.tokens.json not found."
926
+ };
927
+ }
925
928
  return {
926
- id: stem,
927
- sourcePath: fp,
928
- content: readFileSync4(fp, "utf-8")
929
+ variant: loaded.variant,
930
+ tokens: flattenTokens(snapshot.base),
931
+ sources: snapshot.sources
929
932
  };
930
933
  }
931
- function readBrand(loaded) {
932
- const brandDir = join4(loaded.rootDir, "brand");
933
- const out = {};
934
- if (!existsSync4(brandDir)) {
935
- out.note = "brand/ not present \u2014 this design variant does not ship brand-specific tone / voice / examples.";
936
- return out;
934
+ function searchTokens(loaded, query, limit = 20) {
935
+ const list = listTokens(loaded);
936
+ const q = query.trim().toLowerCase();
937
+ if (!q) {
938
+ return {
939
+ variant: list.variant,
940
+ query,
941
+ matches: [],
942
+ sources: list.sources,
943
+ note: "query is empty."
944
+ };
937
945
  }
938
- for (const key of ["tone", "voice", "examples"]) {
939
- const fp = join4(brandDir, `${key}.md`);
940
- if (existsSync4(fp)) {
941
- out[key] = { sourcePath: fp, content: readFileSync4(fp, "utf-8") };
942
- }
946
+ if (list.note && list.tokens.length === 0) {
947
+ return {
948
+ variant: list.variant,
949
+ query,
950
+ matches: [],
951
+ sources: list.sources,
952
+ note: list.note
953
+ };
943
954
  }
944
- return out;
955
+ const hits = list.tokens.filter((t) => {
956
+ if (t.category.toLowerCase().includes(q)) return true;
957
+ if (t.name.toLowerCase().includes(q)) return true;
958
+ if (t.description?.toLowerCase().includes(q)) return true;
959
+ return Object.values(t.values).some((v) => v.toLowerCase().includes(q));
960
+ });
961
+ hits.sort((a, b) => {
962
+ const c = a.category.localeCompare(b.category);
963
+ return c !== 0 ? c : a.name.localeCompare(b.name);
964
+ });
965
+ return {
966
+ variant: list.variant,
967
+ query,
968
+ matches: hits.slice(0, limit),
969
+ sources: list.sources
970
+ };
945
971
  }
946
972
 
947
- // src/groups/design.ts
973
+ // src/groups/tokens.ts
948
974
  var EmptyInput = z4.object({});
949
- var GetPatternInput = z4.object({
950
- id: z4.string().min(1)
975
+ var SearchInput = z4.object({
976
+ query: z4.string().min(1),
977
+ limit: z4.number().int().min(1).max(100).optional()
951
978
  });
952
979
  var TOOLS4 = [
953
980
  {
954
- name: "design_list_principles",
955
- description: 'List the design principles defined by the consumer project\'s installed design variant. Reads `.teamix-evo/design/philosophy/principles.md` and parses headings of the form `## P1 \xB7 Name`. Returns id, display name, and a one-line definition for each. Use this when the user asks about "the four principles", "design philosophy", or to ground a design review in the variant\'s stated values. Returns `{ principles: [], note: "..." }` if the project hasn\'t installed a design pack.',
956
- inputSchema: { type: "object", properties: {} }
957
- },
958
- {
959
- name: "design_get_tokens",
960
- description: "Fetch the consumer project's design tokens \u2014 parsed JSON from `.teamix-evo/tokens/base.tokens.json` and `semantic.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 tool result lists `sources` so you can cite paths.",
981
+ name: "tokens_get",
982
+ description: "Fetch the consumer project's design tokens \u2014 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.",
961
983
  inputSchema: { type: "object", properties: {} }
962
984
  },
963
985
  {
964
- name: "design_list_patterns",
965
- description: "Index every pattern in `.teamix-evo/design/patterns/*.md` (page types, journeys, flows, plus variant-specific markers like `cloud-*`, `opentrek-*`, `uni-manager-*`). Returns `{ id, title, sourcePath, variantSpecific }` for each. Use this before `design_get_pattern` to discover which patterns exist. When both a baseline (`page-types`) and a variant-specific (`cloud-page-types`) entry are available, prefer the variant-specific one for projects that match.",
986
+ name: "tokens_list",
987
+ description: "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 \u2014 much cheaper than parsing the whole CSS file. Use `tokens_search` instead when you have a keyword.",
966
988
  inputSchema: { type: "object", properties: {} }
967
989
  },
968
990
  {
969
- name: "design_get_pattern",
970
- description: "Fetch the full markdown body of one pattern by id (filename stem, e.g. `page-types` or `cloud-page-types`). Use after `design_list_patterns` discovered the id. Returns the raw markdown plus `sourcePath`. Returns isError if the id does not exist \u2014 call `design_list_patterns` first to discover available ids.",
991
+ name: "tokens_search",
992
+ description: '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.',
971
993
  inputSchema: {
972
994
  type: "object",
973
995
  properties: {
974
- id: {
975
- type: "string",
976
- description: 'Pattern id \u2014 filename stem under `patterns/`, e.g. "page-types", "cloud-page-types".'
996
+ query: { type: "string", description: "Free-text query." },
997
+ limit: {
998
+ type: "integer",
999
+ minimum: 1,
1000
+ maximum: 100,
1001
+ description: "Max matches to return (default 20)."
977
1002
  }
978
1003
  },
979
- required: ["id"]
1004
+ required: ["query"]
980
1005
  }
981
- },
982
- {
983
- name: "design_get_brand",
984
- description: "Fetch the consumer project's variant-specific brand voice \u2014 `brand/tone.md`, `brand/voice.md`, `brand/examples.md`. Each is optional; the response contains only the files that exist. Some variants (like `_template` or `default`) ship no brand content \u2014 that's not an error, the response simply lists no entries. Use this when generating or reviewing user-facing copy, error messages, empty states, or onboarding text where brand voice matters.",
985
- inputSchema: { type: "object", properties: {} }
986
1006
  }
987
1007
  ];
988
1008
  var TOOL_NAMES4 = new Set(TOOLS4.map((t) => t.name));
989
- var NO_DESIGN_NOTE = ".teamix-evo/design/ not found in this project. Run `npx teamix-evo design init <variant>` to install a design pack.";
990
- function createDesignGroup(opts = {}) {
1009
+ var NO_TOKENS_NOTE = "tokens/ directory not found in this project. Run `npx teamix-evo tokens init <variant>` to install design tokens.";
1010
+ function createTokensGroup(opts = {}) {
991
1011
  let cache = opts.loaded === void 0 ? void 0 : opts.loaded;
992
- function getDesign() {
993
- if (cache === void 0) cache = loadDesign(opts.rootDir);
1012
+ function getLoaded() {
1013
+ if (cache === void 0) cache = loadTokens(opts.rootDir);
994
1014
  return cache;
995
1015
  }
996
1016
  return {
997
- name: "design",
1017
+ name: "tokens",
998
1018
  tools: TOOLS4,
999
1019
  async handle(name, args) {
1000
1020
  if (!TOOL_NAMES4.has(name)) return void 0;
1001
- const loaded = getDesign();
1002
- if (name === "design_list_principles") {
1003
- EmptyInput.parse(args ?? {});
1004
- if (!loaded) {
1005
- return jsonResult({ principles: [], sourcePath: null, note: NO_DESIGN_NOTE });
1006
- }
1007
- return jsonResult(readPrinciples(loaded));
1008
- }
1009
- if (name === "design_get_tokens") {
1021
+ const loaded = getLoaded();
1022
+ if (name === "tokens_get") {
1010
1023
  EmptyInput.parse(args ?? {});
1011
1024
  if (!loaded) {
1012
- return jsonResult({ sources: [], note: NO_DESIGN_NOTE });
1025
+ return jsonResult({ sources: [], note: NO_TOKENS_NOTE });
1013
1026
  }
1014
1027
  return jsonResult(readTokens(loaded));
1015
1028
  }
1016
- if (name === "design_list_patterns") {
1029
+ if (name === "tokens_list") {
1017
1030
  EmptyInput.parse(args ?? {});
1018
1031
  if (!loaded) {
1019
- return jsonResult({ patterns: [], note: NO_DESIGN_NOTE });
1020
- }
1021
- return jsonResult({
1022
- variant: loaded.variant,
1023
- patterns: readPatternIndex(loaded)
1024
- });
1025
- }
1026
- if (name === "design_get_pattern") {
1027
- const input = GetPatternInput.parse(args);
1028
- if (!loaded) {
1029
- return {
1030
- content: [{ type: "text", text: NO_DESIGN_NOTE }],
1031
- isError: true
1032
- };
1033
- }
1034
- const result = readPatternContent(loaded, input.id);
1035
- if (!result) {
1036
- return {
1037
- content: [
1038
- {
1039
- type: "text",
1040
- text: `Pattern not found: ${input.id}. Use design_list_patterns to discover available ids.`
1041
- }
1042
- ],
1043
- isError: true
1044
- };
1032
+ return jsonResult({
1033
+ variant: null,
1034
+ tokens: [],
1035
+ sources: [],
1036
+ note: NO_TOKENS_NOTE
1037
+ });
1045
1038
  }
1046
- return jsonResult(result);
1039
+ return jsonResult(listTokens(loaded));
1047
1040
  }
1048
- if (name === "design_get_brand") {
1049
- EmptyInput.parse(args ?? {});
1041
+ if (name === "tokens_search") {
1042
+ const parsed = SearchInput.parse(args ?? {});
1050
1043
  if (!loaded) {
1051
- return jsonResult({ note: NO_DESIGN_NOTE });
1044
+ return jsonResult({
1045
+ variant: null,
1046
+ query: parsed.query,
1047
+ matches: [],
1048
+ sources: [],
1049
+ note: NO_TOKENS_NOTE
1050
+ });
1052
1051
  }
1053
- return jsonResult(readBrand(loaded));
1052
+ return jsonResult(searchTokens(loaded, parsed.query, parsed.limit));
1054
1053
  }
1055
1054
  return void 0;
1056
1055
  }
@@ -1068,7 +1067,7 @@ function createServer(opts = {}) {
1068
1067
  createRegistryGroup(opts.registry),
1069
1068
  createAdrGroup(opts.adr),
1070
1069
  createSkillsGroup(opts.skills),
1071
- createDesignGroup(opts.design)
1070
+ createTokensGroup(opts.tokens)
1072
1071
  // Future: createScenarioGroup(opts.scenario), // ADR 0011, v0.8
1073
1072
  ];
1074
1073
  const seen = /* @__PURE__ */ new Set();
@@ -1115,27 +1114,26 @@ function createServer(opts = {}) {
1115
1114
  }
1116
1115
  export {
1117
1116
  createAdrGroup,
1118
- createDesignGroup,
1119
1117
  createRegistryGroup,
1120
1118
  createServer,
1121
1119
  createSkillsGroup,
1120
+ createTokensGroup,
1122
1121
  findAdr,
1123
1122
  findSkill,
1123
+ flattenTokens,
1124
+ listTokens,
1124
1125
  loadAdrContent,
1125
1126
  loadAdrIndex,
1126
- loadDesign,
1127
1127
  loadManifest,
1128
1128
  loadMeta,
1129
1129
  loadSkillContent,
1130
1130
  loadSkillsManifest,
1131
- readBrand,
1132
- readPatternContent,
1133
- readPatternIndex,
1134
- readPrinciples,
1131
+ loadTokens,
1135
1132
  readTokens,
1136
1133
  resolveAdrRoot,
1137
- resolveDesignRoot,
1138
1134
  resolveManifestPath,
1139
- resolveSkillsRoot
1135
+ resolveSkillsRoot,
1136
+ resolveTokensRoot,
1137
+ searchTokens
1140
1138
  };
1141
1139
  //# sourceMappingURL=index.js.map