@elevasis/sdk 1.32.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
  });
@@ -23742,7 +23742,7 @@ async function withSnapshotRollback(filePaths, op) {
23742
23742
  const snapshots = /* @__PURE__ */ new Map();
23743
23743
  for (const filePath of filePaths) {
23744
23744
  try {
23745
- snapshots.set(filePath, (0, import_node_fs8.readFileSync)(filePath, "utf8"));
23745
+ snapshots.set(filePath, (0, import_node_fs9.readFileSync)(filePath, "utf8"));
23746
23746
  } catch {
23747
23747
  snapshots.set(filePath, null);
23748
23748
  }
@@ -23753,7 +23753,7 @@ async function withSnapshotRollback(filePaths, op) {
23753
23753
  for (const [filePath, snapshot] of snapshots) {
23754
23754
  if (snapshot !== null) {
23755
23755
  try {
23756
- (0, import_node_fs8.writeFileSync)(filePath, snapshot, "utf8");
23756
+ (0, import_node_fs9.writeFileSync)(filePath, snapshot, "utf8");
23757
23757
  } catch {
23758
23758
  }
23759
23759
  }
@@ -23774,14 +23774,14 @@ function insertBeforeAnchorInContent(content, code, anchor) {
23774
23774
  return lines.join("\n");
23775
23775
  }
23776
23776
  async function appendBeforeAnchor(filePath, code, anchor) {
23777
- const content = (0, import_node_fs8.readFileSync)(filePath, "utf8");
23777
+ const content = (0, import_node_fs9.readFileSync)(filePath, "utf8");
23778
23778
  const updated = insertBeforeAnchorInContent(content, code, anchor);
23779
- (0, import_node_fs8.writeFileSync)(filePath, updated, "utf8");
23779
+ (0, import_node_fs9.writeFileSync)(filePath, updated, "utf8");
23780
23780
  }
23781
23781
  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");
23782
+ (0, import_node_fs9.mkdirSync)((0, import_node_path10.dirname)(newConstFilePath), { recursive: true });
23783
+ (0, import_node_fs9.writeFileSync)(newConstFilePath, newConstFileCode, "utf8");
23784
+ const systemsContent = (0, import_node_fs9.readFileSync)(systemsFilePath, "utf8");
23785
23785
  const afterImport = insertBeforeAnchorInContent(systemsContent, importLine + "\n", importAnchor);
23786
23786
  const lines = afterImport.split("\n");
23787
23787
  const fieldAnchorIndex = lines.findIndex((line) => fieldAnchor.test(line));
@@ -23791,14 +23791,14 @@ async function applyConstImport(systemsFilePath, importLine, fieldLine, importAn
23791
23791
  );
23792
23792
  }
23793
23793
  lines.splice(fieldAnchorIndex + 1, 0, fieldLine);
23794
- (0, import_node_fs8.writeFileSync)(systemsFilePath, lines.join("\n"), "utf8");
23794
+ (0, import_node_fs9.writeFileSync)(systemsFilePath, lines.join("\n"), "utf8");
23795
23795
  }
23796
- var import_node_fs8, import_node_path8;
23796
+ var import_node_fs9, import_node_path10;
23797
23797
  var init_splice = __esm({
23798
23798
  "src/cli/commands/om/splice.ts"() {
23799
23799
  "use strict";
23800
- import_node_fs8 = require("node:fs");
23801
- import_node_path8 = require("node:path");
23800
+ import_node_fs9 = require("node:fs");
23801
+ import_node_path10 = require("node:path");
23802
23802
  }
23803
23803
  });
23804
23804
 
@@ -23861,7 +23861,7 @@ async function scaffoldSystem(opts) {
23861
23861
  }
23862
23862
  return;
23863
23863
  }
23864
- const systemsFilePath = (0, import_node_path9.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23864
+ const systemsFilePath = (0, import_node_path11.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23865
23865
  try {
23866
23866
  await withSnapshotRollback([systemsFilePath], async () => {
23867
23867
  await appendBeforeAnchor(systemsFilePath, code, anchor);
@@ -23882,11 +23882,11 @@ async function scaffoldSystem(opts) {
23882
23882
  );
23883
23883
  }
23884
23884
  }
23885
- var import_node_path9, import_node_child_process2;
23885
+ var import_node_path11, import_node_child_process2;
23886
23886
  var init_scaffold_system = __esm({
23887
23887
  "src/cli/commands/om/scaffold-system.ts"() {
23888
23888
  "use strict";
23889
- import_node_path9 = require("node:path");
23889
+ import_node_path11 = require("node:path");
23890
23890
  import_node_child_process2 = require("node:child_process");
23891
23891
  init_source();
23892
23892
  init_config();
@@ -23980,7 +23980,7 @@ async function scaffoldResource(opts) {
23980
23980
  console.log(code);
23981
23981
  return;
23982
23982
  }
23983
- const systemsFilePath = (0, import_node_path10.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23983
+ const systemsFilePath = (0, import_node_path12.join)(projectDir, "core", "config", "organization-model", "systems.ts");
23984
23984
  try {
23985
23985
  await withSnapshotRollback([systemsFilePath], async () => {
23986
23986
  await appendBeforeAnchor(systemsFilePath, code, anchor);
@@ -23998,11 +23998,11 @@ Resource \`${id}\` references system \`${systemPath}\` which is not in \`templat
23998
23998
  }
23999
23999
  console.log(source_default.green(`Resource \`${id}\` scaffolded in core/config/organization-model/systems.ts`));
24000
24000
  }
24001
- var import_node_path10, import_node_child_process3;
24001
+ var import_node_path12, import_node_child_process3;
24002
24002
  var init_scaffold_resource = __esm({
24003
24003
  "src/cli/commands/om/scaffold-resource.ts"() {
24004
24004
  "use strict";
24005
- import_node_path10 = require("node:path");
24005
+ import_node_path12 = require("node:path");
24006
24006
  import_node_child_process3 = require("node:child_process");
24007
24007
  init_source();
24008
24008
  init_config();
@@ -24073,7 +24073,7 @@ async function scaffoldRole(opts) {
24073
24073
  console.log(code);
24074
24074
  return;
24075
24075
  }
24076
- const profileFilePath = (0, import_node_path11.join)(projectDir, "core", "config", "organization-model", "profile.ts");
24076
+ const profileFilePath = (0, import_node_path13.join)(projectDir, "core", "config", "organization-model", "profile.ts");
24077
24077
  try {
24078
24078
  await withSnapshotRollback([profileFilePath], async () => {
24079
24079
  await appendBeforeAnchor(profileFilePath, code, anchor);
@@ -24089,11 +24089,11 @@ async function scaffoldRole(opts) {
24089
24089
  }
24090
24090
  console.log(source_default.green(`Role \`${id}\` scaffolded in core/config/organization-model/profile.ts`));
24091
24091
  }
24092
- var import_node_path11, import_node_child_process4;
24092
+ var import_node_path13, import_node_child_process4;
24093
24093
  var init_scaffold_role = __esm({
24094
24094
  "src/cli/commands/om/scaffold-role.ts"() {
24095
24095
  "use strict";
24096
- import_node_path11 = require("node:path");
24096
+ import_node_path13 = require("node:path");
24097
24097
  import_node_child_process4 = require("node:child_process");
24098
24098
  init_source();
24099
24099
  init_config();
@@ -24168,25 +24168,25 @@ async function scaffoldKnowledge(opts) {
24168
24168
  console.log(source_default.yellow("Run `elevasis-sdk om:generate` to register this node."));
24169
24169
  return;
24170
24170
  }
24171
- const absoluteFilePath = (0, import_node_path12.join)(projectDir, relativeFilePath);
24172
- if ((0, import_node_fs9.existsSync)(absoluteFilePath)) {
24171
+ const absoluteFilePath = (0, import_node_path14.join)(projectDir, relativeFilePath);
24172
+ if ((0, import_node_fs10.existsSync)(absoluteFilePath)) {
24173
24173
  process.stderr.write(
24174
24174
  source_default.red(`Knowledge node file already exists at \`${relativeFilePath}\`. Choose a different id.
24175
24175
  `)
24176
24176
  );
24177
24177
  process.exit(1);
24178
24178
  }
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");
24179
+ (0, import_node_fs10.mkdirSync)((0, import_node_path14.join)(projectDir, "core", "config", "knowledge", "nodes"), { recursive: true });
24180
+ (0, import_node_fs10.writeFileSync)(absoluteFilePath, content, "utf8");
24181
24181
  console.log(source_default.green(`Knowledge node \`${id}\` written to \`${relativeFilePath}\``));
24182
24182
  console.log(source_default.yellow("Run `elevasis-sdk om:generate` to register this node."));
24183
24183
  }
24184
- var import_node_path12, import_node_fs9, VALID_KINDS;
24184
+ var import_node_path14, import_node_fs10, VALID_KINDS;
24185
24185
  var init_scaffold_knowledge = __esm({
24186
24186
  "src/cli/commands/om/scaffold-knowledge.ts"() {
24187
24187
  "use strict";
24188
- import_node_path12 = require("node:path");
24189
- import_node_fs9 = require("node:fs");
24188
+ import_node_path14 = require("node:path");
24189
+ import_node_fs10 = require("node:fs");
24190
24190
  init_source();
24191
24191
  init_config();
24192
24192
  init_project_layout();
@@ -24240,7 +24240,7 @@ __export(scaffold_fill_exports, {
24240
24240
  default: () => scaffoldFill
24241
24241
  });
24242
24242
  function conformanceGapTempPath(orgName) {
24243
- return (0, import_node_path13.join)(os2.tmpdir(), `elevasis-conformance-${orgName}-${Date.now()}.json`);
24243
+ return (0, import_node_path15.join)(os2.tmpdir(), `elevasis-conformance-${orgName}-${Date.now()}.json`);
24244
24244
  }
24245
24245
  function runValidation4(projectDir) {
24246
24246
  for (const script of ["check-types", "check"]) {
@@ -24263,7 +24263,7 @@ async function scaffoldFill(opts) {
24263
24263
  process.stderr.write(source_default.red("Missing gaps file. Pass --gaps <path> pointing to a conformance gap JSON file.\n"));
24264
24264
  process.exit(1);
24265
24265
  }
24266
- if (!(0, import_node_fs10.existsSync)(options.gaps)) {
24266
+ if (!(0, import_node_fs11.existsSync)(options.gaps)) {
24267
24267
  process.stderr.write(
24268
24268
  source_default.red(
24269
24269
  `Missing gaps file. Pass --gaps <path> pointing to a conformance gap JSON file.
@@ -24275,7 +24275,7 @@ async function scaffoldFill(opts) {
24275
24275
  }
24276
24276
  let payload;
24277
24277
  try {
24278
- const raw = (0, import_node_fs10.readFileSync)(options.gaps, "utf8");
24278
+ const raw = (0, import_node_fs11.readFileSync)(options.gaps, "utf8");
24279
24279
  payload = JSON.parse(raw);
24280
24280
  } catch {
24281
24281
  process.stderr.write(
@@ -24300,7 +24300,7 @@ async function scaffoldFill(opts) {
24300
24300
  const systemPath = payload.systemPath;
24301
24301
  const skippedGaps = [];
24302
24302
  const appliedGaps = [];
24303
- const systemsFilePath = (0, import_node_path13.join)(projectDir, "core", "config", "organization-model", "systems.ts");
24303
+ const systemsFilePath = (0, import_node_path15.join)(projectDir, "core", "config", "organization-model", "systems.ts");
24304
24304
  const touchedFiles = [systemsFilePath];
24305
24305
  const emitResults = [];
24306
24306
  for (const gap of payload.gaps) {
@@ -24317,7 +24317,7 @@ async function scaffoldFill(opts) {
24317
24317
  resourceIds,
24318
24318
  message: gap.reason
24319
24319
  });
24320
- const constFilePath = (0, import_node_path13.join)(
24320
+ const constFilePath = (0, import_node_path15.join)(
24321
24321
  projectDir,
24322
24322
  "core",
24323
24323
  "config",
@@ -24365,7 +24365,7 @@ async function scaffoldFill(opts) {
24365
24365
  await withSnapshotRollback(touchedFiles, async () => {
24366
24366
  for (let i = 0; i < emitResults.length; i++) {
24367
24367
  const result = emitResults[i];
24368
- const constFilePath = (0, import_node_path13.join)(
24368
+ const constFilePath = (0, import_node_path15.join)(
24369
24369
  projectDir,
24370
24370
  "core",
24371
24371
  "config",
@@ -24395,8 +24395,8 @@ async function scaffoldFill(opts) {
24395
24395
  }
24396
24396
  }
24397
24397
  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");
24398
+ const skippedPath = options.skipped ?? (0, import_node_path15.join)(os2.tmpdir(), `elevasis-fill-skipped-${systemPath}-${Date.now()}.json`);
24399
+ (0, import_node_fs11.writeFileSync)(skippedPath, JSON.stringify({ systemPath, skipped: skippedGaps }, null, 2), "utf8");
24400
24400
  console.log(
24401
24401
  source_default.yellow(
24402
24402
  `Partial fill: ${appliedGaps.length} gap(s) applied, ${skippedGaps.length} skipped \u2014 see \`${skippedPath}\` for fields requiring manual input.`
@@ -24410,13 +24410,13 @@ async function scaffoldFill(opts) {
24410
24410
  )
24411
24411
  );
24412
24412
  }
24413
- var import_node_path13, os2, import_node_fs10, import_node_child_process5;
24413
+ var import_node_path15, os2, import_node_fs11, import_node_child_process5;
24414
24414
  var init_scaffold_fill = __esm({
24415
24415
  "src/cli/commands/om/scaffold-fill.ts"() {
24416
24416
  "use strict";
24417
- import_node_path13 = require("node:path");
24417
+ import_node_path15 = require("node:path");
24418
24418
  os2 = __toESM(require("node:os"), 1);
24419
- import_node_fs10 = require("node:fs");
24419
+ import_node_fs11 = require("node:fs");
24420
24420
  import_node_child_process5 = require("node:child_process");
24421
24421
  init_source();
24422
24422
  init_config();
@@ -45716,7 +45716,7 @@ function wrapAction(commandName, fn) {
45716
45716
  // package.json
45717
45717
  var package_default = {
45718
45718
  name: "@elevasis/sdk",
45719
- version: "1.32.0",
45719
+ version: "1.33.0",
45720
45720
  description: "SDK for building Elevasis organization resources",
45721
45721
  type: "module",
45722
45722
  bin: {
@@ -45756,7 +45756,7 @@ var package_default = {
45756
45756
  ],
45757
45757
  scripts: {
45758
45758
  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`,
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/verify-skill-coverage.mjs && node scripts/copy-reference-docs.mjs && node ../../scripts/monorepo/generate-reference-artifacts.js`,
45760
45760
  "type-check": "tsc --noEmit",
45761
45761
  "check-types": "pnpm type-check",
45762
45762
  test: "pnpm build && node ../../scripts/monorepo/validate-reference-artifacts.js && vitest run --config vitest.bundle.config.ts",
@@ -46236,10 +46236,221 @@ import { startWorker } from '@elevasis/sdk/worker'
46236
46236
 
46237
46237
  // src/cli/commands/check.ts
46238
46238
  init_config();
46239
+
46240
+ // src/cli/commands/skill/skill-check-coverage.ts
46241
+ var import_node_path2 = require("node:path");
46242
+ init_source();
46243
+
46244
+ // src/cli/commands/cli/catalog.ts
46245
+ function buildCliCatalogFromProgram(program3, options = {}) {
46246
+ const commands = program3.commands.flatMap((command) => collectRuntimeCommands(command));
46247
+ return groupCommands(commands, "registered Commander commands", options.domain);
46248
+ }
46249
+ function groupCommands(commands, sourceRoot, domain2) {
46250
+ const filtered = domain2 ? commands.filter((command) => command.domain === domain2) : commands;
46251
+ const sorted = filtered.sort((a, b) => a.domain.localeCompare(b.domain) || a.syntax.localeCompare(b.syntax));
46252
+ const domainNames = [...new Set(sorted.map((command) => command.domain))];
46253
+ return {
46254
+ sourceRoot,
46255
+ domains: domainNames.map((name) => ({
46256
+ name,
46257
+ commands: sorted.filter((command) => command.domain === name)
46258
+ }))
46259
+ };
46260
+ }
46261
+ function collectRuntimeCommands(command, parent) {
46262
+ const commandName = command.name();
46263
+ const argSuffix = formatRuntimeArguments(command.registeredArguments);
46264
+ const syntaxSegment = argSuffix ? `${commandName} ${argSuffix}` : commandName;
46265
+ const syntax = parent ? `${parent.syntax} ${syntaxSegment}` : syntaxSegment;
46266
+ const domain2 = parent?.domain ?? domainFromCommand(commandName);
46267
+ const current = {
46268
+ command: commandName,
46269
+ syntax,
46270
+ domain: domain2
46271
+ };
46272
+ const aliases = command.aliases().map((alias) => parent ? `${parent.syntax} ${alias}` : alias);
46273
+ return [
46274
+ {
46275
+ syntax,
46276
+ command: commandName,
46277
+ domain: domain2,
46278
+ description: firstLine(command.description()),
46279
+ aliases,
46280
+ options: command.options.map((option) => ({
46281
+ flags: option.flags,
46282
+ description: option.description,
46283
+ required: option.mandatory
46284
+ })),
46285
+ source: "runtime"
46286
+ },
46287
+ ...command.commands.flatMap((child) => collectRuntimeCommands(child, current))
46288
+ ];
46289
+ }
46290
+ function formatRuntimeArguments(args) {
46291
+ return args.map((arg) => {
46292
+ const name = `${arg.name()}${arg.variadic ? "..." : ""}`;
46293
+ return arg.required ? `<${name}>` : `[${name}]`;
46294
+ }).join(" ");
46295
+ }
46296
+ function renderCliCatalogMarkdown(catalog) {
46297
+ const lines = [
46298
+ "# elevasis-sdk CLI Catalog",
46299
+ "",
46300
+ `Source: \`${catalog.sourceRoot}\``,
46301
+ ""
46302
+ ];
46303
+ if (catalog.domains.length === 0) {
46304
+ lines.push("No commands found.");
46305
+ return lines.join("\n");
46306
+ }
46307
+ for (const domain2 of catalog.domains) {
46308
+ lines.push(`## ${domain2.name}`, "");
46309
+ lines.push("| Command | Description | Aliases | Options | Source |");
46310
+ lines.push("| --- | --- | --- | --- | --- |");
46311
+ for (const command of domain2.commands) {
46312
+ const aliases = command.aliases.length > 0 ? command.aliases.map((alias) => `\`${alias}\``).join(", ") : "-";
46313
+ const options = command.options.length > 0 ? command.options.map((option) => `${option.required ? "required " : ""}\`${option.flags}\``).join("<br>") : "-";
46314
+ lines.push(
46315
+ `| \`elevasis-sdk ${command.syntax}\` | ${escapeMarkdownTable(command.description || "-")} | ${aliases} | ${options} | \`${command.source}\` |`
46316
+ );
46317
+ }
46318
+ lines.push("");
46319
+ }
46320
+ return lines.join("\n").trimEnd();
46321
+ }
46322
+ function renderCliCatalogJson(catalog) {
46323
+ return JSON.stringify(catalog, null, 2);
46324
+ }
46325
+ function domainFromCommand(command) {
46326
+ if (command.includes(":")) return command.split(":")[0];
46327
+ return "platform";
46328
+ }
46329
+ function firstLine(value) {
46330
+ return value.split("\n")[0]?.trim() ?? "";
46331
+ }
46332
+ function escapeMarkdownTable(value) {
46333
+ return value.replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
46334
+ }
46335
+ function knownDomains(catalog) {
46336
+ return catalog.domains.map((domain2) => domain2.name);
46337
+ }
46338
+
46339
+ // src/cli/commands/skill/skill-coverage.ts
46340
+ var import_node_fs = require("node:fs");
46341
+ var import_node_path = require("node:path");
46342
+ function loadSkillCoverage(projectRoot) {
46343
+ const coveragePath = (0, import_node_path.join)(projectRoot, ".claude", "registries", "skill-coverage.json");
46344
+ if (!(0, import_node_fs.existsSync)(coveragePath)) return null;
46345
+ const raw = (0, import_node_fs.readFileSync)(coveragePath, "utf8");
46346
+ return JSON.parse(raw);
46347
+ }
46348
+ function runCoverageGate(knownDomains2, coverage, presentSkills, coverageFilePath) {
46349
+ const violations = [];
46350
+ const domainSet = new Set(knownDomains2);
46351
+ const ownedDomains = /* @__PURE__ */ new Set();
46352
+ for (const entry of Object.values(coverage.skills)) {
46353
+ for (const domain2 of entry.domains) {
46354
+ ownedDomains.add(domain2);
46355
+ }
46356
+ }
46357
+ const waivedDomains = new Set(Object.keys(coverage.waived));
46358
+ for (const domain2 of knownDomains2) {
46359
+ if (!ownedDomains.has(domain2) && !waivedDomains.has(domain2)) {
46360
+ violations.push({
46361
+ kind: "uncovered",
46362
+ domain: domain2,
46363
+ detail: `Domain "${domain2}" exists in the CLI but is neither skill-owned nor waived in ${coverageFilePath}. Add it to "skills" or "waived".`
46364
+ });
46365
+ }
46366
+ }
46367
+ for (const [skillName, entry] of Object.entries(coverage.skills)) {
46368
+ for (const domain2 of entry.domains) {
46369
+ if (!domainSet.has(domain2)) {
46370
+ violations.push({
46371
+ kind: "stale-owned",
46372
+ domain: domain2,
46373
+ 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.`
46374
+ });
46375
+ }
46376
+ }
46377
+ }
46378
+ for (const domain2 of waivedDomains) {
46379
+ if (!domainSet.has(domain2)) {
46380
+ violations.push({
46381
+ kind: "stale-waived",
46382
+ domain: domain2,
46383
+ detail: `Domain "${domain2}" is declared as waived in ${coverageFilePath} but no longer exists in the CLI catalog. Remove the waiver.`
46384
+ });
46385
+ }
46386
+ }
46387
+ return {
46388
+ violations,
46389
+ domainsChecked: knownDomains2,
46390
+ coverageFile: coverageFilePath
46391
+ };
46392
+ }
46393
+
46394
+ // src/cli/commands/skill/skill-check-coverage.ts
46395
+ init_config();
46396
+ async function runSkillCoverageCheck(program3, options = {}) {
46397
+ const projectRoot = tryFindProjectRoot(process.cwd());
46398
+ if (projectRoot === null) {
46399
+ return { passed: true, violationCount: 0 };
46400
+ }
46401
+ const coveragePath = (0, import_node_path2.join)(projectRoot, ".claude", "registries", "skill-coverage.json");
46402
+ const coverage = loadSkillCoverage(projectRoot);
46403
+ if (coverage === null) {
46404
+ if (!options.silent) {
46405
+ console.log(
46406
+ source_default.yellow(" warn skill-coverage.json not found \u2014 skipping coverage gate") + source_default.gray(`
46407
+ Expected: ${coveragePath}`)
46408
+ );
46409
+ }
46410
+ return { passed: true, violationCount: 0 };
46411
+ }
46412
+ const catalog = buildCliCatalogFromProgram(program3);
46413
+ const domains = knownDomains(catalog);
46414
+ const result = runCoverageGate(domains, coverage, /* @__PURE__ */ new Set(), coveragePath);
46415
+ if (result.violations.length === 0) {
46416
+ if (!options.silent) {
46417
+ console.log(
46418
+ source_default.green(" Skill coverage OK") + source_default.gray(` (${domains.length} domains checked, all covered or waived)`)
46419
+ );
46420
+ }
46421
+ return { passed: true, violationCount: 0 };
46422
+ }
46423
+ for (const violation of result.violations) {
46424
+ const prefix = violation.kind === "uncovered" ? source_default.red(" ERROR coverage") : source_default.yellow(" WARN coverage");
46425
+ console.error(`${prefix} ${violation.detail}`);
46426
+ }
46427
+ return { passed: false, violationCount: result.violations.length };
46428
+ }
46429
+ function registerSkillCheckCoverageCommand(program3) {
46430
+ program3.command("skill:check-coverage").description(
46431
+ "Verify CLI domains are covered by skills or waived in skill-coverage.json\n Example: elevasis-sdk skill:check-coverage"
46432
+ ).action(
46433
+ wrapAction("skill:check-coverage", async () => {
46434
+ const catalog = buildCliCatalogFromProgram(program3);
46435
+ const domains = knownDomains(catalog);
46436
+ console.log(source_default.cyan(`Checking skill coverage for ${domains.length} CLI domains...`));
46437
+ const { passed, violationCount } = await runSkillCoverageCheck(program3);
46438
+ if (!passed) {
46439
+ console.error("");
46440
+ console.error(
46441
+ 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".')
46442
+ );
46443
+ process.exitCode = 1;
46444
+ }
46445
+ })
46446
+ );
46447
+ }
46448
+
46449
+ // src/cli/commands/check.ts
46239
46450
  function registerCheckCommand(program3) {
46240
46451
  program3.command("check").description(
46241
46452
  "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(
46453
+ ).option("--entry <path>", "Path to entry file (default: ./src/index.ts)").option("--skip-coverage", "Skip the skill coverage gate").action(
46243
46454
  wrapAction("check", async (options) => {
46244
46455
  const entryPath = options.entry ?? "./src/index.ts";
46245
46456
  const spinner = ora("Validating resources...").start();
@@ -46290,6 +46501,20 @@ function registerCheckCommand(program3) {
46290
46501
  }
46291
46502
  console.log(source_default.gray(" Schemas will be unavailable on the platform for these resources."));
46292
46503
  }
46504
+ if (!options.skipCoverage) {
46505
+ console.log("");
46506
+ const coverageResult = await runSkillCoverageCheck(program3);
46507
+ if (!coverageResult.passed) {
46508
+ console.error("");
46509
+ console.error(
46510
+ source_default.red(`Skill coverage check failed: ${coverageResult.violationCount} violation(s).`) + "\n" + source_default.gray(
46511
+ ' Update .claude/registries/skill-coverage.json to add the domain to "skills" or "waived".\n Run with --skip-coverage to suppress this check.'
46512
+ )
46513
+ );
46514
+ process.exitCode = 1;
46515
+ return;
46516
+ }
46517
+ }
46293
46518
  } catch (error46) {
46294
46519
  if (error46 instanceof RegistryValidationError) {
46295
46520
  spinner.fail(source_default.red("Validation failed"));
@@ -46311,8 +46536,8 @@ function registerCheckCommand(program3) {
46311
46536
  }
46312
46537
 
46313
46538
  // src/cli/commands/exec.ts
46314
- var import_node_fs = require("node:fs");
46315
- var import_node_path = require("node:path");
46539
+ var import_node_fs2 = require("node:fs");
46540
+ var import_node_path3 = require("node:path");
46316
46541
  init_source();
46317
46542
  init_config();
46318
46543
  var POLL_INTERVAL_MS = 3e3;
@@ -46385,14 +46610,14 @@ function registerExecCommand(program3) {
46385
46610
  "exec",
46386
46611
  async (resourceId, options) => {
46387
46612
  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) : {};
46613
+ const input = resolvedInputFile ? JSON.parse((0, import_node_fs2.readFileSync)(resolvedInputFile, "utf8")) : options.input ? JSON.parse(options.input) : {};
46389
46614
  const apiUrl = resolveApiUrl(options.apiUrl);
46390
46615
  const maybeCleanupInput = () => {
46391
46616
  if (!options.cleanupInput || !resolvedInputFile) return;
46392
- const tmpDir = (0, import_node_path.join)(getProjectRoot(), "tmp");
46617
+ const tmpDir = (0, import_node_path3.join)(getProjectRoot(), "tmp");
46393
46618
  if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
46394
46619
  try {
46395
- (0, import_node_fs.unlinkSync)(resolvedInputFile);
46620
+ (0, import_node_fs2.unlinkSync)(resolvedInputFile);
46396
46621
  } catch {
46397
46622
  }
46398
46623
  } else {
@@ -49057,11 +49282,11 @@ function bullet(items) {
49057
49282
  function field(label, value) {
49058
49283
  return value === void 0 || value === null || value === "" ? "" : `${label}: ${value}`;
49059
49284
  }
49060
- function join3(parts) {
49285
+ function join5(parts) {
49061
49286
  return parts.filter((p) => p.length > 0).join("\n\n");
49062
49287
  }
49063
49288
  function formatSystemDescribe(r) {
49064
- const header = join3([
49289
+ const header = join5([
49065
49290
  `System: ${r.id}`,
49066
49291
  [
49067
49292
  field("Label", r.label),
@@ -49090,10 +49315,10 @@ ${resourceLines.join("\n")}`;
49090
49315
  const ontologyEntries = Object.entries(r.ontologyCountsByKind);
49091
49316
  const ontologySection = ontologyEntries.length ? `Ontology: ${ontologyEntries.map(([k, n]) => `${k}s: ${n}`).join(", ")}` : "";
49092
49317
  const childSection = section("Subsystems", bullet(r.childSystemPaths));
49093
- return join3([header, govSection, resourceSection, ontologySection, childSection]);
49318
+ return join5([header, govSection, resourceSection, ontologySection, childSection]);
49094
49319
  }
49095
49320
  function formatResourceDescribe(r) {
49096
- const header = join3([
49321
+ const header = join5([
49097
49322
  `Resource: ${r.id}`,
49098
49323
  [
49099
49324
  field("Kind", r.resourceKind),
@@ -49117,10 +49342,10 @@ function formatResourceDescribe(r) {
49117
49342
  ${ontologyLines.join("\n")}` : "";
49118
49343
  const codeRefsSection = r.codeRefPaths.length ? `Code refs:
49119
49344
  ${bullet(r.codeRefPaths)}` : "";
49120
- return join3([header, ontologySection, codeRefsSection]);
49345
+ return join5([header, ontologySection, codeRefsSection]);
49121
49346
  }
49122
49347
  function formatKnowledgeDescribe(r) {
49123
- const header = join3([
49348
+ const header = join5([
49124
49349
  `Knowledge: ${r.id}`,
49125
49350
  [field("Kind", r.knowledgeKind), field("Title", r.title), field("Updated", r.updatedAt)].filter((s) => s.length > 0).join("\n"),
49126
49351
  r.summary ? `Summary: ${r.summary}` : ""
@@ -49130,28 +49355,28 @@ ${bullet(r.ownerIds)}` : "";
49130
49355
  const govSection = section("Governs", bullet(r.governs));
49131
49356
  const bodySection = `Body excerpt (${r.bodyLineCount} lines total \u2014 use knowledge:cat for full):
49132
49357
  ${r.bodyExcerpt}`;
49133
- return join3([header, ownerSection, govSection, bodySection]);
49358
+ return join5([header, ownerSection, govSection, bodySection]);
49134
49359
  }
49135
49360
  function formatOntologyDescribe(r) {
49136
- const header = join3([
49361
+ const header = join5([
49137
49362
  `Ontology: ${r.id}`,
49138
49363
  [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
49364
  r.description ? `Description: ${r.description}` : ""
49140
49365
  ]);
49141
49366
  const govSection = section("Governed by knowledge", bullet(r.governingKnowledgeIds));
49142
- return join3([header, govSection]);
49367
+ return join5([header, govSection]);
49143
49368
  }
49144
49369
  function formatRoleDescribe(r) {
49145
- const header = join3([
49370
+ const header = join5([
49146
49371
  `Role: ${r.id}`,
49147
49372
  [field("Title", r.title), field("Reports to", r.reportsToId)].filter((s) => s.length > 0).join("\n")
49148
49373
  ]);
49149
49374
  const respSection = section("Responsibilities", bullet(r.responsibilities));
49150
49375
  const responsibleForSection = section("Responsible for systems", bullet(r.responsibleFor));
49151
- return join3([header, respSection, responsibleForSection]);
49376
+ return join5([header, respSection, responsibleForSection]);
49152
49377
  }
49153
49378
  function formatPolicyDescribe(r) {
49154
- const header = join3([
49379
+ const header = join5([
49155
49380
  `Policy: ${r.id}`,
49156
49381
  [field("Label", r.label), field("Trigger", r.triggerKind)].filter((s) => s.length > 0).join("\n"),
49157
49382
  r.description ? `Description: ${r.description}` : ""
@@ -49164,7 +49389,7 @@ function formatPolicyDescribe(r) {
49164
49389
  if (r.appliesToRoleIds.length) appliesLines.push(` roles: ${r.appliesToRoleIds.join(", ")}`);
49165
49390
  const appliesSection = appliesLines.length ? `Applies to:
49166
49391
  ${appliesLines.join("\n")}` : "";
49167
- return join3([header, effectSection, appliesSection]);
49392
+ return join5([header, effectSection, appliesSection]);
49168
49393
  }
49169
49394
 
49170
49395
  // src/cli/commands/knowledge/ls.ts
@@ -49564,12 +49789,12 @@ function registerKnowledgeSkills(program3) {
49564
49789
  }
49565
49790
 
49566
49791
  // src/cli/commands/knowledge/generate.ts
49567
- var import_node_fs3 = require("node:fs");
49568
- var import_node_path3 = require("node:path");
49792
+ var import_node_fs4 = require("node:fs");
49793
+ var import_node_path5 = require("node:path");
49569
49794
 
49570
49795
  // src/knowledge-codegen.ts
49571
- var import_node_fs2 = require("node:fs");
49572
- var import_node_path2 = require("node:path");
49796
+ var import_node_fs3 = require("node:fs");
49797
+ var import_node_path4 = require("node:path");
49573
49798
  function targetFromNodeId2(nodeId2) {
49574
49799
  const [kind, ...idParts] = nodeId2.split(":");
49575
49800
  return {
@@ -49587,10 +49812,10 @@ function canonicalizeKnowledgeNodeLinks(node) {
49587
49812
  };
49588
49813
  }
49589
49814
  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);
49815
+ return (0, import_node_fs3.readdirSync)(directory, { withFileTypes: true }).flatMap((entry) => {
49816
+ const path3 = (0, import_node_path4.join)(directory, entry.name);
49592
49817
  if (entry.isDirectory()) return listMdxFiles(path3);
49593
- return entry.isFile() && (0, import_node_path2.extname)(entry.name) === ".mdx" ? [path3] : [];
49818
+ return entry.isFile() && (0, import_node_path4.extname)(entry.name) === ".mdx" ? [path3] : [];
49594
49819
  });
49595
49820
  }
49596
49821
  function parseScalar(value) {
@@ -49785,7 +50010,7 @@ function readCommandForNode(node, cliCommand = "elevasis") {
49785
50010
  ];
49786
50011
  }
49787
50012
  function readKnowledgeNodeMdx(filePath) {
49788
- const raw = (0, import_node_fs2.readFileSync)(filePath, "utf8");
50013
+ const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8");
49789
50014
  const { frontmatter, body } = parseFrontmatter(raw, filePath);
49790
50015
  return {
49791
50016
  id: assertString(frontmatter, "id", filePath),
@@ -49883,25 +50108,25 @@ function generateKnowledgeNodesTs(options) {
49883
50108
  }
49884
50109
  function generateKnowledgeNodes(options) {
49885
50110
  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))
50111
+ (a, b) => (0, import_node_path4.relative)(options.sourceDir, a).localeCompare((0, import_node_path4.relative)(options.sourceDir, b))
49887
50112
  );
49888
50113
  const nodes = files.map((file2) => {
49889
- const relativePath = (0, import_node_path2.relative)(options.sourceDir, file2);
50114
+ const relativePath = (0, import_node_path4.relative)(options.sourceDir, file2);
49890
50115
  return {
49891
50116
  ...readKnowledgeNodeMdx(file2),
49892
50117
  sourceFilePath: toSourceFilePath(options.sourceLabel, relativePath)
49893
50118
  };
49894
50119
  });
49895
50120
  const sourcePaths = Object.fromEntries(
49896
- files.map((file2, index) => [nodes[index].id, toRegistryPath((0, import_node_path2.relative)(options.sourceDir, file2))])
50121
+ files.map((file2, index) => [nodes[index].id, toRegistryPath((0, import_node_path4.relative)(options.sourceDir, file2))])
49897
50122
  );
49898
50123
  const ids = /* @__PURE__ */ new Set();
49899
50124
  for (const node of nodes) {
49900
50125
  if (ids.has(node.id)) throw new Error(`[knowledge-node-codegen] Duplicate knowledge node id: ${node.id}`);
49901
50126
  ids.add(node.id);
49902
50127
  }
49903
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(options.outputPath), { recursive: true });
49904
- (0, import_node_fs2.writeFileSync)(
50128
+ (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(options.outputPath), { recursive: true });
50129
+ (0, import_node_fs3.writeFileSync)(
49905
50130
  options.outputPath,
49906
50131
  generateKnowledgeNodesTs({
49907
50132
  nodes,
@@ -49912,8 +50137,8 @@ function generateKnowledgeNodes(options) {
49912
50137
  "utf8"
49913
50138
  );
49914
50139
  if (options.knowledgeFlagsOutputPath) {
49915
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(options.knowledgeFlagsOutputPath), { recursive: true });
49916
- (0, import_node_fs2.writeFileSync)(
50140
+ (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(options.knowledgeFlagsOutputPath), { recursive: true });
50141
+ (0, import_node_fs3.writeFileSync)(
49917
50142
  options.knowledgeFlagsOutputPath,
49918
50143
  `${JSON.stringify(
49919
50144
  generateKnowledgeFlagRegistry(nodes, sourcePaths, {
@@ -49945,13 +50170,13 @@ function registerKnowledgeGenerate(program3) {
49945
50170
  ).action(
49946
50171
  wrapAction("knowledge:generate", async (options) => {
49947
50172
  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)(
50173
+ const sourceDir = (0, import_node_path5.resolve)(projectRoot, options.source ?? "core/config/knowledge/nodes");
50174
+ const outputPath = (0, import_node_path5.resolve)(projectRoot, options.output ?? "core/config/knowledge/_generated/nodes.ts");
50175
+ const knowledgeFlagsOutputPath = (0, import_node_path5.resolve)(
49951
50176
  projectRoot,
49952
50177
  options.flagsOutput ?? ".claude/registries/knowledge-flags.json"
49953
50178
  );
49954
- if (!(0, import_node_fs3.existsSync)(sourceDir)) {
50179
+ if (!(0, import_node_fs4.existsSync)(sourceDir)) {
49955
50180
  process.stderr.write(`knowledge:generate: source directory not found: ${sourceDir}
49956
50181
  `);
49957
50182
  process.exitCode = 1;
@@ -50063,8 +50288,8 @@ function registerKnowledgeCommands(program3) {
50063
50288
  }
50064
50289
 
50065
50290
  // src/cli/commands/request/request.ts
50066
- var import_node_fs4 = require("node:fs");
50067
- var import_node_path4 = require("node:path");
50291
+ var import_node_fs5 = require("node:fs");
50292
+ var import_node_path6 = require("node:path");
50068
50293
  init_source();
50069
50294
  init_config();
50070
50295
 
@@ -50128,7 +50353,7 @@ function registerRequestCommands(program3) {
50128
50353
  throw new Error("Provide --input <json> or --input-file <path>");
50129
50354
  }
50130
50355
  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);
50356
+ const raw = resolvedInputFile ? JSON.parse((0, import_node_fs5.readFileSync)(resolvedInputFile, "utf8")) : JSON.parse(options.input);
50132
50357
  const parsed = CreateRequestInputSchema.safeParse(raw);
50133
50358
  if (!parsed.success) {
50134
50359
  const issues = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
@@ -50149,10 +50374,10 @@ ${issues}`);
50149
50374
  console.log(JSON.stringify(result, null, 2));
50150
50375
  }
50151
50376
  if (options.cleanupInput && resolvedInputFile) {
50152
- const tmpDir = (0, import_node_path4.join)(getProjectRoot(), "tmp");
50377
+ const tmpDir = (0, import_node_path6.join)(getProjectRoot(), "tmp");
50153
50378
  if (resolvedInputFile.startsWith(tmpDir + "/") || resolvedInputFile.startsWith(tmpDir + "\\")) {
50154
50379
  try {
50155
- (0, import_node_fs4.unlinkSync)(resolvedInputFile);
50380
+ (0, import_node_fs5.unlinkSync)(resolvedInputFile);
50156
50381
  } catch {
50157
50382
  }
50158
50383
  } else {
@@ -50221,8 +50446,8 @@ ${rows.length} request${rows.length === 1 ? "" : "s"}`));
50221
50446
 
50222
50447
  // src/cli/commands/ui/ui-switcher.ts
50223
50448
  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);
50449
+ var import_node_fs6 = __toESM(require("node:fs"), 1);
50450
+ var import_node_path7 = __toESM(require("node:path"), 1);
50226
50451
  init_config();
50227
50452
  function run(command, args, cwd) {
50228
50453
  (0, import_node_child_process.execFileSync)(command, args, {
@@ -50232,10 +50457,10 @@ function run(command, args, cwd) {
50232
50457
  });
50233
50458
  }
50234
50459
  function readJson(filePath) {
50235
- return JSON.parse(import_node_fs5.default.readFileSync(filePath, "utf8"));
50460
+ return JSON.parse(import_node_fs6.default.readFileSync(filePath, "utf8"));
50236
50461
  }
50237
50462
  function writeJson(filePath, value) {
50238
- import_node_fs5.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
50463
+ import_node_fs6.default.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
50239
50464
  `);
50240
50465
  }
50241
50466
  function requireDependencies(packageJson, filePath) {
@@ -50245,8 +50470,8 @@ function requireDependencies(packageJson, filePath) {
50245
50470
  return packageJson.dependencies;
50246
50471
  }
50247
50472
  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()) {
50473
+ const resolved = import_node_path7.default.resolve(dir);
50474
+ if (!import_node_fs6.default.existsSync(resolved) || !import_node_fs6.default.statSync(resolved).isDirectory()) {
50250
50475
  throw new Error(`${label} not found: ${resolved}`);
50251
50476
  }
50252
50477
  return resolved;
@@ -50254,8 +50479,8 @@ function resolveExistingDir(label, dir) {
50254
50479
  function findRepoRootFromProject(projectRoot) {
50255
50480
  let dir = projectRoot;
50256
50481
  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);
50482
+ if (import_node_fs6.default.existsSync(import_node_path7.default.join(dir, "packages", "ui", "package.json"))) return dir;
50483
+ const parent = import_node_path7.default.dirname(dir);
50259
50484
  if (parent === dir) return null;
50260
50485
  dir = parent;
50261
50486
  }
@@ -50268,13 +50493,13 @@ function resolveUiPackageRoot(projectRoot, explicitRoot) {
50268
50493
  "Could not find packages/ui from this Elevasis project. Pass --ui-package-root <path> from a monorepo checkout."
50269
50494
  );
50270
50495
  }
50271
- return import_node_path5.default.join(repoRoot, "packages", "ui");
50496
+ return import_node_path7.default.join(repoRoot, "packages", "ui");
50272
50497
  }
50273
50498
  function removeLocalUiTarballs(templateTmpDir) {
50274
- if (!import_node_fs5.default.existsSync(templateTmpDir)) return;
50275
- for (const entry of import_node_fs5.default.readdirSync(templateTmpDir)) {
50499
+ if (!import_node_fs6.default.existsSync(templateTmpDir)) return;
50500
+ for (const entry of import_node_fs6.default.readdirSync(templateTmpDir)) {
50276
50501
  if (entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz")) {
50277
- import_node_fs5.default.rmSync(import_node_path5.default.join(templateTmpDir, entry), { force: true });
50502
+ import_node_fs6.default.rmSync(import_node_path7.default.join(templateTmpDir, entry), { force: true });
50278
50503
  }
50279
50504
  }
50280
50505
  }
@@ -50294,29 +50519,29 @@ function useLocalUi(options = {}) {
50294
50519
  const projectRoot = getProjectRoot();
50295
50520
  const repoRoot = findRepoRootFromProject(projectRoot);
50296
50521
  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)) {
50522
+ const commandRoot = repoRoot ?? import_node_path7.default.dirname(import_node_path7.default.dirname(uiPackageRoot));
50523
+ const templateUiPackageJsonPath = import_node_path7.default.join(projectRoot, "ui", "package.json");
50524
+ const templateTmpDir = import_node_path7.default.join(projectRoot, "tmp");
50525
+ const uiPackageJsonPath = import_node_path7.default.join(uiPackageRoot, "package.json");
50526
+ const uiPackageBackupPath = import_node_path7.default.join(uiPackageRoot, "package.json.local-pack.bak");
50527
+ if (!import_node_fs6.default.existsSync(templateUiPackageJsonPath)) {
50303
50528
  throw new Error(`Template UI package.json not found: ${templateUiPackageJsonPath}`);
50304
50529
  }
50305
- import_node_fs5.default.mkdirSync(templateTmpDir, { recursive: true });
50530
+ import_node_fs6.default.mkdirSync(templateTmpDir, { recursive: true });
50306
50531
  removeLocalUiTarballs(templateTmpDir);
50307
50532
  run("pnpm", ["--filter", "@repo/ui", "build:publish"], commandRoot);
50308
50533
  try {
50309
- const raw = import_node_fs5.default.readFileSync(uiPackageJsonPath, "utf8");
50310
- import_node_fs5.default.writeFileSync(uiPackageBackupPath, raw);
50534
+ const raw = import_node_fs6.default.readFileSync(uiPackageJsonPath, "utf8");
50535
+ import_node_fs6.default.writeFileSync(uiPackageBackupPath, raw);
50311
50536
  writeJson(uiPackageJsonPath, prepareUiPackageForPack(JSON.parse(raw)));
50312
50537
  run("pnpm", ["-C", uiPackageRoot, "pack", "--pack-destination", templateTmpDir], commandRoot);
50313
50538
  } 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 });
50539
+ if (import_node_fs6.default.existsSync(uiPackageBackupPath)) {
50540
+ import_node_fs6.default.copyFileSync(uiPackageBackupPath, uiPackageJsonPath);
50541
+ import_node_fs6.default.rmSync(uiPackageBackupPath, { force: true });
50317
50542
  }
50318
50543
  }
50319
- const tarballName = import_node_fs5.default.readdirSync(templateTmpDir).find((entry) => entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz"));
50544
+ const tarballName = import_node_fs6.default.readdirSync(templateTmpDir).find((entry) => entry.startsWith("elevasis-ui-") && entry.endsWith(".tgz"));
50320
50545
  if (!tarballName) {
50321
50546
  throw new Error(`Failed to create local @elevasis/ui tarball in ${templateTmpDir}`);
50322
50547
  }
@@ -50324,20 +50549,20 @@ function useLocalUi(options = {}) {
50324
50549
  requireDependencies(templateUiPackageJson, templateUiPackageJsonPath)["@elevasis/ui"] = `file:../tmp/${tarballName}`;
50325
50550
  writeJson(templateUiPackageJsonPath, templateUiPackageJson);
50326
50551
  run("pnpm", ["-C", projectRoot, "install"], commandRoot);
50327
- console.log(`${import_node_path5.default.basename(projectRoot)}/ui now uses local @elevasis/ui tarball: ${tarballName}`);
50552
+ console.log(`${import_node_path7.default.basename(projectRoot)}/ui now uses local @elevasis/ui tarball: ${tarballName}`);
50328
50553
  }
50329
50554
  function usePublishedUi(options = {}) {
50330
50555
  const projectRoot = getProjectRoot();
50331
50556
  const repoRoot = findRepoRootFromProject(projectRoot);
50332
50557
  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");
50558
+ const templateUiPackageJsonPath = import_node_path7.default.join(projectRoot, "ui", "package.json");
50559
+ const templateTmpDir = import_node_path7.default.join(projectRoot, "tmp");
50335
50560
  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;
50561
+ const uiVersion = options.version ?? readJson(import_node_path7.default.join(uiPackageRoot, "package.json")).version;
50337
50562
  if (!uiVersion) {
50338
50563
  throw new Error("Could not determine @elevasis/ui version. Pass --version <version>.");
50339
50564
  }
50340
- if (!import_node_fs5.default.existsSync(templateUiPackageJsonPath)) {
50565
+ if (!import_node_fs6.default.existsSync(templateUiPackageJsonPath)) {
50341
50566
  throw new Error(`Template UI package.json not found: ${templateUiPackageJsonPath}`);
50342
50567
  }
50343
50568
  const templateUiPackageJson = readJson(templateUiPackageJsonPath);
@@ -50345,7 +50570,7 @@ function usePublishedUi(options = {}) {
50345
50570
  writeJson(templateUiPackageJsonPath, templateUiPackageJson);
50346
50571
  removeLocalUiTarballs(templateTmpDir);
50347
50572
  run("pnpm", ["-C", projectRoot, "install"], commandRoot);
50348
- console.log(`${import_node_path5.default.basename(projectRoot)}/ui restored to published @elevasis/ui ^${uiVersion}`);
50573
+ console.log(`${import_node_path7.default.basename(projectRoot)}/ui restored to published @elevasis/ui ^${uiVersion}`);
50349
50574
  }
50350
50575
 
50351
50576
  // src/cli/commands/ui/ui.ts
@@ -50363,8 +50588,8 @@ function registerUiCommands(program3) {
50363
50588
  }
50364
50589
 
50365
50590
  // src/cli/commands/doctor.ts
50366
- var import_node_fs6 = require("node:fs");
50367
- var import_node_path6 = __toESM(require("node:path"), 1);
50591
+ var import_node_fs7 = require("node:fs");
50592
+ var import_node_path8 = __toESM(require("node:path"), 1);
50368
50593
  init_source();
50369
50594
  init_config();
50370
50595
  function ok(label, detail) {
@@ -50402,8 +50627,8 @@ function registerDoctorCommand(program3) {
50402
50627
  printSummary(failCount);
50403
50628
  process.exit(1);
50404
50629
  }
50405
- const envPath2 = import_node_path6.default.join(projectRoot, ".env");
50406
- const envExists = (0, import_node_fs6.existsSync)(envPath2);
50630
+ const envPath2 = import_node_path8.default.join(projectRoot, ".env");
50631
+ const envExists = (0, import_node_fs7.existsSync)(envPath2);
50407
50632
  if (!envExists) {
50408
50633
  fail(".env", `Not found at ${envPath2}. Create it from .env.example and fill in ELEVASIS_PLATFORM_KEY.`);
50409
50634
  if (isVerbose) verbose(`Checked: ${envPath2}`);
@@ -50490,101 +50715,6 @@ function printSummary(failCount) {
50490
50715
  }
50491
50716
  }
50492
50717
 
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
50718
  // src/cli/commands/cli/cli.ts
50589
50719
  var FORMATS = /* @__PURE__ */ new Set(["markdown", "json"]);
50590
50720
  function registerCliCatalogCommand(program3) {
@@ -51638,10 +51768,93 @@ function registerOmScaffoldCommands(program3) {
51638
51768
  });
51639
51769
  }
51640
51770
 
51771
+ // src/cli/commands/skill/skill-scaffold.ts
51772
+ init_source();
51773
+ function buildSkillMd(domain2) {
51774
+ const name = domain2.name;
51775
+ const commandNames = domain2.commands.map((c) => c.command.replace(`${name}:`, ""));
51776
+ const argumentHint = `[${commandNames.join(" | ")}] [args]`;
51777
+ const descriptionText = `${name} domain operations \u2014 ${commandNames.join(", ")} \u2014 via the elevasis-sdk ${name}:* CLI.`;
51778
+ const lines = [
51779
+ "---",
51780
+ `name: ${name}`,
51781
+ `description: "${descriptionText}"`,
51782
+ `argument-hint: "${argumentHint}"`,
51783
+ `allowed-tools: Bash, Read, Write, Edit, Glob, Grep`,
51784
+ "---",
51785
+ "",
51786
+ `# ${name.charAt(0).toUpperCase() + name.slice(1)} Skill`,
51787
+ "",
51788
+ `> **Generated stub.** Curate the prose below: add vibe integration, confirm ceremony,`,
51789
+ `> and any operation-level detail. The usage table is pre-filled from the CLI catalog.`,
51790
+ "",
51791
+ "## Usage",
51792
+ "",
51793
+ "| Command | Description | Options |",
51794
+ "| --- | --- | --- |"
51795
+ ];
51796
+ for (const cmd of domain2.commands) {
51797
+ const syntax = `\`elevasis-sdk ${cmd.syntax}\``;
51798
+ const description = cmd.description || "-";
51799
+ const options = cmd.options.length > 0 ? cmd.options.map((o) => `${o.required ? "required " : ""}\`${o.flags}\``).join(", ") : "-";
51800
+ lines.push(`| ${syntax} | ${description} | ${options} |`);
51801
+ }
51802
+ lines.push("");
51803
+ const commandsWithAliases = domain2.commands.filter((c) => c.aliases.length > 0);
51804
+ if (commandsWithAliases.length > 0) {
51805
+ lines.push("## Aliases", "");
51806
+ for (const cmd of commandsWithAliases) {
51807
+ for (const alias of cmd.aliases) {
51808
+ lines.push(`- \`elevasis-sdk ${alias}\` \u2192 \`elevasis-sdk ${cmd.syntax}\``);
51809
+ }
51810
+ }
51811
+ lines.push("");
51812
+ }
51813
+ lines.push(
51814
+ "## Connection",
51815
+ "",
51816
+ "```bash",
51817
+ "# .env (project root)",
51818
+ "ELEVASIS_PLATFORM_KEY=sk_...",
51819
+ "```",
51820
+ "",
51821
+ "```bash",
51822
+ `pnpm elevasis-sdk ${name}:<command> [args]`,
51823
+ "```",
51824
+ ""
51825
+ );
51826
+ return lines.join("\n");
51827
+ }
51828
+ function registerSkillScaffoldCommand(program3) {
51829
+ program3.command("skill:scaffold <domain>").description(
51830
+ "Emit a SKILL.md stub for a CLI domain from the catalog\n Example: elevasis-sdk skill:scaffold client"
51831
+ ).option("--output", "Write the stub to stdout only (default behavior)").action(
51832
+ wrapAction("skill:scaffold", async (domain2) => {
51833
+ const catalog = buildCliCatalogFromProgram(program3, { domain: domain2 });
51834
+ if (catalog.domains.length === 0) {
51835
+ const fullCatalog = buildCliCatalogFromProgram(program3);
51836
+ const known = knownDomains(fullCatalog);
51837
+ throw new Error(`No CLI domain "${domain2}" found. Known domains: ${known.join(", ")}`);
51838
+ }
51839
+ const domainEntry = catalog.domains[0];
51840
+ const stub = buildSkillMd(domainEntry);
51841
+ console.log(
51842
+ source_default.gray(
51843
+ `# SKILL.md stub for domain "${domain2}" (${domainEntry.commands.length} commands)
51844
+ # Copy this to: external/_template/.claude/skills/${domain2}/SKILL.md
51845
+ # Then curate: add vibe integration, confirm ceremony, and operation prose.
51846
+ `
51847
+ )
51848
+ );
51849
+ console.log(stub);
51850
+ })
51851
+ );
51852
+ }
51853
+
51641
51854
  // src/cli/index.ts
51642
51855
  init_config();
51643
51856
  var PREFLIGHT_SKIP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
51644
- var PREFLIGHT_SKIP_COMMANDS = /* @__PURE__ */ new Set(["cli"]);
51857
+ var PREFLIGHT_SKIP_COMMANDS = /* @__PURE__ */ new Set(["cli", "skill:scaffold"]);
51645
51858
  var LOCAL_PROJECT_COMMANDS = /* @__PURE__ */ new Set([
51646
51859
  "ui:use-local",
51647
51860
  "ui:use-published",
@@ -51771,6 +51984,8 @@ registerUiCommands(program2);
51771
51984
  registerDoctorCommand(program2);
51772
51985
  registerCliCatalogCommand(program2);
51773
51986
  registerOmScaffoldCommands(program2);
51987
+ registerSkillScaffoldCommand(program2);
51988
+ registerSkillCheckCoverageCommand(program2);
51774
51989
  program2.parse();
51775
51990
  // Annotate the CommonJS export names for ESM import in node:
51776
51991
  0 && (module.exports = {