@elevasis/sdk 1.18.0 → 1.20.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 (58) hide show
  1. package/dist/cli.cjs +1915 -70
  2. package/dist/index.d.ts +825 -16
  3. package/dist/index.js +714 -63
  4. package/dist/node/index.d.ts +1 -0
  5. package/dist/node/index.js +213 -2
  6. package/dist/test-utils/index.d.ts +479 -14
  7. package/dist/test-utils/index.js +660 -54
  8. package/dist/worker/index.js +516 -54
  9. package/package.json +4 -4
  10. package/reference/_navigation.md +2 -1
  11. package/reference/_reference-manifest.json +14 -0
  12. package/reference/claude-config/registries/graph-skills.json +4 -0
  13. package/reference/claude-config/rules/agent-start-here.md +5 -5
  14. package/reference/claude-config/rules/deployment.md +4 -3
  15. package/reference/claude-config/rules/frontend.md +2 -2
  16. package/reference/claude-config/rules/operations.md +17 -13
  17. package/reference/claude-config/rules/organization-model.md +7 -5
  18. package/reference/claude-config/rules/organization-os.md +13 -11
  19. package/reference/claude-config/rules/ui.md +3 -3
  20. package/reference/claude-config/rules/vibe.md +4 -4
  21. package/reference/claude-config/skills/explore/SKILL.md +4 -4
  22. package/reference/claude-config/skills/knowledge/SKILL.md +17 -16
  23. package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +7 -7
  24. package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +13 -13
  25. package/reference/claude-config/skills/knowledge/operations/customers.md +1 -1
  26. package/reference/claude-config/skills/knowledge/operations/goals.md +1 -1
  27. package/reference/claude-config/skills/knowledge/operations/identity.md +1 -1
  28. package/reference/claude-config/skills/knowledge/operations/offerings.md +1 -1
  29. package/reference/claude-config/skills/knowledge/operations/roles.md +1 -1
  30. package/reference/claude-config/skills/knowledge/operations/techStack.md +19 -91
  31. package/reference/claude-config/skills/project/SKILL.md +73 -13
  32. package/reference/claude-config/skills/save/SKILL.md +5 -5
  33. package/reference/claude-config/skills/tutorial/technical.md +11 -14
  34. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -0
  35. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -0
  36. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -0
  37. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -0
  38. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -0
  39. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -0
  40. package/reference/examples/organization-model.ts +17 -5
  41. package/reference/framework/index.mdx +1 -1
  42. package/reference/framework/project-structure.mdx +10 -8
  43. package/reference/packages/core/src/business/README.md +2 -2
  44. package/reference/packages/core/src/organization-model/README.md +10 -3
  45. package/reference/resources/index.mdx +27 -17
  46. package/reference/scaffold/core/organization-model.mdx +33 -14
  47. package/reference/scaffold/operations/workflow-recipes.md +35 -29
  48. package/reference/scaffold/recipes/add-a-feature.md +18 -3
  49. package/reference/scaffold/recipes/add-a-resource.md +50 -10
  50. package/reference/scaffold/recipes/customize-crm-actions.md +12 -6
  51. package/reference/scaffold/recipes/customize-organization-model.md +18 -3
  52. package/reference/scaffold/recipes/extend-crm.md +17 -19
  53. package/reference/scaffold/recipes/extend-lead-gen.md +31 -31
  54. package/reference/scaffold/recipes/index.md +1 -1
  55. package/reference/scaffold/reference/contracts.md +512 -307
  56. package/reference/scaffold/reference/feature-registry.md +1 -1
  57. package/reference/scaffold/reference/glossary.md +8 -3
  58. package/reference/scaffold/ui/recipes.md +21 -6
@@ -18,6 +18,7 @@ interface GenerateKnowledgeNodesOptions {
18
18
  sourceDir: string;
19
19
  outputPath: string;
20
20
  graphSkillsOutputPath?: string;
21
+ knowledgeFlagsOutputPath?: string;
21
22
  typeImportPath?: string;
22
23
  exportedName?: string;
23
24
  sourceLabel?: string;
@@ -68,6 +68,132 @@ function optionalStringArray(frontmatter, key, filePath) {
68
68
  }
69
69
  return value.map((entry) => entry.trim()).filter(Boolean);
70
70
  }
71
+ var ROUTING_STOPWORDS = /* @__PURE__ */ new Set([
72
+ "about",
73
+ "after",
74
+ "again",
75
+ "against",
76
+ "all",
77
+ "also",
78
+ "and",
79
+ "any",
80
+ "are",
81
+ "before",
82
+ "but",
83
+ "can",
84
+ "cannot",
85
+ "could",
86
+ "for",
87
+ "from",
88
+ "has",
89
+ "have",
90
+ "how",
91
+ "into",
92
+ "its",
93
+ "may",
94
+ "more",
95
+ "must",
96
+ "not",
97
+ "now",
98
+ "off",
99
+ "one",
100
+ "only",
101
+ "our",
102
+ "out",
103
+ "over",
104
+ "per",
105
+ "run",
106
+ "same",
107
+ "should",
108
+ "than",
109
+ "that",
110
+ "the",
111
+ "their",
112
+ "then",
113
+ "there",
114
+ "this",
115
+ "through",
116
+ "use",
117
+ "uses",
118
+ "using",
119
+ "when",
120
+ "where",
121
+ "with",
122
+ "workflow",
123
+ "workflows",
124
+ "would",
125
+ "you",
126
+ "your"
127
+ ]);
128
+ function toRegistryPath(path) {
129
+ return path.replace(/\\/g, "/");
130
+ }
131
+ function slugify(value) {
132
+ return value.trim().toLowerCase().replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
133
+ }
134
+ function toTitle(value) {
135
+ return value.split(/[-:\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
136
+ }
137
+ function tokenizeRoutingText(...values) {
138
+ return values.join(" ").toLowerCase().replace(/```[\s\S]*?```/g, " ").replace(/[\\/]/g, " ").match(/[a-z0-9]+(?:[.-][a-z0-9]+)*/g)?.flatMap((token) => {
139
+ const expanded = token.includes(".") ? [token, ...token.split(".")] : [token];
140
+ return expanded.flatMap((entry) => entry.includes("-") ? [entry, ...entry.split("-")] : [entry]);
141
+ }) ?? [];
142
+ }
143
+ function rankedTerms(values, limit) {
144
+ const counts = /* @__PURE__ */ new Map();
145
+ for (const value of values) {
146
+ const token = slugify(value);
147
+ if (!token || ROUTING_STOPWORDS.has(token)) continue;
148
+ if (token.length < 3 && token !== "ai") continue;
149
+ counts.set(token, (counts.get(token) ?? 0) + 1);
150
+ }
151
+ return [...counts.entries()].sort(([termA, countA], [termB, countB]) => countB - countA || termA.localeCompare(termB)).slice(0, limit).map(([term]) => term);
152
+ }
153
+ function uniqueSorted(values) {
154
+ return [...new Set(values.filter(Boolean))].sort((a, b) => a.localeCompare(b));
155
+ }
156
+ function nodeRoutingTerms(node, sourcePath, limit) {
157
+ return rankedTerms(
158
+ tokenizeRoutingText(
159
+ node.id,
160
+ node.kind,
161
+ node.title,
162
+ node.summary,
163
+ node.body,
164
+ node.domain ?? "",
165
+ sourcePath,
166
+ ...node.links.map((link) => link.nodeId),
167
+ ...node.skills
168
+ ),
169
+ limit
170
+ );
171
+ }
172
+ function nodeTags(node, sourcePath) {
173
+ return uniqueSorted([
174
+ ...node.domain ? [node.domain] : [],
175
+ node.kind,
176
+ ...tokenizeRoutingText(
177
+ node.title,
178
+ node.summary,
179
+ sourcePath,
180
+ ...node.links.map((link) => link.nodeId),
181
+ ...node.skills
182
+ ).map(slugify).filter((term) => term && !ROUTING_STOPWORDS.has(term) && (term.length >= 3 || term === "ai")).slice(0, 20)
183
+ ]);
184
+ }
185
+ function readCommandForNode(node) {
186
+ return [
187
+ {
188
+ command: `pnpm exec elevasis knowledge:cat ${node.id}`,
189
+ description: `Read ${node.title}`
190
+ },
191
+ {
192
+ command: `pnpm exec elevasis knowledge:ls /by-kind/${node.kind}`,
193
+ description: `List ${node.kind} knowledge nodes`
194
+ }
195
+ ];
196
+ }
71
197
  function readKnowledgeNodeMdx(filePath) {
72
198
  const raw = readFileSync(filePath, "utf8");
73
199
  const { frontmatter, body } = parseFrontmatter(raw, filePath);
@@ -108,6 +234,79 @@ function generateGraphSkillsRegistry(nodes) {
108
234
  domains: Object.fromEntries(Object.entries(domains).sort(([a], [b]) => a.localeCompare(b)))
109
235
  };
110
236
  }
237
+ function generateKnowledgeFlagRegistry(nodes, sourcePaths = {}) {
238
+ const routes = /* @__PURE__ */ new Map();
239
+ for (const node of nodes) {
240
+ const routeKey = node.domain ?? `kind-${node.kind}`;
241
+ const flag = `--${slugify(routeKey)}`;
242
+ const sourcePath = toRegistryPath(sourcePaths[node.id] ?? "");
243
+ const routingTerms = nodeRoutingTerms(node, sourcePath, 24);
244
+ const tags = nodeTags(node, sourcePath);
245
+ const skills = uniqueSorted(node.skills);
246
+ const cliBindings = readCommandForNode(node);
247
+ const route = routes.get(flag) ?? {
248
+ flag,
249
+ label: toTitle(routeKey),
250
+ ...node.domain ? { domain: node.domain } : { kind: node.kind },
251
+ tags: [],
252
+ queryTerms: [],
253
+ skills: [],
254
+ cliBindings: [],
255
+ nodes: []
256
+ };
257
+ route.tags = uniqueSorted([...route.tags, ...tags]);
258
+ route.queryTerms = rankedTerms([...route.queryTerms, ...routingTerms], 40);
259
+ route.skills = uniqueSorted([...route.skills, ...skills]);
260
+ route.cliBindings = [...route.cliBindings, ...cliBindings].filter(
261
+ (binding, index, bindings) => bindings.findIndex((candidate) => candidate.command === binding.command) === index
262
+ );
263
+ route.nodes.push({
264
+ id: node.id,
265
+ title: node.title,
266
+ kind: node.kind,
267
+ ...node.domain ? { domain: node.domain } : {},
268
+ sourcePath,
269
+ tags,
270
+ routingTerms,
271
+ links: node.links.map((link) => link.nodeId),
272
+ skills,
273
+ cliBindings
274
+ });
275
+ routes.set(flag, route);
276
+ }
277
+ const sortedRoutes = [...routes.values()].sort((a, b) => a.flag.localeCompare(b.flag));
278
+ const aliasCandidates = sortedRoutes.flatMap((route) => {
279
+ const aliasTerms = uniqueSorted([
280
+ route.flag.replace(/^--/, ""),
281
+ route.label.toLowerCase(),
282
+ ...route.tags.slice(0, 12),
283
+ ...route.queryTerms.slice(0, 12)
284
+ ]);
285
+ return aliasTerms.map((alias) => [alias, route.flag]);
286
+ });
287
+ const aliasCounts = aliasCandidates.reduce((counts, [alias]) => {
288
+ counts.set(alias, (counts.get(alias) ?? 0) + 1);
289
+ return counts;
290
+ }, /* @__PURE__ */ new Map());
291
+ const aliases = Object.fromEntries(
292
+ aliasCandidates.filter(([alias]) => aliasCounts.get(alias) === 1).sort(([aliasA], [aliasB]) => aliasA.localeCompare(aliasB))
293
+ );
294
+ return {
295
+ generatedBy: "generate-knowledge-nodes",
296
+ routingMode: "deterministic-keyword",
297
+ flags: Object.fromEntries(
298
+ sortedRoutes.map((route) => [
299
+ route.flag,
300
+ {
301
+ ...route,
302
+ cliBindings: route.cliBindings.sort((a, b) => a.command.localeCompare(b.command)),
303
+ nodes: route.nodes.sort((a, b) => a.id.localeCompare(b.id))
304
+ }
305
+ ])
306
+ ),
307
+ aliases
308
+ };
309
+ }
111
310
  function generateKnowledgeNodesTs(options) {
112
311
  const exportedName = options.exportedName ?? "mdxKnowledgeNodes";
113
312
  const typeImport = options.typeImportPath ? [`import type { OrgKnowledgeNode } from '${options.typeImportPath}'`, ""] : [];
@@ -127,6 +326,9 @@ function generateKnowledgeNodes(options) {
127
326
  (a, b) => relative(options.sourceDir, a).localeCompare(relative(options.sourceDir, b))
128
327
  );
129
328
  const nodes = files.map(readKnowledgeNodeMdx);
329
+ const sourcePaths = Object.fromEntries(
330
+ files.map((file, index) => [nodes[index].id, toRegistryPath(relative(options.sourceDir, file))])
331
+ );
130
332
  const ids = /* @__PURE__ */ new Set();
131
333
  for (const node of nodes) {
132
334
  if (ids.has(node.id)) throw new Error(`[knowledge-node-codegen] Duplicate knowledge node id: ${node.id}`);
@@ -148,6 +350,15 @@ function generateKnowledgeNodes(options) {
148
350
  writeFileSync(
149
351
  options.graphSkillsOutputPath,
150
352
  `${JSON.stringify(generateGraphSkillsRegistry(nodes), null, 2)}
353
+ `,
354
+ "utf8"
355
+ );
356
+ }
357
+ if (options.knowledgeFlagsOutputPath) {
358
+ mkdirSync(dirname(options.knowledgeFlagsOutputPath), { recursive: true });
359
+ writeFileSync(
360
+ options.knowledgeFlagsOutputPath,
361
+ `${JSON.stringify(generateKnowledgeFlagRegistry(nodes, sourcePaths), null, 2)}
151
362
  `,
152
363
  "utf8"
153
364
  );
@@ -188,7 +399,7 @@ function stripToPlainText(body) {
188
399
  var BODIES_HEADER = [
189
400
  "// @generated by generate-knowledge-bodies -- DO NOT EDIT",
190
401
  "// Regenerate: pnpm scaffold:sync",
191
- "// Source: packages/elevasis-core/src/organization-model.ts",
402
+ "// Source: packages/elevasis-core/src/organization-model/index.ts",
192
403
  "",
193
404
  "import { Fragment, jsx, jsxs } from 'react/jsx-runtime'",
194
405
  "import type { ComponentType } from 'react'",
@@ -236,7 +447,7 @@ async function generateKnowledgeBodies(nodes) {
236
447
  const bodiesTsx2 = [
237
448
  "// @generated by generate-knowledge-bodies -- DO NOT EDIT",
238
449
  "// Regenerate: pnpm scaffold:sync",
239
- "// Source: packages/elevasis-core/src/organization-model.ts",
450
+ "// Source: packages/elevasis-core/src/organization-model/index.ts",
240
451
  "",
241
452
  "import type { ComponentType } from 'react'",
242
453
  "",