@hasna/skills 0.10.81 → 0.10.82

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/bin/index.js CHANGED
@@ -36888,7 +36888,7 @@ var package_default;
36888
36888
  var init_package = __esm(() => {
36889
36889
  package_default = {
36890
36890
  name: "@hasna/skills",
36891
- version: "0.10.81",
36891
+ version: "0.10.82",
36892
36892
  description: "Skills library for AI coding agents",
36893
36893
  type: "module",
36894
36894
  bin: {
@@ -40624,7 +40624,7 @@ function hashClaudePluginCacheOrphanMarker(path, budget2, changes) {
40624
40624
  if (!before2)
40625
40625
  return null;
40626
40626
  const uid = process.getuid?.();
40627
- if (!before2.isFile() || uid === undefined || before2.uid !== uid || before2.size > 32)
40627
+ if (!before2.isFile() || uid === undefined || before2.uid !== uid || before2.size > 32 || (before2.mode & 73) !== 0)
40628
40628
  throw new Error("Invalid Claude orphan marker file or owner");
40629
40629
  const fd = openSync3(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
40630
40630
  try {
@@ -48216,7 +48216,7 @@ function safe2(path) {
48216
48216
  function same2(before2, after2) {
48217
48217
  return Boolean(after2 && after2.isDirectory() && before2.dev === after2.dev && before2.ino === after2.ino && before2.mtimeMs === after2.mtimeMs && before2.ctimeMs === after2.ctimeMs);
48218
48218
  }
48219
- function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
48219
+ function capture(path, budget2, excludedRoots, omittedRoots = [], rows, claudeMarkers) {
48220
48220
  safe2(path);
48221
48221
  if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
48222
48222
  return { path, sha256: null };
@@ -48244,6 +48244,11 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
48244
48244
  need3(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
48245
48245
  const stat = lstatSync7(child2);
48246
48246
  need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
48247
+ if (claudeMarkers && isClaudePluginCacheOrphanMarker(child2)) {
48248
+ need3(hashClaudePluginCacheOrphanMarker(child2) !== null, "Claude orphan marker changed while reading directory");
48249
+ if (claudeMarkers === "omit")
48250
+ continue;
48251
+ }
48247
48252
  const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
48248
48253
  `;
48249
48254
  budget2.bytes += Buffer.byteLength(row);
@@ -48300,25 +48305,33 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots, tolerance
48300
48305
  witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, "Native discovery directory membership changed outside retired Codex roots"), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
48301
48306
  }
48302
48307
  }
48303
- function captureDiscoveryDirectories(paths, excludedRoots = []) {
48308
+ function captureOrdinaryDirectories(paths, excludedRoots, claudeMarkers) {
48304
48309
  need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
48305
48310
  const budget2 = { entries: 0, bytes: 0 };
48306
48311
  for (const root of excludedRoots)
48307
48312
  safe2(root);
48308
- return paths.map((path) => capture(path, budget2, excludedRoots));
48313
+ return paths.map((path) => capture(path, budget2, excludedRoots, [], undefined, claudeMarkers));
48314
+ }
48315
+ function captureDiscoveryDirectories(paths, excludedRoots = []) {
48316
+ return captureOrdinaryDirectories(paths, excludedRoots, "omit");
48309
48317
  }
48310
48318
  function verifyDiscoveryDirectories(directories, excludedRoots = [], tolerance) {
48311
48319
  need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
48312
48320
  for (const directory of directories)
48313
48321
  need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
48314
48322
  const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
48323
+ let legacy;
48315
48324
  for (let i = 0;i < directories.length; i++)
48316
48325
  if (current[i].sha256 !== directories[i].sha256) {
48326
+ legacy ??= captureOrdinaryDirectories(directories.map((directory) => directory.path), excludedRoots, "retain");
48327
+ if (legacy[i].sha256 === directories[i].sha256)
48328
+ continue;
48317
48329
  witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
48318
48330
  }
48319
48331
  }
48320
48332
  var init_agent_discovery_directories = __esm(() => {
48321
48333
  init_agent_policy_limits();
48334
+ init_claude_plugin_cache_marker();
48322
48335
  init_native_discovery_witness_change();
48323
48336
  });
48324
48337
 
@@ -67851,7 +67864,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
67851
67864
  return invalid3();
67852
67865
  return Object.freeze({ ...value });
67853
67866
  }
67854
- async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false) {
67867
+ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false, readBinding) {
67855
67868
  const controller = new AbortController;
67856
67869
  let reader;
67857
67870
  let response;
@@ -67867,8 +67880,18 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
67867
67880
  redirect: "error",
67868
67881
  credentials: "omit",
67869
67882
  signal: controller.signal,
67870
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }
67883
+ headers: {
67884
+ "Content-Type": "application/json",
67885
+ Authorization: `Bearer ${token}`,
67886
+ ...readBinding ? {
67887
+ "x-skills-user-id": readBinding.userId,
67888
+ "x-skills-workspace-id": readBinding.organizationId,
67889
+ "x-skills-membership-id": readBinding.membershipId
67890
+ } : {}
67891
+ }
67871
67892
  });
67893
+ if (readBinding && response.ok && response.status !== 200)
67894
+ return invalid3();
67872
67895
  const length = response.headers.get("content-length");
67873
67896
  if (length !== null && (!/^\d+$/.test(length) || Number(length) > 65536))
67874
67897
  return invalid3();
@@ -67936,6 +67959,81 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
67936
67959
  response?.body?.cancel().catch(() => {});
67937
67960
  }
67938
67961
  }
67962
+ function historyDate(value) {
67963
+ if (typeof value !== "string")
67964
+ return false;
67965
+ const parts = /^(\d{4})-(\d{2})-(\d{2})(T| )(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|[+-](\d{2})(?::(\d{2}))?)$/.exec(value);
67966
+ if (!parts)
67967
+ return false;
67968
+ const [, y, m, d, separator, h, minute, second, fraction, zone, offsetHour, offsetMinute] = parts;
67969
+ if (separator === " " ? zone === "Z" || (fraction?.length ?? 0) > 6 : zone !== "Z" && offsetMinute === undefined)
67970
+ return false;
67971
+ const year = Number(y), month = Number(m), day = Number(d);
67972
+ const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
67973
+ const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
67974
+ return year > 0 && month >= 1 && month <= 12 && day >= 1 && day <= days[month - 1] && Number(h) <= 23 && Number(minute) <= 59 && Number(second) <= 59 && (zone === "Z" || Number(offsetHour) <= 23 && Number(offsetMinute ?? 0) <= 59);
67975
+ }
67976
+ function privateHistory(value, organizationId, skillId, limit, cursor) {
67977
+ if (!record7(value) || value.organizationId !== organizationId || value.skillId !== skillId || typeof value.slug !== "string" || !/^[a-z0-9-]+$/.test(value.slug) || !(value.currentVersion === null || historyText(value.currentVersion)) || !(value.currentVersionId === null || publicationUuid(value.currentVersionId)) || value.currentVersion === null !== (value.currentVersionId === null) || !(value.nextCursor === null || publicationUuid(value.nextCursor)) || !Array.isArray(value.versions) || value.versions.length > limit)
67978
+ return historyResponse();
67979
+ const seen = new Set;
67980
+ let previous = cursor;
67981
+ const versions = value.versions.map((row) => {
67982
+ if (!record7(row) || !publicationUuid(row.id) || seen.has(row.id) || previous !== undefined && row.id >= previous || !historyText(row.version) || !(row.releasedAt === null || historyDate(row.releasedAt)) || !historyDate(row.createdAt) || row.id === value.currentVersionId !== (row.version === value.currentVersion))
67983
+ return historyResponse();
67984
+ seen.add(row.id);
67985
+ previous = row.id;
67986
+ return Object.freeze({ id: row.id, version: row.version, releasedAt: row.releasedAt, createdAt: row.createdAt });
67987
+ });
67988
+ if (value.nextCursor !== null && (!versions.length || value.nextCursor !== versions.at(-1).id))
67989
+ return historyResponse();
67990
+ return Object.freeze({
67991
+ organizationId,
67992
+ skillId,
67993
+ slug: value.slug,
67994
+ currentVersion: value.currentVersion,
67995
+ currentVersionId: value.currentVersionId,
67996
+ versions: Object.freeze(versions),
67997
+ nextCursor: value.nextCursor
67998
+ });
67999
+ }
68000
+
68001
+ class RemotePrivateSkillHistoryClient {
68002
+ apiOrigin;
68003
+ organizationId;
68004
+ userId;
68005
+ membershipId;
68006
+ #token;
68007
+ constructor(apiUrl, session) {
68008
+ const checked = parseWorkspaceSession(session, { userId: session?.user?.id, membershipId: session?.user?.membershipId });
68009
+ this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
68010
+ this.#token = checked.token;
68011
+ this.organizationId = checked.organization.id;
68012
+ this.userId = checked.user.id;
68013
+ this.membershipId = checked.user.membershipId;
68014
+ Object.freeze(this);
68015
+ }
68016
+ async listVersions(skillId, options = {}) {
68017
+ if (!publicationUuid(skillId) || options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 50) || options.cursor !== undefined && !publicationUuid(options.cursor) || options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
68018
+ return historyInput();
68019
+ const limit = options.limit ?? 20, cursor = options.cursor;
68020
+ const query = new URLSearchParams;
68021
+ if (options.limit !== undefined)
68022
+ query.set("limit", String(limit));
68023
+ if (cursor !== undefined)
68024
+ query.set("cursor", cursor);
68025
+ const path = `/api/v1/skills/${skillId}/versions${query.size ? `?${query}` : ""}`;
68026
+ let value;
68027
+ try {
68028
+ value = await boundedJson(skillsApiRequestUrl(this.apiOrigin, path), { method: "GET" }, this.#token, false, options.timeoutMs, options.signal, false, this);
68029
+ } catch (error) {
68030
+ if (error instanceof PrivatePublicationError && error.code === "INVALID_PUBLICATION_RESPONSE")
68031
+ return historyResponse();
68032
+ throw new PrivatePublicationError("PRIVATE_HISTORY_UNAVAILABLE", "Unable to read private version history. Check the selected server, current membership and fresh sign-in; no skill or credential was changed.", false, error instanceof PrivatePublicationError ? error.status : undefined);
68033
+ }
68034
+ return privateHistory(value, this.organizationId, skillId, limit, cursor);
68035
+ }
68036
+ }
67939
68037
 
67940
68038
  class RemotePrivatePublicationsClient {
67941
68039
  apiOrigin;
@@ -68109,7 +68207,11 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures, PrivatePublica
68109
68207
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
68110
68208
  }, invalid3 = () => {
68111
68209
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
68112
- }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record7(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash31("sha256").update(bytes).digest("hex");
68210
+ }, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record7(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash31("sha256").update(bytes).digest("hex"), historyInput = () => {
68211
+ throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, limit from 1 to 50, and an optional UUID cursor; timeoutMs must be from 1 to 15000.");
68212
+ }, historyResponse = () => {
68213
+ throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_RESPONSE", "The server returned invalid private version history.");
68214
+ }, historyText = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value);
68113
68215
  var init_remote_private_publications = __esm(() => {
68114
68216
  init_fleet_credentials();
68115
68217
  init_remote_workspace_selection();
@@ -89514,6 +89616,10 @@ class RemoteSkillsAuthClient {
89514
89616
  const origin = this.apiOrigin, captured = workspaceContext(context);
89515
89617
  return new RemotePrivatePublicationsClient(origin, await this.switchWorkspace(email4, code, captured));
89516
89618
  }
89619
+ async openPrivateSkillHistory(email4, code, context) {
89620
+ const origin = this.apiOrigin, captured = workspaceContext(context);
89621
+ return new RemotePrivateSkillHistoryClient(origin, await this.switchWorkspace(email4, code, captured));
89622
+ }
89517
89623
  requestInvitationEmailChallenge(input2) {
89518
89624
  return requestInvitationEmail(this.apiOrigin, "challenge", input2);
89519
89625
  }
@@ -116446,7 +116552,7 @@ var init_remote_invitation_tools = __esm(() => {
116446
116552
  });
116447
116553
 
116448
116554
  // src/lib/private-publication-customer.ts
116449
- function preparePrivatePublicationSession(requested) {
116555
+ function preparePrivateSession(requested, action, open2) {
116450
116556
  const selectors = [
116451
116557
  "HASNA_PROFILE",
116452
116558
  "HASNA_HOME",
@@ -116460,7 +116566,7 @@ function preparePrivatePublicationSession(requested) {
116460
116566
  "SKILLS_API_KEY"
116461
116567
  ];
116462
116568
  const before2 = new Map(selectors.map((key2) => [key2, process.env[key2]]));
116463
- const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace("Manage private publications");
116569
+ const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(action);
116464
116570
  const captured = requested ? { ...requested } : undefined;
116465
116571
  const unchanged3 = () => {
116466
116572
  if (selectors.some((key2) => process.env[key2] !== before2.get(key2)) || selectedSkillsProfile(process.env) !== profile)
@@ -116474,12 +116580,18 @@ function preparePrivatePublicationSession(requested) {
116474
116580
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide the observed user and membership IDs, or select an enrolled workspace profile.");
116475
116581
  unchanged3();
116476
116582
  target.unchanged();
116477
- const client2 = await new RemoteSkillsAuthClient(target.origin).openPrivatePublications(email5, code2, context2);
116583
+ const client2 = await open2(new RemoteSkillsAuthClient(target.origin), email5, code2, context2);
116478
116584
  unchanged3();
116479
116585
  target.unchanged();
116480
116586
  return client2;
116481
116587
  } };
116482
116588
  }
116589
+ function preparePrivatePublicationSession(requested) {
116590
+ return preparePrivateSession(requested, "Manage private publications", (auth, email5, code2, context2) => auth.openPrivatePublications(email5, code2, context2));
116591
+ }
116592
+ function preparePrivateSkillHistorySession(requested) {
116593
+ return preparePrivateSession(requested, "Read private version history", (auth, email5, code2, context2) => auth.openPrivateSkillHistory(email5, code2, context2));
116594
+ }
116483
116595
  async function privatePublicationSession(email5, code2, requested) {
116484
116596
  return preparePrivatePublicationSession(requested).verify(email5, code2);
116485
116597
  }
@@ -117201,7 +117313,7 @@ var exports_runtime_mcp = {};
117201
117313
  __export(exports_runtime_mcp, {
117202
117314
  handleMcp: () => handleMcp
117203
117315
  });
117204
- import { existsSync as existsSync33, lstatSync as lstatSync40, mkdirSync as mkdirSync26, readFileSync as readFileSync43, renameSync as renameSync14, rmdirSync as rmdirSync4, statSync as statSync22, writeFileSync as writeFileSync23 } from "fs";
117316
+ import { closeSync as closeSync29, constants as constants28, existsSync as existsSync33, fstatSync as fstatSync29, lstatSync as lstatSync40, mkdirSync as mkdirSync26, openSync as openSync29, readFileSync as readFileSync43, readSync as readSync21, renameSync as renameSync14, rmdirSync as rmdirSync4, statSync as statSync22, writeFileSync as writeFileSync23 } from "fs";
117205
117317
  import { randomUUID as randomUUID10 } from "crypto";
117206
117318
  import { homedir as homedir10 } from "os";
117207
117319
  import { dirname as dirname40, isAbsolute as isAbsolute38, join as join66 } from "path";
@@ -117270,10 +117382,14 @@ async function registerClaudeMcp(command, server2, environment) {
117270
117382
  const desired = { type: "stdio", ...server2, env: environment };
117271
117383
  try {
117272
117384
  const path = claudeUserConfigPath();
117385
+ const firstRun = lstatSync40(path, { throwIfNoEntry: false }) === undefined ? claudeFirstRunPathWitness(path) : undefined;
117273
117386
  const before2 = withClaudeConfigLock(path, () => {
117274
117387
  if (claudeUserConfigPath() !== path)
117275
117388
  throw new Error;
117389
+ firstRun?.();
117276
117390
  const bytes = readClaudeConfig(path);
117391
+ if (firstRun && bytes !== null)
117392
+ throw new Error;
117277
117393
  if (bytes !== null) {
117278
117394
  const backup = `${path}.skills-mcp-${randomUUID10()}.backup`;
117279
117395
  writeFileSync23(backup, bytes, { flag: "wx", mode: 384 });
@@ -117308,11 +117424,11 @@ async function registerClaudeMcp(command, server2, environment) {
117308
117424
  return withClaudeConfigLock(path, () => {
117309
117425
  if (claudeUserConfigPath() !== path)
117310
117426
  throw new Error;
117311
- const current = readClaudeConfig(path);
117427
+ const current = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
117312
117428
  const previous = parseClaudeConfig(before2), data = parseClaudeConfig(current);
117313
117429
  if (exitCode === 0) {
117314
117430
  const actual = isPlainObject4(data.mcpServers) ? data.mcpServers[MCP_SERVER_NAME] : undefined;
117315
- if (!claudeNativeConfigPreserved(previous, data) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
117431
+ if (!claudeNativeConfigPreserved(previous, data, firstRun !== undefined && before2 === null) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
117316
117432
  throw new Error;
117317
117433
  } else {
117318
117434
  if (!cliUnavailable && (!duplicateAccepted || !isPlainObject4(previous.mcpServers) || !previous.mcpServers[MCP_SERVER_NAME]))
@@ -117326,7 +117442,7 @@ async function registerClaudeMcp(command, server2, environment) {
117326
117442
  writeFileSync23(temporary, next, { flag: "wx", mode: 384 });
117327
117443
  if (!readFileSync43(temporary).equals(next))
117328
117444
  throw new Error;
117329
- const latest = readClaudeConfig(path);
117445
+ const latest = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
117330
117446
  if (claudeUserConfigPath() !== path || (before2 === null ? latest !== null : latest === null || !latest.equals(before2)))
117331
117447
  throw new Error;
117332
117448
  renameSync14(temporary, path);
@@ -117360,27 +117476,92 @@ function claudeUserConfigPath() {
117360
117476
  return modern;
117361
117477
  }
117362
117478
  function readClaudeConfig(path) {
117363
- if (!existsSync33(path))
117479
+ const info = lstatSync40(path, { throwIfNoEntry: false });
117480
+ if (info === undefined)
117364
117481
  return null;
117365
- const info = lstatSync40(path);
117366
117482
  if (!info.isFile() || info.size > 16777216)
117367
117483
  throw new Error;
117368
117484
  const bytes = readFileSync43(path);
117369
117485
  parseClaudeConfig(bytes);
117370
117486
  return bytes;
117371
117487
  }
117488
+ function claudeFirstRunPathWitness(path) {
117489
+ if (!process.getuid || constants28.O_NOFOLLOW === undefined)
117490
+ throw new Error;
117491
+ const uid2 = BigInt(process.getuid()), canonical9 = canonicalSystemPath(path);
117492
+ const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}`;
117493
+ const directories = [];
117494
+ for (let cursor2 = dirname40(canonical9);; cursor2 = dirname40(cursor2)) {
117495
+ directories.unshift({ path: cursor2, identity: "" });
117496
+ if (dirname40(cursor2) === cursor2)
117497
+ break;
117498
+ }
117499
+ const verify = () => {
117500
+ if (canonicalSystemPath(path) !== canonical9)
117501
+ throw new Error;
117502
+ for (const directory3 of directories) {
117503
+ const info = lstatSync40(directory3.path, { bigint: true });
117504
+ if (!info.isDirectory() || identity6(info) !== directory3.identity)
117505
+ throw new Error;
117506
+ }
117507
+ };
117508
+ for (const directory3 of directories) {
117509
+ let info = lstatSync40(directory3.path, { bigint: true, throwIfNoEntry: false });
117510
+ if (!info) {
117511
+ mkdirSync26(directory3.path, { mode: 448 });
117512
+ info = lstatSync40(directory3.path, { bigint: true });
117513
+ }
117514
+ if (!info.isDirectory() || info.uid !== 0n && info.uid !== uid2 || (info.mode & 0o022n) !== 0n && !(info.uid === 0n && (info.mode & 0o1000n) !== 0n))
117515
+ throw new Error;
117516
+ directory3.identity = identity6(info);
117517
+ }
117518
+ verify();
117519
+ if (lstatSync40(path, { throwIfNoEntry: false }) !== undefined)
117520
+ throw new Error;
117521
+ return verify;
117522
+ }
117523
+ function readClaudeFirstRunConfig(path, verifyPath) {
117524
+ verifyPath();
117525
+ const before2 = lstatSync40(path, { bigint: true, throwIfNoEntry: false });
117526
+ if (!before2)
117527
+ return null;
117528
+ const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}:${info.nlink}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`;
117529
+ if (!before2.isFile() || before2.nlink !== 1n || before2.uid !== BigInt(process.getuid()) || (before2.mode & 0o022n) !== 0n || before2.size > 16n * 1024n * 1024n)
117530
+ throw new Error;
117531
+ const fd = openSync29(path, constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
117532
+ try {
117533
+ if (identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2))
117534
+ throw new Error;
117535
+ const bytes = Buffer.alloc(Number(before2.size) + 1);
117536
+ let length = 0;
117537
+ while (length < bytes.length) {
117538
+ const count = readSync21(fd, bytes, length, bytes.length - length, null);
117539
+ if (!count)
117540
+ break;
117541
+ length += count;
117542
+ }
117543
+ if (BigInt(length) !== before2.size || identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2) || identity6(lstatSync40(path, { bigint: true })) !== identity6(before2))
117544
+ throw new Error;
117545
+ const content = bytes.subarray(0, length);
117546
+ verifyPath();
117547
+ parseClaudeConfig(content);
117548
+ return content;
117549
+ } finally {
117550
+ closeSync29(fd);
117551
+ }
117552
+ }
117372
117553
  function parseClaudeConfig(bytes) {
117373
117554
  const data = bytes === null ? {} : JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
117374
117555
  if (!isPlainObject4(data) || data.mcpServers !== undefined && !isPlainObject4(data.mcpServers))
117375
117556
  throw new Error;
117376
117557
  return data;
117377
117558
  }
117378
- function claudeNativeConfigPreserved(before2, after2) {
117559
+ function claudeNativeConfigPreserved(before2, after2, firstRun = false) {
117379
117560
  const previous = withoutClaudeSkills(before2), current = withoutClaudeSkills(after2);
117380
117561
  for (const key2 of Object.keys(current)) {
117381
117562
  if (Object.hasOwn(previous, key2))
117382
117563
  continue;
117383
- if (!isClaudeBootstrapAddition(key2, current[key2]))
117564
+ if (!(firstRun && key2 === "userID" && typeof current[key2] === "string" && /^[0-9a-f]{64}$/i.test(current[key2])) && !isClaudeBootstrapAddition(key2, current[key2]))
117384
117565
  return false;
117385
117566
  delete current[key2];
117386
117567
  }
@@ -117562,6 +117743,7 @@ var MCP_SERVER_NAME = "skills", MCP_COMMAND_NAME = "skills-mcp";
117562
117743
  var init_runtime_mcp = __esm(() => {
117563
117744
  init_source();
117564
117745
  init_installer();
117746
+ init_agent_integration();
117565
117747
  init_credential_profile_command();
117566
117748
  init_mcp_registration_environment();
117567
117749
  });
@@ -120456,30 +120638,30 @@ var exports_recurring = {};
120456
120638
  __export(exports_recurring, {
120457
120639
  registerRecurringCommands: () => registerRecurringCommands
120458
120640
  });
120459
- import { constants as constants28, closeSync as closeSync29, fstatSync as fstatSync29, lstatSync as lstatSync43, openSync as openSync29, readSync as readSync21 } from "fs";
120641
+ import { constants as constants29, closeSync as closeSync30, fstatSync as fstatSync30, lstatSync as lstatSync43, openSync as openSync30, readSync as readSync22 } from "fs";
120460
120642
  import { createInterface as createInterface2 } from "readline";
120461
120643
  function readRequest(path) {
120462
- const fd = openSync29(path, constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
120644
+ const fd = openSync30(path, constants29.O_RDONLY | constants29.O_NOFOLLOW | constants29.O_NONBLOCK);
120463
120645
  try {
120464
- const before2 = fstatSync29(fd);
120646
+ const before2 = fstatSync30(fd);
120465
120647
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
120466
120648
  throw new RecurringInputError;
120467
120649
  const bytes = Buffer.alloc(before2.size + 1);
120468
120650
  let length = 0;
120469
120651
  while (length < bytes.length) {
120470
- const n2 = readSync21(fd, bytes, length, bytes.length - length, length);
120652
+ const n2 = readSync22(fd, bytes, length, bytes.length - length, length);
120471
120653
  if (!n2)
120472
120654
  break;
120473
120655
  length += n2;
120474
120656
  }
120475
- const after2 = fstatSync29(fd), current = lstatSync43(path);
120657
+ const after2 = fstatSync30(fd), current = lstatSync43(path);
120476
120658
  if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
120477
120659
  throw new RecurringInputError;
120478
120660
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
120479
120661
  } catch {
120480
120662
  throw new RecurringInputError;
120481
120663
  } finally {
120482
- closeSync29(fd);
120664
+ closeSync30(fd);
120483
120665
  }
120484
120666
  }
120485
120667
  async function acceptAtTerminal(draft) {
@@ -123119,7 +123301,7 @@ var init_claude_installer_binding = __esm(() => {
123119
123301
  });
123120
123302
 
123121
123303
  // src/cli/commands/claude-installer-capture.ts
123122
- import { closeSync as closeSync30, constants as constants29, fstatSync as fstatSync30, lstatSync as lstatSync48, openSync as openSync30, readSync as readSync22 } from "fs";
123304
+ import { closeSync as closeSync31, constants as constants30, fstatSync as fstatSync31, lstatSync as lstatSync48, openSync as openSync31, readSync as readSync23 } from "fs";
123123
123305
  import { isAbsolute as isAbsolute46, resolve as resolve44 } from "path";
123124
123306
  function need11(condition, code2) {
123125
123307
  if (!condition)
@@ -123141,19 +123323,19 @@ function readRequest2(path) {
123141
123323
  const before2 = lstatSync48(path, { throwIfNoEntry: false });
123142
123324
  if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
123143
123325
  throw new CaptureRefusal("INVALID_REQUEST_FILE: --request must name a regular non-symlink JSON file no larger than 64 KiB");
123144
- const fd = openSync30(path, constants29.O_RDONLY | (constants29.O_NOFOLLOW ?? 0) | constants29.O_NONBLOCK);
123326
+ const fd = openSync31(path, constants30.O_RDONLY | (constants30.O_NOFOLLOW ?? 0) | constants30.O_NONBLOCK);
123145
123327
  try {
123146
- const opened = fstatSync30(fd);
123328
+ const opened = fstatSync31(fd);
123147
123329
  need11(opened.isFile() && opened.dev === before2.dev && opened.ino === before2.ino && opened.size === before2.size, "INVALID_REQUEST_FILE: --request must remain the same regular file while read");
123148
123330
  const bytes = Buffer.alloc(MAX_REQUEST_BYTES + 1);
123149
123331
  let length = 0;
123150
123332
  while (length < bytes.length) {
123151
- const count = readSync22(fd, bytes, length, bytes.length - length, null);
123333
+ const count = readSync23(fd, bytes, length, bytes.length - length, null);
123152
123334
  if (!count)
123153
123335
  break;
123154
123336
  length += count;
123155
123337
  }
123156
- const after2 = fstatSync30(fd), current = lstatSync48(path);
123338
+ const after2 = fstatSync31(fd), current = lstatSync48(path);
123157
123339
  need11(length <= MAX_REQUEST_BYTES && length === opened.size && after2.size === opened.size && after2.mtimeMs === opened.mtimeMs && after2.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "INVALID_REQUEST_FILE: --request must remain unchanged while read");
123158
123340
  try {
123159
123341
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
@@ -123161,7 +123343,7 @@ function readRequest2(path) {
123161
123343
  throw new CaptureRefusal("INVALID_REQUEST_JSON: --request must contain one valid UTF-8 JSON object");
123162
123344
  }
123163
123345
  } finally {
123164
- closeSync30(fd);
123346
+ closeSync31(fd);
123165
123347
  }
123166
123348
  }
123167
123349
  function paths(value) {
@@ -123305,7 +123487,7 @@ var exports_agent_integration = {};
123305
123487
  __export(exports_agent_integration, {
123306
123488
  registerAgentIntegration: () => registerAgentIntegration
123307
123489
  });
123308
- import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as readSync23, writeFileSync as writeFileSync27 } from "fs";
123490
+ import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as readSync24, writeFileSync as writeFileSync27 } from "fs";
123309
123491
  import { createHash as createHash48 } from "crypto";
123310
123492
  import { homedir as homedir14 } from "os";
123311
123493
  import { basename as basename25, isAbsolute as isAbsolute47, resolve as resolve45 } from "path";
@@ -123420,7 +123602,7 @@ function registerAgentIntegration(parent) {
123420
123602
  const bytes = Buffer.alloc(1024 * 1024 + 1);
123421
123603
  let length = 0;
123422
123604
  while (length < bytes.length) {
123423
- const count = readSync23(0, bytes, length, bytes.length - length, null);
123605
+ const count = readSync24(0, bytes, length, bytes.length - length, null);
123424
123606
  if (!count)
123425
123607
  break;
123426
123608
  length += count;
@@ -123976,17 +124158,17 @@ var exports_profiles = {};
123976
124158
  __export(exports_profiles, {
123977
124159
  registerProfiles: () => registerProfiles
123978
124160
  });
123979
- import { closeSync as closeSync31, constants as constants30, fstatSync as fstatSync31, openSync as openSync31, readSync as readSync24, writeFileSync as writeFileSync28 } from "fs";
124161
+ import { closeSync as closeSync32, constants as constants31, fstatSync as fstatSync32, openSync as openSync32, readSync as readSync25, writeFileSync as writeFileSync28 } from "fs";
123980
124162
  function readProfileInput(path) {
123981
- const fd = openSync31(path, constants30.O_RDONLY | constants30.O_NONBLOCK);
124163
+ const fd = openSync32(path, constants31.O_RDONLY | constants31.O_NONBLOCK);
123982
124164
  try {
123983
- const stat3 = fstatSync31(fd);
124165
+ const stat3 = fstatSync32(fd);
123984
124166
  if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
123985
124167
  throw new Error("Profile input exceeds the size limit or is not a regular file");
123986
124168
  const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
123987
124169
  let size2 = 0;
123988
124170
  while (size2 < bytes.length) {
123989
- const read3 = readSync24(fd, bytes, size2, bytes.length - size2, null);
124171
+ const read3 = readSync25(fd, bytes, size2, bytes.length - size2, null);
123990
124172
  if (!read3)
123991
124173
  break;
123992
124174
  size2 += read3;
@@ -123995,7 +124177,7 @@ function readProfileInput(path) {
123995
124177
  throw new Error("Profile input exceeds the size limit");
123996
124178
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
123997
124179
  } finally {
123998
- closeSync31(fd);
124180
+ closeSync32(fd);
123999
124181
  }
124000
124182
  }
124001
124183
  function registerProfiles(parent) {
@@ -124409,23 +124591,23 @@ __export(exports_grants, {
124409
124591
  registerGrants: () => registerGrants
124410
124592
  });
124411
124593
  import {
124412
- constants as constants31,
124413
- closeSync as closeSync32,
124414
- fstatSync as fstatSync32,
124415
- openSync as openSync32,
124416
- readSync as readSync25,
124594
+ constants as constants32,
124595
+ closeSync as closeSync33,
124596
+ fstatSync as fstatSync33,
124597
+ openSync as openSync33,
124598
+ readSync as readSync26,
124417
124599
  writeFileSync as writeFileSync29
124418
124600
  } from "fs";
124419
124601
  function readInput(path) {
124420
- const fd = openSync32(path, constants31.O_RDONLY | constants31.O_NONBLOCK);
124602
+ const fd = openSync33(path, constants32.O_RDONLY | constants32.O_NONBLOCK);
124421
124603
  try {
124422
- const stat3 = fstatSync32(fd);
124604
+ const stat3 = fstatSync33(fd);
124423
124605
  if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
124424
124606
  throw new Error("Grant input must be a regular file within the policy size limit.");
124425
124607
  const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
124426
124608
  let size2 = 0;
124427
124609
  while (size2 < bytes.length) {
124428
- const count = readSync25(fd, bytes, size2, bytes.length - size2, null);
124610
+ const count = readSync26(fd, bytes, size2, bytes.length - size2, null);
124429
124611
  if (!count)
124430
124612
  break;
124431
124613
  size2 += count;
@@ -124438,7 +124620,7 @@ function readInput(path) {
124438
124620
  throw new Error("Grant input must be a JSON document containing a grants array.");
124439
124621
  }
124440
124622
  } finally {
124441
- closeSync32(fd);
124623
+ closeSync33(fd);
124442
124624
  }
124443
124625
  }
124444
124626
  function registerGrants(parent) {
@@ -125221,17 +125403,17 @@ var exports_metadata = {};
125221
125403
  __export(exports_metadata, {
125222
125404
  registerMetadata: () => registerMetadata
125223
125405
  });
125224
- import { closeSync as closeSync33, constants as constants32, fstatSync as fstatSync33, openSync as openSync33, readFileSync as readFileSync53, readSync as readSync26, writeFileSync as writeFileSync32 } from "fs";
125406
+ import { closeSync as closeSync34, constants as constants33, fstatSync as fstatSync34, openSync as openSync34, readFileSync as readFileSync53, readSync as readSync27, writeFileSync as writeFileSync32 } from "fs";
125225
125407
  function readPlan(path) {
125226
- const fd = openSync33(path, constants32.O_RDONLY | constants32.O_NONBLOCK | constants32.O_NOFOLLOW);
125408
+ const fd = openSync34(path, constants33.O_RDONLY | constants33.O_NONBLOCK | constants33.O_NOFOLLOW);
125227
125409
  try {
125228
- const stat3 = fstatSync33(fd);
125410
+ const stat3 = fstatSync34(fd);
125229
125411
  if (!stat3.isFile() || stat3.size > 8 * 1024 * 1024)
125230
125412
  throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
125231
125413
  const bytes = Buffer.alloc(stat3.size + 1);
125232
125414
  let size2 = 0;
125233
125415
  while (size2 < bytes.length) {
125234
- const count = readSync26(fd, bytes, size2, bytes.length - size2, null);
125416
+ const count = readSync27(fd, bytes, size2, bytes.length - size2, null);
125235
125417
  if (!count)
125236
125418
  break;
125237
125419
  size2 += count;
@@ -125240,7 +125422,7 @@ function readPlan(path) {
125240
125422
  throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
125241
125423
  return metadataPlan(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2))));
125242
125424
  } finally {
125243
- closeSync33(fd);
125425
+ closeSync34(fd);
125244
125426
  }
125245
125427
  }
125246
125428
  function failure(error61) {
@@ -125606,7 +125788,7 @@ var init_registry_sync = __esm(() => {
125606
125788
  });
125607
125789
 
125608
125790
  // src/lib/review-export.ts
125609
- import { constants as constants33, closeSync as closeSync34, existsSync as existsSync38, fstatSync as fstatSync34, fsyncSync as fsyncSync10, lstatSync as lstatSync51, openSync as openSync34, realpathSync as realpathSync25, statSync as statSync27, writeFileSync as writeFileSync34 } from "fs";
125791
+ import { constants as constants34, closeSync as closeSync35, existsSync as existsSync38, fstatSync as fstatSync35, fsyncSync as fsyncSync10, lstatSync as lstatSync51, openSync as openSync35, realpathSync as realpathSync25, statSync as statSync27, writeFileSync as writeFileSync34 } from "fs";
125610
125792
  import { basename as basename26, dirname as dirname52, isAbsolute as isAbsolute49, join as join80, parse as parse13, resolve as resolve48, sep as sep25 } from "path";
125611
125793
  function exactVersion(spec) {
125612
125794
  const at2 = spec.indexOf("@");
@@ -125670,16 +125852,16 @@ async function exportSkillVersionForReview(spec, output2, client2) {
125670
125852
  if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
125671
125853
  throw new Error("Published bundle bytes do not match the exact version metadata.");
125672
125854
  }
125673
- const fd = openSync34(target, constants33.O_WRONLY | constants33.O_CREAT | constants33.O_EXCL | constants33.O_NOFOLLOW, 384);
125855
+ const fd = openSync35(target, constants34.O_WRONLY | constants34.O_CREAT | constants34.O_EXCL | constants34.O_NOFOLLOW, 384);
125674
125856
  try {
125675
125857
  writeFileSync34(fd, bytes);
125676
125858
  fsyncSync10(fd);
125677
- if (fstatSync34(fd).size !== bytes.byteLength)
125859
+ if (fstatSync35(fd).size !== bytes.byteLength)
125678
125860
  throw new Error("Incomplete review output write.");
125679
125861
  } catch (error61) {
125680
125862
  throw new Error(`Review output write failed. A private partial file may remain at ${target}; use Trash to remove it before reusing this path.`, { cause: error61 });
125681
125863
  } finally {
125682
- closeSync34(fd);
125864
+ closeSync35(fd);
125683
125865
  }
125684
125866
  return { slug: slug2, version: version2, bundleSha256: metadata2.bundleSha256.toLowerCase(), bundleByteSize: bytes.byteLength, output: target };
125685
125867
  }
@@ -126217,7 +126399,7 @@ function verifySessionOptions(options) {
126217
126399
  if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
126218
126400
  throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
126219
126401
  if (!options.codeStdin && (options.json || !process.stdin.isTTY || !process.stderr.isTTY))
126220
- throw new PrivatePublicationError("PUBLICATION_CODE_REQUIRED", "Use --code-stdin with a fresh code for noninteractive publishing.");
126402
+ throw new PrivatePublicationError("PUBLICATION_CODE_REQUIRED", "Use --code-stdin with a fresh code for noninteractive private-skill commands.");
126221
126403
  }
126222
126404
  function verifyOptions(options, action) {
126223
126405
  verifySessionOptions(options);
@@ -126273,6 +126455,45 @@ function registerPrivatePublications(parent) {
126273
126455
  process.exitCode = 1;
126274
126456
  }
126275
126457
  });
126458
+ group.command("versions").allowExcessArguments(false).description("Read one page of a private skill's versions and current version using fresh interactive sign-in").argument("<skill-id>", "Private or team skill UUID from the workspace catalog or create result").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--limit <count>", "Page size from 1 to 50", "20").option("--cursor <uuid>", "Read the next page using its returned cursor").option("--json", "Output validated history metadata without credentials or source content").action(async (skillId, options) => {
126459
+ try {
126460
+ if (!publicationUuid(skillId) || !/^[1-9]\d?$/.test(options.limit) || Number(options.limit) > 50 || options.cursor !== undefined && !publicationUuid(options.cursor))
126461
+ throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, --limit from 1 to 50, and an optional UUID --cursor.");
126462
+ verifySessionOptions(options);
126463
+ const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
126464
+ const pending = preparePrivateSkillHistorySession(context2);
126465
+ let code2;
126466
+ if (options.codeStdin)
126467
+ code2 = await readCode();
126468
+ else {
126469
+ await new RemoteSkillsAuthClient(pending.origin).requestCode(options.email);
126470
+ code2 = await promptCode();
126471
+ }
126472
+ if (code2 === null)
126473
+ return;
126474
+ const client2 = await pending.verify(options.email, code2);
126475
+ const history = await client2.listVersions(skillId, { limit: Number(options.limit), cursor: options.cursor });
126476
+ if (options.json)
126477
+ console.log(JSON.stringify(history));
126478
+ else {
126479
+ console.log(`Private versions of ${history.slug} (${history.skillId})`);
126480
+ console.log(`Current version: ${history.currentVersion ?? "Not published yet"}`);
126481
+ if (!history.versions.length)
126482
+ console.log("No versions on this page.");
126483
+ for (const version2 of history.versions)
126484
+ console.log(` ${version2.version}${version2.id === history.currentVersionId ? " (current)" : ""} published: ${version2.releasedAt ?? "Not released"} created: ${version2.createdAt}`);
126485
+ if (history.nextCursor)
126486
+ console.log(`More versions: repeat this command with --cursor ${history.nextCursor} and fresh verification.`);
126487
+ }
126488
+ } catch (error61) {
126489
+ const result2 = error61 instanceof PrivatePublicationError ? privatePublicationCustomerError(error61) : { error: "Unable to read private version history. Check the selected account, workspace and fresh verification; no skill or credential was changed.", code: "PRIVATE_HISTORY_UNAVAILABLE", uncertain: false };
126490
+ if (options.json)
126491
+ console.log(JSON.stringify(result2));
126492
+ else
126493
+ console.error(result2.error);
126494
+ process.exitCode = 1;
126495
+ }
126496
+ });
126276
126497
  const publishCommand = group.command("publish").allowExcessArguments(false).description("Publish private source with explicit current-version comparison").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs").option("--confirm", "Explicitly approve this action").argument("<directory>", "Validated local skill directory").requiredOption("--skill-id <uuid>", "Existing private/team skill UUID").option("--expected-current-version <uuid>", "Compare against the observed current version UUID").option("--expect-empty", "Require the skill to have no current version").option("--idempotency-key <uuid>", "Stable intent key; generated and saved before begin when omitted").option("--wait-seconds <seconds>", "Bounded status wait from 0 to 300", "60");
126277
126498
  const statusCommand = group.command("status").allowExcessArguments(false).description("Inspect the exact saved publication").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs");
126278
126499
  const resumeCommand = group.command("resume").allowExcessArguments(false).description("Reconcile the saved intent without creating a replacement").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs").option("--confirm", "Explicitly approve this action").option("--wait-seconds <seconds>", "Bounded status wait from 0 to 300", "60");