@hasna/skills 0.8.8 → 0.8.10

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/mcp.js CHANGED
@@ -20019,7 +20019,7 @@ var package_default;
20019
20019
  var init_package = __esm(() => {
20020
20020
  package_default = {
20021
20021
  name: "@hasna/skills",
20022
- version: "0.8.8",
20022
+ version: "0.8.10",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
@@ -20057,6 +20057,7 @@ var init_package = __esm(() => {
20057
20057
  "bin/",
20058
20058
  "migrations/",
20059
20059
  "docs/skill-standard.md",
20060
+ "docs/plugin-admission.md",
20060
20061
  "schemas/",
20061
20062
  "LICENSE",
20062
20063
  "README.md",
@@ -39811,7 +39812,18 @@ function assertAgentPolicyCollections(policy) {
39811
39812
  text(source.path);
39812
39813
  requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
39813
39814
  if (source.hashMode !== undefined)
39814
- requireBound(["bytes", "path-bytes"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode !== "path-bytes" || source.sha256 !== null));
39815
+ requireBound(["bytes", "path-bytes", "claude-plugin-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
39816
+ if (source.hashMode === "claude-plugin-registry") {
39817
+ requireBound(agent === "claude");
39818
+ const managed = array3(source.managedPlugins, 64);
39819
+ requireBound(managed.length > 0);
39820
+ for (const entry of managed) {
39821
+ requireBound(object4(entry) && Object.keys(entry).every((key) => ["bindingId", "storeRoot"].includes(key)));
39822
+ text(entry.storeRoot);
39823
+ requireBound(typeof entry.bindingId === "string" && /^[a-f0-9]{64}$/.test(entry.bindingId));
39824
+ }
39825
+ } else
39826
+ requireBound(source.managedPlugins === undefined);
39815
39827
  if (source.format !== undefined)
39816
39828
  requireBound(["json", "toml", "yaml"].includes(source.format));
39817
39829
  if (source.fields !== undefined)
@@ -40036,10 +40048,10 @@ class HttpProfileClient {
40036
40048
  this.origin = normalizeSkillsApiOrigin(origin);
40037
40049
  this.authority = skillsApiRequestUrl(this.origin, "/api/v1/").replace(/\/+$/, "");
40038
40050
  }
40039
- async request(path, init = {}) {
40051
+ async requestRoute(route, init = {}) {
40040
40052
  let response;
40041
40053
  try {
40042
- response = await fetch(skillsApiRequestUrl(this.origin, `/api/v1${path}`), {
40054
+ response = await fetch(skillsApiRequestUrl(this.origin, route), {
40043
40055
  ...init,
40044
40056
  redirect: "error",
40045
40057
  credentials: "omit",
@@ -40060,6 +40072,9 @@ class HttpProfileClient {
40060
40072
  }
40061
40073
  return response;
40062
40074
  }
40075
+ request(path, init = {}) {
40076
+ return this.requestRoute(`/api/v1${path}`, init);
40077
+ }
40063
40078
  async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
40064
40079
  try {
40065
40080
  return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit)));
@@ -40085,6 +40100,12 @@ class HttpProfileClient {
40085
40100
  invalid();
40086
40101
  return result;
40087
40102
  }
40103
+ async resolvePrincipal() {
40104
+ const result = await this.read(await this.requestRoute("/api/auth/whoami"), 16 * 1024);
40105
+ if (!object5(result) || Object.keys(result).sort().join(",") !== "organization,user" || !object5(result.user) || Object.keys(result.user).sort().join(",") !== "email,id,role" || !object5(result.organization) || Object.keys(result.organization).sort().join(",") !== "id,name,slug" || !identifier(result.user.id) || typeof result.user.email !== "string" || !result.user.email.trim() || !["owner", "admin", "member", "viewer"].includes(String(result.user.role)) || !identifier(result.organization.id) || !identifier(result.organization.slug) || typeof result.organization.name !== "string" || !result.organization.name.trim())
40106
+ invalid();
40107
+ return { userId: result.user.id, accountId: result.organization.id, role: result.user.role };
40108
+ }
40088
40109
  async recordStation(id, input2) {
40089
40110
  if (!identifier(id) || !identifier(input2.profileId) || !identifier(input2.profileRevision) || !Array.isArray(input2.selections) || input2.selections.length > MAX_PROFILE_SELECTIONS)
40090
40111
  throw new Error("Invalid station state");
@@ -47371,6 +47392,66 @@ var init_agent_discovery_path_bytes = __esm(() => {
47371
47392
  init_agent_discovery_bytes();
47372
47393
  });
47373
47394
 
47395
+ // src/lib/plugin-projection.ts
47396
+ var PLUGIN_PROJECTION_LIMITS;
47397
+ var init_plugin_projection = __esm(() => {
47398
+ init_selection_cache();
47399
+ PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
47400
+ });
47401
+
47402
+ // src/lib/plugin-projection-store.ts
47403
+ import { constants as constants5, closeSync as closeSync8, fchmodSync, fstatSync as fstatSync8, fsyncSync, linkSync, lstatSync as lstatSync8, mkdirSync as mkdirSync6, openSync as openSync8, opendirSync, readSync as readSync4, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
47404
+ var READ_FLAGS, WRITE_FLAGS;
47405
+ var init_plugin_projection_store = __esm(() => {
47406
+ init_plugin_projection();
47407
+ READ_FLAGS = constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK;
47408
+ WRITE_FLAGS = constants5.O_WRONLY | constants5.O_CREAT | constants5.O_EXCL | constants5.O_NOFOLLOW | constants5.O_NONBLOCK;
47409
+ });
47410
+
47411
+ // src/lib/selected-manifest.ts
47412
+ function jsonEntry(entries, path) {
47413
+ const entry = entries.find((candidate) => candidate.path === path);
47414
+ if (!entry)
47415
+ return {};
47416
+ try {
47417
+ const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(entry.bytes));
47418
+ if (!value || typeof value !== "object" || Array.isArray(value))
47419
+ throw new Error;
47420
+ return value;
47421
+ } catch {
47422
+ throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected skill has an invalid execution manifest.");
47423
+ }
47424
+ }
47425
+ function describeEntries(entries) {
47426
+ const manifest = jsonEntry(entries, "skill.json"), packageJson = jsonEntry(entries, "package.json");
47427
+ const docs = entries.find((entry) => entry.path === "SKILL.md");
47428
+ const frontmatter = docs ? parseSkillFrontmatter(new TextDecoder().decode(docs.bytes)) : null;
47429
+ const kind = frontmatter?.kind === "instruction" || manifest.kind === "instruction" || packageJson.skills?.kind === "instruction" ? "instruction" : "executable";
47430
+ return { kind, manifest, packageJson };
47431
+ }
47432
+ var init_selected_manifest = __esm(() => {
47433
+ init_skill_validation();
47434
+ init_selection_cache();
47435
+ });
47436
+
47437
+ // src/lib/plugin-admission.ts
47438
+ var init_plugin_admission = __esm(() => {
47439
+ init_profile_client();
47440
+ init_skill_bundle();
47441
+ init_selection_cache();
47442
+ init_selection_resolver();
47443
+ init_plugin_projection();
47444
+ init_plugin_projection_store();
47445
+ init_selected_manifest();
47446
+ });
47447
+
47448
+ // src/lib/plugin-discovery.ts
47449
+ var init_plugin_discovery = __esm(() => {
47450
+ init_plugin_admission();
47451
+ init_plugin_projection();
47452
+ init_plugin_projection_store();
47453
+ });
47454
+
47374
47455
  // src/lib/agent-discovery.ts
47375
47456
  var init_agent_discovery = __esm(() => {
47376
47457
  init_agent_policy_limits();
@@ -47378,12 +47459,17 @@ var init_agent_discovery = __esm(() => {
47378
47459
  init_agent_discovery_directories();
47379
47460
  init_agent_discovery_bytes();
47380
47461
  init_agent_discovery_path_bytes();
47462
+ init_plugin_discovery();
47463
+ init_plugin_admission();
47381
47464
  init_agent_discovery_directories();
47382
47465
  });
47383
47466
 
47384
47467
  // src/lib/agent-adapters.ts
47385
47468
  var init_agent_adapters = () => {};
47386
47469
 
47470
+ // src/lib/agent-codex.ts
47471
+ var init_agent_codex = () => {};
47472
+
47387
47473
  // src/lib/agent-integration.ts
47388
47474
  var init_agent_integration = __esm(() => {
47389
47475
  init_config();
@@ -47391,6 +47477,7 @@ var init_agent_integration = __esm(() => {
47391
47477
  init_agent_bridge();
47392
47478
  init_agent_discovery();
47393
47479
  init_agent_adapters();
47480
+ init_agent_codex();
47394
47481
  init_agent_hermes();
47395
47482
  });
47396
47483
 
@@ -47414,7 +47501,7 @@ function normalizeSkillName(name) {
47414
47501
  }
47415
47502
 
47416
47503
  // src/lib/project-state.ts
47417
- import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
47504
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
47418
47505
  import { join as join16 } from "path";
47419
47506
  function getProjectStateDir(targetDir = process.cwd()) {
47420
47507
  return join16(targetDir, SKILLS_PROJECT_DIR);
@@ -47448,7 +47535,7 @@ function ensureProjectConfig(targetDir = process.cwd()) {
47448
47535
  }
47449
47536
  function saveProjectConfig(config2, targetDir = process.cwd()) {
47450
47537
  const dir = getProjectStateDir(targetDir);
47451
- mkdirSync6(dir, { recursive: true });
47538
+ mkdirSync7(dir, { recursive: true });
47452
47539
  const normalized = normalizeProjectConfig({ ...config2, updatedAt: new Date().toISOString() });
47453
47540
  writeFileSync5(getProjectConfigPath(targetDir), JSON.stringify(normalized, null, 2) + `
47454
47541
  `);
@@ -47535,7 +47622,7 @@ var init_project_state = __esm(() => {
47535
47622
  });
47536
47623
 
47537
47624
  // src/lib/installer.ts
47538
- import { existsSync as existsSync11, readFileSync as readFileSync13, rmSync as rmSync2 } from "fs";
47625
+ import { existsSync as existsSync11, readFileSync as readFileSync13, rmSync as rmSync3 } from "fs";
47539
47626
  import { join as join17 } from "path";
47540
47627
  import { homedir as homedir2 } from "os";
47541
47628
  function getSkillPath(name) {
@@ -47649,6 +47736,43 @@ var init_installer = __esm(() => {
47649
47736
  };
47650
47737
  });
47651
47738
 
47739
+ // src/lib/skill-doc-file.ts
47740
+ function resolveSkillDocFile(file2) {
47741
+ switch (file2) {
47742
+ case undefined:
47743
+ case "":
47744
+ return;
47745
+ case "skill":
47746
+ return "SKILL.md";
47747
+ case "readme":
47748
+ return "README.md";
47749
+ case "claude":
47750
+ return "CLAUDE.md";
47751
+ default:
47752
+ throw new SkillDocFileError("SKILL_DOC_FILE_INVALID", "Unsupported documentation file. Choose skill, readme, or claude.");
47753
+ }
47754
+ }
47755
+ function selectSkillDoc(docs, file2) {
47756
+ const path = resolveSkillDocFile(file2);
47757
+ if (path === undefined)
47758
+ return docs.skillMd || docs.readme || docs.claudeMd || null;
47759
+ const content = path === "SKILL.md" ? docs.skillMd : path === "README.md" ? docs.readme : docs.claudeMd;
47760
+ if (content === null)
47761
+ throw new SkillDocFileError("SKILL_DOC_FILE_MISSING", `Documentation file ${path} was not found.`);
47762
+ return content;
47763
+ }
47764
+ var SkillDocFileError;
47765
+ var init_skill_doc_file = __esm(() => {
47766
+ SkillDocFileError = class SkillDocFileError extends Error {
47767
+ code;
47768
+ constructor(code, message) {
47769
+ super(message);
47770
+ this.code = code;
47771
+ this.name = "SkillDocFileError";
47772
+ }
47773
+ };
47774
+ });
47775
+
47652
47776
  // src/lib/skillinfo.ts
47653
47777
  import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
47654
47778
  import { join as join18 } from "path";
@@ -47674,11 +47798,12 @@ function getSkillDocs(name) {
47674
47798
  claudeMd: readIfExists(join18(skillPath, "CLAUDE.md"))
47675
47799
  };
47676
47800
  }
47677
- function getSkillBestDoc(name) {
47801
+ function getSkillBestDoc(name, file2) {
47802
+ resolveSkillDocFile(file2);
47678
47803
  const docs = getSkillDocs(name);
47679
47804
  if (!docs)
47680
47805
  return null;
47681
- return docs.skillMd || docs.readme || docs.claudeMd || null;
47806
+ return selectSkillDoc(docs, file2);
47682
47807
  }
47683
47808
  function getSkillRequirements(name) {
47684
47809
  const skillPath = getSkillPath(name);
@@ -47856,6 +47981,7 @@ var init_skillinfo = __esm(() => {
47856
47981
  init_installer();
47857
47982
  init_registry();
47858
47983
  init_skill_validation();
47984
+ init_skill_doc_file();
47859
47985
  HOSTED_PROVIDER_ENV_PREFIXES = [
47860
47986
  "OPENAI_",
47861
47987
  "ANTHROPIC_",
@@ -48834,7 +48960,7 @@ var init_remote_workspace_leave = __esm(() => {
48834
48960
  });
48835
48961
 
48836
48962
  // src/lib/auth-store.ts
48837
- import { chmodSync, existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync15, renameSync as renameSync3, statSync as statSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
48963
+ import { chmodSync, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync15, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
48838
48964
  import { basename as basename4, dirname as dirname6, join as join19 } from "path";
48839
48965
  function getAuthFilePath(env = process.env) {
48840
48966
  return skillsCredentialFilePath(env);
@@ -49092,6 +49218,61 @@ var init_remote_quote_errors = __esm(() => {
49092
49218
  });
49093
49219
  });
49094
49220
 
49221
+ // src/lib/remote-permissions.ts
49222
+ function parseSkillsAccess(value) {
49223
+ if (value === undefined)
49224
+ return {};
49225
+ if (!record7(value))
49226
+ throw new Error("Invalid Skills permission contract");
49227
+ const result = {};
49228
+ if (value.scopes !== undefined) {
49229
+ if (!Array.isArray(value.scopes) || value.scopes.length > 256 || value.scopes.some((scope) => typeof scope !== "string" || scope.length > 128 || !/^(?:\*|[a-z][a-z0-9.-]*:[a-z0-9.*-]+)$/.test(scope)))
49230
+ throw new Error("Invalid Skills scope contract");
49231
+ result.scopes = [...value.scopes];
49232
+ }
49233
+ if (value.permissions !== undefined) {
49234
+ if (!record7(value.permissions))
49235
+ throw new Error("Invalid Skills permission contract");
49236
+ result.permissions = {};
49237
+ for (const name of permissionNames) {
49238
+ const permission = value.permissions[name];
49239
+ if (permission === undefined)
49240
+ continue;
49241
+ if (typeof permission !== "boolean")
49242
+ throw new Error("Invalid Skills permission contract");
49243
+ result.permissions[name] = permission;
49244
+ }
49245
+ }
49246
+ return result;
49247
+ }
49248
+ function assertSkillsPermission(access, permission) {
49249
+ if (access.permissions?.[permission] === false)
49250
+ throw new RemoteSkillsPermissionError(permission);
49251
+ }
49252
+ var permissionNames, record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), RemoteSkillsPermissionError;
49253
+ var init_remote_permissions = __esm(() => {
49254
+ permissionNames = [
49255
+ "read",
49256
+ "publish",
49257
+ "profilesWrite",
49258
+ "stationStateWrite",
49259
+ "cloudSubmit",
49260
+ "executionGrantsRead",
49261
+ "executionGrantsWrite",
49262
+ "executionGrantsResolve"
49263
+ ];
49264
+ RemoteSkillsPermissionError = class RemoteSkillsPermissionError extends Error {
49265
+ permission;
49266
+ code = "SKILLS_PERMISSION_DENIED";
49267
+ status = 403;
49268
+ constructor(permission) {
49269
+ super(`The current Skills credential cannot ${permission === "publish" ? "publish skills" : "write shared profiles"}. ` + "Workspace role does not override credential permissions. Ask the workspace administrator to authorize this credential, " + "then check skills auth whoami or skills capabilities. This write request was not sent.");
49270
+ this.permission = permission;
49271
+ this.name = "RemoteSkillsPermissionError";
49272
+ }
49273
+ };
49274
+ });
49275
+
49095
49276
  // src/lib/remote-client.ts
49096
49277
  var exports_remote_client = {};
49097
49278
  __export(exports_remote_client, {
@@ -49210,15 +49391,23 @@ class RemoteSkillsClient {
49210
49391
  }, { quoteRefusal: true });
49211
49392
  return parseRemoteRunQuote(await response.json());
49212
49393
  }
49213
- getCapabilities() {
49214
- if (!this.capabilities)
49394
+ getCapabilities(options = {}) {
49395
+ if (!this.capabilities || options.refresh)
49215
49396
  this.capabilities = (async () => {
49216
- const value = await (await this.requestNewRoute("/api/v1/capabilities")).json();
49397
+ const response = await this.requestNewRoute("/api/v1/capabilities");
49398
+ let value;
49399
+ try {
49400
+ value = await response.json();
49401
+ if (!value || typeof value !== "object" || Array.isArray(value))
49402
+ throw new Error;
49403
+ } catch {
49404
+ throw new Error("Invalid Skills capability response");
49405
+ }
49217
49406
  if (value.contractVersion !== 1 || value.apiVersion !== 1 || !Array.isArray(value.capabilities) || value.capabilities.some((item) => typeof item !== "string"))
49218
49407
  throw new Error("Unsupported Skills server capability contract");
49219
49408
  const billing = value.billing;
49220
49409
  const recurringConsents = parseRecurringCapability(value.recurringConsents);
49221
- return { contractVersion: 1, apiVersion: 1, capabilities: value.capabilities, ...billing ? { billing } : {}, ...recurringConsents ? { recurringConsents } : {} };
49410
+ return { contractVersion: 1, apiVersion: 1, capabilities: value.capabilities, ...parseSkillsAccess(value), ...billing ? { billing } : {}, ...recurringConsents ? { recurringConsents } : {} };
49222
49411
  })();
49223
49412
  return this.capabilities;
49224
49413
  }
@@ -49685,6 +49874,12 @@ class RemoteSkillsClient {
49685
49874
  }
49686
49875
  }
49687
49876
  async publishSkill(manifest, bundle, ifMatch) {
49877
+ try {
49878
+ assertSkillsPermission(await this.getCapabilities({ refresh: true }), "publish");
49879
+ } catch (error61) {
49880
+ if (!(error61 instanceof RemoteRouteUnsupportedError))
49881
+ throw error61;
49882
+ }
49688
49883
  const form = new FormData;
49689
49884
  form.set("manifest", JSON.stringify(manifest));
49690
49885
  if (bundle) {
@@ -49779,13 +49974,13 @@ class RemoteSkillsClient {
49779
49974
  return normalizeUpdatedSincePage(await response.json());
49780
49975
  }
49781
49976
  }
49782
- function requireOptionalString(record7, field) {
49783
- if (record7[field] === undefined)
49977
+ function requireOptionalString(record8, field) {
49978
+ if (record8[field] === undefined)
49784
49979
  return;
49785
- if (typeof record7[field] !== "string") {
49980
+ if (typeof record8[field] !== "string") {
49786
49981
  throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
49787
49982
  }
49788
- return record7[field];
49983
+ return record8[field];
49789
49984
  }
49790
49985
  function isVersionRecord(value) {
49791
49986
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -49807,19 +50002,19 @@ function normalizePin(entry) {
49807
50002
  if (!entry || typeof entry !== "object") {
49808
50003
  throw new Error("Remote pin payload did not match the expected contract (expected an object)");
49809
50004
  }
49810
- const record7 = entry;
49811
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
50005
+ const record8 = entry;
50006
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
49812
50007
  if (!slug2) {
49813
50008
  throw new Error("Remote pin payload did not match the expected contract (missing slug)");
49814
50009
  }
49815
50010
  let metadata;
49816
- if (record7.metadata !== undefined) {
49817
- if (!record7.metadata || typeof record7.metadata !== "object" || Array.isArray(record7.metadata)) {
50011
+ if (record8.metadata !== undefined) {
50012
+ if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
49818
50013
  throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
49819
50014
  }
49820
- metadata = record7.metadata;
50015
+ metadata = record8.metadata;
49821
50016
  }
49822
- const pinnedAt = requireOptionalString(record7, "pinnedAt");
50017
+ const pinnedAt = requireOptionalString(record8, "pinnedAt");
49823
50018
  return {
49824
50019
  slug: slug2,
49825
50020
  ...pinnedAt !== undefined ? { pinnedAt } : {},
@@ -49836,16 +50031,16 @@ function normalizeSkillSummary(entry) {
49836
50031
  if (!entry || typeof entry !== "object") {
49837
50032
  throw new Error("Remote skill payload did not match the expected contract (expected an object)");
49838
50033
  }
49839
- const record7 = entry;
49840
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
50034
+ const record8 = entry;
50035
+ const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
49841
50036
  if (!slug2) {
49842
50037
  throw new Error("Remote skill payload did not match the expected contract (missing slug)");
49843
50038
  }
49844
50039
  return {
49845
50040
  slug: slug2,
49846
- ...requireOptionalString(record7, "name") !== undefined ? { name: requireOptionalString(record7, "name") } : {},
49847
- ...requireOptionalString(record7, "version") !== undefined ? { version: requireOptionalString(record7, "version") } : {},
49848
- ...requireOptionalString(record7, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record7, "updatedAt") } : {}
50041
+ ...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
50042
+ ...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
50043
+ ...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
49849
50044
  };
49850
50045
  }
49851
50046
  function normalizeSkillSummaryList(payload) {
@@ -49898,12 +50093,12 @@ function normalizeUpdatedSincePage(payload) {
49898
50093
  if (!payload || typeof payload !== "object") {
49899
50094
  throw new Error("Updated-since payload did not match the expected contract (expected an object)");
49900
50095
  }
49901
- const record7 = payload;
49902
- if (!Array.isArray(record7.skills)) {
50096
+ const record8 = payload;
50097
+ if (!Array.isArray(record8.skills)) {
49903
50098
  throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
49904
50099
  }
49905
- const skills = record7.skills.map(normalizeSkillSummary);
49906
- const nextCursor = record7.nextCursor === undefined || record7.nextCursor === null ? null : record7.nextCursor;
50100
+ const skills = record8.skills.map(normalizeSkillSummary);
50101
+ const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
49907
50102
  if (nextCursor !== null && typeof nextCursor !== "string") {
49908
50103
  throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
49909
50104
  }
@@ -49929,6 +50124,7 @@ var init_remote_client = __esm(() => {
49929
50124
  init_remote_account();
49930
50125
  init_remote_files();
49931
50126
  init_remote_quote_errors();
50127
+ init_remote_permissions();
49932
50128
  RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
49933
50129
  path;
49934
50130
  status;
@@ -49998,7 +50194,7 @@ function invitationEmailIds(invitationId, challengeId) {
49998
50194
  }
49999
50195
  function invitationEmailInput(action, input2) {
50000
50196
  const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
50001
- if (!record7(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
50197
+ if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
50002
50198
  throw new InvitationEmailInputError;
50003
50199
  const value = { ...input2 };
50004
50200
  const ids = invitationEmailIds(value.invitationId, value.challengeId);
@@ -50027,12 +50223,12 @@ async function requestInvitationEmail(origin, action, input2) {
50027
50223
  signal: AbortSignal.timeout(15000)
50028
50224
  });
50029
50225
  const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
50030
- if (!response.ok && record7(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
50226
+ if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
50031
50227
  const code = parsed.code;
50032
50228
  if (response.status === refusals[code][0])
50033
50229
  throw new RemoteInvitationEmailError(code);
50034
50230
  }
50035
- if (!record7(parsed))
50231
+ if (!record8(parsed))
50036
50232
  throw new RemoteInvitationEmailUnconfirmedError(action);
50037
50233
  if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
50038
50234
  return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
@@ -50051,7 +50247,7 @@ function invitationEmailCustomerError(error61) {
50051
50247
  return { code: error61.code, error: error61.message };
50052
50248
  return { code: "INVITATION_EMAIL_UNAVAILABLE", error: "Unable to prepare this recovery action. Check the explicit server and stable profile. No credential was saved." };
50053
50249
  }
50054
- var InvitationEmailInputError, refusals, RemoteInvitationEmailError, RemoteInvitationEmailUnconfirmedError, record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v), uuid11 = (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);
50250
+ var InvitationEmailInputError, refusals, RemoteInvitationEmailError, RemoteInvitationEmailUnconfirmedError, record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v), uuid11 = (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);
50055
50251
  var init_remote_invitation_recovery = __esm(() => {
50056
50252
  init_fleet_credentials();
50057
50253
  init_remote_files();
@@ -50098,7 +50294,7 @@ function checkedPublicationDeclaration(value) {
50098
50294
  return bad();
50099
50295
  try {
50100
50296
  const manifest = JSON.parse(value.manifestText);
50101
- if (!record8(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
50297
+ if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
50102
50298
  return bad();
50103
50299
  } catch {
50104
50300
  return bad();
@@ -50156,7 +50352,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
50156
50352
  return invalid4();
50157
50353
  }
50158
50354
  if (!response.ok) {
50159
- const code = record8(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
50355
+ const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
50160
50356
  if (code && failures2[code][0] === response.status)
50161
50357
  throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
50162
50358
  throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
@@ -50211,8 +50407,8 @@ class RemotePrivatePublicationsClient {
50211
50407
  if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
50212
50408
  return bad();
50213
50409
  const response = await boundedJson(skillsApiRequestUrl(this.apiOrigin, "/api/v1/capabilities"), {}, this.#token, false, options.timeoutMs, options.signal);
50214
- const p = record8(response) && response.privatePublishing;
50215
- if (!record8(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
50410
+ const p = record9(response) && response.privatePublishing;
50411
+ if (!record9(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
50216
50412
  throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
50217
50413
  return Object.freeze({ ...p });
50218
50414
  }
@@ -50228,7 +50424,7 @@ class RemotePrivatePublicationsClient {
50228
50424
  async#view(path, method, skillId, intentId, declaration, options = {}) {
50229
50425
  const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
50230
50426
  try {
50231
- if (!record8(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
50427
+ if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
50232
50428
  return invalid4();
50233
50429
  return checkedPublicationView(value.upload, skillId, intentId, declaration);
50234
50430
  } catch (error61) {
@@ -50353,7 +50549,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
50353
50549
  throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
50354
50550
  }, invalid4 = () => {
50355
50551
  throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
50356
- }, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record8(v) && Object.keys(v).sort().join(",") === keys.sort().join(","), date6 = (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) => createHash7("sha256").update(bytes).digest("hex");
50552
+ }, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.sort().join(","), date6 = (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) => createHash7("sha256").update(bytes).digest("hex");
50357
50553
  var init_remote_private_publications = __esm(() => {
50358
50554
  init_fleet_credentials();
50359
50555
  init_remote_workspace_selection();
@@ -50417,10 +50613,10 @@ async function requestAuthApi(instance, path, options) {
50417
50613
  const text3 = await res.text();
50418
50614
  const body = text3 ? parseJsonBody(text3) : {};
50419
50615
  if (!res.ok) {
50420
- const record9 = isRecord5(body) ? body : {};
50421
- const detail = typeof record9.detail === "string" ? record9.detail : undefined;
50422
- const error61 = typeof record9.error === "string" ? record9.error : undefined;
50423
- const code = typeof record9.code === "string" ? record9.code : undefined;
50616
+ const record10 = isRecord5(body) ? body : {};
50617
+ const detail = typeof record10.detail === "string" ? record10.detail : undefined;
50618
+ const error61 = typeof record10.error === "string" ? record10.error : undefined;
50619
+ const code = typeof record10.code === "string" ? record10.code : undefined;
50424
50620
  throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
50425
50621
  status: res.status,
50426
50622
  code,
@@ -50630,10 +50826,10 @@ var init_remote_auth = __esm(() => {
50630
50826
  });
50631
50827
 
50632
50828
  // src/lib/workspace-profile.ts
50633
- import { constants as constants5, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync8, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, openSync as openSync8, readFileSync as readFileSync16, renameSync as renameSync4, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
50829
+ import { constants as constants6, closeSync as closeSync9, fstatSync as fstatSync9, lstatSync as lstatSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, openSync as openSync9, readFileSync as readFileSync16, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
50634
50830
  function stat(path) {
50635
50831
  try {
50636
- return lstatSync8(path);
50832
+ return lstatSync9(path);
50637
50833
  } catch (error61) {
50638
50834
  if (error61.code === "ENOENT")
50639
50835
  return null;
@@ -50643,14 +50839,14 @@ function stat(path) {
50643
50839
  function safeText(file2) {
50644
50840
  if (stat(file2) === null)
50645
50841
  return null;
50646
- const fd = openSync8(file2, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
50842
+ const fd = openSync9(file2, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
50647
50843
  try {
50648
- const s = fstatSync8(fd);
50844
+ const s = fstatSync9(fd);
50649
50845
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
50650
50846
  return fail("The selected profile must use bounded owner-only regular files.");
50651
50847
  return readFileSync16(fd, "utf8");
50652
50848
  } finally {
50653
- closeSync8(fd);
50849
+ closeSync9(fd);
50654
50850
  }
50655
50851
  }
50656
50852
  function checkIdentityMetadata(file2, identity2) {
@@ -50862,7 +51058,7 @@ var init_recurring_customer = __esm(() => {
50862
51058
  });
50863
51059
 
50864
51060
  // src/lib/recurring-recovery.ts
50865
- import { constants as constants6, closeSync as closeSync9, fsyncSync, fstatSync as fstatSync9, lstatSync as lstatSync9, mkdirSync as mkdirSync9, openSync as openSync9, readSync as readSync4, realpathSync as realpathSync4, renameSync as renameSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "fs";
51061
+ import { constants as constants7, closeSync as closeSync10, fsyncSync as fsyncSync2, fstatSync as fstatSync10, lstatSync as lstatSync10, mkdirSync as mkdirSync10, openSync as openSync10, readSync as readSync5, realpathSync as realpathSync4, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync8 } from "fs";
50866
51062
  import { dirname as dirname7, isAbsolute as isAbsolute4, join as join20, resolve as resolve4 } from "path";
50867
51063
  import { randomUUID as randomUUID2 } from "crypto";
50868
51064
 
@@ -50874,7 +51070,7 @@ class RecoveryOwner {
50874
51070
  if (!isAbsolute4(directory) || resolve4(directory) !== directory || realpathSync4(directory) !== directory)
50875
51071
  invalid5();
50876
51072
  for (let path = directory;; path = dirname7(path)) {
50877
- const stat2 = lstatSync9(path);
51073
+ const stat2 = lstatSync10(path);
50878
51074
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
50879
51075
  invalid5();
50880
51076
  this.parents.push({ path, dev: stat2.dev, ino: stat2.ino });
@@ -50887,59 +51083,59 @@ class RecoveryOwner {
50887
51083
  if (realpathSync4(this.directory) !== this.directory)
50888
51084
  invalid5();
50889
51085
  for (const prior of this.parents) {
50890
- const now = lstatSync9(prior.path);
51086
+ const now = lstatSync10(prior.path);
50891
51087
  if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
50892
51088
  invalid5();
50893
51089
  }
50894
- const own2 = lstatSync9(this.directory);
51090
+ const own2 = lstatSync10(this.directory);
50895
51091
  if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
50896
51092
  invalid5();
50897
51093
  }
50898
51094
  read(name) {
50899
51095
  this.assert();
50900
- const fd = openSync9(join20(this.directory, name), constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
51096
+ const fd = openSync10(join20(this.directory, name), constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
50901
51097
  try {
50902
- const before = fstatSync9(fd);
51098
+ const before = fstatSync10(fd);
50903
51099
  if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
50904
51100
  invalid5();
50905
51101
  const bytes = Buffer.alloc(before.size + 1);
50906
51102
  let size = 0;
50907
51103
  while (size < bytes.length) {
50908
- const n2 = readSync4(fd, bytes, size, bytes.length - size, size);
51104
+ const n2 = readSync5(fd, bytes, size, bytes.length - size, size);
50909
51105
  if (!n2)
50910
51106
  break;
50911
51107
  size += n2;
50912
51108
  }
50913
- const after = fstatSync9(fd), path = lstatSync9(join20(this.directory, name));
51109
+ const after = fstatSync10(fd), path = lstatSync10(join20(this.directory, name));
50914
51110
  if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
50915
51111
  invalid5();
50916
51112
  this.assert();
50917
51113
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size));
50918
51114
  } finally {
50919
- closeSync9(fd);
51115
+ closeSync10(fd);
50920
51116
  }
50921
51117
  }
50922
51118
  write(name, value) {
50923
51119
  this.assert();
50924
51120
  const bytes = canonicalJson(value, 8192) + `
50925
51121
  `;
50926
- const fd = openSync9(join20(this.directory, name), constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
51122
+ const fd = openSync10(join20(this.directory, name), constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
50927
51123
  try {
50928
51124
  writeFileSync8(fd, bytes);
50929
- fsyncSync(fd);
51125
+ fsyncSync2(fd);
50930
51126
  } finally {
50931
- closeSync9(fd);
51127
+ closeSync10(fd);
50932
51128
  }
50933
51129
  this.assert();
50934
51130
  this.sync();
50935
51131
  }
50936
51132
  sync() {
50937
51133
  this.assert();
50938
- const fd = openSync9(this.directory, constants6.O_RDONLY | constants6.O_NOFOLLOW);
51134
+ const fd = openSync10(this.directory, constants7.O_RDONLY | constants7.O_NOFOLLOW);
50939
51135
  try {
50940
- fsyncSync(fd);
51136
+ fsyncSync2(fd);
50941
51137
  } finally {
50942
- closeSync9(fd);
51138
+ closeSync10(fd);
50943
51139
  }
50944
51140
  }
50945
51141
  saveState(state, expected) {
@@ -50950,30 +51146,30 @@ class RecoveryOwner {
50950
51146
  if (this.read("state.json") !== expected)
50951
51147
  invalid5();
50952
51148
  this.assert();
50953
- renameSync5(join20(this.directory, name), join20(this.directory, "state.json"));
51149
+ renameSync6(join20(this.directory, name), join20(this.directory, "state.json"));
50954
51150
  this.sync();
50955
51151
  }
50956
51152
  async locked(action) {
50957
51153
  this.assert();
50958
51154
  let fd;
50959
51155
  try {
50960
- fd = openSync9(join20(this.directory, "operation.lock"), constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
51156
+ fd = openSync10(join20(this.directory, "operation.lock"), constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
50961
51157
  } catch {
50962
51158
  throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
50963
51159
  }
50964
- const owner = fstatSync9(fd);
51160
+ const owner = fstatSync10(fd);
50965
51161
  try {
50966
51162
  writeFileSync8(fd, JSON.stringify({ pid: process.pid }));
50967
- fsyncSync(fd);
51163
+ fsyncSync2(fd);
50968
51164
  this.sync();
50969
51165
  return await action();
50970
51166
  } finally {
50971
- closeSync9(fd);
51167
+ closeSync10(fd);
50972
51168
  this.assert();
50973
- const now = lstatSync9(join20(this.directory, "operation.lock"));
51169
+ const now = lstatSync10(join20(this.directory, "operation.lock"));
50974
51170
  if (owner.dev !== now.dev || owner.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
50975
51171
  invalid5();
50976
- unlinkSync4(join20(this.directory, "operation.lock"));
51172
+ unlinkSync5(join20(this.directory, "operation.lock"));
50977
51173
  this.sync();
50978
51174
  }
50979
51175
  }
@@ -51008,7 +51204,7 @@ function base(customer, organizationId) {
51008
51204
  function create(directory, intent) {
51009
51205
  if (!isAbsolute4(directory) || resolve4(directory) !== directory || realpathSync4(dirname7(directory)) !== dirname7(directory))
51010
51206
  invalid5();
51011
- mkdirSync9(directory, { mode: 448 });
51207
+ mkdirSync10(directory, { mode: 448 });
51012
51208
  const owner = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
51013
51209
  owner.write(`intent-${intentSha256}.json`, checked);
51014
51210
  owner.write("state.json", { contractVersion: 1, intentSha256, phase: "prepared", consentId: null });
@@ -53104,7 +53300,7 @@ var init_credential_state = __esm(() => {
53104
53300
 
53105
53301
  // src/lib/run-state.ts
53106
53302
  import { createHash as createHash8, randomBytes } from "crypto";
53107
- import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync17, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
53303
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync17, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
53108
53304
  import { extname, join as join21, relative as relative5 } from "path";
53109
53305
  function createSkillRun(params, targetDir = process.cwd()) {
53110
53306
  const now = new Date;
@@ -53115,10 +53311,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
53115
53311
  const runDir = join21(root, "runs", day, id);
53116
53312
  const logsDir = join21(runDir, "logs");
53117
53313
  const exportDir = join21(root, "exports", skillName, id);
53118
- mkdirSync10(logsDir, { recursive: true });
53119
- mkdirSync10(exportDir, { recursive: true });
53120
- mkdirSync10(join21(root, "tmp"), { recursive: true });
53121
- const record9 = {
53314
+ mkdirSync11(logsDir, { recursive: true });
53315
+ mkdirSync11(exportDir, { recursive: true });
53316
+ mkdirSync11(join21(root, "tmp"), { recursive: true });
53317
+ const record10 = {
53122
53318
  id,
53123
53319
  skill: skillName,
53124
53320
  status: params.status ?? "running",
@@ -53136,10 +53332,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
53136
53332
  logsDir: toProjectRelative(targetDir, logsDir)
53137
53333
  }
53138
53334
  };
53139
- const context2 = { targetDir, runDir, exportDir, logsDir, record: record9 };
53335
+ const context2 = { targetDir, runDir, exportDir, logsDir, record: record10 };
53140
53336
  writeRunRecord(context2);
53141
53337
  writeArtifactsManifest(context2, []);
53142
- appendRunEvent(context2, "created", { status: record9.status });
53338
+ appendRunEvent(context2, "created", { status: record10.status });
53143
53339
  return context2;
53144
53340
  }
53145
53341
  function completeSkillRun(context2, patch) {
@@ -53184,9 +53380,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
53184
53380
  if (!existsSync14(runsRoot))
53185
53381
  return null;
53186
53382
  for (const day of readdirSync8(runsRoot)) {
53187
- const record9 = readRunRecord(join21(runsRoot, day, runId));
53188
- if (record9)
53189
- return record9;
53383
+ const record10 = readRunRecord(join21(runsRoot, day, runId));
53384
+ if (record10)
53385
+ return record10;
53190
53386
  }
53191
53387
  return null;
53192
53388
  }
@@ -53335,7 +53531,7 @@ var init_run_routing = __esm(() => {
53335
53531
  // node_modules/@hasna/secrets/dist/sdk.js
53336
53532
  import { isIP as isIP2 } from "net";
53337
53533
  import { spawnSync as spawnSync2 } from "child_process";
53338
- import { closeSync as closeSync10, fstatSync as fstatSync10, openSync as openSync10, readFileSync as readFileSync18 } from "fs";
53534
+ import { closeSync as closeSync11, fstatSync as fstatSync11, openSync as openSync11, readFileSync as readFileSync18 } from "fs";
53339
53535
  import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
53340
53536
  import { createRequire as createRequire2 } from "module";
53341
53537
  import { hostname as osHostname2 } from "os";
@@ -53440,7 +53636,7 @@ function readAppConfigFile2(path) {
53440
53636
  };
53441
53637
  let fd = -1;
53442
53638
  try {
53443
- fd = openSync10(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
53639
+ fd = openSync11(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
53444
53640
  } catch (error61) {
53445
53641
  const code2 = error61.code;
53446
53642
  if (code2 === "ENOENT" || code2 === "ENOTDIR")
@@ -53450,7 +53646,7 @@ function readAppConfigFile2(path) {
53450
53646
  unsafe(`the path could not be opened (${code2 ?? "unknown error"})`);
53451
53647
  }
53452
53648
  try {
53453
- const before = fstatSync10(fd);
53649
+ const before = fstatSync11(fd);
53454
53650
  if (!before.isFile())
53455
53651
  unsafe("the path is not a regular file");
53456
53652
  if (!configFileModeAllowed2(before.mode)) {
@@ -53462,14 +53658,14 @@ function readAppConfigFile2(path) {
53462
53658
  if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
53463
53659
  unsafe("the file exceeds the size limit");
53464
53660
  const bytes = readFileSync18(fd);
53465
- const after = fstatSync10(fd);
53661
+ const after = fstatSync11(fd);
53466
53662
  if (!configFileReadsCoherent2(before, after)) {
53467
53663
  unsafe("the file changed while being read");
53468
53664
  }
53469
53665
  return parseEnvFile2(bytes.toString("utf8"));
53470
53666
  } finally {
53471
53667
  if (fd !== -1)
53472
- closeSync10(fd);
53668
+ closeSync11(fd);
53473
53669
  }
53474
53670
  }
53475
53671
  function readCredentialFile2(path, apiKeyKeys) {
@@ -54635,7 +54831,7 @@ var init_sdk = __esm(() => {
54635
54831
  });
54636
54832
 
54637
54833
  // src/lib/execution-secrets.ts
54638
- import { constants as constants7, closeSync as closeSync11, fstatSync as fstatSync11, openSync as openSync11, readSync as readSync5, realpathSync as realpathSync5 } from "fs";
54834
+ import { constants as constants8, closeSync as closeSync12, fstatSync as fstatSync12, openSync as openSync12, readSync as readSync6, realpathSync as realpathSync5 } from "fs";
54639
54835
  import { hostname as stationHostname } from "os";
54640
54836
  function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
54641
54837
  let secretsAuthority;
@@ -54656,7 +54852,7 @@ function selectedSecretBindingsTemplate(scope, names, createClient = createSecre
54656
54852
  function refuse(code2, message) {
54657
54853
  throw new SkillSelectionError(code2, message);
54658
54854
  }
54659
- function record9(value) {
54855
+ function record10(value) {
54660
54856
  return !!value && typeof value === "object" && !Array.isArray(value);
54661
54857
  }
54662
54858
  function exactKeys(value, keys) {
@@ -54677,7 +54873,7 @@ function declaredSecretNames(value) {
54677
54873
  return value;
54678
54874
  }
54679
54875
  function validateSelectedSecretBindings(value, scope, names) {
54680
- if (!record9(value) || !exactKeys(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record9(value.selection) || !exactKeys(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record9(value.consumer) || !exactKeys(value.consumer, ["stationId", "workspaceDirectory"]) || !record9(value.bindings)) {
54876
+ if (!record10(value) || !exactKeys(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record10(value.selection) || !exactKeys(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record10(value.consumer) || !exactKeys(value.consumer, ["stationId", "workspaceDirectory"]) || !record10(value.bindings)) {
54681
54877
  return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
54682
54878
  }
54683
54879
  for (const [key, expected] of Object.entries({ authority: scope.selection.authority, workspaceId: scope.selection.workspaceId, profileId: scope.profileId, profileRevision: scope.selection.profileRevision, slug: scope.selection.slug, version: scope.selection.version, bundleDigest: scope.selection.bundleDigest })) {
@@ -54870,32 +55066,6 @@ var init_execution_grant_client = __esm(() => {
54870
55066
  init_execution_grants();
54871
55067
  });
54872
55068
 
54873
- // src/lib/selected-manifest.ts
54874
- function jsonEntry(entries, path) {
54875
- const entry = entries.find((candidate) => candidate.path === path);
54876
- if (!entry)
54877
- return {};
54878
- try {
54879
- const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(entry.bytes));
54880
- if (!value || typeof value !== "object" || Array.isArray(value))
54881
- throw new Error;
54882
- return value;
54883
- } catch {
54884
- throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected skill has an invalid execution manifest.");
54885
- }
54886
- }
54887
- function describeEntries(entries) {
54888
- const manifest = jsonEntry(entries, "skill.json"), packageJson = jsonEntry(entries, "package.json");
54889
- const docs = entries.find((entry) => entry.path === "SKILL.md");
54890
- const frontmatter = docs ? parseSkillFrontmatter(new TextDecoder().decode(docs.bytes)) : null;
54891
- const kind = frontmatter?.kind === "instruction" || manifest.kind === "instruction" || packageJson.skills?.kind === "instruction" ? "instruction" : "executable";
54892
- return { kind, manifest, packageJson };
54893
- }
54894
- var init_selected_manifest = __esm(() => {
54895
- init_skill_validation();
54896
- init_selection_cache();
54897
- });
54898
-
54899
55069
  // src/lib/selected-run.ts
54900
55070
  var exports_selected_run = {};
54901
55071
  __export(exports_selected_run, {
@@ -54905,7 +55075,7 @@ __export(exports_selected_run, {
54905
55075
  });
54906
55076
  import { createHash as createHash9 } from "crypto";
54907
55077
  import { spawn } from "child_process";
54908
- import { mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync6 } from "fs";
55078
+ import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync6 } from "fs";
54909
55079
  import { dirname as dirname8, join as join23, resolve as resolve5 } from "path";
54910
55080
  import { tmpdir, hostname as stationHostname2 } from "os";
54911
55081
  async function resolveSelectedRun(spec, profileId, options = {}) {
@@ -54995,7 +55165,7 @@ async function executeSelectedLocal(selected, options = {}) {
54995
55165
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
54996
55166
  });
54997
55167
  const destination = join23(runDirectory, entry.path);
54998
- mkdirSync11(dirname8(destination), { recursive: true, mode: 448 });
55168
+ mkdirSync12(dirname8(destination), { recursive: true, mode: 448 });
54999
55169
  writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
55000
55170
  }
55001
55171
  env.SKILLS_INPUT_JSON = input2;
@@ -55903,7 +56073,7 @@ var init_operation_tools = __esm(() => {
55903
56073
  });
55904
56074
 
55905
56075
  // src/lib/feedback.ts
55906
- import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync12 } from "fs";
56076
+ import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "fs";
55907
56077
  import { dirname as dirname9, join as join25 } from "path";
55908
56078
  import { Database } from "bun:sqlite";
55909
56079
  function getFeedbackDbPath() {
@@ -55913,7 +56083,7 @@ function getFeedbackDb() {
55913
56083
  const dbPath = getFeedbackDbPath();
55914
56084
  const dir = dirname9(dbPath);
55915
56085
  if (!existsSync16(dir))
55916
- mkdirSync12(dir, { recursive: true });
56086
+ mkdirSync13(dir, { recursive: true });
55917
56087
  const db = new Database(dbPath);
55918
56088
  db.exec("PRAGMA journal_mode = WAL");
55919
56089
  db.exec([
@@ -55942,7 +56112,7 @@ function saveFeedback(input2) {
55942
56112
  const path = join25(getDataDir(), "feedback.jsonl");
55943
56113
  const dir = dirname9(path);
55944
56114
  if (!existsSync16(dir))
55945
- mkdirSync12(dir, { recursive: true });
56115
+ mkdirSync13(dir, { recursive: true });
55946
56116
  appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
55947
56117
  `);
55948
56118
  return { saved: true, category, path };
@@ -56103,7 +56273,7 @@ var init_resource_meta_tools = __esm(() => {
56103
56273
  });
56104
56274
 
56105
56275
  // src/lib/scheduler.ts
56106
- import { existsSync as existsSync17, readFileSync as readFileSync19, writeFileSync as writeFileSync11, mkdirSync as mkdirSync13 } from "fs";
56276
+ import { existsSync as existsSync17, readFileSync as readFileSync19, writeFileSync as writeFileSync11, mkdirSync as mkdirSync14 } from "fs";
56107
56277
  import { join as join26 } from "path";
56108
56278
  function getSchedulesPath(targetDir = process.cwd()) {
56109
56279
  return join26(targetDir, ".skills", "schedules.json");
@@ -56121,7 +56291,7 @@ function saveSchedules(data, targetDir = process.cwd()) {
56121
56291
  const path = getSchedulesPath(targetDir);
56122
56292
  const dir = join26(targetDir, ".skills");
56123
56293
  if (!existsSync17(dir))
56124
- mkdirSync13(dir, { recursive: true });
56294
+ mkdirSync14(dir, { recursive: true });
56125
56295
  writeFileSync11(path, JSON.stringify(data, null, 2));
56126
56296
  }
56127
56297
  function validateCronField(expr, min, max, label) {
@@ -56394,7 +56564,7 @@ var init_schedule_tools = __esm(() => {
56394
56564
  import { createHash as createHash10, createHmac } from "crypto";
56395
56565
  import {
56396
56566
  existsSync as existsSync18,
56397
- mkdirSync as mkdirSync14,
56567
+ mkdirSync as mkdirSync15,
56398
56568
  readFileSync as readFileSync20,
56399
56569
  readdirSync as readdirSync10,
56400
56570
  statSync as statSync11,
@@ -56760,20 +56930,20 @@ var init_private_publication_customer = __esm(() => {
56760
56930
  });
56761
56931
 
56762
56932
  // src/lib/private-publication-recovery.ts
56763
- import { constants as constants8, closeSync as closeSync12, fsyncSync as fsyncSync2, fstatSync as fstatSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync15, openSync as openSync12, readSync as readSync6, realpathSync as realpathSync7, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
56933
+ import { constants as constants9, closeSync as closeSync13, fsyncSync as fsyncSync3, fstatSync as fstatSync13, lstatSync as lstatSync11, mkdirSync as mkdirSync16, openSync as openSync13, readSync as readSync7, realpathSync as realpathSync7, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync13 } from "fs";
56764
56934
  import { dirname as dirname11, isAbsolute as isAbsolute7, join as join28, resolve as resolve6 } from "path";
56765
56935
  import { randomUUID as randomUUID3 } from "crypto";
56766
56936
  function safeDirectory(directory2) {
56767
56937
  if (!isAbsolute7(directory2) || directory2 !== resolve6(directory2) || realpathSync7(directory2) !== directory2)
56768
56938
  return fail2();
56769
56939
  for (let path = directory2;; path = dirname11(path)) {
56770
- const stat2 = lstatSync10(path);
56940
+ const stat2 = lstatSync11(path);
56771
56941
  if (!stat2.isDirectory() || stat2.isSymbolicLink())
56772
56942
  return fail2();
56773
56943
  if (path === dirname11(path))
56774
56944
  break;
56775
56945
  }
56776
- const own2 = lstatSync10(directory2);
56946
+ const own2 = lstatSync11(directory2);
56777
56947
  if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
56778
56948
  return fail2();
56779
56949
  return { dev: own2.dev, ino: own2.ino };
@@ -56785,35 +56955,35 @@ function unchangedDirectory(directory2, identity2) {
56785
56955
  }
56786
56956
  function readOwned(directory2, name, max) {
56787
56957
  const identity2 = safeDirectory(directory2), file2 = join28(directory2, name);
56788
- const fd = openSync12(file2, constants8.O_RDONLY | constants8.O_NOFOLLOW);
56958
+ const fd = openSync13(file2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
56789
56959
  try {
56790
- const stat2 = fstatSync12(fd);
56960
+ const stat2 = fstatSync13(fd);
56791
56961
  if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > max || stat2.size < 1 || (stat2.mode & 63) !== 0 || process.getuid && stat2.uid !== process.getuid())
56792
56962
  return fail2();
56793
56963
  const buffer = Buffer.alloc(Math.min(max, stat2.size) + 1);
56794
56964
  let length = 0;
56795
56965
  while (length < buffer.length) {
56796
- const count = readSync6(fd, buffer, length, buffer.length - length, length);
56966
+ const count = readSync7(fd, buffer, length, buffer.length - length, length);
56797
56967
  if (count === 0)
56798
56968
  break;
56799
56969
  length += count;
56800
56970
  }
56801
- const bytes = buffer.subarray(0, length), after = fstatSync12(fd);
56971
+ const bytes = buffer.subarray(0, length), after = fstatSync13(fd);
56802
56972
  unchangedDirectory(directory2, identity2);
56803
56973
  if (bytes.length !== stat2.size || stat2.size !== after.size || stat2.mtimeMs !== after.mtimeMs || stat2.ctimeMs !== after.ctimeMs)
56804
56974
  return fail2();
56805
56975
  return bytes;
56806
56976
  } finally {
56807
- closeSync12(fd);
56977
+ closeSync13(fd);
56808
56978
  }
56809
56979
  }
56810
56980
  function writeOwned(directory2, name, bytes) {
56811
- const fd = openSync12(join28(directory2, name), constants8.O_WRONLY | constants8.O_CREAT | constants8.O_EXCL | constants8.O_NOFOLLOW, 384);
56981
+ const fd = openSync13(join28(directory2, name), constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
56812
56982
  try {
56813
56983
  writeFileSync13(fd, bytes);
56814
- fsyncSync2(fd);
56984
+ fsyncSync3(fd);
56815
56985
  } finally {
56816
- closeSync12(fd);
56986
+ closeSync13(fd);
56817
56987
  }
56818
56988
  }
56819
56989
  function save(directory2, value) {
@@ -56821,12 +56991,12 @@ function save(directory2, value) {
56821
56991
  writeOwned(directory2, temporary, JSON.stringify(value) + `
56822
56992
  `);
56823
56993
  unchangedDirectory(directory2, identity2);
56824
- renameSync6(join28(directory2, temporary), join28(directory2, "receipt.json"));
56825
- const fd = openSync12(directory2, constants8.O_RDONLY | constants8.O_NOFOLLOW);
56994
+ renameSync7(join28(directory2, temporary), join28(directory2, "receipt.json"));
56995
+ const fd = openSync13(directory2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
56826
56996
  try {
56827
- fsyncSync2(fd);
56997
+ fsyncSync3(fd);
56828
56998
  } finally {
56829
- closeSync12(fd);
56999
+ closeSync13(fd);
56830
57000
  }
56831
57001
  }
56832
57002
  function bind(client, receipt) {
@@ -56837,23 +57007,23 @@ async function locked(directory2, action) {
56837
57007
  const identity2 = safeDirectory(directory2), file2 = join28(directory2, "operation.lock");
56838
57008
  let fd;
56839
57009
  try {
56840
- fd = openSync12(file2, constants8.O_WRONLY | constants8.O_CREAT | constants8.O_EXCL | constants8.O_NOFOLLOW, 384);
57010
+ fd = openSync13(file2, constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
56841
57011
  } catch {
56842
57012
  throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
56843
57013
  }
56844
- const lock = fstatSync12(fd);
57014
+ const lock = fstatSync13(fd);
56845
57015
  try {
56846
57016
  writeFileSync13(fd, JSON.stringify({ pid: process.pid }) + `
56847
57017
  `);
56848
- fsyncSync2(fd);
57018
+ fsyncSync3(fd);
56849
57019
  return await action();
56850
57020
  } finally {
56851
- closeSync12(fd);
57021
+ closeSync13(fd);
56852
57022
  unchangedDirectory(directory2, identity2);
56853
- const now = lstatSync10(file2);
57023
+ const now = lstatSync11(file2);
56854
57024
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
56855
57025
  fail2();
56856
- unlinkSync5(file2);
57026
+ unlinkSync6(file2);
56857
57027
  }
56858
57028
  }
56859
57029
  function readPrivatePublicationRecovery(directory2) {
@@ -56904,13 +57074,13 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
56904
57074
  };
56905
57075
  if (!isAbsolute7(recoveryDirectory) || resolve6(recoveryDirectory) !== recoveryDirectory || realpathSync7(dirname11(recoveryDirectory)) !== dirname11(recoveryDirectory))
56906
57076
  return fail2();
56907
- mkdirSync15(recoveryDirectory, { mode: 448 });
57077
+ mkdirSync16(recoveryDirectory, { mode: 448 });
56908
57078
  safeDirectory(recoveryDirectory);
56909
- const parent = openSync12(dirname11(recoveryDirectory), constants8.O_RDONLY | constants8.O_NOFOLLOW);
57079
+ const parent = openSync13(dirname11(recoveryDirectory), constants9.O_RDONLY | constants9.O_NOFOLLOW);
56910
57080
  try {
56911
- fsyncSync2(parent);
57081
+ fsyncSync3(parent);
56912
57082
  } finally {
56913
- closeSync12(parent);
57083
+ closeSync13(parent);
56914
57084
  }
56915
57085
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
56916
57086
  save(recoveryDirectory, receipt);
@@ -57431,7 +57601,7 @@ var WSContext = class {
57431
57601
  var init_websocket = () => {};
57432
57602
 
57433
57603
  // node_modules/@hono/node-server/dist/index.mjs
57434
- import { Http2ServerRequest, constants as constants9 } from "http2";
57604
+ import { Http2ServerRequest, constants as constants10 } from "http2";
57435
57605
  import { Readable } from "stream";
57436
57606
  async function readWithoutBlocking(readPromise) {
57437
57607
  return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(undefined))]);
@@ -57846,7 +58016,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
57846
58016
  incomingWithDrainState[incomingDraining] = true;
57847
58017
  if (incoming instanceof Http2ServerRequest) {
57848
58018
  try {
57849
- incoming.stream?.close?.(constants9.NGHTTP2_NO_ERROR);
58019
+ incoming.stream?.close?.(constants10.NGHTTP2_NO_ERROR);
57850
58020
  } catch {}
57851
58021
  return;
57852
58022
  }