@hasna/skills 0.10.89 → 0.10.91

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.89",
36891
+ version: "0.10.91",
36892
36892
  description: "Skills library for AI coding agents",
36893
36893
  type: "module",
36894
36894
  bin: {
@@ -36932,6 +36932,7 @@ var init_package = __esm(() => {
36932
36932
  "docs/runtime-activation.md",
36933
36933
  "schemas/",
36934
36934
  "LICENSE",
36935
+ "THIRD_PARTY_NOTICES",
36935
36936
  "README.md",
36936
36937
  "!dist/**/*test-utils.d.ts",
36937
36938
  "!dist/**/*fixtures.d.ts"
@@ -36939,9 +36940,9 @@ var init_package = __esm(() => {
36939
36940
  main: "./dist/index.js",
36940
36941
  types: "./dist/index.d.ts",
36941
36942
  scripts: {
36942
- clean: "rm -rf bin/ dist/",
36943
- build: "bun run clean && bun build --external @hasna/contracts/kernel-lock ./src/cli/index.tsx --outdir ./bin --target bun && bun build --external @modelcontextprotocol/sdk ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build --external @hasna/contracts/kernel-lock ./src/server/maintenance.ts --outfile ./bin/maintenance.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36944
- "build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36943
+ clean: "rm -rf bin/ dist/ THIRD_PARTY_NOTICES",
36944
+ build: "bun run clean && bun build --external @hasna/secrets --external @hasna/contracts/kernel-lock ./src/cli/index.tsx --outdir ./bin --target bun && bun build --external @hasna/secrets --external @modelcontextprotocol/sdk ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build --external @hasna/secrets --external @hasna/contracts/kernel-lock ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build --external @hasna/secrets --external @hasna/contracts/kernel-lock ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build --external @hasna/secrets --external @hasna/contracts/kernel-lock ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build --external @hasna/secrets --external @hasna/contracts/kernel-lock ./src/server/maintenance.ts --outfile ./bin/maintenance.js --target bun && bun build --external @hasna/secrets ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts && bun scripts/third-party-notices.ts",
36945
+ "build:js": "rm -rf dist && bun build --external @hasna/secrets ./src/index.ts ./src/storage.ts ./src/sdk/index.ts ./src/admin-contract.ts ./src/runtime-prerequisites.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist && bun scripts/stage-kernel-lock-assets.ts",
36945
36946
  test: "bun test --timeout 30000",
36946
36947
  dev: "bun run ./src/cli/index.tsx",
36947
36948
  "dev:watch": "bun --watch run ./src/cli/index.tsx",
@@ -36992,7 +36993,6 @@ var init_package = __esm(() => {
36992
36993
  "@aws-sdk/client-ecs": "^3.1079.0",
36993
36994
  "@aws-sdk/client-s3": "^3.1079.0",
36994
36995
  "@hasna/events": "0.1.18",
36995
- "@hasna/secrets": "0.4.2",
36996
36996
  "@modelcontextprotocol/sdk": "^1.26.0",
36997
36997
  chalk: "^5.3.0",
36998
36998
  commander: "^12.1.0",
@@ -37004,6 +37004,9 @@ var init_package = __esm(() => {
37004
37004
  zod: "^4.3.6",
37005
37005
  "@hasna/contracts": "1.3.5"
37006
37006
  },
37007
+ optionalDependencies: {
37008
+ "@hasna/secrets": "0.4.2"
37009
+ },
37007
37010
  engines: {
37008
37011
  bun: ">=1.0.0"
37009
37012
  },
@@ -55539,6 +55542,9 @@ async function resolveSkillsConnection(env3 = process.env, options = {}) {
55539
55542
  completed = await completePointerCredential(SKILLS_APP, pointer, explicitVault ? snapshotEnv : env3);
55540
55543
  } catch (error) {
55541
55544
  const translated = asSkillsFleetCredentialError(error, pointer.pointerVaultKey);
55545
+ if (translated?.message.includes("(@hasna/secrets) is not installed")) {
55546
+ throw new SkillsFleetCredentialError(`${translated.message} @hasna/secrets is optional and private: install it with access to it.`, "MISSING_API_CREDENTIAL");
55547
+ }
55542
55548
  if (translated)
55543
55549
  throw translated;
55544
55550
  throw error;
@@ -96948,1312 +96954,19 @@ var init_cloud_executions = __esm(() => {
96948
96954
  init_fleet_credentials();
96949
96955
  });
96950
96956
 
96951
- // node_modules/@hasna/secrets/dist/sdk.js
96952
- import { isIP as isIP3 } from "net";
96953
- import { spawnSync as spawnSync5 } from "child_process";
96954
- import { closeSync as closeSync26, fstatSync as fstatSync26, openSync as openSync26, readFileSync as readFileSync38 } from "fs";
96955
- import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
96956
- import { createRequire as createRequire2 } from "module";
96957
- import { hostname as osHostname2 } from "os";
96958
- import { isAbsolute as isAbsolute34, join as join60 } from "path";
96959
- import { createRequire as createRequire22 } from "module";
96960
- function envToken2(name) {
96961
- return name.toUpperCase().replace(/-/g, "_");
96962
- }
96963
- function clientTransportEnvKeys2(name) {
96964
- const envSegment = envToken2(name);
96965
- return {
96966
- apiUrlKeys: [`HASNA_${envSegment}_API_URL`, `${envSegment}_API_URL`],
96967
- apiKeyKeys: [`HASNA_${envSegment}_API_KEY`, `${envSegment}_API_KEY`]
96968
- };
96969
- }
96970
- function credentialOverrideEnvKey2(name) {
96971
- return `HASNA_${envToken2(name)}_API_KEY_OVERRIDE`;
96972
- }
96973
- function credentialPointerEnvKey2(name) {
96974
- return `HASNA_${envToken2(name)}_API_KEY_REF`;
96975
- }
96976
- function homeDir2(env3) {
96977
- const home = env3.HOME?.trim();
96978
- return home ? home : null;
96979
- }
96980
- function absoluteOverride2(env3, key2) {
96981
- const value = env3[key2]?.trim();
96982
- return value && isAbsolute34(value) ? value : null;
96983
- }
96984
- function hasnaHomeDir2(env3) {
96985
- const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
96986
- if (override)
96987
- return override;
96988
- const home = homeDir2(env3);
96989
- return home ? join60(home, HASNA_HOME_DIR2) : null;
96990
- }
96991
- function appConfigDir2(name, env3) {
96992
- const configRoot = absoluteOverride2(env3, HASNA_CONFIG_HOME_ENV_KEY2);
96993
- if (configRoot)
96994
- return join60(configRoot, name);
96995
- const root2 = hasnaHomeDir2(env3);
96996
- return root2 ? join60(root2, name, CONFIG_SUBDIR2) : null;
96997
- }
96998
- function credentialDiskSourceList2(name, env3, profile = null) {
96999
- if (!SAFE_APP_SLUG2.test(name))
97000
- return [];
97001
- const directory2 = appConfigDir2(name, env3);
97002
- if (!directory2)
97003
- return [];
97004
- const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
97005
- return [{ path: join60(directory2, file2), tier: "disk" }];
97006
- }
97007
- function credentialDiskSources2(name, env3) {
97008
- return credentialDiskSourceList2(name, env3, null).map((s) => s.path);
97009
- }
97010
- function profileDiskSources2(name, env3, profile) {
97011
- return credentialDiskSourceList2(name, env3, profile).map((s) => s.path);
97012
- }
97013
- function parseEnvFile2(text5) {
97014
- const values2 = new Map;
97015
- const unusable = new Set;
97016
- for (const rawLine of text5.split(/\r?\n/)) {
97017
- const line = rawLine.trim();
97018
- if (line.length === 0 || line.startsWith("#"))
97019
- continue;
97020
- const withoutExport = line.startsWith("export ") ? line.slice("export ".length).trim() : line;
97021
- const equals = withoutExport.indexOf("=");
97022
- if (equals <= 0)
97023
- continue;
97024
- const key2 = withoutExport.slice(0, equals).trim();
97025
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key2))
97026
- continue;
97027
- let value = withoutExport.slice(equals + 1).trim();
97028
- const quote3 = value[0];
97029
- if (quote3 === '"' || quote3 === "'") {
97030
- if (value.length < 2 || !value.endsWith(quote3)) {
97031
- unusable.add(key2);
97032
- continue;
97033
- }
97034
- value = value.slice(1, -1);
97035
- }
97036
- if (value.trim().length === 0) {
97037
- unusable.add(key2);
97038
- continue;
97039
- }
97040
- if (values2.has(key2) && values2.get(key2) !== value)
97041
- unusable.add(key2);
97042
- values2.set(key2, value);
97043
- }
97044
- return { values: values2, unusable };
97045
- }
97046
- function configFileModeAllowed2(mode) {
97047
- const permissions = mode & 4095;
97048
- return permissions === 256 || permissions === 384;
97049
- }
97050
- function configFileReadsCoherent2(before2, after2) {
97051
- return before2.dev === after2.dev && before2.ino === after2.ino && before2.size === after2.size && before2.mtimeMs === after2.mtimeMs && before2.ctimeMs === after2.ctimeMs;
97052
- }
97053
- function readAppConfigFile2(path) {
97054
- const unsafe = (reason2) => {
97055
- throw new CredentialFileUnsafeError2(path, reason2);
97056
- };
97057
- let fd = -1;
97058
- try {
97059
- fd = openSync26(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
97060
- } catch (error61) {
97061
- const code = error61.code;
97062
- if (code === "ENOENT" || code === "ENOTDIR")
97063
- return null;
97064
- if (code === "ELOOP")
97065
- unsafe("the path is a symlink");
97066
- unsafe(`the path could not be opened (${code ?? "unknown error"})`);
97067
- }
97068
- try {
97069
- const before2 = fstatSync26(fd);
97070
- if (!before2.isFile())
97071
- unsafe("the path is not a regular file");
97072
- if (!configFileModeAllowed2(before2.mode)) {
97073
- unsafe(`permission mode ${(before2.mode & 4095).toString(8).padStart(4, "0")} is not owner-only 0400 or 0600`);
97074
- }
97075
- const uid2 = process.getuid?.() ?? process.geteuid?.();
97076
- if (uid2 !== undefined && before2.uid !== uid2)
97077
- unsafe("the file is not owned by the current user");
97078
- if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
97079
- unsafe("the file exceeds the size limit");
97080
- const bytes = readFileSync38(fd);
97081
- const after2 = fstatSync26(fd);
97082
- if (!configFileReadsCoherent2(before2, after2)) {
97083
- unsafe("the file changed while being read");
97084
- }
97085
- return parseEnvFile2(bytes.toString("utf8"));
97086
- } finally {
97087
- if (fd !== -1)
97088
- closeSync26(fd);
97089
- }
97090
- }
97091
- function readCredentialFile2(path, apiKeyKeys) {
97092
- const parsed = readAppConfigFile2(path);
97093
- if (!parsed)
97094
- return null;
97095
- for (const key2 of apiKeyKeys) {
97096
- if (parsed.unusable.has(key2)) {
97097
- throw new CredentialFileUnsafeError2(path, `${key2} is declared but blank or malformed`);
97098
- }
97099
- }
97100
- const values2 = apiKeyKeys.map((key2) => parsed.values.get(key2)?.trim()).filter((value) => Boolean(value));
97101
- if (new Set(values2).size > 1) {
97102
- throw new CredentialFileUnsafeError2(path, "credential aliases disagree");
97103
- }
97104
- return values2[0] ?? null;
97105
- }
97106
- function appConfigDiskValue2(name, env3, keys3) {
97107
- const wanted = keys3.filter((key2) => !CREDENTIAL_SHAPED_KEY2.test(key2));
97108
- if (wanted.length === 0)
97109
- return null;
97110
- for (const path of credentialDiskSources2(name, env3)) {
97111
- const parsed = readAppConfigFile2(path);
97112
- if (!parsed)
97113
- continue;
97114
- if (wanted.some((key2) => parsed.unusable.has(key2))) {
97115
- return { key: wanted.find((key2) => parsed.unusable.has(key2)), value: "", path, unusable: true };
97116
- }
97117
- const values2 = wanted.map((key2) => parsed.values.get(key2)?.trim()).filter((value) => Boolean(value));
97118
- if (new Set(values2).size > 1)
97119
- throw new CredentialFileUnsafeError2(path, "configuration aliases disagree");
97120
- for (const key2 of wanted) {
97121
- if (parsed.unusable.has(key2))
97122
- return { key: key2, value: "", path, unusable: true };
97123
- const value = parsed.values.get(key2)?.trim();
97124
- if (value)
97125
- return { key: key2, value, path };
97126
- }
97127
- }
97128
- return null;
97129
- }
97130
- function assertUsableCredential2(appName, source, value) {
97131
- if (VAULT_POINTER_SHAPE2.test(value)) {
97132
- throw new CredentialResolutionError2(appName, `The credential from ${source} looks like a secrets-vault pointer (a path-shaped reference like ` + `'namespace/app/live/api_key'). A vault path is NEVER accepted as a literal API key. ` + `Use ${credentialPointerEnvKey2(appName)} to resolve the key through the vault, or provide the actual key value.`, [source]);
97133
- }
97134
- if (!ILLEGAL_IN_HEADER_VALUE2.test(value))
97135
- return;
97136
- throw new CredentialResolutionError2(appName, `The credential from ${source} contains characters that cannot be sent in an HTTP header ` + `(a control character or non-ASCII byte). A file written with CR-only line endings is the usual ` + `cause. Rewrite that credential file with one LF-terminated KEY=value line. ` + `The value is not shown here, and is deliberately never logged.`, [source]);
97137
- }
97138
- function sealCredential2(fields2) {
97139
- const { apiKey } = fields2;
97140
- const visible = {
97141
- tier: fields2.tier,
97142
- source: fields2.source,
97143
- deliberate: fields2.deliberate,
97144
- diskCandidates: Object.freeze([...fields2.diskCandidates]),
97145
- warning: fields2.warning
97146
- };
97147
- const sealed = { ...visible };
97148
- Object.defineProperty(sealed, "apiKey", {
97149
- value: apiKey,
97150
- enumerable: false,
97151
- writable: false,
97152
- configurable: false
97153
- });
97154
- if (fields2.pointerVaultKey !== undefined) {
97155
- Object.defineProperty(sealed, "pointerVaultKey", {
97156
- value: fields2.pointerVaultKey,
97157
- enumerable: false,
97158
- writable: false,
97159
- configurable: false
97160
- });
97161
- }
97162
- Object.defineProperty(sealed, INSPECT_CUSTOM2, {
97163
- value: () => ({ ...visible, apiKey: "[redacted]" }),
97164
- enumerable: false,
97165
- writable: false,
97166
- configurable: false
97167
- });
97168
- Object.defineProperty(sealed, CREDENTIAL_SEAL2, {
97169
- value: true,
97170
- enumerable: false,
97171
- writable: false,
97172
- configurable: false
97173
- });
97174
- return Object.freeze(sealed);
97175
- }
97176
- function isSealedCredential(credential) {
97177
- return credential[CREDENTIAL_SEAL2] === true;
97178
- }
97179
- function explicitCredential(appName, apiKey) {
97180
- const source = "explicit apiKey option";
97181
- assertUsableCredential2(appName, source, apiKey);
97182
- return sealCredential2({
97183
- apiKey,
97184
- tier: "argument",
97185
- source,
97186
- deliberate: true,
97187
- diskCandidates: [],
97188
- warning: null
97189
- });
97190
- }
97191
- function validateAndSealResolvedCredential(appName, credential) {
97192
- const apiKey = credential.apiKey;
97193
- assertUsableCredential2(appName, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE, apiKey);
97194
- if (!isSealedCredential(credential)) {
97195
- return sealCredential2({
97196
- apiKey,
97197
- tier: "argument",
97198
- source: CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE,
97199
- deliberate: true,
97200
- diskCandidates: [],
97201
- warning: null
97202
- });
97203
- }
97204
- return sealCredential2({
97205
- apiKey,
97206
- tier: credential.tier,
97207
- source: credential.source,
97208
- deliberate: credential.deliberate,
97209
- diskCandidates: credential.diskCandidates,
97210
- warning: credential.warning,
97211
- ...credential.pointerVaultKey !== undefined ? { pointerVaultKey: credential.pointerVaultKey } : {}
97212
- });
97213
- }
97214
- function firstEnvValue2(env3, keys3) {
97215
- for (const key2 of keys3) {
97216
- if (!Object.prototype.hasOwnProperty.call(env3, key2))
97217
- continue;
97218
- const value = env3[key2]?.trim();
97219
- if (value)
97220
- return { key: key2, value };
97221
- }
97222
- return null;
97223
- }
97224
- function isAmbientEnvironment2(env3) {
97225
- return env3 === process.env || env3[AMBIENT_ENVIRONMENT2] === true;
97226
- }
97227
- function defaultKeychainRunner2(argv) {
97228
- const result2 = spawnSync5(KEYCHAIN_SECURITY_BIN2, [...argv], {
97229
- encoding: "utf8",
97230
- stdio: ["ignore", "pipe", "pipe"],
97231
- timeout: KEYCHAIN_SPAWN_TIMEOUT_MS2
97232
- });
97233
- return {
97234
- status: result2.status,
97235
- stdout: result2.stdout ?? "",
97236
- stderr: result2.error ? result2.error.message : result2.stderr ?? ""
97237
- };
97238
- }
97239
- function keychainTierEnabled2(env3, options) {
97240
- if ((options.platform ?? process.platform) !== "darwin")
97241
- return false;
97242
- if (options.enabled !== undefined)
97243
- return options.enabled;
97244
- return options.run !== undefined || isAmbientEnvironment2(env3);
97245
- }
97246
- function keychainAccount2(env3, options) {
97247
- const station = env3[KEYCHAIN_STATION_ENV_KEY2]?.trim();
97248
- if (station)
97249
- return station;
97250
- const host = (options.hostname ?? osHostname2)().split(".")[0]?.trim() ?? "";
97251
- if (host)
97252
- return host;
97253
- const user = env3.USER?.trim();
97254
- return user || null;
97255
- }
97256
- function keychainFailureHint2(text5) {
97257
- const line = text5.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
97258
- const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
97259
- return clean ? `: ${clean}` : "";
97260
- }
97261
- function readKeychainItem2(name, env3, kind, options) {
97262
- if (!SAFE_APP_SLUG2.test(name) || !keychainTierEnabled2(env3, options))
97263
- return null;
97264
- const account = keychainAccount2(env3, options);
97265
- if (!account)
97266
- return null;
97267
- const service = `${KEYCHAIN_SERVICE_PREFIX2}.${name}.${kind}`;
97268
- const source = `keychain:${service}@${account}`;
97269
- const run = options.run ?? defaultKeychainRunner2;
97270
- let result2;
97271
- try {
97272
- result2 = run(["find-generic-password", "-a", account, "-s", service, "-w"]);
97273
- } catch (error61) {
97274
- const reason2 = keychainFailureHint2(error61 instanceof Error ? error61.message : String(error61));
97275
- throw new CredentialResolutionError2(name, `The Keychain lookup for ${source} could not run${reason2}. A Keychain failure is never resolved ` + `around: fix the keychain, or delete the item to fall through to the credential on disk.`, [source]);
97276
- }
97277
- if (result2.status === KEYCHAIN_ITEM_NOT_FOUND_STATUS2)
97278
- return null;
97279
- if (result2.status !== 0) {
97280
- throw new CredentialResolutionError2(name, `The Keychain lookup for ${source} failed (security exited ` + `${result2.status ?? "without a status"}${keychainFailureHint2(result2.stderr)}). A Keychain item that ` + `exists but cannot be read is never resolved around: unlock the keychain, run from a session that ` + `may use it, or delete the item to fall through to the credential on disk.`, [source]);
97281
- }
97282
- const value = result2.stdout.trim();
97283
- if (!value) {
97284
- throw new CredentialResolutionError2(name, `${source} exists but holds an empty value; a declared item never falls through to another ` + `identity. Store a value in it or delete the item.`, [source]);
97285
- }
97286
- return { value, source };
97287
- }
97288
- function keychainConfigValue2(name, env3, options = {}) {
97289
- return readKeychainItem2(name, env3, "api-url", options);
97290
- }
97291
- function snapshotClientEnvironment2(name, env3) {
97292
- const keys3 = clientTransportEnvKeys2(name);
97293
- const ambient = isAmbientEnvironment2(env3);
97294
- const snapshot2 = Object.create(null);
97295
- for (const key2 of [
97296
- ...keys3.apiUrlKeys,
97297
- ...keys3.apiKeyKeys,
97298
- credentialOverrideEnvKey2(name),
97299
- credentialPointerEnvKey2(name),
97300
- CREDENTIAL_PROFILE_ENV_KEY2,
97301
- "HOME",
97302
- HASNA_HOME_ENV_KEY2,
97303
- HASNA_CONFIG_HOME_ENV_KEY2,
97304
- KEYCHAIN_STATION_ENV_KEY2,
97305
- "USER"
97306
- ]) {
97307
- const descriptor = Object.getOwnPropertyDescriptor(env3, key2);
97308
- if (!descriptor)
97309
- continue;
97310
- if (!("value" in descriptor)) {
97311
- throw new CredentialResolutionError2(name, `${key2} is accessor-backed; client configuration requires own data properties.`, [key2]);
97312
- }
97313
- if (descriptor.value !== undefined && typeof descriptor.value !== "string") {
97314
- throw new CredentialResolutionError2(name, `${key2} must be a string data property.`, [key2]);
97315
- }
97316
- snapshot2[key2] = descriptor.value;
97317
- }
97318
- if (ambient) {
97319
- Object.defineProperty(snapshot2, AMBIENT_ENVIRONMENT2, {
97320
- value: true,
97321
- enumerable: false,
97322
- writable: false,
97323
- configurable: false
97324
- });
97325
- }
97326
- return Object.freeze(snapshot2);
97327
- }
97328
- function resolveCredential2(name, env3, options = {}) {
97329
- env3 = snapshotClientEnvironment2(name, env3);
97330
- const { apiKeyKeys } = clientTransportEnvKeys2(name);
97331
- const diskPaths = credentialDiskSources2(name, env3);
97332
- if (options.apiKey !== undefined) {
97333
- const explicitKey = options.apiKey.trim();
97334
- if (!explicitKey) {
97335
- throw new CredentialResolutionError2(name, "The explicit apiKey argument is blank; an explicit credential never falls through to another identity.", ["explicit apiKey argument"]);
97336
- }
97337
- assertUsableCredential2(name, "the explicit apiKey argument", explicitKey);
97338
- return sealCredential2({
97339
- apiKey: explicitKey,
97340
- tier: "argument",
97341
- source: "explicit apiKey argument",
97342
- deliberate: true,
97343
- diskCandidates: diskPaths,
97344
- warning: null
97345
- });
97346
- }
97347
- const overrideKeyName = credentialOverrideEnvKey2(name);
97348
- const overrideRaw = Object.prototype.hasOwnProperty.call(env3, overrideKeyName) ? env3[overrideKeyName] : undefined;
97349
- if (overrideRaw !== undefined) {
97350
- const override = overrideRaw.trim();
97351
- if (!override) {
97352
- throw new CredentialResolutionError2(name, `${overrideKeyName} is set but empty. It is a deliberate override, so it is not resolved around: ` + `either give it a real key or unset it to fall back to the credential on disk.`, [overrideKeyName]);
97353
- }
97354
- assertUsableCredential2(name, overrideKeyName, override);
97355
- return sealCredential2({
97356
- apiKey: override,
97357
- tier: "override",
97358
- source: overrideKeyName,
97359
- deliberate: true,
97360
- diskCandidates: diskPaths,
97361
- warning: null
97362
- });
97363
- }
97364
- const pointerKeyName = credentialPointerEnvKey2(name);
97365
- const pointerRaw = Object.prototype.hasOwnProperty.call(env3, pointerKeyName) ? env3[pointerKeyName] : undefined;
97366
- if (pointerRaw !== undefined) {
97367
- const pointer = pointerRaw.trim();
97368
- if (!pointer) {
97369
- throw new CredentialResolutionError2(name, `${pointerKeyName} is set but empty. It is a deliberate vault pointer, so it is not resolved around: ` + `either give it a vault item key or unset it to fall back to the credential on disk.`, [pointerKeyName]);
97370
- }
97371
- if (!VAULT_POINTER_SHAPE2.test(pointer)) {
97372
- throw new CredentialResolutionError2(name, `${pointerKeyName} must name a vault ITEM KEY (a path-shaped reference like ` + `'namespace/app/live/api_key'), not a credential value. A pointer that carries a literal is refused.`, [pointerKeyName]);
97373
- }
97374
- return sealCredential2({
97375
- apiKey: "",
97376
- pointerVaultKey: pointer,
97377
- tier: "pointer",
97378
- source: pointerKeyName,
97379
- deliberate: true,
97380
- diskCandidates: diskPaths,
97381
- warning: null
97382
- });
97383
- }
97384
- if (options.profile !== undefined && !options.profile.trim()) {
97385
- throw new CredentialResolutionError2(name, "The explicit profile argument is blank; an explicit identity selection never falls through.", ["explicit profile argument"]);
97386
- }
97387
- const profileRaw = Object.prototype.hasOwnProperty.call(env3, CREDENTIAL_PROFILE_ENV_KEY2) ? env3[CREDENTIAL_PROFILE_ENV_KEY2] : undefined;
97388
- if (profileRaw !== undefined && !profileRaw.trim()) {
97389
- throw new CredentialResolutionError2(name, `${CREDENTIAL_PROFILE_ENV_KEY2} is set but blank.`, [CREDENTIAL_PROFILE_ENV_KEY2]);
97390
- }
97391
- const profile = options.profile?.trim() || profileRaw?.trim();
97392
- if (profile) {
97393
- const profileSource = options.profile?.trim() ? "explicit profile argument" : CREDENTIAL_PROFILE_ENV_KEY2;
97394
- if (!SAFE_PROFILE2.test(profile)) {
97395
- throw new CredentialResolutionError2(name, `Profile name from ${profileSource} is not usable in a path. ` + `Use letters, digits, dot, dash, or underscore.`, [profileSource]);
97396
- }
97397
- const paths = profileDiskSources2(name, env3, profile);
97398
- for (const path of paths) {
97399
- const value = readCredentialFile2(path, apiKeyKeys);
97400
- if (value) {
97401
- assertUsableCredential2(name, path, value);
97402
- return sealCredential2({
97403
- apiKey: value,
97404
- tier: "profile",
97405
- source: path,
97406
- deliberate: true,
97407
- diskCandidates: paths,
97408
- warning: null
97409
- });
97410
- }
97411
- }
97412
- throw new CredentialResolutionError2(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} for '${name}'. ` + `Looked in: ${paths.join(", ") || "<no HOME in this environment>"}. ` + `A profile names WHICH identity to use, so it is never resolved around \u2014 ` + `create the profile's credential file or unset ${CREDENTIAL_PROFILE_ENV_KEY2}.`, paths);
97413
- }
97414
- const definedEnvEntries = apiKeyKeys.filter((key2) => Object.prototype.hasOwnProperty.call(env3, key2) && env3[key2] !== undefined).map((key2) => ({ key: key2, value: String(env3[key2]).trim() }));
97415
- const blankEnv = definedEnvEntries.find((entry) => entry.value.length === 0);
97416
- if (blankEnv) {
97417
- throw new CredentialResolutionError2(name, `${blankEnv.key} is set but blank; a declared credential never falls through to another alias or identity.`, [blankEnv.key]);
97418
- }
97419
- if (definedEnvEntries.length > 1 && new Set(definedEnvEntries.map((entry) => entry.value)).size > 1) {
97420
- throw new CredentialResolutionError2(name, `${definedEnvEntries.map((entry) => entry.key).join(" and ")} disagree; credential aliases must be identical or only one may be set.`, definedEnvEntries.map((entry) => entry.key));
97421
- }
97422
- const envHit = firstEnvValue2(env3, apiKeyKeys);
97423
- const keychainHit = readKeychainItem2(name, env3, "api-key", options.keychain ?? {});
97424
- if (keychainHit) {
97425
- assertUsableCredential2(name, keychainHit.source, keychainHit.value);
97426
- const warning = envHit && envHit.value !== keychainHit.value ? `Credential sources disagree for '${name}': ${keychainHit.source} and ${envHit.key} hold ` + `different keys. ${keychainHit.source} wins, because the Keychain is re-read on every call while ` + `an environment variable is a snapshot. Reconcile them \u2014 a rotation that updated only one leaves ` + `the other to fail 401 wherever it is loaded first.` : null;
97427
- return sealCredential2({
97428
- apiKey: keychainHit.value,
97429
- tier: "keychain",
97430
- source: keychainHit.source,
97431
- deliberate: false,
97432
- diskCandidates: diskPaths,
97433
- warning
97434
- });
97435
- }
97436
- const diskSourceList = credentialDiskSourceList2(name, env3, null);
97437
- const diskHits = diskSourceList.map((src) => ({ src, value: readCredentialFile2(src.path, apiKeyKeys) })).filter((hit) => hit.value !== null);
97438
- if (diskHits.length > 0) {
97439
- const winner = diskHits[0];
97440
- assertUsableCredential2(name, winner.src.path, winner.value);
97441
- const divergentSources = [
97442
- ...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.src.path),
97443
- ...envHit && envHit.value !== winner.value ? [envHit.key] : []
97444
- ];
97445
- const warning = divergentSources.length > 0 ? `Credential sources disagree for '${name}': ${winner.src.path} and ` + `${divergentSources.join(", ")} hold different keys. ${winner.src.path} wins, because a file on ` + `disk is re-read on every call while an environment variable is a snapshot. Reconcile them \u2014 ` + `a rotation that updated only one leaves the other to fail 401 wherever it is loaded first.` : null;
97446
- return sealCredential2({
97447
- apiKey: winner.value,
97448
- tier: winner.src.tier,
97449
- source: winner.src.path,
97450
- deliberate: false,
97451
- diskCandidates: diskPaths,
97452
- warning
97453
- });
97454
- }
97455
- if (envHit) {
97456
- assertUsableCredential2(name, envHit.key, envHit.value);
97457
- return sealCredential2({
97458
- apiKey: envHit.value,
97459
- tier: "env",
97460
- source: envHit.key,
97461
- deliberate: false,
97462
- diskCandidates: diskPaths,
97463
- warning: null
97464
- });
97465
- }
97466
- return null;
97467
- }
97468
- async function completePointerCredential2(name, pointerResolution, env3 = process.env) {
97469
- const vaultKey = pointerResolution.pointerVaultKey;
97470
- const pointerEnvKey = pointerResolution.source;
97471
- if (!vaultKey) {
97472
- throw new CredentialResolutionError2(name, `Pointer resolution from ${pointerEnvKey} carries no vault item key; this is a defect in the resolver.`, [pointerEnvKey]);
97473
- }
97474
- let secretsSdk;
97475
- try {
97476
- secretsSdk = requireSecretsSdk2(SECRETS_PACKAGE_SPECIFIER);
97477
- } catch {
97478
- throw new CredentialResolutionError2(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets SDK (@hasna/secrets) is not installed ` + `in this process. A vault pointer is TERMINAL: install @hasna/secrets to resolve it, or unset ${pointerEnvKey}.`, [pointerEnvKey]);
97479
- }
97480
- let client2;
97481
- try {
97482
- client2 = secretsSdk.createSecretsClientFromEnv(env3);
97483
- } catch {
97484
- throw new CredentialResolutionError2(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets client could not be configured from this ` + `environment (the secrets service URL and key env are missing or invalid). A vault pointer is TERMINAL and ` + `never falls through to a literal or disk credential.`, [pointerEnvKey]);
97485
- }
97486
- let secret;
96957
+ // src/lib/execution-secrets.ts
96958
+ import { constants as constants26, closeSync as closeSync26, fstatSync as fstatSync26, openSync as openSync26, readSync as readSync20, realpathSync as realpathSync16 } from "fs";
96959
+ import { hostname as stationHostname } from "os";
96960
+ async function defaultSecretsClientFactory(load = () => import("@hasna/secrets/sdk")) {
96961
+ let sdk;
97487
96962
  try {
97488
- secret = await client2.getSecret({ key: vaultKey });
96963
+ sdk = await load();
97489
96964
  } catch {
97490
- throw new CredentialResolutionError2(name, `${pointerEnvKey} names vault item '${vaultKey}', but the vault could not be reached or the item is ` + `unavailable. A vault pointer is TERMINAL and never falls through to a literal or disk credential.`, [pointerEnvKey]);
97491
- }
97492
- const value = secret.value;
97493
- if (!value) {
97494
- throw new CredentialResolutionError2(name, `${pointerEnvKey} resolved vault item '${vaultKey}', but it holds no value. A vault pointer is TERMINAL.`, [pointerEnvKey]);
97495
- }
97496
- assertUsableCredential2(name, `${pointerEnvKey} -> vault:${vaultKey}`, value);
97497
- return sealCredential2({
97498
- apiKey: value,
97499
- tier: "pointer",
97500
- source: `${pointerEnvKey} -> vault:${vaultKey}`,
97501
- deliberate: true,
97502
- diskCandidates: pointerResolution.diskCandidates,
97503
- warning: null
97504
- });
97505
- }
97506
- function defaultFleetGatewayBaseUrl2(name) {
97507
- return `${DEFAULT_FLEET_GATEWAY_ORIGIN2}/${validateAppSlug2(name)}`;
97508
- }
97509
- function isValidDnsDomain2(value) {
97510
- if (value.length === 0 || value.length > 253 || ASCII_CONTROL_PATTERN2.test(value) || /[^\x00-\x7f]/.test(value)) {
97511
- return false;
97512
- }
97513
- return value.split(".").every((label) => label.length <= 63 && !label.startsWith("xn--") && DNS_LABEL_PATTERN2.test(label));
97514
- }
97515
- function validateAppSlug2(name) {
97516
- if (name.length > 63 || !DNS_LABEL_PATTERN2.test(name)) {
97517
- throw new Error("App name must be one lowercase DNS label.");
97518
- }
97519
- return name;
97520
- }
97521
- function rawAuthority2(value) {
97522
- const match = /^[a-z][a-z0-9+.-]*:\/\//i.exec(value);
97523
- if (!match)
97524
- throw new Error("API URL must be absolute.");
97525
- const afterScheme = value.slice(match[0].length);
97526
- const boundary = afterScheme.search(/[/?#]/);
97527
- const authority = boundary === -1 ? afterScheme : afterScheme.slice(0, boundary);
97528
- if (!authority)
97529
- throw new Error("API URL must include a hostname.");
97530
- return authority;
97531
- }
97532
- function assertCanonicalPort2(port) {
97533
- if (!/^[0-9]+$/.test(port) || port.length > 1 && port.startsWith("0")) {
97534
- throw new Error("API URL authority must contain a canonical port between 1 and 65535.");
97535
- }
97536
- const numericPort = Number(port);
97537
- if (!Number.isSafeInteger(numericPort) || numericPort < 1 || numericPort > 65535) {
97538
- throw new Error("API URL authority must contain a canonical port between 1 and 65535.");
97539
- }
97540
- }
97541
- function canonicalAuthorityHostname2(authority) {
97542
- let rawHostname;
97543
- if (authority.startsWith("[")) {
97544
- const closingBracket = authority.indexOf("]");
97545
- if (closingBracket === -1) {
97546
- throw new Error("API URL authority must contain a canonical hostname.");
97547
- }
97548
- rawHostname = authority.slice(0, closingBracket + 1);
97549
- const portSuffix = authority.slice(closingBracket + 1);
97550
- if (portSuffix) {
97551
- if (!portSuffix.startsWith(":")) {
97552
- throw new Error("API URL authority must contain a canonical hostname and port.");
97553
- }
97554
- assertCanonicalPort2(portSuffix.slice(1));
97555
- }
97556
- if (isIP3(rawHostname.slice(1, -1)) !== 6) {
97557
- throw new Error("API URL authority must contain a canonical IPv6 literal.");
97558
- }
97559
- } else {
97560
- const firstColon = authority.indexOf(":");
97561
- const lastColon = authority.lastIndexOf(":");
97562
- if (firstColon !== lastColon) {
97563
- throw new Error("IPv6 API URL authorities must use brackets.");
97564
- }
97565
- if (lastColon !== -1) {
97566
- const port = authority.slice(lastColon + 1);
97567
- assertCanonicalPort2(port);
97568
- rawHostname = authority.slice(0, lastColon);
97569
- } else {
97570
- rawHostname = authority;
97571
- }
97572
- const ipVersion = isIP3(rawHostname);
97573
- const numericAddressParts = rawHostname.split(".");
97574
- const looksLikeNonCanonicalIpv4 = numericAddressParts.every((part) => /^(?:0x[0-9a-f]+|[0-9]+)$/i.test(part));
97575
- if (ipVersion !== 4 && looksLikeNonCanonicalIpv4 || ipVersion !== 4 && !isValidDnsDomain2(rawHostname.toLowerCase())) {
97576
- throw new Error("API URL authority must contain a canonical ASCII hostname.");
97577
- }
97578
- }
97579
- return rawHostname.toLowerCase();
97580
- }
97581
- function isDeliberateLoopbackHttpAuthority2(authority) {
97582
- return /^(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?$/i.test(authority);
97583
- }
97584
- function toV1BaseUrl2(apiUrl) {
97585
- if (ASCII_CONTROL_PATTERN2.test(apiUrl)) {
97586
- throw new Error("API URL must not contain ASCII control characters.");
97587
- }
97588
- const input2 = apiUrl.trim();
97589
- const authority = rawAuthority2(input2);
97590
- if (authority.includes("@") || authority.includes("\\") || authority.includes("%") || /[^\x00-\x7f]/.test(authority)) {
97591
- throw new Error("API URL authority must be canonical ASCII without credentials.");
97592
- }
97593
- const canonicalHostname = canonicalAuthorityHostname2(authority);
97594
- const url2 = new URL(input2);
97595
- if (url2.protocol !== "http:" && url2.protocol !== "https:") {
97596
- throw new Error("API URL must use http or https.");
97597
- }
97598
- if (url2.username || url2.password) {
97599
- throw new Error("API URL must not include credentials.");
97600
- }
97601
- if (!url2.hostname || url2.hostname.endsWith(".")) {
97602
- throw new Error("API URL must include a canonical hostname.");
97603
- }
97604
- if (url2.hostname.toLowerCase() !== canonicalHostname) {
97605
- throw new Error("API URL authority must not rely on parser hostname normalization.");
97606
- }
97607
- if (url2.hostname.split(".").some((label) => label.toLowerCase().startsWith("xn--"))) {
97608
- throw new Error("API URL must not use IDN or punycode hostnames.");
97609
- }
97610
- if (url2.protocol === "http:" && !isDeliberateLoopbackHttpAuthority2(authority)) {
97611
- throw new Error("API URL may use http only for an exact loopback authority.");
97612
- }
97613
- if (url2.search || url2.hash) {
97614
- throw new Error("API URL must not include a query string or fragment.");
97615
- }
97616
- let path = url2.pathname.replace(/\/+$/, "");
97617
- if (path.endsWith("/v1"))
97618
- path = path.slice(0, -"/v1".length);
97619
- url2.pathname = `${path}/v1`;
97620
- return url2.toString().replace(/\/+$/, "");
97621
- }
97622
- function resolveClientTransportSnapshot(name, env3 = process.env, options = {}) {
97623
- env3 = snapshotClientEnvironment2(name, env3);
97624
- const keys3 = clientTransportEnvKeys2(name);
97625
- const definedUrlEntries = keys3.apiUrlKeys.filter((key2) => Object.prototype.hasOwnProperty.call(env3, key2) && env3[key2] !== undefined).map((key2) => ({ key: key2, raw: String(env3[key2]) }));
97626
- const blankUrl = definedUrlEntries.find((entry) => entry.raw.trim().length === 0);
97627
- if (blankUrl) {
97628
- throw new ClientTransportConfigurationError2(name, `${blankUrl.key} is set but blank; public clients require an explicit HTTPS API URL and never select local storage.`, [blankUrl.key]);
97629
- }
97630
- const controlledUrl = definedUrlEntries.find((entry) => ASCII_CONTROL_PATTERN2.test(entry.raw));
97631
- if (controlledUrl) {
97632
- throw new ClientTransportConfigurationError2(name, `${controlledUrl.key} contains ASCII control characters.`, [controlledUrl.key]);
97633
- }
97634
- const usableUrlEntries = definedUrlEntries.map((entry) => ({ key: entry.key, value: entry.raw.trim() }));
97635
- if (usableUrlEntries.length > 1 && new Set(usableUrlEntries.map((entry) => entry.value)).size > 1) {
97636
- throw new ClientTransportConfigurationError2(name, `${usableUrlEntries.map((entry) => entry.key).join(" and ")} disagree; client authority aliases must be identical or only one may be set.`, usableUrlEntries.map((entry) => entry.key));
97637
- }
97638
- const envUrlHit = usableUrlEntries[0] ?? null;
97639
- const keychainUrlHit = keychainConfigValue2(name, env3, options.credentials?.keychain);
97640
- const diskConfigUrlHit = appConfigDiskValue2(name, env3, keys3.apiUrlKeys);
97641
- if (diskConfigUrlHit?.unusable) {
97642
- throw new ClientTransportConfigurationError2(name, `${diskConfigUrlHit.key} in ${diskConfigUrlHit.path} is declared but blank or malformed; public clients require a valid HTTPS service authority.`, [diskConfigUrlHit.path]);
97643
- }
97644
- const urlCandidates = [
97645
- ...envUrlHit ? [envUrlHit] : [],
97646
- ...keychainUrlHit ? [{ key: keychainUrlHit.source, value: keychainUrlHit.value }] : [],
97647
- ...diskConfigUrlHit ? [{ key: diskConfigUrlHit.path, value: diskConfigUrlHit.value.trim() }] : []
97648
- ];
97649
- const configuredUrl = urlCandidates[0] ?? null;
97650
- const divergentUrls = urlCandidates.filter((candidate2) => candidate2.value !== configuredUrl?.value);
97651
- if (configuredUrl && divergentUrls.length > 0) {
97652
- throw new ClientTransportConfigurationError2(name, `${configuredUrl.key} and ${divergentUrls.map((candidate2) => candidate2.key).join(" and ")} select different service authorities; refusing to send a credential written for one authority to the other.`, urlCandidates.map((candidate2) => candidate2.key));
97653
- }
97654
- const warnings = [];
97655
- if (configuredUrl && !envUrlHit) {
97656
- warnings.push(`No ${keys3.apiUrlKeys[0]} in the environment; the server URL in ${configuredUrl.key} was used, so this client connects to the server. ` + `Keep that entry aligned with the intended service authority.`);
97657
- }
97658
- const credential = resolveCredential2(name, env3, options.credentials);
97659
- if (!credential) {
97660
- const diskHint = credentialDiskSourcesForMessage(name, env3);
97661
- const lead = configuredUrl ? `${configuredUrl.key} selects the HTTP server for '${name}', but no API key could be resolved` : `${keys3.apiUrlKeys[0]} is not set and no API key could be resolved for '${name}'; a credential is required before the default fleet gateway authority applies`;
97662
- warnings.push(`${lead}; refusing to create an unauthenticated client \u2014 public clients never fall back to SQLite or another local store. ` + `Looked in the Keychain (macOS only), then for a credential file at ${diskHint}, then for ${keys3.apiKeyKeys[0]} in the environment.`);
97663
- throw new ClientTransportConfigurationError2(name, warnings.join(" "), [configuredUrl?.key ?? keys3.apiUrlKeys[0]]);
97664
- }
97665
- if (credential.warning)
97666
- warnings.push(credential.warning);
97667
- let urlHit;
97668
- if (configuredUrl) {
97669
- urlHit = configuredUrl;
97670
- } else {
97671
- try {
97672
- urlHit = { key: DEFAULT_AUTHORITY_SOURCE, value: defaultFleetGatewayBaseUrl2(name) };
97673
- } catch (error61) {
97674
- const message = error61 instanceof Error ? error61.message : String(error61);
97675
- throw new ClientTransportConfigurationError2(name, `No ${keys3.apiUrlKeys[0]} is configured and the default fleet gateway authority cannot be composed for '${name}': ${message}`, [keys3.apiUrlKeys[0]]);
97676
- }
97677
- }
97678
- const apiUrlSource = urlHit.key;
97679
- let baseUrl;
97680
- try {
97681
- baseUrl = toV1BaseUrl2(urlHit.value);
97682
- } catch (error61) {
97683
- const message = error61 instanceof Error ? error61.message : String(error61);
97684
- throw new ClientTransportConfigurationError2(name, `Invalid API URL from ${apiUrlSource}: ${message}`, [apiUrlSource]);
96965
+ return refuse6("LOCAL_SECRET_UNAVAILABLE", "Vault secret bindings need the optional @hasna/secrets package, which this install could not load. Install @hasna/secrets with access to it, then run again.");
97685
96966
  }
97686
- return {
97687
- resolution: {
97688
- transport: "http",
97689
- transportSource: urlHit.key,
97690
- baseUrl,
97691
- apiUrlSource,
97692
- apiKeyPresent: true,
97693
- apiKeySource: credential.source,
97694
- apiKeyTier: credential.tier,
97695
- misconfigured: false,
97696
- warning: warnings.length > 0 ? warnings.join(" ") : null
97697
- },
97698
- credential
97699
- };
97700
- }
97701
- function resolveClientTransport(name, env3 = process.env, options = {}) {
97702
- return resolveClientTransportSnapshot(name, env3, options).resolution;
97703
- }
97704
- function credentialDiskSourcesForMessage(name, env3) {
97705
- const paths = credentialDiskSources2(name, env3);
97706
- return paths.length > 0 ? paths.join(" or ") : "<no HOME or HASNA_HOME set in this environment, so no credential file was consulted>";
96967
+ return () => sdk.createSecretsClientFromEnv();
97707
96968
  }
97708
- function currentCredential(name, apiKey) {
97709
- if (typeof apiKey === "function") {
97710
- return validateAndSealResolvedCredential(name, apiKey());
97711
- }
97712
- return explicitCredential(name, apiKey);
97713
- }
97714
- async function resolveRequestCredential(name, apiKey, env3 = process.env) {
97715
- const resolved = currentCredential(name, apiKey);
97716
- if (resolved.tier === "pointer") {
97717
- return completePointerCredential2(name, resolved, env3);
97718
- }
97719
- return resolved;
97720
- }
97721
- function authFailureGuidance(credential) {
97722
- const origin = `The API key for this request came from ${credential.source}`;
97723
- if (credential.deliberate) {
97724
- const remedy = credential.source === CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE ? `Fix that provider so it returns the current key, or replace it with resolveCredential() ` + `so diagnostics can name the original source.` : `Rotate that key, or unset the override to use the credential on disk.`;
97725
- return `${origin} \u2014 a credential you selected deliberately. It was NOT substituted with any other key: ` + `falling back here would authenticate as a different principal than the one you named, which is ` + `exactly the failure an override exists to prevent. ${remedy}`;
97726
- }
97727
- if (credential.tier === "env") {
97728
- const target = credential.diskCandidates[0];
97729
- const remedy = target ? `Store the CURRENT key in the Keychain or write it to ${target} \u2014 both are re-read on every call, so ` + `rotations take effect immediately and in every shell. Do not simply unset ${credential.source}: ` + `nothing was found in the Keychain or on disk, so that would leave this client with no credential at all.` : `This environment has no HOME or HASNA_HOME, so no credential file could be consulted; the disk tier is ` + `unavailable here and there is nothing to fall back to. Set HOME, or supply the key explicitly.`;
97730
- return `${origin}, a variable in this process's environment. If a wrapper injected it for this one process, the ` + `wrapper re-reads its store on every invocation and the stored key itself is being rejected \u2014 rotate it. ` + `If this SHELL exported it, the export is a snapshot taken when the shell started: a STALE SHELL that ` + `exported the key before it was rotated keeps sending the old one until it exits. ${remedy}`;
97731
- }
97732
- if (credential.tier === "keychain") {
97733
- return `${origin}, which was re-read from the Keychain on this very call \u2014 so a stale shell is NOT the cause ` + `here. The stored item is genuinely being rejected: update it with the current key, or re-run the fleet ` + `key distribution so this machine gets the current key.`;
97734
- }
97735
- return `${origin}, which was re-read from disk on this very call \u2014 so a stale shell is NOT the cause here. ` + `The stored credential is genuinely being rejected: rotate it, or re-run the fleet key distribution ` + `so this machine gets the current key.`;
97736
- }
97737
- function assertNoAuthorityOverrideHeaders(headers, source) {
97738
- if (!headers)
97739
- return;
97740
- const forbidden = Object.keys(headers).find((name) => AUTHORITY_OVERRIDE_HEADERS2.has(name.trim().toLowerCase()));
97741
- if (forbidden) {
97742
- throw new Error(`Authenticated ${source} headers must not set authority header '${forbidden}'.`);
97743
- }
97744
- }
97745
- function appendQuery(path, query) {
97746
- if (!query)
97747
- return path;
97748
- const params = query instanceof URLSearchParams ? query : new URLSearchParams;
97749
- if (!(query instanceof URLSearchParams)) {
97750
- for (const [key2, value] of Object.entries(query)) {
97751
- if (value === null || value === undefined)
97752
- continue;
97753
- if (Array.isArray(value)) {
97754
- for (const v of value)
97755
- params.append(key2, String(v));
97756
- } else {
97757
- params.append(key2, String(value));
97758
- }
97759
- }
97760
- }
97761
- const qs = params.toString();
97762
- if (!qs)
97763
- return path;
97764
- return `${path}${path.includes("?") ? "&" : "?"}${qs}`;
97765
- }
97766
- function createHasnaHttpTransportInternal(options, requestBindingProvider) {
97767
- const fetchImpl = options.fetchImpl ?? ((input2, init) => fetch(input2, init));
97768
- const base2 = toV1BaseUrl2(options.baseUrl);
97769
- const timeoutMs = options.timeoutMs ?? 30000;
97770
- const sleep = options.sleepImpl ?? defaultSleep;
97771
- const defaultRetry = options.retry;
97772
- function resolveRetry(callRetry) {
97773
- const chosen = callRetry !== undefined ? callRetry : defaultRetry;
97774
- if (chosen === false)
97775
- return null;
97776
- const r2 = chosen ?? {};
97777
- return {
97778
- retries: r2.retries ?? 2,
97779
- baseDelayMs: r2.baseDelayMs ?? 200,
97780
- maxDelayMs: r2.maxDelayMs ?? 2000,
97781
- retryStatuses: r2.retryStatuses ?? [...DEFAULT_RETRY_STATUSES]
97782
- };
97783
- }
97784
- async function once2(method2, rel, url2, body, opts, credential) {
97785
- assertNoAuthorityOverrideHeaders(options.headers, "transport");
97786
- assertNoAuthorityOverrideHeaders(opts.headers, "request");
97787
- const headers = {
97788
- "x-api-key": credential.apiKey,
97789
- Authorization: `Bearer ${credential.apiKey}`,
97790
- Accept: "application/json",
97791
- ...options.headers ?? {},
97792
- ...opts.headers ?? {}
97793
- };
97794
- if (opts.idempotencyKey)
97795
- headers["Idempotency-Key"] = opts.idempotencyKey;
97796
- const init = {
97797
- method: method2,
97798
- headers,
97799
- redirect: "manual"
97800
- };
97801
- if (body !== undefined) {
97802
- headers["Content-Type"] = "application/json";
97803
- init.body = JSON.stringify(body);
97804
- }
97805
- const controller = new AbortController;
97806
- const onAbort = () => controller.abort();
97807
- if (opts.signal) {
97808
- if (opts.signal.aborted)
97809
- controller.abort();
97810
- else
97811
- opts.signal.addEventListener("abort", onAbort, { once: true });
97812
- }
97813
- const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? timeoutMs);
97814
- init.signal = controller.signal;
97815
- let response;
97816
- try {
97817
- response = await fetchImpl(url2, init);
97818
- } catch (error61) {
97819
- const err = error61 instanceof Error ? error61 : new Error(String(error61));
97820
- if (opts.signal?.aborted)
97821
- return { ok: false, retryable: false, error: err };
97822
- return { ok: false, retryable: true, error: err };
97823
- } finally {
97824
- clearTimeout(timer);
97825
- if (opts.signal)
97826
- opts.signal.removeEventListener("abort", onAbort);
97827
- }
97828
- const authenticationFailure = response.status === 401 || response.status === 403;
97829
- let parsed = undefined;
97830
- if (authenticationFailure) {
97831
- try {
97832
- await response.body?.cancel();
97833
- } catch {}
97834
- } else {
97835
- const text5 = await response.text();
97836
- if (text5.length > 0) {
97837
- try {
97838
- parsed = JSON.parse(text5);
97839
- } catch {
97840
- parsed = text5;
97841
- }
97842
- }
97843
- }
97844
- if (!response.ok) {
97845
- if (response.status >= 300 && response.status < 400) {
97846
- return {
97847
- ok: false,
97848
- retryable: false,
97849
- error: new HasnaHttpError(method2, rel, response.status, parsed)
97850
- };
97851
- }
97852
- if (authenticationFailure) {
97853
- return {
97854
- ok: false,
97855
- retryable: false,
97856
- error: new HasnaHttpError(method2, rel, response.status, undefined, {
97857
- source: credential.source,
97858
- tier: credential.tier,
97859
- guidance: authFailureGuidance(credential)
97860
- })
97861
- };
97862
- }
97863
- const retry = resolveRetry(opts.retry);
97864
- const retryable = retry ? retry.retryStatuses.includes(response.status) : false;
97865
- return { ok: false, retryable, error: new HasnaHttpError(method2, rel, response.status, parsed) };
97866
- }
97867
- return { ok: true, value: parsed };
97868
- }
97869
- async function request(method2, path, body, opts = {}) {
97870
- const upper = method2.toUpperCase();
97871
- const rel = appendQuery(path.startsWith("/") ? path : `/${path}`, opts.query);
97872
- const retry = resolveRetry(opts.retry);
97873
- const methodRetryable = IDEMPOTENT_METHODS2.has(upper) || Boolean(opts.idempotencyKey);
97874
- const maxAttempts = retry && methodRetryable ? retry.retries + 1 : 1;
97875
- const binding = requestBindingProvider ? await requestBindingProvider() : {
97876
- baseUrl: base2,
97877
- credential: await resolveRequestCredential(options.name, options.apiKey)
97878
- };
97879
- const url2 = `${binding.baseUrl}${rel}`;
97880
- const credential = binding.credential;
97881
- let last2 = null;
97882
- for (let attempt2 = 1;attempt2 <= maxAttempts; attempt2++) {
97883
- const result2 = await once2(upper, rel, url2, body, opts, credential);
97884
- if (result2.ok)
97885
- return result2.value;
97886
- last2 = result2;
97887
- const canRetry = retry !== null && methodRetryable && result2.retryable && attempt2 < maxAttempts;
97888
- if (!canRetry)
97889
- break;
97890
- const backoff = Math.min(retry.maxDelayMs, retry.baseDelayMs * 2 ** (attempt2 - 1));
97891
- const jitter = Math.floor(Math.random() * (backoff / 2 + 1));
97892
- await sleep(backoff + jitter);
97893
- }
97894
- throw last2.error;
97895
- }
97896
- return {
97897
- baseUrl: base2,
97898
- request,
97899
- get: (path, opts) => request("GET", path, undefined, opts),
97900
- post: (path, body, opts) => request("POST", path, body, opts),
97901
- put: (path, body, opts) => request("PUT", path, body, opts),
97902
- patch: (path, body, opts) => request("PATCH", path, body, opts),
97903
- del: (path, body, opts) => request("DELETE", path, body, opts)
97904
- };
97905
- }
97906
- function createHasnaHttpTransport(options) {
97907
- return createHasnaHttpTransportInternal(options);
97908
- }
97909
-
97910
- class SecretsClient {
97911
- transport;
97912
- probeRoot;
97913
- fetchImpl;
97914
- baseHeaders;
97915
- constructor(options) {
97916
- if (!options.baseUrl)
97917
- throw new Error("SecretsClient requires a baseUrl.");
97918
- this.transport = createHasnaHttpTransport({
97919
- name: "secrets",
97920
- baseUrl: options.baseUrl.replace(/\/+$/, ""),
97921
- apiKey: options.apiKey ?? "",
97922
- ...options.fetch ? { fetchImpl: (input2, init) => options.fetch(input2, init) } : {},
97923
- ...options.headers ? { headers: options.headers } : {}
97924
- });
97925
- this.probeRoot = this.transport.baseUrl.replace(/\/v1$/, "");
97926
- this.fetchImpl = options.fetch ? (input2, init) => options.fetch(input2, init) : (input2, init) => fetch(input2, init);
97927
- this.baseHeaders = options.headers ?? {};
97928
- }
97929
- get baseUrl() {
97930
- return this.transport.baseUrl;
97931
- }
97932
- async probe(path, init) {
97933
- const headers = { Accept: "application/json", ...this.baseHeaders };
97934
- new Headers(init?.headers ?? {}).forEach((value, key2) => {
97935
- headers[key2] = value;
97936
- });
97937
- const response = await this.fetchImpl(`${this.probeRoot}${path}`, {
97938
- ...init,
97939
- method: "GET",
97940
- headers,
97941
- redirect: "manual"
97942
- });
97943
- const text5 = await response.text();
97944
- let body = undefined;
97945
- if (text5) {
97946
- try {
97947
- body = JSON.parse(text5);
97948
- } catch {
97949
- body = text5;
97950
- }
97951
- }
97952
- if (!response.ok) {
97953
- throw new ApiError(response.status, `GET ${path} failed: ${response.status}`, body);
97954
- }
97955
- return body;
97956
- }
97957
- async request(method2, path, opts) {
97958
- const requestOpts = {};
97959
- if (opts.query)
97960
- requestOpts.query = opts.query;
97961
- const initHeaders = opts.init?.headers;
97962
- if (initHeaders)
97963
- requestOpts.headers = initHeaders;
97964
- if (opts.init?.signal)
97965
- requestOpts.signal = opts.init.signal;
97966
- try {
97967
- return await this.transport.request(method2, path, opts.body, requestOpts);
97968
- } catch (error61) {
97969
- if (error61 instanceof HasnaHttpError) {
97970
- throw new ApiError(error61.status, `${method2} ${path} failed: ${error61.status}`, error61.body);
97971
- }
97972
- throw error61;
97973
- }
97974
- }
97975
- async health(init) {
97976
- return this.probe(`/health`, init);
97977
- }
97978
- async ready(init) {
97979
- return this.probe(`/ready`, init);
97980
- }
97981
- async listAudit(query, init) {
97982
- return this.request("GET", `/audit`, {
97983
- body: undefined,
97984
- query,
97985
- init
97986
- });
97987
- }
97988
- async listItems(query, init) {
97989
- return this.request("GET", `/items`, {
97990
- body: undefined,
97991
- query,
97992
- init
97993
- });
97994
- }
97995
- async putItem(body, init) {
97996
- return this.request("POST", `/items`, {
97997
- body,
97998
- query: undefined,
97999
- init
98000
- });
98001
- }
98002
- async searchItems(query, init) {
98003
- return this.request("GET", `/items/search`, {
98004
- body: undefined,
98005
- query,
98006
- init
98007
- });
98008
- }
98009
- async getItem(id, init) {
98010
- return this.request("GET", `/items/${encodeURIComponent(String(id))}`, {
98011
- body: undefined,
98012
- query: undefined,
98013
- init
98014
- });
98015
- }
98016
- async deleteItem(id, init) {
98017
- return this.request("DELETE", `/items/${encodeURIComponent(String(id))}`, {
98018
- body: undefined,
98019
- query: undefined,
98020
- init
98021
- });
98022
- }
98023
- async listSecrets(query, init) {
98024
- return this.request("GET", `/secrets`, {
98025
- body: undefined,
98026
- query,
98027
- init
98028
- });
98029
- }
98030
- async putSecret(body, init) {
98031
- return this.request("POST", `/secrets`, {
98032
- body,
98033
- query: undefined,
98034
- init
98035
- });
98036
- }
98037
- async deleteSecret(query, init) {
98038
- return this.request("DELETE", `/secrets`, {
98039
- body: undefined,
98040
- query,
98041
- init
98042
- });
98043
- }
98044
- async getSecret(query, init) {
98045
- return this.request("GET", `/secrets/get`, {
98046
- body: undefined,
98047
- query,
98048
- init
98049
- });
98050
- }
98051
- async searchSecrets(query, init) {
98052
- return this.request("GET", `/secrets/search`, {
98053
- body: undefined,
98054
- query,
98055
- init
98056
- });
98057
- }
98058
- async listSecretVersions(query, init) {
98059
- return this.request("GET", `/secrets/versions`, {
98060
- body: undefined,
98061
- query,
98062
- init
98063
- });
98064
- }
98065
- async checkSecretVersion(query, init) {
98066
- return this.request("GET", `/secrets/versions/check`, {
98067
- body: undefined,
98068
- query,
98069
- init
98070
- });
98071
- }
98072
- async restoreSecretVersion(body, init) {
98073
- return this.request("POST", `/secrets/restore`, {
98074
- body,
98075
- query: undefined,
98076
- init
98077
- });
98078
- }
98079
- async listUsers(query, init) {
98080
- return this.request("GET", `/users`, {
98081
- body: undefined,
98082
- query,
98083
- init
98084
- });
98085
- }
98086
- async registerUser(body, init) {
98087
- return this.request("POST", `/users`, {
98088
- body,
98089
- query: undefined,
98090
- init
98091
- });
98092
- }
98093
- async version(init) {
98094
- return this.probe(`/version`, init);
98095
- }
98096
- }
98097
- function createSecretsClientFromEnv(env3 = process.env, overrides = {}) {
98098
- const { credentials, ...clientOverrides } = overrides;
98099
- if (clientOverrides.baseUrl !== undefined) {
98100
- const pinnedKey = clientOverrides.apiKey ?? credentials?.apiKey;
98101
- if (pinnedKey === undefined || pinnedKey === "") {
98102
- throw new Error("createSecretsClientFromEnv: an explicit baseUrl requires an explicit apiKey; the ambient " + "credential (Keychain hasna.credentials.secrets.api-key, ~/.hasna/secrets/config/credentials, " + "HASNA_SECRETS_API_KEY) is never sent to a caller-supplied authority (hasna/apps#1794).");
98103
- }
98104
- return new SecretsClient({ ...clientOverrides, baseUrl: clientOverrides.baseUrl, apiKey: pinnedKey });
98105
- }
98106
- const clientEnv = env3;
98107
- const resolverOptions = credentials ? { credentials } : {};
98108
- const resolution = resolveClientTransport("secrets", clientEnv, resolverOptions);
98109
- const baseUrl = resolution.baseUrl;
98110
- const apiKey = clientOverrides.apiKey ?? (() => {
98111
- const resolved = resolveCredential2("secrets", clientEnv, credentials);
98112
- if (!resolved) {
98113
- throw new Error("createSecretsClientFromEnv: no @hasna/secrets credential resolved (Keychain, " + "~/.hasna/secrets/config/credentials, HASNA_SECRETS_API_KEY).");
98114
- }
98115
- return resolved;
98116
- });
98117
- return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
98118
- }
98119
- var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve34) => setTimeout(resolve34, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE3, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
98120
- var init_sdk = __esm(() => {
98121
- init_transport2 = __esm2(() => {
98122
- CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
98123
- appName;
98124
- attempted;
98125
- constructor(appName, message, attempted) {
98126
- super(message);
98127
- this.name = "CredentialResolutionError";
98128
- this.appName = appName;
98129
- this.attempted = attempted;
98130
- }
98131
- };
98132
- CredentialFileUnsafeError2 = class CredentialFileUnsafeError3 extends Error {
98133
- path;
98134
- constructor(path, reason2) {
98135
- super(`Refusing unsafe credential/config file ${path}: ${reason2}.`);
98136
- this.name = "CredentialFileUnsafeError";
98137
- this.path = path;
98138
- }
98139
- };
98140
- MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
98141
- SAFE_APP_SLUG2 = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
98142
- SAFE_PROFILE2 = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
98143
- ILLEGAL_IN_HEADER_VALUE2 = /[^\t\x20-\x7e]/;
98144
- VAULT_POINTER_SHAPE2 = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
98145
- CREDENTIAL_SHAPED_KEY2 = /(?:^|_)(?:API_KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)(?:_|$)/;
98146
- INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
98147
- CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
98148
- AMBIENT_ENVIRONMENT2 = Symbol.for("hasna:contracts:ambientClientEnvironment");
98149
- SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
98150
- requireSecretsSdk2 = createRequire2(import.meta.url);
98151
- ASCII_CONTROL_PATTERN2 = /[\u0000-\u001f\u007f]/;
98152
- DNS_LABEL_PATTERN2 = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
98153
- ClientTransportConfigurationError2 = class ClientTransportConfigurationError3 extends Error {
98154
- appName;
98155
- sources;
98156
- constructor(appName, message, sources = []) {
98157
- super(message);
98158
- this.name = "ClientTransportConfigurationError";
98159
- this.appName = appName;
98160
- this.sources = Object.freeze([...sources]);
98161
- }
98162
- };
98163
- HasnaHttpError = class HasnaHttpError2 extends Error {
98164
- status;
98165
- method;
98166
- path;
98167
- credentialSource;
98168
- credentialTier;
98169
- constructor(method2, path, status, body, credential) {
98170
- const guidance = credential ? `. ${credential.guidance}` : "";
98171
- super(`Hasna cloud request failed: ${method2} ${path} -> ${status}${guidance}`);
98172
- this.name = "HasnaHttpError";
98173
- this.status = status;
98174
- this.method = method2;
98175
- this.path = path;
98176
- Object.defineProperty(this, "body", {
98177
- value: body,
98178
- enumerable: status !== 401 && status !== 403,
98179
- writable: false,
98180
- configurable: false
98181
- });
98182
- this.credentialSource = credential?.source ?? null;
98183
- this.credentialTier = credential?.tier ?? null;
98184
- }
98185
- };
98186
- DEFAULT_RETRY_STATUSES = [408, 425, 429, 500, 502, 503, 504];
98187
- IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
98188
- AUTHORITY_OVERRIDE_HEADERS2 = new Set([
98189
- "host",
98190
- ":authority",
98191
- "forwarded",
98192
- "x-forwarded-host",
98193
- "x-original-host"
98194
- ]);
98195
- });
98196
- init_storage = __esm2(() => {
98197
- MAX_CREDENTIAL_FILE_BYTES22 = 64 * 1024;
98198
- INSPECT_CUSTOM22 = Symbol.for("nodejs.util.inspect.custom");
98199
- CREDENTIAL_SEAL22 = Symbol.for("hasna:contracts:sealedCredential");
98200
- AMBIENT_ENVIRONMENT22 = Symbol.for("hasna:contracts:ambientClientEnvironment");
98201
- SECRETS_PACKAGE_SPECIFIER2 = "@hasna/" + "secrets";
98202
- requireSecretsSdk22 = createRequire22(import.meta.url);
98203
- IDEMPOTENT_METHODS22 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
98204
- AUTHORITY_OVERRIDE_HEADERS22 = new Set([
98205
- "host",
98206
- ":authority",
98207
- "forwarded",
98208
- "x-forwarded-host",
98209
- "x-original-host"
98210
- ]);
98211
- });
98212
- init_data_dir = __esm2(() => {
98213
- PATHS_RESOLVER_APP_SLUG_RE3 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
98214
- SQLITE_SIDECAR_FILES = ["vault.db-wal", "vault.db-shm", "vault.db-journal"];
98215
- LEGACY_SERVICE_FILES = [
98216
- "vault.key",
98217
- "vault.key.enc",
98218
- "kms.json",
98219
- "aws.json",
98220
- ".serve-token"
98221
- ];
98222
- });
98223
- init_test_isolation = __esm2(() => {
98224
- init_data_dir();
98225
- SecretsTestIsolationError = class SecretsTestIsolationError2 extends Error {
98226
- constructor(message) {
98227
- super(message);
98228
- this.name = "SecretsTestIsolationError";
98229
- }
98230
- };
98231
- TEST_ENTRYPOINT_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
98232
- });
98233
- init_client = __esm2(() => {
98234
- init_transport2();
98235
- init_storage();
98236
- init_test_isolation();
98237
- init_transport2();
98238
- });
98239
- init_client();
98240
- ApiError = class ApiError extends Error {
98241
- status;
98242
- body;
98243
- constructor(status, message, body) {
98244
- super(message);
98245
- this.status = status;
98246
- this.body = body;
98247
- this.name = "ApiError";
98248
- }
98249
- };
98250
- init_client();
98251
- });
98252
-
98253
- // src/lib/execution-secrets.ts
98254
- import { constants as constants26, closeSync as closeSync27, fstatSync as fstatSync27, openSync as openSync27, readSync as readSync20, realpathSync as realpathSync16 } from "fs";
98255
- import { hostname as stationHostname } from "os";
98256
- function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
96969
+ function selectedSecretBindingsTemplate(scope, names, createClient2) {
98257
96970
  let secretsAuthority;
98258
96971
  try {
98259
96972
  secretsAuthority = createClient2().baseUrl;
@@ -98295,8 +97008,8 @@ function declaredSecretNames(value) {
98295
97008
  function readSelectedSecretBindings(path) {
98296
97009
  let fd;
98297
97010
  try {
98298
- fd = openSync27(path, constants26.O_RDONLY | constants26.O_NOFOLLOW | constants26.O_NONBLOCK);
98299
- const stat2 = fstatSync27(fd);
97011
+ fd = openSync26(path, constants26.O_RDONLY | constants26.O_NOFOLLOW | constants26.O_NONBLOCK);
97012
+ const stat2 = fstatSync26(fd);
98300
97013
  if (!stat2.isFile() || stat2.size > 65536)
98301
97014
  throw new Error;
98302
97015
  const bytes = Buffer.alloc(65537);
@@ -98311,7 +97024,7 @@ function readSelectedSecretBindings(path) {
98311
97024
  return refuse6("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
98312
97025
  } finally {
98313
97026
  if (fd !== undefined)
98314
- closeSync27(fd);
97027
+ closeSync26(fd);
98315
97028
  }
98316
97029
  }
98317
97030
  function validateSelectedSecretBindings(value, scope, names) {
@@ -98345,12 +97058,13 @@ function validateSelectedSecretBindings(value, scope, names) {
98345
97058
  }
98346
97059
  return structuredClone(value);
98347
97060
  }
98348
- async function resolveSelectedSecrets(bindings, createClient2 = createSecretsClientFromEnv) {
97061
+ async function resolveSelectedSecrets(bindings, createClient2) {
98349
97062
  if (!Object.keys(bindings.bindings).length)
98350
97063
  return {};
97064
+ const factory = createClient2 ?? await defaultSecretsClientFactory();
98351
97065
  let client2;
98352
97066
  try {
98353
- client2 = createClient2();
97067
+ client2 = factory();
98354
97068
  } catch {
98355
97069
  return refuse6("LOCAL_SECRET_UNAVAILABLE", "The configured Secrets client could not authenticate. No ambient credential fallback was attempted.");
98356
97070
  }
@@ -98383,7 +97097,6 @@ function redactExecutionSecrets(text5, env3) {
98383
97097
  return text5;
98384
97098
  }
98385
97099
  var init_execution_secrets = __esm(() => {
98386
- init_sdk();
98387
97100
  init_selection_cache();
98388
97101
  });
98389
97102
 
@@ -98607,7 +97320,7 @@ __export(exports_selected_run, {
98607
97320
  import { createHash as createHash41 } from "crypto";
98608
97321
  import { spawn as spawn4 } from "child_process";
98609
97322
  import { mkdirSync as mkdirSync19, mkdtempSync as mkdtempSync5, writeFileSync as writeFileSync18, realpathSync as realpathSync17 } from "fs";
98610
- import { dirname as dirname37, join as join61, resolve as resolve34 } from "path";
97323
+ import { dirname as dirname37, join as join60, resolve as resolve34 } from "path";
98611
97324
  import { tmpdir, hostname as stationHostname2 } from "os";
98612
97325
  async function resolveSelectedRun(spec, profileId, options = {}) {
98613
97326
  const context = await resolveSelectionContext(profileId, options);
@@ -98664,7 +97377,7 @@ async function prepareSelectedSecretBindings(selected, cwd2 = process.cwd()) {
98664
97377
  const names = declaredSecretNames(manifest.runtime?.env);
98665
97378
  if (!names.length)
98666
97379
  throw new SkillSelectionError("NO_DECLARED_SECRETS", "This selected executable does not declare any environment references.");
98667
- return selectedSecretBindingsTemplate({ selection: selected.selection, profileId: selected.profileId, cwd: cwd2 }, names);
97380
+ return selectedSecretBindingsTemplate({ selection: selected.selection, profileId: selected.profileId, cwd: cwd2 }, names, await defaultSecretsClientFactory());
98668
97381
  }
98669
97382
  async function executeSelectedLocal(selected, options = {}) {
98670
97383
  const selection2 = structuredClone(selected.selection), profileId = selected.profileId;
@@ -98730,7 +97443,7 @@ async function executeSelectedLocal(selected, options = {}) {
98730
97443
  throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
98731
97444
  secretEnv[name] = value;
98732
97445
  }
98733
- const runDirectory = mkdtempSync5(join61(tmpdir(), "skills-execution-"));
97446
+ const runDirectory = mkdtempSync5(join60(tmpdir(), "skills-execution-"));
98734
97447
  const paths = new SkillEntryPaths;
98735
97448
  for (const entry of entries) {
98736
97449
  paths.add(entry.path, 100, () => {
@@ -98738,7 +97451,7 @@ async function executeSelectedLocal(selected, options = {}) {
98738
97451
  }, () => {
98739
97452
  throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
98740
97453
  });
98741
- const destination = join61(runDirectory, entry.path);
97454
+ const destination = join60(runDirectory, entry.path);
98742
97455
  mkdirSync19(dirname37(destination), { recursive: true, mode: 448 });
98743
97456
  writeFileSync18(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
98744
97457
  }
@@ -98766,7 +97479,7 @@ async function executeSelectedLocal(selected, options = {}) {
98766
97479
  }
98767
97480
  if (bindings)
98768
97481
  secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
98769
- const result2 = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], join61(runDirectory, declaredEntry), ...args], runDirectory, { ...env3, ...secretEnv }, input2, timeoutMs);
97482
+ const result2 = await subprocess([executable2, ...runtimeName === "bun" ? ["--no-env-file"] : [], join60(runDirectory, declaredEntry), ...args], runDirectory, { ...env3, ...secretEnv }, input2, timeoutMs);
98770
97483
  result2.stdout = redactExecutionSecrets(result2.stdout, secretEnv);
98771
97484
  result2.stderr = redactExecutionSecrets(result2.stderr, secretEnv);
98772
97485
  const receipt = {
@@ -98780,7 +97493,7 @@ async function executeSelectedLocal(selected, options = {}) {
98780
97493
  ...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
98781
97494
  ...result2
98782
97495
  };
98783
- writeFileSync18(join61(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
97496
+ writeFileSync18(join60(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
98784
97497
  return receipt;
98785
97498
  }
98786
97499
  async function subprocess(command, cwd2, env3, input2, timeoutMs) {
@@ -102992,20 +101705,20 @@ var init_runs = __esm(() => {
102992
101705
 
102993
101706
  // src/lib/run-state.ts
102994
101707
  import { createHash as createHash42, randomBytes } from "crypto";
102995
- import { existsSync as existsSync28, mkdirSync as mkdirSync20, readFileSync as readFileSync39, readdirSync as readdirSync23, statSync as statSync19, writeFileSync as writeFileSync19 } from "fs";
102996
- import { extname, join as join62, relative as relative11 } from "path";
101708
+ import { existsSync as existsSync28, mkdirSync as mkdirSync20, readFileSync as readFileSync38, readdirSync as readdirSync23, statSync as statSync19, writeFileSync as writeFileSync19 } from "fs";
101709
+ import { extname, join as join61, relative as relative11 } from "path";
102997
101710
  function createSkillRun(params, targetDir = process.cwd()) {
102998
101711
  const now3 = new Date;
102999
101712
  const id2 = createRunId(now3);
103000
101713
  const day = now3.toISOString().slice(0, 10);
103001
101714
  const skillName = normalizeSkillName(params.skill);
103002
101715
  const root2 = getProjectStateDir(targetDir);
103003
- const runDir = join62(root2, "runs", day, id2);
103004
- const logsDir = join62(runDir, "logs");
103005
- const exportDir = join62(root2, "exports", skillName, id2);
101716
+ const runDir = join61(root2, "runs", day, id2);
101717
+ const logsDir = join61(runDir, "logs");
101718
+ const exportDir = join61(root2, "exports", skillName, id2);
103006
101719
  mkdirSync20(logsDir, { recursive: true });
103007
101720
  mkdirSync20(exportDir, { recursive: true });
103008
- mkdirSync20(join62(root2, "tmp"), { recursive: true });
101721
+ mkdirSync20(join61(root2, "tmp"), { recursive: true });
103009
101722
  const record13 = {
103010
101723
  id: id2,
103011
101724
  skill: skillName,
@@ -103057,27 +101770,27 @@ function updateSkillRun(context, patch) {
103057
101770
  return context.record;
103058
101771
  }
103059
101772
  function writeRunLogs(context, stdout = "", stderr = "") {
103060
- writeFileSync19(join62(context.logsDir, "stdout.log"), stdout);
103061
- writeFileSync19(join62(context.logsDir, "stderr.log"), stderr);
101773
+ writeFileSync19(join61(context.logsDir, "stdout.log"), stdout);
101774
+ writeFileSync19(join61(context.logsDir, "stderr.log"), stderr);
103062
101775
  }
103063
101776
  function appendRunEvent(context, event, data = {}) {
103064
101777
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
103065
101778
  `;
103066
- const path = join62(context.runDir, "events.ndjson");
103067
- const previous = existsSync28(path) ? readFileSync39(path, "utf-8") : "";
101779
+ const path = join61(context.runDir, "events.ndjson");
101780
+ const previous = existsSync28(path) ? readFileSync38(path, "utf-8") : "";
103068
101781
  writeFileSync19(path, previous + line);
103069
101782
  }
103070
101783
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
103071
- const runsRoot = join62(getProjectStateDir(targetDir), "runs");
101784
+ const runsRoot = join61(getProjectStateDir(targetDir), "runs");
103072
101785
  if (!existsSync28(runsRoot))
103073
101786
  return [];
103074
101787
  const records = [];
103075
101788
  for (const day of readdirSync23(runsRoot).sort().reverse()) {
103076
- const dayDir = join62(runsRoot, day);
101789
+ const dayDir = join61(runsRoot, day);
103077
101790
  if (!statSync19(dayDir).isDirectory())
103078
101791
  continue;
103079
101792
  for (const runId2 of readdirSync23(dayDir).sort().reverse()) {
103080
- const record13 = readRunRecord(join62(dayDir, runId2));
101793
+ const record13 = readRunRecord(join61(dayDir, runId2));
103081
101794
  if (record13)
103082
101795
  records.push(record13);
103083
101796
  if (records.length >= limit)
@@ -103087,11 +101800,11 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
103087
101800
  return records;
103088
101801
  }
103089
101802
  function findSkillRun(runId2, targetDir = process.cwd()) {
103090
- const runsRoot = join62(getProjectStateDir(targetDir), "runs");
101803
+ const runsRoot = join61(getProjectStateDir(targetDir), "runs");
103091
101804
  if (!existsSync28(runsRoot))
103092
101805
  return null;
103093
101806
  for (const day of readdirSync23(runsRoot)) {
103094
- const record13 = readRunRecord(join62(runsRoot, day, runId2));
101807
+ const record13 = readRunRecord(join61(runsRoot, day, runId2));
103095
101808
  if (record13)
103096
101809
  return record13;
103097
101810
  }
@@ -103108,14 +101821,14 @@ function skillRunEnv(context) {
103108
101821
  };
103109
101822
  }
103110
101823
  function getRunExportDir(runId2, skill, targetDir = process.cwd()) {
103111
- return join62(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId2);
101824
+ return join61(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId2);
103112
101825
  }
103113
101826
  function writeRunRecord(context) {
103114
- writeFileSync19(join62(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
101827
+ writeFileSync19(join61(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
103115
101828
  `);
103116
101829
  }
103117
101830
  function writeArtifactsManifest(context, artifacts) {
103118
- writeFileSync19(join62(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
101831
+ writeFileSync19(join61(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
103119
101832
  `);
103120
101833
  }
103121
101834
  function collectRunArtifacts(context) {
@@ -103124,7 +101837,7 @@ function collectRunArtifacts(context) {
103124
101837
  const artifacts = [];
103125
101838
  for (const path of walkFiles(context.exportDir)) {
103126
101839
  const stat2 = statSync19(path);
103127
- const bytes = readFileSync39(path);
101840
+ const bytes = readFileSync38(path);
103128
101841
  artifacts.push({
103129
101842
  path: toProjectRelative(context.targetDir, path),
103130
101843
  mime: mimeForPath(path),
@@ -103135,11 +101848,11 @@ function collectRunArtifacts(context) {
103135
101848
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
103136
101849
  }
103137
101850
  function readRunRecord(runDir) {
103138
- const path = join62(runDir, "run.json");
101851
+ const path = join61(runDir, "run.json");
103139
101852
  if (!existsSync28(path))
103140
101853
  return null;
103141
101854
  try {
103142
- return JSON.parse(readFileSync39(path, "utf-8"));
101855
+ return JSON.parse(readFileSync38(path, "utf-8"));
103143
101856
  } catch {
103144
101857
  return null;
103145
101858
  }
@@ -103147,7 +101860,7 @@ function readRunRecord(runDir) {
103147
101860
  function walkFiles(dir) {
103148
101861
  const files = [];
103149
101862
  for (const entry of readdirSync23(dir)) {
103150
- const full = join62(dir, entry);
101863
+ const full = join61(dir, entry);
103151
101864
  if (statSync19(full).isDirectory())
103152
101865
  files.push(...walkFiles(full));
103153
101866
  else
@@ -103197,7 +101910,7 @@ var init_run_state = __esm(() => {
103197
101910
  });
103198
101911
 
103199
101912
  // src/lib/mcp-registration-environment.ts
103200
- import { isAbsolute as isAbsolute35 } from "path";
101913
+ import { isAbsolute as isAbsolute34 } from "path";
103201
101914
  function skillsMcpRegistrationEnvironment(env3 = process.env, origin) {
103202
101915
  const result2 = {};
103203
101916
  const profile = selectedSkillsProfile(env3);
@@ -103207,7 +101920,7 @@ function skillsMcpRegistrationEnvironment(env3 = process.env, origin) {
103207
101920
  const value = env3[key2];
103208
101921
  if (value === undefined)
103209
101922
  continue;
103210
- if (!isAbsolute35(value) || /[\x00-\x1f\x7f]/.test(value))
101923
+ if (!isAbsolute34(value) || /[\x00-\x1f\x7f]/.test(value))
103211
101924
  throw new Error(`Invalid ${key2}; expected an absolute configuration path`);
103212
101925
  result2[key2] = value;
103213
101926
  }
@@ -103237,7 +101950,7 @@ var init_mcp_registration_environment = __esm(() => {
103237
101950
  import { randomUUID as randomUUID9 } from "crypto";
103238
101951
  import fs2 from "fs";
103239
101952
  import { homedir as homedir10 } from "os";
103240
- import { dirname as dirname38, isAbsolute as isAbsolute36, join as join63, relative as relative12, resolve as resolve35, sep as sep18 } from "path";
101953
+ import { dirname as dirname38, isAbsolute as isAbsolute35, join as join62, relative as relative12, resolve as resolve35, sep as sep18 } from "path";
103241
101954
  function guardedAgentConfigRefusal(error61) {
103242
101955
  return error61 instanceof ConfigWriteRefusal ? error61.message : "configuration update was refused";
103243
101956
  }
@@ -103276,7 +101989,7 @@ function unchanged3(before2, current) {
103276
101989
  function parentWitnesses(path) {
103277
101990
  const home = canonicalSystemPath(homedir10()), local = relative12(home, path);
103278
101991
  const creationParent = dirname38(path);
103279
- if (!isAbsolute36(path) || resolve35(path) !== path || !local || local === ".." || local.startsWith(".." + sep18))
101992
+ if (!isAbsolute35(path) || resolve35(path) !== path || !local || local === ".." || local.startsWith(".." + sep18))
103280
101993
  throw new Error;
103281
101994
  const parents3 = [];
103282
101995
  for (let ancestor = home;; ancestor = dirname38(ancestor)) {
@@ -103285,7 +101998,7 @@ function parentWitnesses(path) {
103285
101998
  break;
103286
101999
  }
103287
102000
  for (const part of relative12(home, dirname38(path)).split(sep18).filter(Boolean))
103288
- parents3.push(join63(parents3[parents3.length - 1], part));
102001
+ parents3.push(join62(parents3[parents3.length - 1], part));
103289
102002
  return parents3.map((path2) => {
103290
102003
  if (!statOrMissing(path2)) {
103291
102004
  if (!path2.startsWith(home + sep18))
@@ -103345,7 +102058,7 @@ function guardedAgentConfigWrite(path, transform3) {
103345
102058
  if (typeof process.getuid !== "function")
103346
102059
  throw new Error;
103347
102060
  refusal3 = "UNSAFE_PATH";
103348
- if (!isAbsolute36(path) || resolve35(path) !== path)
102061
+ if (!isAbsolute35(path) || resolve35(path) !== path)
103349
102062
  throw new Error;
103350
102063
  path = canonicalSystemPath(path);
103351
102064
  const parents3 = parentWitnesses(path);
@@ -110186,8 +108899,8 @@ var require_utils = __commonJS((exports, module) => {
110186
108899
  var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
110187
108900
  var HOST_DELIM_RE = /[@/?#:]/g;
110188
108901
  var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
110189
- function reescapeHostDelimiters(host, isIP4) {
110190
- const re = isIP4 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
108902
+ function reescapeHostDelimiters(host, isIP3) {
108903
+ const re = isIP3 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
110191
108904
  re.lastIndex = 0;
110192
108905
  return host.replace(re, (ch) => HOST_DELIMS[ch]);
110193
108906
  }
@@ -110837,8 +109550,8 @@ var require_fast_uri = __commonJS((exports, module) => {
110837
109550
  const host = matches2[4];
110838
109551
  return hasMalformedPercentEncoding(matches2[3]) || host !== undefined && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches2[6]) || hasMalformedPercentEncoding(matches2[7]) || hasMalformedPercentEncoding(matches2[8]);
110839
109552
  }
110840
- function canonicalizeHost(parsed, options, schemeHandler, isIP4) {
110841
- if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP4 === false && nonSimpleDomain(parsed.host)) {
109553
+ function canonicalizeHost(parsed, options, schemeHandler, isIP3) {
109554
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP3 === false && nonSimpleDomain(parsed.host)) {
110842
109555
  try {
110843
109556
  parsed.host = new URL("http://" + parsed.host).hostname;
110844
109557
  } catch (e2) {
@@ -110865,7 +109578,7 @@ var require_fast_uri = __commonJS((exports, module) => {
110865
109578
  let malformedHost = false;
110866
109579
  let malformedIPLiteral = false;
110867
109580
  let malformedScheme = false;
110868
- let isIP4 = false;
109581
+ let isIP3 = false;
110869
109582
  if (options.reference === "suffix") {
110870
109583
  if (options.scheme) {
110871
109584
  uri = options.scheme + ":" + uri;
@@ -110928,15 +109641,15 @@ var require_fast_uri = __commonJS((exports, module) => {
110928
109641
  const bracketedIPLiteral = isIPLiteral(parsed.host);
110929
109642
  const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
110930
109643
  const ipv6result = normalizeIPv6(parsed.host);
110931
- isIP4 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
109644
+ isIP3 = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
110932
109645
  malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
110933
- parsed.host = isIP4 ? ipv6result.host : ipv6result.host.toLowerCase();
109646
+ parsed.host = isIP3 ? ipv6result.host : ipv6result.host.toLowerCase();
110934
109647
  if (malformedIPLiteral) {
110935
109648
  parsed.error = parsed.error || "URI host is malformed.";
110936
109649
  malformedAuthorityOrPort = true;
110937
109650
  }
110938
109651
  } else {
110939
- isIP4 = true;
109652
+ isIP3 = true;
110940
109653
  }
110941
109654
  }
110942
109655
  if (parsed.scheme === undefined && parsed.userinfo === undefined && parsed.host === undefined && parsed.port === undefined && parsed.query === undefined && !parsed.path) {
@@ -110953,13 +109666,13 @@ var require_fast_uri = __commonJS((exports, module) => {
110953
109666
  }
110954
109667
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
110955
109668
  if (!malformedIPLiteral) {
110956
- malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP4);
109669
+ malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP3);
110957
109670
  }
110958
109671
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
110959
109672
  if (uri.indexOf("%") !== -1) {
110960
109673
  if (parsed.host !== undefined && !malformedIPLiteral) {
110961
- const host = isIP4 ? parsed.host : normalizePercentEncoding(parsed.host, true);
110962
- parsed.host = reescapeHostDelimiters(host, isIP4);
109674
+ const host = isIP3 ? parsed.host : normalizePercentEncoding(parsed.host, true);
109675
+ parsed.host = reescapeHostDelimiters(host, isIP3);
110963
109676
  }
110964
109677
  }
110965
109678
  if (parsed.path) {
@@ -115388,8 +114101,8 @@ var init_remote_customer_operations = __esm(() => {
115388
114101
  });
115389
114102
 
115390
114103
  // src/lib/workspace-profile.ts
115391
- import { constants as constants27, closeSync as closeSync28, fstatSync as fstatSync28, lstatSync as lstatSync40, mkdirSync as mkdirSync21, mkdtempSync as mkdtempSync6, openSync as openSync28, readFileSync as readFileSync40, renameSync as renameSync13, rmSync as rmSync9, writeFileSync as writeFileSync20 } from "fs";
115392
- import { dirname as dirname39, join as join64 } from "path";
114104
+ import { constants as constants27, closeSync as closeSync27, fstatSync as fstatSync27, lstatSync as lstatSync40, mkdirSync as mkdirSync21, mkdtempSync as mkdtempSync6, openSync as openSync27, readFileSync as readFileSync39, renameSync as renameSync13, rmSync as rmSync9, writeFileSync as writeFileSync20 } from "fs";
114105
+ import { dirname as dirname39, join as join63 } from "path";
115393
114106
  function stat2(path) {
115394
114107
  try {
115395
114108
  return lstatSync40(path);
@@ -115402,14 +114115,14 @@ function stat2(path) {
115402
114115
  function safeText(file2) {
115403
114116
  if (stat2(file2) === null)
115404
114117
  return null;
115405
- const fd = openSync28(file2, constants27.O_RDONLY | constants27.O_NOFOLLOW | constants27.O_NONBLOCK);
114118
+ const fd = openSync27(file2, constants27.O_RDONLY | constants27.O_NOFOLLOW | constants27.O_NONBLOCK);
115406
114119
  try {
115407
- const s = fstatSync28(fd);
114120
+ const s = fstatSync27(fd);
115408
114121
  if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
115409
114122
  return fail4("The selected profile must use bounded owner-only regular files.");
115410
- return readFileSync40(fd, "utf8");
114123
+ return readFileSync39(fd, "utf8");
115411
114124
  } finally {
115412
- closeSync28(fd);
114125
+ closeSync27(fd);
115413
114126
  }
115414
114127
  }
115415
114128
  function checkIdentityMetadata(file2, identity6) {
@@ -115541,11 +114254,11 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
115541
114254
  const identity6 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin, issuedBy: "sign-in" }, null, 2) + `
115542
114255
  `;
115543
114256
  mkdirSync21(dirname39(file2), { recursive: true, mode: 448 });
115544
- const temp = mkdtempSync6(join64(dirname39(file2), ".workspace-login-"));
114257
+ const temp = mkdtempSync6(join63(dirname39(file2), ".workspace-login-"));
115545
114258
  let identityInstalled = false;
115546
114259
  try {
115547
- writeFileSync20(join64(temp, "credentials"), body, { mode: 384, flag: "wx" });
115548
- writeFileSync20(join64(temp, "identity"), identity6, { mode: 384, flag: "wx" });
114260
+ writeFileSync20(join63(temp, "credentials"), body, { mode: 384, flag: "wx" });
114261
+ writeFileSync20(join63(temp, "identity"), identity6, { mode: 384, flag: "wx" });
115549
114262
  unchangedFiles();
115550
114263
  for (const [path, before2] of parents3) {
115551
114264
  const now3 = stat2(path);
@@ -115554,16 +114267,16 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
115554
114267
  if (!before2 && now3 && ((now3.mode & 63) !== 0 || process.getuid && now3.uid !== process.getuid()))
115555
114268
  changed();
115556
114269
  }
115557
- renameSync13(join64(temp, "identity"), identityFile);
114270
+ renameSync13(join63(temp, "identity"), identityFile);
115558
114271
  identityInstalled = true;
115559
- renameSync13(join64(temp, "credentials"), file2);
114272
+ renameSync13(join63(temp, "credentials"), file2);
115560
114273
  } catch (error61) {
115561
114274
  if (identityInstalled) {
115562
114275
  if (oldIdentity === null)
115563
114276
  rmSync9(identityFile, { force: true });
115564
114277
  else {
115565
- writeFileSync20(join64(temp, "restore"), oldIdentity, { mode: 384, flag: "wx" });
115566
- renameSync13(join64(temp, "restore"), identityFile);
114278
+ writeFileSync20(join63(temp, "restore"), oldIdentity, { mode: 384, flag: "wx" });
114279
+ renameSync13(join63(temp, "restore"), identityFile);
115567
114280
  }
115568
114281
  }
115569
114282
  throw error61;
@@ -115757,8 +114470,8 @@ var init_recurring_customer = __esm(() => {
115757
114470
  });
115758
114471
 
115759
114472
  // src/lib/recurring-recovery.ts
115760
- import { constants as constants28, closeSync as closeSync29, fsyncSync as fsyncSync8, fstatSync as fstatSync29, lstatSync as lstatSync41, mkdirSync as mkdirSync22, openSync as openSync29, readSync as readSync21, realpathSync as realpathSync18, renameSync as renameSync14, unlinkSync as unlinkSync10, writeFileSync as writeFileSync21 } from "fs";
115761
- import { dirname as dirname40, isAbsolute as isAbsolute37, join as join65, resolve as resolve36 } from "path";
114473
+ import { constants as constants28, closeSync as closeSync28, fsyncSync as fsyncSync8, fstatSync as fstatSync28, lstatSync as lstatSync41, mkdirSync as mkdirSync22, openSync as openSync28, readSync as readSync21, realpathSync as realpathSync18, renameSync as renameSync14, unlinkSync as unlinkSync10, writeFileSync as writeFileSync21 } from "fs";
114474
+ import { dirname as dirname40, isAbsolute as isAbsolute36, join as join64, resolve as resolve36 } from "path";
115762
114475
  import { randomUUID as randomUUID10 } from "crypto";
115763
114476
 
115764
114477
  class RecoveryOwner {
@@ -115766,7 +114479,7 @@ class RecoveryOwner {
115766
114479
  parents = [];
115767
114480
  constructor(directory2) {
115768
114481
  this.directory = directory2;
115769
- if (!isAbsolute37(directory2) || resolve36(directory2) !== directory2 || realpathSync18(directory2) !== directory2)
114482
+ if (!isAbsolute36(directory2) || resolve36(directory2) !== directory2 || realpathSync18(directory2) !== directory2)
115770
114483
  invalid6();
115771
114484
  for (let path = directory2;; path = dirname40(path)) {
115772
114485
  const stat3 = lstatSync41(path);
@@ -115792,9 +114505,9 @@ class RecoveryOwner {
115792
114505
  }
115793
114506
  read(name) {
115794
114507
  this.assert();
115795
- const fd = openSync29(join65(this.directory, name), constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
114508
+ const fd = openSync28(join64(this.directory, name), constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
115796
114509
  try {
115797
- const before2 = fstatSync29(fd);
114510
+ const before2 = fstatSync28(fd);
115798
114511
  if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
115799
114512
  invalid6();
115800
114513
  const bytes = Buffer.alloc(before2.size + 1);
@@ -115805,36 +114518,36 @@ class RecoveryOwner {
115805
114518
  break;
115806
114519
  size2 += n2;
115807
114520
  }
115808
- const after2 = fstatSync29(fd), path = lstatSync41(join65(this.directory, name));
114521
+ const after2 = fstatSync28(fd), path = lstatSync41(join64(this.directory, name));
115809
114522
  if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
115810
114523
  invalid6();
115811
114524
  this.assert();
115812
114525
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
115813
114526
  } finally {
115814
- closeSync29(fd);
114527
+ closeSync28(fd);
115815
114528
  }
115816
114529
  }
115817
114530
  write(name, value) {
115818
114531
  this.assert();
115819
114532
  const bytes = canonicalJson2(value, 8192) + `
115820
114533
  `;
115821
- const fd = openSync29(join65(this.directory, name), constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
114534
+ const fd = openSync28(join64(this.directory, name), constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
115822
114535
  try {
115823
114536
  writeFileSync21(fd, bytes);
115824
114537
  fsyncSync8(fd);
115825
114538
  } finally {
115826
- closeSync29(fd);
114539
+ closeSync28(fd);
115827
114540
  }
115828
114541
  this.assert();
115829
114542
  this.sync();
115830
114543
  }
115831
114544
  sync() {
115832
114545
  this.assert();
115833
- const fd = openSync29(this.directory, constants28.O_RDONLY | constants28.O_NOFOLLOW);
114546
+ const fd = openSync28(this.directory, constants28.O_RDONLY | constants28.O_NOFOLLOW);
115834
114547
  try {
115835
114548
  fsyncSync8(fd);
115836
114549
  } finally {
115837
- closeSync29(fd);
114550
+ closeSync28(fd);
115838
114551
  }
115839
114552
  }
115840
114553
  saveState(state, expected) {
@@ -115845,30 +114558,30 @@ class RecoveryOwner {
115845
114558
  if (this.read("state.json") !== expected)
115846
114559
  invalid6();
115847
114560
  this.assert();
115848
- renameSync14(join65(this.directory, name), join65(this.directory, "state.json"));
114561
+ renameSync14(join64(this.directory, name), join64(this.directory, "state.json"));
115849
114562
  this.sync();
115850
114563
  }
115851
114564
  async locked(action) {
115852
114565
  this.assert();
115853
114566
  let fd;
115854
114567
  try {
115855
- fd = openSync29(join65(this.directory, "operation.lock"), constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
114568
+ fd = openSync28(join64(this.directory, "operation.lock"), constants28.O_WRONLY | constants28.O_CREAT | constants28.O_EXCL | constants28.O_NOFOLLOW, 384);
115856
114569
  } catch {
115857
114570
  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.");
115858
114571
  }
115859
- const owner3 = fstatSync29(fd);
114572
+ const owner3 = fstatSync28(fd);
115860
114573
  try {
115861
114574
  writeFileSync21(fd, JSON.stringify({ pid: process.pid }));
115862
114575
  fsyncSync8(fd);
115863
114576
  this.sync();
115864
114577
  return await action();
115865
114578
  } finally {
115866
- closeSync29(fd);
114579
+ closeSync28(fd);
115867
114580
  this.assert();
115868
- const now3 = lstatSync41(join65(this.directory, "operation.lock"));
114581
+ const now3 = lstatSync41(join64(this.directory, "operation.lock"));
115869
114582
  if (owner3.dev !== now3.dev || owner3.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
115870
114583
  invalid6();
115871
- unlinkSync10(join65(this.directory, "operation.lock"));
114584
+ unlinkSync10(join64(this.directory, "operation.lock"));
115872
114585
  this.sync();
115873
114586
  }
115874
114587
  }
@@ -115901,7 +114614,7 @@ function base2(customer, organizationId) {
115901
114614
  };
115902
114615
  }
115903
114616
  function create3(directory2, intent) {
115904
- if (!isAbsolute37(directory2) || resolve36(directory2) !== directory2 || realpathSync18(dirname40(directory2)) !== dirname40(directory2))
114617
+ if (!isAbsolute36(directory2) || resolve36(directory2) !== directory2 || realpathSync18(dirname40(directory2)) !== dirname40(directory2))
115905
114618
  invalid6();
115906
114619
  mkdirSync22(directory2, { mode: 448 });
115907
114620
  const owner3 = new RecoveryOwner(directory2), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
@@ -116064,7 +114777,7 @@ var init_recurring_recovery = __esm(() => {
116064
114777
  });
116065
114778
 
116066
114779
  // src/lib/recurring-surface.ts
116067
- import { isAbsolute as isAbsolute38 } from "path";
114780
+ import { isAbsolute as isAbsolute37 } from "path";
116068
114781
  function recurringMcpSchema(action) {
116069
114782
  return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
116070
114783
  }
@@ -116169,7 +114882,7 @@ var init_recurring_surface = __esm(() => {
116169
114882
  uuid12 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
116170
114883
  context = { userId: uuid12.optional(), membershipId: uuid12.optional() };
116171
114884
  page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
116172
- directory2 = exports_external.string().max(4096).refine(isAbsolute38, "Use an absolute recovery directory");
114885
+ directory2 = exports_external.string().max(4096).refine(isAbsolute37, "Use an absolute recovery directory");
116173
114886
  email4 = exports_external.string().trim().toLowerCase().email().max(254);
116174
114887
  code = exports_external.string().regex(/^\d{6}$/);
116175
114888
  recurringSurfaceSchemas = {
@@ -117542,7 +116255,7 @@ var init_run_routing = __esm(() => {
117542
116255
 
117543
116256
  // src/mcp/operation-tools.ts
117544
116257
  import { existsSync as existsSync29, readdirSync as readdirSync24, statSync as statSync20 } from "fs";
117545
- import { join as join66 } from "path";
116258
+ import { join as join65 } from "path";
117546
116259
  function registerOperationTools(server) {
117547
116260
  server.registerTool("cloud_skill_eligibility", {
117548
116261
  title: "Cloud Skill Eligibility",
@@ -118024,7 +116737,7 @@ function registerOperationTools(server) {
118024
116737
  if (exists) {
118025
116738
  try {
118026
116739
  skillCount = readdirSync24(agentSkillsPath).filter((f) => {
118027
- const full = join66(agentSkillsPath, f);
116740
+ const full = join65(agentSkillsPath, f);
118028
116741
  return !f.startsWith(".") && statSync20(full).isDirectory();
118029
116742
  }).length;
118030
116743
  } catch {}
@@ -118092,10 +116805,10 @@ var init_operation_tools = __esm(() => {
118092
116805
 
118093
116806
  // src/lib/feedback.ts
118094
116807
  import { appendFileSync as appendFileSync2, existsSync as existsSync30, mkdirSync as mkdirSync23 } from "fs";
118095
- import { dirname as dirname41, join as join67 } from "path";
116808
+ import { dirname as dirname41, join as join66 } from "path";
118096
116809
  import { Database } from "bun:sqlite";
118097
116810
  function getFeedbackDbPath() {
118098
- return join67(getDataDir(), "skills.db");
116811
+ return join66(getDataDir(), "skills.db");
118099
116812
  }
118100
116813
  function getFeedbackDb() {
118101
116814
  const dbPath = getFeedbackDbPath();
@@ -118127,7 +116840,7 @@ function saveFeedback(input2) {
118127
116840
  throw new Error("Feedback message is required");
118128
116841
  const category = input2.category ?? "general";
118129
116842
  if (isApiMode()) {
118130
- const path = join67(getDataDir(), "feedback.jsonl");
116843
+ const path = join66(getDataDir(), "feedback.jsonl");
118131
116844
  const dir = dirname41(path);
118132
116845
  if (!existsSync30(dir))
118133
116846
  mkdirSync23(dir, { recursive: true });
@@ -118291,23 +117004,23 @@ var init_resource_meta_tools = __esm(() => {
118291
117004
  });
118292
117005
 
118293
117006
  // src/lib/scheduler.ts
118294
- import { existsSync as existsSync31, readFileSync as readFileSync41, writeFileSync as writeFileSync22, mkdirSync as mkdirSync24 } from "fs";
118295
- import { join as join68 } from "path";
117007
+ import { existsSync as existsSync31, readFileSync as readFileSync40, writeFileSync as writeFileSync22, mkdirSync as mkdirSync24 } from "fs";
117008
+ import { join as join67 } from "path";
118296
117009
  function getSchedulesPath(targetDir = process.cwd()) {
118297
- return join68(targetDir, ".skills", "schedules.json");
117010
+ return join67(targetDir, ".skills", "schedules.json");
118298
117011
  }
118299
117012
  function loadSchedules(targetDir = process.cwd()) {
118300
117013
  const path = getSchedulesPath(targetDir);
118301
117014
  if (existsSync31(path)) {
118302
117015
  try {
118303
- return JSON.parse(readFileSync41(path, "utf-8"));
117016
+ return JSON.parse(readFileSync40(path, "utf-8"));
118304
117017
  } catch {}
118305
117018
  }
118306
117019
  return { version: 1, schedules: [] };
118307
117020
  }
118308
117021
  function saveSchedules(data, targetDir = process.cwd()) {
118309
117022
  const path = getSchedulesPath(targetDir);
118310
- const dir = join68(targetDir, ".skills");
117023
+ const dir = join67(targetDir, ".skills");
118311
117024
  if (!existsSync31(dir))
118312
117025
  mkdirSync24(dir, { recursive: true });
118313
117026
  writeFileSync22(path, JSON.stringify(data, null, 2));
@@ -118610,12 +117323,12 @@ import { createHash as createHash43, createHmac as createHmac3 } from "crypto";
118610
117323
  import {
118611
117324
  existsSync as existsSync32,
118612
117325
  mkdirSync as mkdirSync25,
118613
- readFileSync as readFileSync42,
117326
+ readFileSync as readFileSync41,
118614
117327
  readdirSync as readdirSync25,
118615
117328
  statSync as statSync21,
118616
117329
  writeFileSync as writeFileSync23
118617
117330
  } from "fs";
118618
- import { dirname as dirname42, join as join69, normalize as normalize5, relative as relative13, sep as sep19 } from "path";
117331
+ import { dirname as dirname42, join as join68, normalize as normalize5, relative as relative13, sep as sep19 } from "path";
118619
117332
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
118620
117333
  assertNoRetiredModeEnvVars(env3, {
118621
117334
  app: SKILLS_ENV_NAMESPACE,
@@ -118656,7 +117369,7 @@ function getSkillsNativeStorageStatus(options = {}) {
118656
117369
  local: {
118657
117370
  dataDir: getDataDir(),
118658
117371
  projectStateDir: getProjectStateDir(targetDir),
118659
- feedbackDbPath: join69(getDataDir(), "skills.db")
117372
+ feedbackDbPath: join68(getDataDir(), "skills.db")
118660
117373
  },
118661
117374
  remote: {
118662
117375
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -118678,7 +117391,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
118678
117391
  const files = [];
118679
117392
  if (existsSync32(projectStateDir)) {
118680
117393
  for (const filePath of walkFiles2(projectStateDir)) {
118681
- const bytes = readFileSync42(filePath);
117394
+ const bytes = readFileSync41(filePath);
118682
117395
  const relativePath = toPosix(relative13(targetDir, filePath));
118683
117396
  files.push({
118684
117397
  path: relativePath,
@@ -118737,7 +117450,7 @@ function parsePositiveInteger(value) {
118737
117450
  function walkFiles2(dir) {
118738
117451
  const files = [];
118739
117452
  for (const entry of readdirSync25(dir)) {
118740
- const full = join69(dir, entry);
117453
+ const full = join68(dir, entry);
118741
117454
  const stats = statSync21(full);
118742
117455
  if (stats.isDirectory())
118743
117456
  files.push(...walkFiles2(full));
@@ -119009,11 +117722,11 @@ var init_private_publication_customer = __esm(() => {
119009
117722
  });
119010
117723
 
119011
117724
  // src/lib/private-publication-recovery.ts
119012
- import { constants as constants29, closeSync as closeSync30, fsyncSync as fsyncSync9, fstatSync as fstatSync30, lstatSync as lstatSync42, mkdirSync as mkdirSync26, openSync as openSync30, readSync as readSync22, realpathSync as realpathSync19, renameSync as renameSync15, unlinkSync as unlinkSync11, writeFileSync as writeFileSync24 } from "fs";
119013
- import { dirname as dirname43, isAbsolute as isAbsolute39, join as join70, resolve as resolve37 } from "path";
117725
+ import { constants as constants29, closeSync as closeSync29, fsyncSync as fsyncSync9, fstatSync as fstatSync29, lstatSync as lstatSync42, mkdirSync as mkdirSync26, openSync as openSync29, readSync as readSync22, realpathSync as realpathSync19, renameSync as renameSync15, unlinkSync as unlinkSync11, writeFileSync as writeFileSync24 } from "fs";
117726
+ import { dirname as dirname43, isAbsolute as isAbsolute38, join as join69, resolve as resolve37 } from "path";
119014
117727
  import { randomUUID as randomUUID11 } from "crypto";
119015
117728
  function safeDirectory(directory3) {
119016
- if (!isAbsolute39(directory3) || directory3 !== resolve37(directory3) || realpathSync19(directory3) !== directory3)
117729
+ if (!isAbsolute38(directory3) || directory3 !== resolve37(directory3) || realpathSync19(directory3) !== directory3)
119017
117730
  return fail5();
119018
117731
  for (let path = directory3;; path = dirname43(path)) {
119019
117732
  const stat3 = lstatSync42(path);
@@ -119033,10 +117746,10 @@ function unchangedDirectory(directory3, identity6) {
119033
117746
  return fail5();
119034
117747
  }
119035
117748
  function readOwned(directory3, name, max2) {
119036
- const identity6 = safeDirectory(directory3), file2 = join70(directory3, name);
119037
- const fd = openSync30(file2, constants29.O_RDONLY | constants29.O_NOFOLLOW);
117749
+ const identity6 = safeDirectory(directory3), file2 = join69(directory3, name);
117750
+ const fd = openSync29(file2, constants29.O_RDONLY | constants29.O_NOFOLLOW);
119038
117751
  try {
119039
- const stat3 = fstatSync30(fd);
117752
+ const stat3 = fstatSync29(fd);
119040
117753
  if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
119041
117754
  return fail5();
119042
117755
  const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
@@ -119047,22 +117760,22 @@ function readOwned(directory3, name, max2) {
119047
117760
  break;
119048
117761
  length += count;
119049
117762
  }
119050
- const bytes = buffer.subarray(0, length), after2 = fstatSync30(fd);
117763
+ const bytes = buffer.subarray(0, length), after2 = fstatSync29(fd);
119051
117764
  unchangedDirectory(directory3, identity6);
119052
117765
  if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
119053
117766
  return fail5();
119054
117767
  return bytes;
119055
117768
  } finally {
119056
- closeSync30(fd);
117769
+ closeSync29(fd);
119057
117770
  }
119058
117771
  }
119059
117772
  function writeOwned(directory3, name, bytes) {
119060
- const fd = openSync30(join70(directory3, name), constants29.O_WRONLY | constants29.O_CREAT | constants29.O_EXCL | constants29.O_NOFOLLOW, 384);
117773
+ const fd = openSync29(join69(directory3, name), constants29.O_WRONLY | constants29.O_CREAT | constants29.O_EXCL | constants29.O_NOFOLLOW, 384);
119061
117774
  try {
119062
117775
  writeFileSync24(fd, bytes);
119063
117776
  fsyncSync9(fd);
119064
117777
  } finally {
119065
- closeSync30(fd);
117778
+ closeSync29(fd);
119066
117779
  }
119067
117780
  }
119068
117781
  function save2(directory3, value) {
@@ -119070,12 +117783,12 @@ function save2(directory3, value) {
119070
117783
  writeOwned(directory3, temporary, JSON.stringify(value) + `
119071
117784
  `);
119072
117785
  unchangedDirectory(directory3, identity6);
119073
- renameSync15(join70(directory3, temporary), join70(directory3, "receipt.json"));
119074
- const fd = openSync30(directory3, constants29.O_RDONLY | constants29.O_NOFOLLOW);
117786
+ renameSync15(join69(directory3, temporary), join69(directory3, "receipt.json"));
117787
+ const fd = openSync29(directory3, constants29.O_RDONLY | constants29.O_NOFOLLOW);
119075
117788
  try {
119076
117789
  fsyncSync9(fd);
119077
117790
  } finally {
119078
- closeSync30(fd);
117791
+ closeSync29(fd);
119079
117792
  }
119080
117793
  }
119081
117794
  function bind2(client2, receipt) {
@@ -119083,21 +117796,21 @@ function bind2(client2, receipt) {
119083
117796
  throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
119084
117797
  }
119085
117798
  async function locked(directory3, action) {
119086
- const identity6 = safeDirectory(directory3), file2 = join70(directory3, "operation.lock");
117799
+ const identity6 = safeDirectory(directory3), file2 = join69(directory3, "operation.lock");
119087
117800
  let fd;
119088
117801
  try {
119089
- fd = openSync30(file2, constants29.O_WRONLY | constants29.O_CREAT | constants29.O_EXCL | constants29.O_NOFOLLOW, 384);
117802
+ fd = openSync29(file2, constants29.O_WRONLY | constants29.O_CREAT | constants29.O_EXCL | constants29.O_NOFOLLOW, 384);
119090
117803
  } catch {
119091
117804
  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.");
119092
117805
  }
119093
- const lock = fstatSync30(fd);
117806
+ const lock = fstatSync29(fd);
119094
117807
  try {
119095
117808
  writeFileSync24(fd, JSON.stringify({ pid: process.pid }) + `
119096
117809
  `);
119097
117810
  fsyncSync9(fd);
119098
117811
  return await action();
119099
117812
  } finally {
119100
- closeSync30(fd);
117813
+ closeSync29(fd);
119101
117814
  unchangedDirectory(directory3, identity6);
119102
117815
  const now3 = lstatSync42(file2);
119103
117816
  if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
@@ -119151,15 +117864,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
119151
117864
  phase: "prepared",
119152
117865
  intent: null
119153
117866
  };
119154
- if (!isAbsolute39(recoveryDirectory) || resolve37(recoveryDirectory) !== recoveryDirectory || realpathSync19(dirname43(recoveryDirectory)) !== dirname43(recoveryDirectory))
117867
+ if (!isAbsolute38(recoveryDirectory) || resolve37(recoveryDirectory) !== recoveryDirectory || realpathSync19(dirname43(recoveryDirectory)) !== dirname43(recoveryDirectory))
119155
117868
  return fail5();
119156
117869
  mkdirSync26(recoveryDirectory, { mode: 448 });
119157
117870
  safeDirectory(recoveryDirectory);
119158
- const parent = openSync30(dirname43(recoveryDirectory), constants29.O_RDONLY | constants29.O_NOFOLLOW);
117871
+ const parent = openSync29(dirname43(recoveryDirectory), constants29.O_RDONLY | constants29.O_NOFOLLOW);
119159
117872
  try {
119160
117873
  fsyncSync9(parent);
119161
117874
  } finally {
119162
- closeSync30(parent);
117875
+ closeSync29(parent);
119163
117876
  }
119164
117877
  writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
119165
117878
  save2(recoveryDirectory, receipt);
@@ -119252,10 +117965,10 @@ var init_private_publication_recovery = __esm(() => {
119252
117965
  });
119253
117966
 
119254
117967
  // src/mcp/private-publication-tools.ts
119255
- import { isAbsolute as isAbsolute40 } from "path";
117968
+ import { isAbsolute as isAbsolute39 } from "path";
119256
117969
  function registerPrivatePublicationTools(server) {
119257
117970
  const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
119258
- const directory3 = exports_external.string().max(4096).refine(isAbsolute40, "Use an absolute local directory");
117971
+ const directory3 = exports_external.string().max(4096).refine(isAbsolute39, "Use an absolute local directory");
119259
117972
  const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory3 };
119260
117973
  const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
119261
117974
  const handler = (action) => async (value) => {
@@ -119716,10 +118429,10 @@ var exports_runtime_mcp = {};
119716
118429
  __export(exports_runtime_mcp, {
119717
118430
  handleMcp: () => handleMcp
119718
118431
  });
119719
- import { closeSync as closeSync31, constants as constants30, existsSync as existsSync33, fchmodSync as fchmodSync3, fchownSync, fstatSync as fstatSync31, fsyncSync as fsyncSync10, lstatSync as lstatSync43, mkdirSync as mkdirSync27, openSync as openSync31, readFileSync as readFileSync43, readSync as readSync23, renameSync as renameSync16, rmdirSync as rmdirSync4, statSync as statSync22, unlinkSync as unlinkSync12, writeFileSync as writeFileSync25, writeSync as writeSync6 } from "fs";
118432
+ import { closeSync as closeSync30, constants as constants30, existsSync as existsSync33, fchmodSync as fchmodSync3, fchownSync, fstatSync as fstatSync30, fsyncSync as fsyncSync10, lstatSync as lstatSync43, mkdirSync as mkdirSync27, openSync as openSync30, readFileSync as readFileSync42, readSync as readSync23, renameSync as renameSync16, rmdirSync as rmdirSync4, statSync as statSync22, unlinkSync as unlinkSync12, writeFileSync as writeFileSync25, writeSync as writeSync6 } from "fs";
119720
118433
  import { randomUUID as randomUUID12 } from "crypto";
119721
118434
  import { homedir as homedir11 } from "os";
119722
- import { dirname as dirname44, isAbsolute as isAbsolute41, join as join71 } from "path";
118435
+ import { dirname as dirname44, isAbsolute as isAbsolute40, join as join70 } from "path";
119723
118436
  import { isDeepStrictEqual as isDeepStrictEqual19, stripVTControlCharacters } from "util";
119724
118437
  async function handleMcp(options) {
119725
118438
  if (options.register) {
@@ -119766,15 +118479,15 @@ async function registerMcpForAgent(agent, command, environment) {
119766
118479
  case "codex":
119767
118480
  return registerCodexMcp(command, environment);
119768
118481
  case "gemini":
119769
- return registerJsonMcpServer(agent, join71(homedir11(), ".gemini", "settings.json"), "mcpServers", server2);
118482
+ return registerJsonMcpServer(agent, join70(homedir11(), ".gemini", "settings.json"), "mcpServers", server2);
119770
118483
  case "pi":
119771
- return registerJsonMcpServer(agent, join71(homedir11(), ".pi", "agent", "mcp.json"), "mcpServers", server2);
118484
+ return registerJsonMcpServer(agent, join70(homedir11(), ".pi", "agent", "mcp.json"), "mcpServers", server2);
119772
118485
  case "opencode":
119773
118486
  return registerOpenCodeMcp(command, environment);
119774
118487
  case "cursor":
119775
- return registerJsonMcpServer(agent, join71(homedir11(), ".cursor", "mcp.json"), "mcpServers", server2);
118488
+ return registerJsonMcpServer(agent, join70(homedir11(), ".cursor", "mcp.json"), "mcpServers", server2);
119776
118489
  case "windsurf":
119777
- return registerJsonMcpServer(agent, join71(homedir11(), ".windsurf", "mcp.json"), "mcpServers", server2);
118490
+ return registerJsonMcpServer(agent, join70(homedir11(), ".windsurf", "mcp.json"), "mcpServers", server2);
119778
118491
  default:
119779
118492
  return { agent, success: false, error: `Unknown agent: ${agent}. Available: ${AGENT_TARGETS.join(", ")}, all` };
119780
118493
  }
@@ -119798,7 +118511,7 @@ async function registerClaudeMcp(command, server2, environment) {
119798
118511
  const info = lstatSync43(path);
119799
118512
  const backup = `${path}.skills-mcp-${randomUUID12()}.backup`;
119800
118513
  writeFileSync25(backup, bytes, { flag: "wx", mode: 384 });
119801
- if (!readFileSync43(backup).equals(bytes))
118514
+ if (!readFileSync42(backup).equals(bytes))
119802
118515
  throw new Error;
119803
118516
  preimage = { bytes, mode: info.mode & 4095, uid: info.uid, gid: info.gid, nlink: info.nlink, backup };
119804
118517
  }
@@ -119862,13 +118575,13 @@ async function registerClaudeMcp(command, server2, environment) {
119862
118575
  `);
119863
118576
  const temporary = `${path}.skills-mcp-${randomUUID12()}.tmp`;
119864
118577
  writeFileSync25(temporary, next, { flag: "wx", mode: 384 });
119865
- if (!readFileSync43(temporary).equals(next))
118578
+ if (!readFileSync42(temporary).equals(next))
119866
118579
  throw new Error;
119867
118580
  const latest = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
119868
118581
  if (claudeUserConfigPath() !== path || (before2 === null ? latest !== null : latest === null || !latest.equals(before2)))
119869
118582
  throw new Error;
119870
118583
  renameSync16(temporary, path);
119871
- if (!readFileSync43(path).equals(next))
118584
+ if (!readFileSync42(path).equals(next))
119872
118585
  throw new Error;
119873
118586
  }
119874
118587
  return { agent: "claude", success: true, path, command: cliCommand };
@@ -119896,12 +118609,12 @@ function restoreClaudePreimage(path, preimage, observed, command) {
119896
118609
  }
119897
118610
  const rewrite = `${path}.skills-mcp-${randomUUID12()}.rewrite`;
119898
118611
  writeFileSync25(rewrite, observed, { flag: "wx", mode: 384 });
119899
- if (!readFileSync43(rewrite).equals(observed))
118612
+ if (!readFileSync42(rewrite).equals(observed))
119900
118613
  throw new Error;
119901
118614
  const temporary = `${path}.skills-mcp-${randomUUID12()}.tmp`;
119902
118615
  let renamed = false;
119903
118616
  try {
119904
- const fd = openSync31(temporary, constants30.O_WRONLY | constants30.O_CREAT | constants30.O_EXCL | constants30.O_NOFOLLOW, 384);
118617
+ const fd = openSync30(temporary, constants30.O_WRONLY | constants30.O_CREAT | constants30.O_EXCL | constants30.O_NOFOLLOW, 384);
119905
118618
  try {
119906
118619
  for (let offset = 0;offset < preimage.bytes.length; )
119907
118620
  offset += writeSync6(fd, preimage.bytes, offset);
@@ -119909,9 +118622,9 @@ function restoreClaudePreimage(path, preimage, observed, command) {
119909
118622
  fchmodSync3(fd, preimage.mode);
119910
118623
  fsyncSync10(fd);
119911
118624
  } finally {
119912
- closeSync31(fd);
118625
+ closeSync30(fd);
119913
118626
  }
119914
- if (!readFileSync43(temporary).equals(preimage.bytes))
118627
+ if (!readFileSync42(temporary).equals(preimage.bytes))
119915
118628
  throw new Error;
119916
118629
  const latest = readClaudeConfig(path);
119917
118630
  if (claudeUserConfigPath() !== path || latest === null || !latest.equals(observed))
@@ -119923,7 +118636,7 @@ function restoreClaudePreimage(path, preimage, observed, command) {
119923
118636
  unlinkSync12(temporary);
119924
118637
  }
119925
118638
  const info = lstatSync43(path);
119926
- if (!readFileSync43(path).equals(preimage.bytes) || (info.mode & 4095) !== preimage.mode || info.uid !== preimage.uid || info.gid !== preimage.gid)
118639
+ if (!readFileSync42(path).equals(preimage.bytes) || (info.mode & 4095) !== preimage.mode || info.uid !== preimage.uid || info.gid !== preimage.gid)
119927
118640
  throw new Error;
119928
118641
  return {
119929
118642
  agent: "claude",
@@ -119964,10 +118677,10 @@ function claudeConfigLeft(path, preimage, command, rewrite) {
119964
118677
  }
119965
118678
  function claudeUserConfigPath() {
119966
118679
  const override = process.env.CLAUDE_CONFIG_DIR;
119967
- if (override !== undefined && (!override || !isAbsolute41(override) || /[\x00-\x1f\x7f]/.test(override)))
118680
+ if (override !== undefined && (!override || !isAbsolute40(override) || /[\x00-\x1f\x7f]/.test(override)))
119968
118681
  throw new Error;
119969
- const modern = join71(override || homedir11(), process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL ? ".claude-custom-oauth.json" : ".claude.json");
119970
- const legacy = join71(override ?? join71(homedir11(), ".claude"), ".config.json");
118682
+ const modern = join70(override || homedir11(), process.env.CLAUDE_CODE_CUSTOM_OAUTH_URL ? ".claude-custom-oauth.json" : ".claude.json");
118683
+ const legacy = join70(override ?? join70(homedir11(), ".claude"), ".config.json");
119971
118684
  if (existsSync33(legacy)) {
119972
118685
  const info = lstatSync43(legacy);
119973
118686
  if (!info.isFile())
@@ -119983,7 +118696,7 @@ function readClaudeConfig(path) {
119983
118696
  return null;
119984
118697
  if (!info.isFile() || info.size > 16777216)
119985
118698
  throw new Error;
119986
- const bytes = readFileSync43(path);
118699
+ const bytes = readFileSync42(path);
119987
118700
  parseClaudeConfig(bytes);
119988
118701
  return bytes;
119989
118702
  }
@@ -120030,9 +118743,9 @@ function readClaudeFirstRunConfig(path, verifyPath) {
120030
118743
  const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}:${info.nlink}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`;
120031
118744
  if (!before2.isFile() || before2.nlink !== 1n || before2.uid !== BigInt(process.getuid()) || (before2.mode & 0o022n) !== 0n || before2.size > 16n * 1024n * 1024n)
120032
118745
  throw new Error;
120033
- const fd = openSync31(path, constants30.O_RDONLY | constants30.O_NOFOLLOW | constants30.O_NONBLOCK);
118746
+ const fd = openSync30(path, constants30.O_RDONLY | constants30.O_NOFOLLOW | constants30.O_NONBLOCK);
120034
118747
  try {
120035
- if (identity6(fstatSync31(fd, { bigint: true })) !== identity6(before2))
118748
+ if (identity6(fstatSync30(fd, { bigint: true })) !== identity6(before2))
120036
118749
  throw new Error;
120037
118750
  const bytes = Buffer.alloc(Number(before2.size) + 1);
120038
118751
  let length = 0;
@@ -120042,14 +118755,14 @@ function readClaudeFirstRunConfig(path, verifyPath) {
120042
118755
  break;
120043
118756
  length += count;
120044
118757
  }
120045
- if (BigInt(length) !== before2.size || identity6(fstatSync31(fd, { bigint: true })) !== identity6(before2) || identity6(lstatSync43(path, { bigint: true })) !== identity6(before2))
118758
+ if (BigInt(length) !== before2.size || identity6(fstatSync30(fd, { bigint: true })) !== identity6(before2) || identity6(lstatSync43(path, { bigint: true })) !== identity6(before2))
120046
118759
  throw new Error;
120047
118760
  const content = bytes.subarray(0, length);
120048
118761
  verifyPath();
120049
118762
  parseClaudeConfig(content);
120050
118763
  return content;
120051
118764
  } finally {
120052
- closeSync31(fd);
118765
+ closeSync30(fd);
120053
118766
  }
120054
118767
  }
120055
118768
  function parseClaudeConfig(bytes) {
@@ -120113,7 +118826,7 @@ function withClaudeConfigLock(path, action) {
120113
118826
  }
120114
118827
  }
120115
118828
  function registerCodexMcp(command, environment) {
120116
- const path = join71(homedir11(), ".codex", "config.toml");
118829
+ const path = join70(homedir11(), ".codex", "config.toml");
120117
118830
  const body = `command = ${JSON.stringify(command)}
120118
118831
  args = ["--stdio"]${Object.keys(environment).length ? `
120119
118832
  env = { ${Object.entries(environment).map(([key2, value]) => `${JSON.stringify(key2)} = ${JSON.stringify(value)}`).join(", ")} }` : ""}`;
@@ -120135,7 +118848,7 @@ ${body}`;
120135
118848
  }
120136
118849
  }
120137
118850
  function registerOpenCodeMcp(command, environment) {
120138
- const path = join71(homedir11(), ".config", "opencode", "opencode.json");
118851
+ const path = join70(homedir11(), ".config", "opencode", "opencode.json");
120139
118852
  const server2 = {
120140
118853
  type: "local",
120141
118854
  command: [command, "--stdio"],
@@ -120232,7 +118945,7 @@ function findCommandOnPath(command) {
120232
118945
  for (const dir of pathValue.split(":")) {
120233
118946
  if (!dir)
120234
118947
  continue;
120235
- const candidate2 = join71(dir, command);
118948
+ const candidate2 = join70(dir, command);
120236
118949
  if (existsSync33(candidate2))
120237
118950
  return candidate2;
120238
118951
  }
@@ -120457,21 +119170,21 @@ var init_reviewed_runtime_lock = __esm(() => {
120457
119170
  import { createHash as createHash45, randomUUID as randomUUID13 } from "crypto";
120458
119171
  import { Readable } from "stream";
120459
119172
  import { createGunzip as createGunzip2 } from "zlib";
120460
- import { spawnSync as spawnSync6 } from "child_process";
119173
+ import { spawnSync as spawnSync5 } from "child_process";
120461
119174
  import {
120462
119175
  chmodSync as chmodSync4,
120463
119176
  copyFileSync,
120464
119177
  existsSync as existsSync34,
120465
119178
  lstatSync as lstatSync44,
120466
119179
  mkdirSync as mkdirSync28,
120467
- readFileSync as readFileSync44,
119180
+ readFileSync as readFileSync43,
120468
119181
  readdirSync as readdirSync26,
120469
119182
  readlinkSync as readlinkSync8,
120470
119183
  realpathSync as realpathSync20,
120471
119184
  renameSync as renameSync17,
120472
119185
  writeFileSync as writeFileSync26
120473
119186
  } from "fs";
120474
- import { basename as basename23, delimiter as delimiter3, dirname as dirname45, isAbsolute as isAbsolute42, join as join72, relative as relative14, resolve as resolve38, sep as sep20 } from "path";
119187
+ import { basename as basename23, delimiter as delimiter3, dirname as dirname45, isAbsolute as isAbsolute41, join as join71, relative as relative14, resolve as resolve38, sep as sep20 } from "path";
120475
119188
  function oldLauncherState(item) {
120476
119189
  if (item.oldShape === "pinned")
120477
119190
  return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256, format: item.oldFormat, profile: item.oldProfile };
@@ -120497,7 +119210,7 @@ function assertLauncherRecordShapes(item, expectedProfile) {
120497
119210
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
120498
119211
  continue;
120499
119212
  }
120500
- if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute42(runtime) || typeof cwd2 !== "string" || !isAbsolute42(cwd2) || typeof sha7 !== "string" || !hex4.test(sha7)) {
119213
+ if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute41(runtime) || typeof cwd2 !== "string" || !isAbsolute41(cwd2) || typeof sha7 !== "string" || !hex4.test(sha7)) {
120501
119214
  throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
120502
119215
  }
120503
119216
  const target = side === "old" ? item.oldTarget : item.newTarget;
@@ -120524,10 +119237,10 @@ function verifyTargetPrerequisites(manifest, packageRoot, home, cwd2, pathValue)
120524
119237
  if (Object.keys(contract).length !== 2 || contract.version !== 1 || contract.entry !== "dist/runtime-prerequisites.js") {
120525
119238
  throw new Error("RUNTIME_PREREQUISITE_CONTRACT_INVALID");
120526
119239
  }
120527
- const entry = join72(packageRoot, contract.entry);
119240
+ const entry = join71(packageRoot, contract.entry);
120528
119241
  if (!entryExists(entry) || !lstatSync44(entry).isFile() || lstatSync44(entry).isSymbolicLink())
120529
119242
  throw new Error("RUNTIME_PREREQUISITE_ENTRY_MISSING");
120530
- const entrySha256 = hash6(readFileSync44(entry));
119243
+ const entrySha256 = hash6(readFileSync43(entry));
120531
119244
  const env3 = { HOME: home, PATH: pathValue, BUN_RUNTIME_TRANSPILER_CACHE_PATH: "0" };
120532
119245
  for (const key2 of ["HASNA_SKILLS_DIR", "HASNA_SKILLS_HOME", "SKILLS_HOME", "HASNA_DATA_HOME", "XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "XDG_STATE_HOME", "SUMI_HOME", "SUMI_CONFIG_DIR", "HERMES_HOME"]) {
120533
119246
  if (process.env[key2] !== undefined)
@@ -120536,7 +119249,7 @@ function verifyTargetPrerequisites(manifest, packageRoot, home, cwd2, pathValue)
120536
119249
  for (const key2 of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
120537
119250
  if (process.env[key2] !== undefined)
120538
119251
  env3[key2] = "";
120539
- const child2 = spawnSync6(pinnedLauncherRuntime(), [...PINNED_LAUNCHER_BUN_FLAGS2, entry, home, cwd2], {
119252
+ const child2 = spawnSync5(pinnedLauncherRuntime(), [...PINNED_LAUNCHER_BUN_FLAGS2, entry, home, cwd2], {
120540
119253
  cwd: dirname45(packageRoot),
120541
119254
  env: env3,
120542
119255
  encoding: "buffer",
@@ -120570,7 +119283,7 @@ function verifyTargetPrerequisites(manifest, packageRoot, home, cwd2, pathValue)
120570
119283
  }
120571
119284
  if (child2.status !== 0 || result2.code !== null)
120572
119285
  throw new Error("RUNTIME_PREREQUISITE_RESPONSE_INVALID");
120573
- if (hash6(readFileSync44(entry)) !== entrySha256)
119286
+ if (hash6(readFileSync43(entry)) !== entrySha256)
120574
119287
  throw new Error("RUNTIME_PREREQUISITE_ENTRY_CHANGED");
120575
119288
  return { status: "verified", schema: result2.schema, targetVersion: result2.targetVersion, entry: contract.entry, entrySha256, checked: result2.checked };
120576
119289
  }
@@ -120584,7 +119297,7 @@ function hash6(bytes) {
120584
119297
  }
120585
119298
  function isWithin(parent, child2) {
120586
119299
  const rel = relative14(parent, child2);
120587
- return rel === "" || !rel.startsWith(`..${sep20}`) && rel !== ".." && !isAbsolute42(rel);
119300
+ return rel === "" || !rel.startsWith(`..${sep20}`) && rel !== ".." && !isAbsolute41(rel);
120588
119301
  }
120589
119302
  function entryExists(path) {
120590
119303
  try {
@@ -120599,7 +119312,7 @@ function assertNoSymlinkAncestors(path) {
120599
119312
  const parts = absolute.split(sep20).filter(Boolean);
120600
119313
  let current = sep20;
120601
119314
  for (const part of parts) {
120602
- current = join72(current, part);
119315
+ current = join71(current, part);
120603
119316
  const stat3 = lstatSync44(current);
120604
119317
  if (stat3.isSymbolicLink())
120605
119318
  throw new Error("PATH_ANCESTOR_SYMLINK_UNSUPPORTED");
@@ -120608,23 +119321,23 @@ function assertNoSymlinkAncestors(path) {
120608
119321
  }
120609
119322
  }
120610
119323
  function acquireRuntimeLock(runtimeRoot) {
120611
- const lockPath = join72(runtimeRoot, ".copyfile-update-lock");
119324
+ const lockPath = join71(runtimeRoot, ".copyfile-update-lock");
120612
119325
  try {
120613
119326
  mkdirSync28(lockPath, { mode: 448 });
120614
119327
  } catch {
120615
119328
  throw new Error("RUNTIME_UPDATE_LOCKED");
120616
119329
  }
120617
119330
  try {
120618
- writeJsonPrivate(join72(lockPath, "lock.json"), { operationId: randomUUID13(), pid: process.pid, startedAt: new Date().toISOString() });
119331
+ writeJsonPrivate(join71(lockPath, "lock.json"), { operationId: randomUUID13(), pid: process.pid, startedAt: new Date().toISOString() });
120619
119332
  } catch {
120620
119333
  try {
120621
- renameSync17(lockPath, join72(runtimeRoot, `.copyfile-update-lock-incomplete-${randomUUID13()}`));
119334
+ renameSync17(lockPath, join71(runtimeRoot, `.copyfile-update-lock-incomplete-${randomUUID13()}`));
120622
119335
  } catch {}
120623
119336
  throw new Error("RUNTIME_LOCK_INITIALIZATION_FAILED");
120624
119337
  }
120625
119338
  return () => {
120626
- const released = join72(runtimeRoot, `.copyfile-update-lock-released-${randomUUID13()}`);
120627
- writeJsonPrivate(join72(lockPath, "released.json"), { completedAt: new Date().toISOString() });
119339
+ const released = join71(runtimeRoot, `.copyfile-update-lock-released-${randomUUID13()}`);
119340
+ writeJsonPrivate(join71(lockPath, "released.json"), { completedAt: new Date().toISOString() });
120628
119341
  renameSync17(lockPath, released);
120629
119342
  };
120630
119343
  }
@@ -120633,7 +119346,7 @@ function packageBins(pkg) {
120633
119346
  const entries = typeof raw === "string" ? [[PACKAGE_NAME.slice(PACKAGE_NAME.lastIndexOf("/") + 1), raw]] : raw && typeof raw === "object" && !Array.isArray(raw) ? Object.entries(raw) : [];
120634
119347
  const output2 = {};
120635
119348
  for (const [name, value] of entries) {
120636
- if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute42(value)) {
119349
+ if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute41(value)) {
120637
119350
  throw new Error("PACKAGE_BIN_INVALID");
120638
119351
  }
120639
119352
  const normalized2 = value.replaceAll("\\", "/");
@@ -120648,7 +119361,7 @@ function packageBins(pkg) {
120648
119361
  function readPackage(path) {
120649
119362
  let data;
120650
119363
  try {
120651
- data = object11(JSON.parse(readFileSync44(path, "utf8")), "PACKAGE_JSON_INVALID");
119364
+ data = object11(JSON.parse(readFileSync43(path, "utf8")), "PACKAGE_JSON_INVALID");
120652
119365
  } catch {
120653
119366
  throw new Error("PACKAGE_JSON_INVALID");
120654
119367
  }
@@ -120659,7 +119372,7 @@ function readPackage(path) {
120659
119372
  }
120660
119373
  function resolveRuntimeLayout(homeInput, pathInput) {
120661
119374
  const home = realpathSync20(homeInput);
120662
- const runtimeRoot = join72(home, ".hasna", "skills", "runtime");
119375
+ const runtimeRoot = join71(home, ".hasna", "skills", "runtime");
120663
119376
  assertNoSymlinkAncestors(runtimeRoot);
120664
119377
  const runtimeRootStat = lstatSync44(runtimeRoot);
120665
119378
  if (!runtimeRootStat.isDirectory() || runtimeRootStat.isSymbolicLink() || (runtimeRootStat.mode & 63) !== 0) {
@@ -120690,8 +119403,8 @@ function resolveRuntimeLayout(homeInput, pathInput) {
120690
119403
  if (relativePackage.length !== 4 || relativePackage[1] !== "node_modules" || relativePackage[2] !== "@hasna" || relativePackage[3] !== "skills") {
120691
119404
  throw new Error("ACTIVE_RUNTIME_LAYOUT_UNSUPPORTED");
120692
119405
  }
120693
- const current = readPackage(join72(currentPackageRoot, "package.json"));
120694
- if (!activeBinary.startsWith(`${currentPackageRoot}${sep20}`) || activeBinary !== join72(currentPackageRoot, current.bins.skills)) {
119406
+ const current = readPackage(join71(currentPackageRoot, "package.json"));
119407
+ if (!activeBinary.startsWith(`${currentPackageRoot}${sep20}`) || activeBinary !== join71(currentPackageRoot, current.bins.skills)) {
120695
119408
  throw new Error("ACTIVE_RUNTIME_ENTRYPOINT_MISMATCH");
120696
119409
  }
120697
119410
  const launchers = [];
@@ -120702,7 +119415,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
120702
119415
  continue;
120703
119416
  seenDirectories.add(dir);
120704
119417
  for (const [name, target] of Object.entries(current.bins)) {
120705
- const path = join72(dir, name);
119418
+ const path = join71(dir, name);
120706
119419
  if (!existsSync34(path))
120707
119420
  continue;
120708
119421
  assertNoSymlinkAncestors(dir);
@@ -120717,9 +119430,9 @@ function resolveRuntimeLayout(homeInput, pathInput) {
120717
119430
  if (launcher.kind === "foreign")
120718
119431
  continue;
120719
119432
  const actual = launcher.target;
120720
- if (actual !== join72(currentPackageRoot, target))
119433
+ if (actual !== join71(currentPackageRoot, target))
120721
119434
  continue;
120722
- const newTarget = join72(runtimeRoot, "__target__", "node_modules", "@hasna", "skills", target);
119435
+ const newTarget = join71(runtimeRoot, "__target__", "node_modules", "@hasna", "skills", target);
120723
119436
  const backupPath = `${path}.skills-prev-${randomUUID13()}`;
120724
119437
  if (launcher.kind === "symlink") {
120725
119438
  if (resolve38(dirname45(path), launcher.linkTarget) !== actual)
@@ -120878,14 +119591,14 @@ async function downloadPackage(version2, stagingRoot, registryOrigin, fetcher) {
120878
119591
  if (unpacked.name !== PACKAGE_NAME || unpacked.version !== version2)
120879
119592
  throw new Error("TARBALL_PACKAGE_IDENTITY_MISMATCH");
120880
119593
  const bins = packageBins(unpacked);
120881
- const archiveRoot = join72(stagingRoot, "verified-archive");
119594
+ const archiveRoot = join71(stagingRoot, "verified-archive");
120882
119595
  mkdirSync28(archiveRoot, { mode: 448 });
120883
119596
  await archive.extract(archiveRoot);
120884
- const extractedPackage = join72(archiveRoot, "package");
119597
+ const extractedPackage = join71(archiveRoot, "package");
120885
119598
  const extracted = readTree(extractedPackage, false);
120886
- const tarballPath = join72(stagingRoot, "verified-package.tgz");
119599
+ const tarballPath = join71(stagingRoot, "verified-package.tgz");
120887
119600
  writeFileSync26(tarballPath, bytes, { flag: "wx", mode: 384 });
120888
- if (!readFileSync44(tarballPath).equals(Buffer.from(bytes)))
119601
+ if (!readFileSync43(tarballPath).equals(Buffer.from(bytes)))
120889
119602
  throw new Error("TARBALL_READBACK_MISMATCH");
120890
119603
  return {
120891
119604
  tarballPath,
@@ -120931,7 +119644,7 @@ function readTree(root2, includeModes, excludeNpmDependencies = false) {
120931
119644
  const entries = [];
120932
119645
  const walk2 = (dir, prefix = "") => {
120933
119646
  for (const item of readdirSync26(dir).sort()) {
120934
- const path = join72(dir, item);
119647
+ const path = join71(dir, item);
120935
119648
  const rel = prefix ? `${prefix}/${item}` : item;
120936
119649
  const stat3 = lstatSync44(path);
120937
119650
  if (excludeNpmDependencies && !prefix && item === "node_modules") {
@@ -120959,7 +119672,7 @@ function readTree(root2, includeModes, excludeNpmDependencies = false) {
120959
119672
  } else if (stat3.isFile()) {
120960
119673
  if (stat3.nlink !== 1)
120961
119674
  throw new Error("TREE_HARDLINK_UNSUPPORTED");
120962
- const bytes = readFileSync44(path);
119675
+ const bytes = readFileSync43(path);
120963
119676
  entries.push({ path: rel, kind: "file", sha256: hash6(bytes), ...includeModes ? { mode: stat3.mode & 511 } : {} });
120964
119677
  } else
120965
119678
  throw new Error("TREE_ENTRY_TYPE_UNSUPPORTED");
@@ -120975,7 +119688,7 @@ function normalizeModes(root2) {
120975
119688
  chmodSync4(root2, rootStat.mode & 493);
120976
119689
  const walk2 = (dir) => {
120977
119690
  for (const item of readdirSync26(dir)) {
120978
- const path = join72(dir, item);
119691
+ const path = join71(dir, item);
120979
119692
  const stat3 = lstatSync44(path);
120980
119693
  if (stat3.isSymbolicLink())
120981
119694
  continue;
@@ -120995,23 +119708,23 @@ function writeJsonPrivate(path, value) {
120995
119708
  `);
120996
119709
  writeFileSync26(path, bytes, { flag: "wx", mode: 384 });
120997
119710
  chmodSync4(path, 384);
120998
- if (!readFileSync44(path).equals(bytes))
119711
+ if (!readFileSync43(path).equals(bytes))
120999
119712
  throw new Error("PRIVATE_JSON_READBACK_MISMATCH");
121000
119713
  }
121001
119714
  function writePreimageManifest(stage, configs, launchers) {
121002
- const path = join72(stage, "preimage", "manifest.json");
119715
+ const path = join71(stage, "preimage", "manifest.json");
121003
119716
  const value = { schema: "skills.copyfile-preimage.v1", configs, launchers };
121004
119717
  const bytes = Buffer.from(`${JSON.stringify(value, null, 2)}
121005
119718
  `);
121006
119719
  writeFileSync26(path, bytes, { flag: "wx", mode: 256 });
121007
119720
  chmodSync4(path, 256);
121008
- if (!readFileSync44(path).equals(bytes))
119721
+ if (!readFileSync43(path).equals(bytes))
121009
119722
  throw new Error("PREIMAGE_MANIFEST_READBACK_MISMATCH");
121010
119723
  return hash6(bytes);
121011
119724
  }
121012
119725
  function verifyPreimageManifest(runtimePath, receipt, home) {
121013
- const path = join72(runtimePath, "preimage", "manifest.json");
121014
- const bytes = readFileSync44(path);
119726
+ const path = join71(runtimePath, "preimage", "manifest.json");
119727
+ const bytes = readFileSync43(path);
121015
119728
  if (hash6(bytes) !== receipt.preimageSha256)
121016
119729
  throw new Error("PREIMAGE_MANIFEST_DRIFT");
121017
119730
  const manifest = object11(JSON.parse(bytes.toString("utf8")), "PREIMAGE_MANIFEST_INVALID");
@@ -121022,33 +119735,33 @@ function verifyPreimageManifest(runtimePath, receipt, home) {
121022
119735
  throw new Error("PREIMAGE_CONFIG_SET_INVALID");
121023
119736
  for (const [index, relativePath] of CONFIG_PREIMAGE_PATHS.entries()) {
121024
119737
  const config2 = receipt.configs[index];
121025
- if (config2.relativePath !== relativePath || config2.sourcePath !== join72(home, relativePath))
119738
+ if (config2.relativePath !== relativePath || config2.sourcePath !== join71(home, relativePath))
121026
119739
  throw new Error("PREIMAGE_CONFIG_BINDING_INVALID");
121027
119740
  if (config2.present) {
121028
- const backup = join72(runtimePath, "preimage", "configs", relativePath);
119741
+ const backup = join71(runtimePath, "preimage", "configs", relativePath);
121029
119742
  const stat3 = lstatSync44(backup);
121030
- const saved = readFileSync44(backup);
119743
+ const saved = readFileSync43(backup);
121031
119744
  if (!stat3.isFile() || stat3.isSymbolicLink() || hash6(saved) !== config2.sha256 || saved.byteLength !== config2.byteSize)
121032
119745
  throw new Error("PREIMAGE_CONFIG_DRIFT");
121033
119746
  }
121034
119747
  }
121035
119748
  }
121036
119749
  function captureConfigPreimages(home, stage) {
121037
- const root2 = join72(stage, "preimage", "configs");
119750
+ const root2 = join71(stage, "preimage", "configs");
121038
119751
  mkdirSync28(root2, { recursive: true, mode: 448 });
121039
119752
  return CONFIG_PREIMAGE_PATHS.map((relativePath) => {
121040
- const sourcePath = join72(home, relativePath);
119753
+ const sourcePath = join71(home, relativePath);
121041
119754
  if (!entryExists(sourcePath))
121042
119755
  return { sourcePath, relativePath, present: false };
121043
119756
  const stat3 = lstatSync44(sourcePath);
121044
119757
  if (!stat3.isFile() || stat3.isSymbolicLink())
121045
119758
  throw new Error("CONFIG_PREIMAGE_NOT_REGULAR_FILE");
121046
- const bytes = readFileSync44(sourcePath);
121047
- const backupPath = join72(root2, relativePath);
119759
+ const bytes = readFileSync43(sourcePath);
119760
+ const backupPath = join71(root2, relativePath);
121048
119761
  mkdirSync28(dirname45(backupPath), { recursive: true, mode: 448 });
121049
119762
  writeFileSync26(backupPath, bytes, { flag: "wx", mode: 384 });
121050
119763
  chmodSync4(backupPath, 384);
121051
- const readback = readFileSync44(backupPath);
119764
+ const readback = readFileSync43(backupPath);
121052
119765
  if (!readback.equals(bytes))
121053
119766
  throw new Error("CONFIG_PREIMAGE_READBACK_MISMATCH");
121054
119767
  return { sourcePath, relativePath, present: true, sha256: hash6(bytes), byteSize: bytes.byteLength };
@@ -121061,7 +119774,7 @@ function assertConfigUnchanged(configs) {
121061
119774
  throw new Error("CONFIG_DRIFT_DURING_UPDATE");
121062
119775
  if (present2) {
121063
119776
  const stat3 = lstatSync44(config2.sourcePath);
121064
- if (!stat3.isFile() || stat3.isSymbolicLink() || hash6(readFileSync44(config2.sourcePath)) !== config2.sha256) {
119777
+ if (!stat3.isFile() || stat3.isSymbolicLink() || hash6(readFileSync43(config2.sourcePath)) !== config2.sha256) {
121065
119778
  throw new Error("CONFIG_DRIFT_DURING_UPDATE");
121066
119779
  }
121067
119780
  }
@@ -121102,7 +119815,7 @@ async function npmReleaseAgeCapability(cwd2, env3) {
121102
119815
  }
121103
119816
  }
121104
119817
  async function runNpm(args2, cwd2, home, staging, policy) {
121105
- const userNpmrc = join72(staging, "npm-user.npmrc"), globalNpmrc = join72(staging, "npm-global.npmrc");
119818
+ const userNpmrc = join71(staging, "npm-user.npmrc"), globalNpmrc = join71(staging, "npm-global.npmrc");
121106
119819
  const baseConfig = `registry=${REGISTRY_ORIGIN}/
121107
119820
  ignore-scripts=true
121108
119821
  `;
@@ -121117,14 +119830,14 @@ ignore-scripts=true
121117
119830
  CI: "1",
121118
119831
  NPM_CONFIG_USERCONFIG: userNpmrc,
121119
119832
  NPM_CONFIG_GLOBALCONFIG: globalNpmrc,
121120
- NPM_CONFIG_CACHE: join72(staging, "npm-cache"),
119833
+ NPM_CONFIG_CACHE: join71(staging, "npm-cache"),
121121
119834
  NPM_CONFIG_REGISTRY: `${REGISTRY_ORIGIN}/`,
121122
119835
  NPM_CONFIG_IGNORE_SCRIPTS: "true"
121123
119836
  };
121124
- const capabilityNpmrc = join72(staging, "npm-capability.npmrc");
119837
+ const capabilityNpmrc = join71(staging, "npm-capability.npmrc");
121125
119838
  if (policy && !existsSync34(capabilityNpmrc))
121126
119839
  writeFileSync26(capabilityNpmrc, baseConfig, { mode: 384, flag: "wx" });
121127
- if (policy && readFileSync44(capabilityNpmrc, "utf8") !== baseConfig)
119840
+ if (policy && readFileSync43(capabilityNpmrc, "utf8") !== baseConfig)
121128
119841
  throw new Error("NPM_ISOLATED_CONFIG_DRIFT");
121129
119842
  const npmVersion = policy ? await npmReleaseAgeCapability(cwd2, { ...env3, NPM_CONFIG_USERCONFIG: capabilityNpmrc }) : undefined;
121130
119843
  const config2 = baseConfig + (policy ? `min-release-age=${policy.minReleaseAge}
@@ -121132,7 +119845,7 @@ ${policy.minReleaseAgeExclude.map((pattern) => `min-release-age-exclude[]=${patt
121132
119845
  `).join("")}` : "");
121133
119846
  if (!existsSync34(userNpmrc))
121134
119847
  writeFileSync26(userNpmrc, config2, { mode: 384, flag: "wx" });
121135
- if (readFileSync44(userNpmrc, "utf8") !== config2 || readFileSync44(globalNpmrc, "utf8") !== baseConfig)
119848
+ if (readFileSync43(userNpmrc, "utf8") !== config2 || readFileSync43(globalNpmrc, "utf8") !== baseConfig)
121136
119849
  throw new Error("NPM_ISOLATED_CONFIG_DRIFT");
121137
119850
  const proc = Bun.spawn(["npm", ...args2, "--registry", `${REGISTRY_ORIGIN}/`, "--ignore-scripts", "--no-audit", "--no-fund"], {
121138
119851
  cwd: cwd2,
@@ -121146,8 +119859,58 @@ ${policy.minReleaseAgeExclude.map((pattern) => `min-release-age-exclude[]=${patt
121146
119859
  throw new Error("DEPENDENCY_GRAPH_INSTALL_FAILED");
121147
119860
  return npmVersion;
121148
119861
  }
119862
+ async function carryInstalledSecrets(layout, stagePackage, home, stagePath, policy) {
119863
+ const runtimePath = dirname45(dirname45(dirname45(layout.currentPackageRoot)));
119864
+ const source = [join71(layout.currentPackageRoot, "node_modules", PRIVATE_OPTIONAL_PACKAGE), join71(runtimePath, "node_modules", PRIVATE_OPTIONAL_PACKAGE)].find((path) => entryExists(join71(path, "package.json")));
119865
+ if (!source)
119866
+ return null;
119867
+ assertNoSymlinkAncestors(source);
119868
+ const manifest = object11(JSON.parse(readFileSync43(join71(source, "package.json"), "utf8")), "CARRIED_SECRETS_MANIFEST_INVALID");
119869
+ if (manifest.name !== PRIVATE_OPTIONAL_PACKAGE || typeof manifest.version !== "string" || !STABLE_SEMVER_PATTERN.test(manifest.version))
119870
+ throw new Error("CARRIED_SECRETS_MANIFEST_INVALID");
119871
+ let verification2 = "unrecorded";
119872
+ if (entryExists(join71(runtimePath, "rollout-receipt.json"))) {
119873
+ const prior = object11(JSON.parse(readFileSync43(join71(runtimePath, "rollout-receipt.json"), "utf8")), "CARRIED_SECRETS_RUNTIME_DRIFT");
119874
+ if (readTree(join71(runtimePath, "node_modules"), true).digest !== prior.runtimeTreeSha256)
119875
+ throw new Error("CARRIED_SECRETS_RUNTIME_DRIFT");
119876
+ verification2 = "runtime-receipt";
119877
+ }
119878
+ if (entryExists(join71(runtimePath, "install-lock.json"))) {
119879
+ const lock = object11(JSON.parse(readFileSync43(join71(runtimePath, "install-lock.json"), "utf8")), "CARRIED_SECRETS_LOCK_MISMATCH");
119880
+ const locked2 = lock.packages?.[relative14(runtimePath, source).split(sep20).join("/")];
119881
+ if (locked2?.version !== manifest.version)
119882
+ throw new Error("CARRIED_SECRETS_LOCK_MISMATCH");
119883
+ }
119884
+ const carried = join71(stagePackage, "carried");
119885
+ mkdirSync28(carried, { mode: 448 });
119886
+ await runNpm(["pack", source, "--pack-destination", carried], stagePackage, home, stagePath, policy);
119887
+ const file2 = `hasna-secrets-${manifest.version}.tgz`;
119888
+ if (JSON.stringify(readdirSync26(carried)) !== JSON.stringify([file2]))
119889
+ throw new Error("CARRIED_SECRETS_PACK_FAILED");
119890
+ return { spec: `file:./carried/${file2}`, source, record: {
119891
+ version: manifest.version,
119892
+ tarballSha256: hash6(readFileSync43(join71(carried, file2))),
119893
+ packageTreeSha256: readTree(source, false, true).digest,
119894
+ verification: verification2
119895
+ } };
119896
+ }
119897
+ function unresolvedOptionalDependencies(lockBytes) {
119898
+ const lock = object11(JSON.parse(new TextDecoder().decode(lockBytes)), "INSTALL_LOCK_INVALID");
119899
+ const packages = object11(lock.packages, "INSTALL_LOCK_INVALID");
119900
+ const resolves = (from, name) => {
119901
+ for (let base3 = from;; ) {
119902
+ if (packages[base3 ? `${base3}/node_modules/${name}` : `node_modules/${name}`])
119903
+ return true;
119904
+ if (!base3)
119905
+ return false;
119906
+ const at2 = base3.lastIndexOf("node_modules/");
119907
+ base3 = at2 > 0 ? base3.slice(0, at2 - 1) : "";
119908
+ }
119909
+ };
119910
+ return Object.entries(packages).filter(([, entry]) => !entry.link).flatMap(([from, entry]) => Object.keys(entry.optionalDependencies ?? {}).filter((name) => !resolves(from, name)).map((name) => `${from} ${name}`)).sort();
119911
+ }
121149
119912
  function comparePackageTrees(expectedRoot, installedRoot) {
121150
- if (entryExists(join72(expectedRoot, "node_modules")))
119913
+ if (entryExists(join71(expectedRoot, "node_modules")))
121151
119914
  throw new Error("TARBALL_BUNDLED_DEPENDENCIES_UNSUPPORTED");
121152
119915
  const expected = readTree(expectedRoot, false);
121153
119916
  const installed = readTree(installedRoot, false, true);
@@ -121183,12 +119946,12 @@ function atomicJson(path, value) {
121183
119946
  writeFileSync26(temp, bytes, { flag: "wx", mode: 384 });
121184
119947
  chmodSync4(temp, 384);
121185
119948
  renameSync17(temp, path);
121186
- if (!readFileSync44(path).equals(bytes))
119949
+ if (!readFileSync43(path).equals(bytes))
121187
119950
  throw new Error("RECEIPT_READBACK_MISMATCH");
121188
119951
  }
121189
119952
  function persistReceipt(path, value) {
121190
119953
  if (entryExists(path)) {
121191
- const priorBytes = readFileSync44(path);
119954
+ const priorBytes = readFileSync43(path);
121192
119955
  const prior = object11(JSON.parse(priorBytes.toString("utf8")), "RECEIPT_INVALID");
121193
119956
  if (prior.id !== value.id || prior.schema !== "skills.copyfile-runtime-receipt.v1" || typeof prior.state !== "string" || !/^[a-z-]{1,32}$/.test(prior.state))
121194
119957
  throw new Error("RECEIPT_ID_DRIFT");
@@ -121196,23 +119959,23 @@ function persistReceipt(path, value) {
121196
119959
  `);
121197
119960
  if (priorBytes.equals(nextBytes))
121198
119961
  return;
121199
- const historyRoot = join72(dirname45(path), "receipt-history");
119962
+ const historyRoot = join71(dirname45(path), "receipt-history");
121200
119963
  if (!entryExists(historyRoot))
121201
119964
  mkdirSync28(historyRoot, { mode: 448 });
121202
119965
  const historyStat = lstatSync44(historyRoot);
121203
119966
  if (!historyStat.isDirectory() || historyStat.isSymbolicLink() || (historyStat.mode & 63) !== 0)
121204
119967
  throw new Error("RECEIPT_HISTORY_NOT_PRIVATE");
121205
- const historyPath = join72(historyRoot, `${value.id}-${String(prior.state)}-${randomUUID13()}.json`);
119968
+ const historyPath = join71(historyRoot, `${value.id}-${String(prior.state)}-${randomUUID13()}.json`);
121206
119969
  writeFileSync26(historyPath, priorBytes, { flag: "wx", mode: 256 });
121207
119970
  chmodSync4(historyPath, 256);
121208
- if (!readFileSync44(historyPath).equals(priorBytes))
119971
+ if (!readFileSync43(historyPath).equals(priorBytes))
121209
119972
  throw new Error("RECEIPT_HISTORY_READBACK_MISMATCH");
121210
119973
  }
121211
119974
  atomicJson(path, value);
121212
119975
  }
121213
119976
  function persistAliasReceipt(path, value) {
121214
119977
  if (entryExists(path)) {
121215
- const priorBytes = readFileSync44(path);
119978
+ const priorBytes = readFileSync43(path);
121216
119979
  const prior = object11(JSON.parse(priorBytes.toString("utf8")), "ALIAS_RECEIPT_INVALID");
121217
119980
  if (prior.schema !== value.schema || prior.id !== value.id || typeof prior.state !== "string")
121218
119981
  throw new Error("ALIAS_RECEIPT_DRIFT");
@@ -121220,16 +119983,16 @@ function persistAliasReceipt(path, value) {
121220
119983
  `);
121221
119984
  if (priorBytes.equals(nextBytes))
121222
119985
  return;
121223
- const history = join72(dirname45(path), "history");
119986
+ const history = join71(dirname45(path), "history");
121224
119987
  if (!entryExists(history))
121225
119988
  mkdirSync28(history, { mode: 448 });
121226
119989
  const historyStat = lstatSync44(history);
121227
119990
  if (!historyStat.isDirectory() || historyStat.isSymbolicLink() || (historyStat.mode & 63) !== 0)
121228
119991
  throw new Error("ALIAS_RECEIPT_HISTORY_UNSAFE");
121229
- const saved = join72(history, `${value.id}-${String(prior.state)}-${randomUUID13()}.json`);
119992
+ const saved = join71(history, `${value.id}-${String(prior.state)}-${randomUUID13()}.json`);
121230
119993
  writeFileSync26(saved, priorBytes, { flag: "wx", mode: 256 });
121231
119994
  chmodSync4(saved, 256);
121232
- if (!readFileSync44(saved).equals(priorBytes))
119995
+ if (!readFileSync43(saved).equals(priorBytes))
121233
119996
  throw new Error("ALIAS_RECEIPT_HISTORY_READBACK_MISMATCH");
121234
119997
  }
121235
119998
  atomicJson(path, value);
@@ -121249,21 +120012,21 @@ function assertOwnedSafePath(path, home, requireWritable = false) {
121249
120012
  function activeAliasRuntime(home, pathValue) {
121250
120013
  const layout = resolveRuntimeLayout(home, pathValue);
121251
120014
  const runtimePath = dirname45(dirname45(dirname45(layout.currentPackageRoot)));
121252
- const receiptPath = join72(runtimePath, "rollout-receipt.json");
121253
- const rollout = object11(JSON.parse(readFileSync44(receiptPath, "utf8")), "ROLLOUT_RECEIPT_INVALID");
121254
- if (rollout.schema !== "skills.copyfile-runtime-receipt.v1" || rollout.state !== "switched" || rollout.targetPackageRoot !== layout.currentPackageRoot || rollout.targetVersion !== layout.currentVersion || rollout.runtimeRoot !== layout.runtimeRoot || rollout.package !== PACKAGE_NAME || hash6(readFileSync44(join72(runtimePath, "verified-package.tgz"))) !== rollout.tarballSha256 || readTree(join72(runtimePath, "node_modules"), true).digest !== rollout.runtimeTreeSha256) {
120015
+ const receiptPath = join71(runtimePath, "rollout-receipt.json");
120016
+ const rollout = object11(JSON.parse(readFileSync43(receiptPath, "utf8")), "ROLLOUT_RECEIPT_INVALID");
120017
+ if (rollout.schema !== "skills.copyfile-runtime-receipt.v1" || rollout.state !== "switched" || rollout.targetPackageRoot !== layout.currentPackageRoot || rollout.targetVersion !== layout.currentVersion || rollout.runtimeRoot !== layout.runtimeRoot || rollout.package !== PACKAGE_NAME || hash6(readFileSync43(join71(runtimePath, "verified-package.tgz"))) !== rollout.tarballSha256 || readTree(join71(runtimePath, "node_modules"), true).digest !== rollout.runtimeTreeSha256) {
121255
120018
  throw new Error("ACTIVE_RUNTIME_RECEIPT_DRIFT");
121256
120019
  }
121257
120020
  verifyPreimageManifest(runtimePath, rollout, home);
121258
120021
  return { layout, rollout };
121259
120022
  }
121260
120023
  function aliasDirs(home) {
121261
- return [join72(home, ".local", "bin"), join72(home, ".bun", "bin"), "/opt/homebrew/bin", "/usr/local/bin"];
120024
+ return [join71(home, ".local", "bin"), join71(home, ".bun", "bin"), "/opt/homebrew/bin", "/usr/local/bin"];
121262
120025
  }
121263
120026
  function aliasPackageLink(home, aliasPath) {
121264
120027
  const dir = dirname45(aliasPath);
121265
- if (dir === join72(home, ".local", "bin"))
121266
- return join72(home, ".local", "lib", "node_modules", "@hasna", "skills");
120028
+ if (dir === join71(home, ".local", "bin"))
120029
+ return join71(home, ".local", "lib", "node_modules", "@hasna", "skills");
121267
120030
  if (dir === "/opt/homebrew/bin")
121268
120031
  return "/opt/homebrew/lib/node_modules/@hasna/skills";
121269
120032
  if (dir === "/usr/local/bin")
@@ -121279,7 +120042,7 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
121279
120042
  }
121280
120043
  const packageLinkPath = aliasPackageLink(home, aliasPath);
121281
120044
  const physicalPackage = dirname45(dirname45(oldTarget));
121282
- if (!packageLinkPath || immediate !== join72(packageLinkPath, bin) || !isWithin(join72(home, ".hasna", "skills", "runtime"), physicalPackage)) {
120045
+ if (!packageLinkPath || immediate !== join71(packageLinkPath, bin) || !isWithin(join71(home, ".hasna", "skills", "runtime"), physicalPackage)) {
121283
120046
  throw new Error("ALIAS_LINK_CHAIN_UNSUPPORTED");
121284
120047
  }
121285
120048
  assertOwnedSafePath(dirname45(packageLinkPath), home);
@@ -121302,19 +120065,19 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
121302
120065
  }
121303
120066
  function validateAliasSource(home, name, actual) {
121304
120067
  const packageRoot = dirname45(dirname45(actual));
121305
- const roots = [join72(home, ".hasna", "skills", "runtime"), join72(home, ".bun", "install"), join72(home, ".local", "lib", "node_modules")];
120068
+ const roots = [join71(home, ".hasna", "skills", "runtime"), join71(home, ".bun", "install"), join71(home, ".local", "lib", "node_modules")];
121306
120069
  if (basename23(packageRoot) !== "skills" || basename23(dirname45(packageRoot)) !== "@hasna" || !roots.some((root2) => isWithin(root2, packageRoot))) {
121307
120070
  throw new Error("ALIAS_SOURCE_ROOT_UNSUPPORTED");
121308
120071
  }
121309
120072
  assertOwnedSafePath(packageRoot, home);
121310
- const manifestPath = join72(packageRoot, "package.json");
120073
+ const manifestPath = join71(packageRoot, "package.json");
121311
120074
  const manifestStat = lstatSync44(manifestPath), binaryStat = lstatSync44(actual);
121312
120075
  if (!manifestStat.isFile() || manifestStat.isSymbolicLink() || !binaryStat.isFile() || binaryStat.isSymbolicLink() || ![0, process.getuid?.() ?? -1].includes(manifestStat.uid) || ![0, process.getuid?.() ?? -1].includes(binaryStat.uid) || manifestStat.mode & 18)
121313
120076
  throw new Error("ALIAS_SOURCE_UNSAFE");
121314
120077
  const pkg = readPackage(manifestPath);
121315
- if (!pkg.bins[name] || actual !== join72(packageRoot, pkg.bins[name]))
120078
+ if (!pkg.bins[name] || actual !== join71(packageRoot, pkg.bins[name]))
121316
120079
  throw new Error("ALIAS_SOURCE_BIN_MISMATCH");
121317
- return { version: pkg.version, packageRoot, binarySha256: hash6(readFileSync44(actual)) };
120080
+ return { version: pkg.version, packageRoot, binarySha256: hash6(readFileSync43(actual)) };
121318
120081
  }
121319
120082
  function adoptCopyfileAliases(options = {}) {
121320
120083
  const home = realpathSync20(resolve38(options.homeDir ?? process.env.HOME ?? ""));
@@ -121322,12 +120085,12 @@ function adoptCopyfileAliases(options = {}) {
121322
120085
  const { layout, rollout } = activeAliasRuntime(home, pathValue);
121323
120086
  const currentRuntime = dirname45(dirname45(dirname45(layout.currentPackageRoot)));
121324
120087
  const launcherRuntime = pinnedLauncherRuntime();
121325
- pinnedLauncherState(launcherRuntime, currentRuntime, join72(layout.currentPackageRoot, layout.bin.skills ?? "bin/index.js"));
120088
+ pinnedLauncherState(launcherRuntime, currentRuntime, join71(layout.currentPackageRoot, layout.bin.skills ?? "bin/index.js"));
121326
120089
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
121327
120090
  const id2 = randomUUID13();
121328
120091
  const aliases = [];
121329
- const receiptDir = join72(currentRuntime, "alias-adoptions");
121330
- const receiptPath = join72(receiptDir, `${id2}.json`);
120092
+ const receiptDir = join71(currentRuntime, "alias-adoptions");
120093
+ const receiptPath = join71(receiptDir, `${id2}.json`);
121331
120094
  let receipt;
121332
120095
  try {
121333
120096
  const locked2 = activeAliasRuntime(home, pathValue);
@@ -121337,7 +120100,7 @@ function adoptCopyfileAliases(options = {}) {
121337
120100
  if (!entryExists(dir))
121338
120101
  continue;
121339
120102
  for (const [name, target] of Object.entries(layout.bin)) {
121340
- const path = join72(dir, name);
120103
+ const path = join71(dir, name);
121341
120104
  if (!entryExists(path))
121342
120105
  continue;
121343
120106
  assertOwnedSafePath(dir, home, true);
@@ -121354,7 +120117,7 @@ function adoptCopyfileAliases(options = {}) {
121354
120117
  throw new Error("ALIAS_LINK_NOT_OWNED");
121355
120118
  const actual = launcher.target;
121356
120119
  const oldLinkTarget = launcher.kind === "symlink" ? launcher.linkTarget : actual;
121357
- const newTarget = join72(layout.currentPackageRoot, target);
120120
+ const newTarget = join71(layout.currentPackageRoot, target);
121358
120121
  if (actual === newTarget && launcher.kind === "pinned" && launcher.format === "v3" && launcher.profile === launcherProfileForBin(name, target))
121359
120122
  continue;
121360
120123
  const chain = inspectAliasPackageChain(home, path, oldLinkTarget, actual, target);
@@ -121476,19 +120239,19 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
121476
120239
  const pathValue = options.pathValue ?? process.env.PATH ?? "";
121477
120240
  const { layout, rollout } = activeAliasRuntime(home, pathValue);
121478
120241
  const runtimePath = dirname45(dirname45(dirname45(layout.currentPackageRoot)));
121479
- const receiptPath = join72(runtimePath, "alias-adoptions", `${receiptId}.json`);
120242
+ const receiptPath = join71(runtimePath, "alias-adoptions", `${receiptId}.json`);
121480
120243
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
121481
120244
  try {
121482
120245
  const locked2 = activeAliasRuntime(home, pathValue);
121483
120246
  if (locked2.layout.currentPackageRoot !== layout.currentPackageRoot || locked2.rollout.id !== rollout.id)
121484
120247
  throw new Error("ACTIVE_RUNTIME_CHANGED_BEFORE_ALIAS_ROLLBACK");
121485
- const receipt = object11(JSON.parse(readFileSync44(receiptPath, "utf8")), "ALIAS_RECEIPT_INVALID");
120248
+ const receipt = object11(JSON.parse(readFileSync43(receiptPath, "utf8")), "ALIAS_RECEIPT_INVALID");
121486
120249
  if (receipt.schema !== "skills.copyfile-alias-adoption.v1" || receipt.id !== receiptId || !["switched", "switching", "rollback-required"].includes(receipt.state) || receipt.targetPackageRoot !== layout.currentPackageRoot || receipt.targetVersion !== layout.currentVersion || receipt.rolloutReceiptId !== rollout.id || !Array.isArray(receipt.aliases))
121487
120250
  throw new Error("ALIAS_RECEIPT_BINDING_INVALID");
121488
120251
  const seen = new Set;
121489
120252
  for (const item of receipt.aliases) {
121490
120253
  const name = basename23(item.path), target = layout.bin[name];
121491
- if (!target || seen.has(item.path) || !aliasDirs(home).includes(dirname45(item.path)) || item.newTarget !== join72(layout.currentPackageRoot, target) || item.backupPath !== `${item.path}.skills-alias-prev-${receiptId}` || item.chain !== undefined && (!item.chain || typeof item.chain !== "object" || typeof item.chain.packageLinkPath !== "string" || typeof item.chain.packageLinkTarget !== "string")) {
120254
+ if (!target || seen.has(item.path) || !aliasDirs(home).includes(dirname45(item.path)) || item.newTarget !== join71(layout.currentPackageRoot, target) || item.backupPath !== `${item.path}.skills-alias-prev-${receiptId}` || item.chain !== undefined && (!item.chain || typeof item.chain !== "object" || typeof item.chain.packageLinkPath !== "string" || typeof item.chain.packageLinkTarget !== "string")) {
121492
120255
  throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
121493
120256
  }
121494
120257
  inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, target, item.chain, true);
@@ -121564,13 +120327,13 @@ async function updateCopyfileRuntime(version2, options = {}) {
121564
120327
  throw new Error("REVIEWED_LOCK_INPUT_PAIR_REQUIRED");
121565
120328
  if (!policy)
121566
120329
  throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
121567
- if (!isAbsolute42(options.reviewedLock))
120330
+ if (!isAbsolute41(options.reviewedLock))
121568
120331
  throw new Error("REVIEWED_LOCK_ABSOLUTE_PATH_REQUIRED");
121569
120332
  assertNoSymlinkAncestors(dirname45(options.reviewedLock));
121570
120333
  const stat3 = lstatSync44(options.reviewedLock);
121571
120334
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.nlink !== 1 || stat3.uid !== process.getuid?.() || stat3.mode & 63 || stat3.size > 8 * 1024 * 1024)
121572
120335
  throw new Error("REVIEWED_LOCK_FILE_UNSAFE");
121573
- reviewedLockBytes = readFileSync44(options.reviewedLock);
120336
+ reviewedLockBytes = readFileSync43(options.reviewedLock);
121574
120337
  if (!/^[a-f0-9]{64}$/.test(options.reviewedLockSha256))
121575
120338
  throw new Error("REVIEWED_LOCK_SHA256_INVALID");
121576
120339
  if (hash6(reviewedLockBytes) !== options.reviewedLockSha256)
@@ -121592,11 +120355,11 @@ async function updateCopyfileRuntime(version2, options = {}) {
121592
120355
  if ((runtimeRootStat.mode & 63) !== 0)
121593
120356
  throw new Error("RUNTIME_ROOT_NOT_PRIVATE");
121594
120357
  const id2 = randomUUID13();
121595
- const stagePath = join72(layout.runtimeRoot, `.stage-${version2}-${id2}`);
121596
- const finalPath = join72(layout.runtimeRoot, `${version2}-copyfile`);
120358
+ const stagePath = join71(layout.runtimeRoot, `.stage-${version2}-${id2}`);
120359
+ const finalPath = join71(layout.runtimeRoot, `${version2}-copyfile`);
121597
120360
  const launcherRuntime = pinnedLauncherRuntime();
121598
120361
  const launchers = layout.launchers.map((item) => {
121599
- const newTarget = join72(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename23(item.path)]);
120362
+ const newTarget = join71(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename23(item.path)]);
121600
120363
  return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget, launcherProfileForBin(basename23(item.path), layout.bin[basename23(item.path)])) };
121601
120364
  });
121602
120365
  const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
@@ -121613,50 +120376,71 @@ async function updateCopyfileRuntime(version2, options = {}) {
121613
120376
  if (artifact.packageBins && JSON.stringify(Object.entries(artifact.packageBins).sort()) !== JSON.stringify(Object.entries(layout.bin).sort())) {
121614
120377
  throw new Error("PACKAGE_BIN_SET_CHANGED");
121615
120378
  }
121616
- const stagePackage = join72(stagePath, "install");
120379
+ const stagePackage = join71(stagePath, "install");
121617
120380
  mkdirSync28(stagePackage, { mode: 448 });
121618
- copyFileSync(artifact.tarballPath, join72(stagePackage, "verified.tgz"));
121619
- writeFileSync26(join72(stagePackage, "package.json"), JSON.stringify({ name: "skills-runtime-install", version: "0.0.0", private: true, dependencies: { [PACKAGE_NAME]: "file:./verified.tgz" } }, null, 2), { mode: 384, flag: "wx" });
120381
+ copyFileSync(artifact.tarballPath, join71(stagePackage, "verified.tgz"));
120382
+ const carriedSecrets = await carryInstalledSecrets(layout, stagePackage, home, stagePath, policy);
120383
+ if (carriedSecrets && reviewedLockBytes)
120384
+ throw new Error("REVIEWED_LOCK_CANNOT_CARRY_SECRETS");
120385
+ writeFileSync26(join71(stagePackage, "package.json"), JSON.stringify({
120386
+ name: "skills-runtime-install",
120387
+ version: "0.0.0",
120388
+ private: true,
120389
+ dependencies: { [PACKAGE_NAME]: "file:./verified.tgz" },
120390
+ ...carriedSecrets ? { overrides: { [PRIVATE_OPTIONAL_PACKAGE]: carriedSecrets.spec } } : {}
120391
+ }, null, 2), { mode: 384, flag: "wx" });
121620
120392
  let npmVersion;
121621
120393
  if (reviewedLockBytes) {
121622
120394
  await validateReviewedRuntimeLock(reviewedLockBytes, options.reviewedLockSha256, {
121623
120395
  version: version2,
121624
120396
  archiveIntegrity: artifact.integrity,
121625
- packageManifest: object11(JSON.parse(readFileSync44(join72(stagePath, "verified-archive", "package", "package.json"), "utf8")), "PACKAGE_MANIFEST_INVALID"),
120397
+ packageManifest: object11(JSON.parse(readFileSync43(join71(stagePath, "verified-archive", "package", "package.json"), "utf8")), "PACKAGE_MANIFEST_INVALID"),
121626
120398
  registryOrigin: REGISTRY_ORIGIN,
121627
120399
  ...policy,
121628
120400
  fetcher
121629
120401
  });
121630
- writeFileSync26(join72(stagePackage, "package-lock.json"), reviewedLockBytes, { mode: 384, flag: "wx" });
121631
- if (!readFileSync44(join72(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
120402
+ writeFileSync26(join71(stagePackage, "package-lock.json"), reviewedLockBytes, { mode: 384, flag: "wx" });
120403
+ if (!readFileSync43(join71(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
121632
120404
  throw new Error("REVIEWED_LOCK_COPY_MISMATCH");
121633
120405
  } else {
121634
120406
  npmVersion = await runNpm(["install", "--package-lock-only", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
121635
120407
  }
121636
- const ciNpmVersion = await runNpm(["ci", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
120408
+ const plannedLock = readFileSync43(join71(stagePackage, "package-lock.json"));
120409
+ const refusedOptional = unresolvedOptionalDependencies(plannedLock);
120410
+ if (refusedOptional.some((item) => item !== `node_modules/${PACKAGE_NAME} ${PRIVATE_OPTIONAL_PACKAGE}`))
120411
+ throw new Error("DEPENDENCY_GRAPH_OPTIONAL_REFUSED");
120412
+ const ciNpmVersion = await runNpm([refusedOptional.length ? "install" : "ci", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
121637
120413
  if (!reviewedLockBytes && npmVersion !== ciNpmVersion)
121638
120414
  throw new Error("NPM_VERSION_DRIFT_DURING_UPDATE");
120415
+ if (!readFileSync43(join71(stagePackage, "package-lock.json")).equals(plannedLock))
120416
+ throw new Error(reviewedLockBytes ? "REVIEWED_LOCK_DRIFT_DURING_INSTALL" : "INSTALL_LOCK_DRIFT_DURING_INSTALL");
121639
120417
  npmVersion = ciNpmVersion;
121640
- const lockBytes = readFileSync44(join72(stagePackage, "package-lock.json"));
120418
+ const lockBytes = readFileSync43(join71(stagePackage, "package-lock.json"));
121641
120419
  if (reviewedLockBytes) {
121642
120420
  if (!lockBytes.equals(reviewedLockBytes))
121643
120421
  throw new Error("REVIEWED_LOCK_DRIFT_DURING_INSTALL");
121644
120422
  const treeNpmVersion = await runNpm(["sbom", "--sbom-format=cyclonedx", "--package-lock-only=false", "--omit=dev", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
121645
120423
  if (treeNpmVersion !== npmVersion)
121646
120424
  throw new Error("NPM_VERSION_DRIFT_DURING_UPDATE");
121647
- if (!readFileSync44(join72(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
120425
+ if (!readFileSync43(join71(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
121648
120426
  throw new Error("REVIEWED_LOCK_DRIFT_DURING_INSTALL");
121649
120427
  }
121650
- const installedPackage = join72(stagePackage, "node_modules", "@hasna", "skills");
121651
- const installed = readPackage(join72(installedPackage, "package.json"));
120428
+ const installedPackage = join71(stagePackage, "node_modules", "@hasna", "skills");
120429
+ const installedSecrets = [join71(installedPackage, "node_modules", PRIVATE_OPTIONAL_PACKAGE), join71(stagePackage, "node_modules", PRIVATE_OPTIONAL_PACKAGE)].find((path) => entryExists(join71(path, "package.json")));
120430
+ if (carriedSecrets) {
120431
+ if (!installedSecrets || object11(JSON.parse(readFileSync43(join71(installedSecrets, "package.json"), "utf8")), "CARRIED_SECRETS_INSTALL_MISMATCH").version !== carriedSecrets.record.version || readTree(installedSecrets, false, true).digest !== carriedSecrets.record.packageTreeSha256)
120432
+ throw new Error("CARRIED_SECRETS_INSTALL_MISMATCH");
120433
+ } else if (installedSecrets && refusedOptional.length)
120434
+ throw new Error("PRIVATE_OPTIONAL_PACKAGE_UNEXPECTED");
120435
+ const installed = readPackage(join71(installedPackage, "package.json"));
121652
120436
  if (installed.version !== version2 || JSON.stringify(Object.entries(installed.bins).sort()) !== JSON.stringify(Object.entries(layout.bin).sort())) {
121653
120437
  throw new Error("INSTALLED_PACKAGE_IDENTITY_MISMATCH");
121654
120438
  }
121655
- const unpackedPackage = join72(stagePath, "verified-archive", "package");
120439
+ const unpackedPackage = join71(stagePath, "verified-archive", "package");
121656
120440
  const packageTreeSha256 = comparePackageTrees(unpackedPackage, installedPackage);
121657
120441
  if (packageTreeSha256 !== artifact.packageTreeSha256)
121658
120442
  throw new Error("PACKAGE_TREE_HASH_MISMATCH");
121659
- const nodeModules = join72(stagePackage, "node_modules");
120443
+ const nodeModules = join71(stagePackage, "node_modules");
121660
120444
  normalizeModes(nodeModules);
121661
120445
  chmodSync4(stagePath, 448);
121662
120446
  const runtimeTree = readTree(nodeModules, true);
@@ -121664,7 +120448,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
121664
120448
  throw new Error("RUNTIME_FILE_MODE_UNSAFE");
121665
120449
  }
121666
120450
  assertConfigUnchanged(configPreimages);
121667
- const targetPackageRoot = join72(finalPath, "node_modules", "@hasna", "skills");
120451
+ const targetPackageRoot = join71(finalPath, "node_modules", "@hasna", "skills");
121668
120452
  const preimageSha256 = writePreimageManifest(stagePath, configPreimages, launchers);
121669
120453
  const receipt = {
121670
120454
  schema: "skills.copyfile-runtime-receipt.v1",
@@ -121688,36 +120472,38 @@ async function updateCopyfileRuntime(version2, options = {}) {
121688
120472
  preimageSha256,
121689
120473
  ...policy ? { dependencyPolicy: { ...policy, npmVersion } } : {},
121690
120474
  ...reviewedLockBytes ? { reviewedLockSha256: options.reviewedLockSha256 } : {},
120475
+ ...carriedSecrets ? { carriedSecrets: carriedSecrets.record } : {},
120476
+ ...refusedOptional.length ? { refusedOptionalPackages: [PRIVATE_OPTIONAL_PACKAGE] } : {},
121691
120477
  launchers,
121692
120478
  switchedLaunchers: [],
121693
120479
  rollbackCompletedLaunchers: []
121694
120480
  };
121695
- writeJsonPrivate(join72(stagePath, "rollout-receipt.json"), receipt);
120481
+ writeJsonPrivate(join71(stagePath, "rollout-receipt.json"), receipt);
121696
120482
  try {
121697
120483
  receipt.prerequisites = verifyTargetPrerequisites(installed.data, installedPackage, home, resolve38(options.cwd ?? process.env[LAUNCH_CWD_VARIABLE3] ?? process.cwd()), options.pathValue ?? process.env.PATH ?? "");
121698
120484
  } catch (error61) {
121699
120485
  const code2 = error61 instanceof Error && /^RUNTIME_PREREQUISITE_[A-Z_]+$/.test(error61.message) ? error61.message : "RUNTIME_PREREQUISITE_CHECK_UNAVAILABLE";
121700
120486
  receipt.prerequisites = { status: "refused", code: code2 };
121701
- persistReceipt(join72(stagePath, "rollout-receipt.json"), receipt);
120487
+ persistReceipt(join71(stagePath, "rollout-receipt.json"), receipt);
121702
120488
  throw new Error(code2);
121703
120489
  }
121704
- persistReceipt(join72(stagePath, "rollout-receipt.json"), receipt);
121705
- const finalNodeModules = join72(stagePackage, "node_modules");
121706
- const stagedNodeModules = join72(stagePath, "node_modules");
120490
+ persistReceipt(join71(stagePath, "rollout-receipt.json"), receipt);
120491
+ const finalNodeModules = join71(stagePackage, "node_modules");
120492
+ const stagedNodeModules = join71(stagePath, "node_modules");
121707
120493
  renameSync17(finalNodeModules, stagedNodeModules);
121708
- copyFileSync(join72(stagePackage, "package-lock.json"), join72(stagePath, "install-lock.json"));
121709
- chmodSync4(join72(stagePath, "install-lock.json"), 384);
120494
+ copyFileSync(join71(stagePackage, "package-lock.json"), join71(stagePath, "install-lock.json"));
120495
+ chmodSync4(join71(stagePath, "install-lock.json"), 384);
121710
120496
  const stagedTree = readTree(stagedNodeModules, true);
121711
120497
  if (stagedTree.digest !== runtimeTree.digest)
121712
120498
  throw new Error("STAGED_RUNTIME_READBACK_MISMATCH");
121713
- receipt.targetPackageRoot = join72(finalPath, "node_modules", "@hasna", "skills");
120499
+ receipt.targetPackageRoot = join71(finalPath, "node_modules", "@hasna", "skills");
121714
120500
  receipt.runtimeTreeSha256 = stagedTree.digest;
121715
- persistReceipt(join72(stagePath, "rollout-receipt.json"), receipt);
120501
+ persistReceipt(join71(stagePath, "rollout-receipt.json"), receipt);
121716
120502
  renameSync17(stagePath, finalPath);
121717
120503
  moved = true;
121718
120504
  const finalReceiptBytes = Buffer.from(`${JSON.stringify(receipt, null, 2)}
121719
120505
  `);
121720
- if (!readFileSync44(join72(finalPath, "rollout-receipt.json")).equals(finalReceiptBytes))
120506
+ if (!readFileSync43(join71(finalPath, "rollout-receipt.json")).equals(finalReceiptBytes))
121721
120507
  throw new Error("RECEIPT_MOVE_READBACK_MISMATCH");
121722
120508
  assertConfigUnchanged(configPreimages);
121723
120509
  for (const item of launchers) {
@@ -121725,7 +120511,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
121725
120511
  throw new Error("LAUNCHER_DRIFT_BEFORE_SWITCH");
121726
120512
  receipt.state = "switching";
121727
120513
  receipt.switchedLaunchers = [...receipt.switchedLaunchers, item.path];
121728
- persistReceipt(join72(finalPath, "rollout-receipt.json"), receipt);
120514
+ persistReceipt(join71(finalPath, "rollout-receipt.json"), receipt);
121729
120515
  replaceLauncher(item);
121730
120516
  if (!launcherIs(item.path, newLauncherState(item)) || !launcherIs(item.backupPath, oldLauncherState(item))) {
121731
120517
  throw new Error("LAUNCHER_SWITCH_READBACK_MISMATCH");
@@ -121734,7 +120520,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
121734
120520
  options.onLauncherSwitched?.(item.path);
121735
120521
  }
121736
120522
  receipt.state = "switched";
121737
- persistReceipt(join72(finalPath, "rollout-receipt.json"), receipt);
120523
+ persistReceipt(join71(finalPath, "rollout-receipt.json"), receipt);
121738
120524
  return { updated: true, version: version2, currentVersion: layout.currentVersion, receiptId: id2, runtimeRoot: finalPath, tarballSha256: artifact.sha256, tarballIntegrity: artifact.integrity, runtimeTreeSha256: stagedTree.digest, launcherCount: launchers.length, configCount: configPreimages.length, prerequisites: receipt.prerequisites, ...policy ? { dependencyPolicy: { ...policy, npmVersion } } : {}, ...reviewedLockBytes ? { reviewedLockSha256: options.reviewedLockSha256 } : {} };
121739
120525
  } catch (error61) {
121740
120526
  if (switched.length > 0 || moved) {
@@ -121757,8 +120543,8 @@ async function updateCopyfileRuntime(version2, options = {}) {
121757
120543
  }
121758
120544
  }
121759
120545
  try {
121760
- const receiptPath = join72(finalPath, "rollout-receipt.json");
121761
- const receipt = JSON.parse(readFileSync44(receiptPath, "utf8"));
120546
+ const receiptPath = join71(finalPath, "rollout-receipt.json");
120547
+ const receipt = JSON.parse(readFileSync43(receiptPath, "utf8"));
121762
120548
  receipt.state = rollbackFailed ? "rollback-required" : "rolled-back";
121763
120549
  persistReceipt(receiptPath, receipt);
121764
120550
  } catch {
@@ -121777,7 +120563,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
121777
120563
  const home = resolve38(options.homeDir ?? process.env.HOME ?? "");
121778
120564
  if (!home || !existsSync34(home))
121779
120565
  throw new Error("HOME_NOT_FOUND");
121780
- const runtimeRoot = join72(realpathSync20(home), ".hasna", "skills", "runtime");
120566
+ const runtimeRoot = join71(realpathSync20(home), ".hasna", "skills", "runtime");
121781
120567
  assertNoSymlinkAncestors(runtimeRoot);
121782
120568
  const rootStat = lstatSync44(runtimeRoot);
121783
120569
  if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || (rootStat.mode & 63) !== 0)
@@ -121787,40 +120573,40 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
121787
120573
  const matches2 = readdirSync26(runtimeRoot).filter((name) => {
121788
120574
  if (!/^\d+\.\d+\.\d+-copyfile$/.test(name))
121789
120575
  return false;
121790
- const receipt2 = join72(runtimeRoot, name, "rollout-receipt.json");
120576
+ const receipt2 = join71(runtimeRoot, name, "rollout-receipt.json");
121791
120577
  if (!existsSync34(receipt2))
121792
120578
  return false;
121793
120579
  try {
121794
- return JSON.parse(readFileSync44(receipt2, "utf8")).id === receiptId;
120580
+ return JSON.parse(readFileSync43(receipt2, "utf8")).id === receiptId;
121795
120581
  } catch {
121796
120582
  return false;
121797
120583
  }
121798
120584
  });
121799
120585
  if (matches2.length !== 1)
121800
120586
  throw new Error("RECEIPT_NOT_FOUND_OR_AMBIGUOUS");
121801
- const receiptPath = join72(runtimeRoot, matches2[0], "rollout-receipt.json");
121802
- const receipt = object11(JSON.parse(readFileSync44(receiptPath, "utf8")), "RECEIPT_INVALID");
120587
+ const receiptPath = join71(runtimeRoot, matches2[0], "rollout-receipt.json");
120588
+ const receipt = object11(JSON.parse(readFileSync43(receiptPath, "utf8")), "RECEIPT_INVALID");
121803
120589
  if (receipt.schema !== "skills.copyfile-runtime-receipt.v1" || !["switched", "switching", "rollback-required"].includes(receipt.state) || receipt.runtimeRoot !== runtimeRoot) {
121804
120590
  throw new Error("RECEIPT_STATE_INVALID");
121805
120591
  }
121806
120592
  if (receipt.package !== PACKAGE_NAME || matches2[0] !== `${receipt.targetVersion}-copyfile` || !new RegExp(SEMVER_PATTERN).test(receipt.currentVersion) || !new RegExp(SEMVER_PATTERN).test(receipt.targetVersion))
121807
120593
  throw new Error("RECEIPT_BINDING_INVALID");
121808
- const runtimePath = join72(runtimeRoot, matches2[0]);
121809
- if (receipt.targetPackageRoot !== join72(runtimePath, "node_modules", "@hasna", "skills") || receipt.currentPackageRoot !== join72(runtimeRoot, `${receipt.currentVersion}-copyfile`, "node_modules", "@hasna", "skills"))
120594
+ const runtimePath = join71(runtimeRoot, matches2[0]);
120595
+ if (receipt.targetPackageRoot !== join71(runtimePath, "node_modules", "@hasna", "skills") || receipt.currentPackageRoot !== join71(runtimeRoot, `${receipt.currentVersion}-copyfile`, "node_modules", "@hasna", "skills"))
121810
120596
  throw new Error("RECEIPT_RUNTIME_BINDING_INVALID");
121811
- if (readTree(join72(runtimePath, "node_modules"), true).digest !== receipt.runtimeTreeSha256) {
120597
+ if (readTree(join71(runtimePath, "node_modules"), true).digest !== receipt.runtimeTreeSha256) {
121812
120598
  throw new Error("ACTIVE_RUNTIME_TREE_DRIFT");
121813
120599
  }
121814
120600
  verifyPreimageManifest(runtimePath, receipt, home);
121815
- const oldBins = readPackage(join72(receipt.currentPackageRoot, "package.json")).bins;
121816
- const newPackage = readPackage(join72(receipt.targetPackageRoot, "package.json"));
120601
+ const oldBins = readPackage(join71(receipt.currentPackageRoot, "package.json")).bins;
120602
+ const newPackage = readPackage(join71(receipt.targetPackageRoot, "package.json"));
121817
120603
  if (newPackage.version !== receipt.targetVersion || JSON.stringify(Object.entries(oldBins).sort()) !== JSON.stringify(Object.entries(newPackage.bins).sort()))
121818
120604
  throw new Error("RECEIPT_BIN_BINDING_INVALID");
121819
120605
  const switched = [];
121820
120606
  const seen = new Set;
121821
120607
  for (const item of receipt.launchers) {
121822
120608
  const bin = oldBins[basename23(item.path)];
121823
- if (!bin || !isAbsolute42(item.path) || seen.has(item.path) || item.oldTarget !== join72(receipt.currentPackageRoot, bin) || item.newTarget !== join72(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve38(dirname45(item.path), item.oldLinkTarget) !== item.oldTarget)
120609
+ if (!bin || !isAbsolute41(item.path) || seen.has(item.path) || item.oldTarget !== join71(receipt.currentPackageRoot, bin) || item.newTarget !== join71(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve38(dirname45(item.path), item.oldLinkTarget) !== item.oldTarget)
121824
120610
  throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
121825
120611
  assertNoSymlinkAncestors(dirname45(item.path));
121826
120612
  assertLauncherRecordShapes(item, launcherProfileForBin(basename23(item.path), bin));
@@ -121865,7 +120651,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
121865
120651
  releaseLock();
121866
120652
  }
121867
120653
  }
121868
- var PACKAGE_NAME = "@hasna/skills", REGISTRY_ORIGIN = "https://registry.npmjs.org", STABLE_SEMVER_PATTERN, MAX_TARBALL_BYTES, MAX_TARBALL_EXPANDED_BYTES, MAX_TARBALL_ENTRIES = 20000, CONFIG_PREIMAGE_PATHS;
120654
+ var PACKAGE_NAME = "@hasna/skills", PRIVATE_OPTIONAL_PACKAGE = "@hasna/secrets", REGISTRY_ORIGIN = "https://registry.npmjs.org", STABLE_SEMVER_PATTERN, MAX_TARBALL_BYTES, MAX_TARBALL_EXPANDED_BYTES, MAX_TARBALL_ENTRIES = 20000, CONFIG_PREIMAGE_PATHS;
121869
120655
  var init_runtime_copyfile = __esm(() => {
121870
120656
  init_skill_contract();
121871
120657
  init_reviewed_runtime_lock();
@@ -121888,8 +120674,8 @@ __export(exports_runtime, {
121888
120674
  registerRuntime: () => registerRuntime
121889
120675
  });
121890
120676
  import { createHash as createHash46, randomUUID as randomUUID14 } from "crypto";
121891
- import { lstatSync as lstatSync45, mkdirSync as mkdirSync29, readFileSync as readFileSync45, writeFileSync as writeFileSync27 } from "fs";
121892
- import { basename as basename24, isAbsolute as isAbsolute43, join as join73 } from "path";
120677
+ import { lstatSync as lstatSync45, mkdirSync as mkdirSync29, readFileSync as readFileSync44, writeFileSync as writeFileSync27 } from "fs";
120678
+ import { basename as basename24, isAbsolute as isAbsolute42, join as join72 } from "path";
121893
120679
  import { createInterface } from "readline";
121894
120680
  function registerRuntime(parent) {
121895
120681
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
@@ -122092,7 +120878,7 @@ Updating ${name}...
122092
120878
  async function readUpdatedVersion(bunExecutable) {
122093
120879
  const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
122094
120880
  const globalBin = output2.replace(/\r?\n$/, "");
122095
- if (!globalBin || !isAbsolute43(globalBin) || /[\r\n\0]/.test(globalBin))
120881
+ if (!globalBin || !isAbsolute42(globalBin) || /[\r\n\0]/.test(globalBin))
122096
120882
  throw new Error("Update bin discovery failed");
122097
120883
  const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
122098
120884
  const selected = Bun.which("skills");
@@ -122431,7 +121217,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
122431
121217
  const info = lstatSync45(path);
122432
121218
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
122433
121219
  throw new Error("Input must be a regular file no larger than 20 MiB");
122434
- return { name: basename24(path), bytes: new Uint8Array(readFileSync45(path)) };
121220
+ return { name: basename24(path), bytes: new Uint8Array(readFileSync44(path)) };
122435
121221
  });
122436
121222
  describeRemoteFiles(inputFiles);
122437
121223
  client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
@@ -122817,7 +121603,7 @@ async function handleExportsDownload(runId2, options) {
122817
121603
  continue;
122818
121604
  const verified = await client2.getVerifiedRunArtifact(runId2, artifactId);
122819
121605
  const relativePath = safeArtifactRelativePath(typeof artifact.relativePath === "string" ? artifact.relativePath : artifact.fileName, String(artifact.fileName || artifactId));
122820
- const outputPath = join73(exportDir, relativePath);
121606
+ const outputPath = join72(exportDir, relativePath);
122821
121607
  ensureSafeExportParent(exportDir, relativePath);
122822
121608
  writeFileSync27(outputPath, verified.bytes, { flag: "wx", mode: 384 });
122823
121609
  downloaded.push({ id: artifactId, path: outputPath, byteSize: verified.byteSize });
@@ -122856,7 +121642,7 @@ function ensureSafeExportParent(root2, relativePath) {
122856
121642
  let parent = root2;
122857
121643
  for (const part of ["", ...parts]) {
122858
121644
  if (part)
122859
- parent = join73(parent, part);
121645
+ parent = join72(parent, part);
122860
121646
  try {
122861
121647
  if (!lstatSync45(parent).isDirectory() || lstatSync45(parent).isSymbolicLink())
122862
121648
  throw new Error("Unsafe artifact directory");
@@ -123153,12 +121939,12 @@ var exports_recurring = {};
123153
121939
  __export(exports_recurring, {
123154
121940
  registerRecurringCommands: () => registerRecurringCommands
123155
121941
  });
123156
- import { constants as constants31, closeSync as closeSync32, fstatSync as fstatSync32, lstatSync as lstatSync46, openSync as openSync32, readSync as readSync24 } from "fs";
121942
+ import { constants as constants31, closeSync as closeSync31, fstatSync as fstatSync31, lstatSync as lstatSync46, openSync as openSync31, readSync as readSync24 } from "fs";
123157
121943
  import { createInterface as createInterface2 } from "readline";
123158
121944
  function readRequest(path) {
123159
- const fd = openSync32(path, constants31.O_RDONLY | constants31.O_NOFOLLOW | constants31.O_NONBLOCK);
121945
+ const fd = openSync31(path, constants31.O_RDONLY | constants31.O_NOFOLLOW | constants31.O_NONBLOCK);
123160
121946
  try {
123161
- const before2 = fstatSync32(fd);
121947
+ const before2 = fstatSync31(fd);
123162
121948
  if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
123163
121949
  throw new RecurringInputError;
123164
121950
  const bytes = Buffer.alloc(before2.size + 1);
@@ -123169,14 +121955,14 @@ function readRequest(path) {
123169
121955
  break;
123170
121956
  length += n2;
123171
121957
  }
123172
- const after2 = fstatSync32(fd), current = lstatSync46(path);
121958
+ const after2 = fstatSync31(fd), current = lstatSync46(path);
123173
121959
  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())
123174
121960
  throw new RecurringInputError;
123175
121961
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
123176
121962
  } catch {
123177
121963
  throw new RecurringInputError;
123178
121964
  } finally {
123179
- closeSync32(fd);
121965
+ closeSync31(fd);
123180
121966
  }
123181
121967
  }
123182
121968
  async function acceptAtTerminal(draft) {
@@ -123455,7 +122241,7 @@ var init_completion = __esm(() => {
123455
122241
  // src/lib/portable-snapshot-filter.ts
123456
122242
  import { readdirSync as readdirSync27, statSync as statSync23 } from "fs";
123457
122243
  import { homedir as homedir12 } from "os";
123458
- import { join as join74, sep as sep21 } from "path";
122244
+ import { join as join73, sep as sep21 } from "path";
123459
122245
  function isExcludedSkillFileName(fileName) {
123460
122246
  if (EXCLUDE_FILE_NAMES.has(fileName)) {
123461
122247
  return true;
@@ -123478,16 +122264,16 @@ function isPortableWithinSkill(relativeParts) {
123478
122264
  function homePathFor(definition, homesRoot) {
123479
122265
  const home = homesRoot ?? homedir12();
123480
122266
  if (definition.subClass === "skills" || definition.subClass === "custom") {
123481
- return join74(skillsDataRootForHome(home), definition.name);
122267
+ return join73(skillsDataRootForHome(home), definition.name);
123482
122268
  }
123483
122269
  if (definition.agent === "opencode") {
123484
- return join74(home, ".config", "opencode", "skills");
122270
+ return join73(home, ".config", "opencode", "skills");
123485
122271
  }
123486
- return join74(home, `.${definition.agent}`, "skills");
122272
+ return join73(home, `.${definition.agent}`, "skills");
123487
122273
  }
123488
122274
  function destinationFor(definition, stationId, relativePath) {
123489
- const category = definition.subClass === "agent-homes" ? join74("agent-homes", definition.agent ?? "") : definition.name;
123490
- return join74("resources", stationId, "skills", category, ...relativePath.split(sep21));
122275
+ const category = definition.subClass === "agent-homes" ? join73("agent-homes", definition.agent ?? "") : definition.name;
122276
+ return join73("resources", stationId, "skills", category, ...relativePath.split(sep21));
123491
122277
  }
123492
122278
  function walkEntries(absoluteRoot) {
123493
122279
  let entries;
@@ -123498,7 +122284,7 @@ function walkEntries(absoluteRoot) {
123498
122284
  }
123499
122285
  const output2 = [];
123500
122286
  for (const entry of entries) {
123501
- const childFull = join74(absoluteRoot, entry.name);
122287
+ const childFull = join73(absoluteRoot, entry.name);
123502
122288
  if (entry.isSymbolicLink()) {
123503
122289
  output2.push({ kind: "symlink", relativePath: entry.name, fullPath: childFull });
123504
122290
  continue;
@@ -123509,7 +122295,7 @@ function walkEntries(absoluteRoot) {
123509
122295
  }
123510
122296
  const nested = walkEntries(childFull);
123511
122297
  for (const item of nested) {
123512
- output2.push({ ...item, relativePath: join74(entry.name, item.relativePath) });
122298
+ output2.push({ ...item, relativePath: join73(entry.name, item.relativePath) });
123513
122299
  }
123514
122300
  continue;
123515
122301
  }
@@ -123606,18 +122392,18 @@ import { createHash as createHash47 } from "crypto";
123606
122392
  import {
123607
122393
  copyFileSync as copyFileSync2,
123608
122394
  mkdirSync as mkdirSync30,
123609
- readFileSync as readFileSync46,
122395
+ readFileSync as readFileSync45,
123610
122396
  statSync as statSync24,
123611
122397
  writeFileSync as writeFileSync28
123612
122398
  } from "fs";
123613
- import { dirname as dirname47, isAbsolute as isAbsolute44, relative as relative15, resolve as resolve39, sep as sep22 } from "path";
122399
+ import { dirname as dirname47, isAbsolute as isAbsolute43, relative as relative15, resolve as resolve39, sep as sep22 } from "path";
123614
122400
  function validateStationId(stationId) {
123615
122401
  if (!/^[a-z0-9-]+$/.test(stationId)) {
123616
122402
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
123617
122403
  }
123618
122404
  }
123619
122405
  function sha256File(filePath) {
123620
- return createHash47("sha256").update(readFileSync46(filePath)).digest("hex");
122406
+ return createHash47("sha256").update(readFileSync45(filePath)).digest("hex");
123621
122407
  }
123622
122408
  function scanHome(definition, homesRoot) {
123623
122409
  const homePath = homePathFor(definition, homesRoot);
@@ -123716,7 +122502,7 @@ function writeStationSnapshot(options) {
123716
122502
  for (const plan of plans) {
123717
122503
  const destination = resolve39(repoRoot, plan.destination);
123718
122504
  const destinationRelative = relative15(repoRoot, destination);
123719
- if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep22) || isAbsolute44(destinationRelative)) {
122505
+ if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep22) || isAbsolute43(destinationRelative)) {
123720
122506
  throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
123721
122507
  }
123722
122508
  let existingDigest = null;
@@ -123790,7 +122576,7 @@ __export(exports_create_sync_config, {
123790
122576
  registerCreateSync: () => registerCreateSync
123791
122577
  });
123792
122578
  import { existsSync as existsSync35 } from "fs";
123793
- import { join as join75 } from "path";
122579
+ import { join as join74 } from "path";
123794
122580
  function registerCreateSync(parent) {
123795
122581
  const configCmd = parent.command("config").description("Manage skills configuration");
123796
122582
  configCmd.command("show", { isDefault: true }).option("--json", "Output as JSON", false).description("Show current merged configuration").action((options) => {
@@ -123900,7 +122686,7 @@ function handleCreate(name, options) {
123900
122686
  console.log(source_default.green(`\u2713 Created custom skill '${result2.name}' at ${result2.path}`));
123901
122687
  console.log(source_default.dim(` Category: ${result2.manifest.category}`));
123902
122688
  console.log(source_default.dim(` Tags: ${result2.manifest.tags?.join(", ")}`));
123903
- console.log(` ${source_default.cyan("Edit:")} ${join75(result2.path, options.kind === "instruction" ? "SKILL.md" : "src/index.ts")}`);
122689
+ console.log(` ${source_default.cyan("Edit:")} ${join74(result2.path, options.kind === "instruction" ? "SKILL.md" : "src/index.ts")}`);
123904
122690
  console.log(` ${source_default.cyan("Prepare:")} skills prepare ${result2.name} --version <new-semver>`);
123905
122691
  }
123906
122692
  } catch (error61) {
@@ -124190,8 +122976,8 @@ var init_create_sync_config = __esm(() => {
124190
122976
 
124191
122977
  // src/lib/claude-hook-disable.ts
124192
122978
  import { createHash as createHash48, randomUUID as randomUUID15 } from "crypto";
124193
- import { constants as constants32, closeSync as closeSync33, fchownSync as fchownSync2, fchmodSync as fchmodSync4, fsyncSync as fsyncSync11, lstatSync as lstatSync47, mkdirSync as mkdirSync31, openSync as openSync33, realpathSync as realpathSync21 } from "fs";
124194
- import { basename as basename25, dirname as dirname48, isAbsolute as isAbsolute45, join as join76, resolve as resolve40 } from "path";
122979
+ import { constants as constants32, closeSync as closeSync32, fchownSync as fchownSync2, fchmodSync as fchmodSync4, fsyncSync as fsyncSync11, lstatSync as lstatSync47, mkdirSync as mkdirSync31, openSync as openSync32, realpathSync as realpathSync21 } from "fs";
122980
+ import { basename as basename25, dirname as dirname48, isAbsolute as isAbsolute44, join as join75, resolve as resolve40 } from "path";
124195
122981
  import { KernelLock as KernelLock2 } from "@hasna/contracts/kernel-lock";
124196
122982
  function fail6(reason2) {
124197
122983
  throw new Error(`CLAUDE_HOOK_DISABLE_${reason2}`);
@@ -124204,7 +122990,7 @@ function serialize(value) {
124204
122990
  return value.kind === "string" ? JSON.stringify(value.value) : value.value;
124205
122991
  }
124206
122992
  function path(value) {
124207
- if (!isAbsolute45(value) || resolve40(value) !== value || /[\x00-\x1f\x7f]/.test(value))
122993
+ if (!isAbsolute44(value) || resolve40(value) !== value || /[\x00-\x1f\x7f]/.test(value))
124208
122994
  fail6("PATH_INVALID");
124209
122995
  }
124210
122996
  function parents3(file2) {
@@ -124239,10 +123025,10 @@ function executable2(command, expectedSha256) {
124239
123025
  if (commandFile.sha256 !== expectedSha256)
124240
123026
  fail6("COMMAND_CHANGED");
124241
123027
  const entry = resolved.entry, packageRoot = dirname48(dirname48(entry));
124242
- if (entry !== join76(packageRoot, "bin", "index.js") || realpathSync21(entry) !== entry)
123028
+ if (entry !== join75(packageRoot, "bin", "index.js") || realpathSync21(entry) !== entry)
124243
123029
  fail6("COMMAND_UNVERIFIED");
124244
123030
  const entryFile = snapshot(entry, false, { readOnlyPackage: true });
124245
- const manifest = snapshot(join76(packageRoot, "package.json"), false, { readOnlyPackage: true });
123031
+ const manifest = snapshot(join75(packageRoot, "package.json"), false, { readOnlyPackage: true });
124246
123032
  const parsed = parseNativeJsonObject(manifest.text);
124247
123033
  if (string6(field3(parsed, "name")) !== "@hasna/skills" || string6(field3(field3(parsed, "bin"), "skills")) !== "bin/index.js")
124248
123034
  fail6("COMMAND_UNVERIFIED");
@@ -124383,26 +123169,26 @@ function disableClaudeHooks(options) {
124383
123169
  mkdirSync31(options.preimageDir, { mode: 448 });
124384
123170
  if ((lstatSync47(options.preimageDir).mode & 511) !== 448)
124385
123171
  fail6("PREIMAGE_INVALID");
124386
- preimage = join76(options.preimageDir, "settings.preimage.json");
123172
+ preimage = join75(options.preimageDir, "settings.preimage.json");
124387
123173
  save(preimage, before2.bytes);
124388
123174
  const preserved = snapshot(preimage, true), checkPreservationRoot = parents3(preimage);
124389
123175
  if (preserved.sha256 !== before2.sha256 || !preserved.bytes.equals(before2.bytes))
124390
123176
  fail6("PRESERVATION_FAILED");
124391
- displaced = join76(dirname48(options.settings), `.settings.skills-disable-${randomUUID15()}.json`);
123177
+ displaced = join75(dirname48(options.settings), `.settings.skills-disable-${randomUUID15()}.json`);
124392
123178
  save(displaced, after2);
124393
- const fd = openSync33(displaced, constants32.O_RDONLY | constants32.O_NOFOLLOW);
123179
+ const fd = openSync32(displaced, constants32.O_RDONLY | constants32.O_NOFOLLOW);
124394
123180
  try {
124395
123181
  fchownSync2(fd, Number(before2.stat.uid), Number(before2.stat.gid));
124396
123182
  fchmodSync4(fd, 384);
124397
123183
  fsyncSync11(fd);
124398
123184
  } finally {
124399
- closeSync33(fd);
123185
+ closeSync32(fd);
124400
123186
  }
124401
123187
  const staged = snapshot(displaced, true);
124402
123188
  assertNativePathAcl(displaced, staged.stat);
124403
123189
  if (staged.sha256 !== result2.plannedAfterSha256)
124404
123190
  fail6("STAGING_CHANGED");
124405
- receipt = join76(options.preimageDir, "receipt.json");
123191
+ receipt = join75(options.preimageDir, "receipt.json");
124406
123192
  const preparationBytes = `${JSON.stringify({
124407
123193
  ...result2,
124408
123194
  state: "prepared",
@@ -124438,14 +123224,14 @@ function disableClaudeHooks(options) {
124438
123224
  unchanged2(preserved);
124439
123225
  if (movedIdentity(displacedOriginal.stat) !== movedIdentity(before2.stat) || displacedOriginal.sha256 !== before2.sha256 || movedIdentity(current.stat) !== movedIdentity(staged.stat) || current.sha256 !== staged.sha256)
124440
123226
  fail6("POST_WRITE_CHANGED");
124441
- const directory3 = openSync33(dirname48(options.settings), constants32.O_RDONLY | constants32.O_DIRECTORY);
123227
+ const directory3 = openSync32(dirname48(options.settings), constants32.O_RDONLY | constants32.O_DIRECTORY);
124442
123228
  try {
124443
123229
  fsyncSync11(directory3);
124444
123230
  } finally {
124445
- closeSync33(directory3);
123231
+ closeSync32(directory3);
124446
123232
  }
124447
123233
  const applied = { ...result2, state: "applied", mutationOccurred: true, afterSha256: staged.sha256, preimage, displaced, receipt };
124448
- const completed = join76(options.preimageDir, "completed.json");
123234
+ const completed = join75(options.preimageDir, "completed.json");
124449
123235
  const completionBytes = `${JSON.stringify({ ...applied, receipt: completed })}
124450
123236
  `;
124451
123237
  save(completed, completionBytes);
@@ -124489,7 +123275,7 @@ var init_claude_hook_disable = __esm(() => {
124489
123275
 
124490
123276
  // src/lib/agent-install-selection.ts
124491
123277
  import { lstatSync as lstatSync48 } from "fs";
124492
- import { dirname as dirname49, join as join77, resolve as resolve41 } from "path";
123278
+ import { dirname as dirname49, join as join76, resolve as resolve41 } from "path";
124493
123279
  import { homedir as homedir13 } from "os";
124494
123280
  function detectedIntegrationAgents(options = {}) {
124495
123281
  const home = options.home ?? homedir13(), env3 = options.env ?? process.env;
@@ -124513,12 +123299,12 @@ function detectedIntegrationAgents(options = {}) {
124513
123299
  if (agent === "sumi") {
124514
123300
  const xdg = env3.XDG_CONFIG_HOME;
124515
123301
  const xdgSumi = xdg?.trim() ? resolve41(options.cwd ?? process.cwd(), xdg === "~" ? home : xdg.startsWith("~/") || xdg.startsWith("~\\") ? resolve41(home, xdg.slice(2)) : xdg, "sumi") : null;
124516
- return ["SUMI_HOME", "SUMI_CONFIG_DIR", "SUMI_CONFIG", "SUMI_CONFIG_CONTENT"].some((key2) => env3[key2] !== undefined) || Bun.which("sumi-paths", { PATH: env3.PATH ?? "" }) !== null || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === "sumi" && present2(join77(home, dirname49(root2)))) || present2(join77(home, ".config", "sumi")) || xdgSumi !== null && present2(xdgSumi);
123302
+ return ["SUMI_HOME", "SUMI_CONFIG_DIR", "SUMI_CONFIG", "SUMI_CONFIG_CONTENT"].some((key2) => env3[key2] !== undefined) || Bun.which("sumi-paths", { PATH: env3.PATH ?? "" }) !== null || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === "sumi" && present2(join76(home, dirname49(root2)))) || present2(join76(home, ".config", "sumi")) || xdgSumi !== null && present2(xdgSumi);
124517
123303
  }
124518
123304
  if (agent === "hermes" && env3.HERMES_HOME !== undefined)
124519
123305
  return true;
124520
123306
  const adapter = AGENT_ADAPTERS[agent];
124521
- return present2(join77(home, dirname49(adapter.config))) || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === agent && dirname49(root2) === `.${agent}` && present2(join77(home, dirname49(root2))));
123307
+ return present2(join76(home, dirname49(adapter.config))) || NATIVE_SKILL_ROOTS.some(([provider, root2]) => provider === agent && dirname49(root2) === `.${agent}` && present2(join76(home, dirname49(root2))));
124522
123308
  });
124523
123309
  if (!selected.length && !options.allowEmpty)
124524
123310
  throw new Error(`No configured or detected agents; select --agent <agent> explicitly (${INTEGRATION_AGENTS.join(", ")}).`);
@@ -124533,10 +123319,10 @@ var init_agent_install_selection = __esm(() => {
124533
123319
 
124534
123320
  // src/lib/codex-hook-trust-identity.ts
124535
123321
  import { lstatSync as lstatSync49, realpathSync as realpathSync22 } from "fs";
124536
- import { dirname as dirname50, isAbsolute as isAbsolute46, join as join78, resolve as resolve42 } from "path";
123322
+ import { dirname as dirname50, isAbsolute as isAbsolute45, join as join77, resolve as resolve42 } from "path";
124537
123323
  import { isDeepStrictEqual as isDeepStrictEqual20 } from "util";
124538
123324
  function commandPhysical(command) {
124539
- need8(typeof command === "string" && isAbsolute46(command) && !command.includes("\x00") && resolve42(command) === command, COMMAND_NOT_CANONICAL);
123325
+ need8(typeof command === "string" && isAbsolute45(command) && !command.includes("\x00") && resolve42(command) === command, COMMAND_NOT_CANONICAL);
124540
123326
  const physical = realpathSync22(command);
124541
123327
  let spelled;
124542
123328
  try {
@@ -124591,12 +123377,12 @@ function targetUnchanged(command, target) {
124591
123377
  assertPinnedRuntime(target.runtime);
124592
123378
  }
124593
123379
  function inspectRecordedSkillsCli(command, expected) {
124594
- need8(isAbsolute46(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
123380
+ need8(isAbsolute45(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
124595
123381
  const target = skillsCommandTarget(command), resolved = target.entry;
124596
123382
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
124597
- const manifest = snapshot(join78(dirname50(dirname50(resolved)), "package.json"), false, { readOnlyPackage: true });
123383
+ const manifest = snapshot(join77(dirname50(dirname50(resolved)), "package.json"), false, { readOnlyPackage: true });
124598
123384
  const pkg = JSON.parse(manifest.text);
124599
- need8(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join78(dirname50(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
123385
+ need8(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join77(dirname50(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
124600
123386
  need8((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
124601
123387
  const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
124602
123388
  need8(isDeepStrictEqual20(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
@@ -124610,16 +123396,16 @@ function bindSkillsCli(command, reviewed) {
124610
123396
  const normal = Bun.which("skills", { PATH: process.env.PATH });
124611
123397
  need8(normal, "SKILLS_COMMAND_UNAVAILABLE");
124612
123398
  const normalTarget = skillsCommandTarget(normal), resolved = normalTarget.entry;
124613
- const bound = isAbsolute46(command) ? command : command === "skills" ? normal : undefined;
123399
+ const bound = isAbsolute45(command) ? command : command === "skills" ? normal : undefined;
124614
123400
  need8(bound, "SKILLS_COMMAND_MISMATCH");
124615
123401
  const boundTarget = skillsCommandTarget(bound);
124616
123402
  need8(boundTarget.entry === resolved, "SKILLS_COMMAND_MISMATCH");
124617
123403
  const entrypoint = reviewed?.path ?? process.argv[1];
124618
123404
  need8(entrypoint && realpathSync22(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
124619
123405
  const cli = snapshot(resolved, false, { readOnlyPackage: true });
124620
- const manifest = snapshot(join78(dirname50(dirname50(resolved)), "package.json"), false, { readOnlyPackage: true });
123406
+ const manifest = snapshot(join77(dirname50(dirname50(resolved)), "package.json"), false, { readOnlyPackage: true });
124621
123407
  const pkg = JSON.parse(manifest.text);
124622
- need8(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join78(dirname50(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
123408
+ need8(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join77(dirname50(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
124623
123409
  if (reviewed)
124624
123410
  need8(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
124625
123411
  need8((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
@@ -124638,7 +123424,7 @@ function captureSkillsCliProducerIdentity(command) {
124638
123424
  const bound = bindSkillsCli(command);
124639
123425
  const target = skillsCommandTarget(command);
124640
123426
  const cli = snapshot(target.entry, false, { readOnlyPackage: true });
124641
- const manifest = snapshot(join78(dirname50(dirname50(target.entry)), "package.json"), false, { readOnlyPackage: true });
123427
+ const manifest = snapshot(join77(dirname50(dirname50(target.entry)), "package.json"), false, { readOnlyPackage: true });
124642
123428
  const pkg = JSON.parse(manifest.text);
124643
123429
  need8(pkg.name === "@hasna/skills" && pkg.version === bound.receipt.version && target.entry === bound.receipt.path, "SKILLS_PACKAGE_MISMATCH");
124644
123430
  const launcher = target.launcher ?? cli;
@@ -124692,23 +123478,23 @@ var init_codex_hook_policy_recovery = __esm(() => {
124692
123478
  });
124693
123479
 
124694
123480
  // src/lib/agent-codex-trust.ts
124695
- import { lstatSync as lstatSync50, mkdirSync as mkdirSync32, readdirSync as readdirSync28, readFileSync as readFileSync47, realpathSync as realpathSync23, statSync as statSync25 } from "fs";
123481
+ import { lstatSync as lstatSync50, mkdirSync as mkdirSync32, readdirSync as readdirSync28, readFileSync as readFileSync46, realpathSync as realpathSync23, statSync as statSync25 } from "fs";
124696
123482
  import { createHash as createHash49, randomUUID as randomUUID16 } from "crypto";
124697
123483
  import { execFileSync as execFileSync2 } from "child_process";
124698
- import { dirname as dirname51, isAbsolute as isAbsolute47, join as join79, resolve as resolve43 } from "path";
123484
+ import { dirname as dirname51, isAbsolute as isAbsolute46, join as join78, resolve as resolve43 } from "path";
124699
123485
  import { homedir as homedir14 } from "os";
124700
123486
  import { isDeepStrictEqual as isDeepStrictEqual22 } from "util";
124701
123487
  function verifyReleaseArtifact(proof, skillsCli) {
124702
- need8(isAbsolute47(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
123488
+ need8(isAbsolute46(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
124703
123489
  const tarPath = realpathSync23(proof.packageTarPath);
124704
123490
  need8(statSync25(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
124705
- const tarBytes = readFileSync47(tarPath);
123491
+ const tarBytes = readFileSync46(tarPath);
124706
123492
  need8(tarBytes.byteLength === proof.packageTarBytes && createHash49("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
124707
123493
  const packageRoot = dirname51(dirname51(realpathSync23(skillsCli.receipt.path)));
124708
- const manifest = readFileSync47(join79(packageRoot, "package.json"));
123494
+ const manifest = readFileSync46(join78(packageRoot, "package.json"));
124709
123495
  need8(createHash49("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
124710
- need8(createHash49("sha256").update(readFileSync47(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
124711
- const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync47(skillsCli.receipt.path)]];
123496
+ need8(createHash49("sha256").update(readFileSync46(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
123497
+ const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync46(skillsCli.receipt.path)]];
124712
123498
  for (const [member, expected] of members2) {
124713
123499
  let actual;
124714
123500
  try {
@@ -124723,25 +123509,25 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
124723
123509
  let rpc;
124724
123510
  try {
124725
123511
  const home = resolve43(options.home ?? homedir14()), dataDir3 = resolve43(options.dataDir ?? getDataDirReadOnly());
124726
- const parent = resolve43(join79(dataDir3, "native-hook-trust")), journal = resolve43(options.journal);
123512
+ const parent = resolve43(join78(dataDir3, "native-hook-trust")), journal = resolve43(options.journal);
124727
123513
  need8(journal.startsWith(parent + "/") && /^[a-f0-9-]{36}$/.test(journal.slice(parent.length + 1)), "RECONCILE_JOURNAL_PATH");
124728
123514
  const dir = lstatSync50(journal, { throwIfNoEntry: false });
124729
123515
  need8(!!dir && dir.isDirectory() && !dir.isSymbolicLink() && dir.uid === process.getuid() && (dir.mode & 511) === 448, "UNSAFE_JOURNAL");
124730
- need8(!lstatSync50(join79(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
124731
- need8(lstatSync50(join79(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
124732
- const stoppedFile = snapshot(join79(journal, "stopped.json"), true);
124733
- const intentFile = snapshot(join79(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
124734
- const configBefore = snapshot(join79(journal, "config.before.toml"), true), hooksBefore = snapshot(join79(journal, "hooks.before.json"), true), policyBefore = snapshot(join79(journal, "policy.before.json"), true);
123516
+ need8(!lstatSync50(join78(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
123517
+ need8(lstatSync50(join78(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
123518
+ const stoppedFile = snapshot(join78(journal, "stopped.json"), true);
123519
+ const intentFile = snapshot(join78(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
123520
+ const configBefore = snapshot(join78(journal, "config.before.toml"), true), hooksBefore = snapshot(join78(journal, "hooks.before.json"), true), policyBefore = snapshot(join78(journal, "policy.before.json"), true);
124735
123521
  const legacyIntent = intent.home === undefined && intent.configSha256 === undefined && intent.configVersion === undefined && intent.declarations === undefined && intent.admitted === undefined && intent.nativeHooks === undefined;
124736
123522
  need8(intent.version === 1 && /^[a-f0-9]{64}$/.test(intent.planDigest) && typeof intent.configPath === "string" && /^[a-f0-9]{64}$/.test(intent.policySha256) && /^[a-f0-9]{64}$/.test(intent.hooksSha256) && Array.isArray(intent.hooks) && intent.hooks.length > 0 && intent.hooks.length <= 100 && (legacyIntent || typeof intent.home === "string" && intent.home === home && /^[a-f0-9]{64}$/.test(intent.configSha256) && typeof intent.configVersion === "string" && Array.isArray(intent.declarations) && Array.isArray(intent.admitted) && Array.isArray(intent.nativeHooks)), "RECONCILE_INTENT_INVALID");
124737
- const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join79(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
123523
+ const declarations = intent.declarations ?? intent.hooks.map((hook) => ({ event: hook.event, key: `${join78(home, ".codex/hooks.json")}${hook.key.slice(hook.key.indexOf(".codex/hooks.json") + ".codex/hooks.json".length)}`, command: hook.command }));
124738
123524
  const admitted = intent.admitted ?? intent.hooks;
124739
123525
  const configSha256 = intent.configSha256 ?? configBefore.sha256, configVersion = intent.configVersion ?? intent.expectedVersion;
124740
123526
  const digestInput = { version: 1, home: intent.home ?? home, configPath: intent.configPath, ...intent.nativeConfigPath !== undefined ? { nativeConfigPath: intent.nativeConfigPath } : {}, configSha256, configVersion, policySha256: intent.policySha256, hooksSha256: intent.hooksSha256, skillsCli: intent.skillsCli, nativeVersion: intent.nativeVersion, declarations, admitted };
124741
123527
  need8(makePlanDigest(digestInput) === intent.planDigest, "RECONCILE_PLAN_CHANGED");
124742
123528
  need8(isDeepStrictEqual22(intent.hooks, admitted.filter((hook) => !hook.enabled || hook.trustStatus !== "trusted")), "RECONCILE_INTENT_HOOKS_CHANGED");
124743
123529
  need8(configBefore.sha256 === (intent.beforeSha256 ?? intent.configSha256) && hooksBefore.sha256 === intent.hooksSha256 && policyBefore.sha256 === intent.policySha256, "RECONCILE_JOURNAL_CHANGED");
124744
- const policyCurrent = snapshot(join79(dataDir3, "agent-policy.json"), true);
123530
+ const policyCurrent = snapshot(join78(dataDir3, "agent-policy.json"), true);
124745
123531
  const { claudeDiscoveryRecovery: claudeRecovery, nativeHookAdditionsRecovery: additionsRecovery } = options;
124746
123532
  const recovery = claudeRecovery ?? additionsRecovery;
124747
123533
  need8(!recovery || !options.supersedeBinding, "RECONCILE_RECOVERY_MODE_CONFLICT");
@@ -124758,17 +123544,17 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
124758
123544
  if (supersededBinding || recovery) {
124759
123545
  need8(Array.isArray(intent.nativeHooks) && intent.nativeHooks.length > 0, "RECONCILE_NATIVE_INVENTORY_REQUIRED");
124760
123546
  const proof = options.releaseProof;
124761
- need8(!!proof && isAbsolute47(proof.packageTarPath) && /^[a-f0-9]{64}$/.test(proof.packageTarSha256) && Number.isInteger(proof.packageTarBytes) && proof.packageTarBytes > 0 && /^[a-f0-9]{64}$/.test(proof.manifestSha256) && /^[a-f0-9]{64}$/.test(proof.executableSha256), "RECONCILE_RELEASE_PROVENANCE_REQUIRED");
123547
+ need8(!!proof && isAbsolute46(proof.packageTarPath) && /^[a-f0-9]{64}$/.test(proof.packageTarSha256) && Number.isInteger(proof.packageTarBytes) && proof.packageTarBytes > 0 && /^[a-f0-9]{64}$/.test(proof.manifestSha256) && /^[a-f0-9]{64}$/.test(proof.executableSha256), "RECONCILE_RELEASE_PROVENANCE_REQUIRED");
124762
123548
  }
124763
123549
  const currentConfig = snapshot(intent.configPath, true);
124764
123550
  const policy = parseManagedSkillPolicy(policyCurrent.text), binding = policy.bridge;
124765
- const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join79(home, ".codex"), hooksPath = join79(physicalRoot, "hooks.json");
124766
- need8(resolve43(intent.configPath) === resolve43(join79(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
123551
+ const alias = binding.rootAliases?.find((item) => item.agent === "codex"), physicalRoot = alias?.target ?? join78(home, ".codex"), hooksPath = join78(physicalRoot, "hooks.json");
123552
+ need8(resolve43(intent.configPath) === resolve43(join78(physicalRoot, "config.toml")), "RECONCILE_CONFIG_PATH_CHANGED");
124767
123553
  const nativeConfigPath = intent.nativeConfigPath ?? intent.configPath;
124768
- need8([join79(home, ".codex/config.toml"), join79(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
123554
+ need8([join78(home, ".codex/config.toml"), join78(physicalRoot, "config.toml")].includes(nativeConfigPath), "RECONCILE_NATIVE_CONFIG_PATH_CHANGED");
124769
123555
  const codexHome = nativeConfigPath !== intent.configPath ? undefined : dirname51(nativeConfigPath);
124770
123556
  const hooksCurrent = snapshot(hooksPath);
124771
- const additions = additionsRecovery ? reviewNativeHookAdditions({ path: additionsRecovery.path, intent: intentFile, policy: policyCurrent, configBefore, configCurrent: currentConfig, hooksBefore, hooksCurrent, nativeHooksPath: join79(dirname51(nativeConfigPath), "hooks.json"), journalHooks: intent.hooks, recordedNativeHooks: intent.nativeHooks }) : undefined;
123557
+ const additions = additionsRecovery ? reviewNativeHookAdditions({ path: additionsRecovery.path, intent: intentFile, policy: policyCurrent, configBefore, configCurrent: currentConfig, hooksBefore, hooksCurrent, nativeHooksPath: join78(dirname51(nativeConfigPath), "hooks.json"), journalHooks: intent.hooks, recordedNativeHooks: intent.nativeHooks }) : undefined;
124772
123558
  const managedHooks = [...intent.hooks, ...additions?.hooks ?? []];
124773
123559
  const managedKeys = managedHooks.map((h) => h.key);
124774
123560
  const witnessSame = codexTrustReconcileWitness(configBefore.text, managedKeys) === codexTrustReconcileWitness(currentConfig.text, managedKeys);
@@ -124832,7 +123618,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
124832
123618
  need8(isDeepStrictEqual22(actual, expected), "RECONCILE_UNRELATED_HOOK_CHANGED");
124833
123619
  }
124834
123620
  for (const wanted of intent.hooks) {
124835
- const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join79(home, ".codex/hooks.json"), hooksPath));
123621
+ const matches2 = nativeHooks.filter((h2) => h2.key === wanted.key || h2.key === wanted.key.replace(join78(home, ".codex/hooks.json"), hooksPath));
124836
123622
  need8(matches2.length === 1, "RECONCILE_NATIVE_IDENTITY_CHANGED");
124837
123623
  const h = matches2[0];
124838
123624
  const trusted = h.trustStatus === "trusted";
@@ -124881,7 +123667,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
124881
123667
  const receipt = { version: 1, status: preview2 ? "recovery-review-required" : supersededBinding ? "superseded" : "reconciled", reconciled: !preview2, supersededBinding, automaticRollback: false, journal, planDigest: intent.planDigest, nativeVersion: rpc.version, nativeStateVerified: !nativeTrustPending, nativeTrustPending, bindingRefreshRequired: !!configDiscoveryRecovery, nativeExecutionVerified: false, configSha256: currentConfig.sha256, hooksSha256: hooksCurrent.sha256, policySha256: policyBefore.sha256, policyBeforeSha256: policyBefore.sha256, policyCurrentSha256: policyCurrent.sha256, previousSkillsCli: intent.skillsCli, skillsCli: skillsCli.receipt, releaseProof: options.releaseProof, nativeInventoryScope: recordedNativeHooks ? "complete" : "declared-managed-hooks-only", unrelatedNativeHooksPreserved: !!recordedNativeHooks, unrelatedSettingsAndCommentsPreserved: true, ...recoveryPlan ? { recoveryPlan, recoveryPlanDigest } : {}, ...codexAdmissionReceipt(rpc.admission) };
124882
123668
  if (preview2)
124883
123669
  return receipt;
124884
- save(join79(journal, "receipt.json"), json2(receipt));
123670
+ save(join78(journal, "receipt.json"), json2(receipt));
124885
123671
  return receipt;
124886
123672
  } catch (error61) {
124887
123673
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_RECONCILE_REFUSED";
@@ -124892,20 +123678,20 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
124892
123678
  }
124893
123679
  async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
124894
123680
  const home = resolve43(options.home ?? homedir14());
124895
- return withCodexCorpusWriteAsync([join79(home, ".codex")], (_assertCurrent, admission) => enrollCodexNativeHooksUnlocked(options, connect, admission), options);
123681
+ return withCodexCorpusWriteAsync([join78(home, ".codex")], (_assertCurrent, admission) => enrollCodexNativeHooksUnlocked(options, connect, admission), options);
124896
123682
  }
124897
123683
  async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
124898
123684
  let rpc, journal;
124899
123685
  try {
124900
123686
  const home = resolve43(options.home ?? homedir14()), dataDir3 = resolve43(options.dataDir ?? getDataDirReadOnly());
124901
123687
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
124902
- const policyFile = snapshot(join79(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
123688
+ const policyFile = snapshot(join78(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
124903
123689
  const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
124904
123690
  const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
124905
- const physicalRoot = alias?.target ?? join79(home, ".codex"), hooksPath = join79(physicalRoot, "hooks.json"), configPath = join79(physicalRoot, "config.toml");
124906
- need8(options.codexHome === undefined || isAbsolute47(options.codexHome) && [join79(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
123691
+ const physicalRoot = alias?.target ?? join78(home, ".codex"), hooksPath = join78(physicalRoot, "hooks.json"), configPath = join78(physicalRoot, "config.toml");
123692
+ need8(options.codexHome === undefined || isAbsolute46(options.codexHome) && [join78(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
124907
123693
  const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
124908
- const nativeConfigPath = join79(codexHome ?? join79(home, ".codex"), "config.toml");
123694
+ const nativeConfigPath = join78(codexHome ?? join78(home, ".codex"), "config.toml");
124909
123695
  const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure3(configFile.text);
124910
123696
  const declarations = JSON.parse(hooksFile.text).hooks, expected = [];
124911
123697
  for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
@@ -124914,25 +123700,25 @@ async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
124914
123700
  need8(Array.isArray(groups), "DECLARATION_CHANGED");
124915
123701
  const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
124916
123702
  need8(matches2.length === 1 && isDeepStrictEqual22(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
124917
- expected.push({ event: nativeEvent, key: `${join79(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
123703
+ expected.push({ event: nativeEvent, key: `${join78(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
124918
123704
  }
124919
123705
  codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
124920
123706
  rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
124921
123707
  need8(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
124922
123708
  const list2 = async () => {
124923
123709
  const response = await rpc.request("hooks/list", { cwds: [home] });
124924
- const nativeRoots = [...new Set([physicalRoot, join79(home, ".codex")])];
124925
- const coexistenceWarnings = nativeRoots.flatMap((hooksRoot) => nativeRoots.map((configRoot) => `loading hooks from both ${join79(hooksRoot, "hooks.json")} and ${join79(configRoot, "config.toml")}; prefer a single representation for this layer`));
123710
+ const nativeRoots = [...new Set([physicalRoot, join78(home, ".codex")])];
123711
+ const coexistenceWarnings = nativeRoots.flatMap((hooksRoot) => nativeRoots.map((configRoot) => `loading hooks from both ${join78(hooksRoot, "hooks.json")} and ${join78(configRoot, "config.toml")}; prefer a single representation for this layer`));
124926
123712
  const entry = response?.data?.[0];
124927
123713
  need8(Array.isArray(response?.data) && response.data.length === 1 && entry.cwd === home && Array.isArray(entry.hooks) && entry.hooks.length <= 1e4 && Array.isArray(entry.errors) && entry.errors.length === 0 && Array.isArray(entry.warnings) && entry.warnings.length <= 1 && entry.warnings.every((warning) => typeof warning === "string" && coexistenceWarnings.includes(warning)), "NATIVE_DISCOVERY_REFUSED");
124928
123714
  return response.data[0].hooks;
124929
123715
  };
124930
123716
  const admit = (hooks) => expected.map((wanted) => {
124931
- const canonicalKey = wanted.key.replace(join79(home, ".codex/hooks.json"), hooksPath);
123717
+ const canonicalKey = wanted.key.replace(join78(home, ".codex/hooks.json"), hooksPath);
124932
123718
  const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
124933
123719
  need8(matches2.length === 1, "AMBIGUOUS_IDENTITY");
124934
123720
  const h = matches2[0];
124935
- need8(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join79(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
123721
+ need8(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join78(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
124936
123722
  need8(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
124937
123723
  need8(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
124938
123724
  return { key: h.key, event: wanted.event, command: wanted.command, handlerType: h.handlerType, timeoutSec: h.timeoutSec, sourcePath: h.sourcePath, currentHash: h.currentHash, enabled: h.enabled, trustStatus: h.trustStatus };
@@ -124958,7 +123744,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
124958
123744
  const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, nativeConfigPath, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, bindingRefreshRequired: false, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false, ...codexAdmissionReceipt(admission) };
124959
123745
  if (options.apply)
124960
123746
  need8(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
124961
- const parent = join79(dataDir3, "native-hook-trust");
123747
+ const parent = join78(dataDir3, "native-hook-trust");
124962
123748
  const st = lstatSync50(parent, { throwIfNoEntry: false });
124963
123749
  if (st) {
124964
123750
  need8(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
@@ -124966,19 +123752,19 @@ async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
124966
123752
  need8(priorJournals.length < 1000, "JOURNAL_BOUND");
124967
123753
  for (const name of priorJournals) {
124968
123754
  need8(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
124969
- need8(lstatSync50(join79(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
123755
+ need8(lstatSync50(join78(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
124970
123756
  }
124971
123757
  }
124972
123758
  if (!options.apply || !planned.length)
124973
123759
  return baseReceipt;
124974
123760
  if (!st)
124975
123761
  mkdirSync32(parent, { mode: 448 });
124976
- journal = join79(parent, randomUUID16());
123762
+ journal = join78(parent, randomUUID16());
124977
123763
  mkdirSync32(journal, { mode: 448 });
124978
- save(join79(journal, "config.before.toml"), configFile.bytes);
124979
- save(join79(journal, "hooks.before.json"), hooksFile.bytes);
124980
- save(join79(journal, "policy.before.json"), policyFile.bytes);
124981
- save(join79(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook), ...codexAdmissionReceipt(admission) }));
123764
+ save(join78(journal, "config.before.toml"), configFile.bytes);
123765
+ save(join78(journal, "hooks.before.json"), hooksFile.bytes);
123766
+ save(join78(journal, "policy.before.json"), policyFile.bytes);
123767
+ save(join78(journal, "intent.json"), json2({ ...digestInput, planDigest, hooks: planned, nativeHooks: discovered.map(safeNativeHook), ...codexAdmissionReceipt(admission) }));
124982
123768
  need8(isDeepStrictEqual22(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
124983
123769
  checkInputs();
124984
123770
  let result2;
@@ -124994,7 +123780,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
124994
123780
  for (const h of planned)
124995
123781
  expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
124996
123782
  need8(isDeepStrictEqual22(structure3(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys4) === preservationText, "PRESERVATION_FAILED");
124997
- const savedConfig = snapshot(join79(journal, "config.before.toml"), true);
123783
+ const savedConfig = snapshot(join78(journal, "config.before.toml"), true);
124998
123784
  need8(savedConfig.sha256 === configFile.sha256, "JOURNAL_CHANGED");
124999
123785
  const discoveryTransition = binding.discovery?.codex ? createCodexHookDiscoveryRecovery(binding.discovery.codex, savedConfig, after2, planned) : undefined;
125000
123786
  unchanged2(policyFile);
@@ -125010,13 +123796,13 @@ async function enrollCodexNativeHooksUnlocked(options, connect, admission) {
125010
123796
  skillsCli.recheck();
125011
123797
  assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home, codexDiscoveryRecovery: discoveryTransition });
125012
123798
  const receipt = { ...baseReceipt, applied: true, nativeEligible: true, bindingRefreshRequired: !!discoveryTransition, ...discoveryTransition ? { discoveryTransition } : {}, nativeConfigVersion: result2.version, journal, beforeSha256: configFile.sha256, afterSha256: after2.sha256, unrelatedSettingsAndCommentsPreserved: true };
125013
- save(join79(journal, "receipt.json"), json2(receipt));
123799
+ save(join78(journal, "receipt.json"), json2(receipt));
125014
123800
  return receipt;
125015
123801
  } catch (error61) {
125016
123802
  const message = error61 instanceof Error && error61.message.startsWith("CODEX_HOOK_TRUST_") ? error61.message : "CODEX_HOOK_TRUST_REFUSED: verify managed bridge installation and native Codex support";
125017
123803
  if (journal) {
125018
123804
  try {
125019
- save(join79(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true, ...codexAdmissionReceipt(admission) }));
123805
+ save(join78(journal, "stopped.json"), json2({ error: message.split(":")[0], automaticRollback: false, reconcileBeforeRetry: true, ...codexAdmissionReceipt(admission) }));
125020
123806
  } catch {}
125021
123807
  }
125022
123808
  throw new Error(message);
@@ -125050,8 +123836,8 @@ var init_agent_codex_trust = __esm(() => {
125050
123836
 
125051
123837
  // src/lib/codex-native-trust.ts
125052
123838
  import { createHash as createHash50 } from "crypto";
125053
- import { readFileSync as readFileSync48 } from "fs";
125054
- import { join as join80, resolve as resolve44 } from "path";
123839
+ import { readFileSync as readFileSync47 } from "fs";
123840
+ import { join as join79, resolve as resolve44 } from "path";
125055
123841
  function refuse7(detail) {
125056
123842
  throw new Error(`NATIVE_SKILL_POLICY_TRUST_REFUSED: ${detail}`);
125057
123843
  }
@@ -125070,7 +123856,7 @@ function planCodexNativeTrust(options) {
125070
123856
  refuse7("digests must be unique");
125071
123857
  if (typeof expectedPolicySha256 !== "string" || !HEX_DIGEST2.test(expectedPolicySha256))
125072
123858
  refuse7("--expected-policy-sha256 must be lowercase SHA-256 hex");
125073
- const dataDir3 = resolve44(options.dataDir ?? getDataDirReadOnly()), policyPath = join80(dataDir3, "agent-policy.json");
123859
+ const dataDir3 = resolve44(options.dataDir ?? getDataDirReadOnly()), policyPath = join79(dataDir3, "agent-policy.json");
125074
123860
  assertOperatorTrustRoot(dataDir3);
125075
123861
  const snapshot2 = readManagedSkillPolicySnapshot(dataDir3);
125076
123862
  if (!snapshot2)
@@ -125108,7 +123894,7 @@ function applyCodexNativeTrust(plan, expectedPolicySha256) {
125108
123894
  const backupPath = result2.backups[0];
125109
123895
  if (result2.backups.length !== 1 || typeof backupPath !== "string")
125110
123896
  throw new Error("NATIVE_SKILL_POLICY_TRUST_WRITE_UNVERIFIED: the pre-change backup was not recorded");
125111
- const backupSha256 = sha7(readFileSync48(backupPath));
123897
+ const backupSha256 = sha7(readFileSync47(backupPath));
125112
123898
  if (backupSha256 !== plan.policySha256Before)
125113
123899
  throw new Error(`NATIVE_SKILL_POLICY_TRUST_WRITE_UNVERIFIED: the backup at ${backupPath} does not read back as the pre-change policy`);
125114
123900
  receipt.backup = { path: backupPath, sha256: backupSha256, verified: true };
@@ -125135,8 +123921,8 @@ var init_codex_native_trust = __esm(() => {
125135
123921
 
125136
123922
  // src/lib/claude-prospective-review.ts
125137
123923
  import { createHash as createHash51 } from "crypto";
125138
- import { lstatSync as lstatSync51, readFileSync as readFileSync49, readdirSync as readdirSync29, realpathSync as realpathSync24 } from "fs";
125139
- import { basename as basename26, dirname as dirname52, isAbsolute as isAbsolute48, join as join81, relative as relative16, resolve as resolve45, sep as sep23 } from "path";
123924
+ import { lstatSync as lstatSync51, readFileSync as readFileSync48, readdirSync as readdirSync29, realpathSync as realpathSync24 } from "fs";
123925
+ import { basename as basename26, dirname as dirname52, isAbsolute as isAbsolute47, join as join80, relative as relative16, resolve as resolve45, sep as sep23 } from "path";
125140
123926
  import { isDeepStrictEqual as isDeepStrictEqual23 } from "util";
125141
123927
  function hashClaudeDiscoveryBinding(binding) {
125142
123928
  return sha8(JSON.stringify(binding));
@@ -125187,7 +123973,7 @@ function keys4(value, expected, name) {
125187
123973
  refuse8(`${name} has an unsupported shape`);
125188
123974
  }
125189
123975
  function abs(path2, name) {
125190
- if (typeof path2 !== "string" || !path2 || path2.length > 4096 || /[\x00-\x1f\x7f]/.test(path2) || !isAbsolute48(path2) || resolve45(path2) !== path2)
123976
+ if (typeof path2 !== "string" || !path2 || path2.length > 4096 || /[\x00-\x1f\x7f]/.test(path2) || !isAbsolute47(path2) || resolve45(path2) !== path2)
125191
123977
  refuse8(`${name} must be a normalized absolute path`);
125192
123978
  }
125193
123979
  function validUtcTimestamp(value) {
@@ -125205,7 +123991,7 @@ function safeFile(path2, name) {
125205
123991
  const stat3 = lstatSync51(path2, { throwIfNoEntry: false });
125206
123992
  if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_CANDIDATE_BYTES)
125207
123993
  refuse8(`${name} is not a bounded regular file`);
125208
- return readFileSync49(path2);
123994
+ return readFileSync48(path2);
125209
123995
  }
125210
123996
  function canonicalDir(path2, name) {
125211
123997
  abs(path2, name);
@@ -125231,7 +124017,7 @@ function captureClaudeProspectiveCandidateClosure(root2) {
125231
124017
  for (const name of names) {
125232
124018
  if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || /[\x00-\x1f\x7f]/.test(name))
125233
124019
  refuse8("candidate contains an unsupported path member");
125234
- const path2 = join81(directory3, name), rel = relative16(root2, path2).split(sep23).join("/");
124020
+ const path2 = join80(directory3, name), rel = relative16(root2, path2).split(sep23).join("/");
125235
124021
  if (entries.length >= MAX_CANDIDATE_FILES)
125236
124022
  refuse8("candidate closure exceeds its member limit");
125237
124023
  const stat3 = lstatSync51(path2);
@@ -125262,9 +124048,9 @@ function captureClaudeProspectiveCandidateClosure(root2) {
125262
124048
  function captureClaudeInstallerCandidate(root2, policyPath) {
125263
124049
  const closureSha256 = captureClaudeProspectiveCandidateClosure(root2);
125264
124050
  const dataDir3 = getDataDirReadOnly();
125265
- if (policyPath !== join81(dataDir3, "agent-policy.json"))
124051
+ if (policyPath !== join80(dataDir3, "agent-policy.json"))
125266
124052
  refuse8("Skills policy path differs from the package-owned resolver");
125267
- const catalogPath = join81(root2, ".claude-plugin/marketplace.json");
124053
+ const catalogPath = join80(root2, ".claude-plugin/marketplace.json");
125268
124054
  const catalog = jsonFile(catalogPath, "candidate catalog");
125269
124055
  if (!catalog || !Array.isArray(catalog.plugins))
125270
124056
  refuse8("candidate catalog is invalid");
@@ -125275,13 +124061,13 @@ function captureClaudeInstallerCandidate(root2, policyPath) {
125275
124061
  if (names.has(row2.name))
125276
124062
  refuse8("candidate catalog repeats a plugin name");
125277
124063
  names.add(row2.name);
125278
- if (typeof row2.source !== "string" || isAbsolute48(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
124064
+ if (typeof row2.source !== "string" || isAbsolute47(row2.source) || /[\\\x00-\x1f\x7f]/.test(row2.source))
125279
124065
  refuse8("candidate catalog plugin source is invalid");
125280
124066
  const pluginRoot = resolve45(root2, row2.source);
125281
124067
  const relativeRoot = relative16(root2, pluginRoot);
125282
- if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep23}`) || isAbsolute48(relativeRoot))
124068
+ if (!relativeRoot || relativeRoot === "." || relativeRoot === ".." || relativeRoot.startsWith(`..${sep23}`) || isAbsolute47(relativeRoot))
125283
124069
  refuse8("candidate plugin source escapes the candidate root");
125284
- const path2 = join81(pluginRoot, ".claude-plugin/plugin.json");
124070
+ const path2 = join80(pluginRoot, ".claude-plugin/plugin.json");
125285
124071
  return { plugin: row2.name, ...captureClaudePluginManifestFile(path2) };
125286
124072
  });
125287
124073
  const policy = readManagedSkillPolicySnapshot(dataDir3);
@@ -125381,7 +124167,7 @@ function assertNoUnprojectedSkillPayload(root2, catalogPath, marketplace, plugin
125381
124167
  refuse8("candidate marketplace entry declares native skill or command payloads");
125382
124168
  const walk2 = (directory3) => {
125383
124169
  for (const name of readdirSync29(directory3).sort()) {
125384
- const path2 = join81(directory3, name), rel = relative16(root2, path2).split(sep23).join("/");
124170
+ const path2 = join80(directory3, name), rel = relative16(root2, path2).split(sep23).join("/");
125385
124171
  const stat3 = lstatSync51(path2);
125386
124172
  if (stat3.isDirectory())
125387
124173
  walk2(path2);
@@ -125439,11 +124225,11 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125439
124225
  refuse8("Skills policy root alias changed or is invalid");
125440
124226
  }
125441
124227
  const canonical9 = (path2) => canonicalAgentPath(path2, aliases);
125442
- const configRoot = canonical9(join81(request2.native.home, ".claude"));
124228
+ const configRoot = canonical9(join80(request2.native.home, ".claude"));
125443
124229
  canonicalDir(configRoot, "Claude config root");
125444
124230
  if (request2.native.configRoot !== configRoot)
125445
124231
  refuse8("Claude config root differs from the current resolver and reviewed root alias");
125446
- const pluginRoot = join81(configRoot, "plugins");
124232
+ const pluginRoot = join80(configRoot, "plugins");
125447
124233
  if (process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR)
125448
124234
  refuse8("CLAUDE_CODE_PLUGIN_CACHE_DIR overrides are unsupported by this prospective schema; bind and review the actual cache root first");
125449
124235
  if (request2.native.pluginRoot !== pluginRoot)
@@ -125460,7 +124246,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125460
124246
  refuse8("candidate must select between one and 32 plugins from one marketplace");
125461
124247
  if (candidate2.functionHooksEnv !== undefined && candidate2.functionHooksEnv !== "1")
125462
124248
  refuse8("function-hook environment mutation only supports the explicit value 1");
125463
- const settingsMarketplaceWriterVersions = ["2.1.276", "2.1.278", "2.1.282", "2.1.287", "2.1.293", "2.1.296", "2.1.299", "2.1.300", "2.1.301", "2.1.302"];
124249
+ const settingsMarketplaceWriterVersions = ["2.1.276", "2.1.278", "2.1.282", "2.1.287", "2.1.293", "2.1.296", "2.1.299", "2.1.300", "2.1.301", "2.1.302", "2.1.314", "2.1.316"];
125464
124250
  const nativeVersion = request2.native.executable.version;
125465
124251
  const measuredSettingsWriter = settingsMarketplaceWriterVersions.some((version2) => nativeVersion === version2 || nativeVersion === `${version2} (Claude Code)`);
125466
124252
  if (hasOwn2(candidate2, "settingsMarketplaceSource") && (candidate2.settingsMarketplaceSource !== "directory" || request2.scope.kind !== "user" || !measuredSettingsWriter))
@@ -125468,7 +124254,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125468
124254
  abs(candidate2.catalogPath, "catalog path");
125469
124255
  if (!candidate2.catalogPath.startsWith(candidate2.root + sep23))
125470
124256
  refuse8("catalog must be inside the frozen candidate root");
125471
- if (candidate2.catalogPath !== join81(candidate2.root, ".claude-plugin", "marketplace.json"))
124257
+ if (candidate2.catalogPath !== join80(candidate2.root, ".claude-plugin", "marketplace.json"))
125472
124258
  refuse8("marketplace catalog must be at the frozen root's .claude-plugin/marketplace.json path");
125473
124259
  if (!SHA2562.test(candidate2.catalogSha256) || !SHA2562.test(candidate2.closureSha256))
125474
124260
  refuse8("candidate digests must be lowercase SHA-256");
@@ -125510,11 +124296,11 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125510
124296
  if (Buffer.byteLength(canonicalJson3(selected.optionsPatch), "utf8") > 16 * 1024)
125511
124297
  refuse8("selected plugin optionsPatch exceeds its byte bound");
125512
124298
  abs(selected.manifestPath, "manifest path");
125513
- if (!selected.manifestPath.startsWith(candidate2.root + sep23) || basename26(dirname52(selected.manifestPath)) !== ".claude-plugin" || selected.manifestPath !== join81(dirname52(dirname52(selected.manifestPath)), ".claude-plugin", "plugin.json"))
124299
+ if (!selected.manifestPath.startsWith(candidate2.root + sep23) || basename26(dirname52(selected.manifestPath)) !== ".claude-plugin" || selected.manifestPath !== join80(dirname52(dirname52(selected.manifestPath)), ".claude-plugin", "plugin.json"))
125514
124300
  refuse8("plugin manifest must be under a plugin root inside the frozen marketplace closure");
125515
124301
  const pluginRoot2 = dirname52(dirname52(selected.manifestPath));
125516
124302
  const relativePluginRoot = relative16(candidate2.root, pluginRoot2);
125517
- if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep23}`) || isAbsolute48(relativePluginRoot))
124303
+ if (!relativePluginRoot || relativePluginRoot === "." || relativePluginRoot === ".." || relativePluginRoot.startsWith(`..${sep23}`) || isAbsolute47(relativePluginRoot))
125518
124304
  refuse8("plugin root must be a child of the frozen marketplace root");
125519
124305
  canonicalDir(pluginRoot2, "candidate plugin root");
125520
124306
  if (!SHA2562.test(selected.manifestSha256))
@@ -125548,7 +124334,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125548
124334
  const sourcePath = selectedEntry.source;
125549
124335
  const sourceRelativePath = relative16(candidate2.root, pluginRoot2).split(sep23).join("/");
125550
124336
  const expectedSourcePath = sourceRelativePath === "." ? "./" : `./${sourceRelativePath}`;
125551
- if (typeof sourcePath !== "string" || isAbsolute48(sourcePath) || sourcePath !== expectedSourcePath || resolve45(dirname52(dirname52(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
124337
+ if (typeof sourcePath !== "string" || isAbsolute47(sourcePath) || sourcePath !== expectedSourcePath || resolve45(dirname52(dirname52(candidate2.catalogPath)), sourcePath) !== pluginRoot2)
125552
124338
  refuse8("marketplace source does not resolve to the frozen plugin closure; external source mapping is not supported by this schema");
125553
124339
  const entry = captureClaudeMarketplaceEntry(candidate2.catalogPath, candidate2.marketplace, selected.plugin);
125554
124340
  if (entry.sha256.length !== 64)
@@ -125568,12 +124354,12 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125568
124354
  for (const name of ["settings", "projectSettings", "projectSettingsLocal", "marketplaces", "installedPlugins"])
125569
124355
  keys4(request2.preimages[name], ["path", "sha256"], `${name} preimage`);
125570
124356
  const expectedPaths = {
125571
- settings: request2.scope.kind === "project" ? canonical9(join81(request2.scope.projectPath, ".claude/settings.json")) : canonical9(join81(request2.native.home, ".claude/settings.json")),
125572
- userSettings: canonical9(join81(request2.native.home, ".claude/settings.json")),
125573
- projectSettings: canonical9(join81(request2.scope.projectPath, ".claude/settings.json")),
125574
- projectSettingsLocal: canonical9(join81(request2.scope.projectPath, ".claude/settings.local.json")),
125575
- marketplaces: canonical9(join81(request2.native.home, ".claude/plugins/known_marketplaces.json")),
125576
- installedPlugins: canonical9(join81(request2.native.home, ".claude/plugins/installed_plugins.json"))
124357
+ settings: request2.scope.kind === "project" ? canonical9(join80(request2.scope.projectPath, ".claude/settings.json")) : canonical9(join80(request2.native.home, ".claude/settings.json")),
124358
+ userSettings: canonical9(join80(request2.native.home, ".claude/settings.json")),
124359
+ projectSettings: canonical9(join80(request2.scope.projectPath, ".claude/settings.json")),
124360
+ projectSettingsLocal: canonical9(join80(request2.scope.projectPath, ".claude/settings.local.json")),
124361
+ marketplaces: canonical9(join80(request2.native.home, ".claude/plugins/known_marketplaces.json")),
124362
+ installedPlugins: canonical9(join80(request2.native.home, ".claude/plugins/installed_plugins.json"))
125577
124363
  };
125578
124364
  for (const name of Object.keys(expectedPaths)) {
125579
124365
  const witness = request2.preimages[name];
@@ -125706,7 +124492,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125706
124492
  const manifestVersion = manifest.version;
125707
124493
  const sanitizeComponent = (value) => value.replace(/[^A-Za-z0-9_-]/g, "-");
125708
124494
  const sanitizedVersion = manifestVersion === "." || manifestVersion === ".." ? "-" : manifestVersion.replace(/[^A-Za-z0-9._-]/g, "-");
125709
- const expectedInstallPath = join81(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
124495
+ const expectedInstallPath = join80(pluginRoot, "cache", sanitizeComponent(candidate2.marketplace), sanitizeComponent(plugin), sanitizedVersion);
125710
124496
  if (expectedInstallPath.length > 4096)
125711
124497
  refuse8("candidate native cache path exceeds its bound");
125712
124498
  const targetRegistration = {
@@ -125845,7 +124631,7 @@ function reviewClaudeProspectiveCandidate(request2, requestFileSha256) {
125845
124631
  { name: "project-settings-local", path: expectedPaths.projectSettingsLocal, sha256: request2.preimages.projectSettingsLocal.sha256 },
125846
124632
  { name: "known-marketplaces", path: expectedPaths.marketplaces, sha256: request2.preimages.marketplaces.sha256 },
125847
124633
  { name: "installed-plugins", path: expectedPaths.installedPlugins, sha256: request2.preimages.installedPlugins.sha256 },
125848
- { name: "skills-policy", path: join81(request2.skills.dataDir, "agent-policy.json"), sha256: request2.skills.policySha256 }
124634
+ { name: "skills-policy", path: join80(request2.skills.dataDir, "agent-policy.json"), sha256: request2.skills.policySha256 }
125849
124635
  ],
125850
124636
  ownedDelta: { settingsEnabledPlugins: selectedPluginIds, selectedPluginOptions: selectedOptionPaths, functionHooksEnv: candidate2.functionHooksEnv ?? null, knownMarketplace: candidate2.marketplace, installedPlugins: selectedPluginIds, unrelatedGraph: "preserved-by-complete-semantic-documents" },
125851
124637
  identityPrecondition: "Harnesses must resolve the installed Claude home/config/plugin roots and executable path/version/hash plus the installed Skills data directory through their package-owned consumers, then compare every value before trusting this receipt; this validator checks supplied paths and current bytes only and does not establish actual consumer identity",
@@ -125887,7 +124673,7 @@ var init_claude_prospective_review = __esm(() => {
125887
124673
 
125888
124674
  // src/lib/codex-plugin-reconcile.ts
125889
124675
  import { realpathSync as realpathSync25 } from "fs";
125890
- import { join as join82, resolve as resolve46 } from "path";
124676
+ import { join as join81, resolve as resolve46 } from "path";
125891
124677
  function boundedMessage(text5) {
125892
124678
  const line = text5.replace(/[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g, " ").trim();
125893
124679
  return line.length > 800 ? `${line.slice(0, 797)}...` : line;
@@ -125930,11 +124716,11 @@ async function runCodexPluginReconcile(options) {
125930
124716
  return resolve46(path2);
125931
124717
  }
125932
124718
  };
125933
- if (canonical9(options.codexHome) !== canonical9(join82(home, ".codex")))
124719
+ if (canonical9(options.codexHome) !== canonical9(join81(home, ".codex")))
125934
124720
  throw new CodexPluginReconcileRefusal("CODEX_RECONCILE_CODEX_HOME_UNSUPPORTED", "CODEX_HOME names a Codex home other than the one the Skills binding reviews");
125935
124721
  }
125936
124722
  const capture2 = options.captureCatalog ?? captureCodexNativeSkillCatalog;
125937
- const remoteReceipts = captureCodexRemoteReceiptSnapshot(join82(home, ".codex/plugins/cache"));
124723
+ const remoteReceipts = captureCodexRemoteReceiptSnapshot(join81(home, ".codex/plugins/cache"));
125938
124724
  const captured = await capture2({ command: options.codexCommand ?? "codex", home, ...options.codexHome === undefined ? {} : { codexHome: options.codexHome }, cwd: projectDir });
125939
124725
  const catalog = captured && typeof captured === "object" ? { ...captured, remoteReceipts } : captured;
125940
124726
  base3.codexVersion = typeof catalog?.version === "string" ? catalog.version : null;
@@ -125996,7 +124782,7 @@ var init_codex_plugin_reconcile = __esm(() => {
125996
124782
 
125997
124783
  // src/lib/claude-installer-binding.ts
125998
124784
  import { createHash as createHash52 } from "crypto";
125999
- import { join as join83 } from "path";
124785
+ import { join as join82 } from "path";
126000
124786
  function readPolicy(dataDir3) {
126001
124787
  let snapshot2;
126002
124788
  try {
@@ -126008,7 +124794,7 @@ function readPolicy(dataDir3) {
126008
124794
  }
126009
124795
  function verifyClaudeInstallerDiscoveryBinding(policyPath) {
126010
124796
  const dataDir3 = getDataDirReadOnly();
126011
- if (policyPath !== join83(dataDir3, "agent-policy.json"))
124797
+ if (policyPath !== join82(dataDir3, "agent-policy.json"))
126012
124798
  refuse9("POLICY_PATH_MISMATCH");
126013
124799
  const snapshot2 = readPolicy(dataDir3);
126014
124800
  const bridge = snapshot2.value.bridge;
@@ -126087,8 +124873,8 @@ var init_claude_installer_binding = __esm(() => {
126087
124873
  });
126088
124874
 
126089
124875
  // src/cli/commands/claude-installer-capture.ts
126090
- import { closeSync as closeSync34, constants as constants33, fstatSync as fstatSync33, lstatSync as lstatSync52, openSync as openSync34, readSync as readSync25 } from "fs";
126091
- import { isAbsolute as isAbsolute49, resolve as resolve47 } from "path";
124876
+ import { closeSync as closeSync33, constants as constants33, fstatSync as fstatSync32, lstatSync as lstatSync52, openSync as openSync33, readSync as readSync25 } from "fs";
124877
+ import { isAbsolute as isAbsolute48, resolve as resolve47 } from "path";
126092
124878
  function need11(condition, code2) {
126093
124879
  if (!condition)
126094
124880
  throw new CaptureRefusal(code2);
@@ -126102,16 +124888,16 @@ function exactKeys5(value, expected, operation) {
126102
124888
  }
126103
124889
  }
126104
124890
  function canonicalPath2(value) {
126105
- need11(typeof value === "string" && isAbsolute49(value) && resolve47(value) === value && !/[\x00-\x1f\x7f]/.test(value), "INVALID_PATH: path fields must be normalized absolute paths without control characters");
124891
+ need11(typeof value === "string" && isAbsolute48(value) && resolve47(value) === value && !/[\x00-\x1f\x7f]/.test(value), "INVALID_PATH: path fields must be normalized absolute paths without control characters");
126106
124892
  }
126107
124893
  function readRequest2(path2) {
126108
124894
  canonicalPath2(path2);
126109
124895
  const before2 = lstatSync52(path2, { throwIfNoEntry: false });
126110
124896
  if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
126111
124897
  throw new CaptureRefusal("INVALID_REQUEST_FILE: --request must name a regular non-symlink JSON file no larger than 64 KiB");
126112
- const fd = openSync34(path2, constants33.O_RDONLY | (constants33.O_NOFOLLOW ?? 0) | constants33.O_NONBLOCK);
124898
+ const fd = openSync33(path2, constants33.O_RDONLY | (constants33.O_NOFOLLOW ?? 0) | constants33.O_NONBLOCK);
126113
124899
  try {
126114
- const opened = fstatSync33(fd);
124900
+ const opened = fstatSync32(fd);
126115
124901
  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");
126116
124902
  const bytes = Buffer.alloc(MAX_REQUEST_BYTES + 1);
126117
124903
  let length = 0;
@@ -126121,7 +124907,7 @@ function readRequest2(path2) {
126121
124907
  break;
126122
124908
  length += count;
126123
124909
  }
126124
- const after2 = fstatSync33(fd), current = lstatSync52(path2);
124910
+ const after2 = fstatSync32(fd), current = lstatSync52(path2);
126125
124911
  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");
126126
124912
  try {
126127
124913
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
@@ -126129,7 +124915,7 @@ function readRequest2(path2) {
126129
124915
  throw new CaptureRefusal("INVALID_REQUEST_JSON: --request must contain one valid UTF-8 JSON object");
126130
124916
  }
126131
124917
  } finally {
126132
- closeSync34(fd);
124918
+ closeSync33(fd);
126133
124919
  }
126134
124920
  }
126135
124921
  function paths(value) {
@@ -126283,10 +125069,10 @@ __export(exports_agent_integration, {
126283
125069
  MANAGED_HOOK_CONTEXT_MAX_SKILLS: () => MANAGED_HOOK_CONTEXT_MAX_SKILLS,
126284
125070
  MANAGED_HOOK_CONTEXT_MAX_CHARS: () => MANAGED_HOOK_CONTEXT_MAX_CHARS
126285
125071
  });
126286
- import { existsSync as existsSync36, lstatSync as lstatSync53, readFileSync as readFileSync50, readSync as readSync26, writeFileSync as writeFileSync29 } from "fs";
125072
+ import { existsSync as existsSync36, lstatSync as lstatSync53, readFileSync as readFileSync49, readSync as readSync26, writeFileSync as writeFileSync29 } from "fs";
126287
125073
  import { createHash as createHash53 } from "crypto";
126288
125074
  import { homedir as homedir15 } from "os";
126289
- import { basename as basename27, isAbsolute as isAbsolute50, resolve as resolve48 } from "path";
125075
+ import { basename as basename27, isAbsolute as isAbsolute49, resolve as resolve48 } from "path";
126290
125076
  function boundedEnvInteger(name, fallback, [min2, max2]) {
126291
125077
  const raw = process.env[name];
126292
125078
  if (raw === undefined || !/^[0-9]{1,6}$/.test(raw.trim()))
@@ -126470,7 +125256,7 @@ function registerAgentIntegration(parent) {
126470
125256
  });
126471
125257
  hook.command("native-catalog").requiredOption("--cwd <path>", "Absolute project directory observed by native Codex skills/list").requiredOption("--output <file>", "New private file for the projected native catalog").option("--codex-command <path>", "Installed Codex executable used by the native client", "codex").option("--json", "Output bounded capture metadata as JSON", false).description("Capture a reviewed Codex native skill catalog for exact hook enrollment").action(async (options) => {
126472
125258
  try {
126473
- if (!isAbsolute50(options.cwd) || !isAbsolute50(options.output))
125259
+ if (!isAbsolute49(options.cwd) || !isAbsolute49(options.output))
126474
125260
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
126475
125261
  if (existsSync36(options.output))
126476
125262
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
@@ -126495,7 +125281,7 @@ function registerAgentIntegration(parent) {
126495
125281
  throw error61;
126496
125282
  }
126497
125283
  const written = lstatSync53(options.output);
126498
- if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync50(options.output, "utf8") !== bytes)
125284
+ if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync49(options.output, "utf8") !== bytes)
126499
125285
  throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
126500
125286
  const receipt = {
126501
125287
  version: catalog.version,
@@ -126572,12 +125358,12 @@ function registerAgentIntegration(parent) {
126572
125358
  });
126573
125359
  hook.command("review-claude-candidate").requiredOption("--request <file>", "Frozen skills.claude-plugin-prospective-review/v1 JSON request").option("--json", "Return the validation-only receipt as JSON", false).description("Validate a prospective Claude plugin candidate and current preimages without changing native state; Harnesses must compare native and Skills paths against installed package-owned resolvers before trusting the receipt").action(async (options) => {
126574
125360
  try {
126575
- if (!isAbsolute50(options.request))
125361
+ if (!isAbsolute49(options.request))
126576
125362
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: --request must be an absolute path");
126577
125363
  const stat3 = lstatSync53(options.request);
126578
125364
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > 1024 * 1024)
126579
125365
  throw new Error("CLAUDE_CANDIDATE_REVIEW_REFUSED: request must be a regular file no larger than 1 MiB");
126580
- const requestBytes = readFileSync50(options.request);
125366
+ const requestBytes = readFileSync49(options.request);
126581
125367
  const request2 = JSON.parse(requestBytes.toString("utf8"));
126582
125368
  const receipt = reviewClaudeProspectiveCandidate(request2, createHash53("sha256").update(requestBytes).digest("hex"));
126583
125369
  await writeCliOutput(options.json ? JSON.stringify(receipt) : `Claude plugin candidate review accepted for ${receipt.pluginIds.length} selected plugin(s); native state was not changed.`);
@@ -126651,8 +125437,8 @@ function registerAgentIntegration(parent) {
126651
125437
  });
126652
125438
  hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all (default: configured or detected agents; explicit all requires every adapter)`).option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-skill-denials <file>", "Explicit reviewed remote skill denials: array of exact name, path and document sha256; requires fresh catalog and discovery inputs").option("--codex-native-catalog <file>", "Reviewed supported Codex skill and installed-plugin receipt for exact qualified-name disables").option("--reviewed-cache-alias <path>", "Exact skill-containing vendor cache alias reviewed for this hook plan").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
126653
125439
  try {
126654
- const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync50(options.discoveryInputs, "utf8")) : undefined;
126655
- const plan = planAgentIntegration({ projectDir: process.cwd(), agents: options.agent === undefined ? detectedIntegrationAgents() : agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexSkillDenials: options.codexSkillDenials ? JSON.parse(readFileSync50(options.codexSkillDenials, "utf8")) : undefined, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync50(options.codexNativeCatalog, "utf8")) : undefined });
125440
+ const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync49(options.discoveryInputs, "utf8")) : undefined;
125441
+ const plan = planAgentIntegration({ projectDir: process.cwd(), agents: options.agent === undefined ? detectedIntegrationAgents() : agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexSkillDenials: options.codexSkillDenials ? JSON.parse(readFileSync49(options.codexSkillDenials, "utf8")) : undefined, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync49(options.codexNativeCatalog, "utf8")) : undefined });
126656
125442
  const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
126657
125443
  const receipt = { codexPluginSkillReview: plan.codexPluginSkillReview, codexPluginSkills: plan.changes.filter((change) => change.path.endsWith("agent-policy.json")).map((change) => JSON.parse(change.after).bridge?.codexPluginSkills ?? []).flat(), applied: options.apply, planned: plan.changes.map((change) => change.path), ...result2, rootAliases: plan.rootAliases ?? [], discovery: plan.discoveryAfter, nativeSkills: plan.nativeSkills.map((entry) => ({ agent: entry.agent, path: entry.path, managed: entry.managed, vendor: entry.vendor, system: entry.system === true, bridge: entry.bridge === true })), requiresNativeRetirement: plan.nativeSkills.some((entry) => !entry.bridge && !entry.system) };
126658
125444
  if (options.json)
@@ -126714,7 +125500,7 @@ function registerAgentIntegration(parent) {
126714
125500
  try {
126715
125501
  if (agents(options.agent).length !== 1)
126716
125502
  throw new Error("A hook invocation requires one agent");
126717
- const inputBytes = readFileSync50(0), inputText = inputBytes.toString("utf8");
125503
+ const inputBytes = readFileSync49(0), inputText = inputBytes.toString("utf8");
126718
125504
  if (inputText.length > 1024 * 1024)
126719
125505
  throw new Error("Hook input is too large");
126720
125506
  let input3 = JSON.parse(inputText);
@@ -126727,12 +125513,12 @@ function registerAgentIntegration(parent) {
126727
125513
  input3.hook_event_name = event;
126728
125514
  const projects = [process.cwd()];
126729
125515
  if (input3.cwd !== undefined) {
126730
- if (typeof input3.cwd !== "string" || !isAbsolute50(input3.cwd) || input3.cwd.includes("\x00"))
125516
+ if (typeof input3.cwd !== "string" || !isAbsolute49(input3.cwd) || input3.cwd.includes("\x00"))
126731
125517
  throw new Error("Invalid native hook working directory");
126732
125518
  projects.push(input3.cwd);
126733
125519
  }
126734
125520
  if (options.agent === "cursor") {
126735
- if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path2) => typeof path2 !== "string" || !isAbsolute50(path2) || path2.includes("\x00")))
125521
+ if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path2) => typeof path2 !== "string" || !isAbsolute49(path2) || path2.includes("\x00")))
126736
125522
  throw new Error("Invalid Cursor workspace roots");
126737
125523
  projects.push(...input3.workspace_roots);
126738
125524
  input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
@@ -126880,7 +125666,7 @@ ${driftWarning}` : unavailable2, ...output2 }));
126880
125666
  try {
126881
125667
  if (options.agent && !INTEGRATION_AGENTS.includes(options.agent))
126882
125668
  throw new Error(`Unsupported migration agent: ${options.agent}`);
126883
- const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync50(options.discoveryInputs, "utf8")) : undefined;
125669
+ const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync49(options.discoveryInputs, "utf8")) : undefined;
126884
125670
  if (options.targetManifest && (options.includeUnmanaged || options.includeVendor))
126885
125671
  throw new Error("--target-manifest cannot be combined with broad native migration selectors");
126886
125672
  const targetManifest = options.targetManifest ? readNativeMigrationTargetManifest(options.targetManifest) : undefined;
@@ -127075,11 +125861,11 @@ var exports_profiles = {};
127075
125861
  __export(exports_profiles, {
127076
125862
  registerProfiles: () => registerProfiles
127077
125863
  });
127078
- import { closeSync as closeSync35, constants as constants34, fstatSync as fstatSync34, openSync as openSync35, readSync as readSync27, writeFileSync as writeFileSync30 } from "fs";
125864
+ import { closeSync as closeSync34, constants as constants34, fstatSync as fstatSync33, openSync as openSync34, readSync as readSync27, writeFileSync as writeFileSync30 } from "fs";
127079
125865
  function readProfileInput(path2) {
127080
- const fd = openSync35(path2, constants34.O_RDONLY | constants34.O_NONBLOCK);
125866
+ const fd = openSync34(path2, constants34.O_RDONLY | constants34.O_NONBLOCK);
127081
125867
  try {
127082
- const stat3 = fstatSync34(fd);
125868
+ const stat3 = fstatSync33(fd);
127083
125869
  if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
127084
125870
  throw new Error("Profile input exceeds the size limit or is not a regular file");
127085
125871
  const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
@@ -127094,7 +125880,7 @@ function readProfileInput(path2) {
127094
125880
  throw new Error("Profile input exceeds the size limit");
127095
125881
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
127096
125882
  } finally {
127097
- closeSync35(fd);
125883
+ closeSync34(fd);
127098
125884
  }
127099
125885
  }
127100
125886
  function registerProfiles(parent) {
@@ -127509,16 +126295,16 @@ __export(exports_grants, {
127509
126295
  });
127510
126296
  import {
127511
126297
  constants as constants35,
127512
- closeSync as closeSync36,
127513
- fstatSync as fstatSync35,
127514
- openSync as openSync36,
126298
+ closeSync as closeSync35,
126299
+ fstatSync as fstatSync34,
126300
+ openSync as openSync35,
127515
126301
  readSync as readSync28,
127516
126302
  writeFileSync as writeFileSync31
127517
126303
  } from "fs";
127518
126304
  function readInput(path2) {
127519
- const fd = openSync36(path2, constants35.O_RDONLY | constants35.O_NONBLOCK);
126305
+ const fd = openSync35(path2, constants35.O_RDONLY | constants35.O_NONBLOCK);
127520
126306
  try {
127521
- const stat3 = fstatSync35(fd);
126307
+ const stat3 = fstatSync34(fd);
127522
126308
  if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
127523
126309
  throw new Error("Grant input must be a regular file within the policy size limit.");
127524
126310
  const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
@@ -127537,7 +126323,7 @@ function readInput(path2) {
127537
126323
  throw new Error("Grant input must be a JSON document containing a grants array.");
127538
126324
  }
127539
126325
  } finally {
127540
- closeSync36(fd);
126326
+ closeSync35(fd);
127541
126327
  }
127542
126328
  }
127543
126329
  function registerGrants(parent) {
@@ -127578,23 +126364,23 @@ import {
127578
126364
  copyFileSync as copyFileSync3,
127579
126365
  mkdirSync as mkdirSync33,
127580
126366
  readdirSync as readdirSync30,
127581
- readFileSync as readFileSync51,
126367
+ readFileSync as readFileSync50,
127582
126368
  statSync as statSync26,
127583
126369
  writeFileSync as writeFileSync32
127584
126370
  } from "fs";
127585
- import { dirname as dirname53, join as join84, resolve as resolve49, sep as sep24 } from "path";
126371
+ import { dirname as dirname53, join as join83, resolve as resolve49, sep as sep24 } from "path";
127586
126372
  function fail7(code2, message, detail = []) {
127587
126373
  throw new StationSnapshotError(code2, message, detail);
127588
126374
  }
127589
126375
  function snapshotRootFor(repoRoot, stationId) {
127590
- return join84(repoRoot, "resources", stationId, "skills");
126376
+ return join83(repoRoot, "resources", stationId, "skills");
127591
126377
  }
127592
126378
  function readSnapshotManifest(repoRoot, stationId) {
127593
126379
  const snapshotRoot = snapshotRootFor(repoRoot, stationId);
127594
- const manifestPath = join84(snapshotRoot, "sync-manifest.json");
126380
+ const manifestPath = join83(snapshotRoot, "sync-manifest.json");
127595
126381
  let manifest;
127596
126382
  try {
127597
- manifest = JSON.parse(readFileSync51(manifestPath, "utf8"));
126383
+ manifest = JSON.parse(readFileSync50(manifestPath, "utf8"));
127598
126384
  } catch (error61) {
127599
126385
  fail7("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
127600
126386
  }
@@ -127618,7 +126404,7 @@ function planStationHydration(stationId, repoRoot) {
127618
126404
  const hashMismatches = [];
127619
126405
  const skippedByRule = [];
127620
126406
  for (const agent of SYNC_AGENTS) {
127621
- const agentRoot = join84(snapshotRoot, "agent-homes", agent);
126407
+ const agentRoot = join83(snapshotRoot, "agent-homes", agent);
127622
126408
  let identEntries;
127623
126409
  try {
127624
126410
  identEntries = readdirSync30(agentRoot, { withFileTypes: true });
@@ -127629,7 +126415,7 @@ function planStationHydration(stationId, repoRoot) {
127629
126415
  if (!identEntry.isDirectory() || identEntry.name.startsWith(".")) {
127630
126416
  continue;
127631
126417
  }
127632
- const identRoot = join84(agentRoot, identEntry.name);
126418
+ const identRoot = join83(agentRoot, identEntry.name);
127633
126419
  const entries = walkEntries(identRoot);
127634
126420
  for (const entry of entries) {
127635
126421
  const relativeParts = [identEntry.name, ...entry.relativePath.split(sep24)];
@@ -127730,7 +126516,7 @@ function planStationHydration(stationId, repoRoot) {
127730
126516
  for (const copy of copies) {
127731
126517
  let isStub = false;
127732
126518
  try {
127733
- isStub = isPointerSkillMd(readFileSync51(copy.fullPath, "utf8"));
126519
+ isStub = isPointerSkillMd(readFileSync50(copy.fullPath, "utf8"));
127734
126520
  } catch {
127735
126521
  isStub = false;
127736
126522
  }
@@ -127814,7 +126600,7 @@ function writeStationHydration(options) {
127814
126600
  const toWrite = [];
127815
126601
  for (const skill of plan.winners) {
127816
126602
  for (const file2 of skill.files) {
127817
- const destination = join84(cacheRoot, skill.ident, file2.withinIdent);
126603
+ const destination = join83(cacheRoot, skill.ident, file2.withinIdent);
127818
126604
  const digest7 = sha256File(file2.winner.fullPath);
127819
126605
  let existingDigest = null;
127820
126606
  try {
@@ -127856,7 +126642,7 @@ function writeStationHydration(options) {
127856
126642
  },
127857
126643
  skills: resultSkills
127858
126644
  };
127859
- const hydrationManifestPath = join84(dirname53(cacheRoot), `hydration-${options.stationId}.json`);
126645
+ const hydrationManifestPath = join83(dirname53(cacheRoot), `hydration-${options.stationId}.json`);
127860
126646
  mkdirSync33(dirname53(hydrationManifestPath), { recursive: true });
127861
126647
  writeFileSync32(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
127862
126648
  `);
@@ -127934,14 +126720,14 @@ var init_hydrate = __esm(() => {
127934
126720
 
127935
126721
  // src/lib/prepare-skill.ts
127936
126722
  import { createHash as createHash55, randomUUID as randomUUID17 } from "crypto";
127937
- import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync54, mkdirSync as mkdirSync34, mkdtempSync as mkdtempSync7, readFileSync as readFileSync52, readdirSync as readdirSync31, renameSync as renameSync18, rmSync as rmSync10, writeFileSync as writeFileSync33 } from "fs";
126723
+ import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync54, mkdirSync as mkdirSync34, mkdtempSync as mkdtempSync7, readFileSync as readFileSync51, readdirSync as readdirSync31, renameSync as renameSync18, rmSync as rmSync10, writeFileSync as writeFileSync33 } from "fs";
127938
126724
  import { tmpdir as tmpdir2 } from "os";
127939
- import { dirname as dirname54, isAbsolute as isAbsolute51, join as join85, relative as relative17, resolve as resolve50, sep as sep25 } from "path";
126725
+ import { dirname as dirname54, isAbsolute as isAbsolute50, join as join84, relative as relative17, resolve as resolve50, sep as sep25 } from "path";
127940
126726
  function prepareSkill(name, options) {
127941
126727
  const normalized2 = normalizePortableSkillName(name);
127942
126728
  if (!new RegExp(SEMVER_PATTERN).test(options.version))
127943
126729
  throw new Error("--version must be a semantic version, for example 0.2.0.");
127944
- const path2 = join85(getPortableSkillsRootReadOnly(options), normalized2);
126730
+ const path2 = join84(getPortableSkillsRootReadOnly(options), normalized2);
127945
126731
  assertPortableAuthoringPath(path2, options);
127946
126732
  const before2 = snapshot2(path2);
127947
126733
  const manifestFile = before2.files.find((file2) => file2.path === "skill.json");
@@ -127976,16 +126762,16 @@ function prepareSkill(name, options) {
127976
126762
  throw new Error("skill.json provenance must be an object.");
127977
126763
  const provenance = manifest.provenance;
127978
126764
  const candidate2 = { ...manifest, version: options.version, kind, provenance: { ...provenance } };
127979
- const staging = mkdtempSync7(join85(tmpdir2(), "skills-prepare-"));
126765
+ const staging = mkdtempSync7(join84(tmpdir2(), "skills-prepare-"));
127980
126766
  try {
127981
126767
  for (const directory3 of before2.directories)
127982
- mkdirSync34(join85(staging, directory3), { recursive: true });
126768
+ mkdirSync34(join84(staging, directory3), { recursive: true });
127983
126769
  for (const file2 of before2.files) {
127984
- const destination = join85(staging, file2.path);
126770
+ const destination = join84(staging, file2.path);
127985
126771
  mkdirSync34(dirname54(destination), { recursive: true });
127986
126772
  writeFileSync33(destination, file2.bytes, { mode: file2.mode });
127987
126773
  }
127988
- const stagedManifest = join85(staging, "skill.json");
126774
+ const stagedManifest = join84(staging, "skill.json");
127989
126775
  writeFileSync33(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
127990
126776
  `);
127991
126777
  const contentHash = computeContentHash(staging);
@@ -128008,11 +126794,11 @@ ${validation.issues.map((issue2) => `${issue2.code}: ${issue2.message}`).join(`
128008
126794
  if (snapshot2(path2).identity !== before2.identity)
128009
126795
  throw new Error("Skill changed during preparation; review the draft and run prepare again.");
128010
126796
  if (changed3 && !options.dryRun) {
128011
- const temporary = join85(path2, `.skill-prepare-${randomUUID17()}.tmp`);
126797
+ const temporary = join84(path2, `.skill-prepare-${randomUUID17()}.tmp`);
128012
126798
  try {
128013
126799
  writeFileSync33(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
128014
126800
  chmodSync5(temporary, manifestFile.mode);
128015
- renameSync18(temporary, join85(path2, "skill.json"));
126801
+ renameSync18(temporary, join84(path2, "skill.json"));
128016
126802
  } finally {
128017
126803
  rmSync10(temporary, { force: true });
128018
126804
  }
@@ -128043,7 +126829,7 @@ function validateRuntimeEntrypoint(candidate2, root2) {
128043
126829
  if (typeof entry !== "string")
128044
126830
  return;
128045
126831
  const target = resolve50(root2, entry), rel = relative17(root2, target);
128046
- if (isAbsolute51(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep25}`) || isAbsolute51(rel) || !existsSync37(target) || !lstatSync54(target).isFile()) {
126832
+ if (isAbsolute50(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep25}`) || isAbsolute50(rel) || !existsSync37(target) || !lstatSync54(target).isFile()) {
128047
126833
  throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
128048
126834
  }
128049
126835
  }
@@ -128135,13 +126921,13 @@ function snapshot2(root2) {
128135
126921
  const hash8 = createHash55("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
128136
126922
  let count = 0, bytes = 0;
128137
126923
  const walk2 = (relative18) => {
128138
- for (const name of readdirSync31(join85(root2, relative18)).sort()) {
126924
+ for (const name of readdirSync31(join84(root2, relative18)).sort()) {
128139
126925
  if (IGNORED.has(name.toLowerCase()) || !relative18 && ROOT_IGNORED.has(name.toLowerCase()))
128140
126926
  continue;
128141
126927
  const path2 = relative18 ? `${relative18}/${name}` : name;
128142
126928
  if (++count > 20000)
128143
126929
  throw new Error("Skill exceeds the preparation entry limit (20000).");
128144
- const absolute = join85(root2, path2), stat3 = lstatSync54(absolute);
126930
+ const absolute = join84(root2, path2), stat3 = lstatSync54(absolute);
128145
126931
  if (stat3.isSymbolicLink())
128146
126932
  throw new Error(`Skill contains a symlink: ${path2}. No files were changed.`);
128147
126933
  if (stat3.isDirectory() && name === "node_modules")
@@ -128154,7 +126940,7 @@ function snapshot2(root2) {
128154
126940
  bytes += stat3.size;
128155
126941
  if (bytes > 50000000)
128156
126942
  throw new Error("Skill exceeds the preparation size limit (50000000 bytes).");
128157
- const content = readFileSync52(absolute);
126943
+ const content = readFileSync51(absolute);
128158
126944
  if (content.length !== stat3.size)
128159
126945
  throw new Error("Skill changed during preparation.");
128160
126946
  files.push({ path: path2, bytes: content, mode: stat3.mode & 511 });
@@ -128320,11 +127106,11 @@ var exports_metadata = {};
128320
127106
  __export(exports_metadata, {
128321
127107
  registerMetadata: () => registerMetadata
128322
127108
  });
128323
- import { closeSync as closeSync37, constants as constants36, fstatSync as fstatSync36, openSync as openSync37, readFileSync as readFileSync53, readSync as readSync29, writeFileSync as writeFileSync34 } from "fs";
127109
+ import { closeSync as closeSync36, constants as constants36, fstatSync as fstatSync35, openSync as openSync36, readFileSync as readFileSync52, readSync as readSync29, writeFileSync as writeFileSync34 } from "fs";
128324
127110
  function readPlan(path2) {
128325
- const fd = openSync37(path2, constants36.O_RDONLY | constants36.O_NONBLOCK | constants36.O_NOFOLLOW);
127111
+ const fd = openSync36(path2, constants36.O_RDONLY | constants36.O_NONBLOCK | constants36.O_NOFOLLOW);
128326
127112
  try {
128327
- const stat3 = fstatSync36(fd);
127113
+ const stat3 = fstatSync35(fd);
128328
127114
  if (!stat3.isFile() || stat3.size > 8 * 1024 * 1024)
128329
127115
  throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
128330
127116
  const bytes = Buffer.alloc(stat3.size + 1);
@@ -128339,7 +127125,7 @@ function readPlan(path2) {
128339
127125
  throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
128340
127126
  return metadataPlan(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2))));
128341
127127
  } finally {
128342
- closeSync37(fd);
127128
+ closeSync36(fd);
128343
127129
  }
128344
127130
  }
128345
127131
  function failure(error61) {
@@ -128360,7 +127146,7 @@ function registerMetadata(parent) {
128360
127146
  const bytes = `${JSON.stringify(plan)}
128361
127147
  `;
128362
127148
  writeFileSync34(options.save, bytes, { mode: 384, flag: "wx" });
128363
- if (readFileSync53(options.save, "utf8") !== bytes)
127149
+ if (readFileSync52(options.save, "utf8") !== bytes)
128364
127150
  throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
128365
127151
  await writeCliOutput(JSON.stringify(metadataPlanSummary(plan), null, 2));
128366
127152
  } catch (error61) {
@@ -128705,8 +127491,8 @@ var init_registry_sync = __esm(() => {
128705
127491
  });
128706
127492
 
128707
127493
  // src/lib/review-export.ts
128708
- import { constants as constants37, closeSync as closeSync38, existsSync as existsSync38, fstatSync as fstatSync37, fsyncSync as fsyncSync12, lstatSync as lstatSync55, openSync as openSync38, realpathSync as realpathSync26, statSync as statSync27, writeFileSync as writeFileSync36 } from "fs";
128709
- import { basename as basename28, dirname as dirname56, isAbsolute as isAbsolute52, join as join86, parse as parse13, resolve as resolve51, sep as sep26 } from "path";
127494
+ import { constants as constants37, closeSync as closeSync37, existsSync as existsSync38, fstatSync as fstatSync36, fsyncSync as fsyncSync12, lstatSync as lstatSync55, openSync as openSync37, realpathSync as realpathSync26, statSync as statSync27, writeFileSync as writeFileSync36 } from "fs";
127495
+ import { basename as basename28, dirname as dirname56, isAbsolute as isAbsolute51, join as join85, parse as parse13, resolve as resolve51, sep as sep26 } from "path";
128710
127496
  function exactVersion(spec) {
128711
127497
  const at2 = spec.indexOf("@");
128712
127498
  const slug2 = spec.slice(0, at2);
@@ -128717,7 +127503,7 @@ function exactVersion(spec) {
128717
127503
  return { slug: slug2, version: version2 };
128718
127504
  }
128719
127505
  function assertPrivateDestination(output2) {
128720
- if (!isAbsolute52(output2) || resolve51(output2) !== output2 || !basename28(output2).endsWith(".tar.gz")) {
127506
+ if (!isAbsolute51(output2) || resolve51(output2) !== output2 || !basename28(output2).endsWith(".tar.gz")) {
128721
127507
  throw new Error("Review output must be an absolute, normalized .tar.gz path.");
128722
127508
  }
128723
127509
  const parent = dirname56(output2);
@@ -128733,7 +127519,7 @@ function assertPrivateDestination(output2) {
128733
127519
  throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
128734
127520
  }
128735
127521
  for (let current = parent;; current = dirname56(current)) {
128736
- if (existsSync38(join86(current, ".git"))) {
127522
+ if (existsSync38(join85(current, ".git"))) {
128737
127523
  throw new Error("Review output cannot be placed inside a Git worktree.");
128738
127524
  }
128739
127525
  if (current === parse13(current).root)
@@ -128769,16 +127555,16 @@ async function exportSkillVersionForReview(spec, output2, client2) {
128769
127555
  if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
128770
127556
  throw new Error("Published bundle bytes do not match the exact version metadata.");
128771
127557
  }
128772
- const fd = openSync38(target, constants37.O_WRONLY | constants37.O_CREAT | constants37.O_EXCL | constants37.O_NOFOLLOW, 384);
127558
+ const fd = openSync37(target, constants37.O_WRONLY | constants37.O_CREAT | constants37.O_EXCL | constants37.O_NOFOLLOW, 384);
128773
127559
  try {
128774
127560
  writeFileSync36(fd, bytes);
128775
127561
  fsyncSync12(fd);
128776
- if (fstatSync37(fd).size !== bytes.byteLength)
127562
+ if (fstatSync36(fd).size !== bytes.byteLength)
128777
127563
  throw new Error("Incomplete review output write.");
128778
127564
  } catch (error61) {
128779
127565
  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 });
128780
127566
  } finally {
128781
- closeSync38(fd);
127567
+ closeSync37(fd);
128782
127568
  }
128783
127569
  return { slug: slug2, version: version2, bundleSha256: metadata2.bundleSha256.toLowerCase(), bundleByteSize: bytes.byteLength, output: target };
128784
127570
  }
@@ -129018,9 +127804,9 @@ __export(exports_publish, {
129018
127804
  PushSkillError: () => PushSkillError
129019
127805
  });
129020
127806
  import { execFileSync as execFileSync3 } from "child_process";
129021
- import { existsSync as existsSync39, readFileSync as readFileSync54 } from "fs";
127807
+ import { existsSync as existsSync39, readFileSync as readFileSync53 } from "fs";
129022
127808
  import { hostname as hostname6 } from "os";
129023
- import { join as join87 } from "path";
127809
+ import { join as join86 } from "path";
129024
127810
  function registerPublish(parent) {
129025
127811
  parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--force-new-version", "If name@version already exists with different content, publish as the next patch version", false).option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
129026
127812
  try {
@@ -129072,8 +127858,8 @@ async function pushSkill(name, options = {}) {
129072
127858
  const packed = packSkillBundle(skill.path, { maxUnpackedBytes: MAX_UNPACKED_BYTES });
129073
127859
  await verifyPackedCanonicalHash(skill.name, packed);
129074
127860
  const versionManifest = buildVersionManifest(skill.path, packed);
129075
- const skillMdPath = join87(skill.path, "SKILL.md");
129076
- const skillMd = existsSync39(skillMdPath) ? readFileSync54(skillMdPath, "utf-8") : undefined;
127861
+ const skillMdPath = join86(skill.path, "SKILL.md");
127862
+ const skillMd = existsSync39(skillMdPath) ? readFileSync53(skillMdPath, "utf-8") : undefined;
129077
127863
  const base3 = {
129078
127864
  slug: skill.name,
129079
127865
  path: skill.path,
@@ -130892,15 +129678,15 @@ function registerStorage(parent) {
130892
129678
  }
130893
129679
  });
130894
129680
  }
130895
- var init_storage2 = __esm(() => {
129681
+ var init_storage = __esm(() => {
130896
129682
  init_source();
130897
129683
  init_native_storage();
130898
129684
  init_home_migration();
130899
129685
  });
130900
129686
 
130901
129687
  // src/lib/registry-reconcile.ts
130902
- import { existsSync as existsSync40, readFileSync as readFileSync55, statSync as statSync28, writeFileSync as writeFileSync37 } from "fs";
130903
- import { join as join88 } from "path";
129688
+ import { existsSync as existsSync40, readFileSync as readFileSync54, statSync as statSync28, writeFileSync as writeFileSync37 } from "fs";
129689
+ import { join as join87 } from "path";
130904
129690
  function isDirectory2(path2) {
130905
129691
  try {
130906
129692
  return statSync28(path2).isDirectory();
@@ -130911,15 +129697,15 @@ function isDirectory2(path2) {
130911
129697
  function migrationNeeded(options) {
130912
129698
  if (options.rootDir)
130913
129699
  return false;
130914
- const appDir = options.homeDir ? join88(options.homeDir, ".hasna", "skills") : getDataDir();
130915
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join88(appDir, SKILLS_CACHE_DIRNAME)));
129700
+ const appDir = options.homeDir ? join87(options.homeDir, ".hasna", "skills") : getDataDir();
129701
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join87(appDir, SKILLS_CACHE_DIRNAME)));
130916
129702
  }
130917
129703
  function readBaseline(skillDir) {
130918
- const markerPath = join88(skillDir, PULL_MARKER_FILE);
129704
+ const markerPath = join87(skillDir, PULL_MARKER_FILE);
130919
129705
  if (!existsSync40(markerPath))
130920
129706
  return;
130921
129707
  try {
130922
- const marker = JSON.parse(readFileSync55(markerPath, "utf-8"));
129708
+ const marker = JSON.parse(readFileSync54(markerPath, "utf-8"));
130923
129709
  if (!isSkillsOwnershipMarker(marker))
130924
129710
  return;
130925
129711
  return {
@@ -130931,11 +129717,11 @@ function readBaseline(skillDir) {
130931
129717
  }
130932
129718
  }
130933
129719
  function readCursor(root2) {
130934
- const path2 = join88(root2, SYNC_CURSOR_FILE);
129720
+ const path2 = join87(root2, SYNC_CURSOR_FILE);
130935
129721
  if (!existsSync40(path2))
130936
129722
  return { runCount: 0 };
130937
129723
  try {
130938
- const cursor2 = JSON.parse(readFileSync55(path2, "utf-8"));
129724
+ const cursor2 = JSON.parse(readFileSync54(path2, "utf-8"));
130939
129725
  return { runCount: typeof cursor2.runCount === "number" ? cursor2.runCount : 0 };
130940
129726
  } catch {
130941
129727
  return { runCount: 0 };
@@ -130944,12 +129730,12 @@ function readCursor(root2) {
130944
129730
  function resolveCorpusRootReadOnly(options) {
130945
129731
  if (options.rootDir)
130946
129732
  return { root: options.rootDir, migrationPending: false };
130947
- const appDir = options.homeDir ? join88(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
130948
- const cache3 = join88(appDir, SKILLS_CACHE_DIRNAME);
129733
+ const appDir = options.homeDir ? join87(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
129734
+ const cache3 = join87(appDir, SKILLS_CACHE_DIRNAME);
130949
129735
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
130950
129736
  return { root: cache3, migrationPending: false };
130951
129737
  }
130952
- return { root: join88(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
129738
+ return { root: join87(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
130953
129739
  }
130954
129740
  function remoteRowToSkill(record14) {
130955
129741
  const slug2 = typeof record14.slug === "string" ? record14.slug : typeof record14.name === "string" ? record14.name : undefined;
@@ -131083,7 +129869,7 @@ async function reconcileRegistry(options = {}) {
131083
129869
  for (const slug2 of allSlugs) {
131084
129870
  const local = locals.get(slug2);
131085
129871
  const remote = remotes.get(slug2);
131086
- const baseline = local ? readBaseline(join88(root2, slug2)) : undefined;
129872
+ const baseline = local ? readBaseline(join87(root2, slug2)) : undefined;
131087
129873
  const { state, reason: reason2 } = classifySkill(local, remote, baseline);
131088
129874
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
131089
129875
  if (state === "remote-only" && isDigestless(remote)) {
@@ -131142,7 +129928,7 @@ async function reconcileRegistry(options = {}) {
131142
129928
  try {
131143
129929
  await pushSkill(slug2, { rootDir: root2, client: client2 });
131144
129930
  const pushed = locals.get(slug2);
131145
- writePullMarker(join88(root2, slug2), {
129931
+ writePullMarker(join87(root2, slug2), {
131146
129932
  skill: slug2,
131147
129933
  ...pushed?.version ? { version: pushed.version } : {},
131148
129934
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -131214,7 +130000,7 @@ async function reconcileRegistry(options = {}) {
131214
130000
  runCount: readCursor(root2).runCount + 1,
131215
130001
  summary
131216
130002
  };
131217
- writeFileSync37(join88(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
130003
+ writeFileSync37(join87(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
131218
130004
  `);
131219
130005
  return {
131220
130006
  corpusRoot: root2,
@@ -139550,7 +138336,7 @@ var { registerCustomerProfileCommands: registerCustomerProfileCommands2 } = awai
139550
138336
  registerCustomerProfileCommands2(program2);
139551
138337
  var { registerFeedback: registerFeedback2 } = await Promise.resolve().then(() => (init_feedback2(), exports_feedback));
139552
138338
  registerFeedback2(program2);
139553
- var { registerStorage: registerStorage2 } = await Promise.resolve().then(() => (init_storage2(), exports_storage));
138339
+ var { registerStorage: registerStorage2 } = await Promise.resolve().then(() => (init_storage(), exports_storage));
139554
138340
  registerStorage2(program2);
139555
138341
  var { registerRegistryReconcile: registerRegistryReconcile2 } = await Promise.resolve().then(() => (init_registry_reconcile2(), exports_registry_reconcile));
139556
138342
  registerRegistryReconcile2(program2);