@elevasis/sdk 1.32.0 → 1.33.1

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.cjs +617 -376
  2. package/dist/index.d.ts +3 -4
  3. package/dist/index.js +15 -3
  4. package/dist/node/index.d.ts +1 -2
  5. package/dist/test-utils/index.d.ts +0 -1
  6. package/dist/test-utils/index.js +14 -2
  7. package/package.json +3 -3
  8. package/reference/claude-config/Overview.md +123 -0
  9. package/reference/claude-config/registries/skill-coverage.json +19 -0
  10. package/reference/claude-config/skills/client/SKILL.md +201 -0
  11. package/reference/claude-config/skills/elevasis/SKILL.md +244 -235
  12. package/reference/claude-config/skills/om/SKILL.md +56 -5
  13. package/reference/claude-config/skills/om/operations/features.md +12 -5
  14. package/reference/claude-config/skills/om/operations/scaffold.md +10 -0
  15. package/reference/claude-config/skills/setup/SKILL.md +9 -0
  16. package/reference/claude-config/sync-notes/2026-06-02-knowledge-nested-group-routing.md +27 -0
  17. package/reference/claude-config/sync-notes/2026-06-02-nest-projects-under-platform.md +45 -0
  18. package/reference/claude-config/sync-notes/2026-06-03-skill-autogen-and-client-skill.md +34 -0
  19. package/reference/claude-config/sync-notes/2026-06-04-scaffold-registry-lane-severity.md +34 -0
  20. package/reference/rules/agent-start-here.md +8 -2
  21. package/reference/rules/organization-os.md +11 -7
  22. package/reference/rules/package-taxonomy.md +4 -0
  23. package/reference/scaffold/core/organization-graph.mdx +9 -8
  24. package/reference/scaffold/operations/propagation-pipeline.md +13 -9
  25. package/reference/scaffold/operations/scaffold-maintenance.md +8 -7
  26. package/reference/scaffold/recipes/customize-knowledge-browser.md +23 -26
  27. package/reference/scaffold/reference/feature-registry.md +1 -1
  28. package/reference/scaffold/ui/composition-extensibility.mdx +1 -1
  29. package/reference/sdk/cli-management.mdx +2 -2
  30. package/reference/sdk/framework/agent.mdx +1 -1
package/dist/cli.cjs CHANGED
@@ -5765,7 +5765,7 @@ var require_buffer_list = __commonJS({
5765
5765
  }
5766
5766
  }, {
5767
5767
  key: "join",
5768
- value: function join13(s) {
5768
+ value: function join15(s) {
5769
5769
  if (this.length === 0) return "";
5770
5770
  var p = this.head;
5771
5771
  var ret = "" + p.data;
@@ -23628,20 +23628,20 @@ var init_config = __esm({
23628
23628
 
23629
23629
  // src/cli/commands/om/project-layout.ts
23630
23630
  function assertSplitLayout(projectDir) {
23631
- const omDir = (0, import_node_path7.join)(projectDir, "core", "config", "organization-model");
23632
- const missing = REQUIRED_FILES.filter((f) => !(0, import_node_fs7.existsSync)((0, import_node_path7.join)(omDir, f)));
23631
+ const omDir = (0, import_node_path9.join)(projectDir, "core", "config", "organization-model");
23632
+ const missing = REQUIRED_FILES.filter((f) => !(0, import_node_fs8.existsSync)((0, import_node_path9.join)(omDir, f)));
23633
23633
  if (missing.length > 0) {
23634
23634
  throw new Error(
23635
23635
  "Legacy single-file OM layout detected. Split into `core/config/organization-model/{profile.ts, systems.ts, navigation.ts}` before scaffolding."
23636
23636
  );
23637
23637
  }
23638
23638
  }
23639
- var import_node_fs7, import_node_path7, REQUIRED_FILES;
23639
+ var import_node_fs8, import_node_path9, REQUIRED_FILES;
23640
23640
  var init_project_layout = __esm({
23641
23641
  "src/cli/commands/om/project-layout.ts"() {
23642
23642
  "use strict";
23643
- import_node_fs7 = require("node:fs");
23644
- import_node_path7 = require("node:path");
23643
+ import_node_fs8 = require("node:fs");
23644
+ import_node_path9 = require("node:path");
23645
23645
  REQUIRED_FILES = ["profile.ts", "systems.ts", "navigation.ts"];
23646
23646
  }
23647
23647
  });
@@ -23715,7 +23715,6 @@ function emitSystemEntry(opts) {
23715
23715
  const apiInterfaceBlock = opts.apiBacked ? `
23716
23716
  apiInterface: {
23717
23717
  lifecycle: 'active',
23718
- readinessProfile: 'standard',
23719
23718
  resourceIds: []
23720
23719
  },` : "";
23721
23720
  const code = ` {
@@ -23742,7 +23741,7 @@ async function withSnapshotRollback(filePaths, op) {
23742
23741
  const snapshots = /* @__PURE__ */ new Map();
23743
23742
  for (const filePath of filePaths) {
23744
23743
  try {
23745
- snapshots.set(filePath, (0, import_node_fs8.readFileSync)(filePath, "utf8"));
23744
+ snapshots.set(filePath, (0, import_node_fs9.readFileSync)(filePath, "utf8"));
23746
23745
  } catch {
23747
23746
  snapshots.set(filePath, null);
23748
23747
  }
@@ -23753,7 +23752,7 @@ async function withSnapshotRollback(filePaths, op) {
23753
23752
  for (const [filePath, snapshot] of snapshots) {
23754
23753
  if (snapshot !== null) {
23755
23754
  try {
23756
- (0, import_node_fs8.writeFileSync)(filePath, snapshot, "utf8");
23755
+ (0, import_node_fs9.writeFileSync)(filePath, snapshot, "utf8");
23757
23756
  } catch {
23758
23757
  }
23759
23758
  }
@@ -23774,14 +23773,14 @@ function insertBeforeAnchorInContent(content, code, anchor) {
23774
23773
  return lines.join("\n");
23775
23774
  }
23776
23775
  async function appendBeforeAnchor(filePath, code, anchor) {
23777
- const content = (0, import_node_fs8.readFileSync)(filePath, "utf8");
23776
+ const content = (0, import_node_fs9.readFileSync)(filePath, "utf8");
23778
23777
  const updated = insertBeforeAnchorInContent(content, code, anchor);
23779
- (0, import_node_fs8.writeFileSync)(filePath, updated, "utf8");
23778
+ (0, import_node_fs9.writeFileSync)(filePath, updated, "utf8");
23780
23779
  }
23781
23780
  async function applyConstImport(systemsFilePath, importLine, fieldLine, importAnchor, fieldAnchor, newConstFilePath, newConstFileCode) {
23782
- (0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(newConstFilePath), { recursive: true });
23783
- (0, import_node_fs8.writeFileSync)(newConstFilePath, newConstFileCode, "utf8");
23784
- const systemsContent = (0, import_node_fs8.readFileSync)(systemsFilePath, "utf8");
23781
+ (0, import_node_fs9.mkdirSync)((0, import_node_path10.dirname)(newConstFilePath), { recursive: true });
23782
+ (0, import_node_fs9.writeFileSync)(newConstFilePath, newConstFileCode, "utf8");
23783
+ const systemsContent = (0, import_node_fs9.readFileSync)(systemsFilePath, "utf8");
23785
23784
  const afterImport = insertBeforeAnchorInContent(systemsContent, importLine + "\n", importAnchor);
23786
23785
  const lines = afterImport.split("\n");
23787
23786
  const fieldAnchorIndex = lines.findIndex((line) => fieldAnchor.test(line));
@@ -23791,14 +23790,14 @@ async function applyConstImport(systemsFilePath, importLine, fieldLine, importAn
23791
23790
  );
23792
23791
  }
23793
23792
  lines.splice(fieldAnchorIndex + 1, 0, fieldLine);
23794
- (0, import_node_fs8.writeFileSync)(systemsFilePath, lines.join("\n"), "utf8");
23793
+ (0, import_node_fs9.writeFileSync)(systemsFilePath, lines.join("\n"), "utf8");
23795
23794
  }
23796
- var import_node_fs8, import_node_path8;
23795
+ var import_node_fs9, import_node_path10;
23797
23796
  var init_splice = __esm({
23798
23797
  "src/cli/commands/om/splice.ts"() {
23799
23798
  "use strict";
23800
- import_node_fs8 = require("node:fs");
23801
- import_node_path8 = require("node:path");
23799
+ import_node_fs9 = require("node:fs");
23800
+ import_node_path10 = require("node:path");
23802
23801
  }
23803
23802
  });
23804
23803
 
@@ -23861,7 +23860,7 @@ async function scaffoldSystem(opts) {
23861
23860
  }
23862
23861
  return;
23863
23862
  }
23864
- const systemsFilePath = (0, import_node_path9.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23863
+ const systemsFilePath = (0, import_node_path11.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23865
23864
  try {
23866
23865
  await withSnapshotRollback([systemsFilePath], async () => {
23867
23866
  await appendBeforeAnchor(systemsFilePath, code, anchor);
@@ -23882,11 +23881,11 @@ async function scaffoldSystem(opts) {
23882
23881
  );
23883
23882
  }
23884
23883
  }
23885
- var import_node_path9, import_node_child_process2;
23884
+ var import_node_path11, import_node_child_process2;
23886
23885
  var init_scaffold_system = __esm({
23887
23886
  "src/cli/commands/om/scaffold-system.ts"() {
23888
23887
  "use strict";
23889
- import_node_path9 = require("node:path");
23888
+ import_node_path11 = require("node:path");
23890
23889
  import_node_child_process2 = require("node:child_process");
23891
23890
  init_source();
23892
23891
  init_config();
@@ -23980,7 +23979,7 @@ async function scaffoldResource(opts) {
23980
23979
  console.log(code);
23981
23980
  return;
23982
23981
  }
23983
- const systemsFilePath = (0, import_node_path10.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23982
+ const systemsFilePath = (0, import_node_path12.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23984
23983
  try {
23985
23984
  await withSnapshotRollback([systemsFilePath], async () => {
23986
23985
  await appendBeforeAnchor(systemsFilePath, code, anchor);
@@ -23998,11 +23997,11 @@ Resource \`${id}\` references system \`${systemPath}\` which is not in \`templat
23998
23997
  }
23999
23998
  console.log(source_default.green(`Resource \`${id}\` scaffolded in core/config/organization-model/systems.ts`));
24000
23999
  }
24001
- var import_node_path10, import_node_child_process3;
24000
+ var import_node_path12, import_node_child_process3;
24002
24001
  var init_scaffold_resource = __esm({
24003
24002
  "src/cli/commands/om/scaffold-resource.ts"() {
24004
24003
  "use strict";
24005
- import_node_path10 = require("node:path");
24004
+ import_node_path12 = require("node:path");
24006
24005
  import_node_child_process3 = require("node:child_process");
24007
24006
  init_source();
24008
24007
  init_config();
@@ -24073,7 +24072,7 @@ async function scaffoldRole(opts) {
24073
24072
  console.log(code);
24074
24073
  return;
24075
24074
  }
24076
- const profileFilePath = (0, import_node_path11.join)(projectDir, "core", "config", "organization-model", "profile.ts");
24075
+ const profileFilePath = (0, import_node_path13.join)(projectDir, "core", "config", "organization-model", "profile.ts");
24077
24076
  try {
24078
24077
  await withSnapshotRollback([profileFilePath], async () => {
24079
24078
  await appendBeforeAnchor(profileFilePath, code, anchor);
@@ -24089,11 +24088,11 @@ async function scaffoldRole(opts) {
24089
24088
  }
24090
24089
  console.log(source_default.green(`Role \`${id}\` scaffolded in core/config/organization-model/profile.ts`));
24091
24090
  }
24092
- var import_node_path11, import_node_child_process4;
24091
+ var import_node_path13, import_node_child_process4;
24093
24092
  var init_scaffold_role = __esm({
24094
24093
  "src/cli/commands/om/scaffold-role.ts"() {
24095
24094
  "use strict";
24096
- import_node_path11 = require("node:path");
24095
+ import_node_path13 = require("node:path");
24097
24096
  import_node_child_process4 = require("node:child_process");
24098
24097
  init_source();
24099
24098
  init_config();
@@ -24168,25 +24167,25 @@ async function scaffoldKnowledge(opts) {
24168
24167
  console.log(source_default.yellow("Run `elevasis-sdk om:generate` to register this node."));
24169
24168
  return;
24170
24169
  }
24171
- const absoluteFilePath = (0, import_node_path12.join)(projectDir, relativeFilePath);
24172
- if ((0, import_node_fs9.existsSync)(absoluteFilePath)) {
24170
+ const absoluteFilePath = (0, import_node_path14.join)(projectDir, relativeFilePath);
24171
+ if ((0, import_node_fs10.existsSync)(absoluteFilePath)) {
24173
24172
  process.stderr.write(
24174
24173
  source_default.red(`Knowledge node file already exists at \`${relativeFilePath}\`. Choose a different id.
24175
24174
  `)
24176
24175
  );
24177
24176
  process.exit(1);
24178
24177
  }
24179
- (0, import_node_fs9.mkdirSync)((0, import_node_path12.join)(projectDir, "core", "config", "knowledge", "nodes"), { recursive: true });
24180
- (0, import_node_fs9.writeFileSync)(absoluteFilePath, content, "utf8");
24178
+ (0, import_node_fs10.mkdirSync)((0, import_node_path14.join)(projectDir, "core", "config", "knowledge", "nodes"), { recursive: true });
24179
+ (0, import_node_fs10.writeFileSync)(absoluteFilePath, content, "utf8");
24181
24180
  console.log(source_default.green(`Knowledge node \`${id}\` written to \`${relativeFilePath}\``));
24182
24181
  console.log(source_default.yellow("Run `elevasis-sdk om:generate` to register this node."));
24183
24182
  }
24184
- var import_node_path12, import_node_fs9, VALID_KINDS;
24183
+ var import_node_path14, import_node_fs10, VALID_KINDS;
24185
24184
  var init_scaffold_knowledge = __esm({
24186
24185
  "src/cli/commands/om/scaffold-knowledge.ts"() {
24187
24186
  "use strict";
24188
- import_node_path12 = require("node:path");
24189
- import_node_fs9 = require("node:fs");
24187
+ import_node_path14 = require("node:path");
24188
+ import_node_fs10 = require("node:fs");
24190
24189
  init_source();
24191
24190
  init_config();
24192
24191
  init_project_layout();
@@ -24210,7 +24209,6 @@ function emitApiInterfaceBlock(gap) {
24210
24209
 
24211
24210
  export const ${constName} = {
24212
24211
  lifecycle: 'active' as const,
24213
- readinessProfile: 'standard' as const,
24214
24212
  resourceIds: ${resourceIdsLiteral}
24215
24213
  }
24216
24214
  `;
@@ -24240,7 +24238,7 @@ __export(scaffold_fill_exports, {
24240
24238
  default: () => scaffoldFill
24241
24239
  });
24242
24240
  function conformanceGapTempPath(orgName) {
24243
- return (0, import_node_path13.join)(os2.tmpdir(), `elevasis-conformance-${orgName}-${Date.now()}.json`);
24241
+ return (0, import_node_path15.join)(os2.tmpdir(), `elevasis-conformance-${orgName}-${Date.now()}.json`);
24244
24242
  }
24245
24243
  function runValidation4(projectDir) {
24246
24244
  for (const script of ["check-types", "check"]) {
@@ -24263,7 +24261,7 @@ async function scaffoldFill(opts) {
24263
24261
  process.stderr.write(source_default.red("Missing gaps file. Pass --gaps <path> pointing to a conformance gap JSON file.\n"));
24264
24262
  process.exit(1);
24265
24263
  }
24266
- if (!(0, import_node_fs10.existsSync)(options.gaps)) {
24264
+ if (!(0, import_node_fs11.existsSync)(options.gaps)) {
24267
24265
  process.stderr.write(
24268
24266
  source_default.red(
24269
24267
  `Missing gaps file. Pass --gaps <path> pointing to a conformance gap JSON file.
@@ -24275,7 +24273,7 @@ async function scaffoldFill(opts) {
24275
24273
  }
24276
24274
  let payload;
24277
24275
  try {
24278
- const raw = (0, import_node_fs10.readFileSync)(options.gaps, "utf8");
24276
+ const raw = (0, import_node_fs11.readFileSync)(options.gaps, "utf8");
24279
24277
  payload = JSON.parse(raw);
24280
24278
  } catch {
24281
24279
  process.stderr.write(
@@ -24300,7 +24298,7 @@ async function scaffoldFill(opts) {
24300
24298
  const systemPath = payload.systemPath;
24301
24299
  const skippedGaps = [];
24302
24300
  const appliedGaps = [];
24303
- const systemsFilePath = (0, import_node_path13.join)(projectDir, "core", "config", "organization-model", "systems.ts");
24301
+ const systemsFilePath = (0, import_node_path15.join)(projectDir, "core", "config", "organization-model", "systems.ts");
24304
24302
  const touchedFiles = [systemsFilePath];
24305
24303
  const emitResults = [];
24306
24304
  for (const gap of payload.gaps) {
@@ -24317,7 +24315,7 @@ async function scaffoldFill(opts) {
24317
24315
  resourceIds,
24318
24316
  message: gap.reason
24319
24317
  });
24320
- const constFilePath = (0, import_node_path13.join)(
24318
+ const constFilePath = (0, import_node_path15.join)(
24321
24319
  projectDir,
24322
24320
  "core",
24323
24321
  "config",
@@ -24365,7 +24363,7 @@ async function scaffoldFill(opts) {
24365
24363
  await withSnapshotRollback(touchedFiles, async () => {
24366
24364
  for (let i = 0; i < emitResults.length; i++) {
24367
24365
  const result = emitResults[i];
24368
- const constFilePath = (0, import_node_path13.join)(
24366
+ const constFilePath = (0, import_node_path15.join)(
24369
24367
  projectDir,
24370
24368
  "core",
24371
24369
  "config",
@@ -24395,8 +24393,8 @@ async function scaffoldFill(opts) {
24395
24393
  }
24396
24394
  }
24397
24395
  if (skippedGaps.length > 0) {
24398
- const skippedPath = options.skipped ?? (0, import_node_path13.join)(os2.tmpdir(), `elevasis-fill-skipped-${systemPath}-${Date.now()}.json`);
24399
- (0, import_node_fs10.writeFileSync)(skippedPath, JSON.stringify({ systemPath, skipped: skippedGaps }, null, 2), "utf8");
24396
+ const skippedPath = options.skipped ?? (0, import_node_path15.join)(os2.tmpdir(), `elevasis-fill-skipped-${systemPath}-${Date.now()}.json`);
24397
+ (0, import_node_fs11.writeFileSync)(skippedPath, JSON.stringify({ systemPath, skipped: skippedGaps }, null, 2), "utf8");
24400
24398
  console.log(
24401
24399
  source_default.yellow(
24402
24400
  `Partial fill: ${appliedGaps.length} gap(s) applied, ${skippedGaps.length} skipped \u2014 see \`${skippedPath}\` for fields requiring manual input.`
@@ -24410,13 +24408,13 @@ async function scaffoldFill(opts) {
24410
24408
  )
24411
24409
  );
24412
24410
  }
24413
- var import_node_path13, os2, import_node_fs10, import_node_child_process5;
24411
+ var import_node_path15, os2, import_node_fs11, import_node_child_process5;
24414
24412
  var init_scaffold_fill = __esm({
24415
24413
  "src/cli/commands/om/scaffold-fill.ts"() {
24416
24414
  "use strict";
24417
- import_node_path13 = require("node:path");
24415
+ import_node_path15 = require("node:path");
24418
24416
  os2 = __toESM(require("node:os"), 1);
24419
- import_node_fs10 = require("node:fs");
24417
+ import_node_fs11 = require("node:fs");
24420
24418
  import_node_child_process5 = require("node:child_process");
24421
24419
  init_source();
24422
24420
  init_config();
@@ -37928,7 +37926,8 @@ var ONTOLOGY_REFERENCE_KEY_KINDS = {
37928
37926
  surfaceType: "surface",
37929
37927
  stepCatalog: "catalog"
37930
37928
  };
37931
- function buildOmCrossRefIndex(model) {
37929
+ var omCompilationContextCache = /* @__PURE__ */ new WeakMap();
37930
+ function buildOmCrossRefIndexFromOntology(model, ontologyCompilation) {
37932
37931
  const systemsById = /* @__PURE__ */ new Map();
37933
37932
  for (const { path: path3, system } of listAllSystems(model)) {
37934
37933
  systemsById.set(path3, system);
@@ -37942,7 +37941,6 @@ function buildOmCrossRefIndex(model) {
37942
37941
  const actionIds = new Set(Object.keys(model.actions ?? {}));
37943
37942
  const customerSegmentIds = new Set(Object.keys(model.customers ?? {}));
37944
37943
  const offeringIds = new Set(Object.keys(model.offerings ?? {}));
37945
- const ontologyCompilation = compileOrganizationOntology(model);
37946
37944
  const ontologyIndexByKind = {
37947
37945
  object: ontologyCompilation.ontology.objectTypes,
37948
37946
  link: ontologyCompilation.ontology.linkTypes,
@@ -37981,6 +37979,15 @@ function buildOmCrossRefIndex(model) {
37981
37979
  stageIds
37982
37980
  };
37983
37981
  }
37982
+ function buildOmCompilationContext(model) {
37983
+ const cached2 = omCompilationContextCache.get(model);
37984
+ if (cached2 !== void 0) return cached2;
37985
+ const ontologyCompilation = compileOrganizationOntology(model);
37986
+ const crossRefIndex = buildOmCrossRefIndexFromOntology(model, ontologyCompilation);
37987
+ const context = { crossRefIndex, ontologyCompilation };
37988
+ omCompilationContextCache.set(model, context);
37989
+ return context;
37990
+ }
37984
37991
  function knowledgeTargetExists(index, kind, id) {
37985
37992
  if (kind === "system") return index.systemsById.has(id);
37986
37993
  if (kind === "client") return index.clientIds.has(id);
@@ -38632,8 +38639,6 @@ var SystemEntrySchema = external_exports.object({
38632
38639
  path: PathSchema.optional(),
38633
38640
  /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
38634
38641
  icon: IconNameSchema.optional(),
38635
- /** @deprecated Feature color token, retained for one-cycle compatibility. */
38636
- color: ColorTokenSchema.optional(),
38637
38642
  /** @deprecated UI placement hint, retained for one-cycle compatibility. */
38638
38643
  uiPosition: UiPositionSchema.optional(),
38639
38644
  /** @deprecated Use lifecycle. */
@@ -38730,7 +38735,7 @@ var ResourceOntologyBindingSchema = external_exports.object({
38730
38735
  /**
38731
38736
  * Optional typed contract binding for this resource's workflow I/O.
38732
38737
  * Each ref is a `package/subpath#ExportName` string that resolves to a
38733
- * Zod schema in `@repo/elevasis-core` (or the consumer's equivalent package).
38738
+ * Zod schema in the tenant-owned organization model package.
38734
38739
  *
38735
38740
  * Absence of this field preserves all existing behavior — it is additive + optional.
38736
38741
  * Tier-1 validation (schema.ts): ref-string shape only (browser-safe, no imports).
@@ -39489,9 +39494,8 @@ function refineOrganizationModel(model, ctx) {
39489
39494
  }
39490
39495
  });
39491
39496
  });
39492
- const idx = buildOmCrossRefIndex(model);
39497
+ const { crossRefIndex: idx, ontologyCompilation } = buildOmCompilationContext(model);
39493
39498
  const { ontologyIndexByKind, ontologyIds } = idx;
39494
- const ontologyCompilation = compileOrganizationOntology(model);
39495
39499
  function topologyTargetExists(ref) {
39496
39500
  if (ref.kind === "system") return systemsById.has(ref.id);
39497
39501
  if (ref.kind === "resource") return resourcesById.has(ref.id);
@@ -42173,6 +42177,20 @@ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel) {
42173
42177
  for (const { path: path3, system } of listAllSystems(model)) {
42174
42178
  if (system.apiInterface === void 0) continue;
42175
42179
  const interfaceKey = "api";
42180
+ const resourceIds = system.apiInterface.resourceIds ?? [];
42181
+ if (resourceIds.length === 0) {
42182
+ const readinessProfile = system.apiInterface.readinessProfile;
42183
+ if (readinessProfile !== void 0 && !SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile)) {
42184
+ addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, {
42185
+ family: "SYSTEM_INTERFACE_INVALID",
42186
+ code: "unknown-readiness-profile",
42187
+ path: `systems.${path3}.apiInterface.readinessProfile`,
42188
+ ref: readinessProfile,
42189
+ message: `System Interface "${path3}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
42190
+ });
42191
+ }
42192
+ continue;
42193
+ }
42176
42194
  const result = computeInterfaceReadiness(model, { systemPath: path3, interfaceKey });
42177
42195
  for (const issue2 of result.issues) {
42178
42196
  addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, issue2);
@@ -45716,7 +45734,7 @@ function wrapAction(commandName, fn) {
45716
45734
  // package.json
45717
45735
  var package_default = {
45718
45736
  name: "@elevasis/sdk",
45719
- version: "1.32.0",
45737
+ version: "1.33.1",
45720
45738
  description: "SDK for building Elevasis organization resources",
45721
45739
  type: "module",
45722
45740
  bin: {
@@ -45756,7 +45774,7 @@ var package_default = {
45756
45774
  ],
45757
45775
  scripts: {
45758
45776
  lint: "eslint src --max-warnings 0",
45759
- build: `node -e "require('fs').rmSync('dist',{recursive:true,force:true})" && tsc -p tsconfig.core-dts.json && tsc -p tsconfig.build.json && tsup && rollup -c rollup.dts.config.mjs && esbuild src/cli/index.ts --bundle --platform=node --outfile=dist/cli.cjs --format=cjs --external:esbuild --banner:js="#!/usr/bin/env node" && node scripts/copy-reference-docs.mjs && node ../../scripts/monorepo/generate-reference-artifacts.js`,
45777
+ build: `node -e "require('fs').rmSync('dist',{recursive:true,force:true})" && tsc -p tsconfig.core-dts.json && tsc -p tsconfig.build.json && tsup && rollup -c rollup.dts.config.mjs && esbuild src/cli/index.ts --bundle --platform=node --outfile=dist/cli.cjs --format=cjs --external:esbuild --banner:js="#!/usr/bin/env node" && node scripts/verify-skill-coverage.mjs && node scripts/copy-reference-docs.mjs && node ../../scripts/monorepo/generate-reference-artifacts.js`,
45760
45778
  "type-check": "tsc --noEmit",
45761
45779
  "check-types": "pnpm type-check",
45762
45780
  test: "pnpm build && node ../../scripts/monorepo/validate-reference-artifacts.js && vitest run --config vitest.bundle.config.ts",
@@ -46236,10 +46254,221 @@ import { startWorker } from '@elevasis/sdk/worker'
46236
46254
 
46237
46255
  // src/cli/commands/check.ts
46238
46256
  init_config();
46257
+
46258
+ // src/cli/commands/skill/skill-check-coverage.ts
46259
+ var import_node_path2 = require("node:path");
46260
+ init_source();
46261
+
46262
+ // src/cli/commands/cli/catalog.ts
46263
+ function buildCliCatalogFromProgram(program3, options = {}) {
46264
+ const commands = program3.commands.flatMap((command) => collectRuntimeCommands(command));
46265
+ return groupCommands(commands, "registered Commander commands", options.domain);
46266
+ }
46267
+ function groupCommands(commands, sourceRoot, domain2) {
46268
+ const filtered = domain2 ? commands.filter((command) => command.domain === domain2) : commands;
46269
+ const sorted = filtered.sort((a, b) => a.domain.localeCompare(b.domain) || a.syntax.localeCompare(b.syntax));
46270
+ const domainNames = [...new Set(sorted.map((command) => command.domain))];
46271
+ return {
46272
+ sourceRoot,
46273
+ domains: domainNames.map((name) => ({
46274
+ name,
46275
+ commands: sorted.filter((command) => command.domain === name)
46276
+ }))
46277
+ };
46278
+ }
46279
+ function collectRuntimeCommands(command, parent) {
46280
+ const commandName = command.name();
46281
+ const argSuffix = formatRuntimeArguments(command.registeredArguments);
46282
+ const syntaxSegment = argSuffix ? `${commandName} ${argSuffix}` : commandName;
46283
+ const syntax = parent ? `${parent.syntax} ${syntaxSegment}` : syntaxSegment;
46284
+ const domain2 = parent?.domain ?? domainFromCommand(commandName);
46285
+ const current = {
46286
+ command: commandName,
46287
+ syntax,
46288
+ domain: domain2
46289
+ };
46290
+ const aliases = command.aliases().map((alias) => parent ? `${parent.syntax} ${alias}` : alias);
46291
+ return [
46292
+ {
46293
+ syntax,
46294
+ command: commandName,
46295
+ domain: domain2,
46296
+ description: firstLine(command.description()),
46297
+ aliases,
46298
+ options: command.options.map((option) => ({
46299
+ flags: option.flags,
46300
+ description: option.description,
46301
+ required: option.mandatory
46302
+ })),
46303
+ source: "runtime"
46304
+ },
46305
+ ...command.commands.flatMap((child) => collectRuntimeCommands(child, current))
46306
+ ];
46307
+ }
46308
+ function formatRuntimeArguments(args) {
46309
+ return args.map((arg) => {
46310
+ const name = `${arg.name()}${arg.variadic ? "..." : ""}`;
46311
+ return arg.required ? `<${name}>` : `[${name}]`;
46312
+ }).join(" ");
46313
+ }
46314
+ function renderCliCatalogMarkdown(catalog) {
46315
+ const lines = [
46316
+ "# elevasis-sdk CLI Catalog",
46317
+ "",
46318
+ `Source: \`${catalog.sourceRoot}\``,
46319
+ ""
46320
+ ];
46321
+ if (catalog.domains.length === 0) {
46322
+ lines.push("No commands found.");
46323
+ return lines.join("\n");
46324
+ }
46325
+ for (const domain2 of catalog.domains) {
46326
+ lines.push(`## ${domain2.name}`, "");
46327
+ lines.push("| Command | Description | Aliases | Options | Source |");
46328
+ lines.push("| --- | --- | --- | --- | --- |");
46329
+ for (const command of domain2.commands) {
46330
+ const aliases = command.aliases.length > 0 ? command.aliases.map((alias) => `\`${alias}\``).join(", ") : "-";
46331
+ const options = command.options.length > 0 ? command.options.map((option) => `${option.required ? "required " : ""}\`${option.flags}\``).join("<br>") : "-";
46332
+ lines.push(
46333
+ `| \`elevasis-sdk ${command.syntax}\` | ${escapeMarkdownTable(command.description || "-")} | ${aliases} | ${options} | \`${command.source}\` |`
46334
+ );
46335
+ }
46336
+ lines.push("");
46337
+ }
46338
+ return lines.join("\n").trimEnd();
46339
+ }
46340
+ function renderCliCatalogJson(catalog) {
46341
+ return JSON.stringify(catalog, null, 2);
46342
+ }
46343
+ function domainFromCommand(command) {
46344
+ if (command.includes(":")) return command.split(":")[0];
46345
+ return "platform";
46346
+ }
46347
+ function firstLine(value) {
46348
+ return value.split("\n")[0]?.trim() ?? "";
46349
+ }
46350
+ function escapeMarkdownTable(value) {
46351
+ return value.replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
46352
+ }
46353
+ function knownDomains(catalog) {
46354
+ return catalog.domains.map((domain2) => domain2.name);
46355
+ }
46356
+
46357
+ // src/cli/commands/skill/skill-coverage.ts
46358
+ var import_node_fs = require("node:fs");
46359
+ var import_node_path = require("node:path");
46360
+ function loadSkillCoverage(projectRoot) {
46361
+ const coveragePath = (0, import_node_path.join)(projectRoot, ".claude", "registries", "skill-coverage.json");
46362
+ if (!(0, import_node_fs.existsSync)(coveragePath)) return null;
46363
+ const raw = (0, import_node_fs.readFileSync)(coveragePath, "utf8");
46364
+ return JSON.parse(raw);
46365
+ }
46366
+ function runCoverageGate(knownDomains2, coverage, presentSkills, coverageFilePath) {
46367
+ const violations = [];
46368
+ const domainSet = new Set(knownDomains2);
46369
+ const ownedDomains = /* @__PURE__ */ new Set();
46370
+ for (const entry of Object.values(coverage.skills)) {
46371
+ for (const domain2 of entry.domains) {
46372
+ ownedDomains.add(domain2);
46373
+ }
46374
+ }
46375
+ const waivedDomains = new Set(Object.keys(coverage.waived));
46376
+ for (const domain2 of knownDomains2) {
46377
+ if (!ownedDomains.has(domain2) && !waivedDomains.has(domain2)) {
46378
+ violations.push({
46379
+ kind: "uncovered",
46380
+ domain: domain2,
46381
+ detail: `Domain "${domain2}" exists in the CLI but is neither skill-owned nor waived in ${coverageFilePath}. Add it to "skills" or "waived".`
46382
+ });
46383
+ }
46384
+ }
46385
+ for (const [skillName, entry] of Object.entries(coverage.skills)) {
46386
+ for (const domain2 of entry.domains) {
46387
+ if (!domainSet.has(domain2)) {
46388
+ violations.push({
46389
+ kind: "stale-owned",
46390
+ domain: domain2,
46391
+ detail: `Domain "${domain2}" is declared as owned by skill "${skillName}" in ${coverageFilePath} but no longer exists in the CLI catalog. Remove or update the entry.`
46392
+ });
46393
+ }
46394
+ }
46395
+ }
46396
+ for (const domain2 of waivedDomains) {
46397
+ if (!domainSet.has(domain2)) {
46398
+ violations.push({
46399
+ kind: "stale-waived",
46400
+ domain: domain2,
46401
+ detail: `Domain "${domain2}" is declared as waived in ${coverageFilePath} but no longer exists in the CLI catalog. Remove the waiver.`
46402
+ });
46403
+ }
46404
+ }
46405
+ return {
46406
+ violations,
46407
+ domainsChecked: knownDomains2,
46408
+ coverageFile: coverageFilePath
46409
+ };
46410
+ }
46411
+
46412
+ // src/cli/commands/skill/skill-check-coverage.ts
46413
+ init_config();
46414
+ async function runSkillCoverageCheck(program3, options = {}) {
46415
+ const projectRoot = tryFindProjectRoot(process.cwd());
46416
+ if (projectRoot === null) {
46417
+ return { passed: true, violationCount: 0 };
46418
+ }
46419
+ const coveragePath = (0, import_node_path2.join)(projectRoot, ".claude", "registries", "skill-coverage.json");
46420
+ const coverage = loadSkillCoverage(projectRoot);
46421
+ if (coverage === null) {
46422
+ if (!options.silent) {
46423
+ console.log(
46424
+ source_default.yellow(" warn skill-coverage.json not found \u2014 skipping coverage gate") + source_default.gray(`
46425
+ Expected: ${coveragePath}`)
46426
+ );
46427
+ }
46428
+ return { passed: true, violationCount: 0 };
46429
+ }
46430
+ const catalog = buildCliCatalogFromProgram(program3);
46431
+ const domains = knownDomains(catalog);
46432
+ const result = runCoverageGate(domains, coverage, /* @__PURE__ */ new Set(), coveragePath);
46433
+ if (result.violations.length === 0) {
46434
+ if (!options.silent) {
46435
+ console.log(
46436
+ source_default.green(" Skill coverage OK") + source_default.gray(` (${domains.length} domains checked, all covered or waived)`)
46437
+ );
46438
+ }
46439
+ return { passed: true, violationCount: 0 };
46440
+ }
46441
+ for (const violation of result.violations) {
46442
+ const prefix = violation.kind === "uncovered" ? source_default.red(" ERROR coverage") : source_default.yellow(" WARN coverage");
46443
+ console.error(`${prefix} ${violation.detail}`);
46444
+ }
46445
+ return { passed: false, violationCount: result.violations.length };
46446
+ }
46447
+ function registerSkillCheckCoverageCommand(program3) {
46448
+ program3.command("skill:check-coverage").description(
46449
+ "Verify CLI domains are covered by skills or waived in skill-coverage.json\n Example: elevasis-sdk skill:check-coverage"
46450
+ ).action(
46451
+ wrapAction("skill:check-coverage", async () => {
46452
+ const catalog = buildCliCatalogFromProgram(program3);
46453
+ const domains = knownDomains(catalog);
46454
+ console.log(source_default.cyan(`Checking skill coverage for ${domains.length} CLI domains...`));
46455
+ const { passed, violationCount } = await runSkillCoverageCheck(program3);
46456
+ if (!passed) {
46457
+ console.error("");
46458
+ console.error(
46459
+ source_default.red(`Skill coverage check failed: ${violationCount} violation(s).`) + "\n" + source_default.gray(' Update .claude/registries/skill-coverage.json to add the domain to "skills" or "waived".')
46460
+ );
46461
+ process.exitCode = 1;
46462
+ }
46463
+ })
46464
+ );
46465
+ }
46466
+
46467
+ // src/cli/commands/check.ts
46239
46468
  function registerCheckCommand(program3) {
46240
46469
  program3.command("check").description(
46241
46470
  "Validate project resources against the ResourceRegistry\n Example: elevasis-sdk check --entry ./src/index.ts"
46242
- ).option("--entry <path>", "Path to entry file (default: ./src/index.ts)").action(
46471
+ ).option("--entry <path>", "Path to entry file (default: ./src/index.ts)").option("--skip-coverage", "Skip the skill coverage gate").action(
46243
46472
  wrapAction("check", async (options) => {
46244
46473
  const entryPath = options.entry ?? "./src/index.ts";
46245
46474
  const spinner = ora("Validating resources...").start();
@@ -46290,6 +46519,20 @@ function registerCheckCommand(program3) {
46290
46519
  }
46291
46520
  console.log(source_default.gray(" Schemas will be unavailable on the platform for these resources."));
46292
46521
  }
46522
+ if (!options.skipCoverage) {
46523
+ console.log("");
46524
+ const coverageResult = await runSkillCoverageCheck(program3);
46525
+ if (!coverageResult.passed) {
46526
+ console.error("");
46527
+ console.error(
46528
+ source_default.red(`Skill coverage check failed: ${coverageResult.violationCount} violation(s).`) + "\n" + source_default.gray(
46529
+ ' Update .claude/registries/skill-coverage.json to add the domain to "skills" or "waived".\n Run with --skip-coverage to suppress this check.'
46530
+ )
46531
+ );
46532
+ process.exitCode = 1;
46533
+ return;
46534
+ }
46535
+ }
46293
46536
  } catch (error46) {
46294
46537
  if (error46 instanceof RegistryValidationError) {
46295
46538
  spinner.fail(source_default.red("Validation failed"));
@@ -46311,8 +46554,8 @@ function registerCheckCommand(program3) {
46311
46554
  }
46312
46555
 
46313
46556
  // src/cli/commands/exec.ts
46314
- var import_node_fs = require("node:fs");
46315
- var import_node_path = require("node:path");
46557
+ var import_node_fs2 = require("node:fs");
46558
+ var import_node_path3 = require("node:path");
46316
46559
  init_source();
46317
46560
  init_config();
46318
46561
  var POLL_INTERVAL_MS = 3e3;
@@ -46385,14 +46628,14 @@ function registerExecCommand(program3) {
46385
46628
  "exec",
46386
46629
  async (resourceId, options) => {
46387
46630
  const resolvedInputFile = options.inputFile ? resolveProjectRelative(options.inputFile) : void 0;
46388
- const input = resolvedInputFile ? JSON.parse((0, import_node_fs.readFileSync)(resolvedInputFile, "utf8")) : options.input ? JSON.parse(options.input) : {};
46631
+ const input = resolvedInputFile ? JSON.parse((0, import_node_fs2.readFileSync)(resolvedInputFile, "utf8")) : options.input ? JSON.parse(options.input) : {};
46389
46632
  const apiUrl = resolveApiUrl(options.apiUrl);
46390
46633
  const maybeCleanupInput = () => {
46391
46634
  if (!options.cleanupInput || !resolvedInputFile) return;
46392
- const tmpDir = (0, import_node_path.join)(getProjectRoot(), "tmp");
46635
+ const tmpDir = (0, import_node_path3.join)(getProjectRoot(), "tmp");
46393
46636
  if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
46394
46637
  try {
46395
- (0, import_node_fs.unlinkSync)(resolvedInputFile);
46638
+ (0, import_node_fs2.unlinkSync)(resolvedInputFile);
46396
46639
  } catch {
46397
46640
  }
46398
46641
  } else {
@@ -49057,11 +49300,11 @@ function bullet(items) {
49057
49300
  function field(label, value) {
49058
49301
  return value === void 0 || value === null || value === "" ? "" : `${label}: ${value}`;
49059
49302
  }
49060
- function join3(parts) {
49303
+ function join5(parts) {
49061
49304
  return parts.filter((p) => p.length > 0).join("\n\n");
49062
49305
  }
49063
49306
  function formatSystemDescribe(r) {
49064
- const header = join3([
49307
+ const header = join5([
49065
49308
  `System: ${r.id}`,
49066
49309
  [
49067
49310
  field("Label", r.label),
@@ -49090,10 +49333,10 @@ ${resourceLines.join("\n")}`;
49090
49333
  const ontologyEntries = Object.entries(r.ontologyCountsByKind);
49091
49334
  const ontologySection = ontologyEntries.length ? `Ontology: ${ontologyEntries.map(([k, n]) => `${k}s: ${n}`).join(", ")}` : "";
49092
49335
  const childSection = section("Subsystems", bullet(r.childSystemPaths));
49093
- return join3([header, govSection, resourceSection, ontologySection, childSection]);
49336
+ return join5([header, govSection, resourceSection, ontologySection, childSection]);
49094
49337
  }
49095
49338
  function formatResourceDescribe(r) {
49096
- const header = join3([
49339
+ const header = join5([
49097
49340
  `Resource: ${r.id}`,
49098
49341
  [
49099
49342
  field("Kind", r.resourceKind),
@@ -49117,10 +49360,10 @@ function formatResourceDescribe(r) {
49117
49360
  ${ontologyLines.join("\n")}` : "";
49118
49361
  const codeRefsSection = r.codeRefPaths.length ? `Code refs:
49119
49362
  ${bullet(r.codeRefPaths)}` : "";
49120
- return join3([header, ontologySection, codeRefsSection]);
49363
+ return join5([header, ontologySection, codeRefsSection]);
49121
49364
  }
49122
49365
  function formatKnowledgeDescribe(r) {
49123
- const header = join3([
49366
+ const header = join5([
49124
49367
  `Knowledge: ${r.id}`,
49125
49368
  [field("Kind", r.knowledgeKind), field("Title", r.title), field("Updated", r.updatedAt)].filter((s) => s.length > 0).join("\n"),
49126
49369
  r.summary ? `Summary: ${r.summary}` : ""
@@ -49130,28 +49373,28 @@ ${bullet(r.ownerIds)}` : "";
49130
49373
  const govSection = section("Governs", bullet(r.governs));
49131
49374
  const bodySection = `Body excerpt (${r.bodyLineCount} lines total \u2014 use knowledge:cat for full):
49132
49375
  ${r.bodyExcerpt}`;
49133
- return join3([header, ownerSection, govSection, bodySection]);
49376
+ return join5([header, ownerSection, govSection, bodySection]);
49134
49377
  }
49135
49378
  function formatOntologyDescribe(r) {
49136
- const header = join3([
49379
+ const header = join5([
49137
49380
  `Ontology: ${r.id}`,
49138
49381
  [field("Kind", r.ontologyKind), field("Scope", r.scope), field("Local id", r.localId), field("Label", r.label)].filter((s) => s.length > 0).join("\n"),
49139
49382
  r.description ? `Description: ${r.description}` : ""
49140
49383
  ]);
49141
49384
  const govSection = section("Governed by knowledge", bullet(r.governingKnowledgeIds));
49142
- return join3([header, govSection]);
49385
+ return join5([header, govSection]);
49143
49386
  }
49144
49387
  function formatRoleDescribe(r) {
49145
- const header = join3([
49388
+ const header = join5([
49146
49389
  `Role: ${r.id}`,
49147
49390
  [field("Title", r.title), field("Reports to", r.reportsToId)].filter((s) => s.length > 0).join("\n")
49148
49391
  ]);
49149
49392
  const respSection = section("Responsibilities", bullet(r.responsibilities));
49150
49393
  const responsibleForSection = section("Responsible for systems", bullet(r.responsibleFor));
49151
- return join3([header, respSection, responsibleForSection]);
49394
+ return join5([header, respSection, responsibleForSection]);
49152
49395
  }
49153
49396
  function formatPolicyDescribe(r) {
49154
- const header = join3([
49397
+ const header = join5([
49155
49398
  `Policy: ${r.id}`,
49156
49399
  [field("Label", r.label), field("Trigger", r.triggerKind)].filter((s) => s.length > 0).join("\n"),
49157
49400
  r.description ? `Description: ${r.description}` : ""
@@ -49164,7 +49407,156 @@ function formatPolicyDescribe(r) {
49164
49407
  if (r.appliesToRoleIds.length) appliesLines.push(` roles: ${r.appliesToRoleIds.join(", ")}`);
49165
49408
  const appliesSection = appliesLines.length ? `Applies to:
49166
49409
  ${appliesLines.join("\n")}` : "";
49167
- return join3([header, effectSection, appliesSection]);
49410
+ return join5([header, effectSection, appliesSection]);
49411
+ }
49412
+
49413
+ // ../core/src/knowledge/cli-helpers.ts
49414
+ var OM_SEARCH_HIT_KINDS = ["system", "resource", "knowledge", "ontology", "role", "policy"];
49415
+ function parseKnowledgeSearchLimit(raw, commandName = "knowledge:search") {
49416
+ if (raw === void 0) return 10;
49417
+ const n = Number.parseInt(raw, 10);
49418
+ if (Number.isNaN(n) || n < 0) {
49419
+ throw new Error(`${commandName}: --limit must be a non-negative integer (got "${raw}")`);
49420
+ }
49421
+ return n;
49422
+ }
49423
+ function parseKnowledgeSearchKinds(raw, commandName = "knowledge:search") {
49424
+ if (raw === void 0) return void 0;
49425
+ const requested = raw.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
49426
+ const valid = [];
49427
+ const invalid = [];
49428
+ for (const kind of requested) {
49429
+ if (OM_SEARCH_HIT_KINDS.includes(kind)) {
49430
+ valid.push(kind);
49431
+ } else {
49432
+ invalid.push(kind);
49433
+ }
49434
+ }
49435
+ if (invalid.length > 0) {
49436
+ throw new Error(`${commandName}: unknown kind(s) "${invalid.join(", ")}". Valid: ${OM_SEARCH_HIT_KINDS.join(", ")}`);
49437
+ }
49438
+ return valid.length > 0 ? valid : void 0;
49439
+ }
49440
+ function formatKnowledgeSystemsList(entries) {
49441
+ if (entries.length === 0) return "(no results)";
49442
+ const pathWidth = Math.max(...entries.map((e) => e.path.length), 4);
49443
+ const header = `${"PATH".padEnd(pathWidth)} LABEL`;
49444
+ const divider = "-".repeat(header.length + 20);
49445
+ const rows = entries.map((e) => {
49446
+ const label = e.system.label ?? e.system.title ?? e.path;
49447
+ return `${e.path.padEnd(pathWidth)} ${label}`;
49448
+ });
49449
+ return [header, divider, ...rows].join("\n");
49450
+ }
49451
+ function formatKnowledgeResourcesList(resources) {
49452
+ if (resources.length === 0) return "(no results)";
49453
+ const idWidth = Math.max(...resources.map((r) => r.id.length), 4);
49454
+ const kindWidth = Math.max(...resources.map((r) => r.kind.length), 4);
49455
+ const header = `${"ID".padEnd(idWidth)} ${"KIND".padEnd(kindWidth)} TITLE`;
49456
+ const divider = "-".repeat(header.length + 20);
49457
+ const rows = resources.map((r) => {
49458
+ const title = r.title ?? r.id;
49459
+ return `${r.id.padEnd(idWidth)} ${r.kind.padEnd(kindWidth)} ${title}`;
49460
+ });
49461
+ return [header, divider, ...rows].join("\n");
49462
+ }
49463
+ function formatKnowledgeRolesList(roles) {
49464
+ if (roles.length === 0) return "(no results)";
49465
+ const idWidth = Math.max(...roles.map((r) => r.id.length), 4);
49466
+ const header = `${"ID".padEnd(idWidth)} TITLE`;
49467
+ const divider = "-".repeat(header.length + 20);
49468
+ const rows = roles.map((r) => `${r.id.padEnd(idWidth)} ${r.title}`);
49469
+ return [header, divider, ...rows].join("\n");
49470
+ }
49471
+ function normalizeKnowledgeNodeId(id) {
49472
+ return id.startsWith("knowledge:") ? id.slice("knowledge:".length) : id;
49473
+ }
49474
+ function formatKnowledgeInvocationLabel(invocation) {
49475
+ switch (invocation.kind) {
49476
+ case "slash-command":
49477
+ return invocation.command;
49478
+ case "mcp-tool":
49479
+ return `${invocation.server}/${invocation.name}`;
49480
+ case "api-endpoint":
49481
+ return `${invocation.method} ${invocation.path}`;
49482
+ case "script-execution":
49483
+ return invocation.resourceId;
49484
+ }
49485
+ }
49486
+ function pushActionSource(sources, seen, action) {
49487
+ if (!action || action.invocations.length === 0) return;
49488
+ const key = `action:${action.id}`;
49489
+ if (seen.has(key)) return;
49490
+ seen.add(key);
49491
+ sources.push({
49492
+ kind: "action",
49493
+ id: action.id,
49494
+ label: action.label,
49495
+ targetNodeId: `action:${action.id}`,
49496
+ invocations: action.invocations
49497
+ });
49498
+ }
49499
+ function pushAgentResourceSource(sources, seen, resource) {
49500
+ if (!resource || resource.kind !== "agent" || resource.invocations.length === 0) return;
49501
+ const agentResource = resource;
49502
+ const key = `agent-resource:${agentResource.id}`;
49503
+ if (seen.has(key)) return;
49504
+ seen.add(key);
49505
+ sources.push({
49506
+ kind: "agent-resource",
49507
+ id: agentResource.id,
49508
+ label: agentResource.id,
49509
+ targetNodeId: `resource:${agentResource.id}`,
49510
+ invocations: agentResource.invocations
49511
+ });
49512
+ }
49513
+ function resolveKnowledgeInvocationNeighbors(model, id) {
49514
+ const normalizedNodeId = normalizeKnowledgeNodeId(id);
49515
+ const node = model.knowledge[normalizedNodeId];
49516
+ if (!node) return void 0;
49517
+ const sources = [];
49518
+ const seen = /* @__PURE__ */ new Set();
49519
+ for (const link of node.links) {
49520
+ const target = link.target;
49521
+ if (target.kind === "action") {
49522
+ pushActionSource(sources, seen, model.actions[target.id]);
49523
+ continue;
49524
+ }
49525
+ if (target.kind === "resource") {
49526
+ pushAgentResourceSource(sources, seen, model.resources[target.id]);
49527
+ continue;
49528
+ }
49529
+ if (target.kind === "system") {
49530
+ const system = getSystem(model, target.id);
49531
+ for (const actionRef of system?.actions ?? []) {
49532
+ pushActionSource(sources, seen, model.actions[actionRef.actionId]);
49533
+ }
49534
+ for (const resource of Object.values(model.resources)) {
49535
+ if (resource.systemPath === target.id) {
49536
+ pushAgentResourceSource(sources, seen, resource);
49537
+ }
49538
+ }
49539
+ }
49540
+ }
49541
+ return {
49542
+ id: node.id,
49543
+ title: node.title,
49544
+ invocationSources: sources.sort((a, b) => a.targetNodeId.localeCompare(b.targetNodeId))
49545
+ };
49546
+ }
49547
+ function formatKnowledgeInvocationNeighbors(result) {
49548
+ const lines = [`Invocation-bearing graph neighbors for ${result.id}`, ""];
49549
+ if (result.invocationSources.length === 0) {
49550
+ lines.push(" (none)");
49551
+ } else {
49552
+ for (const source of result.invocationSources) {
49553
+ lines.push(`${source.kind}: ${source.id}`);
49554
+ for (const invocation of source.invocations) {
49555
+ lines.push(` ${invocation.kind}: ${formatKnowledgeInvocationLabel(invocation)}`);
49556
+ }
49557
+ }
49558
+ }
49559
+ return lines.join("\n");
49168
49560
  }
49169
49561
 
49170
49562
  // src/cli/commands/knowledge/ls.ts
@@ -49225,34 +49617,6 @@ async function loadOrgModel(projectRoot) {
49225
49617
  }
49226
49618
 
49227
49619
  // src/cli/commands/knowledge/ls.ts
49228
- function formatAllSystems(entries) {
49229
- if (entries.length === 0) return "(no results)";
49230
- const pathWidth = Math.max(...entries.map((e) => e.path.length), 4);
49231
- const header = `${"PATH".padEnd(pathWidth)} LABEL`;
49232
- const divider = "-".repeat(header.length + 20);
49233
- const rows = entries.map((e) => {
49234
- const label = e.system.label ?? e.system.title ?? e.path;
49235
- return `${e.path.padEnd(pathWidth)} ${label}`;
49236
- });
49237
- return [header, divider, ...rows].join("\n");
49238
- }
49239
- function formatAllResources(resources) {
49240
- if (resources.length === 0) return "(no results)";
49241
- const idWidth = Math.max(...resources.map((r) => r.id.length), 4);
49242
- const kindWidth = Math.max(...resources.map((r) => r.kind.length), 4);
49243
- const header = `${"ID".padEnd(idWidth)} ${"KIND".padEnd(kindWidth)} TITLE`;
49244
- const divider = "-".repeat(header.length + 20);
49245
- const rows = resources.map((r) => `${r.id.padEnd(idWidth)} ${r.kind.padEnd(kindWidth)} ${r.title}`);
49246
- return [header, divider, ...rows].join("\n");
49247
- }
49248
- function formatAllRoles(roles) {
49249
- if (roles.length === 0) return "(no results)";
49250
- const idWidth = Math.max(...roles.map((r) => r.id.length), 4);
49251
- const header = `${"ID".padEnd(idWidth)} TITLE`;
49252
- const divider = "-".repeat(header.length + 20);
49253
- const rows = roles.map((r) => `${r.id.padEnd(idWidth)} ${r.title}`);
49254
- return [header, divider, ...rows].join("\n");
49255
- }
49256
49620
  function registerKnowledgeLs(program3) {
49257
49621
  program3.command("knowledge:ls <path>").alias("om:ls").description(
49258
49622
  "List knowledge nodes for a Knowledge Map path\n Examples:\n elevasis-sdk om:ls /by-kind/playbook\n elevasis-sdk om:ls /by-system/sales.crm\n elevasis-sdk om:ls /by-ontology/sales.crm:object/deal\n elevasis-sdk om:ls /by-owner/role.ops-lead\n elevasis-sdk om:ls /graph/knowledge.outreach-playbook/governs\n elevasis-sdk om:ls /graph/system:sales.crm/governed-by\n elevasis-sdk om:ls /all-systems\n elevasis-sdk om:ls /all-resources\n elevasis-sdk om:ls /all-roles"
@@ -49276,7 +49640,7 @@ function registerKnowledgeLs(program3) {
49276
49640
  const out = entries.map((e) => e.path).join("\n");
49277
49641
  if (out) process.stdout.write(out + "\n");
49278
49642
  } else {
49279
- process.stdout.write(formatAllSystems(entries) + "\n");
49643
+ process.stdout.write(formatKnowledgeSystemsList(entries) + "\n");
49280
49644
  }
49281
49645
  return;
49282
49646
  }
@@ -49288,7 +49652,7 @@ function registerKnowledgeLs(program3) {
49288
49652
  const out = resources.map((r) => r.id).join("\n");
49289
49653
  if (out) process.stdout.write(out + "\n");
49290
49654
  } else {
49291
- process.stdout.write(formatAllResources(resources) + "\n");
49655
+ process.stdout.write(formatKnowledgeResourcesList(resources) + "\n");
49292
49656
  }
49293
49657
  return;
49294
49658
  }
@@ -49300,7 +49664,7 @@ function registerKnowledgeLs(program3) {
49300
49664
  const out = roles.map((r) => r.id).join("\n");
49301
49665
  if (out) process.stdout.write(out + "\n");
49302
49666
  } else {
49303
- process.stdout.write(formatAllRoles(roles) + "\n");
49667
+ process.stdout.write(formatKnowledgeRolesList(roles) + "\n");
49304
49668
  }
49305
49669
  return;
49306
49670
  }
@@ -49454,82 +49818,6 @@ function registerKnowledgeGraph(program3) {
49454
49818
 
49455
49819
  // src/cli/commands/knowledge/skills.ts
49456
49820
  init_config();
49457
- function normalizeKnowledgeId(id) {
49458
- return id.startsWith("knowledge:") ? id.slice("knowledge:".length) : id;
49459
- }
49460
- function invocationLabel2(invocation) {
49461
- switch (invocation.kind) {
49462
- case "slash-command":
49463
- return invocation.command;
49464
- case "mcp-tool":
49465
- return `${invocation.server}/${invocation.name}`;
49466
- case "api-endpoint":
49467
- return `${invocation.method} ${invocation.path}`;
49468
- case "script-execution":
49469
- return invocation.resourceId;
49470
- }
49471
- }
49472
- function pushActionSource(sources, seen, action) {
49473
- if (!action || action.invocations.length === 0) return;
49474
- const key = `action:${action.id}`;
49475
- if (seen.has(key)) return;
49476
- seen.add(key);
49477
- sources.push({
49478
- kind: "action",
49479
- id: action.id,
49480
- label: action.label,
49481
- targetNodeId: `action:${action.id}`,
49482
- invocations: action.invocations
49483
- });
49484
- }
49485
- function pushAgentResourceSource(sources, seen, resource) {
49486
- if (!resource || resource.kind !== "agent" || resource.invocations.length === 0) return;
49487
- const agentResource = resource;
49488
- const key = `agent-resource:${agentResource.id}`;
49489
- if (seen.has(key)) return;
49490
- seen.add(key);
49491
- sources.push({
49492
- kind: "agent-resource",
49493
- id: agentResource.id,
49494
- label: agentResource.id,
49495
- targetNodeId: `resource:${agentResource.id}`,
49496
- invocations: agentResource.invocations
49497
- });
49498
- }
49499
- function resolveKnowledgeInvocationNeighbors(model, id) {
49500
- const normalizedNodeId = normalizeKnowledgeId(id);
49501
- const node = model.knowledge[normalizedNodeId];
49502
- if (!node) return void 0;
49503
- const sources = [];
49504
- const seen = /* @__PURE__ */ new Set();
49505
- for (const link of node.links) {
49506
- const target = link.target;
49507
- if (target.kind === "action") {
49508
- pushActionSource(sources, seen, model.actions[target.id]);
49509
- continue;
49510
- }
49511
- if (target.kind === "resource") {
49512
- pushAgentResourceSource(sources, seen, model.resources[target.id]);
49513
- continue;
49514
- }
49515
- if (target.kind === "system") {
49516
- const system = getSystem(model, target.id);
49517
- for (const actionRef of system?.actions ?? []) {
49518
- pushActionSource(sources, seen, model.actions[actionRef.actionId]);
49519
- }
49520
- for (const resource of Object.values(model.resources)) {
49521
- if (resource.systemPath === target.id) {
49522
- pushAgentResourceSource(sources, seen, resource);
49523
- }
49524
- }
49525
- }
49526
- }
49527
- return {
49528
- id: node.id,
49529
- title: node.title,
49530
- invocationSources: sources.sort((a, b) => a.targetNodeId.localeCompare(b.targetNodeId))
49531
- };
49532
- }
49533
49821
  function registerKnowledgeSkills(program3) {
49534
49822
  program3.command("knowledge:skills <id>").alias("om:skills").description(
49535
49823
  "Show callable invocations on graph neighbors for a knowledge node\n Example: elevasis-sdk om:skills knowledge.new-vertical-launch-playbook"
@@ -49547,29 +49835,18 @@ function registerKnowledgeSkills(program3) {
49547
49835
  process.stdout.write(JSON.stringify(result, null, 2) + "\n");
49548
49836
  return;
49549
49837
  }
49550
- const lines = [`Invocation-bearing graph neighbors for ${result.id}`, ""];
49551
- if (result.invocationSources.length === 0) {
49552
- lines.push(" (none)");
49553
- } else {
49554
- for (const source of result.invocationSources) {
49555
- lines.push(`${source.kind}: ${source.id}`);
49556
- for (const invocation of source.invocations) {
49557
- lines.push(` ${invocation.kind}: ${invocationLabel2(invocation)}`);
49558
- }
49559
- }
49560
- }
49561
- process.stdout.write(lines.join("\n") + "\n");
49838
+ process.stdout.write(formatKnowledgeInvocationNeighbors(result) + "\n");
49562
49839
  })
49563
49840
  );
49564
49841
  }
49565
49842
 
49566
49843
  // src/cli/commands/knowledge/generate.ts
49567
- var import_node_fs3 = require("node:fs");
49568
- var import_node_path3 = require("node:path");
49844
+ var import_node_fs4 = require("node:fs");
49845
+ var import_node_path5 = require("node:path");
49569
49846
 
49570
49847
  // src/knowledge-codegen.ts
49571
- var import_node_fs2 = require("node:fs");
49572
- var import_node_path2 = require("node:path");
49848
+ var import_node_fs3 = require("node:fs");
49849
+ var import_node_path4 = require("node:path");
49573
49850
  function targetFromNodeId2(nodeId2) {
49574
49851
  const [kind, ...idParts] = nodeId2.split(":");
49575
49852
  return {
@@ -49587,10 +49864,10 @@ function canonicalizeKnowledgeNodeLinks(node) {
49587
49864
  };
49588
49865
  }
49589
49866
  function listMdxFiles(directory) {
49590
- return (0, import_node_fs2.readdirSync)(directory, { withFileTypes: true }).flatMap((entry) => {
49591
- const path3 = (0, import_node_path2.join)(directory, entry.name);
49867
+ return (0, import_node_fs3.readdirSync)(directory, { withFileTypes: true }).flatMap((entry) => {
49868
+ const path3 = (0, import_node_path4.join)(directory, entry.name);
49592
49869
  if (entry.isDirectory()) return listMdxFiles(path3);
49593
- return entry.isFile() && (0, import_node_path2.extname)(entry.name) === ".mdx" ? [path3] : [];
49870
+ return entry.isFile() && (0, import_node_path4.extname)(entry.name) === ".mdx" ? [path3] : [];
49594
49871
  });
49595
49872
  }
49596
49873
  function parseScalar(value) {
@@ -49785,7 +50062,7 @@ function readCommandForNode(node, cliCommand = "elevasis") {
49785
50062
  ];
49786
50063
  }
49787
50064
  function readKnowledgeNodeMdx(filePath) {
49788
- const raw = (0, import_node_fs2.readFileSync)(filePath, "utf8");
50065
+ const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8");
49789
50066
  const { frontmatter, body } = parseFrontmatter(raw, filePath);
49790
50067
  return {
49791
50068
  id: assertString(frontmatter, "id", filePath),
@@ -49883,25 +50160,25 @@ function generateKnowledgeNodesTs(options) {
49883
50160
  }
49884
50161
  function generateKnowledgeNodes(options) {
49885
50162
  const files = listMdxFiles(options.sourceDir).sort(
49886
- (a, b) => (0, import_node_path2.relative)(options.sourceDir, a).localeCompare((0, import_node_path2.relative)(options.sourceDir, b))
50163
+ (a, b) => (0, import_node_path4.relative)(options.sourceDir, a).localeCompare((0, import_node_path4.relative)(options.sourceDir, b))
49887
50164
  );
49888
50165
  const nodes = files.map((file2) => {
49889
- const relativePath = (0, import_node_path2.relative)(options.sourceDir, file2);
50166
+ const relativePath = (0, import_node_path4.relative)(options.sourceDir, file2);
49890
50167
  return {
49891
50168
  ...readKnowledgeNodeMdx(file2),
49892
50169
  sourceFilePath: toSourceFilePath(options.sourceLabel, relativePath)
49893
50170
  };
49894
50171
  });
49895
50172
  const sourcePaths = Object.fromEntries(
49896
- files.map((file2, index) => [nodes[index].id, toRegistryPath((0, import_node_path2.relative)(options.sourceDir, file2))])
50173
+ files.map((file2, index) => [nodes[index].id, toRegistryPath((0, import_node_path4.relative)(options.sourceDir, file2))])
49897
50174
  );
49898
50175
  const ids = /* @__PURE__ */ new Set();
49899
50176
  for (const node of nodes) {
49900
50177
  if (ids.has(node.id)) throw new Error(`[knowledge-node-codegen] Duplicate knowledge node id: ${node.id}`);
49901
50178
  ids.add(node.id);
49902
50179
  }
49903
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(options.outputPath), { recursive: true });
49904
- (0, import_node_fs2.writeFileSync)(
50180
+ (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(options.outputPath), { recursive: true });
50181
+ (0, import_node_fs3.writeFileSync)(
49905
50182
  options.outputPath,
49906
50183
  generateKnowledgeNodesTs({
49907
50184
  nodes,
@@ -49912,8 +50189,8 @@ function generateKnowledgeNodes(options) {
49912
50189
  "utf8"
49913
50190
  );
49914
50191
  if (options.knowledgeFlagsOutputPath) {
49915
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(options.knowledgeFlagsOutputPath), { recursive: true });
49916
- (0, import_node_fs2.writeFileSync)(
50192
+ (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(options.knowledgeFlagsOutputPath), { recursive: true });
50193
+ (0, import_node_fs3.writeFileSync)(
49917
50194
  options.knowledgeFlagsOutputPath,
49918
50195
  `${JSON.stringify(
49919
50196
  generateKnowledgeFlagRegistry(nodes, sourcePaths, {
@@ -49945,13 +50222,13 @@ function registerKnowledgeGenerate(program3) {
49945
50222
  ).action(
49946
50223
  wrapAction("knowledge:generate", async (options) => {
49947
50224
  const projectRoot = getProjectRoot();
49948
- const sourceDir = (0, import_node_path3.resolve)(projectRoot, options.source ?? "core/config/knowledge/nodes");
49949
- const outputPath = (0, import_node_path3.resolve)(projectRoot, options.output ?? "core/config/knowledge/_generated/nodes.ts");
49950
- const knowledgeFlagsOutputPath = (0, import_node_path3.resolve)(
50225
+ const sourceDir = (0, import_node_path5.resolve)(projectRoot, options.source ?? "core/config/knowledge/nodes");
50226
+ const outputPath = (0, import_node_path5.resolve)(projectRoot, options.output ?? "core/config/knowledge/_generated/nodes.ts");
50227
+ const knowledgeFlagsOutputPath = (0, import_node_path5.resolve)(
49951
50228
  projectRoot,
49952
50229
  options.flagsOutput ?? ".claude/registries/knowledge-flags.json"
49953
50230
  );
49954
- if (!(0, import_node_fs3.existsSync)(sourceDir)) {
50231
+ if (!(0, import_node_fs4.existsSync)(sourceDir)) {
49955
50232
  process.stderr.write(`knowledge:generate: source directory not found: ${sourceDir}
49956
50233
  `);
49957
50234
  process.exitCode = 1;
@@ -49974,39 +50251,13 @@ function registerKnowledgeGenerate(program3) {
49974
50251
 
49975
50252
  // src/cli/commands/knowledge/search.ts
49976
50253
  init_config();
49977
- var ALL_KINDS = ["system", "resource", "knowledge", "ontology", "role", "policy"];
49978
- function parseLimit(raw) {
49979
- if (raw === void 0) return 10;
49980
- const n = Number.parseInt(raw, 10);
49981
- if (Number.isNaN(n) || n < 0) {
49982
- throw new Error(`knowledge:search: --limit must be a non-negative integer (got "${raw}")`);
49983
- }
49984
- return n;
49985
- }
49986
- function parseKinds(raw) {
49987
- if (raw === void 0) return void 0;
49988
- const requested = raw.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
49989
- const valid = [];
49990
- const invalid = [];
49991
- for (const kind of requested) {
49992
- if (ALL_KINDS.includes(kind)) {
49993
- valid.push(kind);
49994
- } else {
49995
- invalid.push(kind);
49996
- }
49997
- }
49998
- if (invalid.length > 0) {
49999
- throw new Error(`knowledge:search: unknown kind(s) "${invalid.join(", ")}". Valid: ${ALL_KINDS.join(", ")}`);
50000
- }
50001
- return valid.length > 0 ? valid : void 0;
50002
- }
50003
50254
  function registerKnowledgeSearch(program3) {
50004
50255
  program3.command("knowledge:search <query>").alias("om:search").description(
50005
50256
  'Universal keyword search across the entire Organization Model\n (systems, resources, knowledge, ontology, roles, policies)\n Example: elevasis-sdk om:search "lead gen"\n Example: elevasis-sdk om:search outreach --kinds knowledge\n Example: elevasis-sdk om:search apollo --ids-only'
50006
50257
  ).option("--limit <n>", "max number of hits to return (0 = unlimited)", "10").option("--kinds <list>", "comma-separated kinds filter (system,resource,knowledge,ontology,role,policy)").option("--json", "Print wrapped JSON envelope").option("--ids-only", "Print one ID per line (for piping)").action(
50007
50258
  wrapAction("knowledge:search", async (query, options) => {
50008
- const limit = parseLimit(options.limit);
50009
- const kinds = parseKinds(options.kinds);
50259
+ const limit = parseKnowledgeSearchLimit(options.limit);
50260
+ const kinds = parseKnowledgeSearchKinds(options.kinds);
50010
50261
  const projectRoot = getProjectRoot();
50011
50262
  const model = await loadOrgModel(projectRoot);
50012
50263
  const hits = omSearch(model, query, { limit, kinds });
@@ -50063,8 +50314,8 @@ function registerKnowledgeCommands(program3) {
50063
50314
  }
50064
50315
 
50065
50316
  // src/cli/commands/request/request.ts
50066
- var import_node_fs4 = require("node:fs");
50067
- var import_node_path4 = require("node:path");
50317
+ var import_node_fs5 = require("node:fs");
50318
+ var import_node_path6 = require("node:path");
50068
50319
  init_source();
50069
50320
  init_config();
50070
50321
 
@@ -50128,7 +50379,7 @@ function registerRequestCommands(program3) {
50128
50379
  throw new Error("Provide --input <json> or --input-file <path>");
50129
50380
  }
50130
50381
  const resolvedInputFile = options.inputFile ? resolveProjectRelative(options.inputFile) : void 0;
50131
- const raw = resolvedInputFile ? JSON.parse((0, import_node_fs4.readFileSync)(resolvedInputFile, "utf8")) : JSON.parse(options.input);
50382
+ const raw = resolvedInputFile ? JSON.parse((0, import_node_fs5.readFileSync)(resolvedInputFile, "utf8")) : JSON.parse(options.input);
50132
50383
  const parsed = CreateRequestInputSchema.safeParse(raw);
50133
50384
  if (!parsed.success) {
50134
50385
  const issues = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
@@ -50149,10 +50400,10 @@ ${issues}`);
50149
50400
  console.log(JSON.stringify(result, null, 2));
50150
50401
  }
50151
50402
  if (options.cleanupInput && resolvedInputFile) {
50152
- const tmpDir = (0, import_node_path4.join)(getProjectRoot(), "tmp");
50403
+ const tmpDir = (0, import_node_path6.join)(getProjectRoot(), "tmp");
50153
50404
  if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
50154
50405
  try {
50155
- (0, import_node_fs4.unlinkSync)(resolvedInputFile);
50406
+ (0, import_node_fs5.unlinkSync)(resolvedInputFile);
50156
50407
  } catch {
50157
50408
  }
50158
50409
  } else {
@@ -50221,8 +50472,8 @@ ${rows.length} request${rows.length === 1 ? "" : "s"}`));
50221
50472
 
50222
50473
  // src/cli/commands/ui/ui-switcher.ts
50223
50474
  var import_node_child_process = require("node:child_process");
50224
- var import_node_fs5 = __toESM(require("node:fs"), 1);
50225
- var import_node_path5 = __toESM(require("node:path"), 1);
50475
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
50476
+ var import_node_path7 = __toESM(require("node:path"), 1);
50226
50477
  init_config();
50227
50478
  function run(command, args, cwd) {
50228
50479
  (0, import_node_child_process.execFileSync)(command, args, {
@@ -50232,10 +50483,10 @@ function run(command, args, cwd) {
50232
50483
  });
50233
50484
  }
50234
50485
  function readJson(filePath) {
50235
- return JSON.parse(import_node_fs5.default.readFileSync(filePath, "utf8"));
50486
+ return JSON.parse(import_node_fs6.default.readFileSync(filePath, "utf8"));
50236
50487
  }
50237
50488
  function writeJson(filePath, value) {
50238
- import_node_fs5.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
50489
+ import_node_fs6.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
50239
50490
  `);
50240
50491
  }
50241
50492
  function requireDependencies(packageJson, filePath) {
@@ -50245,8 +50496,8 @@ function requireDependencies(packageJson, filePath) {
50245
50496
  return packageJson.dependencies;
50246
50497
  }
50247
50498
  function resolveExistingDir(label, dir) {
50248
- const resolved = import_node_path5.default.resolve(dir);
50249
- if (!import_node_fs5.default.existsSync(resolved) || !import_node_fs5.default.statSync(resolved).isDirectory()) {
50499
+ const resolved = import_node_path7.default.resolve(dir);
50500
+ if (!import_node_fs6.default.existsSync(resolved) || !import_node_fs6.default.statSync(resolved).isDirectory()) {
50250
50501
  throw new Error(`${label} not found: ${resolved}`);
50251
50502
  }
50252
50503
  return resolved;
@@ -50254,8 +50505,8 @@ function resolveExistingDir(label, dir) {
50254
50505
  function findRepoRootFromProject(projectRoot) {
50255
50506
  let dir = projectRoot;
50256
50507
  while (true) {
50257
- if (import_node_fs5.default.existsSync(import_node_path5.default.join(dir, "packages", "ui", "package.json"))) return dir;
50258
- const parent = import_node_path5.default.dirname(dir);
50508
+ if (import_node_fs6.default.existsSync(import_node_path7.default.join(dir, "packages", "ui", "package.json"))) return dir;
50509
+ const parent = import_node_path7.default.dirname(dir);
50259
50510
  if (parent === dir) return null;
50260
50511
  dir = parent;
50261
50512
  }
@@ -50268,13 +50519,13 @@ function resolveUiPackageRoot(projectRoot, explicitRoot) {
50268
50519
  "Could not find packages/ui from this Elevasis project. Pass --ui-package-root <path> from a monorepo checkout."
50269
50520
  );
50270
50521
  }
50271
- return import_node_path5.default.join(repoRoot, "packages", "ui");
50522
+ return import_node_path7.default.join(repoRoot, "packages", "ui");
50272
50523
  }
50273
50524
  function removeLocalUiTarballs(templateTmpDir) {
50274
- if (!import_node_fs5.default.existsSync(templateTmpDir)) return;
50275
- for (const entry of import_node_fs5.default.readdirSync(templateTmpDir)) {
50525
+ if (!import_node_fs6.default.existsSync(templateTmpDir)) return;
50526
+ for (const entry of import_node_fs6.default.readdirSync(templateTmpDir)) {
50276
50527
  if (entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz")) {
50277
- import_node_fs5.default.rmSync(import_node_path5.default.join(templateTmpDir, entry), { force: true });
50528
+ import_node_fs6.default.rmSync(import_node_path7.default.join(templateTmpDir, entry), { force: true });
50278
50529
  }
50279
50530
  }
50280
50531
  }
@@ -50294,29 +50545,29 @@ function useLocalUi(options = {}) {
50294
50545
  const projectRoot = getProjectRoot();
50295
50546
  const repoRoot = findRepoRootFromProject(projectRoot);
50296
50547
  const uiPackageRoot = resolveUiPackageRoot(projectRoot, options.uiPackageRoot);
50297
- const commandRoot = repoRoot ?? import_node_path5.default.dirname(import_node_path5.default.dirname(uiPackageRoot));
50298
- const templateUiPackageJsonPath = import_node_path5.default.join(projectRoot, "ui", "package.json");
50299
- const templateTmpDir = import_node_path5.default.join(projectRoot, "tmp");
50300
- const uiPackageJsonPath = import_node_path5.default.join(uiPackageRoot, "package.json");
50301
- const uiPackageBackupPath = import_node_path5.default.join(uiPackageRoot, "package.json.local-pack.bak");
50302
- if (!import_node_fs5.default.existsSync(templateUiPackageJsonPath)) {
50548
+ const commandRoot = repoRoot ?? import_node_path7.default.dirname(import_node_path7.default.dirname(uiPackageRoot));
50549
+ const templateUiPackageJsonPath = import_node_path7.default.join(projectRoot, "ui", "package.json");
50550
+ const templateTmpDir = import_node_path7.default.join(projectRoot, "tmp");
50551
+ const uiPackageJsonPath = import_node_path7.default.join(uiPackageRoot, "package.json");
50552
+ const uiPackageBackupPath = import_node_path7.default.join(uiPackageRoot, "package.json.local-pack.bak");
50553
+ if (!import_node_fs6.default.existsSync(templateUiPackageJsonPath)) {
50303
50554
  throw new Error(`Template UI package.json not found: ${templateUiPackageJsonPath}`);
50304
50555
  }
50305
- import_node_fs5.default.mkdirSync(templateTmpDir, { recursive: true });
50556
+ import_node_fs6.default.mkdirSync(templateTmpDir, { recursive: true });
50306
50557
  removeLocalUiTarballs(templateTmpDir);
50307
50558
  run("pnpm", ["--filter", "@repo/ui", "build:publish"], commandRoot);
50308
50559
  try {
50309
- const raw = import_node_fs5.default.readFileSync(uiPackageJsonPath, "utf8");
50310
- import_node_fs5.default.writeFileSync(uiPackageBackupPath, raw);
50560
+ const raw = import_node_fs6.default.readFileSync(uiPackageJsonPath, "utf8");
50561
+ import_node_fs6.default.writeFileSync(uiPackageBackupPath, raw);
50311
50562
  writeJson(uiPackageJsonPath, prepareUiPackageForPack(JSON.parse(raw)));
50312
50563
  run("pnpm", ["-C", uiPackageRoot, "pack", "--pack-destination", templateTmpDir], commandRoot);
50313
50564
  } finally {
50314
- if (import_node_fs5.default.existsSync(uiPackageBackupPath)) {
50315
- import_node_fs5.default.copyFileSync(uiPackageBackupPath, uiPackageJsonPath);
50316
- import_node_fs5.default.rmSync(uiPackageBackupPath, { force: true });
50565
+ if (import_node_fs6.default.existsSync(uiPackageBackupPath)) {
50566
+ import_node_fs6.default.copyFileSync(uiPackageBackupPath, uiPackageJsonPath);
50567
+ import_node_fs6.default.rmSync(uiPackageBackupPath, { force: true });
50317
50568
  }
50318
50569
  }
50319
- const tarballName = import_node_fs5.default.readdirSync(templateTmpDir).find((entry) => entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz"));
50570
+ const tarballName = import_node_fs6.default.readdirSync(templateTmpDir).find((entry) => entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz"));
50320
50571
  if (!tarballName) {
50321
50572
  throw new Error(`Failed to create local @elevasis/ui tarball in ${templateTmpDir}`);
50322
50573
  }
@@ -50324,20 +50575,20 @@ function useLocalUi(options = {}) {
50324
50575
  requireDependencies(templateUiPackageJson, templateUiPackageJsonPath)["@elevasis/ui"] = `file:../tmp/${tarballName}`;
50325
50576
  writeJson(templateUiPackageJsonPath, templateUiPackageJson);
50326
50577
  run("pnpm", ["-C", projectRoot, "install"], commandRoot);
50327
- console.log(`${import_node_path5.default.basename(projectRoot)}/ui now uses local @elevasis/ui tarball: ${tarballName}`);
50578
+ console.log(`${import_node_path7.default.basename(projectRoot)}/ui now uses local @elevasis/ui tarball: ${tarballName}`);
50328
50579
  }
50329
50580
  function usePublishedUi(options = {}) {
50330
50581
  const projectRoot = getProjectRoot();
50331
50582
  const repoRoot = findRepoRootFromProject(projectRoot);
50332
50583
  const commandRoot = repoRoot ?? projectRoot;
50333
- const templateUiPackageJsonPath = import_node_path5.default.join(projectRoot, "ui", "package.json");
50334
- const templateTmpDir = import_node_path5.default.join(projectRoot, "tmp");
50584
+ const templateUiPackageJsonPath = import_node_path7.default.join(projectRoot, "ui", "package.json");
50585
+ const templateTmpDir = import_node_path7.default.join(projectRoot, "tmp");
50335
50586
  const uiPackageRoot = options.version ? void 0 : resolveUiPackageRoot(projectRoot, options.uiPackageRoot);
50336
- const uiVersion = options.version ?? readJson(import_node_path5.default.join(uiPackageRoot, "package.json")).version;
50587
+ const uiVersion = options.version ?? readJson(import_node_path7.default.join(uiPackageRoot, "package.json")).version;
50337
50588
  if (!uiVersion) {
50338
50589
  throw new Error("Could not determine @elevasis/ui version. Pass --version <version>.");
50339
50590
  }
50340
- if (!import_node_fs5.default.existsSync(templateUiPackageJsonPath)) {
50591
+ if (!import_node_fs6.default.existsSync(templateUiPackageJsonPath)) {
50341
50592
  throw new Error(`Template UI package.json not found: ${templateUiPackageJsonPath}`);
50342
50593
  }
50343
50594
  const templateUiPackageJson = readJson(templateUiPackageJsonPath);
@@ -50345,7 +50596,7 @@ function usePublishedUi(options = {}) {
50345
50596
  writeJson(templateUiPackageJsonPath, templateUiPackageJson);
50346
50597
  removeLocalUiTarballs(templateTmpDir);
50347
50598
  run("pnpm", ["-C", projectRoot, "install"], commandRoot);
50348
- console.log(`${import_node_path5.default.basename(projectRoot)}/ui restored to published @elevasis/ui ^${uiVersion}`);
50599
+ console.log(`${import_node_path7.default.basename(projectRoot)}/ui restored to published @elevasis/ui ^${uiVersion}`);
50349
50600
  }
50350
50601
 
50351
50602
  // src/cli/commands/ui/ui.ts
@@ -50363,8 +50614,8 @@ function registerUiCommands(program3) {
50363
50614
  }
50364
50615
 
50365
50616
  // src/cli/commands/doctor.ts
50366
- var import_node_fs6 = require("node:fs");
50367
- var import_node_path6 = __toESM(require("node:path"), 1);
50617
+ var import_node_fs7 = require("node:fs");
50618
+ var import_node_path8 = __toESM(require("node:path"), 1);
50368
50619
  init_source();
50369
50620
  init_config();
50370
50621
  function ok(label, detail) {
@@ -50402,8 +50653,8 @@ function registerDoctorCommand(program3) {
50402
50653
  printSummary(failCount);
50403
50654
  process.exit(1);
50404
50655
  }
50405
- const envPath2 = import_node_path6.default.join(projectRoot, ".env");
50406
- const envExists = (0, import_node_fs6.existsSync)(envPath2);
50656
+ const envPath2 = import_node_path8.default.join(projectRoot, ".env");
50657
+ const envExists = (0, import_node_fs7.existsSync)(envPath2);
50407
50658
  if (!envExists) {
50408
50659
  fail(".env", `Not found at ${envPath2}. Create it from .env.example and fill in ELEVASIS_PLATFORM_KEY.`);
50409
50660
  if (isVerbose) verbose(`Checked: ${envPath2}`);
@@ -50490,101 +50741,6 @@ function printSummary(failCount) {
50490
50741
  }
50491
50742
  }
50492
50743
 
50493
- // src/cli/commands/cli/catalog.ts
50494
- function buildCliCatalogFromProgram(program3, options = {}) {
50495
- const commands = program3.commands.flatMap((command) => collectRuntimeCommands(command));
50496
- return groupCommands(commands, "registered Commander commands", options.domain);
50497
- }
50498
- function groupCommands(commands, sourceRoot, domain2) {
50499
- const filtered = domain2 ? commands.filter((command) => command.domain === domain2) : commands;
50500
- const sorted = filtered.sort((a, b) => a.domain.localeCompare(b.domain) || a.syntax.localeCompare(b.syntax));
50501
- const domainNames = [...new Set(sorted.map((command) => command.domain))];
50502
- return {
50503
- sourceRoot,
50504
- domains: domainNames.map((name) => ({
50505
- name,
50506
- commands: sorted.filter((command) => command.domain === name)
50507
- }))
50508
- };
50509
- }
50510
- function collectRuntimeCommands(command, parent) {
50511
- const commandName = command.name();
50512
- const argSuffix = formatRuntimeArguments(command.registeredArguments);
50513
- const syntaxSegment = argSuffix ? `${commandName} ${argSuffix}` : commandName;
50514
- const syntax = parent ? `${parent.syntax} ${syntaxSegment}` : syntaxSegment;
50515
- const domain2 = parent?.domain ?? domainFromCommand(commandName);
50516
- const current = {
50517
- command: commandName,
50518
- syntax,
50519
- domain: domain2
50520
- };
50521
- const aliases = command.aliases().map((alias) => parent ? `${parent.syntax} ${alias}` : alias);
50522
- return [
50523
- {
50524
- syntax,
50525
- command: commandName,
50526
- domain: domain2,
50527
- description: firstLine(command.description()),
50528
- aliases,
50529
- options: command.options.map((option) => ({
50530
- flags: option.flags,
50531
- description: option.description,
50532
- required: option.mandatory
50533
- })),
50534
- source: "runtime"
50535
- },
50536
- ...command.commands.flatMap((child) => collectRuntimeCommands(child, current))
50537
- ];
50538
- }
50539
- function formatRuntimeArguments(args) {
50540
- return args.map((arg) => {
50541
- const name = `${arg.name()}${arg.variadic ? "..." : ""}`;
50542
- return arg.required ? `<${name}>` : `[${name}]`;
50543
- }).join(" ");
50544
- }
50545
- function renderCliCatalogMarkdown(catalog) {
50546
- const lines = [
50547
- "# elevasis-sdk CLI Catalog",
50548
- "",
50549
- `Source: \`${catalog.sourceRoot}\``,
50550
- ""
50551
- ];
50552
- if (catalog.domains.length === 0) {
50553
- lines.push("No commands found.");
50554
- return lines.join("\n");
50555
- }
50556
- for (const domain2 of catalog.domains) {
50557
- lines.push(`## ${domain2.name}`, "");
50558
- lines.push("| Command | Description | Aliases | Options | Source |");
50559
- lines.push("| --- | --- | --- | --- | --- |");
50560
- for (const command of domain2.commands) {
50561
- const aliases = command.aliases.length > 0 ? command.aliases.map((alias) => `\`${alias}\``).join(", ") : "-";
50562
- const options = command.options.length > 0 ? command.options.map((option) => `${option.required ? "required " : ""}\`${option.flags}\``).join("<br>") : "-";
50563
- lines.push(
50564
- `| \`elevasis-sdk ${command.syntax}\` | ${escapeMarkdownTable(command.description || "-")} | ${aliases} | ${options} | \`${command.source}\` |`
50565
- );
50566
- }
50567
- lines.push("");
50568
- }
50569
- return lines.join("\n").trimEnd();
50570
- }
50571
- function renderCliCatalogJson(catalog) {
50572
- return JSON.stringify(catalog, null, 2);
50573
- }
50574
- function domainFromCommand(command) {
50575
- if (command.includes(":")) return command.split(":")[0];
50576
- return "platform";
50577
- }
50578
- function firstLine(value) {
50579
- return value.split("\n")[0]?.trim() ?? "";
50580
- }
50581
- function escapeMarkdownTable(value) {
50582
- return value.replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
50583
- }
50584
- function knownDomains(catalog) {
50585
- return catalog.domains.map((domain2) => domain2.name);
50586
- }
50587
-
50588
50744
  // src/cli/commands/cli/cli.ts
50589
50745
  var FORMATS = /* @__PURE__ */ new Set(["markdown", "json"]);
50590
50746
  function registerCliCatalogCommand(program3) {
@@ -51638,10 +51794,93 @@ function registerOmScaffoldCommands(program3) {
51638
51794
  });
51639
51795
  }
51640
51796
 
51797
+ // src/cli/commands/skill/skill-scaffold.ts
51798
+ init_source();
51799
+ function buildSkillMd(domain2) {
51800
+ const name = domain2.name;
51801
+ const commandNames = domain2.commands.map((c) => c.command.replace(`${name}:`, ""));
51802
+ const argumentHint = `[${commandNames.join(" | ")}] [args]`;
51803
+ const descriptionText = `${name} domain operations \u2014 ${commandNames.join(", ")} \u2014 via the elevasis-sdk ${name}:* CLI.`;
51804
+ const lines = [
51805
+ "---",
51806
+ `name: ${name}`,
51807
+ `description: "${descriptionText}"`,
51808
+ `argument-hint: "${argumentHint}"`,
51809
+ `allowed-tools: Bash, Read, Write, Edit, Glob, Grep`,
51810
+ "---",
51811
+ "",
51812
+ `# ${name.charAt(0).toUpperCase() + name.slice(1)} Skill`,
51813
+ "",
51814
+ `> **Generated stub.** Curate the prose below: add vibe integration, confirm ceremony,`,
51815
+ `> and any operation-level detail. The usage table is pre-filled from the CLI catalog.`,
51816
+ "",
51817
+ "## Usage",
51818
+ "",
51819
+ "| Command | Description | Options |",
51820
+ "| --- | --- | --- |"
51821
+ ];
51822
+ for (const cmd of domain2.commands) {
51823
+ const syntax = `\`elevasis-sdk ${cmd.syntax}\``;
51824
+ const description = cmd.description || "-";
51825
+ const options = cmd.options.length > 0 ? cmd.options.map((o) => `${o.required ? "required " : ""}\`${o.flags}\``).join(", ") : "-";
51826
+ lines.push(`| ${syntax} | ${description} | ${options} |`);
51827
+ }
51828
+ lines.push("");
51829
+ const commandsWithAliases = domain2.commands.filter((c) => c.aliases.length > 0);
51830
+ if (commandsWithAliases.length > 0) {
51831
+ lines.push("## Aliases", "");
51832
+ for (const cmd of commandsWithAliases) {
51833
+ for (const alias of cmd.aliases) {
51834
+ lines.push(`- \`elevasis-sdk ${alias}\` \u2192 \`elevasis-sdk ${cmd.syntax}\``);
51835
+ }
51836
+ }
51837
+ lines.push("");
51838
+ }
51839
+ lines.push(
51840
+ "## Connection",
51841
+ "",
51842
+ "```bash",
51843
+ "# .env (project root)",
51844
+ "ELEVASIS_PLATFORM_KEY=sk_...",
51845
+ "```",
51846
+ "",
51847
+ "```bash",
51848
+ `pnpm elevasis-sdk ${name}:<command> [args]`,
51849
+ "```",
51850
+ ""
51851
+ );
51852
+ return lines.join("\n");
51853
+ }
51854
+ function registerSkillScaffoldCommand(program3) {
51855
+ program3.command("skill:scaffold <domain>").description(
51856
+ "Emit a SKILL.md stub for a CLI domain from the catalog\n Example: elevasis-sdk skill:scaffold client"
51857
+ ).option("--output", "Write the stub to stdout only (default behavior)").action(
51858
+ wrapAction("skill:scaffold", async (domain2) => {
51859
+ const catalog = buildCliCatalogFromProgram(program3, { domain: domain2 });
51860
+ if (catalog.domains.length === 0) {
51861
+ const fullCatalog = buildCliCatalogFromProgram(program3);
51862
+ const known = knownDomains(fullCatalog);
51863
+ throw new Error(`No CLI domain "${domain2}" found. Known domains: ${known.join(", ")}`);
51864
+ }
51865
+ const domainEntry = catalog.domains[0];
51866
+ const stub = buildSkillMd(domainEntry);
51867
+ console.log(
51868
+ source_default.gray(
51869
+ `# SKILL.md stub for domain "${domain2}" (${domainEntry.commands.length} commands)
51870
+ # Copy this to: external/_template/.claude/skills/${domain2}/SKILL.md
51871
+ # Then curate: add vibe integration, confirm ceremony, and operation prose.
51872
+ `
51873
+ )
51874
+ );
51875
+ console.log(stub);
51876
+ })
51877
+ );
51878
+ }
51879
+
51641
51880
  // src/cli/index.ts
51642
51881
  init_config();
51643
51882
  var PREFLIGHT_SKIP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
51644
- var PREFLIGHT_SKIP_COMMANDS = /* @__PURE__ */ new Set(["cli"]);
51883
+ var PREFLIGHT_SKIP_COMMANDS = /* @__PURE__ */ new Set(["cli", "skill:scaffold"]);
51645
51884
  var LOCAL_PROJECT_COMMANDS = /* @__PURE__ */ new Set([
51646
51885
  "ui:use-local",
51647
51886
  "ui:use-published",
@@ -51771,6 +52010,8 @@ registerUiCommands(program2);
51771
52010
  registerDoctorCommand(program2);
51772
52011
  registerCliCatalogCommand(program2);
51773
52012
  registerOmScaffoldCommands(program2);
52013
+ registerSkillScaffoldCommand(program2);
52014
+ registerSkillCheckCoverageCommand(program2);
51774
52015
  program2.parse();
51775
52016
  // Annotate the CommonJS export names for ESM import in node:
51776
52017
  0 && (module.exports = {