@skillsmith/cli 0.8.5 → 0.8.6

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.js CHANGED
@@ -782,7 +782,7 @@ var init_is_inside_container = __esm({
782
782
 
783
783
  // ../../node_modules/is-wsl/index.js
784
784
  import process4 from "node:process";
785
- import os6 from "node:os";
785
+ import os5 from "node:os";
786
786
  import fs14 from "node:fs";
787
787
  var isWsl, is_wsl_default;
788
788
  var init_is_wsl = __esm({
@@ -792,7 +792,7 @@ var init_is_wsl = __esm({
792
792
  if (process4.platform !== "linux") {
793
793
  return false;
794
794
  }
795
- if (os6.release().toLowerCase().includes("microsoft")) {
795
+ if (os5.release().toLowerCase().includes("microsoft")) {
796
796
  if (isInsideContainer()) {
797
797
  return false;
798
798
  }
@@ -1332,19 +1332,19 @@ var init_open = __esm({
1332
1332
  }
1333
1333
  const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
1334
1334
  if (options.wait) {
1335
- return new Promise((resolve19, reject) => {
1335
+ return new Promise((resolve20, reject) => {
1336
1336
  subprocess.once("error", reject);
1337
1337
  subprocess.once("close", (exitCode) => {
1338
1338
  if (!options.allowNonzeroExitCode && exitCode !== 0) {
1339
1339
  reject(new Error(`Exited with code ${exitCode}`));
1340
1340
  return;
1341
1341
  }
1342
- resolve19(subprocess);
1342
+ resolve20(subprocess);
1343
1343
  });
1344
1344
  });
1345
1345
  }
1346
1346
  if (isFallbackAttempt) {
1347
- return new Promise((resolve19, reject) => {
1347
+ return new Promise((resolve20, reject) => {
1348
1348
  subprocess.once("error", reject);
1349
1349
  subprocess.once("spawn", () => {
1350
1350
  subprocess.once("close", (exitCode) => {
@@ -1354,17 +1354,17 @@ var init_open = __esm({
1354
1354
  return;
1355
1355
  }
1356
1356
  subprocess.unref();
1357
- resolve19(subprocess);
1357
+ resolve20(subprocess);
1358
1358
  });
1359
1359
  });
1360
1360
  });
1361
1361
  }
1362
1362
  subprocess.unref();
1363
- return new Promise((resolve19, reject) => {
1363
+ return new Promise((resolve20, reject) => {
1364
1364
  subprocess.once("error", reject);
1365
1365
  subprocess.once("spawn", () => {
1366
1366
  subprocess.off("error", reject);
1367
- resolve19(subprocess);
1367
+ resolve20(subprocess);
1368
1368
  });
1369
1369
  });
1370
1370
  };
@@ -1452,7 +1452,7 @@ import { homedir as homedir8 } from "os";
1452
1452
  // ../core/dist/src/install/paths.js
1453
1453
  import { existsSync } from "node:fs";
1454
1454
  import { homedir } from "node:os";
1455
- import { join } from "node:path";
1455
+ import { isAbsolute, join, resolve } from "node:path";
1456
1456
  var CLIENT_NATIVE_PATHS = {
1457
1457
  "claude-code": join(homedir(), ".claude", "skills"),
1458
1458
  cursor: join(homedir(), ".cursor", "skills"),
@@ -1461,7 +1461,8 @@ var CLIENT_NATIVE_PATHS = {
1461
1461
  agents: join(homedir(), ".agents", "skills"),
1462
1462
  opencode: join(homedir(), ".config", "opencode", "skills"),
1463
1463
  hermes: join(homedir(), ".hermes", "skills"),
1464
- grok: join(homedir(), ".grok", "skills")
1464
+ grok: join(homedir(), ".grok", "skills"),
1465
+ antigravity: join(homedir(), ".gemini", "config", "skills")
1465
1466
  };
1466
1467
  var CANONICAL_CLIENT = "claude-code";
1467
1468
  var CLIENT_DISPLAY_LABELS = {
@@ -1472,7 +1473,8 @@ var CLIENT_DISPLAY_LABELS = {
1472
1473
  agents: "your agent",
1473
1474
  opencode: "OpenCode",
1474
1475
  hermes: "Hermes",
1475
- grok: "Grok Build"
1476
+ grok: "Grok Build",
1477
+ antigravity: "Antigravity"
1476
1478
  };
1477
1479
  var CLIENT_IDS = Object.freeze([
1478
1480
  "claude-code",
@@ -1482,7 +1484,8 @@ var CLIENT_IDS = Object.freeze([
1482
1484
  "agents",
1483
1485
  "opencode",
1484
1486
  "hermes",
1485
- "grok"
1487
+ "grok",
1488
+ "antigravity"
1486
1489
  ]);
1487
1490
  function getCanonicalInstallPath() {
1488
1491
  return CLIENT_NATIVE_PATHS[CANONICAL_CLIENT];
@@ -1515,6 +1518,108 @@ function enumerateHarnessPresence() {
1515
1518
  };
1516
1519
  });
1517
1520
  }
1521
+ var COMPANION_AGENT_TARGETS = {
1522
+ "claude-code": {
1523
+ dir: join(homedir(), ".claude", "agents"),
1524
+ fileMode: "flat",
1525
+ filenamePattern: "{name}-specialist.md"
1526
+ },
1527
+ cursor: {
1528
+ // AGENT_SHIM_TARGETS.cursor is null (no distinct value) — defaults like
1529
+ // every client with no independent evidence. See doc comment above.
1530
+ dir: join(homedir(), ".claude", "agents"),
1531
+ fileMode: "flat",
1532
+ filenamePattern: "{name}-specialist.md"
1533
+ },
1534
+ copilot: {
1535
+ // PR-review finding (BLOCKING): both dir AND filename are now cited
1536
+ // from AGENT_SHIM_TARGETS.copilot (agent-harness-targets.ts:156,
1537
+ // `skillsmith-agent.agent.md`) and shims.ts's own doc comment ("Copilot
1538
+ // `.agent.md` (Copilot cloud-agent + CLI surfaces, which do not read
1539
+ // `.claude/agents`)") -- this codebase already has independently
1540
+ // verified evidence that Copilot's real companion-agent format is
1541
+ // `<name>.agent.md`, not the generic `-specialist.md` suffix every
1542
+ // other client here defaults to. Writing plain `.md` risked producing
1543
+ // an undiscoverable companion file.
1544
+ dir: join(homedir(), ".copilot", "agents"),
1545
+ fileMode: "flat",
1546
+ filenamePattern: "{name}.agent.md"
1547
+ },
1548
+ windsurf: {
1549
+ // No AGENT_SHIM_TARGETS entry exists for windsurf (not a HarnessId
1550
+ // member) — defaults to today's actual behavior.
1551
+ dir: join(homedir(), ".claude", "agents"),
1552
+ fileMode: "flat",
1553
+ filenamePattern: "{name}-specialist.md"
1554
+ },
1555
+ agents: {
1556
+ // No AGENT_SHIM_TARGETS entry exists for `agents` (not a HarnessId
1557
+ // member) — defaults to today's actual behavior.
1558
+ dir: join(homedir(), ".claude", "agents"),
1559
+ fileMode: "flat",
1560
+ filenamePattern: "{name}-specialist.md"
1561
+ },
1562
+ opencode: {
1563
+ // Directory cited from AGENT_SHIM_TARGETS.opencode (agent-harness-targets.ts)
1564
+ // as independent evidence of OpenCode's own agents-dir convention.
1565
+ // Filename pattern is this map's own naming, not copied from that table.
1566
+ dir: join(homedir(), ".config", "opencode", "agents"),
1567
+ fileMode: "flat",
1568
+ filenamePattern: "{name}-specialist.md"
1569
+ },
1570
+ hermes: {
1571
+ // No AGENT_SHIM_TARGETS entry exists for hermes (not a HarnessId
1572
+ // member) — defaults to today's actual behavior.
1573
+ dir: join(homedir(), ".claude", "agents"),
1574
+ fileMode: "flat",
1575
+ filenamePattern: "{name}-specialist.md"
1576
+ },
1577
+ grok: {
1578
+ // No AGENT_SHIM_TARGETS entry exists for grok (not a HarnessId member)
1579
+ // — defaults to today's actual behavior.
1580
+ dir: join(homedir(), ".claude", "agents"),
1581
+ fileMode: "flat",
1582
+ filenamePattern: "{name}-specialist.md"
1583
+ },
1584
+ antigravity: {
1585
+ // SMI-5982 (Wave 6): directory-package mode, not flat — confirmed via a
1586
+ // live web search against antigravity.google/docs/cli/commands/agents
1587
+ // (2026-08-11): each agent is a directory `<name>/` containing a single
1588
+ // `agent.md` (YAML frontmatter: `name`, `description` only — no
1589
+ // `subagent:` field or equivalent exists in the real schema, confirming
1590
+ // the plan's decision NOT to emit one). `dir` is intentionally a
1591
+ // RELATIVE path (`.agents/agents`, resolved against the process's
1592
+ // invocation directory by Node's fs calls) — project-scoped, per Step 1
1593
+ // of the SMI-5982 plan: this CLI has no existing global-vs-project
1594
+ // install-mode distinction to hook into, so this defaults to
1595
+ // project-scoped rather than inventing scope-detection logic. Global
1596
+ // scope (`~/.gemini/config/agents/`) is an explicit fast-follow.
1597
+ dir: join(".agents", "agents"),
1598
+ fileMode: "directory-package",
1599
+ filenamePattern: "agent.md"
1600
+ }
1601
+ };
1602
+ function getCompanionAgentTarget(client = CANONICAL_CLIENT) {
1603
+ return COMPANION_AGENT_TARGETS[client];
1604
+ }
1605
+ function resolveCompanionAgentDir(client = CANONICAL_CLIENT) {
1606
+ return getCompanionAgentTarget(client).dir;
1607
+ }
1608
+ function resolveCompanionAgentPath(skillName, client = CANONICAL_CLIENT, baseDir) {
1609
+ const target = getCompanionAgentTarget(client);
1610
+ if (target.fileMode === "directory-package" && baseDir === void 0) {
1611
+ throw new Error(`resolveCompanionAgentPath: client "${client}" uses directory-package mode with a relative companion-agent directory, so an explicit baseDir is required \u2014 it cannot safely default to process.cwd() (a long-running MCP server's cwd does not track the calling client's real project; see SMI-5982 PR review).`);
1612
+ }
1613
+ const resolvedDir = isAbsolute(target.dir) ? target.dir : resolve(baseDir, target.dir);
1614
+ if (target.fileMode === "directory-package") {
1615
+ if (skillName === "" || skillName === "." || skillName === ".." || skillName.includes("/") || skillName.includes("\\")) {
1616
+ throw new Error(`Unsafe skill name for directory-package companion path: ${JSON.stringify(skillName)}`);
1617
+ }
1618
+ return join(resolvedDir, skillName, target.filenamePattern);
1619
+ }
1620
+ const filename = target.filenamePattern.replace("{name}", skillName);
1621
+ return join(resolvedDir, filename);
1622
+ }
1518
1623
 
1519
1624
  // ../core/dist/src/install/fan-out.js
1520
1625
  import { homedir as homedir2 } from "node:os";
@@ -2700,12 +2805,12 @@ var AGENT_TOOL_PROFILE_NAMES = [
2700
2805
 
2701
2806
  // ../core/dist/src/install/agent-home-relocate.js
2702
2807
  import { homedir as homedir4 } from "node:os";
2703
- import { isAbsolute, join as join6, relative as relative2 } from "node:path";
2808
+ import { isAbsolute as isAbsolute2, join as join6, relative as relative2 } from "node:path";
2704
2809
  function relocateUnderHome(absolutePath, homeDir) {
2705
2810
  if (!homeDir)
2706
2811
  return absolutePath;
2707
2812
  const rel = relative2(homedir4(), absolutePath);
2708
- if (rel.startsWith("..") || isAbsolute(rel))
2813
+ if (rel.startsWith("..") || isAbsolute2(rel))
2709
2814
  return absolutePath;
2710
2815
  return join6(homeDir, rel);
2711
2816
  }
@@ -3694,7 +3799,7 @@ import { existsSync as existsSync10, readFileSync as readFileSync8, rmdirSync, u
3694
3799
 
3695
3800
  // ../core/dist/src/install/agent-manifest-path-guard.js
3696
3801
  import { homedir as homedir7 } from "node:os";
3697
- import { join as join16, relative as relative3, resolve as resolve2, sep } from "node:path";
3802
+ import { join as join16, relative as relative3, resolve as resolve3, sep } from "node:path";
3698
3803
  function computeAllowedPathSuffixes() {
3699
3804
  const suffixes = /* @__PURE__ */ new Set();
3700
3805
  const home2 = homedir7();
@@ -3728,7 +3833,7 @@ function allowedPathSuffixes() {
3728
3833
  return cachedSuffixes;
3729
3834
  }
3730
3835
  function isAllowedManifestEntryPath(path27) {
3731
- const normalized = resolve2(path27);
3836
+ const normalized = resolve3(path27);
3732
3837
  for (const suffix of allowedPathSuffixes()) {
3733
3838
  if (normalized.endsWith(sep + suffix) || normalized === suffix)
3734
3839
  return true;
@@ -3736,8 +3841,8 @@ function isAllowedManifestEntryPath(path27) {
3736
3841
  return false;
3737
3842
  }
3738
3843
  function isAllowedManifestBackupPath(backupPath) {
3739
- const backupsDir2 = resolve2(getAgentInstallBackupsDir());
3740
- const normalized = resolve2(backupPath);
3844
+ const backupsDir2 = resolve3(getAgentInstallBackupsDir());
3845
+ const normalized = resolve3(backupPath);
3741
3846
  return normalized === backupsDir2 || normalized.startsWith(backupsDir2 + sep);
3742
3847
  }
3743
3848
 
@@ -19985,7 +20090,7 @@ function validateUrl(url2) {
19985
20090
  }
19986
20091
 
19987
20092
  // ../core/dist/src/validation/path-validators.js
19988
- import { resolve as resolve3 } from "path";
20093
+ import { resolve as resolve4 } from "path";
19989
20094
  function validatePath(path27, rootDir) {
19990
20095
  if (!path27) {
19991
20096
  throw new ValidationError("Path cannot be empty", "EMPTY_PATH");
@@ -19993,8 +20098,8 @@ function validatePath(path27, rootDir) {
19993
20098
  if (!rootDir) {
19994
20099
  throw new ValidationError("Root directory cannot be empty", "EMPTY_ROOT_DIR");
19995
20100
  }
19996
- const normalizedPath = resolve3(rootDir, path27);
19997
- const normalizedRoot = resolve3(rootDir);
20101
+ const normalizedPath = resolve4(rootDir, path27);
20102
+ const normalizedRoot = resolve4(rootDir);
19998
20103
  const isWithinRoot = normalizedPath.startsWith(normalizedRoot + "/") || normalizedPath === normalizedRoot;
19999
20104
  if (!isWithinRoot) {
20000
20105
  throw new ValidationError(`Path traversal detected: ${path27}`, "PATH_TRAVERSAL", {
@@ -22016,12 +22121,12 @@ var logger3 = createLogger("Sanitization");
22016
22121
 
22017
22122
  // ../core/dist/src/security/pathValidation.js
22018
22123
  init_logger();
22019
- import { resolve as resolve4, normalize, dirname as dirname10, isAbsolute as isAbsolute2 } from "path";
22124
+ import { resolve as resolve5, normalize, dirname as dirname10, isAbsolute as isAbsolute3 } from "path";
22020
22125
  import { homedir as homedir9 } from "os";
22021
22126
  var logger4 = createLogger("PathValidation");
22022
22127
  var DEFAULT_ALLOWED_DIRS = [
22023
- resolve4(homedir9(), ".skillsmith"),
22024
- resolve4(homedir9(), ".claude")
22128
+ resolve5(homedir9(), ".skillsmith"),
22129
+ resolve5(homedir9(), ".claude")
22025
22130
  ];
22026
22131
  var TEMP_DIRS = ["/tmp", "/var/tmp", "/private/tmp", process.env.TMPDIR].filter(Boolean);
22027
22132
 
@@ -22407,7 +22512,7 @@ var QueueManager = class {
22407
22512
  onMetricsUpdate(false);
22408
22513
  throw new RateLimitQueueFullError(key, this.config.maxQueueSize);
22409
22514
  }
22410
- return new Promise((resolve19, reject) => {
22515
+ return new Promise((resolve20, reject) => {
22411
22516
  const requestId = randomUUID();
22412
22517
  const queuedAt = Date.now();
22413
22518
  const timeoutHandle = setTimeout(() => {
@@ -22421,7 +22526,7 @@ var QueueManager = class {
22421
22526
  }, this.config.queueTimeoutMs);
22422
22527
  const request = {
22423
22528
  id: requestId,
22424
- resolve: resolve19,
22529
+ resolve: resolve20,
22425
22530
  reject,
22426
22531
  cost,
22427
22532
  queuedAt,
@@ -22861,7 +22966,7 @@ function calculateDelay(attempt, initialDelayMs, maxDelayMs, backoffMultiplier,
22861
22966
  return delay;
22862
22967
  }
22863
22968
  function sleep2(ms) {
22864
- return new Promise((resolve19) => setTimeout(resolve19, ms));
22969
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
22865
22970
  }
22866
22971
  async function withRetry(fn, config2 = {}) {
22867
22972
  const { maxRetries = DEFAULT_RETRY_CONFIG.maxRetries, initialDelayMs = DEFAULT_RETRY_CONFIG.initialDelayMs, maxDelayMs = DEFAULT_RETRY_CONFIG.maxDelayMs, backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier, jitter = DEFAULT_RETRY_CONFIG.jitter, isRetryable = isTransientError, onRetry } = config2;
@@ -23163,7 +23268,7 @@ var BaseSourceAdapter = class {
23163
23268
  * Delay helper
23164
23269
  */
23165
23270
  delay(ms) {
23166
- return new Promise((resolve19) => setTimeout(resolve19, ms));
23271
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
23167
23272
  }
23168
23273
  /**
23169
23274
  * Validate configuration
@@ -23188,7 +23293,7 @@ var log4 = createLogger("RawUrlAdapter");
23188
23293
  // ../core/dist/src/sources/LocalFilesystemAdapter.js
23189
23294
  init_logger();
23190
23295
  import { createHash as createHash2 } from "crypto";
23191
- import { basename as basename2, dirname as dirname12, resolve as resolve5, join as join19 } from "path";
23296
+ import { basename as basename2, dirname as dirname12, resolve as resolve6, join as join19 } from "path";
23192
23297
 
23193
23298
  // ../core/dist/src/sources/LocalFilesystemAdapter.helpers.js
23194
23299
  import { promises as fs2 } from "fs";
@@ -23590,7 +23695,7 @@ var LocalFilesystemAdapter = class extends BaseSourceAdapter {
23590
23695
  throw new Error("Invalid location: must specify path or repo");
23591
23696
  }
23592
23697
  validatePath(resolvedPath, this.rootDir);
23593
- const absolutePath = resolve5(resolvedPath);
23698
+ const absolutePath = resolve6(resolvedPath);
23594
23699
  const realResult = await resolveSafeRealpath(absolutePath, this.rootDir, {
23595
23700
  allowSymlinksOutsideRoot: this.allowSymlinksOutsideRoot
23596
23701
  });
@@ -24198,7 +24303,7 @@ function isBetterSqlite3Available() {
24198
24303
 
24199
24304
  // ../core/dist/src/db/drivers/sqljsDriver.js
24200
24305
  import { createRequire as createRequire2 } from "node:module";
24201
- import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "node:fs";
24306
+ import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync10, renameSync as renameSync3, unlinkSync as unlinkSync3 } from "node:fs";
24202
24307
 
24203
24308
  // ../core/dist/src/db/drivers/corruption.js
24204
24309
  import { existsSync as existsSync12, renameSync as renameSync2 } from "node:fs";
@@ -24420,12 +24525,31 @@ var SqlJsDatabaseAdapter = class {
24420
24525
  }
24421
24526
  /**
24422
24527
  * Persist the in-memory database to file
24528
+ *
24529
+ * SMI-5997: writes atomically (temp file + rename) rather than a direct
24530
+ * writeFileSync to filePath. A direct write truncates the target file
24531
+ * before the new bytes land; a process kill/crash mid-write (OOM, SIGKILL,
24532
+ * machine sleep) during that window leaves a 0-byte file on disk, which
24533
+ * openDatabaseAsync() then silently misclassifies as a fresh/legacy import
24534
+ * instead of a corrupt file — see schema.ts. rename() is atomic on the
24535
+ * same filesystem, so the target is only ever fully-old or fully-new.
24423
24536
  */
24424
24537
  persist() {
24425
24538
  if (this._memory || !this.filePath)
24426
24539
  return;
24427
24540
  const data = this.db.export();
24428
- writeFileSync10(this.filePath, Buffer.from(data));
24541
+ const tmpPath = `${this.filePath}.tmp`;
24542
+ try {
24543
+ writeFileSync10(tmpPath, Buffer.from(data));
24544
+ renameSync3(tmpPath, this.filePath);
24545
+ } catch (error46) {
24546
+ try {
24547
+ if (existsSync13(tmpPath))
24548
+ unlinkSync3(tmpPath);
24549
+ } catch {
24550
+ }
24551
+ throw error46;
24552
+ }
24429
24553
  }
24430
24554
  /**
24431
24555
  * Export the database as a Uint8Array
@@ -24642,7 +24766,7 @@ function findSimilarBruteForceFromMap(embeddings, queryEmbedding, topK) {
24642
24766
  }
24643
24767
 
24644
24768
  // ../core/dist/src/embeddings/hnsw-search.js
24645
- import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync11, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync11 } from "fs";
24769
+ import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync11, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "fs";
24646
24770
  import { dirname as dirname13, join as join21 } from "path";
24647
24771
  var cachedCtor = null;
24648
24772
  async function loadHnswCtor() {
@@ -24704,7 +24828,7 @@ function readLabels(labelsPath) {
24704
24828
  function writeAtomic(tmp, final, contents) {
24705
24829
  mkdirSync8(dirname13(tmp), { recursive: true });
24706
24830
  writeFileSync11(tmp, contents, typeof contents === "string" ? { encoding: "utf-8" } : void 0);
24707
- renameSync3(tmp, final);
24831
+ renameSync4(tmp, final);
24708
24832
  }
24709
24833
  async function loadOrBuildHnsw(args) {
24710
24834
  const Ctor = await loadHnswCtor();
@@ -24738,11 +24862,11 @@ async function loadOrBuildHnsw(args) {
24738
24862
  } catch (err) {
24739
24863
  try {
24740
24864
  if (existsSync14(paths.bin))
24741
- unlinkSync3(paths.bin);
24865
+ unlinkSync4(paths.bin);
24742
24866
  if (existsSync14(paths.meta))
24743
- unlinkSync3(paths.meta);
24867
+ unlinkSync4(paths.meta);
24744
24868
  if (existsSync14(paths.labels))
24745
- unlinkSync3(paths.labels);
24869
+ unlinkSync4(paths.labels);
24746
24870
  } catch {
24747
24871
  }
24748
24872
  try {
@@ -24805,7 +24929,7 @@ function createHandle(args) {
24805
24929
  return;
24806
24930
  }
24807
24931
  args.index.writeIndexSync(args.paths.binTmp);
24808
- renameSync3(args.paths.binTmp, args.paths.bin);
24932
+ renameSync4(args.paths.binTmp, args.paths.bin);
24809
24933
  const labelsArr = Array.from(args.labelToId.entries());
24810
24934
  writeAtomic(args.paths.labelsTmp, args.paths.labels, JSON.stringify(labelsArr));
24811
24935
  const meta3 = {
@@ -26298,18 +26422,18 @@ function getState(surface) {
26298
26422
  return state;
26299
26423
  }
26300
26424
  function closeStream(stream) {
26301
- return new Promise((resolve19) => {
26302
- const done = () => resolve19();
26425
+ return new Promise((resolve20) => {
26426
+ const done = () => resolve20();
26303
26427
  stream.once("error", done);
26304
26428
  stream.end(done);
26305
26429
  });
26306
26430
  }
26307
26431
  function openStream(filePath) {
26308
- return new Promise((resolve19, reject) => {
26432
+ return new Promise((resolve20, reject) => {
26309
26433
  const stream = createWriteStream(filePath, { flags: "a" });
26310
26434
  const onOpen = () => {
26311
26435
  cleanup();
26312
- resolve19(stream);
26436
+ resolve20(stream);
26313
26437
  };
26314
26438
  const onError = (err) => {
26315
26439
  cleanup();
@@ -26329,12 +26453,12 @@ function openStream(filePath) {
26329
26453
  });
26330
26454
  }
26331
26455
  function writeChunk(stream, buf) {
26332
- return new Promise((resolve19, reject) => {
26456
+ return new Promise((resolve20, reject) => {
26333
26457
  stream.write(buf, (err) => {
26334
26458
  if (err)
26335
26459
  reject(err);
26336
26460
  else
26337
- resolve19();
26461
+ resolve20();
26338
26462
  });
26339
26463
  });
26340
26464
  }
@@ -27420,10 +27544,10 @@ function addEnvironmentDeps(declared, result) {
27420
27544
  }
27421
27545
  }
27422
27546
  if (declared.environment.os) {
27423
- for (const os16 of declared.environment.os) {
27547
+ for (const os15 of declared.environment.os) {
27424
27548
  result.push({
27425
27549
  depType: "env_os",
27426
- depTarget: os16,
27550
+ depTarget: os15,
27427
27551
  depVersion: null,
27428
27552
  depSource: "declared",
27429
27553
  confidence: 1,
@@ -27483,7 +27607,6 @@ import { createHash as createHash7 } from "crypto";
27483
27607
  // ../core/dist/src/services/skill-installation.io.js
27484
27608
  import * as fs4 from "fs/promises";
27485
27609
  import * as path3 from "path";
27486
- import * as os2 from "os";
27487
27610
 
27488
27611
  // ../core/dist/src/utils/safe-fs.js
27489
27612
  import { open, lstat as lstat2, constants as constants2 } from "fs/promises";
@@ -27920,7 +28043,7 @@ async function mkdirNoFollow(baseDir, dir) {
27920
28043
  await ensureDirNoFollow(current);
27921
28044
  }
27922
28045
  }
27923
- async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, subSkillFiles, subagentContent) {
28046
+ async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, subSkillFiles, subagentContent, client = CANONICAL_CLIENT, companionBaseDir) {
27924
28047
  const writtenFiles = [];
27925
28048
  let subagentPath;
27926
28049
  const resolvedInstall = path3.resolve(installPath);
@@ -27952,9 +28075,9 @@ async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillCo
27952
28075
  }));
27953
28076
  }
27954
28077
  if (subagentContent) {
27955
- const agentsDir = path3.join(os2.homedir(), ".claude", "agents");
28078
+ subagentPath = resolveCompanionAgentPath(skillName, client, companionBaseDir);
28079
+ const agentsDir = path3.dirname(subagentPath);
27956
28080
  await fs4.mkdir(agentsDir, { recursive: true });
27957
- subagentPath = path3.join(agentsDir, skillName + "-specialist.md");
27958
28081
  await safeWriteFile(subagentPath, subagentContent);
27959
28082
  writtenFiles.push(subagentPath);
27960
28083
  }
@@ -27963,6 +28086,10 @@ async function writeInstallFiles(installPath, skillsDir, skillName, finalSkillCo
27963
28086
  await fs4.unlink(filePath).catch(() => {
27964
28087
  });
27965
28088
  }
28089
+ if (subagentPath && getCompanionAgentTarget(client).fileMode === "directory-package") {
28090
+ await fs4.rmdir(path3.dirname(subagentPath)).catch(() => {
28091
+ });
28092
+ }
27966
28093
  if (pathValidated) {
27967
28094
  await fs4.rm(installPath, { recursive: true, force: true }).catch(() => {
27968
28095
  });
@@ -28160,8 +28287,11 @@ async function performUninstall(params) {
28160
28287
  } catch {
28161
28288
  }
28162
28289
  onProgress("manifest", "Updating manifest");
28163
- delete manifestData.installedSkills[manifestKey];
28164
- await manifest.save(manifestData);
28290
+ await manifest.updateSafely((current) => {
28291
+ const next = { ...current, installedSkills: { ...current.installedSkills } };
28292
+ delete next.installedSkills[manifestKey];
28293
+ return next;
28294
+ });
28165
28295
  onProgress("done", "Uninstall complete");
28166
28296
  return {
28167
28297
  success: true,
@@ -28225,7 +28355,12 @@ var KNOWN_ERROR_PREFIXES = [
28225
28355
  "Refusing to write to symlink",
28226
28356
  "Refusing to write to hardlinked file",
28227
28357
  "Install path escapes skills directory",
28228
- "Cannot skip security scan"
28358
+ "Cannot skip security scan",
28359
+ // SMI-5982 PR-review follow-up: resolveCompanionAgentPath()'s required-baseDir guard
28360
+ // (install/paths.ts) — must surface verbatim so a directory-package-mode client (e.g.
28361
+ // a private-registry install with no per-call cwd input) fails closed with a
28362
+ // diagnosable message instead of the generic fallback below.
28363
+ "uses directory-package mode"
28229
28364
  ];
28230
28365
  function sanitizeInstallError(error46) {
28231
28366
  if (error46 instanceof Error) {
@@ -28238,7 +28373,7 @@ function sanitizeInstallError(error46) {
28238
28373
 
28239
28374
  // ../core/dist/src/services/skill-installation.service.js
28240
28375
  import * as path7 from "path";
28241
- import * as os3 from "os";
28376
+ import * as os2 from "os";
28242
28377
 
28243
28378
  // ../core/dist/src/services/skill-installation.types.js
28244
28379
  var TRUST_TIER_SCANNER_OPTIONS = {
@@ -28356,7 +28491,7 @@ function skillNameFromSkillId(skillId) {
28356
28491
  return name;
28357
28492
  }
28358
28493
  async function installFromContent(params) {
28359
- const { db, skillsDir, manifest, client, onProgress, skillId, version: version2, content, force = false } = params;
28494
+ const { db, skillsDir, manifest, client, onProgress, skillId, version: version2, content, force = false, companionBaseDir } = params;
28360
28495
  const skillName = skillNameFromSkillId(skillId);
28361
28496
  const trustTier = CONTENT_INSTALL_TRUST_TIER;
28362
28497
  if (skillName === null) {
@@ -28433,7 +28568,7 @@ async function installFromContent(params) {
28433
28568
  const teamAuthoredSubFiles = Object.entries(content).filter(([filename]) => filename !== "SKILL.md").map(([filename, fileContent]) => ({ filename, content: fileContent }));
28434
28569
  const generatedNoCollision = subSkillFiles.filter((generated) => !teamAuthoredSubFiles.some((team) => team.filename === generated.filename));
28435
28570
  onProgress("write", "Writing skill files");
28436
- const writeResult = await writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, [...generatedNoCollision, ...teamAuthoredSubFiles], subagentContent);
28571
+ const writeResult = await writeInstallFiles(installPath, skillsDir, skillName, finalSkillContent, [...generatedNoCollision, ...teamAuthoredSubFiles], subagentContent, client, companionBaseDir);
28437
28572
  if (writeResult.subagentPath) {
28438
28573
  optimizationInfo.subagentPath = writeResult.subagentPath;
28439
28574
  }
@@ -28506,6 +28641,7 @@ function collectTrendWarnings(params) {
28506
28641
  // ../core/dist/src/services/skill-manifest.js
28507
28642
  import * as fs6 from "fs/promises";
28508
28643
  import * as path6 from "path";
28644
+ import { randomUUID as randomUUID3 } from "node:crypto";
28509
28645
  var MANIFEST_LOCK_TIMEOUT_MS = 3e4;
28510
28646
  var MANIFEST_LOCK_RETRY_MS = 100;
28511
28647
  var ManifestManager = class {
@@ -28513,19 +28649,56 @@ var ManifestManager = class {
28513
28649
  constructor(manifestPath) {
28514
28650
  this.manifestPath = manifestPath;
28515
28651
  }
28652
+ /**
28653
+ * SMI-6007: distinguishes "no manifest yet" (ENOENT — legitimate first-run
28654
+ * case, safe to synthesize an empty manifest) from "a manifest file exists
28655
+ * but couldn't be read/parsed" (corrupt JSON, permission error, I/O
28656
+ * failure). The latter used to be silently swallowed into the same empty
28657
+ * manifest, which is a real data-loss risk: a caller that then `save()`s
28658
+ * that empty snapshot back out would erase every previously-recorded
28659
+ * install. Now it throws loudly instead, so a corrupt manifest surfaces as
28660
+ * an error rather than silently wiping state on the next write.
28661
+ */
28516
28662
  async load() {
28663
+ let content;
28664
+ try {
28665
+ content = await fs6.readFile(this.manifestPath, "utf-8");
28666
+ } catch (error46) {
28667
+ if (error46.code === "ENOENT") {
28668
+ return { version: "1.0.0", installedSkills: {} };
28669
+ }
28670
+ throw error46;
28671
+ }
28517
28672
  try {
28518
- const content = await fs6.readFile(this.manifestPath, "utf-8");
28519
28673
  return JSON.parse(content);
28520
- } catch {
28521
- return { version: "1.0.0", installedSkills: {} };
28674
+ } catch (error46) {
28675
+ throw new Error("Manifest file at " + this.manifestPath + " exists but is corrupt/unparseable: " + (error46 instanceof Error ? error46.message : String(error46)));
28522
28676
  }
28523
28677
  }
28678
+ /**
28679
+ * SMI-6007: the temp filename now includes a `randomUUID()` suffix (not
28680
+ * just `process.pid`) — two concurrent `save()` calls in the same process
28681
+ * previously collided on an identical `.tmp.<pid>` path, letting one
28682
+ * call's temp file win the write while the other's `rename()` either
28683
+ * clobbered it mid-flight or failed outright. Each call now owns a
28684
+ * uniquely-named temp file for its own lifetime. The write+rename is
28685
+ * wrapped in try/catch so a failure best-effort removes only *this
28686
+ * invocation's* temp file before rethrowing the original error (mirrors
28687
+ * `sqljsDriver.ts`'s `persist()`, SMI-5997) — the error is never swallowed.
28688
+ */
28524
28689
  async save(manifest) {
28525
28690
  await fs6.mkdir(path6.dirname(this.manifestPath), { recursive: true });
28526
- const tempPath = this.manifestPath + ".tmp." + process.pid;
28527
- await fs6.writeFile(tempPath, JSON.stringify(manifest, null, 2));
28528
- await fs6.rename(tempPath, this.manifestPath);
28691
+ const tempPath = this.manifestPath + ".tmp." + process.pid + "." + randomUUID3();
28692
+ try {
28693
+ await fs6.writeFile(tempPath, JSON.stringify(manifest, null, 2));
28694
+ await fs6.rename(tempPath, this.manifestPath);
28695
+ } catch (error46) {
28696
+ try {
28697
+ await fs6.unlink(tempPath);
28698
+ } catch {
28699
+ }
28700
+ throw error46;
28701
+ }
28529
28702
  }
28530
28703
  async acquireLock() {
28531
28704
  const lockPath = this.manifestPath + ".lock";
@@ -28547,7 +28720,7 @@ var ManifestManager = class {
28547
28720
  } catch {
28548
28721
  continue;
28549
28722
  }
28550
- await new Promise((resolve19) => setTimeout(resolve19, MANIFEST_LOCK_RETRY_MS));
28723
+ await new Promise((resolve20) => setTimeout(resolve20, MANIFEST_LOCK_RETRY_MS));
28551
28724
  } else {
28552
28725
  throw error46;
28553
28726
  }
@@ -28574,8 +28747,8 @@ var ManifestManager = class {
28574
28747
  };
28575
28748
 
28576
28749
  // ../core/dist/src/services/skill-installation.service.js
28577
- var DEFAULT_SKILLS_DIR2 = path7.join(os3.homedir(), ".claude", "skills");
28578
- var DEFAULT_MANIFEST_PATH2 = path7.join(os3.homedir(), ".skillsmith", "manifest.json");
28750
+ var DEFAULT_SKILLS_DIR2 = path7.join(os2.homedir(), ".claude", "skills");
28751
+ var DEFAULT_MANIFEST_PATH2 = path7.join(os2.homedir(), ".skillsmith", "manifest.json");
28579
28752
  var SkillInstallationService = class {
28580
28753
  db;
28581
28754
  skillRepo;
@@ -28590,6 +28763,7 @@ var SkillInstallationService = class {
28590
28763
  riskHistoryRepo;
28591
28764
  aiDefenceFeedback;
28592
28765
  client;
28766
+ companionBaseDir;
28593
28767
  constructor(params) {
28594
28768
  this.db = params.db;
28595
28769
  this.skillRepo = params.skillRepo;
@@ -28605,6 +28779,7 @@ var SkillInstallationService = class {
28605
28779
  this.aiDefenceFeedback = params.aiDefenceFeedback;
28606
28780
  this.sessionInstalledSkillIds = params.sessionInstalledSkillIds ?? [];
28607
28781
  this.client = params.client ?? CANONICAL_CLIENT;
28782
+ this.companionBaseDir = params.companionBaseDir;
28608
28783
  }
28609
28784
  async install(skillId, options = {}) {
28610
28785
  let trustTier = "unknown";
@@ -28780,7 +28955,7 @@ var SkillInstallationService = class {
28780
28955
  }
28781
28956
  this.onProgress("write", "Writing skill files");
28782
28957
  const subSkillsNoCollision = subSkillFiles.filter((s) => !optionalFiles.filesToWrite.some((o) => o.filename === s.filename));
28783
- const writeResult = await writeInstallFiles(installPath, this.skillsDir, skillName, finalSkillContent, [...subSkillsNoCollision, ...optionalFiles.filesToWrite], subagentContent);
28958
+ const writeResult = await writeInstallFiles(installPath, this.skillsDir, skillName, finalSkillContent, [...subSkillsNoCollision, ...optionalFiles.filesToWrite], subagentContent, this.client, this.companionBaseDir);
28784
28959
  if (writeResult.subagentPath) {
28785
28960
  optimizationInfo.subagentPath = writeResult.subagentPath;
28786
28961
  }
@@ -28878,6 +29053,7 @@ var SkillInstallationService = class {
28878
29053
  skillsDir: this.skillsDir,
28879
29054
  manifest: this.manifest,
28880
29055
  client: this.client,
29056
+ companionBaseDir: this.companionBaseDir,
28881
29057
  onProgress: this.onProgress
28882
29058
  });
28883
29059
  }
@@ -28980,6 +29156,94 @@ function buildEmptyStackGuidance() {
28980
29156
  return "No technology stack could be derived for recommendations \u2014 this usually means a non-Node project, a stack with no production dependencies, or an unsupported language, not a backend or registry problem. Provide project context (a short description of the project or its tooling) or an explicit list of installed/currently-used skills, then try again.";
28981
29157
  }
28982
29158
 
29159
+ // ../core/dist/src/services/context-words.js
29160
+ var MAX_CONTEXT_WORDS = 5;
29161
+ var CONTEXT_STOPWORDS = /* @__PURE__ */ new Set([
29162
+ // 2-letter
29163
+ "an",
29164
+ "is",
29165
+ "it",
29166
+ "be",
29167
+ "to",
29168
+ "of",
29169
+ "in",
29170
+ "on",
29171
+ "at",
29172
+ "as",
29173
+ "or",
29174
+ "if",
29175
+ "so",
29176
+ "no",
29177
+ "do",
29178
+ "am",
29179
+ "we",
29180
+ "us",
29181
+ "he",
29182
+ "my",
29183
+ "up",
29184
+ // 3-letter
29185
+ "the",
29186
+ "and",
29187
+ "but",
29188
+ "not",
29189
+ "did",
29190
+ "has",
29191
+ "had",
29192
+ "she",
29193
+ "him",
29194
+ "her",
29195
+ "its",
29196
+ "our",
29197
+ "all",
29198
+ "few",
29199
+ "out",
29200
+ "off",
29201
+ "via",
29202
+ "per",
29203
+ "own",
29204
+ "too",
29205
+ "yet",
29206
+ "nor",
29207
+ "you",
29208
+ "are",
29209
+ "was",
29210
+ "for",
29211
+ "may",
29212
+ "who",
29213
+ "why",
29214
+ "how"
29215
+ // Code-review correction (SMI-5986): "any" (TS/SQL keyword), "let"
29216
+ // (JS/Rust keyword), and "can" (CAN-bus acronym) were removed from this
29217
+ // set — each is a real technical term this fix exists to stop dropping,
29218
+ // same class as "git"/"ci"/"aws"/"sql". Leaving them in would have
29219
+ // contradicted this list's own documented promise above.
29220
+ ]);
29221
+ function isKeepChar(ch) {
29222
+ return ch >= "a" && ch <= "z" || ch >= "0" && ch <= "9" || ch === "+" || ch === "#";
29223
+ }
29224
+ function hasAlphaNumeric(word) {
29225
+ for (let i = 0; i < word.length; i++) {
29226
+ const ch = word[i];
29227
+ if (ch >= "a" && ch <= "z" || ch >= "0" && ch <= "9")
29228
+ return true;
29229
+ }
29230
+ return false;
29231
+ }
29232
+ function stripEdgePunctuation(word) {
29233
+ let start = 0;
29234
+ while (start < word.length && !isKeepChar(word[start]))
29235
+ start++;
29236
+ let end = word.length;
29237
+ while (end > start && !isKeepChar(word[end - 1]))
29238
+ end--;
29239
+ return word.slice(start, end);
29240
+ }
29241
+ function extractContextWords(projectContext, maxWords = MAX_CONTEXT_WORDS) {
29242
+ if (!projectContext)
29243
+ return [];
29244
+ return projectContext.toLowerCase().split(/\s+/).map(stripEdgePunctuation).filter((word) => word.length >= 2 && hasAlphaNumeric(word) && !(word.length <= 3 && CONTEXT_STOPWORDS.has(word))).slice(0, maxWords);
29245
+ }
29246
+
28983
29247
  // ../core/dist/src/db/schema-sql.js
28984
29248
  var SCHEMA_SQL = `
28985
29249
  -- Enable WAL mode for better concurrent performance
@@ -29584,7 +29848,7 @@ function runMigrations(db) {
29584
29848
  throw error46;
29585
29849
  }
29586
29850
  }
29587
- db.prepare("INSERT INTO schema_version (version) VALUES (?)").run(migration.version);
29851
+ db.prepare("INSERT OR IGNORE INTO schema_version (version) VALUES (?)").run(migration.version);
29588
29852
  migrationsRun++;
29589
29853
  }
29590
29854
  }
@@ -29615,7 +29879,7 @@ function runMigrationsSafe(db) {
29615
29879
  throw error46;
29616
29880
  }
29617
29881
  }
29618
- db.prepare("INSERT INTO schema_version (version) VALUES (?)").run(migration.version);
29882
+ db.prepare("INSERT OR IGNORE INTO schema_version (version) VALUES (?)").run(migration.version);
29619
29883
  migrationsRun++;
29620
29884
  } catch (error46) {
29621
29885
  console.warn(`Migration ${migration.version} failed:`, error46);
@@ -29636,11 +29900,23 @@ function initializeSchema(db) {
29636
29900
  db.prepare("INSERT OR IGNORE INTO schema_version (version) VALUES (1)").run();
29637
29901
  runMigrations(db);
29638
29902
  }
29903
+ function assertLegacyImportHasTables(db, path27) {
29904
+ const tableCount = db.prepare("SELECT count(*) as count FROM sqlite_master WHERE type='table'").get();
29905
+ if (!tableCount || tableCount.count === 0) {
29906
+ throw new Error(`[Skillsmith] Database at ${path27} has no tables and no version metadata \u2014 it is empty or corrupt, not a legacy import.
29907
+ [skillsmith] Run this command in the repo root, then reconnect via /mcp:
29908
+
29909
+ mv "${path27}" "${path27}.corrupt-$(date +%s)"
29910
+
29911
+ [skillsmith] (a fresh database will be created automatically on next start)`);
29912
+ }
29913
+ }
29639
29914
  function openDatabase(path27) {
29640
29915
  const db = createDatabaseSync(path27);
29641
29916
  db.pragma("foreign_keys = ON");
29642
29917
  const hasSchemaVersion = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_version'").get();
29643
29918
  if (!hasSchemaVersion) {
29919
+ assertLegacyImportHasTables(db, path27);
29644
29920
  db.exec(`
29645
29921
  CREATE TABLE IF NOT EXISTS schema_version (
29646
29922
  version INTEGER PRIMARY KEY,
@@ -29654,7 +29930,7 @@ function openDatabase(path27) {
29654
29930
  }
29655
29931
 
29656
29932
  // ../core/dist/src/repositories/SkillRepository.js
29657
- import { randomUUID as randomUUID3 } from "crypto";
29933
+ import { randomUUID as randomUUID4 } from "crypto";
29658
29934
  var SkillRepository = class {
29659
29935
  db;
29660
29936
  constructor(db) {
@@ -29740,7 +30016,7 @@ var SkillRepository = class {
29740
30016
  * Create a new skill
29741
30017
  */
29742
30018
  create(input7) {
29743
- const id = input7.id || randomUUID3();
30019
+ const id = input7.id || randomUUID4();
29744
30020
  const tags = JSON.stringify(input7.tags || []);
29745
30021
  this.stmts.insert.run(
29746
30022
  id,
@@ -29771,7 +30047,7 @@ var SkillRepository = class {
29771
30047
  const insertMany = this.db.transaction((skills) => {
29772
30048
  const created = [];
29773
30049
  for (const input7 of skills) {
29774
- const id = input7.id || randomUUID3();
30050
+ const id = input7.id || randomUUID4();
29775
30051
  const tags = JSON.stringify(input7.tags || []);
29776
30052
  try {
29777
30053
  this.stmts.insert.run(
@@ -30092,7 +30368,7 @@ function rowToEntry(row) {
30092
30368
  }
30093
30369
 
30094
30370
  // ../core/dist/src/repositories/quarantine/QuarantineRepository.js
30095
- import { randomUUID as randomUUID4 } from "crypto";
30371
+ import { randomUUID as randomUUID5 } from "crypto";
30096
30372
  var QuarantineRepository = class {
30097
30373
  db;
30098
30374
  auditLogger;
@@ -30146,7 +30422,7 @@ var QuarantineRepository = class {
30146
30422
  * @returns Created quarantine entry
30147
30423
  */
30148
30424
  create(input7) {
30149
- const id = input7.id || randomUUID4();
30425
+ const id = input7.id || randomUUID5();
30150
30426
  const patterns = JSON.stringify(input7.detectedPatterns || []);
30151
30427
  this.stmts.insert.run(
30152
30428
  id,
@@ -30599,17 +30875,17 @@ var MS_PER_DAY = 24 * 60 * 60 * 1e3;
30599
30875
 
30600
30876
  // ../core/dist/src/analytics/storage.js
30601
30877
  import { join as join29, dirname as dirname16 } from "path";
30602
- import { homedir as homedir14 } from "os";
30603
- var ANALYTICS_DIR = join29(homedir14(), ".skillsmith");
30878
+ import { homedir as homedir13 } from "os";
30879
+ var ANALYTICS_DIR = join29(homedir13(), ".skillsmith");
30604
30880
  var ANALYTICS_DB = join29(ANALYTICS_DIR, "analytics.db");
30605
30881
 
30606
30882
  // ../core/dist/src/analytics/usage-tracker.js
30607
30883
  var SESSION_TIMEOUT_MS = 60 * 60 * 1e3;
30608
30884
 
30609
30885
  // ../core/dist/src/analytics/metrics-exporter.js
30610
- import { join as join30, resolve as resolve9, isAbsolute as isAbsolute3 } from "path";
30611
- import { homedir as homedir15 } from "os";
30612
- var DEFAULT_EXPORT_DIR = join30(homedir15(), ".skillsmith", "exports");
30886
+ import { join as join30, resolve as resolve10, isAbsolute as isAbsolute4 } from "path";
30887
+ import { homedir as homedir14 } from "os";
30888
+ var DEFAULT_EXPORT_DIR = join30(homedir14(), ".skillsmith", "exports");
30613
30889
 
30614
30890
  // ../core/dist/src/repositories/SkillVersionRepository.js
30615
30891
  var SkillVersionRepository = class {
@@ -31343,8 +31619,8 @@ var EventBatcher = class {
31343
31619
  return;
31344
31620
  } catch {
31345
31621
  }
31346
- await new Promise((resolve19) => {
31347
- const t = setTimeout(resolve19, this.retryDelayMs);
31622
+ await new Promise((resolve20) => {
31623
+ const t = setTimeout(resolve20, this.retryDelayMs);
31348
31624
  if (typeof t.unref === "function") {
31349
31625
  ;
31350
31626
  t.unref();
@@ -31377,8 +31653,8 @@ var EventBatcher = class {
31377
31653
  }
31378
31654
  drainHandler = () => {
31379
31655
  const drain = this.flush();
31380
- const timeout = new Promise((resolve19) => {
31381
- const t = setTimeout(resolve19, this.drainTimeoutMs);
31656
+ const timeout = new Promise((resolve20) => {
31657
+ const t = setTimeout(resolve20, this.drainTimeoutMs);
31382
31658
  if (typeof t.unref === "function") {
31383
31659
  ;
31384
31660
  t.unref();
@@ -31863,7 +32139,7 @@ var SkillsmithApiClient = class {
31863
32139
  if (attempt < this.maxRetries) {
31864
32140
  const delay = calculateBackoff(attempt);
31865
32141
  this.log(`Retrying in ${delay}ms...`);
31866
- await new Promise((resolve19) => setTimeout(resolve19, delay));
32142
+ await new Promise((resolve20) => setTimeout(resolve20, delay));
31867
32143
  }
31868
32144
  }
31869
32145
  }
@@ -31888,6 +32164,9 @@ var SkillsmithApiClient = class {
31888
32164
  if (options.maxRiskScore !== void 0 && options.maxRiskScore !== null) {
31889
32165
  params.set("max_risk", String(options.maxRiskScore));
31890
32166
  }
32167
+ if (options.compatibility && options.compatibility.length > 0) {
32168
+ params.set("compatibility", options.compatibility.join(","));
32169
+ }
31891
32170
  const endpoint = `/skills-search?${params.toString()}`;
31892
32171
  return withResponseCache(this.responseCache, "search", endpoint, callOptions?.cache === "no-store", () => this.request(endpoint, {}, SearchResponseSchema));
31893
32172
  }
@@ -32525,7 +32804,7 @@ function trackSkillInvoke(params) {
32525
32804
 
32526
32805
  // ../core/dist/src/telemetry/wrap.js
32527
32806
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
32528
- import { randomUUID as randomUUID5 } from "node:crypto";
32807
+ import { randomUUID as randomUUID6 } from "node:crypto";
32529
32808
  var wrapped = /* @__PURE__ */ new Set();
32530
32809
  var emissionGateStorage = new AsyncLocalStorage2();
32531
32810
  var emissionGate;
@@ -32547,7 +32826,7 @@ function truncateErrorMessage(message) {
32547
32826
  }
32548
32827
  function withTelemetry(handler, opts) {
32549
32828
  const wrappedFn = async (...args) => {
32550
- return runWithCorrelationId(getCorrelationId() ?? randomUUID5(), async () => {
32829
+ return runWithCorrelationId(getCorrelationId() ?? randomUUID6(), async () => {
32551
32830
  const start = Date.now();
32552
32831
  const skillId = opts.extractSkillId(args);
32553
32832
  const framework = opts.extractFramework?.(args) ?? "unknown";
@@ -32996,11 +33275,11 @@ async function scanLocalSkills(skillsRoot) {
32996
33275
  }
32997
33276
 
32998
33277
  // ../core/dist/src/provenance/SourceRecoveryService.js
32999
- import * as os4 from "os";
33278
+ import * as os3 from "os";
33000
33279
  import * as path12 from "path";
33001
33280
  var frontmatterParser = new SkillParser({ requireName: false });
33002
33281
  function defaultSkillsRoot() {
33003
- return path12.join(os4.homedir(), ".claude", "skills");
33282
+ return path12.join(os3.homedir(), ".claude", "skills");
33004
33283
  }
33005
33284
  function candidateSource(candidate) {
33006
33285
  return { owner: candidate.owner, repo: candidate.repo, url: candidate.url };
@@ -33178,7 +33457,7 @@ var SourceRecoveryService = class {
33178
33457
  // ../core/dist/src/provenance/backfill.js
33179
33458
  import { existsSync as existsSync19 } from "fs";
33180
33459
  import * as fs11 from "fs/promises";
33181
- import * as os5 from "os";
33460
+ import * as os4 from "os";
33182
33461
  import * as path13 from "path";
33183
33462
  var CONFIDENCE_RANK = {
33184
33463
  unknown: 0,
@@ -33189,7 +33468,7 @@ var CONFIDENCE_RANK = {
33189
33468
  "user-specified": 5
33190
33469
  };
33191
33470
  function defaultManifestPath() {
33192
- return path13.join(os5.homedir(), ".skillsmith", "manifest.json");
33471
+ return path13.join(os4.homedir(), ".skillsmith", "manifest.json");
33193
33472
  }
33194
33473
  function nonEmpty(value) {
33195
33474
  return typeof value === "string" && value.trim().length > 0;
@@ -33474,8 +33753,8 @@ async function probeEmbeddingCapability(opts = {}) {
33474
33753
  try {
33475
33754
  const result = await Promise.race([
33476
33755
  EmbeddingService.checkAvailability(),
33477
- new Promise((resolve19) => {
33478
- timeoutHandle = setTimeout(() => resolve19(TIMEOUT_SENTINEL), timeoutMs);
33756
+ new Promise((resolve20) => {
33757
+ timeoutHandle = setTimeout(() => resolve20(TIMEOUT_SENTINEL), timeoutMs);
33479
33758
  })
33480
33759
  ]);
33481
33760
  if (result === TIMEOUT_SENTINEL) {
@@ -33567,11 +33846,11 @@ import ora from "ora";
33567
33846
  import * as path14 from "node:path";
33568
33847
 
33569
33848
  // src/utils/sanitize.ts
33570
- import { homedir as homedir18 } from "os";
33849
+ import { homedir as homedir17 } from "os";
33571
33850
  var logger9 = getCliLogger();
33572
33851
  function sanitizeError(error46) {
33573
33852
  const message = error46 instanceof Error ? error46.message : String(error46);
33574
- const home2 = homedir18();
33853
+ const home2 = homedir17();
33575
33854
  const escapedHome = home2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33576
33855
  let sanitized = message.replace(new RegExp(escapedHome, "g"), "~");
33577
33856
  sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "~/");
@@ -33582,7 +33861,7 @@ function sanitizeError(error46) {
33582
33861
 
33583
33862
  // src/commands/install.ts
33584
33863
  var logger10 = getCliLogger();
33585
- var VALID_CLIENT_HINT = "Valid IDs: claude-code | cursor | copilot | windsurf | agents | opencode | hermes (Codex users pass --client agents).";
33864
+ var VALID_CLIENT_HINT = "Valid IDs: claude-code | cursor | copilot | windsurf | agents | opencode | hermes | grok | antigravity (Codex users pass --client agents).";
33586
33865
  function parseAlsoLink(raw, defaultClient) {
33587
33866
  if (!raw || raw.trim() === "") return [];
33588
33867
  const ids = raw.split(",").map((s) => s.trim()).filter((s) => s !== "");
@@ -33749,6 +34028,13 @@ async function installActionImpl(skillId, opts) {
33749
34028
  manifestPath: DEFAULT_MANIFEST_PATH,
33750
34029
  registryLookup,
33751
34030
  client,
34031
+ // SMI-5982 PR-review follow-up: explicit now that
34032
+ // resolveCompanionAgentPath() no longer defaults a missing baseDir to
34033
+ // process.cwd() itself — this CLI command's real "cwd" IS the
34034
+ // process's invocation directory, so this restores today's exact
34035
+ // behavior explicitly instead of relying on a now-removed implicit
34036
+ // default.
34037
+ companionBaseDir: process.cwd(),
33752
34038
  onProgress: (_stage, detail) => {
33753
34039
  if (spinner) {
33754
34040
  spinner.text = detail;
@@ -34165,6 +34451,13 @@ ${outcome.message}`));
34165
34451
  registryLookup,
34166
34452
  skillsDir: getInstallPath(client),
34167
34453
  client,
34454
+ // SMI-5982 PR-review follow-up: explicit now that
34455
+ // resolveCompanionAgentPath() no longer defaults a missing
34456
+ // baseDir to process.cwd() itself — this CLI command's real
34457
+ // "cwd" IS the process's invocation directory, so this
34458
+ // restores today's exact behavior explicitly instead of
34459
+ // relying on a now-removed implicit default.
34460
+ companionBaseDir: process.cwd(),
34168
34461
  onProgress: (_stage, detail) => {
34169
34462
  installSpinner.text = detail;
34170
34463
  }
@@ -34566,11 +34859,11 @@ import { readFile as readFile8 } from "fs/promises";
34566
34859
  import { basename as basename6, join as join41 } from "path";
34567
34860
 
34568
34861
  // src/utils/manifest.ts
34569
- import { createHash as createHash9, randomUUID as randomUUID6 } from "crypto";
34570
- import { readFile as readFile7, writeFile as writeFile4, mkdir as mkdir5, rename as rename3 } from "fs/promises";
34862
+ import { createHash as createHash9, randomUUID as randomUUID7 } from "crypto";
34863
+ import { readFile as readFile7, writeFile as writeFile4, mkdir as mkdir5, rename as rename3, unlink as unlink5 } from "fs/promises";
34571
34864
  import { join as join40, dirname as dirname19 } from "path";
34572
- import { homedir as homedir19 } from "os";
34573
- var SKILLSMITH_DIR = join40(homedir19(), ".skillsmith");
34865
+ import { homedir as homedir18 } from "os";
34866
+ var SKILLSMITH_DIR = join40(homedir18(), ".skillsmith");
34574
34867
  var MANIFEST_PATH = join40(SKILLSMITH_DIR, "manifest.json");
34575
34868
  async function loadManifest2() {
34576
34869
  try {
@@ -34582,9 +34875,17 @@ async function loadManifest2() {
34582
34875
  }
34583
34876
  async function saveManifest2(manifest) {
34584
34877
  await mkdir5(dirname19(MANIFEST_PATH), { recursive: true });
34585
- const tmpPath = `${MANIFEST_PATH}.tmp.${process.pid}`;
34586
- await writeFile4(tmpPath, JSON.stringify(manifest, null, 2));
34587
- await rename3(tmpPath, MANIFEST_PATH);
34878
+ const tmpPath = `${MANIFEST_PATH}.tmp.${process.pid}.${randomUUID7()}`;
34879
+ try {
34880
+ await writeFile4(tmpPath, JSON.stringify(manifest, null, 2));
34881
+ await rename3(tmpPath, MANIFEST_PATH);
34882
+ } catch (error46) {
34883
+ try {
34884
+ await unlink5(tmpPath);
34885
+ } catch {
34886
+ }
34887
+ throw error46;
34888
+ }
34588
34889
  }
34589
34890
  async function updateManifestEntry(updateFn) {
34590
34891
  const manifest = await loadManifest2();
@@ -34595,7 +34896,7 @@ var ROTATION_DAYS = 365;
34595
34896
  var OVERLAP_DAYS = 7;
34596
34897
  var MS_PER_DAY2 = 864e5;
34597
34898
  function generateAnonymousId2() {
34598
- return createHash9("sha256").update(randomUUID6()).digest("hex");
34899
+ return createHash9("sha256").update(randomUUID7()).digest("hex");
34599
34900
  }
34600
34901
  function shouldRotateAnonymousId(manifest) {
34601
34902
  const createdAt = manifest.telemetry?.anonymousIdCreatedAt;
@@ -34811,6 +35112,13 @@ Changes for ${skillName}:`));
34811
35112
  manifestPath: DEFAULT_MANIFEST_PATH,
34812
35113
  registryLookup,
34813
35114
  client,
35115
+ // SMI-5982 PR-review follow-up: explicit now that
35116
+ // resolveCompanionAgentPath() no longer defaults a missing baseDir to
35117
+ // process.cwd() itself — this CLI command's real "cwd" IS the
35118
+ // process's invocation directory, so this restores today's exact
35119
+ // behavior explicitly instead of relying on a now-removed implicit
35120
+ // default.
35121
+ companionBaseDir: process.cwd(),
34814
35122
  onProgress: (_stage, detail) => {
34815
35123
  updateSpinner.text = detail;
34816
35124
  }
@@ -35113,7 +35421,7 @@ var InitSkillError = class _InitSkillError extends Error {
35113
35421
  import { input as input2, confirm as confirm3, select as select2 } from "@inquirer/prompts";
35114
35422
  import ora5 from "ora";
35115
35423
  import { mkdir as mkdir9, writeFile as writeFile6, readFile as readFile9, stat as stat7, readdir as readdir7 } from "fs/promises";
35116
- import { dirname as dirname21, join as join44, resolve as resolve11 } from "path";
35424
+ import { dirname as dirname21, join as join43, resolve as resolve12 } from "path";
35117
35425
  import { createHash as createHash10 } from "crypto";
35118
35426
 
35119
35427
  // src/utils/skill-name.ts
@@ -35129,8 +35437,8 @@ function validateSkillName(name) {
35129
35437
  // src/commands/author/utils.ts
35130
35438
  import { access as access3 } from "fs/promises";
35131
35439
  import { mkdir as mkdir7 } from "fs/promises";
35132
- import { join as join42, resolve as resolve10 } from "path";
35133
- import { homedir as homedir20 } from "os";
35440
+ import { resolve as resolve11 } from "path";
35441
+ import { homedir as homedir19 } from "os";
35134
35442
  function printValidationResult(result, filePath) {
35135
35443
  console.log(source_default.bold(`
35136
35444
  Validation Result for ${filePath}:
@@ -35162,8 +35470,8 @@ async function fileExists(path27) {
35162
35470
  return false;
35163
35471
  }
35164
35472
  }
35165
- async function ensureAgentsDirectory(customPath) {
35166
- const agentsDir = customPath ? resolve10(customPath.replace(/^~/, homedir20())) : join42(homedir20(), ".claude", "agents");
35473
+ async function ensureAgentsDirectory(customPath, client) {
35474
+ const agentsDir = customPath ? resolve11(customPath.replace(/^~/, homedir19())) : resolveCompanionAgentDir(client);
35167
35475
  await mkdir7(agentsDir, { recursive: true });
35168
35476
  return agentsDir;
35169
35477
  }
@@ -35218,7 +35526,7 @@ function validateSubagentDefinition(content) {
35218
35526
 
35219
35527
  // src/commands/author/init.helpers.ts
35220
35528
  import { mkdir as mkdir8, writeFile as writeFile5, rm as rm4 } from "fs/promises";
35221
- import { join as join43 } from "path";
35529
+ import { join as join42 } from "path";
35222
35530
 
35223
35531
  // src/templates/skill.md.template.ts
35224
35532
  var SKILL_MD_TEMPLATE = `---
@@ -35734,6 +36042,30 @@ args = ["-y", "{{name}}"]
35734
36042
  [mcp_servers.{{name}}.env]
35735
36043
  SKILLSMITH_API_KEY = "sk_live_..."`,
35736
36044
  notes: "Grok Build uses TOML under the [mcp_servers.<name>] table, mirroring the Codex CLI convention above \u2014 confirmed against docs.x.ai for the command/args shape; the env sub-table follows the same pattern as the Codex entry."
36045
+ },
36046
+ // SMI-5982 Wave 6: antigravity added to ClientId (paths.ts); this
36047
+ // Record<SnippetClientId, ClientSnippet> is exhaustive over ClientId, so
36048
+ // this entry is required for the type to compile. Path + shape verified
36049
+ // 2026-08-11 via live web search (antigravity.google/docs/mcp, corroborated
36050
+ // by an independent third-party source): global config at
36051
+ // ~/.gemini/config/mcp_config.json, standard `mcpServers` object shape
36052
+ // (same command/args/env fields every non-Codex/non-OpenCode client uses).
36053
+ antigravity: {
36054
+ label: "Google Antigravity",
36055
+ configPath: "~/.gemini/config/mcp_config.json",
36056
+ format: "json",
36057
+ body: `{
36058
+ "mcpServers": {
36059
+ "{{name}}": {
36060
+ "command": "npx",
36061
+ "args": ["-y", "{{name}}"],
36062
+ "env": {
36063
+ "SKILLSMITH_API_KEY": "sk_live_..."
36064
+ }
36065
+ }
36066
+ }
36067
+ }`,
36068
+ notes: "One config file is shared across Antigravity CLI, IDE, and 2.0. A workspace-scoped alternative also exists at .agents/mcp_config.json (project root) if you prefer not to register the server globally."
35737
36069
  }
35738
36070
  };
35739
36071
  function renderSnippet(client, packageName) {
@@ -35769,7 +36101,8 @@ var SNIPPET_DISPLAY_ORDER = Object.freeze([
35769
36101
  "agents",
35770
36102
  "opencode",
35771
36103
  "hermes",
35772
- "grok"
36104
+ "grok",
36105
+ "antigravity"
35773
36106
  ]);
35774
36107
 
35775
36108
  // src/templates/mcp-server.template.ts
@@ -36115,15 +36448,15 @@ function renderMcpServerTemplates(data) {
36115
36448
  async function scaffoldSkillDirectory(input7) {
36116
36449
  const { skillDir, skillName, description, author, category, createdFresh } = input7;
36117
36450
  try {
36118
- await mkdir8(join43(skillDir, "scripts"), { recursive: true });
36119
- await mkdir8(join43(skillDir, "resources"), { recursive: true });
36451
+ await mkdir8(join42(skillDir, "scripts"), { recursive: true });
36452
+ await mkdir8(join42(skillDir, "resources"), { recursive: true });
36120
36453
  const skillMdContent = SKILL_MD_TEMPLATE.replace(/\{\{name\}\}/g, skillName).replace(/\{\{description\}\}/g, description).replace(/\{\{author\}\}/g, author).replace(/\{\{category\}\}/g, category).replace(/\{\{date\}\}/g, (/* @__PURE__ */ new Date()).toISOString().split("T")[0] || "").replace(/\{\{behavioralClassification\}\}/g, "");
36121
- await writeFile5(join43(skillDir, "SKILL.md"), skillMdContent, "utf-8");
36454
+ await writeFile5(join42(skillDir, "SKILL.md"), skillMdContent, "utf-8");
36122
36455
  const readmeContent = README_MD_TEMPLATE.replace(/\{\{name\}\}/g, skillName).replace(
36123
36456
  /\{\{description\}\}/g,
36124
36457
  description
36125
36458
  );
36126
- await writeFile5(join43(skillDir, "README.md"), readmeContent, "utf-8");
36459
+ await writeFile5(join42(skillDir, "README.md"), readmeContent, "utf-8");
36127
36460
  const placeholderScript = `#!/usr/bin/env node
36128
36461
  /**
36129
36462
  * ${skillName} - Example Script
@@ -36133,7 +36466,7 @@ async function scaffoldSkillDirectory(input7) {
36133
36466
 
36134
36467
  console.log('${skillName} script executed');
36135
36468
  `;
36136
- await writeFile5(join43(skillDir, "scripts", "example.js"), placeholderScript, "utf-8");
36469
+ await writeFile5(join42(skillDir, "scripts", "example.js"), placeholderScript, "utf-8");
36137
36470
  const gitignore = `# Dependencies
36138
36471
  node_modules/
36139
36472
 
@@ -36148,7 +36481,7 @@ dist/
36148
36481
  .DS_Store
36149
36482
  Thumbs.db
36150
36483
  `;
36151
- await writeFile5(join43(skillDir, ".gitignore"), gitignore, "utf-8");
36484
+ await writeFile5(join42(skillDir, ".gitignore"), gitignore, "utf-8");
36152
36485
  return { ok: true };
36153
36486
  } catch (error46) {
36154
36487
  await rollbackPartialScaffold(skillDir, createdFresh);
@@ -36208,7 +36541,7 @@ async function initSkill(name, targetPath, options = {}) {
36208
36541
  { name: "Other", value: "other" }
36209
36542
  ]
36210
36543
  });
36211
- const skillDir = resolve11(targetPath, skillName);
36544
+ const skillDir = resolve12(targetPath, skillName);
36212
36545
  let skillDirPreExisted = false;
36213
36546
  try {
36214
36547
  await stat7(skillDir);
@@ -36260,15 +36593,15 @@ async function initSkill(name, targetPath, options = {}) {
36260
36593
  async function validateSkill(skillPath) {
36261
36594
  const spinner = ora5("Validating skill...").start();
36262
36595
  try {
36263
- let filePath = resolve11(skillPath);
36596
+ let filePath = resolve12(skillPath);
36264
36597
  try {
36265
36598
  const stats = await stat7(filePath);
36266
36599
  if (stats.isDirectory()) {
36267
- filePath = join44(filePath, "SKILL.md");
36600
+ filePath = join43(filePath, "SKILL.md");
36268
36601
  }
36269
36602
  } catch {
36270
36603
  if (!filePath.endsWith(".md")) {
36271
- filePath = join44(filePath, "SKILL.md");
36604
+ filePath = join43(filePath, "SKILL.md");
36272
36605
  }
36273
36606
  }
36274
36607
  const content = await readFile9(filePath, "utf-8");
@@ -36305,7 +36638,7 @@ async function validateSkill(skillPath) {
36305
36638
  async function publishSkill(skillPath, options = {}) {
36306
36639
  const spinner = ora5("Preparing skill for publishing...").start();
36307
36640
  try {
36308
- let dirPath = resolve11(skillPath || ".");
36641
+ let dirPath = resolve12(skillPath || ".");
36309
36642
  try {
36310
36643
  const stats = await stat7(dirPath);
36311
36644
  if (!stats.isDirectory()) {
@@ -36315,7 +36648,7 @@ async function publishSkill(skillPath, options = {}) {
36315
36648
  spinner.fail(`Directory not found: ${dirPath}`);
36316
36649
  return false;
36317
36650
  }
36318
- const skillMdPath = join44(dirPath, "SKILL.md");
36651
+ const skillMdPath = join43(dirPath, "SKILL.md");
36319
36652
  spinner.text = "Validating skill...";
36320
36653
  const content = await readFile9(skillMdPath, "utf-8");
36321
36654
  const parser2 = new SkillParser({ requireName: true });
@@ -36361,7 +36694,7 @@ async function publishSkill(skillPath, options = {}) {
36361
36694
  }).filter((p) => p !== null);
36362
36695
  let totalWarnings = 0;
36363
36696
  for (const mdFile of mdFiles) {
36364
- const filePath = join44(dirPath, mdFile);
36697
+ const filePath = join43(dirPath, mdFile);
36365
36698
  const fileContent = await readFile9(filePath, "utf-8");
36366
36699
  const result = SkillParser.checkReferences(fileContent, customPatterns);
36367
36700
  if (result.matches.length > 0) {
@@ -36390,7 +36723,7 @@ async function publishSkill(skillPath, options = {}) {
36390
36723
  spinner.start();
36391
36724
  }
36392
36725
  }
36393
- const manifestPath = join44(dirPath, ".skillsmith-publish.json");
36726
+ const manifestPath = join43(dirPath, ".skillsmith-publish.json");
36394
36727
  await writeFile6(manifestPath, JSON.stringify(publishInfo, null, 2), "utf-8");
36395
36728
  spinner.succeed("Skill prepared for publishing");
36396
36729
  console.log(source_default.bold("\nPublish Information:"));
@@ -36497,7 +36830,7 @@ function createPublishCommand() {
36497
36830
  import { Command as Command5 } from "commander";
36498
36831
  import ora6 from "ora";
36499
36832
  import { readFile as readFile10, writeFile as writeFile7, stat as stat8 } from "fs/promises";
36500
- import { basename as basename7, dirname as dirname22, join as join45, resolve as resolve12 } from "path";
36833
+ import { basename as basename7, dirname as dirname22, join as join44, resolve as resolve13 } from "path";
36501
36834
 
36502
36835
  // src/utils/tool-analyzer.ts
36503
36836
  var TOOL_PATTERNS3 = {
@@ -36621,18 +36954,18 @@ var logger14 = getCliLogger();
36621
36954
  async function generateSubagent2(skillPath, options) {
36622
36955
  const spinner = ora6("Generating subagent...").start();
36623
36956
  try {
36624
- let dirPath = resolve12(skillPath || ".");
36957
+ let dirPath = resolve13(skillPath || ".");
36625
36958
  let skillMdPath;
36626
36959
  try {
36627
36960
  const stats = await stat8(dirPath);
36628
36961
  if (stats.isDirectory()) {
36629
- skillMdPath = join45(dirPath, "SKILL.md");
36962
+ skillMdPath = join44(dirPath, "SKILL.md");
36630
36963
  } else {
36631
36964
  skillMdPath = dirPath;
36632
36965
  dirPath = dirname22(dirPath);
36633
36966
  }
36634
36967
  } catch {
36635
- skillMdPath = dirPath.endsWith(".md") ? dirPath : join45(dirPath, "SKILL.md");
36968
+ skillMdPath = dirPath.endsWith(".md") ? dirPath : join44(dirPath, "SKILL.md");
36636
36969
  }
36637
36970
  spinner.text = "Reading SKILL.md...";
36638
36971
  const content = await readFile10(skillMdPath, "utf-8");
@@ -36679,7 +37012,11 @@ async function generateSubagent2(skillPath, options) {
36679
37012
  return;
36680
37013
  }
36681
37014
  const agentsDir = await ensureAgentsDirectory(options.output);
36682
- const subagentPath = join45(agentsDir, `${basename7(metadata.name)}-specialist.md`);
37015
+ const subagentFilename = getCompanionAgentTarget().filenamePattern.replace(
37016
+ "{name}",
37017
+ basename7(metadata.name)
37018
+ );
37019
+ const subagentPath = join44(agentsDir, subagentFilename);
36683
37020
  if (await fileExists(subagentPath)) {
36684
37021
  if (!options.force) {
36685
37022
  spinner.warn(`Subagent already exists: ${subagentPath}`);
@@ -36739,32 +37076,31 @@ var subagentAction = withTelemetry(subagentActionImpl, {
36739
37076
  extractFramework: () => "cli"
36740
37077
  });
36741
37078
  function createSubagentCommand() {
36742
- return new Command5("subagent").description("Generate a companion subagent for a skill").argument("[path]", "Path to skill directory", ".").option("-o, --output <path>", "Output directory", "~/.claude/agents").option("--tools <tools>", "Override detected tools (comma-separated)").option("--model <model>", "Model for subagent: sonnet|opus|haiku", "sonnet").option("--skip-claude-md", "Skip CLAUDE.md snippet generation").option("--force", "Overwrite existing subagent definition").action(subagentAction);
37079
+ return new Command5("subagent").description("Generate a companion subagent for a skill").argument("[path]", "Path to skill directory", ".").option("-o, --output <path>", "Output directory (default: ~/.claude/agents)").option("--tools <tools>", "Override detected tools (comma-separated)").option("--model <model>", "Model for subagent: sonnet|opus|haiku", "sonnet").option("--skip-claude-md", "Skip CLAUDE.md snippet generation").option("--force", "Overwrite existing subagent definition").action(subagentAction);
36743
37080
  }
36744
37081
 
36745
37082
  // src/commands/author/transform.ts
36746
37083
  import { Command as Command6 } from "commander";
36747
37084
  import ora7 from "ora";
36748
37085
  import { readFile as readFile11, readdir as readdir8 } from "fs/promises";
36749
- import { join as join46, resolve as resolve13 } from "path";
36750
- import { homedir as homedir21 } from "os";
37086
+ import { join as join45, resolve as resolve14 } from "path";
36751
37087
  var logger15 = getCliLogger();
36752
37088
  async function transformSkill2(skillPath, options) {
36753
37089
  const spinner = ora7("Transforming skill...").start();
36754
37090
  try {
36755
- const dirPath = resolve13(skillPath || ".");
37091
+ const dirPath = resolve14(skillPath || ".");
36756
37092
  if (options.batch) {
36757
37093
  spinner.text = "Processing batch...";
36758
37094
  let skillDirs = [];
36759
37095
  if (dirPath.includes(",")) {
36760
- skillDirs = dirPath.split(",").map((p) => resolve13(p.trim()));
37096
+ skillDirs = dirPath.split(",").map((p) => resolve14(p.trim()));
36761
37097
  } else {
36762
37098
  const subdirs = await readdir8(dirPath, { withFileTypes: true });
36763
37099
  for (const entry of subdirs) {
36764
37100
  if (entry.isDirectory()) {
36765
- const skillMdPath2 = join46(dirPath, entry.name, "SKILL.md");
37101
+ const skillMdPath2 = join45(dirPath, entry.name, "SKILL.md");
36766
37102
  if (await fileExists(skillMdPath2)) {
36767
- skillDirs.push(join46(dirPath, entry.name));
37103
+ skillDirs.push(join45(dirPath, entry.name));
36768
37104
  }
36769
37105
  }
36770
37106
  }
@@ -36786,7 +37122,7 @@ Processing: ${skillDir}`));
36786
37122
  }
36787
37123
  return;
36788
37124
  }
36789
- const skillMdPath = join46(dirPath, "SKILL.md");
37125
+ const skillMdPath = join45(dirPath, "SKILL.md");
36790
37126
  if (!await fileExists(skillMdPath)) {
36791
37127
  spinner.fail(`No SKILL.md found at: ${skillMdPath}`);
36792
37128
  throw new Error(`No SKILL.md found at: ${skillMdPath}`);
@@ -36800,8 +37136,7 @@ Processing: ${skillDir}`));
36800
37136
  printValidationResult(validation, skillMdPath);
36801
37137
  return;
36802
37138
  }
36803
- const agentsDir = join46(homedir21(), ".claude", "agents");
36804
- const subagentPath = join46(agentsDir, `${metadata.name}-specialist.md`);
37139
+ const subagentPath = resolveCompanionAgentPath(metadata.name);
36805
37140
  if (await fileExists(subagentPath)) {
36806
37141
  if (!options.force) {
36807
37142
  spinner.warn(`Subagent already exists: ${subagentPath}`);
@@ -36859,7 +37194,7 @@ import { Command as Command7 } from "commander";
36859
37194
  import { input as input3, confirm as confirm4 } from "@inquirer/prompts";
36860
37195
  import ora8 from "ora";
36861
37196
  import { mkdir as mkdir10, writeFile as writeFile8, stat as stat9 } from "fs/promises";
36862
- import { dirname as dirname23, join as join47, resolve as resolve14 } from "path";
37197
+ import { dirname as dirname23, join as join46, resolve as resolve15 } from "path";
36863
37198
  var logger16 = getCliLogger();
36864
37199
  async function initMcpServer(name, options) {
36865
37200
  const serverName = name || await input3({
@@ -36948,7 +37283,7 @@ async function initMcpServer(name, options) {
36948
37283
  }
36949
37284
  }
36950
37285
  }
36951
- const targetDir = options.output ? resolve14(options.output) : resolve14(".", serverName);
37286
+ const targetDir = options.output ? resolve15(options.output) : resolve15(".", serverName);
36952
37287
  try {
36953
37288
  await stat9(targetDir);
36954
37289
  if (!options.force) {
@@ -36972,10 +37307,10 @@ async function initMcpServer(name, options) {
36972
37307
  author
36973
37308
  });
36974
37309
  await mkdir10(targetDir, { recursive: true });
36975
- await mkdir10(join47(targetDir, "src"), { recursive: true });
36976
- await mkdir10(join47(targetDir, "src", "tools"), { recursive: true });
37310
+ await mkdir10(join46(targetDir, "src"), { recursive: true });
37311
+ await mkdir10(join46(targetDir, "src", "tools"), { recursive: true });
36977
37312
  for (const [filePath, content] of files) {
36978
- const fullPath = join47(targetDir, filePath);
37313
+ const fullPath = join46(targetDir, filePath);
36979
37314
  const dir = dirname23(fullPath);
36980
37315
  await mkdir10(dir, { recursive: true });
36981
37316
  await writeFile8(fullPath, content, "utf-8");
@@ -36995,7 +37330,7 @@ async function initMcpServer(name, options) {
36995
37330
  "mcpServers": {
36996
37331
  "${serverName}": {
36997
37332
  "command": "npx",
36998
- "args": ["tsx", "${join47(targetDir, "src", "index.ts")}"]
37333
+ "args": ["tsx", "${join46(targetDir, "src", "index.ts")}"]
36999
37334
  }
37000
37335
  }
37001
37336
  }`)
@@ -37177,7 +37512,7 @@ import ora9 from "ora";
37177
37512
 
37178
37513
  // src/commands/recommend.helpers.ts
37179
37514
  import { existsSync as existsSync21, readdirSync as readdirSync2, readFileSync as readFileSync18, statSync as statSync4 } from "node:fs";
37180
- import { join as join48 } from "node:path";
37515
+ import { join as join47 } from "node:path";
37181
37516
 
37182
37517
  // src/commands/recommend.types.ts
37183
37518
  var VALID_TRUST_TIERS = [
@@ -37504,7 +37839,7 @@ function getInstalledSkills2() {
37504
37839
  try {
37505
37840
  const entries = readdirSync2(skillsDir);
37506
37841
  for (const entry of entries) {
37507
- const skillPath = join48(skillsDir, entry);
37842
+ const skillPath = join47(skillsDir, entry);
37508
37843
  const stat13 = statSync4(skillPath);
37509
37844
  if (!stat13.isDirectory()) continue;
37510
37845
  const skill = {
@@ -37513,7 +37848,7 @@ function getInstalledSkills2() {
37513
37848
  tags: [],
37514
37849
  category: null
37515
37850
  };
37516
- const skillMdPath = join48(skillPath, "SKILL.md");
37851
+ const skillMdPath = join47(skillPath, "SKILL.md");
37517
37852
  if (existsSync21(skillMdPath)) {
37518
37853
  try {
37519
37854
  const content = readFileSync18(skillMdPath, "utf-8");
@@ -37560,8 +37895,7 @@ async function runRecommend(targetPath, options) {
37560
37895
  spinner.start("Finding skill recommendations...");
37561
37896
  const stack = buildStackFromAnalysis(codebaseContext);
37562
37897
  if (options.context) {
37563
- const contextWords = options.context.toLowerCase().split(/\s+/).filter((w) => w.length > 3).slice(0, 5);
37564
- stack.push(...contextWords);
37898
+ stack.push(...extractContextWords(options.context));
37565
37899
  }
37566
37900
  if (options.installed?.length) {
37567
37901
  stack.push(...options.installed.map((id) => id.toLowerCase().split("/").pop() ?? id));
@@ -38169,7 +38503,7 @@ function createSyncCommand() {
38169
38503
 
38170
38504
  // src/commands/merge.ts
38171
38505
  import { Command as Command11 } from "commander";
38172
- import { resolve as resolve15 } from "path";
38506
+ import { resolve as resolve16 } from "path";
38173
38507
  import { existsSync as existsSync22 } from "fs";
38174
38508
  var logger20 = getCliLogger();
38175
38509
  function formatMergeResult(result) {
@@ -38201,8 +38535,8 @@ async function mergeActionImpl(sourcePath, targetPath, options) {
38201
38535
  logger20.error(`Valid strategies: ${validStrategies.join(", ")}`);
38202
38536
  process.exit(1);
38203
38537
  }
38204
- const resolvedSource = resolve15(sourcePath);
38205
- const resolvedTarget = targetPath ? resolve15(targetPath) : getDefaultDbPath();
38538
+ const resolvedSource = resolve16(sourcePath);
38539
+ const resolvedTarget = targetPath ? resolve16(targetPath) : getDefaultDbPath();
38206
38540
  if (!existsSync22(resolvedSource)) {
38207
38541
  logger20.error(`Source database not found: ${resolvedSource}`);
38208
38542
  process.exit(1);
@@ -38393,6 +38727,13 @@ ${message}`));
38393
38727
  skillsDir,
38394
38728
  manifestPath: DEFAULT_MANIFEST_PATH,
38395
38729
  client,
38730
+ // SMI-5982 PR-review follow-up: explicit now that
38731
+ // resolveCompanionAgentPath() no longer defaults a missing baseDir to
38732
+ // process.cwd() itself — this CLI command's real "cwd" IS the
38733
+ // process's invocation directory, so this restores today's exact
38734
+ // behavior explicitly instead of relying on a now-removed implicit
38735
+ // default.
38736
+ companionBaseDir: process.cwd(),
38396
38737
  onProgress: (_stage, detail) => {
38397
38738
  if (spinner) {
38398
38739
  spinner.text = detail;
@@ -38465,13 +38806,13 @@ function createRegistryCommand() {
38465
38806
  import { Command as Command13 } from "commander";
38466
38807
  import ora12 from "ora";
38467
38808
  import { mkdir as mkdir11, copyFile as copyFile2, stat as stat10, readdir as readdir9 } from "fs/promises";
38468
- import { join as join49, dirname as dirname24 } from "path";
38809
+ import { join as join48, dirname as dirname24 } from "path";
38469
38810
  var logger22 = getCliLogger();
38470
38811
  function getAssetsPath() {
38471
- return join49(packageRoot(), "assets", "skillsmith-skill");
38812
+ return join48(packageRoot(), "assets", "skillsmith-skill");
38472
38813
  }
38473
38814
  function getTargetPath() {
38474
- return join49(getCanonicalInstallPath(), "skillsmith");
38815
+ return join48(getCanonicalInstallPath(), "skillsmith");
38475
38816
  }
38476
38817
  async function directoryExists(path27) {
38477
38818
  try {
@@ -38488,8 +38829,8 @@ async function copyDirectory(src, dest) {
38488
38829
  if (entry.isSymbolicLink()) {
38489
38830
  continue;
38490
38831
  }
38491
- const srcPath = join49(src, entry.name);
38492
- const destPath = join49(dest, entry.name);
38832
+ const srcPath = join48(src, entry.name);
38833
+ const destPath = join48(dest, entry.name);
38493
38834
  if (entry.isDirectory()) {
38494
38835
  await mkdir11(destPath, { recursive: true });
38495
38836
  filesCopied += await copyDirectory(srcPath, destPath);
@@ -38822,11 +39163,11 @@ async function loginActionImpl(options) {
38822
39163
  output: process.stdout,
38823
39164
  terminal: false
38824
39165
  });
38825
- const choice = await new Promise((resolve19) => {
39166
+ const choice = await new Promise((resolve20) => {
38826
39167
  process.stdout.write("Choice [a]: ");
38827
39168
  rl.once("line", (line) => {
38828
39169
  rl.close();
38829
- resolve19(line.trim().toLowerCase());
39170
+ resolve20(line.trim().toLowerCase());
38830
39171
  });
38831
39172
  });
38832
39173
  if (choice === "" || choice === "a") {
@@ -38933,21 +39274,35 @@ function createWhoamiCommand() {
38933
39274
  // src/commands/diff.ts
38934
39275
  import { Command as Command17 } from "commander";
38935
39276
  import { readFile as readFile12 } from "fs/promises";
38936
- import { join as join50 } from "path";
39277
+ import { join as join49 } from "path";
38937
39278
 
38938
39279
  // src/utils/license-types.ts
38939
39280
  var TIER_FEATURES = {
38940
39281
  community: ["basic_search", "skill_install", "local_validation"],
38941
- individual: ["basic_analytics", "email_support"],
39282
+ individual: [
39283
+ "basic_analytics",
39284
+ "email_support",
39285
+ // SMI-5949: pre-existing drift fix — version_tracking is part of
39286
+ // INDIVIDUAL_FEATURES in the canonical @smith-horn/enterprise package
39287
+ // (packages/enterprise/src/license/FeatureFlags.ts) and was silently
39288
+ // missing here (this file has no compiler backstop, unlike the
39289
+ // Record<FeatureFlag, ...> mirrors in toolFeatureMapping.ts). Caught by
39290
+ // the new TIER_FEATURES.enterprise parity regression test.
39291
+ "version_tracking"
39292
+ ],
38942
39293
  team: [
38943
39294
  // Individual features (inherited)
38944
39295
  "basic_analytics",
38945
39296
  "email_support",
39297
+ "version_tracking",
38946
39298
  // Team features
38947
39299
  "team_workspaces",
38948
39300
  "private_skills",
38949
39301
  "usage_analytics",
38950
39302
  "priority_support",
39303
+ // SMI-5949: pre-existing drift fix — skill_security_audit is part of
39304
+ // TEAM_FEATURES in the canonical package and was silently missing here.
39305
+ "skill_security_audit",
38951
39306
  // SMI-3140: expanded to Team + Enterprise (2026-07-14)
38952
39307
  "compliance_reports"
38953
39308
  ],
@@ -38955,11 +39310,13 @@ var TIER_FEATURES = {
38955
39310
  // Individual features (inherited)
38956
39311
  "basic_analytics",
38957
39312
  "email_support",
39313
+ "version_tracking",
38958
39314
  // Team features (inherited)
38959
39315
  "team_workspaces",
38960
39316
  "private_skills",
38961
39317
  "usage_analytics",
38962
39318
  "priority_support",
39319
+ "skill_security_audit",
38963
39320
  "compliance_reports",
38964
39321
  // Enterprise-only features (canonical names from enterprise package)
38965
39322
  "sso_saml",
@@ -38968,7 +39325,9 @@ var TIER_FEATURES = {
38968
39325
  "siem_export",
38969
39326
  "private_registry",
38970
39327
  "custom_integrations",
38971
- "advanced_analytics"
39328
+ "advanced_analytics",
39329
+ // SMI-5949: separately-flagged approval gate for private_registry_publish (D-11)
39330
+ "registry_approval"
38972
39331
  ]
38973
39332
  };
38974
39333
 
@@ -39123,7 +39482,7 @@ function diffSections(oldContent, newContent) {
39123
39482
  return { added, removed, modified };
39124
39483
  }
39125
39484
  async function readInstalledSkillContent(skillName) {
39126
- const skillPath = join50(getCanonicalInstallPath(), skillName, "SKILL.md");
39485
+ const skillPath = join49(getCanonicalInstallPath(), skillName, "SKILL.md");
39127
39486
  try {
39128
39487
  return await readFile12(skillPath, "utf-8");
39129
39488
  } catch {
@@ -39334,15 +39693,15 @@ import { Command as Command22 } from "commander";
39334
39693
  // src/commands/audit-collisions.ts
39335
39694
  import * as crypto12 from "node:crypto";
39336
39695
  import * as fs34 from "node:fs";
39337
- import { homedir as homedir30 } from "node:os";
39338
- import { join as join62 } from "node:path";
39696
+ import { homedir as homedir28 } from "node:os";
39697
+ import { join as join61 } from "node:path";
39339
39698
  import { Command as Command19 } from "commander";
39340
39699
  import { input as input4, select as select3 } from "@inquirer/prompts";
39341
39700
 
39342
39701
  // ../mcp-server/dist/src/audit/audit-history.js
39343
39702
  import * as crypto3 from "node:crypto";
39344
39703
  import * as fs17 from "node:fs/promises";
39345
- import * as os7 from "node:os";
39704
+ import * as os6 from "node:os";
39346
39705
  import * as path16 from "node:path";
39347
39706
 
39348
39707
  // ../mcp-server/node_modules/ulid/dist/node/index.js
@@ -39441,7 +39800,7 @@ function ulid3(seedTime, prng) {
39441
39800
  }
39442
39801
 
39443
39802
  // ../mcp-server/dist/src/audit/audit-history.js
39444
- var DEFAULT_AUDITS_DIR = path16.join(os7.homedir(), ".skillsmith", "audits");
39803
+ var DEFAULT_AUDITS_DIR = path16.join(os6.homedir(), ".skillsmith", "audits");
39445
39804
  function newAuditId() {
39446
39805
  return ulid3();
39447
39806
  }
@@ -44552,24 +44911,24 @@ function formatTokens(tokens) {
44552
44911
  // ../mcp-server/dist/src/audit/security-audit.js
44553
44912
  import * as crypto6 from "node:crypto";
44554
44913
  import * as fs22 from "node:fs";
44555
- import * as os11 from "node:os";
44914
+ import * as os10 from "node:os";
44556
44915
 
44557
44916
  // ../mcp-server/dist/src/utils/local-inventory.js
44558
44917
  import * as fs20 from "node:fs";
44559
- import * as os8 from "node:os";
44918
+ import * as os7 from "node:os";
44560
44919
  import * as path18 from "node:path";
44561
- var DEFAULT_HOME_CLAUDE_DIR = path18.join(os8.homedir(), ".claude");
44562
- var DEFAULT_MANIFEST_PATH3 = path18.join(os8.homedir(), ".skillsmith", "manifest.json");
44920
+ var DEFAULT_HOME_CLAUDE_DIR = path18.join(os7.homedir(), ".claude");
44921
+ var DEFAULT_MANIFEST_PATH3 = path18.join(os7.homedir(), ".skillsmith", "manifest.json");
44563
44922
  async function scanLocalInventory(opts = {}) {
44564
44923
  const startedAt = process.hrtime.bigint();
44565
- const homeDir = opts.homeDir ?? os8.homedir();
44924
+ const homeDir = opts.homeDir ?? os7.homedir();
44566
44925
  const claudeDir = opts.homeDir ? path18.join(opts.homeDir, ".claude") : DEFAULT_HOME_CLAUDE_DIR;
44567
44926
  const manifestPath = opts.manifestPath ?? DEFAULT_MANIFEST_PATH3;
44568
44927
  const warnings = [];
44569
44928
  const entries = [];
44570
44929
  const manifest = loadManifest3(manifestPath);
44571
44930
  entries.push(...scanSkills(path18.join(claudeDir, "skills"), manifest, warnings));
44572
- const agentsSkillsDir = opts.homeDir ? path18.join(opts.homeDir, ".agents", "skills") : path18.join(os8.homedir(), ".agents", "skills");
44931
+ const agentsSkillsDir = opts.homeDir ? path18.join(opts.homeDir, ".agents", "skills") : path18.join(os7.homedir(), ".agents", "skills");
44573
44932
  entries.push(...scanSkills(agentsSkillsDir, manifest, warnings));
44574
44933
  entries.push(...scanCommands(path18.join(claudeDir, "commands"), warnings));
44575
44934
  entries.push(...scanAgents(path18.join(claudeDir, "agents"), warnings));
@@ -44704,7 +45063,7 @@ function coerceDescription2(value) {
44704
45063
  // ../mcp-server/dist/src/audit/security-acceptance.js
44705
45064
  import * as crypto5 from "node:crypto";
44706
45065
  import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2 } from "node:fs";
44707
- import * as os9 from "node:os";
45066
+ import * as os8 from "node:os";
44708
45067
  import * as path19 from "node:path";
44709
45068
 
44710
45069
  // ../mcp-server/dist/src/audit/security-acceptance.types.js
@@ -44716,7 +45075,7 @@ function emptyAcceptanceStore() {
44716
45075
  }
44717
45076
 
44718
45077
  // ../mcp-server/dist/src/audit/security-acceptance.js
44719
- function defaultAcceptancePath(homeDir = os9.homedir()) {
45078
+ function defaultAcceptancePath(homeDir = os8.homedir()) {
44720
45079
  return path19.join(homeDir, ".skillsmith", "audits", "security-acceptance.json");
44721
45080
  }
44722
45081
  function fingerprintTuple(f) {
@@ -44954,10 +45313,10 @@ function isAcceptDisabled() {
44954
45313
 
44955
45314
  // ../mcp-server/dist/src/audit/security-baseline.js
44956
45315
  import * as fs21 from "node:fs";
44957
- import * as os10 from "node:os";
45316
+ import * as os9 from "node:os";
44958
45317
  import * as path20 from "node:path";
44959
45318
  var SECURITY_BASELINE_VERSION = 1;
44960
- function defaultBaselinePath(homeDir = os10.homedir()) {
45319
+ function defaultBaselinePath(homeDir = os9.homedir()) {
44961
45320
  return path20.join(homeDir, ".skillsmith", "audits", "security-baseline.json");
44962
45321
  }
44963
45322
  function emptyBaseline() {
@@ -45045,7 +45404,7 @@ function buildFinding(params) {
45045
45404
  }
45046
45405
  async function runSecurityAudit(opts = {}) {
45047
45406
  const startedAt = process.hrtime.bigint();
45048
- const homeDir = opts.homeDir ?? os11.homedir();
45407
+ const homeDir = opts.homeDir ?? os10.homedir();
45049
45408
  const auditId = opts.auditId ?? newAuditId();
45050
45409
  const threshold = opts.riskThreshold ?? DEFAULT_RISK_THRESHOLD;
45051
45410
  const readContent = opts.readContent ?? defaultReadContent;
@@ -45348,7 +45707,7 @@ function hashDigest(payload) {
45348
45707
  // ../mcp-server/dist/src/audit/namespace-overrides.js
45349
45708
  import * as crypto8 from "node:crypto";
45350
45709
  import * as fs24 from "node:fs/promises";
45351
- import * as os12 from "node:os";
45710
+ import * as os11 from "node:os";
45352
45711
  import * as path22 from "node:path";
45353
45712
 
45354
45713
  // ../mcp-server/dist/src/audit/namespace-overrides.types.js
@@ -45356,7 +45715,7 @@ var CURRENT_VERSION = 1;
45356
45715
 
45357
45716
  // ../mcp-server/dist/src/audit/namespace-overrides.js
45358
45717
  function defaultLedgerPath() {
45359
- return path22.join(os12.homedir(), ".skillsmith", "namespace-overrides.json");
45718
+ return path22.join(os11.homedir(), ".skillsmith", "namespace-overrides.json");
45360
45719
  }
45361
45720
  var ULID_PREFIX = "ovr_";
45362
45721
  function emptyLedger() {
@@ -45524,7 +45883,7 @@ async function copyDirectory2(src, dest) {
45524
45883
 
45525
45884
  // ../mcp-server/dist/src/audit/rename-engine.apply-paths.js
45526
45885
  import * as fs26 from "node:fs/promises";
45527
- import * as os13 from "node:os";
45886
+ import * as os12 from "node:os";
45528
45887
  import * as path24 from "node:path";
45529
45888
  function actionToKind(action) {
45530
45889
  switch (action) {
@@ -45571,7 +45930,7 @@ async function pathExists2(target) {
45571
45930
  }
45572
45931
  }
45573
45932
  async function stageSingleFileForBackup(srcFile) {
45574
- const tmp = await fs26.mkdtemp(path24.join(os13.tmpdir(), "skillsmith-rename-stage-"));
45933
+ const tmp = await fs26.mkdtemp(path24.join(os12.tmpdir(), "skillsmith-rename-stage-"));
45575
45934
  await fs26.copyFile(srcFile, path24.join(tmp, path24.basename(srcFile)));
45576
45935
  return tmp;
45577
45936
  }
@@ -46298,15 +46657,15 @@ var V1_TEMPLATE_PATTERNS = V1_TEMPLATES.map((t) => t.pattern);
46298
46657
  var MS_PER_DAY3 = 24 * 60 * 60 * 1e3;
46299
46658
 
46300
46659
  // ../mcp-server/dist/src/audit/run-inventory-audit.js
46301
- import * as os15 from "node:os";
46660
+ import * as os14 from "node:os";
46302
46661
 
46303
46662
  // ../core/dist/src/audit/exclusions.js
46304
46663
  import { promises as fs30 } from "node:fs";
46305
- import { join as join60 } from "node:path";
46664
+ import { join as join59 } from "node:path";
46306
46665
  var EXCLUSIONS_FILE = "audit-exclusions.json";
46307
46666
  var EMPTY_CONFIG = { version: 1, exclusions: [] };
46308
46667
  function getExclusionsPath(opts) {
46309
- return join60(opts?.configDir ?? getConfigDir(), EXCLUSIONS_FILE);
46668
+ return join59(opts?.configDir ?? getConfigDir(), EXCLUSIONS_FILE);
46310
46669
  }
46311
46670
  async function loadExclusions(opts = {}) {
46312
46671
  const path27 = opts.configPath ?? getExclusionsPath();
@@ -46379,9 +46738,9 @@ function tierAllowsAuditMode(tier, mode) {
46379
46738
 
46380
46739
  // ../mcp-server/dist/src/audit/audit-suggestions.js
46381
46740
  import * as fs31 from "node:fs/promises";
46382
- import * as os14 from "node:os";
46741
+ import * as os13 from "node:os";
46383
46742
  import * as path26 from "node:path";
46384
- var DEFAULT_AUDITS_DIR2 = path26.join(os14.homedir(), ".skillsmith", "audits");
46743
+ var DEFAULT_AUDITS_DIR2 = path26.join(os13.homedir(), ".skillsmith", "audits");
46385
46744
  async function writeAuditSuggestions(auditId, renameSuggestions, recommendedEdits, opts = {}) {
46386
46745
  const auditsDir = opts.auditsDir ?? DEFAULT_AUDITS_DIR2;
46387
46746
  const auditDir = path26.join(auditsDir, auditId);
@@ -46586,7 +46945,7 @@ function hashFileContent(filePath) {
46586
46945
  // ../mcp-server/dist/src/audit/run-inventory-audit.js
46587
46946
  async function runInventoryAudit(opts = {}) {
46588
46947
  const startedAt = process.hrtime.bigint();
46589
- const homeDir = opts.homeDir ?? os15.homedir();
46948
+ const homeDir = opts.homeDir ?? os14.homedir();
46590
46949
  const scan = await scanLocalInventory({
46591
46950
  homeDir,
46592
46951
  ...opts.projectDir !== void 0 ? { projectDir: opts.projectDir } : {}
@@ -46768,10 +47127,10 @@ async function requireConfirmationPhrase(expected, prompt) {
46768
47127
  }
46769
47128
  }
46770
47129
  function ledgerPath() {
46771
- return join62(homedir30(), ".skillsmith", "namespace-overrides.json");
47130
+ return join61(homedir28(), ".skillsmith", "namespace-overrides.json");
46772
47131
  }
46773
47132
  function backupsDir() {
46774
- return join62(homedir30(), ".skillsmith", "backups");
47133
+ return join61(homedir28(), ".skillsmith", "backups");
46775
47134
  }
46776
47135
  function backupLedgerForReset() {
46777
47136
  const src = ledgerPath();
@@ -46780,7 +47139,7 @@ function backupLedgerForReset() {
46780
47139
  fs34.mkdirSync(dir, { recursive: true, mode: 448 });
46781
47140
  const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
46782
47141
  const suffix = crypto12.randomBytes(4).toString("hex");
46783
- const backupFile = join62(dir, `ledger-${ts2}-${suffix}.json`);
47142
+ const backupFile = join61(dir, `ledger-${ts2}-${suffix}.json`);
46784
47143
  fs34.copyFileSync(src, backupFile);
46785
47144
  return backupFile;
46786
47145
  }
@@ -47817,7 +48176,7 @@ import { Command as Command23 } from "commander";
47817
48176
  import { input as input6, confirm as confirm6, select as select4 } from "@inquirer/prompts";
47818
48177
  import ora13 from "ora";
47819
48178
  import { mkdir as mkdir17, writeFile as writeFile15, stat as stat12 } from "fs/promises";
47820
- import { join as join63 } from "path";
48179
+ import { join as join62 } from "path";
47821
48180
  var logger30 = getCliLogger();
47822
48181
  var VALID_TYPES = ["basic", "intermediate", "advanced"];
47823
48182
  var VALID_BEHAVIORS = ["autonomous", "guided", "interactive", "configurable"];
@@ -47953,7 +48312,7 @@ async function createSkill(name, options = {}) {
47953
48312
  default: false
47954
48313
  });
47955
48314
  const outputDir = options.output ?? getCanonicalInstallPath();
47956
- const skillDir = join63(outputDir, skillName);
48315
+ const skillDir = join62(outputDir, skillName);
47957
48316
  let exists = false;
47958
48317
  try {
47959
48318
  await stat12(skillDir);
@@ -48027,16 +48386,16 @@ Thumbs.db
48027
48386
  const spinner = ora13("Scaffolding skill...").start();
48028
48387
  try {
48029
48388
  await mkdir17(skillDir, { recursive: true });
48030
- await mkdir17(join63(skillDir, "resources"), { recursive: true });
48389
+ await mkdir17(join62(skillDir, "resources"), { recursive: true });
48031
48390
  if (includeScripts) {
48032
- await mkdir17(join63(skillDir, "scripts"), { recursive: true });
48391
+ await mkdir17(join62(skillDir, "scripts"), { recursive: true });
48033
48392
  }
48034
- await writeFile15(join63(skillDir, "SKILL.md"), skillMdContent, "utf-8");
48035
- await writeFile15(join63(skillDir, "README.md"), readmeContent, "utf-8");
48036
- await writeFile15(join63(skillDir, "CHANGELOG.md"), changelogContent, "utf-8");
48037
- await writeFile15(join63(skillDir, ".gitignore"), gitignoreContent, "utf-8");
48393
+ await writeFile15(join62(skillDir, "SKILL.md"), skillMdContent, "utf-8");
48394
+ await writeFile15(join62(skillDir, "README.md"), readmeContent, "utf-8");
48395
+ await writeFile15(join62(skillDir, "CHANGELOG.md"), changelogContent, "utf-8");
48396
+ await writeFile15(join62(skillDir, ".gitignore"), gitignoreContent, "utf-8");
48038
48397
  if (includeScripts) {
48039
- await writeFile15(join63(skillDir, "scripts", "example.js"), scriptContent, "utf-8");
48398
+ await writeFile15(join62(skillDir, "scripts", "example.js"), scriptContent, "utf-8");
48040
48399
  }
48041
48400
  spinner.succeed(`Skill scaffolded at ${skillDir}`);
48042
48401
  } catch (error46) {
@@ -48197,7 +48556,7 @@ var RATE_LIMIT_DELAY = 6e4;
48197
48556
  var DEFAULT_IMPORT_DELAY_MS = 150;
48198
48557
  var IMPORT_DELAY_MS = parseInt(process.env["SKILLSMITH_IMPORT_DELAY_MS"] || "", 10) || DEFAULT_IMPORT_DELAY_MS;
48199
48558
  function sleep3(ms) {
48200
- return new Promise((resolve19) => setTimeout(resolve19, ms));
48559
+ return new Promise((resolve20) => setTimeout(resolve20, ms));
48201
48560
  }
48202
48561
  function getBackoffDelay(attempt, baseDelay = 1e3) {
48203
48562
  return Math.min(baseDelay * Math.pow(2, attempt), 3e4);
@@ -48409,13 +48768,13 @@ function createImportCommand() {
48409
48768
 
48410
48769
  // src/commands/import-local.ts
48411
48770
  import { Command as Command26 } from "commander";
48412
- import { resolve as resolve17 } from "node:path";
48771
+ import { resolve as resolve18 } from "node:path";
48413
48772
  import { promises as fs36 } from "node:fs";
48414
48773
 
48415
48774
  // src/commands/import-local.helpers.ts
48416
48775
  import { createHash as createHash19 } from "node:crypto";
48417
48776
  import { promises as fs35 } from "node:fs";
48418
- import { join as join64, resolve as resolve16, dirname as dirname29, basename as basename10, sep as sep5, relative as relative7 } from "node:path";
48777
+ import { join as join63, resolve as resolve17, dirname as dirname29, basename as basename10, sep as sep5, relative as relative7 } from "node:path";
48419
48778
  import matter from "gray-matter";
48420
48779
  var SKILL_FILENAME = "SKILL.md";
48421
48780
  var MAX_DEPTH = 8;
@@ -48423,7 +48782,7 @@ function localSkillId(canonicalPath) {
48423
48782
  return createHash19("sha256").update(canonicalPath).digest("hex").slice(0, 32);
48424
48783
  }
48425
48784
  async function walkSkillFiles(rootDir) {
48426
- const canonicalRoot = await fs35.realpath(rootDir).catch(() => resolve16(rootDir));
48785
+ const canonicalRoot = await fs35.realpath(rootDir).catch(() => resolve17(rootDir));
48427
48786
  const files = [];
48428
48787
  const skipped = [];
48429
48788
  const visited = /* @__PURE__ */ new Set();
@@ -48436,7 +48795,7 @@ async function walkSkillFiles(rootDir) {
48436
48795
  return;
48437
48796
  }
48438
48797
  for (const entry of entries) {
48439
- const entryPath = join64(dir, entry.name);
48798
+ const entryPath = join63(dir, entry.name);
48440
48799
  if (entry.isSymbolicLink()) {
48441
48800
  let realPath;
48442
48801
  try {
@@ -48536,7 +48895,7 @@ function toStringArray(value) {
48536
48895
  var logger33 = getCliLogger();
48537
48896
  var WATCH_DEBOUNCE_MS = 500;
48538
48897
  function resolveRoot(opts) {
48539
- if (opts.path) return resolve17(opts.path);
48898
+ if (opts.path) return resolve18(opts.path);
48540
48899
  if (opts.client) return getInstallPath(opts.client);
48541
48900
  return getCanonicalInstallPath();
48542
48901
  }
@@ -48744,8 +49103,8 @@ function printHumanSummary(result) {
48744
49103
  // src/commands/config.ts
48745
49104
  import * as crypto13 from "node:crypto";
48746
49105
  import * as fs37 from "node:fs";
48747
- import { homedir as homedir31 } from "node:os";
48748
- import { join as join65, dirname as dirname30 } from "node:path";
49106
+ import { homedir as homedir29 } from "node:os";
49107
+ import { join as join64, dirname as dirname30 } from "node:path";
48749
49108
  import { Command as Command27 } from "commander";
48750
49109
  var logger34 = getCliLogger();
48751
49110
  var CONFIG_DIR3 = ".skillsmith";
@@ -48769,7 +49128,7 @@ function isSupportedKey(key) {
48769
49128
  return SUPPORTED_KEYS.includes(key);
48770
49129
  }
48771
49130
  function configPath() {
48772
- return join65(homedir31(), CONFIG_DIR3, CONFIG_FILE3);
49131
+ return join64(homedir29(), CONFIG_DIR3, CONFIG_FILE3);
48773
49132
  }
48774
49133
  function readConfigFile2() {
48775
49134
  const path27 = configPath();
@@ -48887,15 +49246,15 @@ import { Command as Command28 } from "commander";
48887
49246
 
48888
49247
  // src/commands/telemetry.action.ts
48889
49248
  import { existsSync as existsSync28, copyFileSync as copyFileSync2, chmodSync as chmodSync9, mkdirSync as mkdirSync14 } from "node:fs";
48890
- import { homedir as homedir33 } from "node:os";
48891
- import { join as join67, dirname as dirname32 } from "node:path";
48892
- import { readdirSync as readdirSync4, unlinkSync as unlinkSync4, statSync as statSync6 } from "node:fs";
49249
+ import { homedir as homedir31 } from "node:os";
49250
+ import { join as join66, dirname as dirname32 } from "node:path";
49251
+ import { readdirSync as readdirSync4, unlinkSync as unlinkSync5, statSync as statSync6 } from "node:fs";
48893
49252
 
48894
49253
  // src/commands/telemetry.helpers.ts
48895
49254
  import * as crypto14 from "node:crypto";
48896
49255
  import * as fs38 from "node:fs";
48897
- import { join as join66, dirname as dirname31 } from "node:path";
48898
- import { homedir as homedir32 } from "node:os";
49256
+ import { join as join65, dirname as dirname31 } from "node:path";
49257
+ import { homedir as homedir30 } from "node:os";
48899
49258
  var TelemetryHookError = class extends Error {
48900
49259
  constructor(code, message) {
48901
49260
  super(message);
@@ -48906,9 +49265,9 @@ var TelemetryHookError = class extends Error {
48906
49265
  };
48907
49266
  function resolveSettingsPath(scope) {
48908
49267
  if (scope === "user") {
48909
- return join66(homedir32(), ".claude", "settings.json");
49268
+ return join65(homedir30(), ".claude", "settings.json");
48910
49269
  }
48911
- return join66(process.cwd(), ".claude", "settings.json");
49270
+ return join65(process.cwd(), ".claude", "settings.json");
48912
49271
  }
48913
49272
  function loadClaudeSettings(scope) {
48914
49273
  const path27 = resolveSettingsPath(scope);
@@ -49000,10 +49359,10 @@ var PRIVACY_URL = "https://skillsmith.app/privacy#telemetry";
49000
49359
  var DEFAULT_ENDPOINT = "https://vrcnzpmndtroqxxoqkzy.supabase.co/functions/v1/events";
49001
49360
  var ORPHAN_TTL_MS = 60 * 60 * 1e3;
49002
49361
  function hookScriptPath() {
49003
- return join67(homedir33(), ".skillsmith", "hooks", "skill-telemetry.sh");
49362
+ return join66(homedir31(), ".skillsmith", "hooks", "skill-telemetry.sh");
49004
49363
  }
49005
49364
  function runDir() {
49006
- return join67(homedir33(), ".skillsmith", "run");
49365
+ return join66(homedir31(), ".skillsmith", "run");
49007
49366
  }
49008
49367
  function idTail(id) {
49009
49368
  if (!id) return "(none)";
@@ -49016,10 +49375,10 @@ function gcOrphanRunFiles() {
49016
49375
  const now = Date.now();
49017
49376
  for (const f of readdirSync4(dir)) {
49018
49377
  if (!f.startsWith("skill-")) continue;
49019
- const fp = join67(dir, f);
49378
+ const fp = join66(dir, f);
49020
49379
  try {
49021
49380
  const st = statSync6(fp);
49022
- if (now - st.mtimeMs > ORPHAN_TTL_MS) unlinkSync4(fp);
49381
+ if (now - st.mtimeMs > ORPHAN_TTL_MS) unlinkSync5(fp);
49023
49382
  } catch {
49024
49383
  }
49025
49384
  }
@@ -49116,7 +49475,7 @@ async function runStatus() {
49116
49475
  }
49117
49476
  }
49118
49477
  async function runInstallHook(options) {
49119
- const templateSrc = join67(packageRoot(), "templates", "skill-telemetry.sh");
49478
+ const templateSrc = join66(packageRoot(), "templates", "skill-telemetry.sh");
49120
49479
  if (!existsSync28(templateSrc)) {
49121
49480
  throw new Error(
49122
49481
  "skill-telemetry.sh template not found. Ensure the CLI package is fully built: npm run build"
@@ -49160,7 +49519,7 @@ async function runUninstallHook(options) {
49160
49519
  writeClaudeSettings(scope, updated);
49161
49520
  try {
49162
49521
  const scriptPath = hookScriptPath();
49163
- if (existsSync28(scriptPath)) unlinkSync4(scriptPath);
49522
+ if (existsSync28(scriptPath)) unlinkSync5(scriptPath);
49164
49523
  } catch {
49165
49524
  }
49166
49525
  const scopeLabel = scope === "user" ? "~/.claude/settings.json" : "./.claude/settings.json";
@@ -49580,13 +49939,13 @@ function createAgentCommand() {
49580
49939
 
49581
49940
  // src/commands/diagnose.ts
49582
49941
  import { mkdirSync as mkdirSync15, readFileSync as readFileSync26, writeFileSync as writeFileSync16 } from "node:fs";
49583
- import { basename as basename11, dirname as dirname33, resolve as resolve18 } from "node:path";
49942
+ import { basename as basename11, dirname as dirname33, resolve as resolve19 } from "node:path";
49584
49943
  import { Command as Command31 } from "commander";
49585
49944
 
49586
49945
  // src/commands/log-records.helpers.ts
49587
49946
  import { existsSync as existsSync29, readFileSync as readFileSync25, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
49588
- import { homedir as homedir34 } from "node:os";
49589
- import { join as join68 } from "node:path";
49947
+ import { homedir as homedir32 } from "node:os";
49948
+ import { join as join67 } from "node:path";
49590
49949
  var LOG_FILE_PATTERN = /^skillsmith-[a-z]+-\d{4}-\d{2}-\d{2}\.jsonl(\.\d+)?$/;
49591
49950
  var LOG_LEVEL_ORDER = {
49592
49951
  debug: 0,
@@ -49599,12 +49958,12 @@ function isLogLevel(value) {
49599
49958
  return VALID_LEVELS.has(value);
49600
49959
  }
49601
49960
  function resolveLogDir() {
49602
- return process.env["SKILLSMITH_LOG_DIR"] || join68(homedir34(), ".skillsmith", "logs");
49961
+ return process.env["SKILLSMITH_LOG_DIR"] || join67(homedir32(), ".skillsmith", "logs");
49603
49962
  }
49604
49963
  function listLogFiles(dir) {
49605
49964
  if (!existsSync29(dir)) return [];
49606
49965
  try {
49607
- return readdirSync5(dir).filter((name) => LOG_FILE_PATTERN.test(name)).sort().map((name) => join68(dir, name));
49966
+ return readdirSync5(dir).filter((name) => LOG_FILE_PATTERN.test(name)).sort().map((name) => join67(dir, name));
49608
49967
  } catch {
49609
49968
  return [];
49610
49969
  }
@@ -49728,7 +50087,7 @@ function buildBundleContent(summary, files) {
49728
50087
  }
49729
50088
  function writeBundle(bundleOption, summary, files) {
49730
50089
  const rawPath = typeof bundleOption === "string" && bundleOption.length > 0 ? bundleOption : defaultBundlePath();
49731
- const targetPath = resolve18(rawPath);
50090
+ const targetPath = resolve19(rawPath);
49732
50091
  const content = buildBundleContent(summary, files);
49733
50092
  mkdirSync15(dirname33(targetPath), { recursive: true });
49734
50093
  writeFileSync16(targetPath, content, "utf8");
@@ -49790,7 +50149,7 @@ function createDiagnoseCommand() {
49790
50149
 
49791
50150
  // src/commands/logs.ts
49792
50151
  import { existsSync as existsSync30, readFileSync as readFileSync27, statSync as statSync8 } from "node:fs";
49793
- import { join as join69 } from "node:path";
50152
+ import { join as join68 } from "node:path";
49794
50153
  import { Command as Command32 } from "commander";
49795
50154
  var logger39 = getCliLogger();
49796
50155
  var TAIL_SURFACES = ["cli", "mcp", "vscode", "doc-retrieval"];
@@ -49799,7 +50158,7 @@ function todayDateString2() {
49799
50158
  }
49800
50159
  function todaysFilePaths(dir) {
49801
50160
  const date5 = todayDateString2();
49802
- return TAIL_SURFACES.map((surface) => join69(dir, `skillsmith-${surface}-${date5}.jsonl`));
50161
+ return TAIL_SURFACES.map((surface) => join68(dir, `skillsmith-${surface}-${date5}.jsonl`));
49803
50162
  }
49804
50163
  function resolveLevel(raw) {
49805
50164
  if (raw === void 0) return void 0;
@@ -49854,8 +50213,8 @@ async function startTail(dir, level, opts = {}) {
49854
50213
  usePolling: true,
49855
50214
  interval: 100
49856
50215
  });
49857
- await new Promise((resolve19) => {
49858
- watcher.once("ready", resolve19);
50216
+ await new Promise((resolve20) => {
50217
+ watcher.once("ready", resolve20);
49859
50218
  });
49860
50219
  const handleEvent = (path27) => {
49861
50220
  let size;
@@ -49942,10 +50301,10 @@ function shouldShowStartupHeader(commandPath, isTTY) {
49942
50301
 
49943
50302
  // src/utils/node-version.ts
49944
50303
  import { readFileSync as readFileSync28 } from "fs";
49945
- import { join as join70 } from "path";
50304
+ import { join as join69 } from "path";
49946
50305
  function loadMinNodeVersion() {
49947
50306
  try {
49948
- const packageJsonPath2 = join70(packageRoot(), "package.json");
50307
+ const packageJsonPath2 = join69(packageRoot(), "package.json");
49949
50308
  const packageJson2 = JSON.parse(readFileSync28(packageJsonPath2, "utf-8"));
49950
50309
  const engineConstraint = packageJson2.engines?.node ?? ">=22.22.0";
49951
50310
  return engineConstraint.replace(/[>=<^~\s]/g, "");
@@ -50018,14 +50377,14 @@ function checkNodeVersion() {
50018
50377
 
50019
50378
  // src/index.ts
50020
50379
  import { readFileSync as readFileSync29 } from "fs";
50021
- import { join as join71 } from "path";
50380
+ import { join as join70 } from "path";
50022
50381
  var logger40 = getCliLogger();
50023
50382
  var versionError = checkNodeVersion();
50024
50383
  if (versionError) {
50025
50384
  logger40.error(versionError);
50026
50385
  process.exit(1);
50027
50386
  }
50028
- var packageJsonPath = join71(packageRoot(), "package.json");
50387
+ var packageJsonPath = join70(packageRoot(), "package.json");
50029
50388
  var packageJson = JSON.parse(readFileSync29(packageJsonPath, "utf-8"));
50030
50389
  var CLI_VERSION = packageJson.version;
50031
50390
  var program = new Command33();